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; 1797d36db35SAvi Kivity case 'd': 1807d36db35SAvi Kivity switch (nlong) { 1817d36db35SAvi Kivity case 0: 1822c978d9bSAndrew Jones print_int(&s, va_arg(va, int), 10, props); 1837d36db35SAvi Kivity break; 1847d36db35SAvi Kivity case 1: 1852c978d9bSAndrew Jones print_int(&s, va_arg(va, long), 10, props); 1867d36db35SAvi Kivity break; 1877d36db35SAvi Kivity default: 1882c978d9bSAndrew Jones print_int(&s, va_arg(va, long long), 10, props); 1897d36db35SAvi Kivity break; 1907d36db35SAvi Kivity } 1917d36db35SAvi Kivity break; 1923a08f439SAlex Bennée case 'u': 1933a08f439SAlex Bennée switch (nlong) { 1943a08f439SAlex Bennée case 0: 1953a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned), 10, props); 1963a08f439SAlex Bennée break; 1973a08f439SAlex Bennée case 1: 1983a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned long), 10, props); 1993a08f439SAlex Bennée break; 2003a08f439SAlex Bennée default: 2013a08f439SAlex Bennée print_unsigned(&s, va_arg(va, unsigned long long), 10, props); 2023a08f439SAlex Bennée break; 2033a08f439SAlex Bennée } 2043a08f439SAlex Bennée break; 2057d36db35SAvi Kivity case 'x': 2067d36db35SAvi Kivity switch (nlong) { 2077d36db35SAvi Kivity case 0: 2082c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned), 16, props); 2097d36db35SAvi Kivity break; 2107d36db35SAvi Kivity case 1: 2112c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned long), 16, props); 2127d36db35SAvi Kivity break; 2137d36db35SAvi Kivity default: 2142c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned long long), 16, props); 2157d36db35SAvi Kivity break; 2167d36db35SAvi Kivity } 2177d36db35SAvi Kivity break; 2187d36db35SAvi Kivity case 'p': 2192c978d9bSAndrew Jones print_str(&s, "0x", props); 2202c978d9bSAndrew Jones print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props); 2217d36db35SAvi Kivity break; 2227d36db35SAvi Kivity case 's': 2232c978d9bSAndrew Jones print_str(&s, va_arg(va, const char *), props); 2247d36db35SAvi Kivity break; 2257d36db35SAvi Kivity default: 2267d36db35SAvi Kivity addchar(&s, f); 2277d36db35SAvi Kivity break; 2287d36db35SAvi Kivity } 2297d36db35SAvi Kivity } 2307d36db35SAvi Kivity *s.buffer = 0; 2317d36db35SAvi Kivity ++s.added; 2327d36db35SAvi Kivity return s.added; 2337d36db35SAvi Kivity } 2347d36db35SAvi Kivity 2357d36db35SAvi Kivity 2367d36db35SAvi Kivity int snprintf(char *buf, int size, const char *fmt, ...) 2377d36db35SAvi Kivity { 2387d36db35SAvi Kivity va_list va; 2397d36db35SAvi Kivity int r; 2407d36db35SAvi Kivity 2417d36db35SAvi Kivity va_start(va, fmt); 2427d36db35SAvi Kivity r = vsnprintf(buf, size, fmt, va); 2437d36db35SAvi Kivity va_end(va); 2447d36db35SAvi Kivity return r; 2457d36db35SAvi Kivity } 2467d36db35SAvi Kivity 247cb12ecccSAndrew Jones int vprintf(const char *fmt, va_list va) 248cb12ecccSAndrew Jones { 249cb12ecccSAndrew Jones char buf[BUFSZ]; 250cb12ecccSAndrew Jones int r; 251cb12ecccSAndrew Jones 252cb12ecccSAndrew Jones r = vsnprintf(buf, sizeof(buf), fmt, va); 253cb12ecccSAndrew Jones puts(buf); 254cb12ecccSAndrew Jones return r; 255cb12ecccSAndrew Jones } 256cb12ecccSAndrew Jones 2577d36db35SAvi Kivity int printf(const char *fmt, ...) 2587d36db35SAvi Kivity { 2597d36db35SAvi Kivity va_list va; 260cb12ecccSAndrew Jones char buf[BUFSZ]; 2617d36db35SAvi Kivity int r; 2627d36db35SAvi Kivity 2637d36db35SAvi Kivity va_start(va, fmt); 2647d36db35SAvi Kivity r = vsnprintf(buf, sizeof buf, fmt, va); 2657d36db35SAvi Kivity va_end(va); 2667d36db35SAvi Kivity puts(buf); 2677d36db35SAvi Kivity return r; 2687d36db35SAvi Kivity } 269*840375e1SPeter Feiner 270*840375e1SPeter Feiner void binstr(unsigned long x, char out[BINSTR_SZ]) 271*840375e1SPeter Feiner { 272*840375e1SPeter Feiner int i; 273*840375e1SPeter Feiner char *c; 274*840375e1SPeter Feiner int n; 275*840375e1SPeter Feiner 276*840375e1SPeter Feiner n = sizeof(unsigned long) * 8; 277*840375e1SPeter Feiner i = 0; 278*840375e1SPeter Feiner c = &out[0]; 279*840375e1SPeter Feiner for (;;) { 280*840375e1SPeter Feiner *c++ = (x & (1ul << (n - i - 1))) ? '1' : '0'; 281*840375e1SPeter Feiner i++; 282*840375e1SPeter Feiner 283*840375e1SPeter Feiner if (i == n) { 284*840375e1SPeter Feiner *c = '\0'; 285*840375e1SPeter Feiner break; 286*840375e1SPeter Feiner } 287*840375e1SPeter Feiner if (i % 4 == 0) 288*840375e1SPeter Feiner *c++ = '\''; 289*840375e1SPeter Feiner } 290*840375e1SPeter Feiner assert(c + 1 - &out[0] == BINSTR_SZ); 291*840375e1SPeter Feiner } 292*840375e1SPeter Feiner 293*840375e1SPeter Feiner void print_binstr(unsigned long x) 294*840375e1SPeter Feiner { 295*840375e1SPeter Feiner char out[BINSTR_SZ]; 296*840375e1SPeter Feiner binstr(x, out); 297*840375e1SPeter Feiner printf("%s", out); 298*840375e1SPeter Feiner } 299