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