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