14b6da826SThomas Huth /* 24b6da826SThomas Huth * libc printf and friends 34b6da826SThomas Huth * 44b6da826SThomas Huth * This code is free software; you can redistribute it and/or modify it 54b6da826SThomas Huth * under the terms of the GNU Library General Public License version 2. 64b6da826SThomas Huth */ 74b6da826SThomas Huth 87d36db35SAvi Kivity #include "libcflat.h" 97d36db35SAvi Kivity 10cb12ecccSAndrew Jones #define BUFSZ 2000 11cb12ecccSAndrew Jones 127d36db35SAvi Kivity typedef struct pstream { 137d36db35SAvi Kivity char *buffer; 147d36db35SAvi Kivity int remain; 157d36db35SAvi Kivity int added; 167d36db35SAvi Kivity } pstream_t; 177d36db35SAvi Kivity 182c978d9bSAndrew Jones typedef struct strprops { 192c978d9bSAndrew Jones char pad; 202c978d9bSAndrew Jones int npad; 218ef44442SRadim Krčmář bool alternate; 222c978d9bSAndrew Jones } strprops_t; 232c978d9bSAndrew Jones 247d36db35SAvi Kivity static void addchar(pstream_t *p, char c) 257d36db35SAvi Kivity { 267d36db35SAvi Kivity if (p->remain) { 277d36db35SAvi Kivity *p->buffer++ = c; 287d36db35SAvi Kivity --p->remain; 297d36db35SAvi Kivity } 307d36db35SAvi Kivity ++p->added; 317d36db35SAvi Kivity } 327d36db35SAvi Kivity 33*23b8916bSThomas Huth static void print_str(pstream_t *p, const char *s, strprops_t props) 347d36db35SAvi Kivity { 352c978d9bSAndrew Jones const char *s_orig = s; 362c978d9bSAndrew Jones int npad = props.npad; 372c978d9bSAndrew Jones 382c978d9bSAndrew Jones if (npad > 0) { 392c978d9bSAndrew Jones npad -= strlen(s_orig); 402c978d9bSAndrew Jones while (npad > 0) { 412c978d9bSAndrew Jones addchar(p, props.pad); 422c978d9bSAndrew Jones --npad; 432c978d9bSAndrew Jones } 442c978d9bSAndrew Jones } 452c978d9bSAndrew Jones 467d36db35SAvi Kivity while (*s) 477d36db35SAvi Kivity addchar(p, *s++); 482c978d9bSAndrew Jones 492c978d9bSAndrew Jones if (npad < 0) { 502c978d9bSAndrew Jones props.pad = ' '; /* ignore '0' flag with '-' flag */ 512c978d9bSAndrew Jones npad += strlen(s_orig); 522c978d9bSAndrew Jones while (npad < 0) { 532c978d9bSAndrew Jones addchar(p, props.pad); 542c978d9bSAndrew Jones ++npad; 552c978d9bSAndrew Jones } 562c978d9bSAndrew Jones } 577d36db35SAvi Kivity } 587d36db35SAvi Kivity 597d36db35SAvi Kivity static char digits[16] = "0123456789abcdef"; 607d36db35SAvi Kivity 61*23b8916bSThomas Huth static void print_int(pstream_t *ps, long long n, int base, strprops_t props) 627d36db35SAvi Kivity { 637d36db35SAvi Kivity char buf[sizeof(long) * 3 + 2], *p = buf; 647d36db35SAvi Kivity int s = 0, i; 657d36db35SAvi Kivity 667d36db35SAvi Kivity if (n < 0) { 677d36db35SAvi Kivity n = -n; 687d36db35SAvi Kivity s = 1; 697d36db35SAvi Kivity } 707d36db35SAvi Kivity 717d36db35SAvi Kivity while (n) { 727d36db35SAvi Kivity *p++ = digits[n % base]; 737d36db35SAvi Kivity n /= base; 747d36db35SAvi Kivity } 757d36db35SAvi Kivity 767d36db35SAvi Kivity if (s) 777d36db35SAvi Kivity *p++ = '-'; 787d36db35SAvi Kivity 797d36db35SAvi Kivity if (p == buf) 807d36db35SAvi Kivity *p++ = '0'; 817d36db35SAvi Kivity 827d36db35SAvi Kivity for (i = 0; i < (p - buf) / 2; ++i) { 837d36db35SAvi Kivity char tmp; 847d36db35SAvi Kivity 857d36db35SAvi Kivity tmp = buf[i]; 867d36db35SAvi Kivity buf[i] = p[-1-i]; 877d36db35SAvi Kivity p[-1-i] = tmp; 887d36db35SAvi Kivity } 897d36db35SAvi Kivity 907d36db35SAvi Kivity *p = 0; 917d36db35SAvi Kivity 922c978d9bSAndrew Jones print_str(ps, buf, props); 937d36db35SAvi Kivity } 947d36db35SAvi Kivity 95*23b8916bSThomas Huth static void print_unsigned(pstream_t *ps, unsigned long long n, int base, 962c978d9bSAndrew Jones strprops_t props) 977d36db35SAvi Kivity { 988ef44442SRadim Krčmář char buf[sizeof(long) * 3 + 3], *p = buf; 997d36db35SAvi Kivity int i; 1007d36db35SAvi Kivity 1017d36db35SAvi Kivity while (n) { 1027d36db35SAvi Kivity *p++ = digits[n % base]; 1037d36db35SAvi Kivity n /= base; 1047d36db35SAvi Kivity } 1057d36db35SAvi Kivity 1067d36db35SAvi Kivity if (p == buf) 1077d36db35SAvi Kivity *p++ = '0'; 1088ef44442SRadim Krčmář else if (props.alternate && base == 16) { 109c9af8739SRadim Krčmář if (props.pad == '0') { 110c9af8739SRadim Krčmář addchar(ps, '0'); 111c9af8739SRadim Krčmář addchar(ps, 'x'); 112c9af8739SRadim Krčmář 113c9af8739SRadim Krčmář if (props.npad > 0) 114c9af8739SRadim Krčmář props.npad = MAX(props.npad - 2, 0); 115c9af8739SRadim Krčmář } else { 1168ef44442SRadim Krčmář *p++ = 'x'; 1178ef44442SRadim Krčmář *p++ = '0'; 1188ef44442SRadim Krčmář } 119c9af8739SRadim Krčmář } 1207d36db35SAvi Kivity 1217d36db35SAvi Kivity for (i = 0; i < (p - buf) / 2; ++i) { 1227d36db35SAvi Kivity char tmp; 1237d36db35SAvi Kivity 1247d36db35SAvi Kivity tmp = buf[i]; 1257d36db35SAvi Kivity buf[i] = p[-1-i]; 1267d36db35SAvi Kivity p[-1-i] = tmp; 1277d36db35SAvi Kivity } 1287d36db35SAvi Kivity 1297d36db35SAvi Kivity *p = 0; 1307d36db35SAvi Kivity 1312c978d9bSAndrew Jones print_str(ps, buf, props); 1322c978d9bSAndrew Jones } 1332c978d9bSAndrew Jones 1342c978d9bSAndrew Jones static int fmtnum(const char **fmt) 1352c978d9bSAndrew Jones { 1362c978d9bSAndrew Jones const char *f = *fmt; 1372c978d9bSAndrew Jones int len = 0, num; 1382c978d9bSAndrew Jones 1392c978d9bSAndrew Jones if (*f == '-') 1402c978d9bSAndrew Jones ++f, ++len; 1412c978d9bSAndrew Jones 1422c978d9bSAndrew Jones while (*f >= '0' && *f <= '9') 1432c978d9bSAndrew Jones ++f, ++len; 1442c978d9bSAndrew Jones 1452c978d9bSAndrew Jones num = atol(*fmt); 1462c978d9bSAndrew Jones *fmt += len; 1472c978d9bSAndrew Jones return num; 1487d36db35SAvi Kivity } 1497d36db35SAvi Kivity 1507d36db35SAvi Kivity int vsnprintf(char *buf, int size, const char *fmt, va_list va) 1517d36db35SAvi Kivity { 1527d36db35SAvi Kivity pstream_t s; 1537d36db35SAvi Kivity 1547d36db35SAvi Kivity s.buffer = buf; 1557d36db35SAvi Kivity s.remain = size - 1; 1567d36db35SAvi Kivity s.added = 0; 1577d36db35SAvi Kivity while (*fmt) { 1587d36db35SAvi Kivity char f = *fmt++; 1597d36db35SAvi Kivity int nlong = 0; 1602c978d9bSAndrew Jones strprops_t props; 1612c978d9bSAndrew Jones memset(&props, 0, sizeof(props)); 1622c978d9bSAndrew Jones props.pad = ' '; 1637d36db35SAvi Kivity 1647d36db35SAvi Kivity if (f != '%') { 1657d36db35SAvi Kivity addchar(&s, f); 1667d36db35SAvi Kivity continue; 1677d36db35SAvi Kivity } 1687d36db35SAvi Kivity morefmt: 1697d36db35SAvi Kivity f = *fmt++; 1707d36db35SAvi Kivity switch (f) { 1717d36db35SAvi Kivity case '%': 1727d36db35SAvi Kivity addchar(&s, '%'); 1737d36db35SAvi Kivity break; 1743d7d5195SMichael S. Tsirkin case 'c': 1753d7d5195SMichael S. Tsirkin addchar(&s, va_arg(va, int)); 1763d7d5195SMichael S. Tsirkin break; 1777d36db35SAvi Kivity case '\0': 1787d36db35SAvi Kivity --fmt; 1797d36db35SAvi Kivity break; 180c9af8739SRadim Krčmář case '#': 181c9af8739SRadim Krčmář props.alternate = true; 182c9af8739SRadim Krčmář goto morefmt; 1832c978d9bSAndrew Jones case '0': 1842c978d9bSAndrew Jones props.pad = '0'; 1852c978d9bSAndrew Jones ++fmt; 1862c978d9bSAndrew Jones /* fall through */ 1872c978d9bSAndrew Jones case '1'...'9': 1882c978d9bSAndrew Jones case '-': 1892c978d9bSAndrew Jones --fmt; 1902c978d9bSAndrew Jones props.npad = fmtnum(&fmt); 1912c978d9bSAndrew Jones goto morefmt; 1927d36db35SAvi Kivity case 'l': 1937d36db35SAvi Kivity ++nlong; 1947d36db35SAvi Kivity goto morefmt; 195cda042caSPaolo Bonzini case 't': 196cda042caSPaolo Bonzini case 'z': 197cda042caSPaolo Bonzini /* Here we only care that sizeof(size_t) == sizeof(long). 198cda042caSPaolo Bonzini * On a 32-bit platform it doesn't matter that size_t is 199cda042caSPaolo Bonzini * typedef'ed to int or long; va_arg will work either way. 200cda042caSPaolo Bonzini * Same for ptrdiff_t (%td). 201cda042caSPaolo Bonzini */ 202cda042caSPaolo Bonzini nlong = 1; 203cda042caSPaolo Bonzini goto morefmt; 2047d36db35SAvi Kivity case 'd': 2057d36db35SAvi Kivity switch (nlong) { 2067d36db35SAvi Kivity case 0: 2072c978d9bSAndrew Jones print_int(&s, va_arg(va, int), 10, props); 2087d36db35SAvi Kivity break; 2097d36db35SAvi Kivity case 1: 2102c978d9bSAndrew Jones print_int(&s, va_arg(va, long), 10, props); 2117d36db35SAvi Kivity break; 2127d36db35SAvi Kivity default: 2132c978d9bSAndrew Jones print_int(&s, va_arg(va, long long), 10, props); 2147d36db35SAvi Kivity break; 2157d36db35SAvi Kivity } 2167d36db35SAvi Kivity break; 2173a08f439SAlex Bennée case 'u': 2183a08f439SAlex Bennée switch (nlong) { 2193a08f439SAlex Bennée case 0: 2203a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned), 10, props); 2213a08f439SAlex Bennée break; 2223a08f439SAlex Bennée case 1: 2233a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned long), 10, props); 2243a08f439SAlex Bennée break; 2253a08f439SAlex Bennée default: 2263a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned long long), 10, props); 2273a08f439SAlex Bennée break; 2283a08f439SAlex Bennée } 2293a08f439SAlex Bennée break; 2307d36db35SAvi Kivity case 'x': 2317d36db35SAvi Kivity switch (nlong) { 2327d36db35SAvi Kivity case 0: 2332c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned), 16, props); 2347d36db35SAvi Kivity break; 2357d36db35SAvi Kivity case 1: 2362c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned long), 16, props); 2377d36db35SAvi Kivity break; 2387d36db35SAvi Kivity default: 2392c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned long long), 16, props); 2407d36db35SAvi Kivity break; 2417d36db35SAvi Kivity } 2427d36db35SAvi Kivity break; 2437d36db35SAvi Kivity case 'p': 2448ef44442SRadim Krčmář props.alternate = true; 2452c978d9bSAndrew Jones print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props); 2467d36db35SAvi Kivity break; 2477d36db35SAvi Kivity case 's': 2482c978d9bSAndrew Jones print_str(&s, va_arg(va, const char *), props); 2497d36db35SAvi Kivity break; 2507d36db35SAvi Kivity default: 2517d36db35SAvi Kivity addchar(&s, f); 2527d36db35SAvi Kivity break; 2537d36db35SAvi Kivity } 2547d36db35SAvi Kivity } 2557d36db35SAvi Kivity *s.buffer = 0; 2567d36db35SAvi Kivity return s.added; 2577d36db35SAvi Kivity } 2587d36db35SAvi Kivity 2597d36db35SAvi Kivity 2607d36db35SAvi Kivity int snprintf(char *buf, int size, const char *fmt, ...) 2617d36db35SAvi Kivity { 2627d36db35SAvi Kivity va_list va; 2637d36db35SAvi Kivity int r; 2647d36db35SAvi Kivity 2657d36db35SAvi Kivity va_start(va, fmt); 2667d36db35SAvi Kivity r = vsnprintf(buf, size, fmt, va); 2677d36db35SAvi Kivity va_end(va); 2687d36db35SAvi Kivity return r; 2697d36db35SAvi Kivity } 2707d36db35SAvi Kivity 271cb12ecccSAndrew Jones int vprintf(const char *fmt, va_list va) 272cb12ecccSAndrew Jones { 273cb12ecccSAndrew Jones char buf[BUFSZ]; 274cb12ecccSAndrew Jones int r; 275cb12ecccSAndrew Jones 276cb12ecccSAndrew Jones r = vsnprintf(buf, sizeof(buf), fmt, va); 277cb12ecccSAndrew Jones puts(buf); 278cb12ecccSAndrew Jones return r; 279cb12ecccSAndrew Jones } 280cb12ecccSAndrew Jones 2817d36db35SAvi Kivity int printf(const char *fmt, ...) 2827d36db35SAvi Kivity { 2837d36db35SAvi Kivity va_list va; 284cb12ecccSAndrew Jones char buf[BUFSZ]; 2857d36db35SAvi Kivity int r; 2867d36db35SAvi Kivity 2877d36db35SAvi Kivity va_start(va, fmt); 2887d36db35SAvi Kivity r = vsnprintf(buf, sizeof buf, fmt, va); 2897d36db35SAvi Kivity va_end(va); 2907d36db35SAvi Kivity puts(buf); 2917d36db35SAvi Kivity return r; 2927d36db35SAvi Kivity } 293840375e1SPeter Feiner 294840375e1SPeter Feiner void binstr(unsigned long x, char out[BINSTR_SZ]) 295840375e1SPeter Feiner { 296840375e1SPeter Feiner int i; 297840375e1SPeter Feiner char *c; 298840375e1SPeter Feiner int n; 299840375e1SPeter Feiner 300840375e1SPeter Feiner n = sizeof(unsigned long) * 8; 301840375e1SPeter Feiner i = 0; 302840375e1SPeter Feiner c = &out[0]; 303840375e1SPeter Feiner for (;;) { 304840375e1SPeter Feiner *c++ = (x & (1ul << (n - i - 1))) ? '1' : '0'; 305840375e1SPeter Feiner i++; 306840375e1SPeter Feiner 307840375e1SPeter Feiner if (i == n) { 308840375e1SPeter Feiner *c = '\0'; 309840375e1SPeter Feiner break; 310840375e1SPeter Feiner } 311840375e1SPeter Feiner if (i % 4 == 0) 312840375e1SPeter Feiner *c++ = '\''; 313840375e1SPeter Feiner } 314840375e1SPeter Feiner assert(c + 1 - &out[0] == BINSTR_SZ); 315840375e1SPeter Feiner } 316840375e1SPeter Feiner 317840375e1SPeter Feiner void print_binstr(unsigned long x) 318840375e1SPeter Feiner { 319840375e1SPeter Feiner char out[BINSTR_SZ]; 320840375e1SPeter Feiner binstr(x, out); 321840375e1SPeter Feiner printf("%s", out); 322840375e1SPeter Feiner } 323