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 __FBSDID("$FreeBSD$"); 394a5d661aSToomas Soome 404a5d661aSToomas Soome /* 414a5d661aSToomas Soome * Standaloneified version of the FreeBSD kernel printf family. 424a5d661aSToomas Soome */ 434a5d661aSToomas Soome 444a5d661aSToomas Soome #include <sys/types.h> 454a5d661aSToomas Soome #include <sys/stddef.h> 464a5d661aSToomas Soome #include <sys/stdint.h> 474a5d661aSToomas Soome #include <limits.h> 484a5d661aSToomas Soome #include <string.h> 494a5d661aSToomas Soome #include "stand.h" 504a5d661aSToomas Soome 514a5d661aSToomas Soome /* 524a5d661aSToomas Soome * Note that stdarg.h and the ANSI style va_start macro is used for both 534a5d661aSToomas Soome * ANSI and traditional C compilers. 544a5d661aSToomas Soome */ 554a5d661aSToomas Soome #include <machine/stdarg.h> 564a5d661aSToomas Soome 574a5d661aSToomas Soome #define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1) 584a5d661aSToomas Soome 594a5d661aSToomas Soome typedef void (kvprintf_fn_t)(int, void *); 604a5d661aSToomas Soome 614a5d661aSToomas Soome static char *ksprintn (char *buf, uintmax_t num, int base, int *len, int upper); 624a5d661aSToomas Soome static int kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap); 634a5d661aSToomas Soome 644a5d661aSToomas Soome static void 654a5d661aSToomas Soome putchar_wrapper(int cc, void *arg) 664a5d661aSToomas Soome { 674a5d661aSToomas Soome 684a5d661aSToomas Soome putchar(cc); 694a5d661aSToomas Soome } 704a5d661aSToomas Soome 714a5d661aSToomas Soome int 724a5d661aSToomas Soome printf(const char *fmt, ...) 734a5d661aSToomas Soome { 744a5d661aSToomas Soome va_list ap; 754a5d661aSToomas Soome int retval; 764a5d661aSToomas Soome 774a5d661aSToomas Soome va_start(ap, fmt); 784a5d661aSToomas Soome retval = kvprintf(fmt, putchar_wrapper, NULL, 10, ap); 794a5d661aSToomas Soome va_end(ap); 804a5d661aSToomas Soome return retval; 814a5d661aSToomas Soome } 824a5d661aSToomas Soome 834a5d661aSToomas Soome void 844a5d661aSToomas Soome vprintf(const char *fmt, va_list ap) 854a5d661aSToomas Soome { 864a5d661aSToomas Soome 874a5d661aSToomas Soome kvprintf(fmt, putchar_wrapper, NULL, 10, ap); 884a5d661aSToomas Soome } 894a5d661aSToomas Soome 904a5d661aSToomas Soome int 914a5d661aSToomas Soome sprintf(char *buf, const char *cfmt, ...) 924a5d661aSToomas Soome { 934a5d661aSToomas Soome int retval; 944a5d661aSToomas Soome va_list ap; 954a5d661aSToomas Soome 964a5d661aSToomas Soome va_start(ap, cfmt); 974a5d661aSToomas Soome retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 984a5d661aSToomas Soome buf[retval] = '\0'; 994a5d661aSToomas Soome va_end(ap); 1004a5d661aSToomas Soome return retval; 1014a5d661aSToomas Soome } 1024a5d661aSToomas Soome 1034a5d661aSToomas Soome struct print_buf { 1044a5d661aSToomas Soome char *buf; 1054a5d661aSToomas Soome size_t size; 1064a5d661aSToomas Soome }; 1074a5d661aSToomas Soome 1084a5d661aSToomas Soome static void 1094a5d661aSToomas Soome snprint_func(int ch, void *arg) 1104a5d661aSToomas Soome { 1114a5d661aSToomas Soome struct print_buf *pbuf = arg; 1124a5d661aSToomas Soome 1134a5d661aSToomas Soome if (pbuf->size < 2) { 1144a5d661aSToomas Soome /* 1154a5d661aSToomas Soome * Reserve last buffer position for the terminating 1164a5d661aSToomas Soome * character: 1174a5d661aSToomas Soome */ 1184a5d661aSToomas Soome return; 1194a5d661aSToomas Soome } 1204a5d661aSToomas Soome *(pbuf->buf)++ = ch; 1214a5d661aSToomas Soome pbuf->size--; 1224a5d661aSToomas Soome } 1234a5d661aSToomas Soome 1244a5d661aSToomas Soome int 1254a5d661aSToomas Soome snprintf(char *buf, size_t size, const char *cfmt, ...) 1264a5d661aSToomas Soome { 1274a5d661aSToomas Soome int retval; 1284a5d661aSToomas Soome va_list ap; 1294a5d661aSToomas Soome struct print_buf arg; 1304a5d661aSToomas Soome 1314a5d661aSToomas Soome arg.buf = buf; 1324a5d661aSToomas Soome arg.size = size; 1334a5d661aSToomas Soome 1344a5d661aSToomas Soome va_start(ap, cfmt); 1354a5d661aSToomas Soome retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap); 1364a5d661aSToomas Soome va_end(ap); 1374a5d661aSToomas Soome 1384a5d661aSToomas Soome if (arg.size >= 1) 1394a5d661aSToomas Soome *(arg.buf)++ = 0; 1404a5d661aSToomas Soome return retval; 1414a5d661aSToomas Soome } 1424a5d661aSToomas Soome 1434a5d661aSToomas Soome void 1444a5d661aSToomas Soome vsprintf(char *buf, const char *cfmt, va_list ap) 1454a5d661aSToomas Soome { 1464a5d661aSToomas Soome int retval; 1474a5d661aSToomas Soome 1484a5d661aSToomas Soome retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 1494a5d661aSToomas Soome buf[retval] = '\0'; 1504a5d661aSToomas Soome } 1514a5d661aSToomas Soome 1524a5d661aSToomas Soome void 1534a5d661aSToomas Soome vsnprintf(char *buf, size_t size, const char *cfmt, va_list ap) 1544a5d661aSToomas Soome { 1554a5d661aSToomas Soome int retval; 1564a5d661aSToomas Soome struct print_buf arg; 1574a5d661aSToomas Soome 1584a5d661aSToomas Soome arg.buf = buf; 1594a5d661aSToomas Soome arg.size = size; 1604a5d661aSToomas Soome 1614a5d661aSToomas Soome retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap); 1624a5d661aSToomas Soome buf[retval] = '\0'; 1634a5d661aSToomas Soome } 1644a5d661aSToomas Soome 1654a5d661aSToomas Soome /* 1664a5d661aSToomas Soome * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 1674a5d661aSToomas Soome * order; return an optional length and a pointer to the last character 1684a5d661aSToomas Soome * written in the buffer (i.e., the first character of the string). 1694a5d661aSToomas Soome * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 1704a5d661aSToomas Soome */ 1714a5d661aSToomas Soome static char * 1724a5d661aSToomas Soome ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 1734a5d661aSToomas Soome { 1744a5d661aSToomas Soome char *p, c; 1754a5d661aSToomas Soome 1764a5d661aSToomas Soome p = nbuf; 1774a5d661aSToomas Soome *p = '\0'; 1784a5d661aSToomas Soome do { 1794a5d661aSToomas Soome c = hex2ascii(num % base); 1804a5d661aSToomas Soome *++p = upper ? toupper(c) : c; 1814a5d661aSToomas Soome } while (num /= base); 1824a5d661aSToomas Soome if (lenp) 1834a5d661aSToomas Soome *lenp = p - nbuf; 1844a5d661aSToomas Soome return (p); 1854a5d661aSToomas Soome } 1864a5d661aSToomas Soome 1874a5d661aSToomas Soome /* 1884a5d661aSToomas Soome * Scaled down version of printf(3). 1894a5d661aSToomas Soome * 1904a5d661aSToomas Soome * Two additional formats: 1914a5d661aSToomas Soome * 1924a5d661aSToomas Soome * The format %b is supported to decode error registers. 1934a5d661aSToomas Soome * Its usage is: 1944a5d661aSToomas Soome * 1954a5d661aSToomas Soome * printf("reg=%b\n", regval, "<base><arg>*"); 1964a5d661aSToomas Soome * 1974a5d661aSToomas Soome * where <base> is the output base expressed as a control character, e.g. 1984a5d661aSToomas Soome * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 1994a5d661aSToomas Soome * the first of which gives the bit number to be inspected (origin 1), and 2004a5d661aSToomas Soome * the next characters (up to a control character, i.e. a character <= 32), 2014a5d661aSToomas Soome * give the name of the register. Thus: 2024a5d661aSToomas Soome * 2034a5d661aSToomas Soome * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE"); 2044a5d661aSToomas Soome * 2054a5d661aSToomas Soome * would produce output: 2064a5d661aSToomas Soome * 2074a5d661aSToomas Soome * reg=3<BITTWO,BITONE> 2084a5d661aSToomas Soome * 2094a5d661aSToomas Soome * XXX: %D -- Hexdump, takes pointer and separator string: 2104a5d661aSToomas Soome * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 2114a5d661aSToomas Soome * ("%*D", len, ptr, " " -> XX XX XX XX ... 2124a5d661aSToomas Soome */ 2134a5d661aSToomas Soome static int 2144a5d661aSToomas Soome kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap) 2154a5d661aSToomas Soome { 2164a5d661aSToomas Soome #define PCHAR(c) {int cc=(c); if (func) (*func)(cc, arg); else *d++ = cc; retval++; } 2174a5d661aSToomas Soome char nbuf[MAXNBUF]; 2184a5d661aSToomas Soome char *d; 2194a5d661aSToomas Soome const char *p, *percent, *q; 220*c5121490SToomas Soome uint16_t *S; 2214a5d661aSToomas Soome u_char *up; 2224a5d661aSToomas Soome int ch, n; 2234a5d661aSToomas Soome uintmax_t num; 2244a5d661aSToomas Soome int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 2254a5d661aSToomas Soome int cflag, hflag, jflag, tflag, zflag; 2264a5d661aSToomas Soome int dwidth, upper; 2274a5d661aSToomas Soome char padc; 2284a5d661aSToomas Soome int stop = 0, retval = 0; 2294a5d661aSToomas Soome 2304a5d661aSToomas Soome num = 0; 2314a5d661aSToomas Soome if (!func) 2324a5d661aSToomas Soome d = (char *) arg; 2334a5d661aSToomas Soome else 2344a5d661aSToomas Soome d = NULL; 2354a5d661aSToomas Soome 2364a5d661aSToomas Soome if (fmt == NULL) 2374a5d661aSToomas Soome fmt = "(fmt null)\n"; 2384a5d661aSToomas Soome 2394a5d661aSToomas Soome if (radix < 2 || radix > 36) 2404a5d661aSToomas Soome radix = 10; 2414a5d661aSToomas Soome 2424a5d661aSToomas Soome for (;;) { 2434a5d661aSToomas Soome padc = ' '; 2444a5d661aSToomas Soome width = 0; 2454a5d661aSToomas Soome while ((ch = (u_char)*fmt++) != '%' || stop) { 2464a5d661aSToomas Soome if (ch == '\0') 2474a5d661aSToomas Soome return (retval); 2484a5d661aSToomas Soome PCHAR(ch); 2494a5d661aSToomas Soome } 2504a5d661aSToomas Soome percent = fmt - 1; 2514a5d661aSToomas Soome qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 2524a5d661aSToomas Soome sign = 0; dot = 0; dwidth = 0; upper = 0; 2534a5d661aSToomas Soome cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 2544a5d661aSToomas Soome reswitch: switch (ch = (u_char)*fmt++) { 2554a5d661aSToomas Soome case '.': 2564a5d661aSToomas Soome dot = 1; 2574a5d661aSToomas Soome goto reswitch; 2584a5d661aSToomas Soome case '#': 2594a5d661aSToomas Soome sharpflag = 1; 2604a5d661aSToomas Soome goto reswitch; 2614a5d661aSToomas Soome case '+': 2624a5d661aSToomas Soome sign = 1; 2634a5d661aSToomas Soome goto reswitch; 2644a5d661aSToomas Soome case '-': 2654a5d661aSToomas Soome ladjust = 1; 2664a5d661aSToomas Soome goto reswitch; 2674a5d661aSToomas Soome case '%': 2684a5d661aSToomas Soome PCHAR(ch); 2694a5d661aSToomas Soome break; 2704a5d661aSToomas Soome case '*': 2714a5d661aSToomas Soome if (!dot) { 2724a5d661aSToomas Soome width = va_arg(ap, int); 2734a5d661aSToomas Soome if (width < 0) { 2744a5d661aSToomas Soome ladjust = !ladjust; 2754a5d661aSToomas Soome width = -width; 2764a5d661aSToomas Soome } 2774a5d661aSToomas Soome } else { 2784a5d661aSToomas Soome dwidth = va_arg(ap, int); 2794a5d661aSToomas Soome } 2804a5d661aSToomas Soome goto reswitch; 2814a5d661aSToomas Soome case '0': 2824a5d661aSToomas Soome if (!dot) { 2834a5d661aSToomas Soome padc = '0'; 2844a5d661aSToomas Soome goto reswitch; 2854a5d661aSToomas Soome } 2864a5d661aSToomas Soome case '1': case '2': case '3': case '4': 2874a5d661aSToomas Soome case '5': case '6': case '7': case '8': case '9': 2884a5d661aSToomas Soome for (n = 0;; ++fmt) { 2894a5d661aSToomas Soome n = n * 10 + ch - '0'; 2904a5d661aSToomas Soome ch = *fmt; 2914a5d661aSToomas Soome if (ch < '0' || ch > '9') 2924a5d661aSToomas Soome break; 2934a5d661aSToomas Soome } 2944a5d661aSToomas Soome if (dot) 2954a5d661aSToomas Soome dwidth = n; 2964a5d661aSToomas Soome else 2974a5d661aSToomas Soome width = n; 2984a5d661aSToomas Soome goto reswitch; 2994a5d661aSToomas Soome case 'b': 3004a5d661aSToomas Soome num = (u_int)va_arg(ap, int); 3014a5d661aSToomas Soome p = va_arg(ap, char *); 3024a5d661aSToomas Soome for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 3034a5d661aSToomas Soome PCHAR(*q--); 3044a5d661aSToomas Soome 3054a5d661aSToomas Soome if (num == 0) 3064a5d661aSToomas Soome break; 3074a5d661aSToomas Soome 3084a5d661aSToomas Soome for (tmp = 0; *p;) { 3094a5d661aSToomas Soome n = *p++; 3104a5d661aSToomas Soome if (num & (1 << (n - 1))) { 3114a5d661aSToomas Soome PCHAR(tmp ? ',' : '<'); 3124a5d661aSToomas Soome for (; (n = *p) > ' '; ++p) 3134a5d661aSToomas Soome PCHAR(n); 3144a5d661aSToomas Soome tmp = 1; 3154a5d661aSToomas Soome } else 3164a5d661aSToomas Soome for (; *p > ' '; ++p) 3174a5d661aSToomas Soome continue; 3184a5d661aSToomas Soome } 3194a5d661aSToomas Soome if (tmp) 3204a5d661aSToomas Soome PCHAR('>'); 3214a5d661aSToomas Soome break; 3224a5d661aSToomas Soome case 'c': 3234a5d661aSToomas Soome PCHAR(va_arg(ap, int)); 3244a5d661aSToomas Soome break; 3254a5d661aSToomas Soome case 'D': 3264a5d661aSToomas Soome up = va_arg(ap, u_char *); 3274a5d661aSToomas Soome p = va_arg(ap, char *); 3284a5d661aSToomas Soome if (!width) 3294a5d661aSToomas Soome width = 16; 3304a5d661aSToomas Soome while(width--) { 3314a5d661aSToomas Soome PCHAR(hex2ascii(*up >> 4)); 3324a5d661aSToomas Soome PCHAR(hex2ascii(*up & 0x0f)); 3334a5d661aSToomas Soome up++; 3344a5d661aSToomas Soome if (width) 3354a5d661aSToomas Soome for (q=p;*q;q++) 3364a5d661aSToomas Soome PCHAR(*q); 3374a5d661aSToomas Soome } 3384a5d661aSToomas Soome break; 3394a5d661aSToomas Soome case 'd': 3404a5d661aSToomas Soome case 'i': 3414a5d661aSToomas Soome base = 10; 3424a5d661aSToomas Soome sign = 1; 3434a5d661aSToomas Soome goto handle_sign; 3444a5d661aSToomas Soome case 'h': 3454a5d661aSToomas Soome if (hflag) { 3464a5d661aSToomas Soome hflag = 0; 3474a5d661aSToomas Soome cflag = 1; 3484a5d661aSToomas Soome } else 3494a5d661aSToomas Soome hflag = 1; 3504a5d661aSToomas Soome goto reswitch; 3514a5d661aSToomas Soome case 'j': 3524a5d661aSToomas Soome jflag = 1; 3534a5d661aSToomas Soome goto reswitch; 3544a5d661aSToomas Soome case 'l': 3554a5d661aSToomas Soome if (lflag) { 3564a5d661aSToomas Soome lflag = 0; 3574a5d661aSToomas Soome qflag = 1; 3584a5d661aSToomas Soome } else 3594a5d661aSToomas Soome lflag = 1; 3604a5d661aSToomas Soome goto reswitch; 3614a5d661aSToomas Soome case 'n': 3624a5d661aSToomas Soome if (jflag) 3634a5d661aSToomas Soome *(va_arg(ap, intmax_t *)) = retval; 3644a5d661aSToomas Soome else if (qflag) 3654a5d661aSToomas Soome *(va_arg(ap, quad_t *)) = retval; 3664a5d661aSToomas Soome else if (lflag) 3674a5d661aSToomas Soome *(va_arg(ap, long *)) = retval; 3684a5d661aSToomas Soome else if (zflag) 3694a5d661aSToomas Soome *(va_arg(ap, size_t *)) = retval; 3704a5d661aSToomas Soome else if (hflag) 3714a5d661aSToomas Soome *(va_arg(ap, short *)) = retval; 3724a5d661aSToomas Soome else if (cflag) 3734a5d661aSToomas Soome *(va_arg(ap, char *)) = retval; 3744a5d661aSToomas Soome else 3754a5d661aSToomas Soome *(va_arg(ap, int *)) = retval; 3764a5d661aSToomas Soome break; 3774a5d661aSToomas Soome case 'o': 3784a5d661aSToomas Soome base = 8; 3794a5d661aSToomas Soome goto handle_nosign; 3804a5d661aSToomas Soome case 'p': 3814a5d661aSToomas Soome base = 16; 3824a5d661aSToomas Soome sharpflag = (width == 0); 3834a5d661aSToomas Soome sign = 0; 3844a5d661aSToomas Soome num = (uintptr_t)va_arg(ap, void *); 3854a5d661aSToomas Soome goto number; 3864a5d661aSToomas Soome case 'q': 3874a5d661aSToomas Soome qflag = 1; 3884a5d661aSToomas Soome goto reswitch; 3894a5d661aSToomas Soome case 'r': 3904a5d661aSToomas Soome base = radix; 3914a5d661aSToomas Soome if (sign) 3924a5d661aSToomas Soome goto handle_sign; 3934a5d661aSToomas Soome goto handle_nosign; 3944a5d661aSToomas Soome case 's': 3954a5d661aSToomas Soome p = va_arg(ap, char *); 3964a5d661aSToomas Soome if (p == NULL) 3974a5d661aSToomas Soome p = "(null)"; 3984a5d661aSToomas Soome if (!dot) 3994a5d661aSToomas Soome n = strlen (p); 4004a5d661aSToomas Soome else 4014a5d661aSToomas Soome for (n = 0; n < dwidth && p[n]; n++) 4024a5d661aSToomas Soome continue; 4034a5d661aSToomas Soome 4044a5d661aSToomas Soome width -= n; 4054a5d661aSToomas Soome 4064a5d661aSToomas Soome if (!ladjust && width > 0) 4074a5d661aSToomas Soome while (width--) 4084a5d661aSToomas Soome PCHAR(padc); 4094a5d661aSToomas Soome while (n--) 4104a5d661aSToomas Soome PCHAR(*p++); 4114a5d661aSToomas Soome if (ladjust && width > 0) 4124a5d661aSToomas Soome while (width--) 4134a5d661aSToomas Soome PCHAR(padc); 4144a5d661aSToomas Soome break; 415*c5121490SToomas Soome case 'S': /* Assume console can cope with wide chars */ 416*c5121490SToomas Soome S = va_arg(ap, uint16_t *); 417*c5121490SToomas Soome if (S == NULL) 418*c5121490SToomas Soome S = (uint16_t *)L"(null)"; 419*c5121490SToomas Soome if (!dot) { 420*c5121490SToomas Soome for (n = 0; S[n] != 0; n++) 421*c5121490SToomas Soome continue; 422*c5121490SToomas Soome } else { 423*c5121490SToomas Soome for (n = 0; n < dwidth && S[n]; n++) 424*c5121490SToomas Soome continue; 425*c5121490SToomas Soome } 426*c5121490SToomas Soome 427*c5121490SToomas Soome width -= n; 428*c5121490SToomas Soome 429*c5121490SToomas Soome if (!ladjust && width > 0) 430*c5121490SToomas Soome while (width--) 431*c5121490SToomas Soome PCHAR(padc); 432*c5121490SToomas Soome while (n--) 433*c5121490SToomas Soome PCHAR(*S++); 434*c5121490SToomas Soome if (ladjust && width > 0) 435*c5121490SToomas Soome while (width--) 436*c5121490SToomas Soome PCHAR(padc); 437*c5121490SToomas Soome break; 4384a5d661aSToomas Soome case 't': 4394a5d661aSToomas Soome tflag = 1; 4404a5d661aSToomas Soome goto reswitch; 4414a5d661aSToomas Soome case 'u': 4424a5d661aSToomas Soome base = 10; 4434a5d661aSToomas Soome goto handle_nosign; 4444a5d661aSToomas Soome case 'X': 4454a5d661aSToomas Soome upper = 1; 4464a5d661aSToomas Soome case 'x': 4474a5d661aSToomas Soome base = 16; 4484a5d661aSToomas Soome goto handle_nosign; 4494a5d661aSToomas Soome case 'y': 4504a5d661aSToomas Soome base = 16; 4514a5d661aSToomas Soome sign = 1; 4524a5d661aSToomas Soome goto handle_sign; 4534a5d661aSToomas Soome case 'z': 4544a5d661aSToomas Soome zflag = 1; 4554a5d661aSToomas Soome goto reswitch; 4564a5d661aSToomas Soome handle_nosign: 4574a5d661aSToomas Soome sign = 0; 4584a5d661aSToomas Soome if (jflag) 4594a5d661aSToomas Soome num = va_arg(ap, uintmax_t); 4604a5d661aSToomas Soome else if (qflag) 4614a5d661aSToomas Soome num = va_arg(ap, u_quad_t); 4624a5d661aSToomas Soome else if (tflag) 4634a5d661aSToomas Soome num = va_arg(ap, ptrdiff_t); 4644a5d661aSToomas Soome else if (lflag) 4654a5d661aSToomas Soome num = va_arg(ap, u_long); 4664a5d661aSToomas Soome else if (zflag) 4674a5d661aSToomas Soome num = va_arg(ap, size_t); 4684a5d661aSToomas Soome else if (hflag) 4694a5d661aSToomas Soome num = (u_short)va_arg(ap, int); 4704a5d661aSToomas Soome else if (cflag) 4714a5d661aSToomas Soome num = (u_char)va_arg(ap, int); 4724a5d661aSToomas Soome else 4734a5d661aSToomas Soome num = va_arg(ap, u_int); 4744a5d661aSToomas Soome goto number; 4754a5d661aSToomas Soome handle_sign: 4764a5d661aSToomas Soome if (jflag) 4774a5d661aSToomas Soome num = va_arg(ap, intmax_t); 4784a5d661aSToomas Soome else if (qflag) 4794a5d661aSToomas Soome num = va_arg(ap, quad_t); 4804a5d661aSToomas Soome else if (tflag) 4814a5d661aSToomas Soome num = va_arg(ap, ptrdiff_t); 4824a5d661aSToomas Soome else if (lflag) 4834a5d661aSToomas Soome num = va_arg(ap, long); 4844a5d661aSToomas Soome else if (zflag) 4854a5d661aSToomas Soome num = va_arg(ap, ssize_t); 4864a5d661aSToomas Soome else if (hflag) 4874a5d661aSToomas Soome num = (short)va_arg(ap, int); 4884a5d661aSToomas Soome else if (cflag) 4894a5d661aSToomas Soome num = (char)va_arg(ap, int); 4904a5d661aSToomas Soome else 4914a5d661aSToomas Soome num = va_arg(ap, int); 4924a5d661aSToomas Soome number: 4934a5d661aSToomas Soome if (sign && (intmax_t)num < 0) { 4944a5d661aSToomas Soome neg = 1; 4954a5d661aSToomas Soome num = -(intmax_t)num; 4964a5d661aSToomas Soome } 4974a5d661aSToomas Soome p = ksprintn(nbuf, num, base, &n, upper); 4984a5d661aSToomas Soome tmp = 0; 4994a5d661aSToomas Soome if (sharpflag && num != 0) { 5004a5d661aSToomas Soome if (base == 8) 5014a5d661aSToomas Soome tmp++; 5024a5d661aSToomas Soome else if (base == 16) 5034a5d661aSToomas Soome tmp += 2; 5044a5d661aSToomas Soome } 5054a5d661aSToomas Soome if (neg) 5064a5d661aSToomas Soome tmp++; 5074a5d661aSToomas Soome 5084a5d661aSToomas Soome if (!ladjust && padc == '0') 5094a5d661aSToomas Soome dwidth = width - tmp; 5104a5d661aSToomas Soome width -= tmp + imax(dwidth, n); 5114a5d661aSToomas Soome dwidth -= n; 5124a5d661aSToomas Soome if (!ladjust) 5134a5d661aSToomas Soome while (width-- > 0) 5144a5d661aSToomas Soome PCHAR(' '); 5154a5d661aSToomas Soome if (neg) 5164a5d661aSToomas Soome PCHAR('-'); 5174a5d661aSToomas Soome if (sharpflag && num != 0) { 5184a5d661aSToomas Soome if (base == 8) { 5194a5d661aSToomas Soome PCHAR('0'); 5204a5d661aSToomas Soome } else if (base == 16) { 5214a5d661aSToomas Soome PCHAR('0'); 5224a5d661aSToomas Soome PCHAR('x'); 5234a5d661aSToomas Soome } 5244a5d661aSToomas Soome } 5254a5d661aSToomas Soome while (dwidth-- > 0) 5264a5d661aSToomas Soome PCHAR('0'); 5274a5d661aSToomas Soome 5284a5d661aSToomas Soome while (*p) 5294a5d661aSToomas Soome PCHAR(*p--); 5304a5d661aSToomas Soome 5314a5d661aSToomas Soome if (ladjust) 5324a5d661aSToomas Soome while (width-- > 0) 5334a5d661aSToomas Soome PCHAR(' '); 5344a5d661aSToomas Soome 5354a5d661aSToomas Soome break; 5364a5d661aSToomas Soome default: 5374a5d661aSToomas Soome while (percent < fmt) 5384a5d661aSToomas Soome PCHAR(*percent++); 5394a5d661aSToomas Soome /* 5404a5d661aSToomas Soome * Since we ignore a formatting argument it is no 5414a5d661aSToomas Soome * longer safe to obey the remaining formatting 5424a5d661aSToomas Soome * arguments as the arguments will no longer match 5434a5d661aSToomas Soome * the format specs. 5444a5d661aSToomas Soome */ 5454a5d661aSToomas Soome stop = 1; 5464a5d661aSToomas Soome break; 5474a5d661aSToomas Soome } 5484a5d661aSToomas Soome } 5494a5d661aSToomas Soome #undef PCHAR 5504a5d661aSToomas Soome } 551