vsprintf.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /* -*- linux-c -*- ------------------------------------------------------- *
  3. *
  4. * Copyright (C) 1991, 1992 Linus Torvalds
  5. * Copyright 2007 rPath, Inc. - All Rights Reserved
  6. *
  7. * ----------------------------------------------------------------------- */
  8. /*
  9. * Oh, it's a waste of space, but oh-so-yummy for debugging.
  10. */
  11. #include <linux/stdarg.h>
  12. #include <linux/compiler.h>
  13. #include <linux/ctype.h>
  14. #include <linux/kernel.h>
  15. #include <linux/limits.h>
  16. #include <linux/string.h>
  17. #include <linux/types.h>
  18. static
  19. int skip_atoi(const char **s)
  20. {
  21. int i = 0;
  22. while (isdigit(**s))
  23. i = i * 10 + *((*s)++) - '0';
  24. return i;
  25. }
  26. /*
  27. * put_dec_full4 handles numbers in the range 0 <= r < 10000.
  28. * The multiplier 0xccd is round(2^15/10), and the approximation
  29. * r/10 == (r * 0xccd) >> 15 is exact for all r < 16389.
  30. */
  31. static
  32. void put_dec_full4(char *end, unsigned int r)
  33. {
  34. int i;
  35. for (i = 0; i < 3; i++) {
  36. unsigned int q = (r * 0xccd) >> 15;
  37. *--end = '0' + (r - q * 10);
  38. r = q;
  39. }
  40. *--end = '0' + r;
  41. }
  42. /* put_dec is copied from lib/vsprintf.c with small modifications */
  43. /*
  44. * Call put_dec_full4 on x % 10000, return x / 10000.
  45. * The approximation x/10000 == (x * 0x346DC5D7) >> 43
  46. * holds for all x < 1,128,869,999. The largest value this
  47. * helper will ever be asked to convert is 1,125,520,955.
  48. * (second call in the put_dec code, assuming n is all-ones).
  49. */
  50. static
  51. unsigned int put_dec_helper4(char *end, unsigned int x)
  52. {
  53. unsigned int q = (x * 0x346DC5D7ULL) >> 43;
  54. put_dec_full4(end, x - q * 10000);
  55. return q;
  56. }
  57. /* Based on code by Douglas W. Jones found at
  58. * <http://www.cs.uiowa.edu/~jones/bcd/decimal.html#sixtyfour>
  59. * (with permission from the author).
  60. * Performs no 64-bit division and hence should be fast on 32-bit machines.
  61. */
  62. static
  63. char *put_dec(char *end, unsigned long long n)
  64. {
  65. unsigned int d3, d2, d1, q, h;
  66. char *p = end;
  67. d1 = ((unsigned int)n >> 16); /* implicit "& 0xffff" */
  68. h = (n >> 32);
  69. d2 = (h ) & 0xffff;
  70. d3 = (h >> 16); /* implicit "& 0xffff" */
  71. /* n = 2^48 d3 + 2^32 d2 + 2^16 d1 + d0
  72. = 281_4749_7671_0656 d3 + 42_9496_7296 d2 + 6_5536 d1 + d0 */
  73. q = 656 * d3 + 7296 * d2 + 5536 * d1 + ((unsigned int)n & 0xffff);
  74. q = put_dec_helper4(p, q);
  75. p -= 4;
  76. q += 7671 * d3 + 9496 * d2 + 6 * d1;
  77. q = put_dec_helper4(p, q);
  78. p -= 4;
  79. q += 4749 * d3 + 42 * d2;
  80. q = put_dec_helper4(p, q);
  81. p -= 4;
  82. q += 281 * d3;
  83. q = put_dec_helper4(p, q);
  84. p -= 4;
  85. put_dec_full4(p, q);
  86. p -= 4;
  87. /* strip off the extra 0's we printed */
  88. while (p < end && *p == '0')
  89. ++p;
  90. return p;
  91. }
  92. static
  93. char *number(char *end, unsigned long long num, int base, char locase)
  94. {
  95. /*
  96. * locase = 0 or 0x20. ORing digits or letters with 'locase'
  97. * produces same digits or (maybe lowercased) letters
  98. */
  99. /* we are called with base 8, 10 or 16, only, thus don't need "G..." */
  100. static const char digits[16] = "0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
  101. switch (base) {
  102. case 10:
  103. if (num != 0)
  104. end = put_dec(end, num);
  105. break;
  106. case 8:
  107. for (; num != 0; num >>= 3)
  108. *--end = '0' + (num & 07);
  109. break;
  110. case 16:
  111. for (; num != 0; num >>= 4)
  112. *--end = digits[num & 0xf] | locase;
  113. break;
  114. default:
  115. unreachable();
  116. }
  117. return end;
  118. }
  119. #define ZEROPAD 1 /* pad with zero */
  120. #define SIGN 2 /* unsigned/signed long */
  121. #define PLUS 4 /* show plus */
  122. #define SPACE 8 /* space if plus */
  123. #define LEFT 16 /* left justified */
  124. #define SMALL 32 /* Must be 32 == 0x20 */
  125. #define SPECIAL 64 /* 0x */
  126. #define WIDE 128 /* UTF-16 string */
  127. static
  128. int get_flags(const char **fmt)
  129. {
  130. int flags = 0;
  131. do {
  132. switch (**fmt) {
  133. case '-':
  134. flags |= LEFT;
  135. break;
  136. case '+':
  137. flags |= PLUS;
  138. break;
  139. case ' ':
  140. flags |= SPACE;
  141. break;
  142. case '#':
  143. flags |= SPECIAL;
  144. break;
  145. case '0':
  146. flags |= ZEROPAD;
  147. break;
  148. default:
  149. return flags;
  150. }
  151. ++(*fmt);
  152. } while (1);
  153. }
  154. static
  155. int get_int(const char **fmt, va_list *ap)
  156. {
  157. if (isdigit(**fmt))
  158. return skip_atoi(fmt);
  159. if (**fmt == '*') {
  160. ++(*fmt);
  161. /* it's the next argument */
  162. return va_arg(*ap, int);
  163. }
  164. return 0;
  165. }
  166. static
  167. unsigned long long get_number(int sign, int qualifier, va_list *ap)
  168. {
  169. if (sign) {
  170. switch (qualifier) {
  171. case 'L':
  172. return va_arg(*ap, long long);
  173. case 'l':
  174. return va_arg(*ap, long);
  175. case 'h':
  176. return (short)va_arg(*ap, int);
  177. case 'H':
  178. return (signed char)va_arg(*ap, int);
  179. default:
  180. return va_arg(*ap, int);
  181. };
  182. } else {
  183. switch (qualifier) {
  184. case 'L':
  185. return va_arg(*ap, unsigned long long);
  186. case 'l':
  187. return va_arg(*ap, unsigned long);
  188. case 'h':
  189. return (unsigned short)va_arg(*ap, int);
  190. case 'H':
  191. return (unsigned char)va_arg(*ap, int);
  192. default:
  193. return va_arg(*ap, unsigned int);
  194. }
  195. }
  196. }
  197. static
  198. char get_sign(long long *num, int flags)
  199. {
  200. if (!(flags & SIGN))
  201. return 0;
  202. if (*num < 0) {
  203. *num = -(*num);
  204. return '-';
  205. }
  206. if (flags & PLUS)
  207. return '+';
  208. if (flags & SPACE)
  209. return ' ';
  210. return 0;
  211. }
  212. static
  213. size_t utf16s_utf8nlen(const u16 *s16, size_t maxlen)
  214. {
  215. size_t len, clen;
  216. for (len = 0; len < maxlen && *s16; len += clen) {
  217. u16 c0 = *s16++;
  218. /* First, get the length for a BMP character */
  219. clen = 1 + (c0 >= 0x80) + (c0 >= 0x800);
  220. if (len + clen > maxlen)
  221. break;
  222. /*
  223. * If this is a high surrogate, and we're already at maxlen, we
  224. * can't include the character if it's a valid surrogate pair.
  225. * Avoid accessing one extra word just to check if it's valid
  226. * or not.
  227. */
  228. if ((c0 & 0xfc00) == 0xd800) {
  229. if (len + clen == maxlen)
  230. break;
  231. if ((*s16 & 0xfc00) == 0xdc00) {
  232. ++s16;
  233. ++clen;
  234. }
  235. }
  236. }
  237. return len;
  238. }
  239. static
  240. u32 utf16_to_utf32(const u16 **s16)
  241. {
  242. u16 c0, c1;
  243. c0 = *(*s16)++;
  244. /* not a surrogate */
  245. if ((c0 & 0xf800) != 0xd800)
  246. return c0;
  247. /* invalid: low surrogate instead of high */
  248. if (c0 & 0x0400)
  249. return 0xfffd;
  250. c1 = **s16;
  251. /* invalid: missing low surrogate */
  252. if ((c1 & 0xfc00) != 0xdc00)
  253. return 0xfffd;
  254. /* valid surrogate pair */
  255. ++(*s16);
  256. return (0x10000 - (0xd800 << 10) - 0xdc00) + (c0 << 10) + c1;
  257. }
  258. #define PUTC(c) \
  259. do { \
  260. if (pos < size) \
  261. buf[pos] = (c); \
  262. ++pos; \
  263. } while (0);
  264. int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
  265. {
  266. /* The maximum space required is to print a 64-bit number in octal */
  267. char tmp[(sizeof(unsigned long long) * 8 + 2) / 3];
  268. char *tmp_end = &tmp[ARRAY_SIZE(tmp)];
  269. long long num;
  270. int base;
  271. const char *s;
  272. size_t len, pos;
  273. char sign;
  274. int flags; /* flags to number() */
  275. int field_width; /* width of output field */
  276. int precision; /* min. # of digits for integers; max
  277. number of chars for from string */
  278. int qualifier; /* 'h', 'hh', 'l' or 'll' for integer fields */
  279. va_list args;
  280. /*
  281. * We want to pass our input va_list to helper functions by reference,
  282. * but there's an annoying edge case. If va_list was originally passed
  283. * to us by value, we could just pass &ap down to the helpers. This is
  284. * the case on, for example, X86_32.
  285. * However, on X86_64 (and possibly others), va_list is actually a
  286. * size-1 array containing a structure. Our function parameter ap has
  287. * decayed from T[1] to T*, and &ap has type T** rather than T(*)[1],
  288. * which is what will be expected by a function taking a va_list *
  289. * parameter.
  290. * One standard way to solve this mess is by creating a copy in a local
  291. * variable of type va_list and then passing a pointer to that local
  292. * copy instead, which is what we do here.
  293. */
  294. va_copy(args, ap);
  295. for (pos = 0; *fmt; ++fmt) {
  296. if (*fmt != '%' || *++fmt == '%') {
  297. PUTC(*fmt);
  298. continue;
  299. }
  300. /* process flags */
  301. flags = get_flags(&fmt);
  302. /* get field width */
  303. field_width = get_int(&fmt, &args);
  304. if (field_width < 0) {
  305. field_width = -field_width;
  306. flags |= LEFT;
  307. }
  308. if (flags & LEFT)
  309. flags &= ~ZEROPAD;
  310. /* get the precision */
  311. precision = -1;
  312. if (*fmt == '.') {
  313. ++fmt;
  314. precision = get_int(&fmt, &args);
  315. if (precision >= 0)
  316. flags &= ~ZEROPAD;
  317. }
  318. /* get the conversion qualifier */
  319. qualifier = -1;
  320. if (*fmt == 'h' || *fmt == 'l') {
  321. qualifier = *fmt;
  322. ++fmt;
  323. if (qualifier == *fmt) {
  324. qualifier -= 'a'-'A';
  325. ++fmt;
  326. }
  327. }
  328. sign = 0;
  329. switch (*fmt) {
  330. case 'c':
  331. flags &= LEFT;
  332. s = tmp;
  333. if (qualifier == 'l') {
  334. ((u16 *)tmp)[0] = (u16)va_arg(args, unsigned int);
  335. ((u16 *)tmp)[1] = L'\0';
  336. precision = INT_MAX;
  337. goto wstring;
  338. } else {
  339. tmp[0] = (unsigned char)va_arg(args, int);
  340. precision = len = 1;
  341. }
  342. goto output;
  343. case 's':
  344. flags &= LEFT;
  345. if (precision < 0)
  346. precision = INT_MAX;
  347. s = va_arg(args, void *);
  348. if (!s)
  349. s = precision < 6 ? "" : "(null)";
  350. else if (qualifier == 'l') {
  351. wstring:
  352. flags |= WIDE;
  353. precision = len = utf16s_utf8nlen((const u16 *)s, precision);
  354. goto output;
  355. }
  356. precision = len = strnlen(s, precision);
  357. goto output;
  358. /* integer number formats - set up the flags and "break" */
  359. case 'o':
  360. base = 8;
  361. break;
  362. case 'p':
  363. if (precision < 0)
  364. precision = 2 * sizeof(void *);
  365. fallthrough;
  366. case 'x':
  367. flags |= SMALL;
  368. fallthrough;
  369. case 'X':
  370. base = 16;
  371. break;
  372. case 'd':
  373. case 'i':
  374. flags |= SIGN;
  375. fallthrough;
  376. case 'u':
  377. flags &= ~SPECIAL;
  378. base = 10;
  379. break;
  380. default:
  381. /*
  382. * Bail out if the conversion specifier is invalid.
  383. * There's probably a typo in the format string and the
  384. * remaining specifiers are unlikely to match up with
  385. * the arguments.
  386. */
  387. goto fail;
  388. }
  389. if (*fmt == 'p') {
  390. num = (unsigned long)va_arg(args, void *);
  391. } else {
  392. num = get_number(flags & SIGN, qualifier, &args);
  393. }
  394. sign = get_sign(&num, flags);
  395. if (sign)
  396. --field_width;
  397. s = number(tmp_end, num, base, flags & SMALL);
  398. len = tmp_end - s;
  399. /* default precision is 1 */
  400. if (precision < 0)
  401. precision = 1;
  402. /* precision is minimum number of digits to print */
  403. if (precision < len)
  404. precision = len;
  405. if (flags & SPECIAL) {
  406. /*
  407. * For octal, a leading 0 is printed only if necessary,
  408. * i.e. if it's not already there because of the
  409. * precision.
  410. */
  411. if (base == 8 && precision == len)
  412. ++precision;
  413. /*
  414. * For hexadecimal, the leading 0x is skipped if the
  415. * output is empty, i.e. both the number and the
  416. * precision are 0.
  417. */
  418. if (base == 16 && precision > 0)
  419. field_width -= 2;
  420. else
  421. flags &= ~SPECIAL;
  422. }
  423. /*
  424. * For zero padding, increase the precision to fill the field
  425. * width.
  426. */
  427. if ((flags & ZEROPAD) && field_width > precision)
  428. precision = field_width;
  429. output:
  430. /* Calculate the padding necessary */
  431. field_width -= precision;
  432. /* Leading padding with ' ' */
  433. if (!(flags & LEFT))
  434. while (field_width-- > 0)
  435. PUTC(' ');
  436. /* sign */
  437. if (sign)
  438. PUTC(sign);
  439. /* 0x/0X for hexadecimal */
  440. if (flags & SPECIAL) {
  441. PUTC('0');
  442. PUTC( 'X' | (flags & SMALL));
  443. }
  444. /* Zero padding and excess precision */
  445. while (precision-- > len)
  446. PUTC('0');
  447. /* Actual output */
  448. if (flags & WIDE) {
  449. const u16 *ws = (const u16 *)s;
  450. while (len-- > 0) {
  451. u32 c32 = utf16_to_utf32(&ws);
  452. u8 *s8;
  453. size_t clen;
  454. if (c32 < 0x80) {
  455. PUTC(c32);
  456. continue;
  457. }
  458. /* Number of trailing octets */
  459. clen = 1 + (c32 >= 0x800) + (c32 >= 0x10000);
  460. len -= clen;
  461. s8 = (u8 *)&buf[pos];
  462. /* Avoid writing partial character */
  463. PUTC('\0');
  464. pos += clen;
  465. if (pos >= size)
  466. continue;
  467. /* Set high bits of leading octet */
  468. *s8 = (0xf00 >> 1) >> clen;
  469. /* Write trailing octets in reverse order */
  470. for (s8 += clen; clen; --clen, c32 >>= 6)
  471. *s8-- = 0x80 | (c32 & 0x3f);
  472. /* Set low bits of leading octet */
  473. *s8 |= c32;
  474. }
  475. } else {
  476. while (len-- > 0)
  477. PUTC(*s++);
  478. }
  479. /* Trailing padding with ' ' */
  480. while (field_width-- > 0)
  481. PUTC(' ');
  482. }
  483. fail:
  484. va_end(args);
  485. if (size)
  486. buf[min(pos, size-1)] = '\0';
  487. return pos;
  488. }
  489. int snprintf(char *buf, size_t size, const char *fmt, ...)
  490. {
  491. va_list args;
  492. int i;
  493. va_start(args, fmt);
  494. i = vsnprintf(buf, size, fmt, args);
  495. va_end(args);
  496. return i;
  497. }