printf.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <va_list.h>
  4. static void print_dec(unsigned int value, unsigned int width, char * buf, int * ptr, int fill_zero, int align_right) {
  5. unsigned int n_width = 1;
  6. unsigned int i = 9;
  7. if (value < 10UL) {
  8. n_width = 1;
  9. } else if (value < 100UL) {
  10. n_width = 2;
  11. } else if (value < 1000UL) {
  12. n_width = 3;
  13. } else if (value < 10000UL) {
  14. n_width = 4;
  15. } else if (value < 100000UL) {
  16. n_width = 5;
  17. } else if (value < 1000000UL) {
  18. n_width = 6;
  19. } else if (value < 10000000UL) {
  20. n_width = 7;
  21. } else if (value < 100000000UL) {
  22. n_width = 8;
  23. } else if (value < 1000000000UL) {
  24. n_width = 9;
  25. } else {
  26. n_width = 10;
  27. }
  28. int printed = 0;
  29. if (align_right) {
  30. while (n_width + printed < width) {
  31. buf[*ptr] = fill_zero ? '0' : ' ';
  32. *ptr += 1;
  33. printed += 1;
  34. }
  35. i = n_width;
  36. while (i > 0) {
  37. unsigned int n = value / 10;
  38. int r = value % 10;
  39. buf[*ptr + i - 1] = r + '0';
  40. i--;
  41. value = n;
  42. }
  43. *ptr += n_width;
  44. } else {
  45. i = n_width;
  46. while (i > 0) {
  47. unsigned int n = value / 10;
  48. int r = value % 10;
  49. buf[*ptr + i - 1] = r + '0';
  50. i--;
  51. value = n;
  52. printed++;
  53. }
  54. *ptr += n_width;
  55. while (printed < (int)width) {
  56. buf[*ptr] = fill_zero ? '0' : ' ';
  57. *ptr += 1;
  58. printed += 1;
  59. }
  60. }
  61. }
  62. /*
  63. * Hexadecimal to string
  64. */
  65. static void print_hex(unsigned int value, unsigned int width, char * buf, int * ptr) {
  66. int i = width;
  67. if (i == 0) i = 8;
  68. unsigned int n_width = 1;
  69. unsigned int j = 0x0F;
  70. while (value > j && j < UINT32_MAX) {
  71. n_width += 1;
  72. j *= 0x10;
  73. j += 0x0F;
  74. }
  75. while (i > (int)n_width) {
  76. buf[*ptr] = '0';
  77. *ptr += 1;
  78. i--;
  79. }
  80. i = (int)n_width;
  81. while (i-- > 0) {
  82. buf[*ptr] = "0123456789abcdef"[(value>>(i*4))&0xF];
  83. *ptr += + 1;
  84. }
  85. }
  86. /*
  87. * vasprintf()
  88. */
  89. size_t xvasprintf(char * buf, const char * fmt, va_list args) {
  90. int i = 0;
  91. char * s;
  92. char * b = buf;
  93. int precision = 0;
  94. for (const char *f = fmt; *f; f++) {
  95. if (*f != '%') {
  96. *b++ = *f;
  97. continue;
  98. }
  99. ++f;
  100. unsigned int arg_width = 0;
  101. int align = 1; /* right */
  102. int fill_zero = 0;
  103. int big = 0;
  104. if (*f == '-') {
  105. align = 0;
  106. ++f;
  107. }
  108. if (*f == '*') {
  109. arg_width = (char)va_arg(args, int);
  110. ++f;
  111. }
  112. if (*f == '0') {
  113. fill_zero = 1;
  114. ++f;
  115. }
  116. while (*f >= '0' && *f <= '9') {
  117. arg_width *= 10;
  118. arg_width += *f - '0';
  119. ++f;
  120. }
  121. if (*f == '.') {
  122. ++f;
  123. precision = 0;
  124. while (*f >= '0' && *f <= '9') {
  125. precision *= 10;
  126. precision += *f - '0';
  127. ++f;
  128. }
  129. }
  130. if (*f == 'l') {
  131. big = 1;
  132. ++f;
  133. }
  134. /* fmt[i] == '%' */
  135. switch (*f) {
  136. case 's': /* String pointer -> String */
  137. {
  138. size_t count = 0;
  139. if (big) {
  140. wchar_t * ws = (wchar_t *)va_arg(args, wchar_t *);
  141. if (ws == NULL) {
  142. ws = L"(null)";
  143. }
  144. size_t count = 0;
  145. while (*ws) {
  146. *b++ = *ws++;
  147. count++;
  148. if (arg_width && count == arg_width) break;
  149. }
  150. } else {
  151. s = (char *)va_arg(args, char *);
  152. if (s == NULL) {
  153. s = "(null)";
  154. }
  155. if (precision > 0) {
  156. while (*s && precision > 0) {
  157. *b++ = *s++;
  158. count++;
  159. precision--;
  160. if (arg_width && count == arg_width) break;
  161. }
  162. } else {
  163. while (*s) {
  164. *b++ = *s++;
  165. count++;
  166. if (arg_width && count == arg_width) break;
  167. }
  168. }
  169. }
  170. while (count < arg_width) {
  171. *b++ = ' ';
  172. count++;
  173. }
  174. }
  175. break;
  176. case 'c': /* Single character */
  177. *b++ = (char)va_arg(args, int);
  178. break;
  179. case 'p':
  180. if (!arg_width) {
  181. arg_width = 8;
  182. }
  183. case 'x': /* Hexadecimal number */
  184. i = b - buf;
  185. print_hex((unsigned long)va_arg(args, unsigned long), arg_width, buf, &i);
  186. b = buf + i;
  187. break;
  188. case 'i':
  189. case 'd': /* Decimal number */
  190. i = b - buf;
  191. {
  192. long val = (long)va_arg(args, long);
  193. if (val < 0) {
  194. *b++ = '-';
  195. buf++;
  196. val = -val;
  197. }
  198. print_dec(val, arg_width, buf, &i, fill_zero, align);
  199. }
  200. b = buf + i;
  201. break;
  202. case 'g': /* supposed to also support e */
  203. case 'f':
  204. {
  205. double val = (double)va_arg(args, double);
  206. i = b - buf;
  207. if (val < 0) {
  208. *b++ = '-';
  209. buf++;
  210. val = -val;
  211. }
  212. print_dec((long)val, arg_width, buf, &i, fill_zero, align);
  213. b = buf + i;
  214. i = b - buf;
  215. *b++ = '.';
  216. buf++;
  217. for (int j = 0; j < 10; ++j) {
  218. if ((int)(val * 100000.0) % 100000 == 0 && j != 0) break;
  219. val *= 10.0;
  220. print_dec((int)(val) % 10, 0, buf, &i, 0, 0);
  221. }
  222. b = buf + i;
  223. }
  224. break;
  225. case '%': /* Escape */
  226. *b++ = '%';
  227. break;
  228. default: /* Nothing at all, just dump it */
  229. *b++ = *f;
  230. break;
  231. }
  232. }
  233. /* Ensure the buffer ends in a null */
  234. *b = '\0';
  235. return b - buf;
  236. }
  237. size_t vasprintf(char ** buf, const char * fmt, va_list args) {
  238. char * b = malloc(1024);
  239. *buf = b;
  240. return xvasprintf(b, fmt, args);
  241. }
  242. int vsprintf(char * buf, const char *fmt, va_list args) {
  243. return xvasprintf(buf, fmt, args);
  244. }
  245. int vsnprintf(char * buf, size_t size, const char *fmt, va_list args) {
  246. /* XXX */
  247. return xvasprintf(buf, fmt, args);
  248. }
  249. int fprintf(FILE * device, const char *fmt, ...) {
  250. va_list args;
  251. va_start(args, fmt);
  252. char * buffer;
  253. vasprintf(&buffer, fmt, args);
  254. va_end(args);
  255. int out = fwrite(buffer, 1, strlen(buffer), device);
  256. free(buffer);
  257. return out;
  258. }
  259. int printf(const char *fmt, ...) {
  260. va_list args;
  261. va_start(args, fmt);
  262. char * buffer;
  263. vasprintf(&buffer, fmt, args);
  264. va_end(args);
  265. int out = fwrite(buffer, 1, strlen(buffer), stdout);
  266. free(buffer);
  267. return out;
  268. }
  269. int sprintf(char * buf, const char *fmt, ...) {
  270. va_list args;
  271. va_start(args, fmt);
  272. int out = xvasprintf(buf, fmt, args);
  273. va_end(args);
  274. return out;
  275. }
  276. int snprintf(char * buf, size_t size, const char * fmt, ...) {
  277. /* XXX This is bad. */
  278. (void)size;
  279. va_list args;
  280. va_start(args, fmt);
  281. int out = xvasprintf(buf, fmt, args);
  282. va_end(args);
  283. return out;
  284. }