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 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 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 */ 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 */ 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 */ 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 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 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 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 */ 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 */ 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 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 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 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 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 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 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