|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/usr/lib/libc/stdio/vfprintf.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.1 /*- 2 * Copyright (c) 1990, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Chris Torek. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 /* 34 * Actual printf innards. 35 * 36 * This code is large and complicated... 37 */ 38 39 #include <sys/types.h> 40 41 #include <limits.h> 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <stdarg.h> 46 47 #include "local.h" 48 #include "fvwrite.h" 49 50 /* 51 * Flush out all the vectors defined by the given uio, 52 * then reset it so that it can be reused. 53 */ 54 static int 55 __sprint(FILE *fp, struct __suio *uio) 56 { 57 int error; 58 59 if (uio->uio_resid == 0) { 60 uio->uio_iovcnt = 0; 61 return (0); 62 } 63 error = __sfvwrite(fp, uio); 64 uio->uio_resid = 0; 65 uio->uio_iovcnt = 0; 66 return (error); 67 } 68 69 /* 70 * Helper function for `fprintf to unbuffered unix file': creates a 71 * temporary buffer. We only work on write-only files; this avoids 72 * worries about ungetc buffers and so forth. 73 */ 74 static int 75 __sbprintf(FILE *fp, const char *fmt, va_list ap) 76 { 77 int ret; 78 FILE fake; 79 unsigned char buf[BUFSIZ]; 80 81 /* copy the important variables */ 82 fake._flags = fp->_flags & ~__SNBF; 83 fake._file = fp->_file; 84 85 /* set up the buffer */ 86 fake._bf._base = fake._p = buf; 87 fake._bf._size = fake._w = sizeof(buf); 88 89 /* do the work, then copy any error status */ 90 ret = vfprintf(&fake, fmt, ap); 91 if (ret >= 0 && fflush(&fake)) 92 ret = EOF; 93 if (fake._flags & __SERR) 94 fp->_flags |= __SERR; 95 return (ret); 96 } 97 98 /* 99 * Macros for converting digits to letters and vice versa 100 */ 101 #define to_digit(c) ((c) - '0') 102 #define is_digit(c) ((unsigned)to_digit(c) <= 9) 103 #define to_char(n) ((n) + '0') 104 105 /* 106 * Convert an unsigned long to ASCII for printf purposes, returning 107 * a pointer to the first character of the string representation. 108 * Octal numbers can be forced to have a leading zero; hex numbers 109 * use the given digits. 110 */ 111 static char * 112 __ultoa(u_long val, char *endp, int base, int octzero, char *xdigs) 113 { 114 char *cp = endp; 115 long sval; 116 117 /* 118 * Handle the three cases separately, in the hope of getting 119 * better/faster code. 120 */ 121 switch (base) { 122 case 10: 123 if (val < 10) { /* many numbers are 1 digit */ 124 *--cp = to_char(val); 125 return (cp); 126 } 127 /* 128 * On many machines, unsigned arithmetic is harder than 129 * signed arithmetic, so we do at most one unsigned mod and 130 * divide; this is sufficient to reduce the range of 131 * the incoming value to where signed arithmetic works. 132 */ 133 if (val > LONG_MAX) { 134 *--cp = to_char(val % 10); 135 sval = val / 10; 136 } else 137 sval = val; 138 do { 139 *--cp = to_char(sval % 10); 140 sval /= 10; 141 } while (sval != 0); 142 break; 143 144 case 8: 145 do { 146 *--cp = to_char(val & 7); 147 val >>= 3; 148 } while (val); 149 if (octzero && *cp != '0') 150 *--cp = '0'; 151 break; 152 153 case 16: 154 do { 155 *--cp = xdigs[val & 15]; 156 val >>= 4; 157 } while (val); 158 break; 159 160 default: /* oops */ 161 exit(1); 162 } 163 return (cp); 164 } 165 166 167 #define BUF 32 168 169 170 /* 171 * Flags used during conversion. 172 */ 173 #define ALT 0x001 /* alternate form */ 174 #define HEXPREFIX 0x002 /* add 0x or 0X prefix */ 175 #define LADJUST 0x004 /* left adjustment */ 176 #define LONGDBL 0x008 /* long double; unimplemented */ 177 #define LONGINT 0x010 /* long integer */ 178 #define SHORTINT 0x040 /* short integer */ 179 #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ 180 int 181 vfprintf(fp, fmt0, ap) 182 FILE *fp; 183 const char *fmt0; 184 va_list ap; 185 { 186 char *fmt; /* format string */ 187 int ch; /* character from fmt */ 188 int n; /* handy integer (short term usage) */ 189 char *cp; /* handy char pointer (short term usage) */ 190 struct __siov *iovp; /* for PRINT macro */ 191 int flags; /* flags as above */ 192 int ret; /* return value accumulator */ 193 int width; /* width from format (%8d), or 0 */ 194 int prec; /* precision from format (%.3d), or -1 */ 195 char sign; /* sign prefix (' ', '+', '-', or \0) */ 196 u_long ulval; /* integer arguments %[diouxX] */ 197 int base; /* base for [diouxX] conversion */ 198 int dprec; /* a copy of prec if [diouxX], 0 otherwise */ 199 int fieldsz; /* field size expanded by sign, etc */ 200 int realsz; /* field size expanded by dprec */ 201 int size; /* size of converted field or string */ 202 char *xdigs = NULL; /* digits for [xX] conversion */ 203 #define NIOV 8 204 struct __suio uio; /* output information: summary */ 205 struct __siov iov[NIOV];/* ... and individual io vectors */ 206 char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ 207 char ox[2]; /* space for 0x hex-prefix */ 208 209 /* 210 * Choose PADSIZE to trade efficiency vs. size. If larger printf 211 * fields occur frequently, increase PADSIZE and make the initialisers 212 * below longer. 213 */ 214 #define PADSIZE 16 /* pad chunk size */ 215 static char blanks[PADSIZE] = 216 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '}; 217 static char zeroes[PADSIZE] = 218 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'}; 219 220 /* 221 * BEWARE, these `goto error' on error, and PAD uses `n'. 222 */ 223 #define PRINT(ptr, len) { \ 224 iovp->iov_base = (ptr); \ 225 iovp->iov_len = (len); \ 226 uio.uio_resid += (len); \ 227 iovp++; \ 228 if (++uio.uio_iovcnt >= NIOV) { \ 229 if (__sprint(fp, &uio)) \ 230 goto error; \ 231 iovp = iov; \ 232 } \ 233 } 234 #define PAD(howmany, with) { \ 235 if ((n = (howmany)) > 0) { \ 236 while (n > PADSIZE) { \ 237 PRINT(with, PADSIZE); \ 238 n -= PADSIZE; \ 239 } \ 240 PRINT(with, n); \ 241 } \ 242 } 243 #define FLUSH() { \ 244 if (uio.uio_resid && __sprint(fp, &uio)) \ 245 goto error; \ 246 uio.uio_iovcnt = 0; \ 247 iovp = iov; \ 248 } 249 250 /* 251 * To extend shorts properly, we need both signed and unsigned 252 * argument extraction methods. 253 */ 254 #define SARG() \ 255 (flags&LONGINT ? va_arg(ap, long) : \ 256 flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ 257 (long)va_arg(ap, int)) 258 #define UARG() \ 259 (flags&LONGINT ? va_arg(ap, u_long) : \ 260 flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \ 261 (u_long)va_arg(ap, u_int)) 262 263 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ 264 if (cantwrite(fp)) 265 return (EOF); 266 267 /* optimise fprintf(stderr) (and other unbuffered Unix files) */ 268 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && 269 fp->_file >= 0) 270 return (__sbprintf(fp, fmt0, ap)); 271 272 fmt = (char *)fmt0; 273 uio.uio_iov = iovp = iov; 274 uio.uio_resid = 0; 275 uio.uio_iovcnt = 0; 276 ret = 0; 277 278 /* 279 * Scan the format for conversions (`%' character). 280 */ 281 for (;;) { 282 for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) 283 /* void */; 284 if ((n = fmt - cp) != 0) { 285 PRINT(cp, n); 286 ret += n; 287 } 288 if (ch == '\0') 289 goto done; 290 fmt++; /* skip over '%' */ 291 292 flags = 0; 293 dprec = 0; 294 width = 0; 295 prec = -1; 296 sign = '\0'; 297 298 rflag: ch = *fmt++; 299 reswitch: switch (ch) { 300 case ' ': 301 /* 302 * ``If the space and + flags both appear, the space 303 * flag will be ignored.'' 304 * -- ANSI X3J11 305 */ 306 if (!sign) 307 sign = ' '; 308 goto rflag; 309 case '#': 310 flags |= ALT; 311 goto rflag; 312 case '*': 313 /* 314 * ``A negative field width argument is taken as a 315 * - flag followed by a positive field width.'' 316 * -- ANSI X3J11 317 * They don't exclude field widths read from args. 318 */ 319 if ((width = va_arg(ap, int)) >= 0) 320 goto rflag; 321 width = -width; 322 /* FALLTHROUGH */ 323 case '-': 324 flags |= LADJUST; 325 goto rflag; 326 case '+': 327 sign = '+'; 328 goto rflag; 329 case '.': 330 if ((ch = *fmt++) == '*') { 331 n = va_arg(ap, int); 332 prec = n < 0 ? -1 : n; 333 goto rflag; 334 } 335 n = 0; 336 while (is_digit(ch)) { 337 n = 10 * n + to_digit(ch); 338 ch = *fmt++; 339 } 340 prec = n < 0 ? -1 : n; 341 goto reswitch; 342 case '0': 343 /* 344 * ``Note that 0 is taken as a flag, not as the 345 * beginning of a field width.'' 346 * -- ANSI X3J11 347 */ 348 flags |= ZEROPAD; 349 goto rflag; 350 case '1': case '2': case '3': case '4': 351 case '5': case '6': case '7': case '8': case '9': 352 n = 0; 353 do { 354 n = 10 * n + to_digit(ch); 355 ch = *fmt++; 356 } while (is_digit(ch)); 357 width = n; 358 goto reswitch; 359 case 'h': 360 flags |= SHORTINT; 361 goto rflag; 362 case 'l': 363 flags |= LONGINT; 364 goto rflag; 365 case 'c': 366 *(cp = buf) = va_arg(ap, int); 367 size = 1; 368 sign = '\0'; 369 break; 370 case 'D': 371 flags |= LONGINT; 372 /*FALLTHROUGH*/ 373 case 'd': 374 case 'i': 375 ulval = SARG(); 376 if ((long)ulval < 0) { 377 ulval = -ulval; 378 sign = '-'; 379 } 380 base = 10; 381 goto number; 382 case 'n': 383 if (flags & LONGINT) 384 *va_arg(ap, long *) = ret; 385 else if (flags & SHORTINT) 386 *va_arg(ap, short *) = ret; 387 else 388 *va_arg(ap, int *) = ret; 389 continue; /* no output */ 390 case 'O': 391 flags |= LONGINT; 392 /*FALLTHROUGH*/ 393 case 'o': 394 ulval = UARG(); 395 base = 8; 396 goto nosign; 397 case 'p': 398 /* 399 * ``The argument shall be a pointer to void. The 400 * value of the pointer is converted to a sequence 401 * of printable characters, in an implementation- 402 * defined manner.'' 403 * -- ANSI X3J11 404 */ 405 ulval = (u_long)va_arg(ap, void *); 406 base = 16; 407 xdigs = "0123456789abcdef"; 408 flags |= HEXPREFIX; 409 ch = 'x'; 410 goto nosign; 411 case 's': 412 if ((cp = va_arg(ap, char *)) == NULL) 413 cp = "(null)"; 414 if (prec >= 0) { 415 /* 416 * can't use strlen; can only look for the 417 * NUL in the first `prec' characters, and 418 * strlen() will go further. 419 */ 420 char *p = memchr(cp, 0, prec); 421 422 if (p != NULL) { 423 size = p - cp; 424 if (size > prec) 425 size = prec; 426 } else 427 size = prec; 428 } else 429 size = strlen(cp); 430 sign = '\0'; 431 break; 432 case 'U': 433 flags |= LONGINT; 434 /*FALLTHROUGH*/ 435 case 'u': 436 ulval = UARG(); 437 base = 10; 438 goto nosign; 439 case 'X': 440 xdigs = "0123456789ABCDEF"; 441 goto hex; 442 case 'x': 443 xdigs = "0123456789abcdef"; 444 hex: 445 ulval = UARG(); 446 base = 16; 447 /* leading 0x/X only if non-zero */ 448 if (flags & ALT && ulval != 0) 449 flags |= HEXPREFIX; 450 451 /* unsigned conversions */ 452 nosign: sign = '\0'; 453 /* 454 * ``... diouXx conversions ... if a precision is 455 * specified, the 0 flag will be ignored.'' 456 * -- ANSI X3J11 457 */ 458 number: if ((dprec = prec) >= 0) 459 flags &= ~ZEROPAD; 460 461 /* 462 * ``The result of converting a zero value with an 463 * explicit precision of zero is no characters.'' 464 * -- ANSI X3J11 465 */ 466 cp = buf + BUF; 467 if (ulval != 0 || prec != 0) 468 cp = __ultoa(ulval, cp, base, 469 flags & ALT, xdigs); 470 size = buf + BUF - cp; 471 break; 472 default: /* "%?" prints ?, unless ? is NUL */ 473 if (ch == '\0') 474 goto done; 475 /* pretend it was %c with argument ch */ 476 cp = buf; 477 *cp = ch; 478 size = 1; 479 sign = '\0'; 480 break; 481 } 482 483 /* 484 * All reasonable formats wind up here. At this point, `cp' 485 * points to a string which (if not flags&LADJUST) should be 486 * padded out to `width' places. If flags&ZEROPAD, it should 487 * first be prefixed by any sign or other prefix; otherwise, 488 * it should be blank padded before the prefix is emitted. 489 * After any left-hand padding and prefixing, emit zeroes 490 * required by a decimal [diouxX] precision, then print the 491 * string proper, then emit zeroes required by any leftover 492 * floating precision; finally, if LADJUST, pad with blanks. 493 * 494 * Compute actual size, so we know how much to pad. 495 * fieldsz excludes decimal prec; realsz includes it. 496 */ 497 fieldsz = size; 498 if (sign) 499 fieldsz++; 500 else if (flags & HEXPREFIX) 501 fieldsz += 2; 502 realsz = dprec > fieldsz ? dprec : fieldsz; 503 504 /* right-adjusting blank padding */ 505 if ((flags & (LADJUST|ZEROPAD)) == 0) 506 PAD(width - realsz, blanks); 507 508 /* prefix */ 509 if (sign) { 510 PRINT(&sign, 1); 511 } else if (flags & HEXPREFIX) { 512 ox[0] = '0'; 513 ox[1] = ch; 514 PRINT(ox, 2); 515 } 516 517 /* right-adjusting zero padding */ 518 if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) 519 PAD(width - realsz, zeroes); 520 521 /* leading zeroes from decimal precision */ 522 PAD(dprec - fieldsz, zeroes); 523 524 /* the string or number proper */ 525 PRINT(cp, size); 526 527 /* left-adjusting padding (always blank) */ 528 if (flags & LADJUST) 529 PAD(width - realsz, blanks); 530 531 /* finally, adjust ret */ 532 ret += width > realsz ? width : realsz; 533 534 FLUSH(); /* copy out the I/O vectors */ 535 } 536 done: 537 FLUSH(); 538 error: 539 return (__sferror(fp) ? EOF : ret); 540 /* NOTREACHED */ 541 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |