17d36db35SAvi Kivity #include "libcflat.h" 27d36db35SAvi Kivity 37d36db35SAvi Kivity typedef struct pstream { 47d36db35SAvi Kivity char *buffer; 57d36db35SAvi Kivity int remain; 67d36db35SAvi Kivity int added; 77d36db35SAvi Kivity } pstream_t; 87d36db35SAvi Kivity 9*2c978d9bSAndrew Jones typedef struct strprops { 10*2c978d9bSAndrew Jones char pad; 11*2c978d9bSAndrew Jones int npad; 12*2c978d9bSAndrew Jones } strprops_t; 13*2c978d9bSAndrew Jones 147d36db35SAvi Kivity static void addchar(pstream_t *p, char c) 157d36db35SAvi Kivity { 167d36db35SAvi Kivity if (p->remain) { 177d36db35SAvi Kivity *p->buffer++ = c; 187d36db35SAvi Kivity --p->remain; 197d36db35SAvi Kivity } 207d36db35SAvi Kivity ++p->added; 217d36db35SAvi Kivity } 227d36db35SAvi Kivity 23*2c978d9bSAndrew Jones void print_str(pstream_t *p, const char *s, strprops_t props) 247d36db35SAvi Kivity { 25*2c978d9bSAndrew Jones const char *s_orig = s; 26*2c978d9bSAndrew Jones int npad = props.npad; 27*2c978d9bSAndrew Jones 28*2c978d9bSAndrew Jones if (npad > 0) { 29*2c978d9bSAndrew Jones npad -= strlen(s_orig); 30*2c978d9bSAndrew Jones while (npad > 0) { 31*2c978d9bSAndrew Jones addchar(p, props.pad); 32*2c978d9bSAndrew Jones --npad; 33*2c978d9bSAndrew Jones } 34*2c978d9bSAndrew Jones } 35*2c978d9bSAndrew Jones 367d36db35SAvi Kivity while (*s) 377d36db35SAvi Kivity addchar(p, *s++); 38*2c978d9bSAndrew Jones 39*2c978d9bSAndrew Jones if (npad < 0) { 40*2c978d9bSAndrew Jones props.pad = ' '; /* ignore '0' flag with '-' flag */ 41*2c978d9bSAndrew Jones npad += strlen(s_orig); 42*2c978d9bSAndrew Jones while (npad < 0) { 43*2c978d9bSAndrew Jones addchar(p, props.pad); 44*2c978d9bSAndrew Jones ++npad; 45*2c978d9bSAndrew Jones } 46*2c978d9bSAndrew Jones } 477d36db35SAvi Kivity } 487d36db35SAvi Kivity 497d36db35SAvi Kivity static char digits[16] = "0123456789abcdef"; 507d36db35SAvi Kivity 51*2c978d9bSAndrew Jones void print_int(pstream_t *ps, long long n, int base, strprops_t props) 527d36db35SAvi Kivity { 537d36db35SAvi Kivity char buf[sizeof(long) * 3 + 2], *p = buf; 547d36db35SAvi Kivity int s = 0, i; 557d36db35SAvi Kivity 567d36db35SAvi Kivity if (n < 0) { 577d36db35SAvi Kivity n = -n; 587d36db35SAvi Kivity s = 1; 597d36db35SAvi Kivity } 607d36db35SAvi Kivity 617d36db35SAvi Kivity while (n) { 627d36db35SAvi Kivity *p++ = digits[n % base]; 637d36db35SAvi Kivity n /= base; 647d36db35SAvi Kivity } 657d36db35SAvi Kivity 667d36db35SAvi Kivity if (s) 677d36db35SAvi Kivity *p++ = '-'; 687d36db35SAvi Kivity 697d36db35SAvi Kivity if (p == buf) 707d36db35SAvi Kivity *p++ = '0'; 717d36db35SAvi Kivity 727d36db35SAvi Kivity for (i = 0; i < (p - buf) / 2; ++i) { 737d36db35SAvi Kivity char tmp; 747d36db35SAvi Kivity 757d36db35SAvi Kivity tmp = buf[i]; 767d36db35SAvi Kivity buf[i] = p[-1-i]; 777d36db35SAvi Kivity p[-1-i] = tmp; 787d36db35SAvi Kivity } 797d36db35SAvi Kivity 807d36db35SAvi Kivity *p = 0; 817d36db35SAvi Kivity 82*2c978d9bSAndrew Jones print_str(ps, buf, props); 837d36db35SAvi Kivity } 847d36db35SAvi Kivity 85*2c978d9bSAndrew Jones void print_unsigned(pstream_t *ps, unsigned long long n, int base, 86*2c978d9bSAndrew Jones strprops_t props) 877d36db35SAvi Kivity { 887d36db35SAvi Kivity char buf[sizeof(long) * 3 + 1], *p = buf; 897d36db35SAvi Kivity int i; 907d36db35SAvi Kivity 917d36db35SAvi Kivity while (n) { 927d36db35SAvi Kivity *p++ = digits[n % base]; 937d36db35SAvi Kivity n /= base; 947d36db35SAvi Kivity } 957d36db35SAvi Kivity 967d36db35SAvi Kivity if (p == buf) 977d36db35SAvi Kivity *p++ = '0'; 987d36db35SAvi Kivity 997d36db35SAvi Kivity for (i = 0; i < (p - buf) / 2; ++i) { 1007d36db35SAvi Kivity char tmp; 1017d36db35SAvi Kivity 1027d36db35SAvi Kivity tmp = buf[i]; 1037d36db35SAvi Kivity buf[i] = p[-1-i]; 1047d36db35SAvi Kivity p[-1-i] = tmp; 1057d36db35SAvi Kivity } 1067d36db35SAvi Kivity 1077d36db35SAvi Kivity *p = 0; 1087d36db35SAvi Kivity 109*2c978d9bSAndrew Jones print_str(ps, buf, props); 110*2c978d9bSAndrew Jones } 111*2c978d9bSAndrew Jones 112*2c978d9bSAndrew Jones static int fmtnum(const char **fmt) 113*2c978d9bSAndrew Jones { 114*2c978d9bSAndrew Jones const char *f = *fmt; 115*2c978d9bSAndrew Jones int len = 0, num; 116*2c978d9bSAndrew Jones 117*2c978d9bSAndrew Jones if (*f == '-') 118*2c978d9bSAndrew Jones ++f, ++len; 119*2c978d9bSAndrew Jones 120*2c978d9bSAndrew Jones while (*f >= '0' && *f <= '9') 121*2c978d9bSAndrew Jones ++f, ++len; 122*2c978d9bSAndrew Jones 123*2c978d9bSAndrew Jones num = atol(*fmt); 124*2c978d9bSAndrew Jones *fmt += len; 125*2c978d9bSAndrew Jones return num; 1267d36db35SAvi Kivity } 1277d36db35SAvi Kivity 1287d36db35SAvi Kivity int vsnprintf(char *buf, int size, const char *fmt, va_list va) 1297d36db35SAvi Kivity { 1307d36db35SAvi Kivity pstream_t s; 1317d36db35SAvi Kivity 1327d36db35SAvi Kivity s.buffer = buf; 1337d36db35SAvi Kivity s.remain = size - 1; 1347d36db35SAvi Kivity s.added = 0; 1357d36db35SAvi Kivity while (*fmt) { 1367d36db35SAvi Kivity char f = *fmt++; 1377d36db35SAvi Kivity int nlong = 0; 138*2c978d9bSAndrew Jones strprops_t props; 139*2c978d9bSAndrew Jones memset(&props, 0, sizeof(props)); 140*2c978d9bSAndrew Jones props.pad = ' '; 1417d36db35SAvi Kivity 1427d36db35SAvi Kivity if (f != '%') { 1437d36db35SAvi Kivity addchar(&s, f); 1447d36db35SAvi Kivity continue; 1457d36db35SAvi Kivity } 1467d36db35SAvi Kivity morefmt: 1477d36db35SAvi Kivity f = *fmt++; 1487d36db35SAvi Kivity switch (f) { 1497d36db35SAvi Kivity case '%': 1507d36db35SAvi Kivity addchar(&s, '%'); 1517d36db35SAvi Kivity break; 1523d7d5195SMichael S. Tsirkin case 'c': 1533d7d5195SMichael S. Tsirkin addchar(&s, va_arg(va, int)); 1543d7d5195SMichael S. Tsirkin break; 1557d36db35SAvi Kivity case '\0': 1567d36db35SAvi Kivity --fmt; 1577d36db35SAvi Kivity break; 158*2c978d9bSAndrew Jones case '0': 159*2c978d9bSAndrew Jones props.pad = '0'; 160*2c978d9bSAndrew Jones ++fmt; 161*2c978d9bSAndrew Jones /* fall through */ 162*2c978d9bSAndrew Jones case '1'...'9': 163*2c978d9bSAndrew Jones case '-': 164*2c978d9bSAndrew Jones --fmt; 165*2c978d9bSAndrew Jones props.npad = fmtnum(&fmt); 166*2c978d9bSAndrew Jones goto morefmt; 1677d36db35SAvi Kivity case 'l': 1687d36db35SAvi Kivity ++nlong; 1697d36db35SAvi Kivity goto morefmt; 1707d36db35SAvi Kivity case 'd': 1717d36db35SAvi Kivity switch (nlong) { 1727d36db35SAvi Kivity case 0: 173*2c978d9bSAndrew Jones print_int(&s, va_arg(va, int), 10, props); 1747d36db35SAvi Kivity break; 1757d36db35SAvi Kivity case 1: 176*2c978d9bSAndrew Jones print_int(&s, va_arg(va, long), 10, props); 1777d36db35SAvi Kivity break; 1787d36db35SAvi Kivity default: 179*2c978d9bSAndrew Jones print_int(&s, va_arg(va, long long), 10, props); 1807d36db35SAvi Kivity break; 1817d36db35SAvi Kivity } 1827d36db35SAvi Kivity break; 1837d36db35SAvi Kivity case 'x': 1847d36db35SAvi Kivity switch (nlong) { 1857d36db35SAvi Kivity case 0: 186*2c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned), 16, props); 1877d36db35SAvi Kivity break; 1887d36db35SAvi Kivity case 1: 189*2c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned long), 16, props); 1907d36db35SAvi Kivity break; 1917d36db35SAvi Kivity default: 192*2c978d9bSAndrew Jones print_unsigned(&s, va_arg(va, unsigned long long), 16, props); 1937d36db35SAvi Kivity break; 1947d36db35SAvi Kivity } 1957d36db35SAvi Kivity break; 1967d36db35SAvi Kivity case 'p': 197*2c978d9bSAndrew Jones print_str(&s, "0x", props); 198*2c978d9bSAndrew Jones print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props); 1997d36db35SAvi Kivity break; 2007d36db35SAvi Kivity case 's': 201*2c978d9bSAndrew Jones print_str(&s, va_arg(va, const char *), props); 2027d36db35SAvi Kivity break; 2037d36db35SAvi Kivity default: 2047d36db35SAvi Kivity addchar(&s, f); 2057d36db35SAvi Kivity break; 2067d36db35SAvi Kivity } 2077d36db35SAvi Kivity } 2087d36db35SAvi Kivity *s.buffer = 0; 2097d36db35SAvi Kivity ++s.added; 2107d36db35SAvi Kivity return s.added; 2117d36db35SAvi Kivity } 2127d36db35SAvi Kivity 2137d36db35SAvi Kivity 2147d36db35SAvi Kivity int snprintf(char *buf, int size, const char *fmt, ...) 2157d36db35SAvi Kivity { 2167d36db35SAvi Kivity va_list va; 2177d36db35SAvi Kivity int r; 2187d36db35SAvi Kivity 2197d36db35SAvi Kivity va_start(va, fmt); 2207d36db35SAvi Kivity r = vsnprintf(buf, size, fmt, va); 2217d36db35SAvi Kivity va_end(va); 2227d36db35SAvi Kivity return r; 2237d36db35SAvi Kivity } 2247d36db35SAvi Kivity 2257d36db35SAvi Kivity int printf(const char *fmt, ...) 2267d36db35SAvi Kivity { 2277d36db35SAvi Kivity va_list va; 2287d36db35SAvi Kivity char buf[2000]; 2297d36db35SAvi Kivity int r; 2307d36db35SAvi Kivity 2317d36db35SAvi Kivity va_start(va, fmt); 2327d36db35SAvi Kivity r = vsnprintf(buf, sizeof buf, fmt, va); 2337d36db35SAvi Kivity va_end(va); 2347d36db35SAvi Kivity puts(buf); 2357d36db35SAvi Kivity return r; 2367d36db35SAvi Kivity } 237