xref: /kvm-unit-tests/lib/printf.c (revision e526bc786e9878c3880ae4b09b01a4572756e492)
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"
92a9c2e2fSNikos Nikoleris #include "ctype.h"
107d36db35SAvi Kivity 
11cb12ecccSAndrew Jones #define BUFSZ 2000
12cb12ecccSAndrew Jones 
137d36db35SAvi Kivity typedef struct pstream {
147d36db35SAvi Kivity 	char *buffer;
157d36db35SAvi Kivity 	int remain;
167d36db35SAvi Kivity 	int added;
177d36db35SAvi Kivity } pstream_t;
187d36db35SAvi Kivity 
192c978d9bSAndrew Jones typedef struct strprops {
202c978d9bSAndrew Jones 	char pad;
212c978d9bSAndrew Jones 	int npad;
228ef44442SRadim Krčmář 	bool alternate;
232a9c2e2fSNikos Nikoleris 	int precision;
242c978d9bSAndrew Jones } strprops_t;
252c978d9bSAndrew Jones 
addchar(pstream_t * p,char c)267d36db35SAvi Kivity static void addchar(pstream_t *p, char c)
277d36db35SAvi Kivity {
287d36db35SAvi Kivity 	if (p->remain) {
297d36db35SAvi Kivity 		*p->buffer++ = c;
307d36db35SAvi Kivity 		--p->remain;
317d36db35SAvi Kivity 	}
327d36db35SAvi Kivity 	++p->added;
337d36db35SAvi Kivity }
347d36db35SAvi Kivity 
print_str(pstream_t * p,const char * s,strprops_t props)3523b8916bSThomas Huth static void print_str(pstream_t *p, const char *s, strprops_t props)
367d36db35SAvi Kivity {
372c978d9bSAndrew Jones 	const char *s_orig = s;
382c978d9bSAndrew Jones 	int npad = props.npad;
392c978d9bSAndrew Jones 
402c978d9bSAndrew Jones 	if (npad > 0) {
412c978d9bSAndrew Jones 		npad -= strlen(s_orig);
422c978d9bSAndrew Jones 		while (npad > 0) {
432c978d9bSAndrew Jones 			addchar(p, props.pad);
442c978d9bSAndrew Jones 			--npad;
452c978d9bSAndrew Jones 		}
462c978d9bSAndrew Jones 	}
472c978d9bSAndrew Jones 
482a9c2e2fSNikos Nikoleris 	while (*s && props.precision--)
497d36db35SAvi Kivity 		addchar(p, *s++);
502c978d9bSAndrew Jones 
512c978d9bSAndrew Jones 	if (npad < 0) {
522c978d9bSAndrew Jones 		props.pad = ' ';	/* ignore '0' flag with '-' flag */
532c978d9bSAndrew Jones 		npad += strlen(s_orig);
542c978d9bSAndrew Jones 		while (npad < 0) {
552c978d9bSAndrew Jones 			addchar(p, props.pad);
562c978d9bSAndrew Jones 			++npad;
572c978d9bSAndrew Jones 		}
582c978d9bSAndrew Jones 	}
597d36db35SAvi Kivity }
607d36db35SAvi Kivity 
61*af8e25f9SNikos Nikoleris /*
62*af8e25f9SNikos Nikoleris  * Adapted from drivers/firmware/efi/libstub/vsprintf.c
63*af8e25f9SNikos Nikoleris  */
utf16_to_utf32(const u16 ** s16)64*af8e25f9SNikos Nikoleris static u32 utf16_to_utf32(const u16 **s16)
65*af8e25f9SNikos Nikoleris {
66*af8e25f9SNikos Nikoleris 	u16 c0, c1;
67*af8e25f9SNikos Nikoleris 
68*af8e25f9SNikos Nikoleris 	c0 = *(*s16)++;
69*af8e25f9SNikos Nikoleris 	/* not a surrogate */
70*af8e25f9SNikos Nikoleris 	if ((c0 & 0xf800) != 0xd800)
71*af8e25f9SNikos Nikoleris 		return c0;
72*af8e25f9SNikos Nikoleris 	/* invalid: low surrogate instead of high */
73*af8e25f9SNikos Nikoleris 	if (c0 & 0x0400)
74*af8e25f9SNikos Nikoleris 		return 0xfffd;
75*af8e25f9SNikos Nikoleris 	c1 = **s16;
76*af8e25f9SNikos Nikoleris 	/* invalid: missing low surrogate */
77*af8e25f9SNikos Nikoleris 	if ((c1 & 0xfc00) != 0xdc00)
78*af8e25f9SNikos Nikoleris 		return 0xfffd;
79*af8e25f9SNikos Nikoleris 	/* valid surrogate pair */
80*af8e25f9SNikos Nikoleris 	++(*s16);
81*af8e25f9SNikos Nikoleris 	return (0x10000 - (0xd800 << 10) - 0xdc00) + (c0 << 10) + c1;
82*af8e25f9SNikos Nikoleris }
83*af8e25f9SNikos Nikoleris 
84*af8e25f9SNikos Nikoleris /*
85*af8e25f9SNikos Nikoleris  * Adapted from drivers/firmware/efi/libstub/vsprintf.c
86*af8e25f9SNikos Nikoleris  */
utf16s_utf8nlen(const u16 * s16,size_t maxlen)87*af8e25f9SNikos Nikoleris static size_t utf16s_utf8nlen(const u16 *s16, size_t maxlen)
88*af8e25f9SNikos Nikoleris {
89*af8e25f9SNikos Nikoleris 	size_t len, clen;
90*af8e25f9SNikos Nikoleris 
91*af8e25f9SNikos Nikoleris 	for (len = 0; len < maxlen && *s16; len += clen) {
92*af8e25f9SNikos Nikoleris 		u16 c0 = *s16++;
93*af8e25f9SNikos Nikoleris 
94*af8e25f9SNikos Nikoleris 		/* First, get the length for a BMP character */
95*af8e25f9SNikos Nikoleris 		clen = 1 + (c0 >= 0x80) + (c0 >= 0x800);
96*af8e25f9SNikos Nikoleris 		if (len + clen > maxlen)
97*af8e25f9SNikos Nikoleris 			break;
98*af8e25f9SNikos Nikoleris 		/*
99*af8e25f9SNikos Nikoleris 		 * If this is a high surrogate, and we're already at maxlen, we
100*af8e25f9SNikos Nikoleris 		 * can't include the character if it's a valid surrogate pair.
101*af8e25f9SNikos Nikoleris 		 * Avoid accessing one extra word just to check if it's valid
102*af8e25f9SNikos Nikoleris 		 * or not.
103*af8e25f9SNikos Nikoleris 		 */
104*af8e25f9SNikos Nikoleris 		if ((c0 & 0xfc00) == 0xd800) {
105*af8e25f9SNikos Nikoleris 			if (len + clen == maxlen)
106*af8e25f9SNikos Nikoleris 				break;
107*af8e25f9SNikos Nikoleris 			if ((*s16 & 0xfc00) == 0xdc00) {
108*af8e25f9SNikos Nikoleris 				++s16;
109*af8e25f9SNikos Nikoleris 				++clen;
110*af8e25f9SNikos Nikoleris 			}
111*af8e25f9SNikos Nikoleris 		}
112*af8e25f9SNikos Nikoleris 	}
113*af8e25f9SNikos Nikoleris 
114*af8e25f9SNikos Nikoleris 	return len;
115*af8e25f9SNikos Nikoleris }
116*af8e25f9SNikos Nikoleris 
117*af8e25f9SNikos Nikoleris /*
118*af8e25f9SNikos Nikoleris  * Adapted from drivers/firmware/efi/libstub/vsprintf.c
119*af8e25f9SNikos Nikoleris  */
print_wstring(pstream_t * p,const u16 * s,strprops_t props)120*af8e25f9SNikos Nikoleris static void print_wstring(pstream_t *p, const u16 *s, strprops_t props)
121*af8e25f9SNikos Nikoleris {
122*af8e25f9SNikos Nikoleris 	const u16 *ws = (const u16 *)s;
123*af8e25f9SNikos Nikoleris 	size_t pos = 0, size = p->remain + 1, len = utf16s_utf8nlen(ws, props.precision);
124*af8e25f9SNikos Nikoleris 
125*af8e25f9SNikos Nikoleris 	while (len-- > 0) {
126*af8e25f9SNikos Nikoleris 		u32 c32 = utf16_to_utf32(&ws);
127*af8e25f9SNikos Nikoleris 		u8 *s8;
128*af8e25f9SNikos Nikoleris 		size_t clen;
129*af8e25f9SNikos Nikoleris 
130*af8e25f9SNikos Nikoleris 		if (c32 < 0x80) {
131*af8e25f9SNikos Nikoleris 			addchar(p, c32);
132*af8e25f9SNikos Nikoleris 			continue;
133*af8e25f9SNikos Nikoleris 		}
134*af8e25f9SNikos Nikoleris 
135*af8e25f9SNikos Nikoleris 		/* Number of trailing octets */
136*af8e25f9SNikos Nikoleris 		clen = 1 + (c32 >= 0x800) + (c32 >= 0x10000);
137*af8e25f9SNikos Nikoleris 
138*af8e25f9SNikos Nikoleris 		len -= clen;
139*af8e25f9SNikos Nikoleris 		s8 = (u8 *)(p->buffer - p->added + pos);
140*af8e25f9SNikos Nikoleris 
141*af8e25f9SNikos Nikoleris 		/* Avoid writing partial character */
142*af8e25f9SNikos Nikoleris 		addchar(p, '\0');
143*af8e25f9SNikos Nikoleris 		pos += clen;
144*af8e25f9SNikos Nikoleris 		if (pos >= size)
145*af8e25f9SNikos Nikoleris 			continue;
146*af8e25f9SNikos Nikoleris 
147*af8e25f9SNikos Nikoleris 		/* Set high bits of leading octet */
148*af8e25f9SNikos Nikoleris 		*s8 = (0xf00 >> 1) >> clen;
149*af8e25f9SNikos Nikoleris 		/* Write trailing octets in reverse order */
150*af8e25f9SNikos Nikoleris 		for (s8 += clen; clen; --clen, c32 >>= 6)
151*af8e25f9SNikos Nikoleris 			*s8-- = 0x80 | (c32 & 0x3f);
152*af8e25f9SNikos Nikoleris 		/* Set low bits of leading octet */
153*af8e25f9SNikos Nikoleris 		*s8 |= c32;
154*af8e25f9SNikos Nikoleris 	}
155*af8e25f9SNikos Nikoleris }
156*af8e25f9SNikos Nikoleris 
1577d36db35SAvi Kivity static char digits[16] = "0123456789abcdef";
1587d36db35SAvi Kivity 
print_int(pstream_t * ps,long long n,int base,strprops_t props)15923b8916bSThomas Huth static void print_int(pstream_t *ps, long long n, int base, strprops_t props)
1607d36db35SAvi Kivity {
1617d36db35SAvi Kivity 	char buf[sizeof(long) * 3 + 2], *p = buf;
1627d36db35SAvi Kivity 	int s = 0, i;
1637d36db35SAvi Kivity 
1647d36db35SAvi Kivity 	if (n < 0) {
1657d36db35SAvi Kivity 		n = -n;
1667d36db35SAvi Kivity 		s = 1;
1677d36db35SAvi Kivity 	}
1687d36db35SAvi Kivity 
1697d36db35SAvi Kivity 	while (n) {
1707d36db35SAvi Kivity 		*p++ = digits[n % base];
1717d36db35SAvi Kivity 		n /= base;
1727d36db35SAvi Kivity 	}
1737d36db35SAvi Kivity 
1742a9c2e2fSNikos Nikoleris 	while (p == buf || (p - buf < props.precision))
1752a9c2e2fSNikos Nikoleris 		*p++ = '0';
1762a9c2e2fSNikos Nikoleris 	props.precision = -1;
1772a9c2e2fSNikos Nikoleris 
1787d36db35SAvi Kivity 	if (s)
1797d36db35SAvi Kivity 		*p++ = '-';
1807d36db35SAvi Kivity 
1817d36db35SAvi Kivity 	for (i = 0; i < (p - buf) / 2; ++i) {
1827d36db35SAvi Kivity 		char tmp;
1837d36db35SAvi Kivity 
1847d36db35SAvi Kivity 		tmp = buf[i];
1857d36db35SAvi Kivity 		buf[i] = p[-1 - i];
1867d36db35SAvi Kivity 		p[-1 - i] = tmp;
1877d36db35SAvi Kivity 	}
1887d36db35SAvi Kivity 
1897d36db35SAvi Kivity 	*p = 0;
1907d36db35SAvi Kivity 
1912c978d9bSAndrew Jones 	print_str(ps, buf, props);
1927d36db35SAvi Kivity }
1937d36db35SAvi Kivity 
print_unsigned(pstream_t * ps,unsigned long long n,int base,strprops_t props)19423b8916bSThomas Huth static void print_unsigned(pstream_t *ps, unsigned long long n, int base,
1952c978d9bSAndrew Jones 			   strprops_t props)
1967d36db35SAvi Kivity {
1978ef44442SRadim Krčmář 	char buf[sizeof(long) * 3 + 3], *p = buf;
1987d36db35SAvi Kivity 	int i;
1997d36db35SAvi Kivity 
2007d36db35SAvi Kivity 	while (n) {
2017d36db35SAvi Kivity 		*p++ = digits[n % base];
2027d36db35SAvi Kivity 		n /= base;
2037d36db35SAvi Kivity 	}
2047d36db35SAvi Kivity 
2057d36db35SAvi Kivity 	if (p == buf)
2062a9c2e2fSNikos Nikoleris 		props.alternate = false;
2072a9c2e2fSNikos Nikoleris 
2082a9c2e2fSNikos Nikoleris 	while (p == buf || (p - buf < props.precision))
2097d36db35SAvi Kivity 		*p++ = '0';
2102a9c2e2fSNikos Nikoleris 	props.precision = -1;
2112a9c2e2fSNikos Nikoleris 
2122a9c2e2fSNikos Nikoleris 	if (props.alternate && base == 16) {
213c9af8739SRadim Krčmář 		if (props.pad == '0') {
214c9af8739SRadim Krčmář 			addchar(ps, '0');
215c9af8739SRadim Krčmář 			addchar(ps, 'x');
216c9af8739SRadim Krčmář 
217c9af8739SRadim Krčmář 			if (props.npad > 0)
218c9af8739SRadim Krčmář 				props.npad = MAX(props.npad - 2, 0);
219c9af8739SRadim Krčmář 		} else {
2208ef44442SRadim Krčmář 			*p++ = 'x';
2218ef44442SRadim Krčmář 			*p++ = '0';
2228ef44442SRadim Krčmář 		}
223c9af8739SRadim Krčmář 	}
2247d36db35SAvi Kivity 
2257d36db35SAvi Kivity 	for (i = 0; i < (p - buf) / 2; ++i) {
2267d36db35SAvi Kivity 		char tmp;
2277d36db35SAvi Kivity 
2287d36db35SAvi Kivity 		tmp = buf[i];
2297d36db35SAvi Kivity 		buf[i] = p[-1 - i];
2307d36db35SAvi Kivity 		p[-1 - i] = tmp;
2317d36db35SAvi Kivity 	}
2327d36db35SAvi Kivity 
2337d36db35SAvi Kivity 	*p = 0;
2347d36db35SAvi Kivity 
2352c978d9bSAndrew Jones 	print_str(ps, buf, props);
2362c978d9bSAndrew Jones }
2372c978d9bSAndrew Jones 
fmtnum(const char ** fmt)2382c978d9bSAndrew Jones static int fmtnum(const char **fmt)
2392c978d9bSAndrew Jones {
2402c978d9bSAndrew Jones 	const char *f = *fmt;
2412c978d9bSAndrew Jones 	int len = 0, num;
2422c978d9bSAndrew Jones 
2432c978d9bSAndrew Jones 	if (*f == '-')
2442c978d9bSAndrew Jones 		++f, ++len;
2452c978d9bSAndrew Jones 
2462c978d9bSAndrew Jones 	while (*f >= '0' && *f <= '9')
2472c978d9bSAndrew Jones 		++f, ++len;
2482c978d9bSAndrew Jones 
2492c978d9bSAndrew Jones 	num = atol(*fmt);
2502c978d9bSAndrew Jones 	*fmt += len;
2512c978d9bSAndrew Jones 	return num;
2527d36db35SAvi Kivity }
2537d36db35SAvi Kivity 
2542a9c2e2fSNikos Nikoleris /*
2552a9c2e2fSNikos Nikoleris  * Adapted from drivers/firmware/efi/libstub/vsprintf.c
2562a9c2e2fSNikos Nikoleris  */
skip_atoi(const char ** s)2572a9c2e2fSNikos Nikoleris static int skip_atoi(const char **s)
2582a9c2e2fSNikos Nikoleris {
2592a9c2e2fSNikos Nikoleris 	int i = 0;
2602a9c2e2fSNikos Nikoleris 
2612a9c2e2fSNikos Nikoleris 	do {
2622a9c2e2fSNikos Nikoleris 		i = i*10 + *((*s)++) - '0';
2632a9c2e2fSNikos Nikoleris 	} while (isdigit(**s));
2642a9c2e2fSNikos Nikoleris 
2652a9c2e2fSNikos Nikoleris 	return i;
2662a9c2e2fSNikos Nikoleris }
2672a9c2e2fSNikos Nikoleris 
2682a9c2e2fSNikos Nikoleris /*
2692a9c2e2fSNikos Nikoleris  * Adapted from drivers/firmware/efi/libstub/vsprintf.c
2702a9c2e2fSNikos Nikoleris  */
get_int(const char ** fmt,va_list * ap)2712a9c2e2fSNikos Nikoleris static int get_int(const char **fmt, va_list *ap)
2722a9c2e2fSNikos Nikoleris {
2732a9c2e2fSNikos Nikoleris 	if (isdigit(**fmt))
2742a9c2e2fSNikos Nikoleris 		return skip_atoi(fmt);
2752a9c2e2fSNikos Nikoleris 
2762a9c2e2fSNikos Nikoleris 	if (**fmt == '*') {
2772a9c2e2fSNikos Nikoleris 		++(*fmt);
2782a9c2e2fSNikos Nikoleris 		/* it's the next argument */
2792a9c2e2fSNikos Nikoleris 		return va_arg(*ap, int);
2802a9c2e2fSNikos Nikoleris 	}
2812a9c2e2fSNikos Nikoleris 	return 0;
2822a9c2e2fSNikos Nikoleris }
2832a9c2e2fSNikos Nikoleris 
vsnprintf(char * buf,int size,const char * fmt,va_list va)2847d36db35SAvi Kivity int vsnprintf(char *buf, int size, const char *fmt, va_list va)
2857d36db35SAvi Kivity {
2867d36db35SAvi Kivity 	pstream_t s;
2872a9c2e2fSNikos Nikoleris 	va_list args;
2882a9c2e2fSNikos Nikoleris 
2892a9c2e2fSNikos Nikoleris 	/*
2902a9c2e2fSNikos Nikoleris 	 * We want to pass our input va_list to helper functions by reference,
2912a9c2e2fSNikos Nikoleris 	 * but there's an annoying edge case. If va_list was originally passed
2922a9c2e2fSNikos Nikoleris 	 * to us by value, we could just pass &ap down to the helpers. This is
2932a9c2e2fSNikos Nikoleris 	 * the case on, for example, X86_32.
2942a9c2e2fSNikos Nikoleris 	 * However, on X86_64 (and possibly others), va_list is actually a
2952a9c2e2fSNikos Nikoleris 	 * size-1 array containing a structure. Our function parameter ap has
2962a9c2e2fSNikos Nikoleris 	 * decayed from T[1] to T*, and &ap has type T** rather than T(*)[1],
2972a9c2e2fSNikos Nikoleris 	 * which is what will be expected by a function taking a va_list *
2982a9c2e2fSNikos Nikoleris 	 * parameter.
2992a9c2e2fSNikos Nikoleris 	 * One standard way to solve this mess is by creating a copy in a local
3002a9c2e2fSNikos Nikoleris 	 * variable of type va_list and then passing a pointer to that local
3012a9c2e2fSNikos Nikoleris 	 * copy instead, which is what we do here.
3022a9c2e2fSNikos Nikoleris 	 */
3032a9c2e2fSNikos Nikoleris 	va_copy(args, va);
3047d36db35SAvi Kivity 
3057d36db35SAvi Kivity 	s.buffer = buf;
3067d36db35SAvi Kivity 	s.remain = size - 1;
3077d36db35SAvi Kivity 	s.added = 0;
3087d36db35SAvi Kivity 	while (*fmt) {
3097d36db35SAvi Kivity 		char f = *fmt++;
3107d36db35SAvi Kivity 		int nlong = 0;
3112c978d9bSAndrew Jones 		strprops_t props;
3122c978d9bSAndrew Jones 		memset(&props, 0, sizeof(props));
3132c978d9bSAndrew Jones 		props.pad = ' ';
3142a9c2e2fSNikos Nikoleris 		props.precision = -1;
3157d36db35SAvi Kivity 
3167d36db35SAvi Kivity 		if (f != '%') {
3177d36db35SAvi Kivity 			addchar(&s, f);
3187d36db35SAvi Kivity 			continue;
3197d36db35SAvi Kivity 		}
3207d36db35SAvi Kivity morefmt:
3217d36db35SAvi Kivity 		f = *fmt++;
3227d36db35SAvi Kivity 		switch (f) {
3237d36db35SAvi Kivity 		case '%':
3247d36db35SAvi Kivity 			addchar(&s, '%');
3257d36db35SAvi Kivity 			break;
3263d7d5195SMichael S. Tsirkin 		case 'c':
3272a9c2e2fSNikos Nikoleris 			addchar(&s, va_arg(args, int));
3283d7d5195SMichael S. Tsirkin 			break;
3297d36db35SAvi Kivity 		case '\0':
3307d36db35SAvi Kivity 			--fmt;
3317d36db35SAvi Kivity 			break;
3322a9c2e2fSNikos Nikoleris 		case '.':
3332a9c2e2fSNikos Nikoleris 			props.pad = ' ';
3342a9c2e2fSNikos Nikoleris 			props.precision = get_int(&fmt, &args);
3352a9c2e2fSNikos Nikoleris 			goto morefmt;
336c9af8739SRadim Krčmář 		case '#':
337c9af8739SRadim Krčmář 			props.alternate = true;
338c9af8739SRadim Krčmář 			goto morefmt;
3392c978d9bSAndrew Jones 		case '0':
3402c978d9bSAndrew Jones 			props.pad = '0';
3412c978d9bSAndrew Jones 			++fmt;
3422c978d9bSAndrew Jones 			/* fall through */
3432c978d9bSAndrew Jones 		case '1' ... '9':
3442c978d9bSAndrew Jones 		case '-':
3452c978d9bSAndrew Jones 			--fmt;
3462c978d9bSAndrew Jones 			props.npad = fmtnum(&fmt);
3472c978d9bSAndrew Jones 			goto morefmt;
3487d36db35SAvi Kivity 		case 'l':
3497d36db35SAvi Kivity 			++nlong;
3507d36db35SAvi Kivity 			goto morefmt;
351cda042caSPaolo Bonzini 		case 't':
352cda042caSPaolo Bonzini 		case 'z':
353cda042caSPaolo Bonzini 			/* Here we only care that sizeof(size_t) == sizeof(long).
354cda042caSPaolo Bonzini 			 * On a 32-bit platform it doesn't matter that size_t is
355cda042caSPaolo Bonzini 			 * typedef'ed to int or long; va_arg will work either way.
356cda042caSPaolo Bonzini 			 * Same for ptrdiff_t (%td).
357cda042caSPaolo Bonzini 			 */
358cda042caSPaolo Bonzini 			nlong = 1;
359cda042caSPaolo Bonzini 			goto morefmt;
3607d36db35SAvi Kivity 		case 'd':
3617d36db35SAvi Kivity 			switch (nlong) {
3627d36db35SAvi Kivity 			case 0:
3632a9c2e2fSNikos Nikoleris 				print_int(&s, va_arg(args, int), 10, props);
3647d36db35SAvi Kivity 				break;
3657d36db35SAvi Kivity 			case 1:
3662a9c2e2fSNikos Nikoleris 				print_int(&s, va_arg(args, long), 10, props);
3677d36db35SAvi Kivity 				break;
3687d36db35SAvi Kivity 			default:
3692a9c2e2fSNikos Nikoleris 				print_int(&s, va_arg(args, long long), 10, props);
3707d36db35SAvi Kivity 				break;
3717d36db35SAvi Kivity 			}
3727d36db35SAvi Kivity 			break;
3733a08f439SAlex Bennée 		case 'u':
3743a08f439SAlex Bennée 			switch (nlong) {
3753a08f439SAlex Bennée 			case 0:
3762a9c2e2fSNikos Nikoleris 				print_unsigned(&s, va_arg(args, unsigned int), 10, props);
3773a08f439SAlex Bennée 				break;
3783a08f439SAlex Bennée 			case 1:
3792a9c2e2fSNikos Nikoleris 				print_unsigned(&s, va_arg(args, unsigned long), 10, props);
3803a08f439SAlex Bennée 				break;
3813a08f439SAlex Bennée 			default:
3822a9c2e2fSNikos Nikoleris 				print_unsigned(&s, va_arg(args, unsigned long long), 10, props);
3833a08f439SAlex Bennée 				break;
3843a08f439SAlex Bennée 			}
3853a08f439SAlex Bennée 			break;
3867d36db35SAvi Kivity 		case 'x':
3877d36db35SAvi Kivity 			switch (nlong) {
3887d36db35SAvi Kivity 			case 0:
3892a9c2e2fSNikos Nikoleris 				print_unsigned(&s, va_arg(args, unsigned int), 16, props);
3907d36db35SAvi Kivity 				break;
3917d36db35SAvi Kivity 			case 1:
3922a9c2e2fSNikos Nikoleris 				print_unsigned(&s, va_arg(args, unsigned long), 16, props);
3937d36db35SAvi Kivity 				break;
3947d36db35SAvi Kivity 			default:
3952a9c2e2fSNikos Nikoleris 				print_unsigned(&s, va_arg(args, unsigned long long), 16, props);
3967d36db35SAvi Kivity 				break;
3977d36db35SAvi Kivity 			}
3987d36db35SAvi Kivity 			break;
3997d36db35SAvi Kivity 		case 'p':
4008ef44442SRadim Krčmář 			props.alternate = true;
4012a9c2e2fSNikos Nikoleris 			print_unsigned(&s, (unsigned long)va_arg(args, void *), 16, props);
4027d36db35SAvi Kivity 			break;
4037d36db35SAvi Kivity 		case 's':
404*af8e25f9SNikos Nikoleris 			if (nlong)
405*af8e25f9SNikos Nikoleris 				print_wstring(&s, va_arg(args, const u16 *), props);
406*af8e25f9SNikos Nikoleris 			else
4072a9c2e2fSNikos Nikoleris 				print_str(&s, va_arg(args, const char *), props);
4087d36db35SAvi Kivity 			break;
4097d36db35SAvi Kivity 		default:
4107d36db35SAvi Kivity 			addchar(&s, f);
4117d36db35SAvi Kivity 			break;
4127d36db35SAvi Kivity 		}
4137d36db35SAvi Kivity 	}
4142a9c2e2fSNikos Nikoleris 	va_end(args);
4157d36db35SAvi Kivity 	*s.buffer = 0;
4167d36db35SAvi Kivity 	return s.added;
4177d36db35SAvi Kivity }
4187d36db35SAvi Kivity 
snprintf(char * buf,int size,const char * fmt,...)4197d36db35SAvi Kivity int snprintf(char *buf, int size, const char *fmt, ...)
4207d36db35SAvi Kivity {
4217d36db35SAvi Kivity 	va_list va;
4227d36db35SAvi Kivity 	int r;
4237d36db35SAvi Kivity 
4247d36db35SAvi Kivity 	va_start(va, fmt);
4257d36db35SAvi Kivity 	r = vsnprintf(buf, size, fmt, va);
4267d36db35SAvi Kivity 	va_end(va);
4277d36db35SAvi Kivity 	return r;
4287d36db35SAvi Kivity }
4297d36db35SAvi Kivity 
vprintf(const char * fmt,va_list va)430cb12ecccSAndrew Jones int vprintf(const char *fmt, va_list va)
431cb12ecccSAndrew Jones {
432cb12ecccSAndrew Jones 	char buf[BUFSZ];
433cb12ecccSAndrew Jones 	int r;
434cb12ecccSAndrew Jones 
435cb12ecccSAndrew Jones 	r = vsnprintf(buf, sizeof(buf), fmt, va);
436cb12ecccSAndrew Jones 	puts(buf);
437cb12ecccSAndrew Jones 	return r;
438cb12ecccSAndrew Jones }
439cb12ecccSAndrew Jones 
printf(const char * fmt,...)4407d36db35SAvi Kivity int printf(const char *fmt, ...)
4417d36db35SAvi Kivity {
4427d36db35SAvi Kivity 	va_list va;
443cb12ecccSAndrew Jones 	char buf[BUFSZ];
4447d36db35SAvi Kivity 	int r;
4457d36db35SAvi Kivity 
4467d36db35SAvi Kivity 	va_start(va, fmt);
4477d36db35SAvi Kivity 	r = vsnprintf(buf, sizeof buf, fmt, va);
4487d36db35SAvi Kivity 	va_end(va);
4497d36db35SAvi Kivity 	puts(buf);
4507d36db35SAvi Kivity 	return r;
4517d36db35SAvi Kivity }
452840375e1SPeter Feiner 
binstr(unsigned long x,char out[BINSTR_SZ])453840375e1SPeter Feiner void binstr(unsigned long x, char out[BINSTR_SZ])
454840375e1SPeter Feiner {
455840375e1SPeter Feiner 	int i;
456840375e1SPeter Feiner 	char *c;
457840375e1SPeter Feiner 	int n;
458840375e1SPeter Feiner 
459840375e1SPeter Feiner 	n = sizeof(unsigned long) * 8;
460840375e1SPeter Feiner 	i = 0;
461840375e1SPeter Feiner 	c = &out[0];
462840375e1SPeter Feiner 	for (;;) {
463840375e1SPeter Feiner 		*c++ = (x & (1ul << (n - i - 1))) ? '1' : '0';
464840375e1SPeter Feiner 		i++;
465840375e1SPeter Feiner 
466840375e1SPeter Feiner 		if (i == n) {
467840375e1SPeter Feiner 			*c = '\0';
468840375e1SPeter Feiner 			break;
469840375e1SPeter Feiner 		}
470840375e1SPeter Feiner 		if (i % 4 == 0)
471840375e1SPeter Feiner 			*c++ = '\'';
472840375e1SPeter Feiner 	}
473840375e1SPeter Feiner 	assert(c + 1 - &out[0] == BINSTR_SZ);
474840375e1SPeter Feiner }
475840375e1SPeter Feiner 
print_binstr(unsigned long x)476840375e1SPeter Feiner void print_binstr(unsigned long x)
477840375e1SPeter Feiner {
478840375e1SPeter Feiner 	char out[BINSTR_SZ];
479840375e1SPeter Feiner 	binstr(x, out);
480840375e1SPeter Feiner 	printf("%s", out);
481840375e1SPeter Feiner }
482