1ca987d46SWarner Losh /*- 2ca987d46SWarner Losh * Copyright (c) 1986, 1988, 1991, 1993 3ca987d46SWarner Losh * The Regents of the University of California. All rights reserved. 4ca987d46SWarner Losh * (c) UNIX System Laboratories, Inc. 5ca987d46SWarner Losh * All or some portions of this file are derived from material licensed 6ca987d46SWarner Losh * to the University of California by American Telephone and Telegraph 7ca987d46SWarner Losh * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8ca987d46SWarner Losh * the permission of UNIX System Laboratories, Inc. 9ca987d46SWarner Losh * 10ca987d46SWarner Losh * Redistribution and use in source and binary forms, with or without 11ca987d46SWarner Losh * modification, are permitted provided that the following conditions 12ca987d46SWarner Losh * are met: 13ca987d46SWarner Losh * 1. Redistributions of source code must retain the above copyright 14ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer. 15ca987d46SWarner Losh * 2. Redistributions in binary form must reproduce the above copyright 16ca987d46SWarner Losh * notice, this list of conditions and the following disclaimer in the 17ca987d46SWarner Losh * documentation and/or other materials provided with the distribution. 18ca987d46SWarner Losh * 3. Neither the name of the University nor the names of its contributors 19ca987d46SWarner Losh * may be used to endorse or promote products derived from this software 20ca987d46SWarner Losh * without specific prior written permission. 21ca987d46SWarner Losh * 22ca987d46SWarner Losh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23ca987d46SWarner Losh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24ca987d46SWarner Losh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25ca987d46SWarner Losh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26ca987d46SWarner Losh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27ca987d46SWarner Losh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28ca987d46SWarner Losh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29ca987d46SWarner Losh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30ca987d46SWarner Losh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31ca987d46SWarner Losh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32ca987d46SWarner Losh * SUCH DAMAGE. 33ca987d46SWarner Losh * 34ca987d46SWarner Losh * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 35ca987d46SWarner Losh */ 36ca987d46SWarner Losh 37ca987d46SWarner Losh #include <sys/cdefs.h> 38ca987d46SWarner Losh __FBSDID("$FreeBSD$"); 39ca987d46SWarner Losh 40ca987d46SWarner Losh /* 41ca987d46SWarner Losh * Standaloneified version of the FreeBSD kernel printf family. 42ca987d46SWarner Losh */ 43ca987d46SWarner Losh 44ca987d46SWarner Losh #include <sys/types.h> 45ca987d46SWarner Losh #include <sys/stddef.h> 46ca987d46SWarner Losh #include <sys/stdint.h> 47ca987d46SWarner Losh #include <limits.h> 48ca987d46SWarner Losh #include <string.h> 49ca987d46SWarner Losh #include "stand.h" 50ca987d46SWarner Losh 51ca987d46SWarner Losh /* 52ca987d46SWarner Losh * Note that stdarg.h and the ANSI style va_start macro is used for both 53ca987d46SWarner Losh * ANSI and traditional C compilers. 54ca987d46SWarner Losh */ 55ca987d46SWarner Losh #include <machine/stdarg.h> 56ca987d46SWarner Losh 57ca987d46SWarner Losh #define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1) 58ca987d46SWarner Losh 59ca987d46SWarner Losh typedef void (kvprintf_fn_t)(int, void *); 60ca987d46SWarner Losh 61ca987d46SWarner Losh static char *ksprintn (char *buf, uintmax_t num, int base, int *len, int upper); 62ca987d46SWarner Losh static int kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap); 63ca987d46SWarner Losh 64ca987d46SWarner Losh static void 65ca987d46SWarner Losh putchar_wrapper(int cc, void *arg) 66ca987d46SWarner Losh { 67ca987d46SWarner Losh 68ca987d46SWarner Losh putchar(cc); 69ca987d46SWarner Losh } 70ca987d46SWarner Losh 71ca987d46SWarner Losh int 72ca987d46SWarner Losh printf(const char *fmt, ...) 73ca987d46SWarner Losh { 74ca987d46SWarner Losh va_list ap; 75ca987d46SWarner Losh int retval; 76ca987d46SWarner Losh 77ca987d46SWarner Losh va_start(ap, fmt); 78ca987d46SWarner Losh retval = kvprintf(fmt, putchar_wrapper, NULL, 10, ap); 79ca987d46SWarner Losh va_end(ap); 80ca987d46SWarner Losh return retval; 81ca987d46SWarner Losh } 82ca987d46SWarner Losh 833e9c7874SIan Lepore int 84ca987d46SWarner Losh vprintf(const char *fmt, va_list ap) 85ca987d46SWarner Losh { 86ca987d46SWarner Losh 873e9c7874SIan Lepore return (kvprintf(fmt, putchar_wrapper, NULL, 10, ap)); 88ca987d46SWarner Losh } 89ca987d46SWarner Losh 90ca987d46SWarner Losh int 91ca987d46SWarner Losh sprintf(char *buf, const char *cfmt, ...) 92ca987d46SWarner Losh { 93ca987d46SWarner Losh int retval; 94ca987d46SWarner Losh va_list ap; 95ca987d46SWarner Losh 96ca987d46SWarner Losh va_start(ap, cfmt); 97ca987d46SWarner Losh retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 98ca987d46SWarner Losh buf[retval] = '\0'; 99ca987d46SWarner Losh va_end(ap); 100ca987d46SWarner Losh return retval; 101ca987d46SWarner Losh } 102ca987d46SWarner Losh 103ca987d46SWarner Losh struct print_buf { 104ca987d46SWarner Losh char *buf; 105ca987d46SWarner Losh size_t size; 106ca987d46SWarner Losh }; 107ca987d46SWarner Losh 108ca987d46SWarner Losh static void 109ca987d46SWarner Losh snprint_func(int ch, void *arg) 110ca987d46SWarner Losh { 111ca987d46SWarner Losh struct print_buf *pbuf = arg; 112ca987d46SWarner Losh 113ca987d46SWarner Losh if (pbuf->size < 2) { 114ca987d46SWarner Losh /* 115ca987d46SWarner Losh * Reserve last buffer position for the terminating 116ca987d46SWarner Losh * character: 117ca987d46SWarner Losh */ 118ca987d46SWarner Losh return; 119ca987d46SWarner Losh } 120ca987d46SWarner Losh *(pbuf->buf)++ = ch; 121ca987d46SWarner Losh pbuf->size--; 122ca987d46SWarner Losh } 123ca987d46SWarner Losh 124ca987d46SWarner Losh int 1255e84b578SToomas Soome asprintf(char **buf, const char *cfmt, ...) 1265e84b578SToomas Soome { 1275e84b578SToomas Soome int retval; 1285e84b578SToomas Soome struct print_buf arg; 1295e84b578SToomas Soome va_list ap; 1305e84b578SToomas Soome 1315e84b578SToomas Soome *buf = NULL; 1325e84b578SToomas Soome va_start(ap, cfmt); 1335e84b578SToomas Soome retval = kvprintf(cfmt, NULL, NULL, 10, ap); 1345e84b578SToomas Soome va_end(ap); 1355e84b578SToomas Soome if (retval <= 0) 1365e84b578SToomas Soome return (-1); 1375e84b578SToomas Soome 1385e84b578SToomas Soome arg.size = retval + 1; 1395e84b578SToomas Soome arg.buf = *buf = malloc(arg.size); 1405e84b578SToomas Soome if (*buf == NULL) 1415e84b578SToomas Soome return (-1); 1425e84b578SToomas Soome 1435e84b578SToomas Soome va_start(ap, cfmt); 1445e84b578SToomas Soome retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap); 1455e84b578SToomas Soome va_end(ap); 1465e84b578SToomas Soome 1475e84b578SToomas Soome if (arg.size >= 1) 1485e84b578SToomas Soome *(arg.buf)++ = 0; 1495e84b578SToomas Soome return (retval); 1505e84b578SToomas Soome } 1515e84b578SToomas Soome 1525e84b578SToomas Soome int 153ca987d46SWarner Losh snprintf(char *buf, size_t size, const char *cfmt, ...) 154ca987d46SWarner Losh { 155ca987d46SWarner Losh int retval; 156ca987d46SWarner Losh va_list ap; 157ca987d46SWarner Losh struct print_buf arg; 158ca987d46SWarner Losh 159ca987d46SWarner Losh arg.buf = buf; 160ca987d46SWarner Losh arg.size = size; 161ca987d46SWarner Losh 162ca987d46SWarner Losh va_start(ap, cfmt); 163ca987d46SWarner Losh retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap); 164ca987d46SWarner Losh va_end(ap); 165ca987d46SWarner Losh 166ca987d46SWarner Losh if (arg.size >= 1) 167ca987d46SWarner Losh *(arg.buf)++ = 0; 168ca987d46SWarner Losh return retval; 169ca987d46SWarner Losh } 170ca987d46SWarner Losh 1713e9c7874SIan Lepore int 1721851d70dSIan Lepore vsnprintf(char *buf, size_t size, const char *cfmt, va_list ap) 1731851d70dSIan Lepore { 1741851d70dSIan Lepore struct print_buf arg; 1753e9c7874SIan Lepore int retval; 1761851d70dSIan Lepore 1771851d70dSIan Lepore arg.buf = buf; 1781851d70dSIan Lepore arg.size = size; 1791851d70dSIan Lepore 1803e9c7874SIan Lepore retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap); 1811851d70dSIan Lepore 1821851d70dSIan Lepore if (arg.size >= 1) 1831851d70dSIan Lepore *(arg.buf)++ = 0; 1843e9c7874SIan Lepore 1853e9c7874SIan Lepore return (retval); 1861851d70dSIan Lepore } 1871851d70dSIan Lepore 1883e9c7874SIan Lepore int 189ca987d46SWarner Losh vsprintf(char *buf, const char *cfmt, va_list ap) 190ca987d46SWarner Losh { 191ca987d46SWarner Losh int retval; 192ca987d46SWarner Losh 193ca987d46SWarner Losh retval = kvprintf(cfmt, NULL, (void *)buf, 10, ap); 194ca987d46SWarner Losh buf[retval] = '\0'; 1953e9c7874SIan Lepore 1963e9c7874SIan Lepore return (retval); 197ca987d46SWarner Losh } 198ca987d46SWarner Losh 199ca987d46SWarner Losh /* 200ca987d46SWarner Losh * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse 201ca987d46SWarner Losh * order; return an optional length and a pointer to the last character 202ca987d46SWarner Losh * written in the buffer (i.e., the first character of the string). 203ca987d46SWarner Losh * The buffer pointed to by `nbuf' must have length >= MAXNBUF. 204ca987d46SWarner Losh */ 205ca987d46SWarner Losh static char * 206ca987d46SWarner Losh ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) 207ca987d46SWarner Losh { 208ca987d46SWarner Losh char *p, c; 209ca987d46SWarner Losh 210ca987d46SWarner Losh p = nbuf; 211ca987d46SWarner Losh *p = '\0'; 212ca987d46SWarner Losh do { 213ca987d46SWarner Losh c = hex2ascii(num % base); 214ca987d46SWarner Losh *++p = upper ? toupper(c) : c; 215ca987d46SWarner Losh } while (num /= base); 216ca987d46SWarner Losh if (lenp) 217ca987d46SWarner Losh *lenp = p - nbuf; 218ca987d46SWarner Losh return (p); 219ca987d46SWarner Losh } 220ca987d46SWarner Losh 221ca987d46SWarner Losh /* 222ca987d46SWarner Losh * Scaled down version of printf(3). 223ca987d46SWarner Losh * 224ca987d46SWarner Losh * Two additional formats: 225ca987d46SWarner Losh * 226ca987d46SWarner Losh * The format %b is supported to decode error registers. 227ca987d46SWarner Losh * Its usage is: 228ca987d46SWarner Losh * 229ca987d46SWarner Losh * printf("reg=%b\n", regval, "<base><arg>*"); 230ca987d46SWarner Losh * 231ca987d46SWarner Losh * where <base> is the output base expressed as a control character, e.g. 232ca987d46SWarner Losh * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 233ca987d46SWarner Losh * the first of which gives the bit number to be inspected (origin 1), and 234ca987d46SWarner Losh * the next characters (up to a control character, i.e. a character <= 32), 235ca987d46SWarner Losh * give the name of the register. Thus: 236ca987d46SWarner Losh * 237ca987d46SWarner Losh * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE"); 238ca987d46SWarner Losh * 239ca987d46SWarner Losh * would produce output: 240ca987d46SWarner Losh * 241ca987d46SWarner Losh * reg=3<BITTWO,BITONE> 242ca987d46SWarner Losh * 243ca987d46SWarner Losh * XXX: %D -- Hexdump, takes pointer and separator string: 244ca987d46SWarner Losh * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX 245ca987d46SWarner Losh * ("%*D", len, ptr, " " -> XX XX XX XX ... 246ca987d46SWarner Losh */ 247ca987d46SWarner Losh static int 248ca987d46SWarner Losh kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap) 249ca987d46SWarner Losh { 250*98e28b71SToomas Soome #define PCHAR(c) { \ 251*98e28b71SToomas Soome int cc = (c); \ 252*98e28b71SToomas Soome \ 253*98e28b71SToomas Soome if (func) { \ 254*98e28b71SToomas Soome (*func)(cc, arg); \ 255*98e28b71SToomas Soome } else if (d != NULL) { \ 256*98e28b71SToomas Soome *d++ = cc; \ 257*98e28b71SToomas Soome } \ 258*98e28b71SToomas Soome retval++; \ 259*98e28b71SToomas Soome } 260*98e28b71SToomas Soome 261ca987d46SWarner Losh char nbuf[MAXNBUF]; 262ca987d46SWarner Losh char *d; 263ca987d46SWarner Losh const char *p, *percent, *q; 264ca987d46SWarner Losh uint16_t *S; 265ca987d46SWarner Losh u_char *up; 266ca987d46SWarner Losh int ch, n; 267ca987d46SWarner Losh uintmax_t num; 268ca987d46SWarner Losh int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; 269ca987d46SWarner Losh int cflag, hflag, jflag, tflag, zflag; 270ca987d46SWarner Losh int dwidth, upper; 271ca987d46SWarner Losh char padc; 272ca987d46SWarner Losh int stop = 0, retval = 0; 273ca987d46SWarner Losh 274ca987d46SWarner Losh num = 0; 275ca987d46SWarner Losh if (!func) 276ca987d46SWarner Losh d = (char *) arg; 277ca987d46SWarner Losh else 278ca987d46SWarner Losh d = NULL; 279ca987d46SWarner Losh 280ca987d46SWarner Losh if (fmt == NULL) 281ca987d46SWarner Losh fmt = "(fmt null)\n"; 282ca987d46SWarner Losh 283ca987d46SWarner Losh if (radix < 2 || radix > 36) 284ca987d46SWarner Losh radix = 10; 285ca987d46SWarner Losh 286ca987d46SWarner Losh for (;;) { 287ca987d46SWarner Losh padc = ' '; 288ca987d46SWarner Losh width = 0; 289ca987d46SWarner Losh while ((ch = (u_char)*fmt++) != '%' || stop) { 290ca987d46SWarner Losh if (ch == '\0') 291ca987d46SWarner Losh return (retval); 292ca987d46SWarner Losh PCHAR(ch); 293ca987d46SWarner Losh } 294ca987d46SWarner Losh percent = fmt - 1; 295ca987d46SWarner Losh qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; 296ca987d46SWarner Losh sign = 0; dot = 0; dwidth = 0; upper = 0; 297ca987d46SWarner Losh cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; 298ca987d46SWarner Losh reswitch: switch (ch = (u_char)*fmt++) { 299ca987d46SWarner Losh case '.': 300ca987d46SWarner Losh dot = 1; 301ca987d46SWarner Losh goto reswitch; 302ca987d46SWarner Losh case '#': 303ca987d46SWarner Losh sharpflag = 1; 304ca987d46SWarner Losh goto reswitch; 305ca987d46SWarner Losh case '+': 306ca987d46SWarner Losh sign = 1; 307ca987d46SWarner Losh goto reswitch; 308ca987d46SWarner Losh case '-': 309ca987d46SWarner Losh ladjust = 1; 310ca987d46SWarner Losh goto reswitch; 311ca987d46SWarner Losh case '%': 312ca987d46SWarner Losh PCHAR(ch); 313ca987d46SWarner Losh break; 314ca987d46SWarner Losh case '*': 315ca987d46SWarner Losh if (!dot) { 316ca987d46SWarner Losh width = va_arg(ap, int); 317ca987d46SWarner Losh if (width < 0) { 318ca987d46SWarner Losh ladjust = !ladjust; 319ca987d46SWarner Losh width = -width; 320ca987d46SWarner Losh } 321ca987d46SWarner Losh } else { 322ca987d46SWarner Losh dwidth = va_arg(ap, int); 323ca987d46SWarner Losh } 324ca987d46SWarner Losh goto reswitch; 325ca987d46SWarner Losh case '0': 326ca987d46SWarner Losh if (!dot) { 327ca987d46SWarner Losh padc = '0'; 328ca987d46SWarner Losh goto reswitch; 329ca987d46SWarner Losh } 330ca987d46SWarner Losh case '1': case '2': case '3': case '4': 331ca987d46SWarner Losh case '5': case '6': case '7': case '8': case '9': 332ca987d46SWarner Losh for (n = 0;; ++fmt) { 333ca987d46SWarner Losh n = n * 10 + ch - '0'; 334ca987d46SWarner Losh ch = *fmt; 335ca987d46SWarner Losh if (ch < '0' || ch > '9') 336ca987d46SWarner Losh break; 337ca987d46SWarner Losh } 338ca987d46SWarner Losh if (dot) 339ca987d46SWarner Losh dwidth = n; 340ca987d46SWarner Losh else 341ca987d46SWarner Losh width = n; 342ca987d46SWarner Losh goto reswitch; 343ca987d46SWarner Losh case 'b': 344ca987d46SWarner Losh num = (u_int)va_arg(ap, int); 345ca987d46SWarner Losh p = va_arg(ap, char *); 346ca987d46SWarner Losh for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) 347ca987d46SWarner Losh PCHAR(*q--); 348ca987d46SWarner Losh 349ca987d46SWarner Losh if (num == 0) 350ca987d46SWarner Losh break; 351ca987d46SWarner Losh 352ca987d46SWarner Losh for (tmp = 0; *p;) { 353ca987d46SWarner Losh n = *p++; 354ca987d46SWarner Losh if (num & (1 << (n - 1))) { 355ca987d46SWarner Losh PCHAR(tmp ? ',' : '<'); 356ca987d46SWarner Losh for (; (n = *p) > ' '; ++p) 357ca987d46SWarner Losh PCHAR(n); 358ca987d46SWarner Losh tmp = 1; 359ca987d46SWarner Losh } else 360ca987d46SWarner Losh for (; *p > ' '; ++p) 361ca987d46SWarner Losh continue; 362ca987d46SWarner Losh } 363ca987d46SWarner Losh if (tmp) 364ca987d46SWarner Losh PCHAR('>'); 365ca987d46SWarner Losh break; 366ca987d46SWarner Losh case 'c': 367ca987d46SWarner Losh PCHAR(va_arg(ap, int)); 368ca987d46SWarner Losh break; 369ca987d46SWarner Losh case 'D': 370ca987d46SWarner Losh up = va_arg(ap, u_char *); 371ca987d46SWarner Losh p = va_arg(ap, char *); 372ca987d46SWarner Losh if (!width) 373ca987d46SWarner Losh width = 16; 374ca987d46SWarner Losh while(width--) { 375ca987d46SWarner Losh PCHAR(hex2ascii(*up >> 4)); 376ca987d46SWarner Losh PCHAR(hex2ascii(*up & 0x0f)); 377ca987d46SWarner Losh up++; 378ca987d46SWarner Losh if (width) 379ca987d46SWarner Losh for (q=p;*q;q++) 380ca987d46SWarner Losh PCHAR(*q); 381ca987d46SWarner Losh } 382ca987d46SWarner Losh break; 383ca987d46SWarner Losh case 'd': 384ca987d46SWarner Losh case 'i': 385ca987d46SWarner Losh base = 10; 386ca987d46SWarner Losh sign = 1; 387ca987d46SWarner Losh goto handle_sign; 388ca987d46SWarner Losh case 'h': 389ca987d46SWarner Losh if (hflag) { 390ca987d46SWarner Losh hflag = 0; 391ca987d46SWarner Losh cflag = 1; 392ca987d46SWarner Losh } else 393ca987d46SWarner Losh hflag = 1; 394ca987d46SWarner Losh goto reswitch; 395ca987d46SWarner Losh case 'j': 396ca987d46SWarner Losh jflag = 1; 397ca987d46SWarner Losh goto reswitch; 398ca987d46SWarner Losh case 'l': 399ca987d46SWarner Losh if (lflag) { 400ca987d46SWarner Losh lflag = 0; 401ca987d46SWarner Losh qflag = 1; 402ca987d46SWarner Losh } else 403ca987d46SWarner Losh lflag = 1; 404ca987d46SWarner Losh goto reswitch; 405ca987d46SWarner Losh case 'n': 406ca987d46SWarner Losh if (jflag) 407ca987d46SWarner Losh *(va_arg(ap, intmax_t *)) = retval; 408ca987d46SWarner Losh else if (qflag) 409ca987d46SWarner Losh *(va_arg(ap, quad_t *)) = retval; 410ca987d46SWarner Losh else if (lflag) 411ca987d46SWarner Losh *(va_arg(ap, long *)) = retval; 412ca987d46SWarner Losh else if (zflag) 413ca987d46SWarner Losh *(va_arg(ap, size_t *)) = retval; 414ca987d46SWarner Losh else if (hflag) 415ca987d46SWarner Losh *(va_arg(ap, short *)) = retval; 416ca987d46SWarner Losh else if (cflag) 417ca987d46SWarner Losh *(va_arg(ap, char *)) = retval; 418ca987d46SWarner Losh else 419ca987d46SWarner Losh *(va_arg(ap, int *)) = retval; 420ca987d46SWarner Losh break; 421ca987d46SWarner Losh case 'o': 422ca987d46SWarner Losh base = 8; 423ca987d46SWarner Losh goto handle_nosign; 424ca987d46SWarner Losh case 'p': 425ca987d46SWarner Losh base = 16; 426ca987d46SWarner Losh sharpflag = (width == 0); 427ca987d46SWarner Losh sign = 0; 428ca987d46SWarner Losh num = (uintptr_t)va_arg(ap, void *); 429ca987d46SWarner Losh goto number; 430ca987d46SWarner Losh case 'q': 431ca987d46SWarner Losh qflag = 1; 432ca987d46SWarner Losh goto reswitch; 433ca987d46SWarner Losh case 'r': 434ca987d46SWarner Losh base = radix; 435ca987d46SWarner Losh if (sign) 436ca987d46SWarner Losh goto handle_sign; 437ca987d46SWarner Losh goto handle_nosign; 438ca987d46SWarner Losh case 's': 439ca987d46SWarner Losh p = va_arg(ap, char *); 440ca987d46SWarner Losh if (p == NULL) 441ca987d46SWarner Losh p = "(null)"; 442ca987d46SWarner Losh if (!dot) 443ca987d46SWarner Losh n = strlen (p); 444ca987d46SWarner Losh else 445ca987d46SWarner Losh for (n = 0; n < dwidth && p[n]; n++) 446ca987d46SWarner Losh continue; 447ca987d46SWarner Losh 448ca987d46SWarner Losh width -= n; 449ca987d46SWarner Losh 450ca987d46SWarner Losh if (!ladjust && width > 0) 451ca987d46SWarner Losh while (width--) 452ca987d46SWarner Losh PCHAR(padc); 453ca987d46SWarner Losh while (n--) 454ca987d46SWarner Losh PCHAR(*p++); 455ca987d46SWarner Losh if (ladjust && width > 0) 456ca987d46SWarner Losh while (width--) 457ca987d46SWarner Losh PCHAR(padc); 458ca987d46SWarner Losh break; 459ca987d46SWarner Losh case 'S': /* Assume console can cope with wide chars */ 460ca987d46SWarner Losh for (S = va_arg(ap, uint16_t *); *S != 0; S++) 461ca987d46SWarner Losh PCHAR(*S); 462ca987d46SWarner Losh break; 463ca987d46SWarner Losh case 't': 464ca987d46SWarner Losh tflag = 1; 465ca987d46SWarner Losh goto reswitch; 466ca987d46SWarner Losh case 'u': 467ca987d46SWarner Losh base = 10; 468ca987d46SWarner Losh goto handle_nosign; 469ca987d46SWarner Losh case 'X': 470ca987d46SWarner Losh upper = 1; 471ca987d46SWarner Losh case 'x': 472ca987d46SWarner Losh base = 16; 473ca987d46SWarner Losh goto handle_nosign; 474ca987d46SWarner Losh case 'y': 475ca987d46SWarner Losh base = 16; 476ca987d46SWarner Losh sign = 1; 477ca987d46SWarner Losh goto handle_sign; 478ca987d46SWarner Losh case 'z': 479ca987d46SWarner Losh zflag = 1; 480ca987d46SWarner Losh goto reswitch; 481ca987d46SWarner Losh handle_nosign: 482ca987d46SWarner Losh sign = 0; 483ca987d46SWarner Losh if (jflag) 484ca987d46SWarner Losh num = va_arg(ap, uintmax_t); 485ca987d46SWarner Losh else if (qflag) 486ca987d46SWarner Losh num = va_arg(ap, u_quad_t); 487ca987d46SWarner Losh else if (tflag) 488ca987d46SWarner Losh num = va_arg(ap, ptrdiff_t); 489ca987d46SWarner Losh else if (lflag) 490ca987d46SWarner Losh num = va_arg(ap, u_long); 491ca987d46SWarner Losh else if (zflag) 492ca987d46SWarner Losh num = va_arg(ap, size_t); 493ca987d46SWarner Losh else if (hflag) 494ca987d46SWarner Losh num = (u_short)va_arg(ap, int); 495ca987d46SWarner Losh else if (cflag) 496ca987d46SWarner Losh num = (u_char)va_arg(ap, int); 497ca987d46SWarner Losh else 498ca987d46SWarner Losh num = va_arg(ap, u_int); 499ca987d46SWarner Losh goto number; 500ca987d46SWarner Losh handle_sign: 501ca987d46SWarner Losh if (jflag) 502ca987d46SWarner Losh num = va_arg(ap, intmax_t); 503ca987d46SWarner Losh else if (qflag) 504ca987d46SWarner Losh num = va_arg(ap, quad_t); 505ca987d46SWarner Losh else if (tflag) 506ca987d46SWarner Losh num = va_arg(ap, ptrdiff_t); 507ca987d46SWarner Losh else if (lflag) 508ca987d46SWarner Losh num = va_arg(ap, long); 509ca987d46SWarner Losh else if (zflag) 510ca987d46SWarner Losh num = va_arg(ap, ssize_t); 511ca987d46SWarner Losh else if (hflag) 512ca987d46SWarner Losh num = (short)va_arg(ap, int); 513ca987d46SWarner Losh else if (cflag) 514ca987d46SWarner Losh num = (char)va_arg(ap, int); 515ca987d46SWarner Losh else 516ca987d46SWarner Losh num = va_arg(ap, int); 517ca987d46SWarner Losh number: 518ca987d46SWarner Losh if (sign && (intmax_t)num < 0) { 519ca987d46SWarner Losh neg = 1; 520ca987d46SWarner Losh num = -(intmax_t)num; 521ca987d46SWarner Losh } 522ca987d46SWarner Losh p = ksprintn(nbuf, num, base, &n, upper); 523ca987d46SWarner Losh tmp = 0; 524ca987d46SWarner Losh if (sharpflag && num != 0) { 525ca987d46SWarner Losh if (base == 8) 526ca987d46SWarner Losh tmp++; 527ca987d46SWarner Losh else if (base == 16) 528ca987d46SWarner Losh tmp += 2; 529ca987d46SWarner Losh } 530ca987d46SWarner Losh if (neg) 531ca987d46SWarner Losh tmp++; 532ca987d46SWarner Losh 533ca987d46SWarner Losh if (!ladjust && padc == '0') 534ca987d46SWarner Losh dwidth = width - tmp; 535ca987d46SWarner Losh width -= tmp + imax(dwidth, n); 536ca987d46SWarner Losh dwidth -= n; 537ca987d46SWarner Losh if (!ladjust) 538ca987d46SWarner Losh while (width-- > 0) 539ca987d46SWarner Losh PCHAR(' '); 540ca987d46SWarner Losh if (neg) 541ca987d46SWarner Losh PCHAR('-'); 542ca987d46SWarner Losh if (sharpflag && num != 0) { 543ca987d46SWarner Losh if (base == 8) { 544ca987d46SWarner Losh PCHAR('0'); 545ca987d46SWarner Losh } else if (base == 16) { 546ca987d46SWarner Losh PCHAR('0'); 547ca987d46SWarner Losh PCHAR('x'); 548ca987d46SWarner Losh } 549ca987d46SWarner Losh } 550ca987d46SWarner Losh while (dwidth-- > 0) 551ca987d46SWarner Losh PCHAR('0'); 552ca987d46SWarner Losh 553ca987d46SWarner Losh while (*p) 554ca987d46SWarner Losh PCHAR(*p--); 555ca987d46SWarner Losh 556ca987d46SWarner Losh if (ladjust) 557ca987d46SWarner Losh while (width-- > 0) 558ca987d46SWarner Losh PCHAR(' '); 559ca987d46SWarner Losh 560ca987d46SWarner Losh break; 561ca987d46SWarner Losh default: 562ca987d46SWarner Losh while (percent < fmt) 563ca987d46SWarner Losh PCHAR(*percent++); 564ca987d46SWarner Losh /* 565ca987d46SWarner Losh * Since we ignore a formatting argument it is no 566ca987d46SWarner Losh * longer safe to obey the remaining formatting 567ca987d46SWarner Losh * arguments as the arguments will no longer match 568ca987d46SWarner Losh * the format specs. 569ca987d46SWarner Losh */ 570ca987d46SWarner Losh stop = 1; 571ca987d46SWarner Losh break; 572ca987d46SWarner Losh } 573ca987d46SWarner Losh } 574ca987d46SWarner Losh #undef PCHAR 575ca987d46SWarner Losh } 576