1
0

printf.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /* Copyright (c) 1986, 1988, 1991, 1993
  2. * The Regents of the University of California. All rights reserved.
  3. * (c) UNIX System Laboratories, Inc.
  4. * All or some portions of this file are derived from material licensed
  5. * to the University of California by American Telephone and Telegraph
  6. * Co. or Unix System Laboratories, Inc. and are reproduced herein with
  7. * the permission of UNIX System Laboratories, Inc.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
  34. */
  35. #define putchar putc
  36. void putc(int c, void *stream);
  37. typedef unsigned long size_t;
  38. typedef long ssize_t;
  39. #ifdef __64BIT__
  40. typedef unsigned long long uintmax_t;
  41. typedef long long intmax_t;
  42. #else
  43. typedef unsigned int uintmax_t;
  44. typedef int intmax_t;
  45. #endif
  46. typedef unsigned char u_char;
  47. typedef unsigned int u_int;
  48. typedef unsigned long u_long;
  49. typedef unsigned short u_short;
  50. typedef unsigned long long u_quad_t;
  51. typedef long long quad_t;
  52. typedef unsigned long uintptr_t;
  53. typedef long ptrdiff_t;
  54. #define NULL ((void*)0)
  55. #define NBBY 8 /* number of bits in a byte */
  56. char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  57. #define hex2ascii(hex) (hex2ascii_data[hex])
  58. #define va_list __builtin_va_list
  59. #define va_start __builtin_va_start
  60. #define va_arg __builtin_va_arg
  61. #define va_end __builtin_va_end
  62. #define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
  63. static size_t
  64. strlen(const char *s)
  65. {
  66. size_t l = 0;
  67. while (*s++)
  68. l++;
  69. return l;
  70. }
  71. /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
  72. #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
  73. /*
  74. * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
  75. * order; return an optional length and a pointer to the last character
  76. * written in the buffer (i.e., the first character of the string).
  77. * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
  78. */
  79. static char *
  80. ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
  81. {
  82. char *p, c;
  83. p = nbuf;
  84. *p = '\0';
  85. do {
  86. c = hex2ascii(num % base);
  87. *++p = upper ? toupper(c) : c;
  88. } while (num /= base);
  89. if (lenp)
  90. *lenp = p - nbuf;
  91. return (p);
  92. }
  93. /*
  94. * Scaled down version of printf(3).
  95. *
  96. * Two additional formats:
  97. *
  98. * The format %b is supported to decode error registers.
  99. * Its usage is:
  100. *
  101. * printf("reg=%b\n", regval, "*");
  102. *
  103. * where is the output base expressed as a control character, e.g.
  104. * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
  105. * the first of which gives the bit number to be inspected (origin 1), and
  106. * the next characters (up to a control character, i.e. a character <= 32),
  107. * give the name of the register. Thus:
  108. *
  109. * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
  110. *
  111. * would produce output:
  112. *
  113. * reg=3
  114. *
  115. * XXX: %D -- Hexdump, takes pointer and separator string:
  116. * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
  117. * ("%*D", len, ptr, " " -> XX XX XX XX ...
  118. */
  119. int
  120. kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap)
  121. {
  122. #define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; }
  123. char nbuf[MAXNBUF];
  124. char *d;
  125. const char *p, *percent, *q;
  126. u_char *up;
  127. int ch, n;
  128. uintmax_t num;
  129. int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
  130. int cflag, hflag, jflag, tflag, zflag;
  131. int dwidth, upper;
  132. char padc;
  133. int stop = 0, retval = 0;
  134. num = 0;
  135. if (!func)
  136. d = (char *) arg;
  137. else
  138. d = NULL;
  139. if (fmt == NULL)
  140. fmt = "(fmt null)\n";
  141. if (radix < 2 || radix > 36)
  142. radix = 10;
  143. for (;;) {
  144. padc = ' ';
  145. width = 0;
  146. while ((ch = (u_char)*fmt++) != '%' || stop) {
  147. if (ch == '\0')
  148. return (retval);
  149. PCHAR(ch);
  150. }
  151. percent = fmt - 1;
  152. qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
  153. sign = 0; dot = 0; dwidth = 0; upper = 0;
  154. cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
  155. reswitch: switch (ch = (u_char)*fmt++) {
  156. case '.':
  157. dot = 1;
  158. goto reswitch;
  159. case '#':
  160. sharpflag = 1;
  161. goto reswitch;
  162. case '+':
  163. sign = 1;
  164. goto reswitch;
  165. case '-':
  166. ladjust = 1;
  167. goto reswitch;
  168. case '%':
  169. PCHAR(ch);
  170. break;
  171. case '*':
  172. if (!dot) {
  173. width = va_arg(ap, int);
  174. if (width < 0) {
  175. ladjust = !ladjust;
  176. width = -width;
  177. }
  178. } else {
  179. dwidth = va_arg(ap, int);
  180. }
  181. goto reswitch;
  182. case '0':
  183. if (!dot) {
  184. padc = '0';
  185. goto reswitch;
  186. }
  187. case '1': case '2': case '3': case '4':
  188. case '5': case '6': case '7': case '8': case '9':
  189. for (n = 0;; ++fmt) {
  190. n = n * 10 + ch - '0';
  191. ch = *fmt;
  192. if (ch < '0' || ch > '9')
  193. break;
  194. }
  195. if (dot)
  196. dwidth = n;
  197. else
  198. width = n;
  199. goto reswitch;
  200. case 'b':
  201. num = (u_int)va_arg(ap, int);
  202. p = va_arg(ap, char *);
  203. for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
  204. PCHAR(*q--);
  205. if (num == 0)
  206. break;
  207. for (tmp = 0; *p;) {
  208. n = *p++;
  209. if (num & (1 << (n - 1))) {
  210. PCHAR(tmp ? ',' : '<');
  211. for (; (n = *p) > ' '; ++p)
  212. PCHAR(n);
  213. tmp = 1;
  214. } else
  215. for (; *p > ' '; ++p)
  216. continue;
  217. }
  218. if (tmp)
  219. PCHAR('>');
  220. break;
  221. case 'c':
  222. PCHAR(va_arg(ap, int));
  223. break;
  224. case 'D':
  225. up = va_arg(ap, u_char *);
  226. p = va_arg(ap, char *);
  227. if (!width)
  228. width = 16;
  229. while(width--) {
  230. PCHAR(hex2ascii(*up >> 4));
  231. PCHAR(hex2ascii(*up & 0x0f));
  232. up++;
  233. if (width)
  234. for (q=p;*q;q++)
  235. PCHAR(*q);
  236. }
  237. break;
  238. case 'd':
  239. case 'i':
  240. base = 10;
  241. sign = 1;
  242. goto handle_sign;
  243. case 'h':
  244. if (hflag) {
  245. hflag = 0;
  246. cflag = 1;
  247. } else
  248. hflag = 1;
  249. goto reswitch;
  250. case 'j':
  251. jflag = 1;
  252. goto reswitch;
  253. case 'l':
  254. if (lflag) {
  255. lflag = 0;
  256. qflag = 1;
  257. } else
  258. lflag = 1;
  259. goto reswitch;
  260. case 'n':
  261. if (jflag)
  262. *(va_arg(ap, intmax_t *)) = retval;
  263. else if (qflag)
  264. *(va_arg(ap, quad_t *)) = retval;
  265. else if (lflag)
  266. *(va_arg(ap, long *)) = retval;
  267. else if (zflag)
  268. *(va_arg(ap, size_t *)) = retval;
  269. else if (hflag)
  270. *(va_arg(ap, short *)) = retval;
  271. else if (cflag)
  272. *(va_arg(ap, char *)) = retval;
  273. else
  274. *(va_arg(ap, int *)) = retval;
  275. break;
  276. case 'o':
  277. base = 8;
  278. goto handle_nosign;
  279. case 'p':
  280. base = 16;
  281. sharpflag = (width == 0);
  282. sign = 0;
  283. num = (uintptr_t)va_arg(ap, void *);
  284. goto number;
  285. case 'q':
  286. qflag = 1;
  287. goto reswitch;
  288. case 'r':
  289. base = radix;
  290. if (sign)
  291. goto handle_sign;
  292. goto handle_nosign;
  293. case 's':
  294. p = va_arg(ap, char *);
  295. if (p == NULL)
  296. p = "(null)";
  297. if (!dot)
  298. n = strlen (p);
  299. else
  300. for (n = 0; n < dwidth && p[n]; n++)
  301. continue;
  302. width -= n;
  303. if (!ladjust && width > 0)
  304. while (width--)
  305. PCHAR(padc);
  306. while (n--)
  307. PCHAR(*p++);
  308. if (ladjust && width > 0)
  309. while (width--)
  310. PCHAR(padc);
  311. break;
  312. case 't':
  313. tflag = 1;
  314. goto reswitch;
  315. case 'u':
  316. base = 10;
  317. goto handle_nosign;
  318. case 'X':
  319. upper = 1;
  320. case 'x':
  321. base = 16;
  322. goto handle_nosign;
  323. case 'y':
  324. base = 16;
  325. sign = 1;
  326. goto handle_sign;
  327. case 'z':
  328. zflag = 1;
  329. goto reswitch;
  330. handle_nosign:
  331. sign = 0;
  332. if (jflag)
  333. num = va_arg(ap, uintmax_t);
  334. else if (qflag)
  335. num = va_arg(ap, u_quad_t);
  336. else if (tflag)
  337. num = va_arg(ap, ptrdiff_t);
  338. else if (lflag)
  339. num = va_arg(ap, u_long);
  340. else if (zflag)
  341. num = va_arg(ap, size_t);
  342. else if (hflag)
  343. num = (u_short)va_arg(ap, int);
  344. else if (cflag)
  345. num = (u_char)va_arg(ap, int);
  346. else
  347. num = va_arg(ap, u_int);
  348. goto number;
  349. handle_sign:
  350. if (jflag)
  351. num = va_arg(ap, intmax_t);
  352. else if (qflag)
  353. num = va_arg(ap, quad_t);
  354. else if (tflag)
  355. num = va_arg(ap, ptrdiff_t);
  356. else if (lflag)
  357. num = va_arg(ap, long);
  358. else if (zflag)
  359. num = va_arg(ap, ssize_t);
  360. else if (hflag)
  361. num = (short)va_arg(ap, int);
  362. else if (cflag)
  363. num = (char)va_arg(ap, int);
  364. else
  365. num = va_arg(ap, int);
  366. number:
  367. if (sign && (intmax_t)num < 0) {
  368. neg = 1;
  369. num = -(intmax_t)num;
  370. }
  371. p = ksprintn(nbuf, num, base, &tmp, upper);
  372. if (sharpflag && num != 0) {
  373. if (base == 8)
  374. tmp++;
  375. else if (base == 16)
  376. tmp += 2;
  377. }
  378. if (neg)
  379. tmp++;
  380. if (!ladjust && padc != '0' && width
  381. && (width -= tmp) > 0)
  382. while (width--)
  383. PCHAR(padc);
  384. if (neg)
  385. PCHAR('-');
  386. if (sharpflag && num != 0) {
  387. if (base == 8) {
  388. PCHAR('0');
  389. } else if (base == 16) {
  390. PCHAR('0');
  391. PCHAR('x');
  392. }
  393. }
  394. if (!ladjust && width && (width -= tmp) > 0)
  395. while (width--)
  396. PCHAR(padc);
  397. while (*p)
  398. PCHAR(*p--);
  399. if (ladjust && width && (width -= tmp) > 0)
  400. while (width--)
  401. PCHAR(padc);
  402. break;
  403. default:
  404. while (percent < fmt)
  405. PCHAR(*percent++);
  406. /*
  407. * Since we ignore an formatting argument it is no
  408. * longer safe to obey the remaining formatting
  409. * arguments as the arguments will no longer match
  410. * the format specs.
  411. */
  412. stop = 1;
  413. break;
  414. }
  415. }
  416. #undef PCHAR
  417. }
  418. void
  419. printf(const char *fmt, ...)
  420. {
  421. /* http://www.pagetable.com/?p=298 */
  422. va_list ap;
  423. va_start(ap, fmt);
  424. kvprintf(fmt, putchar, (void*)1, 10, ap);
  425. va_end(ap);
  426. }
  427. /* Thanks to James Cone (https://github.com/JamesC1) for this */
  428. void
  429. sprintf(char *buffer, const char *fmt, ...)
  430. {
  431. va_list ap;
  432. va_start(ap, fmt);
  433. kvprintf(fmt, NULL, (void *)buffer, 10, ap);
  434. va_end(ap);
  435. }