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; 212c978d9bSAndrew Jones } strprops_t; 222c978d9bSAndrew Jones 237d36db35SAvi Kivity static void addchar(pstream_t *p, char c) 247d36db35SAvi Kivity { 257d36db35SAvi Kivity if (p->remain) { 267d36db35SAvi Kivity *p->buffer++ = c; 277d36db35SAvi Kivity --p->remain; 287d36db35SAvi Kivity } 297d36db35SAvi Kivity ++p->added; 307d36db35SAvi Kivity } 317d36db35SAvi Kivity 322c978d9bSAndrew Jones void print_str(pstream_t *p, const char *s, strprops_t props) 337d36db35SAvi Kivity { 342c978d9bSAndrew Jones const char *s_orig = s; 352c978d9bSAndrew Jones int npad = props.npad; 362c978d9bSAndrew Jones 372c978d9bSAndrew Jones if (npad > 0) { 382c978d9bSAndrew Jones npad -= strlen(s_orig); 392c978d9bSAndrew Jones while (npad > 0) { 402c978d9bSAndrew Jones addchar(p, props.pad); 412c978d9bSAndrew Jones --npad; 422c978d9bSAndrew Jones } 432c978d9bSAndrew Jones } 442c978d9bSAndrew Jones 457d36db35SAvi Kivity while (*s) 467d36db35SAvi Kivity addchar(p, *s++); 472c978d9bSAndrew Jones 482c978d9bSAndrew Jones if (npad < 0) { 492c978d9bSAndrew Jones props.pad = ' '; /* ignore '0' flag with '-' flag */ 502c978d9bSAndrew Jones npad += strlen(s_orig); 512c978d9bSAndrew Jones while (npad < 0) { 522c978d9bSAndrew Jones addchar(p, props.pad); 532c978d9bSAndrew Jones ++npad; 542c978d9bSAndrew Jones } 552c978d9bSAndrew Jones } 567d36db35SAvi Kivity } 577d36db35SAvi Kivity 587d36db35SAvi Kivity static char digits[16] = "0123456789abcdef"; 597d36db35SAvi Kivity 602c978d9bSAndrew Jones void print_int(pstream_t *ps, long long n, int base, strprops_t props) 617d36db35SAvi Kivity { 627d36db35SAvi Kivity char buf[sizeof(long) * 3 + 2], *p = buf; 637d36db35SAvi Kivity int s = 0, i; 647d36db35SAvi Kivity 657d36db35SAvi Kivity if (n < 0) { 667d36db35SAvi Kivity n = -n; 677d36db35SAvi Kivity s = 1; 687d36db35SAvi Kivity } 697d36db35SAvi Kivity 707d36db35SAvi Kivity while (n) { 717d36db35SAvi Kivity *p++ = digits[n % base]; 727d36db35SAvi Kivity n /= base; 737d36db35SAvi Kivity } 747d36db35SAvi Kivity 757d36db35SAvi Kivity if (s) 767d36db35SAvi Kivity *p++ = '-'; 777d36db35SAvi Kivity 787d36db35SAvi Kivity if (p == buf) 797d36db35SAvi Kivity *p++ = '0'; 807d36db35SAvi Kivity 817d36db35SAvi Kivity for (i = 0; i < (p - buf) / 2; ++i) { 827d36db35SAvi Kivity char tmp; 837d36db35SAvi Kivity 847d36db35SAvi Kivity tmp = buf[i]; 857d36db35SAvi Kivity buf[i] = p[-1-i]; 867d36db35SAvi Kivity p[-1-i] = tmp; 877d36db35SAvi Kivity } 887d36db35SAvi Kivity 897d36db35SAvi Kivity *p = 0; 907d36db35SAvi Kivity 912c978d9bSAndrew Jones print_str(ps, buf, props); 927d36db35SAvi Kivity } 937d36db35SAvi Kivity 942c978d9bSAndrew Jones void print_unsigned(pstream_t *ps, unsigned long long n, int base, 952c978d9bSAndrew Jones strprops_t props) 967d36db35SAvi Kivity { 977d36db35SAvi Kivity char buf[sizeof(long) * 3 + 1], *p = buf; 987d36db35SAvi Kivity int i; 997d36db35SAvi Kivity 1007d36db35SAvi Kivity while (n) { 1017d36db35SAvi Kivity *p++ = digits[n % base]; 1027d36db35SAvi Kivity n /= base; 1037d36db35SAvi Kivity } 1047d36db35SAvi Kivity 1057d36db35SAvi Kivity if (p == buf) 1067d36db35SAvi Kivity *p++ = '0'; 1077d36db35SAvi Kivity 1087d36db35SAvi Kivity for (i = 0; i < (p - buf) / 2; ++i) { 1097d36db35SAvi Kivity char tmp; 1107d36db35SAvi Kivity 1117d36db35SAvi Kivity tmp = buf[i]; 1127d36db35SAvi Kivity buf[i] = p[-1-i]; 1137d36db35SAvi Kivity p[-1-i] = tmp; 1147d36db35SAvi Kivity } 1157d36db35SAvi Kivity 1167d36db35SAvi Kivity *p = 0; 1177d36db35SAvi Kivity 1182c978d9bSAndrew Jones print_str(ps, buf, props); 1192c978d9bSAndrew Jones } 1202c978d9bSAndrew Jones 1212c978d9bSAndrew Jones static int fmtnum(const char **fmt) 1222c978d9bSAndrew Jones { 1232c978d9bSAndrew Jones const char *f = *fmt; 1242c978d9bSAndrew Jones int len = 0, num; 1252c978d9bSAndrew Jones 1262c978d9bSAndrew Jones if (*f == '-') 1272c978d9bSAndrew Jones ++f, ++len; 1282c978d9bSAndrew Jones 1292c978d9bSAndrew Jones while (*f >= '0' && *f <= '9') 1302c978d9bSAndrew Jones ++f, ++len; 1312c978d9bSAndrew Jones 1322c978d9bSAndrew Jones num = atol(*fmt); 1332c978d9bSAndrew Jones *fmt += len; 1342c978d9bSAndrew Jones return num; 1357d36db35SAvi Kivity } 1367d36db35SAvi Kivity 1377d36db35SAvi Kivity int vsnprintf(char *buf, int size, const char *fmt, va_list va) 1387d36db35SAvi Kivity { 1397d36db35SAvi Kivity pstream_t s; 1407d36db35SAvi Kivity 1417d36db35SAvi Kivity s.buffer = buf; 1427d36db35SAvi Kivity s.remain = size - 1; 1437d36db35SAvi Kivity s.added = 0; 1447d36db35SAvi Kivity while (*fmt) { 1457d36db35SAvi Kivity char f = *fmt++; 1467d36db35SAvi Kivity int nlong = 0; 1472c978d9bSAndrew Jones strprops_t props; 1482c978d9bSAndrew Jones memset(&props, 0, sizeof(props)); 1492c978d9bSAndrew Jones props.pad = ' '; 1507d36db35SAvi Kivity 1517d36db35SAvi Kivity if (f != '%') { 1527d36db35SAvi Kivity addchar(&s, f); 1537d36db35SAvi Kivity continue; 1547d36db35SAvi Kivity } 1557d36db35SAvi Kivity morefmt: 1567d36db35SAvi Kivity f = *fmt++; 1577d36db35SAvi Kivity switch (f) { 1587d36db35SAvi Kivity case '%': 1597d36db35SAvi Kivity addchar(&s, '%'); 1607d36db35SAvi Kivity break; 1613d7d5195SMichael S. Tsirkin case 'c': 1623d7d5195SMichael S. Tsirkin addchar(&s, va_arg(va, int)); 1633d7d5195SMichael S. Tsirkin break; 1647d36db35SAvi Kivity case '\0': 1657d36db35SAvi Kivity --fmt; 1667d36db35SAvi Kivity break; 1672c978d9bSAndrew Jones case '0': 1682c978d9bSAndrew Jones props.pad = '0'; 1692c978d9bSAndrew Jones ++fmt; 1702c978d9bSAndrew Jones /* fall through */ 1712c978d9bSAndrew Jones case '1'...'9': 1722c978d9bSAndrew Jones case '-': 1732c978d9bSAndrew Jones --fmt; 1742c978d9bSAndrew Jones props.npad = fmtnum(&fmt); 1752c978d9bSAndrew Jones goto morefmt; 1767d36db35SAvi Kivity case 'l': 1777d36db35SAvi Kivity ++nlong; 1787d36db35SAvi Kivity goto morefmt; 179*cda042caSPaolo Bonzini case 't': 180*cda042caSPaolo Bonzini case 'z': 181*cda042caSPaolo Bonzini /* Here we only care that sizeof(size_t) == sizeof(long). 182*cda042caSPaolo Bonzini * On a 32-bit platform it doesn't matter that size_t is 183*cda042caSPaolo Bonzini * typedef'ed to int or long; va_arg will work either way. 184*cda042caSPaolo Bonzini * Same for ptrdiff_t (%td). 185*cda042caSPaolo Bonzini */ 186*cda042caSPaolo Bonzini nlong = 1; 187*cda042caSPaolo Bonzini goto morefmt; 1887d36db35SAvi Kivity case 'd': 1897d36db35SAvi Kivity switch (nlong) { 1907d36db35SAvi Kivity case 0: 1912c978d9bSAndrew Jones print_int(&s, va_arg(va, int), 10, props); 1927d36db35SAvi Kivity break; 1937d36db35SAvi Kivity case 1: 1942c978d9bSAndrew Jones print_int(&s, va_arg(va, long), 10, props); 1957d36db35SAvi Kivity break; 1967d36db35SAvi Kivity default: 1972c978d9bSAndrew Jones print_int(&s, va_arg(va, long long), 10, props); 1987d36db35SAvi Kivity break; 1997d36db35SAvi Kivity } 2007d36db35SAvi Kivity break; 2013a08f439SAlex Bennée case 'u': 2023a08f439SAlex Bennée switch (nlong) { 2033a08f439SAlex Bennée case 0: 2043a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned), 10, props); 2053a08f439SAlex Bennée break; 2063a08f439SAlex Bennée case 1: 2073a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned long), 10, props); 2083a08f439SAlex Bennée break; 2093a08f439SAlex Bennée default: 2103a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned long long), 10, props); 2113a08f439SAlex Bennée break; 2123a08f439SAlex Bennée } 2133a08f439SAlex Bennée break; 2147d36db35SAvi Kivity case 'x': 2157d36db35SAvi Kivity switch (nlong) { 2167d36db35SAvi Kivity case 0: 2172c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned), 16, props); 2187d36db35SAvi Kivity break; 2197d36db35SAvi Kivity case 1: 2202c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned long), 16, props); 2217d36db35SAvi Kivity break; 2227d36db35SAvi Kivity default: 2232c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned long long), 16, props); 2247d36db35SAvi Kivity break; 2257d36db35SAvi Kivity } 2267d36db35SAvi Kivity break; 2277d36db35SAvi Kivity case 'p': 2282c978d9bSAndrew Jones print_str(&s, "0x", props); 2292c978d9bSAndrew Jones print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props); 2307d36db35SAvi Kivity break; 2317d36db35SAvi Kivity case 's': 2322c978d9bSAndrew Jones print_str(&s, va_arg(va, const char *), props); 2337d36db35SAvi Kivity break; 2347d36db35SAvi Kivity default: 2357d36db35SAvi Kivity addchar(&s, f); 2367d36db35SAvi Kivity break; 2377d36db35SAvi Kivity } 2387d36db35SAvi Kivity } 2397d36db35SAvi Kivity *s.buffer = 0; 2407d36db35SAvi Kivity return s.added; 2417d36db35SAvi Kivity } 2427d36db35SAvi Kivity 2437d36db35SAvi Kivity 2447d36db35SAvi Kivity int snprintf(char *buf, int size, const char *fmt, ...) 2457d36db35SAvi Kivity { 2467d36db35SAvi Kivity va_list va; 2477d36db35SAvi Kivity int r; 2487d36db35SAvi Kivity 2497d36db35SAvi Kivity va_start(va, fmt); 2507d36db35SAvi Kivity r = vsnprintf(buf, size, fmt, va); 2517d36db35SAvi Kivity va_end(va); 2527d36db35SAvi Kivity return r; 2537d36db35SAvi Kivity } 2547d36db35SAvi Kivity 255cb12ecccSAndrew Jones int vprintf(const char *fmt, va_list va) 256cb12ecccSAndrew Jones { 257cb12ecccSAndrew Jones char buf[BUFSZ]; 258cb12ecccSAndrew Jones int r; 259cb12ecccSAndrew Jones 260cb12ecccSAndrew Jones r = vsnprintf(buf, sizeof(buf), fmt, va); 261cb12ecccSAndrew Jones puts(buf); 262cb12ecccSAndrew Jones return r; 263cb12ecccSAndrew Jones } 264cb12ecccSAndrew Jones 2657d36db35SAvi Kivity int printf(const char *fmt, ...) 2667d36db35SAvi Kivity { 2677d36db35SAvi Kivity va_list va; 268cb12ecccSAndrew Jones char buf[BUFSZ]; 2697d36db35SAvi Kivity int r; 2707d36db35SAvi Kivity 2717d36db35SAvi Kivity va_start(va, fmt); 2727d36db35SAvi Kivity r = vsnprintf(buf, sizeof buf, fmt, va); 2737d36db35SAvi Kivity va_end(va); 2747d36db35SAvi Kivity puts(buf); 2757d36db35SAvi Kivity return r; 2767d36db35SAvi Kivity } 277840375e1SPeter Feiner 278840375e1SPeter Feiner void binstr(unsigned long x, char out[BINSTR_SZ]) 279840375e1SPeter Feiner { 280840375e1SPeter Feiner int i; 281840375e1SPeter Feiner char *c; 282840375e1SPeter Feiner int n; 283840375e1SPeter Feiner 284840375e1SPeter Feiner n = sizeof(unsigned long) * 8; 285840375e1SPeter Feiner i = 0; 286840375e1SPeter Feiner c = &out[0]; 287840375e1SPeter Feiner for (;;) { 288840375e1SPeter Feiner *c++ = (x & (1ul << (n - i - 1))) ? '1' : '0'; 289840375e1SPeter Feiner i++; 290840375e1SPeter Feiner 291840375e1SPeter Feiner if (i == n) { 292840375e1SPeter Feiner *c = '\0'; 293840375e1SPeter Feiner break; 294840375e1SPeter Feiner } 295840375e1SPeter Feiner if (i % 4 == 0) 296840375e1SPeter Feiner *c++ = '\''; 297840375e1SPeter Feiner } 298840375e1SPeter Feiner assert(c + 1 - &out[0] == BINSTR_SZ); 299840375e1SPeter Feiner } 300840375e1SPeter Feiner 301840375e1SPeter Feiner void print_binstr(unsigned long x) 302840375e1SPeter Feiner { 303840375e1SPeter Feiner char out[BINSTR_SZ]; 304840375e1SPeter Feiner binstr(x, out); 305840375e1SPeter Feiner printf("%s", out); 306840375e1SPeter Feiner } 307