14a5d661aSToomas Soome /*- 24a5d661aSToomas Soome * Copyright (c) 1986, 1988, 1991, 1993 34a5d661aSToomas Soome * The Regents of the University of California. All rights reserved. 44a5d661aSToomas Soome * (c) UNIX System Laboratories, Inc. 54a5d661aSToomas Soome * All or some portions of this file are derived from material licensed 64a5d661aSToomas Soome * to the University of California by American Telephone and Telegraph 74a5d661aSToomas Soome * Co. or Unix System Laboratories, Inc. and are reproduced herein with 84a5d661aSToomas Soome * the permission of UNIX System Laboratories, Inc. 94a5d661aSToomas Soome * 104a5d661aSToomas Soome * Redistribution and use in source and binary forms, with or without 114a5d661aSToomas Soome * modification, are permitted provided that the following conditions 124a5d661aSToomas Soome * are met: 134a5d661aSToomas Soome * 1. Redistributions of source code must retain the above copyright 144a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer. 154a5d661aSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 164a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer in the 174a5d661aSToomas Soome * documentation and/or other materials provided with the distribution. 184a5d661aSToomas Soome * 4. Neither the name of the University nor the names of its contributors 194a5d661aSToomas Soome * may be used to endorse or promote products derived from this software 204a5d661aSToomas Soome * without specific prior written permission. 214a5d661aSToomas Soome * 224a5d661aSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 234a5d661aSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 244a5d661aSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 254a5d661aSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 264a5d661aSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 274a5d661aSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 284a5d661aSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 294a5d661aSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 304a5d661aSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 314a5d661aSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 324a5d661aSToomas Soome * SUCH DAMAGE. 334a5d661aSToomas Soome * 344a5d661aSToomas Soome * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 354a5d661aSToomas Soome */ 364a5d661aSToomas Soome 374a5d661aSToomas Soome #include <sys/cdefs.h> 384a5d661aSToomas Soome 394a5d661aSToomas Soome /* 404a5d661aSToomas Soome * Standaloneified version of the FreeBSD kernel printf family. 414a5d661aSToomas Soome */ 424a5d661aSToomas Soome 434a5d661aSToomas Soome #include <sys/types.h> 444a5d661aSToomas Soome #include <sys/stddef.h> 454a5d661aSToomas Soome #include <sys/stdint.h> 464a5d661aSToomas Soome #include <limits.h> 474a5d661aSToomas Soome #include <string.h> 484a5d661aSToomas Soome #include "stand.h" 494a5d661aSToomas Soome 504a5d661aSToomas Soome /* 514a5d661aSToomas Soome * Note that stdarg.h and the ANSI style va_start macro is used for both 524a5d661aSToomas Soome * ANSI and traditional C compilers. 534a5d661aSToomas Soome */ 544a5d661aSToomas Soome #include <machine/stdarg.h> 554a5d661aSToomas Soome 564a5d661aSToomas Soome #define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1) 574a5d661aSToomas Soome 584a5d661aSToomas Soome typedef void (kvprintf_fn_t)(int, void *); 594a5d661aSToomas Soome 604a5d661aSToomas Soome static char *ksprintn (char *buf, uintmax_t num, int base, int *len, int upper); 614a5d661aSToomas Soome static int kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap); 624a5d661aSToomas Soome 634a5d661aSToomas Soome static void 644a5d661aSToomas Soome putchar_wrapper(int cc, void *arg) 654a5d661aSToomas Soome { 664a5d661aSToomas Soome 674a5d661aSToomas Soome putchar(cc); 684a5d661aSToomas Soome } 694a5d661aSToomas Soome 704a5d661aSToomas Soome int 714a5d661aSToomas Soome printf(const char *fmt, ...) 724a5d661aSToomas Soome { 734a5d661aSToomas Soome va_list ap; 744a5d661aSToomas Soome int retval; 754a5d661aSToomas Soome 764a5d661aSToomas Soome va_start(ap, fmt); 774a5d661aSToomas Soome retval = kvprintf(fmt, putchar_wrapper, NULL, 10, ap); 784a5d661aSToomas Soome va_end(ap); 794a5d661aSToomas Soome return retval; 804a5d661aSToomas Soome } 814a5d661aSToomas Soome 824a5d661aSToomas Soome void 834a5d661aSToomas Soome vprintf(const char *fmt, va_list ap) 844a5d661aSToomas Soome { 854a5d661aSToomas Soome 864a5d661aSToomas Soome kvprintf(fmt, putchar_wrapper, NULL, 10, ap); 874a5d661aSToomas Soome } 884a5d661aSToomas Soome 894a5d661aSToomas Soome int 904a5d661aSToomas Soome sprintf(char *buf, const char *cfmt, ...) 914a5d661aSToomas Soome { 924a5d661aSToomas Soome int retval; 934a5d661aSToomas Soome va_list ap; 944a5d661aSToomas Soome 954a5d661aSToomas Soome va_start(ap, cfmt); 964a5d661aSToomas Soome retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 974a5d661aSToomas Soome buf[retval] = '\0'; 984a5d661aSToomas Soome va_end(ap); 994a5d661aSToomas Soome return retval; 1004a5d661aSToomas Soome } 1014a5d661aSToomas Soome 1024a5d661aSToomas Soome struct print_buf { 1034a5d661aSToomas Soome char *buf; 1044a5d661aSToomas Soome size_t size; 1054a5d661aSToomas Soome }; 1064a5d661aSToomas Soome 1074a5d661aSToomas Soome static void 1084a5d661aSToomas Soome snprint_func(int ch, void *arg) 1094a5d661aSToomas Soome { 1104a5d661aSToomas Soome struct print_buf *pbuf = arg; 1114a5d661aSToomas Soome 1124a5d661aSToomas Soome if (pbuf->size < 2) { 1134a5d661aSToomas Soome /* 1144a5d661aSToomas Soome * Reserve last buffer position for the terminating 1154a5d661aSToomas Soome * character: 1164a5d661aSToomas Soome */ 1174a5d661aSToomas Soome return; 1184a5d661aSToomas Soome } 1194a5d661aSToomas Soome *(pbuf->buf)++ = ch; 1204a5d661aSToomas Soome pbuf->size--; 1214a5d661aSToomas Soome } 1224a5d661aSToomas Soome 1234a5d661aSToomas Soome int 124*45ac0b4bSToomas Soome asprintf(char **buf, const char *cfmt, ...) 125*45ac0b4bSToomas Soome { 126*45ac0b4bSToomas Soome int retval; 127*45ac0b4bSToomas Soome struct print_buf arg; 128*45ac0b4bSToomas Soome va_list ap; 129*45ac0b4bSToomas Soome 130*45ac0b4bSToomas Soome *buf = NULL; 131*45ac0b4bSToomas Soome va_start(ap, cfmt); 132*45ac0b4bSToomas Soome retval = kvprintf(cfmt, NULL, NULL, 10, ap); 133*45ac0b4bSToomas Soome va_end(ap); 134*45ac0b4bSToomas Soome if (retval <= 0) 135*45ac0b4bSToomas Soome return (-1); 136*45ac0b4bSToomas Soome 137*45ac0b4bSToomas Soome arg.size = retval + 1; 138*45ac0b4bSToomas Soome arg.buf = *buf = malloc(arg.size); 139*45ac0b4bSToomas Soome if (*buf == NULL) 140*45ac0b4bSToomas Soome return (-1); 141*45ac0b4bSToomas Soome 142*45ac0b4bSToomas Soome va_start(ap, cfmt); 143*45ac0b4bSToomas Soome retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap); 144*45ac0b4bSToomas Soome va_end(ap); 145*45ac0b4bSToomas Soome 146*45ac0b4bSToomas Soome if (arg.size >= 1) 147*45ac0b4bSToomas Soome *(arg.buf)++ = 0; 148*45ac0b4bSToomas Soome return (retval); 149*45ac0b4bSToomas Soome } 150*45ac0b4bSToomas Soome 151*45ac0b4bSToomas Soome int 1524a5d661aSToomas Soome snprintf(char *buf, size_t size, const char *cfmt, ...) 1534a5d661aSToomas Soome { 1544a5d661aSToomas Soome int retval; 1554a5d661aSToomas Soome va_list ap; 1564a5d661aSToomas Soome struct print_buf arg; 1574a5d661aSToomas Soome 1584a5d661aSToomas Soome arg.buf = buf; 1594a5d661aSToomas Soome arg.size = size; 1604a5d661aSToomas Soome 1614a5d661aSToomas Soome va_start(ap, cfmt); 1624a5d661aSToomas Soome retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap); 1634a5d661aSToomas Soome va_end(ap); 1644a5d661aSToomas Soome 1654a5d661aSToomas Soome if (arg.size >= 1) 1664a5d661aSToomas Soome *(arg.buf)++ = 0; 1674a5d661aSToomas Soome return retval; 1684a5d661aSToomas Soome } 1694a5d661aSToomas Soome 1704a5d661aSToomas Soome void 1714a5d661aSToomas Soome vsprintf(char *buf, const char *cfmt, va_list ap) 1724a5d661aSToomas Soome { 1734a5d661aSToomas Soome int retval; 1744a5d661aSToomas Soome 1754a5d661aSToomas Soome retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 1764a5d661aSToomas Soome buf[retval] = '\0'; 1774a5d661aSToomas Soome } 1784a5d661aSToomas Soome 1794a5d661aSToomas Soome void 1804a5d661aSToomas Soome vsnprintf(char *buf, size_t size, const char *cfmt, va_list ap) 1814a5d661aSToomas Soome { 1824a5d661aSToomas Soome int retval; 1834a5d661aSToomas Soome struct print_buf arg; 1844a5d661aSToomas Soome 1854a5d661aSToomas Soome arg.buf = buf; 1864a5d661aSToomas Soome arg.size = size; 1874a5d661aSToomas Soome 1884a5d661aSToomas Soome retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap); 1894a5d661aSToomas Soome buf[retval] = '\0'; 1904a5d661aSToomas Soome } 1914a5d661aSToomas Soome 1924a5d661aSToomas Soome /* 1934a5d661aSToomas Soome * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 1944a5d661aSToomas Soome * order; return an optional length and a pointer to the last character 1954a5d661aSToomas Soome * written in the buffer (i.e., the first character of the string). 1964a5d661aSToomas Soome * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 1974a5d661aSToomas Soome */ 1984a5d661aSToomas Soome static char * 1994a5d661aSToomas Soome ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 2004a5d661aSToomas Soome { 2014a5d661aSToomas Soome char *p, c; 2024a5d661aSToomas Soome 2034a5d661aSToomas Soome p = nbuf; 2044a5d661aSToomas Soome *p = '\0'; 2054a5d661aSToomas Soome do { 2064a5d661aSToomas Soome c = hex2ascii(num % base); 2074a5d661aSToomas Soome *++p = upper ? toupper(c) : c; 2084a5d661aSToomas Soome } while (num /= base); 2094a5d661aSToomas Soome if (lenp) 2104a5d661aSToomas Soome *lenp = p - nbuf; 2114a5d661aSToomas Soome return (p); 2124a5d661aSToomas Soome } 2134a5d661aSToomas Soome 2144a5d661aSToomas Soome /* 2154a5d661aSToomas Soome * Scaled down version of printf(3). 2164a5d661aSToomas Soome * 2174a5d661aSToomas Soome * Two additional formats: 2184a5d661aSToomas Soome * 2194a5d661aSToomas Soome * The format %b is supported to decode error registers. 2204a5d661aSToomas Soome * Its usage is: 2214a5d661aSToomas Soome * 2224a5d661aSToomas Soome * printf("reg=%b\n", regval, "<base><arg>*"); 2234a5d661aSToomas Soome * 2244a5d661aSToomas Soome * where <base> is the output base expressed as a control character, e.g. 2254a5d661aSToomas Soome * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 2264a5d661aSToomas Soome * the first of which gives the bit number to be inspected (origin 1), and 2274a5d661aSToomas Soome * the next characters (up to a control character, i.e. a character <= 32), 2284a5d661aSToomas Soome * give the name of the register. Thus: 2294a5d661aSToomas Soome * 2304a5d661aSToomas Soome * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE"); 2314a5d661aSToomas Soome * 2324a5d661aSToomas Soome * would produce output: 2334a5d661aSToomas Soome * 2344a5d661aSToomas Soome * reg=3<BITTWO,BITONE> 2354a5d661aSToomas Soome * 2364a5d661aSToomas Soome * XXX: %D -- Hexdump, takes pointer and separator string: 2374a5d661aSToomas Soome * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 2384a5d661aSToomas Soome * ("%*D", len, ptr, " " -> XX XX XX XX ... 2394a5d661aSToomas Soome */ 2404a5d661aSToomas Soome static int 2414a5d661aSToomas Soome kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap) 2424a5d661aSToomas Soome { 243*45ac0b4bSToomas Soome #define PCHAR(c) { \ 244*45ac0b4bSToomas Soome int cc = (c); \ 245*45ac0b4bSToomas Soome \ 246*45ac0b4bSToomas Soome if (func) { \ 247*45ac0b4bSToomas Soome (*func)(cc, arg); \ 248*45ac0b4bSToomas Soome } else if (d != NULL) { \ 249*45ac0b4bSToomas Soome *d++ = cc; \ 250*45ac0b4bSToomas Soome } \ 251*45ac0b4bSToomas Soome retval++; \ 252*45ac0b4bSToomas Soome } 253*45ac0b4bSToomas Soome 2544a5d661aSToomas Soome char nbuf[MAXNBUF]; 2554a5d661aSToomas Soome char *d; 2564a5d661aSToomas Soome const char *p, *percent, *q; 257c5121490SToomas Soome uint16_t *S; 2584a5d661aSToomas Soome u_char *up; 2594a5d661aSToomas Soome int ch, n; 2604a5d661aSToomas Soome uintmax_t num; 2614a5d661aSToomas Soome int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 2624a5d661aSToomas Soome int cflag, hflag, jflag, tflag, zflag; 2634a5d661aSToomas Soome int dwidth, upper; 2644a5d661aSToomas Soome char padc; 2654a5d661aSToomas Soome int stop = 0, retval = 0; 2664a5d661aSToomas Soome 2674a5d661aSToomas Soome num = 0; 2684a5d661aSToomas Soome if (!func) 2694a5d661aSToomas Soome d = (char *) arg; 2704a5d661aSToomas Soome else 2714a5d661aSToomas Soome d = NULL; 2724a5d661aSToomas Soome 2734a5d661aSToomas Soome if (fmt == NULL) 2744a5d661aSToomas Soome fmt = "(fmt null)\n"; 2754a5d661aSToomas Soome 2764a5d661aSToomas Soome if (radix < 2 || radix > 36) 2774a5d661aSToomas Soome radix = 10; 2784a5d661aSToomas Soome 2794a5d661aSToomas Soome for (;;) { 2804a5d661aSToomas Soome padc = ' '; 2814a5d661aSToomas Soome width = 0; 2824a5d661aSToomas Soome while ((ch = (u_char)*fmt++) != '%' || stop) { 2834a5d661aSToomas Soome if (ch == '\0') 2844a5d661aSToomas Soome return (retval); 2854a5d661aSToomas Soome PCHAR(ch); 2864a5d661aSToomas Soome } 2874a5d661aSToomas Soome percent = fmt - 1; 2884a5d661aSToomas Soome qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 2894a5d661aSToomas Soome sign = 0; dot = 0; dwidth = 0; upper = 0; 2904a5d661aSToomas Soome cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 2914a5d661aSToomas Soome reswitch: switch (ch = (u_char)*fmt++) { 2924a5d661aSToomas Soome case '.': 2934a5d661aSToomas Soome dot = 1; 2944a5d661aSToomas Soome goto reswitch; 2954a5d661aSToomas Soome case '#': 2964a5d661aSToomas Soome sharpflag = 1; 2974a5d661aSToomas Soome goto reswitch; 2984a5d661aSToomas Soome case '+': 2994a5d661aSToomas Soome sign = 1; 3004a5d661aSToomas Soome goto reswitch; 3014a5d661aSToomas Soome case '-': 3024a5d661aSToomas Soome ladjust = 1; 3034a5d661aSToomas Soome goto reswitch; 3044a5d661aSToomas Soome case '%': 3054a5d661aSToomas Soome PCHAR(ch); 3064a5d661aSToomas Soome break; 3074a5d661aSToomas Soome case '*': 3084a5d661aSToomas Soome if (!dot) { 3094a5d661aSToomas Soome width = va_arg(ap, int); 3104a5d661aSToomas Soome if (width < 0) { 3114a5d661aSToomas Soome ladjust = !ladjust; 3124a5d661aSToomas Soome width = -width; 3134a5d661aSToomas Soome } 3144a5d661aSToomas Soome } else { 3154a5d661aSToomas Soome dwidth = va_arg(ap, int); 3164a5d661aSToomas Soome } 3174a5d661aSToomas Soome goto reswitch; 3184a5d661aSToomas Soome case '0': 3194a5d661aSToomas Soome if (!dot) { 3204a5d661aSToomas Soome padc = '0'; 3214a5d661aSToomas Soome goto reswitch; 3224a5d661aSToomas Soome } 3234a5d661aSToomas Soome case '1': case '2': case '3': case '4': 3244a5d661aSToomas Soome case '5': case '6': case '7': case '8': case '9': 3254a5d661aSToomas Soome for (n = 0;; ++fmt) { 3264a5d661aSToomas Soome n = n * 10 + ch - '0'; 3274a5d661aSToomas Soome ch = *fmt; 3284a5d661aSToomas Soome if (ch < '0' || ch > '9') 3294a5d661aSToomas Soome break; 3304a5d661aSToomas Soome } 3314a5d661aSToomas Soome if (dot) 3324a5d661aSToomas Soome dwidth = n; 3334a5d661aSToomas Soome else 3344a5d661aSToomas Soome width = n; 3354a5d661aSToomas Soome goto reswitch; 3364a5d661aSToomas Soome case 'b': 3374a5d661aSToomas Soome num = (u_int)va_arg(ap, int); 3384a5d661aSToomas Soome p = va_arg(ap, char *); 3394a5d661aSToomas Soome for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 3404a5d661aSToomas Soome PCHAR(*q--); 3414a5d661aSToomas Soome 3424a5d661aSToomas Soome if (num == 0) 3434a5d661aSToomas Soome break; 3444a5d661aSToomas Soome 3454a5d661aSToomas Soome for (tmp = 0; *p;) { 3464a5d661aSToomas Soome n = *p++; 3474a5d661aSToomas Soome if (num & (1 << (n - 1))) { 3484a5d661aSToomas Soome PCHAR(tmp ? ',' : '<'); 3494a5d661aSToomas Soome for (; (n = *p) > ' '; ++p) 3504a5d661aSToomas Soome PCHAR(n); 3514a5d661aSToomas Soome tmp = 1; 3524a5d661aSToomas Soome } else 3534a5d661aSToomas Soome for (; *p > ' '; ++p) 3544a5d661aSToomas Soome continue; 3554a5d661aSToomas Soome } 3564a5d661aSToomas Soome if (tmp) 3574a5d661aSToomas Soome PCHAR('>'); 3584a5d661aSToomas Soome break; 3594a5d661aSToomas Soome case 'c': 3604a5d661aSToomas Soome PCHAR(va_arg(ap, int)); 3614a5d661aSToomas Soome break; 3624a5d661aSToomas Soome case 'D': 3634a5d661aSToomas Soome up = va_arg(ap, u_char *); 3644a5d661aSToomas Soome p = va_arg(ap, char *); 3654a5d661aSToomas Soome if (!width) 3664a5d661aSToomas Soome width = 16; 3674a5d661aSToomas Soome while(width--) { 3684a5d661aSToomas Soome PCHAR(hex2ascii(*up >> 4)); 3694a5d661aSToomas Soome PCHAR(hex2ascii(*up & 0x0f)); 3704a5d661aSToomas Soome up++; 3714a5d661aSToomas Soome if (width) 3724a5d661aSToomas Soome for (q=p;*q;q++) 3734a5d661aSToomas Soome PCHAR(*q); 3744a5d661aSToomas Soome } 3754a5d661aSToomas Soome break; 3764a5d661aSToomas Soome case 'd': 3774a5d661aSToomas Soome case 'i': 3784a5d661aSToomas Soome base = 10; 3794a5d661aSToomas Soome sign = 1; 3804a5d661aSToomas Soome goto handle_sign; 3814a5d661aSToomas Soome case 'h': 3824a5d661aSToomas Soome if (hflag) { 3834a5d661aSToomas Soome hflag = 0; 3844a5d661aSToomas Soome cflag = 1; 3854a5d661aSToomas Soome } else 3864a5d661aSToomas Soome hflag = 1; 3874a5d661aSToomas Soome goto reswitch; 3884a5d661aSToomas Soome case 'j': 3894a5d661aSToomas Soome jflag = 1; 3904a5d661aSToomas Soome goto reswitch; 3914a5d661aSToomas Soome case 'l': 3924a5d661aSToomas Soome if (lflag) { 3934a5d661aSToomas Soome lflag = 0; 3944a5d661aSToomas Soome qflag = 1; 3954a5d661aSToomas Soome } else 3964a5d661aSToomas Soome lflag = 1; 3974a5d661aSToomas Soome goto reswitch; 3984a5d661aSToomas Soome case 'n': 3994a5d661aSToomas Soome if (jflag) 4004a5d661aSToomas Soome *(va_arg(ap, intmax_t *)) = retval; 4014a5d661aSToomas Soome else if (qflag) 4024a5d661aSToomas Soome *(va_arg(ap, quad_t *)) = retval; 4034a5d661aSToomas Soome else if (lflag) 4044a5d661aSToomas Soome *(va_arg(ap, long *)) = retval; 4054a5d661aSToomas Soome else if (zflag) 4064a5d661aSToomas Soome *(va_arg(ap, size_t *)) = retval; 4074a5d661aSToomas Soome else if (hflag) 4084a5d661aSToomas Soome *(va_arg(ap, short *)) = retval; 4094a5d661aSToomas Soome else if (cflag) 4104a5d661aSToomas Soome *(va_arg(ap, char *)) = retval; 4114a5d661aSToomas Soome else 4124a5d661aSToomas Soome *(va_arg(ap, int *)) = retval; 4134a5d661aSToomas Soome break; 4144a5d661aSToomas Soome case 'o': 4154a5d661aSToomas Soome base = 8; 4164a5d661aSToomas Soome goto handle_nosign; 4174a5d661aSToomas Soome case 'p': 4184a5d661aSToomas Soome base = 16; 4194a5d661aSToomas Soome sharpflag = (width == 0); 4204a5d661aSToomas Soome sign = 0; 4214a5d661aSToomas Soome num = (uintptr_t)va_arg(ap, void *); 4224a5d661aSToomas Soome goto number; 4234a5d661aSToomas Soome case 'q': 4244a5d661aSToomas Soome qflag = 1; 4254a5d661aSToomas Soome goto reswitch; 4264a5d661aSToomas Soome case 'r': 4274a5d661aSToomas Soome base = radix; 4284a5d661aSToomas Soome if (sign) 4294a5d661aSToomas Soome goto handle_sign; 4304a5d661aSToomas Soome goto handle_nosign; 4314a5d661aSToomas Soome case 's': 4324a5d661aSToomas Soome p = va_arg(ap, char *); 4334a5d661aSToomas Soome if (p == NULL) 4344a5d661aSToomas Soome p = "(null)"; 4354a5d661aSToomas Soome if (!dot) 4364a5d661aSToomas Soome n = strlen (p); 4374a5d661aSToomas Soome else 4384a5d661aSToomas Soome for (n = 0; n < dwidth && p[n]; n++) 4394a5d661aSToomas Soome continue; 4404a5d661aSToomas Soome 4414a5d661aSToomas Soome width -= n; 4424a5d661aSToomas Soome 4434a5d661aSToomas Soome if (!ladjust && width > 0) 4444a5d661aSToomas Soome while (width--) 4454a5d661aSToomas Soome PCHAR(padc); 4464a5d661aSToomas Soome while (n--) 4474a5d661aSToomas Soome PCHAR(*p++); 4484a5d661aSToomas Soome if (ladjust && width > 0) 4494a5d661aSToomas Soome while (width--) 4504a5d661aSToomas Soome PCHAR(padc); 4514a5d661aSToomas Soome break; 452c5121490SToomas Soome case 'S': /* Assume console can cope with wide chars */ 453c5121490SToomas Soome S = va_arg(ap, uint16_t *); 454c5121490SToomas Soome if (S == NULL) 455c5121490SToomas Soome S = (uint16_t *)L"(null)"; 456c5121490SToomas Soome if (!dot) { 457c5121490SToomas Soome for (n = 0; S[n] != 0; n++) 458c5121490SToomas Soome continue; 459c5121490SToomas Soome } else { 460c5121490SToomas Soome for (n = 0; n < dwidth && S[n]; n++) 461c5121490SToomas Soome continue; 462c5121490SToomas Soome } 463c5121490SToomas Soome 464c5121490SToomas Soome width -= n; 465c5121490SToomas Soome 466c5121490SToomas Soome if (!ladjust && width > 0) 467c5121490SToomas Soome while (width--) 468c5121490SToomas Soome PCHAR(padc); 469c5121490SToomas Soome while (n--) 470c5121490SToomas Soome PCHAR(*S++); 471c5121490SToomas Soome if (ladjust && width > 0) 472c5121490SToomas Soome while (width--) 473c5121490SToomas Soome PCHAR(padc); 474c5121490SToomas Soome break; 4754a5d661aSToomas Soome case 't': 4764a5d661aSToomas Soome tflag = 1; 4774a5d661aSToomas Soome goto reswitch; 4784a5d661aSToomas Soome case 'u': 4794a5d661aSToomas Soome base = 10; 4804a5d661aSToomas Soome goto handle_nosign; 4814a5d661aSToomas Soome case 'X': 4824a5d661aSToomas Soome upper = 1; 4834a5d661aSToomas Soome case 'x': 4844a5d661aSToomas Soome base = 16; 4854a5d661aSToomas Soome goto handle_nosign; 4864a5d661aSToomas Soome case 'y': 4874a5d661aSToomas Soome base = 16; 4884a5d661aSToomas Soome sign = 1; 4894a5d661aSToomas Soome goto handle_sign; 4904a5d661aSToomas Soome case 'z': 4914a5d661aSToomas Soome zflag = 1; 4924a5d661aSToomas Soome goto reswitch; 4934a5d661aSToomas Soome handle_nosign: 4944a5d661aSToomas Soome sign = 0; 4954a5d661aSToomas Soome if (jflag) 4964a5d661aSToomas Soome num = va_arg(ap, uintmax_t); 4974a5d661aSToomas Soome else if (qflag) 4984a5d661aSToomas Soome num = va_arg(ap, u_quad_t); 4994a5d661aSToomas Soome else if (tflag) 5004a5d661aSToomas Soome num = va_arg(ap, ptrdiff_t); 5014a5d661aSToomas Soome else if (lflag) 5024a5d661aSToomas Soome num = va_arg(ap, u_long); 5034a5d661aSToomas Soome else if (zflag) 5044a5d661aSToomas Soome num = va_arg(ap, size_t); 5054a5d661aSToomas Soome else if (hflag) 5064a5d661aSToomas Soome num = (u_short)va_arg(ap, int); 5074a5d661aSToomas Soome else if (cflag) 5084a5d661aSToomas Soome num = (u_char)va_arg(ap, int); 5094a5d661aSToomas Soome else 5104a5d661aSToomas Soome num = va_arg(ap, u_int); 5114a5d661aSToomas Soome goto number; 5124a5d661aSToomas Soome handle_sign: 5134a5d661aSToomas Soome if (jflag) 5144a5d661aSToomas Soome num = va_arg(ap, intmax_t); 5154a5d661aSToomas Soome else if (qflag) 5164a5d661aSToomas Soome num = va_arg(ap, quad_t); 5174a5d661aSToomas Soome else if (tflag) 5184a5d661aSToomas Soome num = va_arg(ap, ptrdiff_t); 5194a5d661aSToomas Soome else if (lflag) 5204a5d661aSToomas Soome num = va_arg(ap, long); 5214a5d661aSToomas Soome else if (zflag) 5224a5d661aSToomas Soome num = va_arg(ap, ssize_t); 5234a5d661aSToomas Soome else if (hflag) 5244a5d661aSToomas Soome num = (short)va_arg(ap, int); 5254a5d661aSToomas Soome else if (cflag) 5264a5d661aSToomas Soome num = (char)va_arg(ap, int); 5274a5d661aSToomas Soome else 5284a5d661aSToomas Soome num = va_arg(ap, int); 5294a5d661aSToomas Soome number: 5304a5d661aSToomas Soome if (sign && (intmax_t)num < 0) { 5314a5d661aSToomas Soome neg = 1; 5324a5d661aSToomas Soome num = -(intmax_t)num; 5334a5d661aSToomas Soome } 5344a5d661aSToomas Soome p = ksprintn(nbuf, num, base, &n, upper); 5354a5d661aSToomas Soome tmp = 0; 5364a5d661aSToomas Soome if (sharpflag && num != 0) { 5374a5d661aSToomas Soome if (base == 8) 5384a5d661aSToomas Soome tmp++; 5394a5d661aSToomas Soome else if (base == 16) 5404a5d661aSToomas Soome tmp += 2; 5414a5d661aSToomas Soome } 5424a5d661aSToomas Soome if (neg) 5434a5d661aSToomas Soome tmp++; 5444a5d661aSToomas Soome 5454a5d661aSToomas Soome if (!ladjust && padc == '0') 5464a5d661aSToomas Soome dwidth = width - tmp; 5474a5d661aSToomas Soome width -= tmp + imax(dwidth, n); 5484a5d661aSToomas Soome dwidth -= n; 5494a5d661aSToomas Soome if (!ladjust) 5504a5d661aSToomas Soome while (width-- > 0) 5514a5d661aSToomas Soome PCHAR(' '); 5524a5d661aSToomas Soome if (neg) 5534a5d661aSToomas Soome PCHAR('-'); 5544a5d661aSToomas Soome if (sharpflag && num != 0) { 5554a5d661aSToomas Soome if (base == 8) { 5564a5d661aSToomas Soome PCHAR('0'); 5574a5d661aSToomas Soome } else if (base == 16) { 5584a5d661aSToomas Soome PCHAR('0'); 5594a5d661aSToomas Soome PCHAR('x'); 5604a5d661aSToomas Soome } 5614a5d661aSToomas Soome } 5624a5d661aSToomas Soome while (dwidth-- > 0) 5634a5d661aSToomas Soome PCHAR('0'); 5644a5d661aSToomas Soome 5654a5d661aSToomas Soome while (*p) 5664a5d661aSToomas Soome PCHAR(*p--); 5674a5d661aSToomas Soome 5684a5d661aSToomas Soome if (ladjust) 5694a5d661aSToomas Soome while (width-- > 0) 5704a5d661aSToomas Soome PCHAR(' '); 5714a5d661aSToomas Soome 5724a5d661aSToomas Soome break; 5734a5d661aSToomas Soome default: 5744a5d661aSToomas Soome while (percent < fmt) 5754a5d661aSToomas Soome PCHAR(*percent++); 5764a5d661aSToomas Soome /* 5774a5d661aSToomas Soome * Since we ignore a formatting argument it is no 5784a5d661aSToomas Soome * longer safe to obey the remaining formatting 5794a5d661aSToomas Soome * arguments as the arguments will no longer match 5804a5d661aSToomas Soome * the format specs. 5814a5d661aSToomas Soome */ 5824a5d661aSToomas Soome stop = 1; 5834a5d661aSToomas Soome break; 5844a5d661aSToomas Soome } 5854a5d661aSToomas Soome } 5864a5d661aSToomas Soome #undef PCHAR 5874a5d661aSToomas Soome } 588