xref: /kvm-unit-tests/lib/printf.c (revision cb12ecccb3d57b7a93f2c4b2393e462c3deb84e9)
17d36db35SAvi Kivity #include "libcflat.h"
27d36db35SAvi Kivity 
3*cb12ecccSAndrew Jones #define BUFSZ 2000
4*cb12ecccSAndrew Jones 
57d36db35SAvi Kivity typedef struct pstream {
67d36db35SAvi Kivity     char *buffer;
77d36db35SAvi Kivity     int remain;
87d36db35SAvi Kivity     int added;
97d36db35SAvi Kivity } pstream_t;
107d36db35SAvi Kivity 
112c978d9bSAndrew Jones typedef struct strprops {
122c978d9bSAndrew Jones     char pad;
132c978d9bSAndrew Jones     int npad;
142c978d9bSAndrew Jones } strprops_t;
152c978d9bSAndrew Jones 
167d36db35SAvi Kivity static void addchar(pstream_t *p, char c)
177d36db35SAvi Kivity {
187d36db35SAvi Kivity     if (p->remain) {
197d36db35SAvi Kivity 	*p->buffer++ = c;
207d36db35SAvi Kivity 	--p->remain;
217d36db35SAvi Kivity     }
227d36db35SAvi Kivity     ++p->added;
237d36db35SAvi Kivity }
247d36db35SAvi Kivity 
252c978d9bSAndrew Jones void print_str(pstream_t *p, const char *s, strprops_t props)
267d36db35SAvi Kivity {
272c978d9bSAndrew Jones     const char *s_orig = s;
282c978d9bSAndrew Jones     int npad = props.npad;
292c978d9bSAndrew Jones 
302c978d9bSAndrew Jones     if (npad > 0) {
312c978d9bSAndrew Jones 	npad -= strlen(s_orig);
322c978d9bSAndrew Jones 	while (npad > 0) {
332c978d9bSAndrew Jones 	    addchar(p, props.pad);
342c978d9bSAndrew Jones 	    --npad;
352c978d9bSAndrew Jones 	}
362c978d9bSAndrew Jones     }
372c978d9bSAndrew Jones 
387d36db35SAvi Kivity     while (*s)
397d36db35SAvi Kivity 	addchar(p, *s++);
402c978d9bSAndrew Jones 
412c978d9bSAndrew Jones     if (npad < 0) {
422c978d9bSAndrew Jones 	props.pad = ' '; /* ignore '0' flag with '-' flag */
432c978d9bSAndrew Jones 	npad += strlen(s_orig);
442c978d9bSAndrew Jones 	while (npad < 0) {
452c978d9bSAndrew Jones 	    addchar(p, props.pad);
462c978d9bSAndrew Jones 	    ++npad;
472c978d9bSAndrew Jones 	}
482c978d9bSAndrew Jones     }
497d36db35SAvi Kivity }
507d36db35SAvi Kivity 
517d36db35SAvi Kivity static char digits[16] = "0123456789abcdef";
527d36db35SAvi Kivity 
532c978d9bSAndrew Jones void print_int(pstream_t *ps, long long n, int base, strprops_t props)
547d36db35SAvi Kivity {
557d36db35SAvi Kivity     char buf[sizeof(long) * 3 + 2], *p = buf;
567d36db35SAvi Kivity     int s = 0, i;
577d36db35SAvi Kivity 
587d36db35SAvi Kivity     if (n < 0) {
597d36db35SAvi Kivity 	n = -n;
607d36db35SAvi Kivity 	s = 1;
617d36db35SAvi Kivity     }
627d36db35SAvi Kivity 
637d36db35SAvi Kivity     while (n) {
647d36db35SAvi Kivity 	*p++ = digits[n % base];
657d36db35SAvi Kivity 	n /= base;
667d36db35SAvi Kivity     }
677d36db35SAvi Kivity 
687d36db35SAvi Kivity     if (s)
697d36db35SAvi Kivity 	*p++ = '-';
707d36db35SAvi Kivity 
717d36db35SAvi Kivity     if (p == buf)
727d36db35SAvi Kivity 	*p++ = '0';
737d36db35SAvi Kivity 
747d36db35SAvi Kivity     for (i = 0; i < (p - buf) / 2; ++i) {
757d36db35SAvi Kivity 	char tmp;
767d36db35SAvi Kivity 
777d36db35SAvi Kivity 	tmp = buf[i];
787d36db35SAvi Kivity 	buf[i] = p[-1-i];
797d36db35SAvi Kivity 	p[-1-i] = tmp;
807d36db35SAvi Kivity     }
817d36db35SAvi Kivity 
827d36db35SAvi Kivity     *p = 0;
837d36db35SAvi Kivity 
842c978d9bSAndrew Jones     print_str(ps, buf, props);
857d36db35SAvi Kivity }
867d36db35SAvi Kivity 
872c978d9bSAndrew Jones void print_unsigned(pstream_t *ps, unsigned long long n, int base,
882c978d9bSAndrew Jones 		    strprops_t props)
897d36db35SAvi Kivity {
907d36db35SAvi Kivity     char buf[sizeof(long) * 3 + 1], *p = buf;
917d36db35SAvi Kivity     int i;
927d36db35SAvi Kivity 
937d36db35SAvi Kivity     while (n) {
947d36db35SAvi Kivity 	*p++ = digits[n % base];
957d36db35SAvi Kivity 	n /= base;
967d36db35SAvi Kivity     }
977d36db35SAvi Kivity 
987d36db35SAvi Kivity     if (p == buf)
997d36db35SAvi Kivity 	*p++ = '0';
1007d36db35SAvi Kivity 
1017d36db35SAvi Kivity     for (i = 0; i < (p - buf) / 2; ++i) {
1027d36db35SAvi Kivity 	char tmp;
1037d36db35SAvi Kivity 
1047d36db35SAvi Kivity 	tmp = buf[i];
1057d36db35SAvi Kivity 	buf[i] = p[-1-i];
1067d36db35SAvi Kivity 	p[-1-i] = tmp;
1077d36db35SAvi Kivity     }
1087d36db35SAvi Kivity 
1097d36db35SAvi Kivity     *p = 0;
1107d36db35SAvi Kivity 
1112c978d9bSAndrew Jones     print_str(ps, buf, props);
1122c978d9bSAndrew Jones }
1132c978d9bSAndrew Jones 
1142c978d9bSAndrew Jones static int fmtnum(const char **fmt)
1152c978d9bSAndrew Jones {
1162c978d9bSAndrew Jones     const char *f = *fmt;
1172c978d9bSAndrew Jones     int len = 0, num;
1182c978d9bSAndrew Jones 
1192c978d9bSAndrew Jones     if (*f == '-')
1202c978d9bSAndrew Jones 	++f, ++len;
1212c978d9bSAndrew Jones 
1222c978d9bSAndrew Jones     while (*f >= '0' && *f <= '9')
1232c978d9bSAndrew Jones 	++f, ++len;
1242c978d9bSAndrew Jones 
1252c978d9bSAndrew Jones     num = atol(*fmt);
1262c978d9bSAndrew Jones     *fmt += len;
1272c978d9bSAndrew Jones     return num;
1287d36db35SAvi Kivity }
1297d36db35SAvi Kivity 
1307d36db35SAvi Kivity int vsnprintf(char *buf, int size, const char *fmt, va_list va)
1317d36db35SAvi Kivity {
1327d36db35SAvi Kivity     pstream_t s;
1337d36db35SAvi Kivity 
1347d36db35SAvi Kivity     s.buffer = buf;
1357d36db35SAvi Kivity     s.remain = size - 1;
1367d36db35SAvi Kivity     s.added = 0;
1377d36db35SAvi Kivity     while (*fmt) {
1387d36db35SAvi Kivity 	char f = *fmt++;
1397d36db35SAvi Kivity 	int nlong = 0;
1402c978d9bSAndrew Jones 	strprops_t props;
1412c978d9bSAndrew Jones 	memset(&props, 0, sizeof(props));
1422c978d9bSAndrew Jones 	props.pad = ' ';
1437d36db35SAvi Kivity 
1447d36db35SAvi Kivity 	if (f != '%') {
1457d36db35SAvi Kivity 	    addchar(&s, f);
1467d36db35SAvi Kivity 	    continue;
1477d36db35SAvi Kivity 	}
1487d36db35SAvi Kivity     morefmt:
1497d36db35SAvi Kivity 	f = *fmt++;
1507d36db35SAvi Kivity 	switch (f) {
1517d36db35SAvi Kivity 	case '%':
1527d36db35SAvi Kivity 	    addchar(&s, '%');
1537d36db35SAvi Kivity 	    break;
1543d7d5195SMichael S. Tsirkin 	case 'c':
1553d7d5195SMichael S. Tsirkin             addchar(&s, va_arg(va, int));
1563d7d5195SMichael S. Tsirkin 	    break;
1577d36db35SAvi Kivity 	case '\0':
1587d36db35SAvi Kivity 	    --fmt;
1597d36db35SAvi Kivity 	    break;
1602c978d9bSAndrew Jones 	case '0':
1612c978d9bSAndrew Jones 	    props.pad = '0';
1622c978d9bSAndrew Jones 	    ++fmt;
1632c978d9bSAndrew Jones 	    /* fall through */
1642c978d9bSAndrew Jones 	case '1'...'9':
1652c978d9bSAndrew Jones 	case '-':
1662c978d9bSAndrew Jones 	    --fmt;
1672c978d9bSAndrew Jones 	    props.npad = fmtnum(&fmt);
1682c978d9bSAndrew Jones 	    goto morefmt;
1697d36db35SAvi Kivity 	case 'l':
1707d36db35SAvi Kivity 	    ++nlong;
1717d36db35SAvi Kivity 	    goto morefmt;
1727d36db35SAvi Kivity 	case 'd':
1737d36db35SAvi Kivity 	    switch (nlong) {
1747d36db35SAvi Kivity 	    case 0:
1752c978d9bSAndrew Jones 		print_int(&s, va_arg(va, int), 10, props);
1767d36db35SAvi Kivity 		break;
1777d36db35SAvi Kivity 	    case 1:
1782c978d9bSAndrew Jones 		print_int(&s, va_arg(va, long), 10, props);
1797d36db35SAvi Kivity 		break;
1807d36db35SAvi Kivity 	    default:
1812c978d9bSAndrew Jones 		print_int(&s, va_arg(va, long long), 10, props);
1827d36db35SAvi Kivity 		break;
1837d36db35SAvi Kivity 	    }
1847d36db35SAvi Kivity 	    break;
1853a08f439SAlex Bennée 	case 'u':
1863a08f439SAlex Bennée 	    switch (nlong) {
1873a08f439SAlex Bennée 	    case 0:
1883a08f439SAlex Bennée 		print_unsigned(&s, va_arg(va, unsigned), 10, props);
1893a08f439SAlex Bennée 		break;
1903a08f439SAlex Bennée 	    case 1:
1913a08f439SAlex Bennée 		print_unsigned(&s, va_arg(va, unsigned long), 10, props);
1923a08f439SAlex Bennée 		break;
1933a08f439SAlex Bennée 	    default:
1943a08f439SAlex Bennée 		print_unsigned(&s, va_arg(va, unsigned long long), 10, props);
1953a08f439SAlex Bennée 		break;
1963a08f439SAlex Bennée 	    }
1973a08f439SAlex Bennée 	    break;
1987d36db35SAvi Kivity 	case 'x':
1997d36db35SAvi Kivity 	    switch (nlong) {
2007d36db35SAvi Kivity 	    case 0:
2012c978d9bSAndrew Jones 		print_unsigned(&s, va_arg(va, unsigned), 16, props);
2027d36db35SAvi Kivity 		break;
2037d36db35SAvi Kivity 	    case 1:
2042c978d9bSAndrew Jones 		print_unsigned(&s, va_arg(va, unsigned long), 16, props);
2057d36db35SAvi Kivity 		break;
2067d36db35SAvi Kivity 	    default:
2072c978d9bSAndrew Jones 		print_unsigned(&s, va_arg(va, unsigned long long), 16, props);
2087d36db35SAvi Kivity 		break;
2097d36db35SAvi Kivity 	    }
2107d36db35SAvi Kivity 	    break;
2117d36db35SAvi Kivity 	case 'p':
2122c978d9bSAndrew Jones 	    print_str(&s, "0x", props);
2132c978d9bSAndrew Jones 	    print_unsigned(&s, (unsigned long)va_arg(va, void *), 16, props);
2147d36db35SAvi Kivity 	    break;
2157d36db35SAvi Kivity 	case 's':
2162c978d9bSAndrew Jones 	    print_str(&s, va_arg(va, const char *), props);
2177d36db35SAvi Kivity 	    break;
2187d36db35SAvi Kivity 	default:
2197d36db35SAvi Kivity 	    addchar(&s, f);
2207d36db35SAvi Kivity 	    break;
2217d36db35SAvi Kivity 	}
2227d36db35SAvi Kivity     }
2237d36db35SAvi Kivity     *s.buffer = 0;
2247d36db35SAvi Kivity     ++s.added;
2257d36db35SAvi Kivity     return s.added;
2267d36db35SAvi Kivity }
2277d36db35SAvi Kivity 
2287d36db35SAvi Kivity 
2297d36db35SAvi Kivity int snprintf(char *buf, int size, const char *fmt, ...)
2307d36db35SAvi Kivity {
2317d36db35SAvi Kivity     va_list va;
2327d36db35SAvi Kivity     int r;
2337d36db35SAvi Kivity 
2347d36db35SAvi Kivity     va_start(va, fmt);
2357d36db35SAvi Kivity     r = vsnprintf(buf, size, fmt, va);
2367d36db35SAvi Kivity     va_end(va);
2377d36db35SAvi Kivity     return r;
2387d36db35SAvi Kivity }
2397d36db35SAvi Kivity 
240*cb12ecccSAndrew Jones int vprintf(const char *fmt, va_list va)
241*cb12ecccSAndrew Jones {
242*cb12ecccSAndrew Jones     char buf[BUFSZ];
243*cb12ecccSAndrew Jones     int r;
244*cb12ecccSAndrew Jones 
245*cb12ecccSAndrew Jones     r = vsnprintf(buf, sizeof(buf), fmt, va);
246*cb12ecccSAndrew Jones     puts(buf);
247*cb12ecccSAndrew Jones     return r;
248*cb12ecccSAndrew Jones }
249*cb12ecccSAndrew Jones 
2507d36db35SAvi Kivity int printf(const char *fmt, ...)
2517d36db35SAvi Kivity {
2527d36db35SAvi Kivity     va_list va;
253*cb12ecccSAndrew Jones     char buf[BUFSZ];
2547d36db35SAvi Kivity     int r;
2557d36db35SAvi Kivity 
2567d36db35SAvi Kivity     va_start(va, fmt);
2577d36db35SAvi Kivity     r = vsnprintf(buf, sizeof buf, fmt, va);
2587d36db35SAvi Kivity     va_end(va);
2597d36db35SAvi Kivity     puts(buf);
2607d36db35SAvi Kivity     return r;
2617d36db35SAvi Kivity }
262