📄 vfprintf.c
字号:
case 'X': xdigs = "0123456789ABCDEF"; goto hex; case 'x': xdigs = "0123456789abcdef";hex: _uquad = UARG(); base = HEX; /* leading 0x/X only if non-zero */ if (flags & ALT && _uquad != 0) flags |= HEXPREFIX; /* unsigned conversions */nosign: sign = '\0'; /* * ``... diouXx conversions ... if a precision is * specified, the 0 flag will be ignored.'' * -- ANSI X3J11 */number: if ((dprec = prec) >= 0) flags &= ~ZEROPAD; /* * ``The result of converting a zero value with an * explicit precision of zero is no characters.'' * -- ANSI X3J11 */ cp = buf + BUF; if (_uquad != 0 || prec != 0) { /* * Unsigned mod is hard, and unsigned mod * by a constant is easier than that by * a variable; hence this switch. */ switch (base) { case OCT: do { *--cp = to_char(_uquad & 7); _uquad >>= 3; } while (_uquad); /* handle octal leading 0 */ if (flags & ALT && *cp != '0') *--cp = '0'; break; case DEC: /* many numbers are 1 digit */ while (_uquad >= 10) { *--cp = to_char(_uquad % 10); _uquad /= 10; } *--cp = to_char(_uquad); break; case HEX: do { *--cp = xdigs[_uquad & 15]; _uquad >>= 4; } while (_uquad); break; default: cp = "bug in vfprintf: bad base"; size = strlen(cp); goto skipsize; } } size = buf + BUF - cp; skipsize: break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; /* pretend it was %c with argument ch */ cp = buf; *cp = ch; size = 1; sign = '\0'; break; } /* * All reasonable formats wind up here. At this point, `cp' * points to a string which (if not flags&LADJUST) should be * padded out to `width' places. If flags&ZEROPAD, it should * first be prefixed by any sign or other prefix; otherwise, * it should be blank padded before the prefix is emitted. * After any left-hand padding and prefixing, emit zeroes * required by a decimal [diouxX] precision, then print the * string proper, then emit zeroes required by any leftover * floating precision; finally, if LADJUST, pad with blanks. * * Compute actual size, so we know how much to pad. * size excludes decimal prec; realsz includes it. */ realsz = dprec > size ? dprec : size; if (sign) realsz++; else if (flags & HEXPREFIX) realsz+= 2; /* right-adjusting blank padding */ if ((flags & (LADJUST|ZEROPAD)) == 0) PAD(width - realsz, blanks); /* prefix */ if (sign) { PRINT(&sign, 1); } else if (flags & HEXPREFIX) { ox[0] = '0'; ox[1] = ch; PRINT(ox, 2); } /* right-adjusting zero padding */ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) PAD(width - realsz, zeroes); /* leading zeroes from decimal precision */ PAD(dprec - size, zeroes); /* the string or number proper */#ifdef FLOATING_POINT if ((flags & FPT) == 0) { PRINT(cp, size); } else { /* glue together f_p fragments */ if (ch >= 'f') { /* 'f' or 'g' */ if (_double == 0) { /* kludge for __dtoa irregularity */ PRINT("0", 1); if (expt < ndig || (flags & ALT) != 0) { PRINT(decimal_point, 1); PAD(ndig - 1, zeroes); } } else if (expt <= 0) { PRINT("0", 1); PRINT(decimal_point, 1); PAD(-expt, zeroes); PRINT(cp, ndig); } else if (expt >= ndig) { PRINT(cp, ndig); PAD(expt - ndig, zeroes); if (flags & ALT) PRINT(".", 1); } else { PRINT(cp, expt); cp += expt; PRINT(".", 1); PRINT(cp, ndig-expt); } } else { /* 'e' or 'E' */ if (ndig > 1 || flags & ALT) { ox[0] = *cp++; ox[1] = '.'; PRINT(ox, 2); if (_double || flags & ALT == 0) { PRINT(cp, ndig-1); } else /* 0.[0..] */ /* __dtoa irregularity */ PAD(ndig - 1, zeroes); } else /* XeYYY */ PRINT(cp, 1); PRINT(expstr, expsize); } }#else PRINT(cp, size);#endif /* left-adjusting padding (always blank) */ if (flags & LADJUST) PAD(width - realsz, blanks); /* finally, adjust ret */ ret += width > realsz ? width : realsz; FLUSH(); /* copy out the I/O vectors */ }done: FLUSH();error: if ((argtable != NULL) && (argtable != statargtable)) free (argtable); return (__sferror(fp) ? EOF : ret); /* NOTREACHED */}/* * Type ids for argument type table. */#define T_UNUSED 0#define T_SHORT 1#define T_U_SHORT 2#define TP_SHORT 3#define T_INT 4#define T_U_INT 5#define TP_INT 6#define T_LONG 7#define T_U_LONG 8#define TP_LONG 9#define T_QUAD 10#define T_U_QUAD 11#define TP_QUAD 12#define T_DOUBLE 13#define T_LONG_DOUBLE 14#define TP_CHAR 15#define TP_VOID 16/* * Find all arguments when a positional parameter is encountered. Returns a * table, indexed by argument number, of pointers to each arguments. The * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries. * It will be replaces with a malloc-ed on if it overflows. */ static void__find_arguments (fmt0, ap, argtable) const char *fmt0; va_list ap; va_list **argtable;{ register char *fmt; /* format string */ register int ch; /* character from fmt */ register int n, n2; /* handy integer (short term usage) */ register char *cp; /* handy char pointer (short term usage) */ register int flags; /* flags as above */ unsigned char *typetable; /* table of types */ unsigned char stattypetable[STATIC_ARG_TBL_SIZE]; int tablesize; /* current size of type table */ int tablemax; /* largest used index in table */ int nextarg; /* 1-based argument index */ /* * Add an argument type to the table, expanding if necessary. */#define ADDTYPE(type) \ ((nextarg >= tablesize) ? \ __grow_type_table(&typetable, &tablesize) : 0, \ typetable[nextarg++] = type, \ (nextarg > tablemax) ? tablemax = nextarg : 0)#define ADDSARG() \ ((flags&LONGINT) ? ADDTYPE(T_LONG) : \ ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))#define ADDUARG() \ ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \ ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT))) /* * Add * arguments to the type array. */#define ADDASTER() \ n2 = 0; \ cp = fmt; \ while (is_digit(*cp)) { \ n2 = 10 * n2 + to_digit(*cp); \ cp++; \ } \ if (*cp == '$') { \ int hold = nextarg; \ nextarg = n2; \ ADDTYPE (T_INT); \ nextarg = hold; \ fmt = ++cp; \ } else { \ ADDTYPE (T_INT); \ } fmt = (char *)fmt0; typetable = stattypetable; tablesize = STATIC_ARG_TBL_SIZE; tablemax = 0; nextarg = 1; memset (typetable, T_UNUSED, STATIC_ARG_TBL_SIZE); /* * Scan the format for conversions (`%' character). */ for (;;) { for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++) /* void */; if (ch == '\0') goto done; fmt++; /* skip over '%' */ flags = 0;rflag: ch = *fmt++;reswitch: switch (ch) { case ' ': case '#': goto rflag; case '*': ADDASTER (); goto rflag; case '-': case '+': goto rflag; case '.': if ((ch = *fmt++) == '*') { ADDASTER (); goto rflag; } while (is_digit(ch)) { ch = *fmt++; } goto reswitch; case '0': goto rflag; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': n = 0; do { n = 10 * n + to_digit(ch); ch = *fmt++; } while (is_digit(ch)); if (ch == '$') { nextarg = n; goto rflag; } goto reswitch;#ifdef FLOATING_POINT case 'L': flags |= LONGDBL; goto rflag;#endif case 'h': flags |= SHORTINT; goto rflag; case 'l': flags |= LONGINT; goto rflag; case 'q': flags |= QUADINT; goto rflag; case 'c': ADDTYPE(T_INT); break; case 'D': flags |= LONGINT; /*FALLTHROUGH*/ case 'd': case 'i': if (flags & QUADINT) { ADDTYPE(T_QUAD); } else { ADDSARG(); } break;#ifdef FLOATING_POINT case 'e': case 'E': case 'f': case 'g': case 'G': if (flags & LONGDBL) ADDTYPE(T_LONG_DOUBLE); else ADDTYPE(T_DOUBLE); break;#endif /* FLOATING_POINT */ case 'n': if (flags & QUADINT) ADDTYPE(TP_QUAD); else if (flags & LONGINT) ADDTYPE(TP_LONG); else if (flags & SHORTINT) ADDTYPE(TP_SHORT); else ADDTYPE(TP_INT); continue; /* no output */ case 'O': flags |= LONGINT; /*FALLTHROUGH*/ case 'o': if (flags & QUADINT) ADDTYPE(T_U_QUAD); else ADDUARG(); break; case 'p': ADDTYPE(TP_VOID); break; case 's': ADDTYPE(TP_CHAR); break; case 'U': flags |= LONGINT; /*FALLTHROUGH*/ case 'u': if (flags & QUADINT) ADDTYPE(T_U_QUAD); else ADDUARG(); break; case 'X': case 'x': if (flags & QUADINT) ADDTYPE(T_U_QUAD); else ADDUARG(); break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; break; } }done: /* * Build the argument table. */ if (tablemax >= STATIC_ARG_TBL_SIZE) { *argtable = (va_list *) malloc (sizeof (va_list) * (tablemax + 1)); }#if 0 /* XXX is this required? */ (*argtable) [0] = NULL;#endif for (n = 1; n <= tablemax; n++) { (*argtable) [n] = ap; switch (typetable [n]) { case T_UNUSED: (void) va_arg (ap, int); break; case T_SHORT: (void) va_arg (ap, int); break; case T_U_SHORT: (void) va_arg (ap, int); break; case TP_SHORT: (void) va_arg (ap, short *); break; case T_INT: (void) va_arg (ap, int); break; case T_U_INT: (void) va_arg (ap, unsigned int); break; case TP_INT: (void) va_arg (ap, int *); break; case T_LONG: (void) va_arg (ap, long); break; case T_U_LONG: (void) va_arg (ap, unsigned long); break; case TP_LONG: (void) va_arg (ap, long *); break; case T_QUAD: (void) va_arg (ap, quad_t); break; case T_U_QUAD: (void) va_arg (ap, u_quad_t); break; case TP_QUAD: (void) va_arg (ap, quad_t *); break; case T_DOUBLE: (void) va_arg (ap, double); break; case T_LONG_DOUBLE: (void) va_arg (ap, long double); break; case TP_CHAR: (void) va_arg (ap, char *); break; case TP_VOID: (void) va_arg (ap, void *); break; } } if ((typetable != NULL) && (typetable != stattypetable)) free (typetable);}/* * Increase the size of the type table. */static int__grow_type_table(typetable, tablesize) unsigned char **typetable; int *tablesize;{ unsigned char *oldtable = *typetable; int newsize = *tablesize * 2; if (*tablesize == STATIC_ARG_TBL_SIZE) { *typetable = (unsigned char *) malloc (sizeof (unsigned char) * newsize); bcopy (oldtable, *typetable, *tablesize); } else { *typetable = (unsigned char *) realloc (typetable, sizeof (unsigned char) * newsize); /* XXX unchecked */ } memset (&typetable [*tablesize], T_UNUSED, (newsize - *tablesize)); *tablesize = newsize; return(0);} #ifdef FLOATING_POINTextern char *__dtoa __P((double, int, int, int *, int *, char **));static char *cvt(value, ndigits, flags, sign, decpt, ch, length) double value; int ndigits, flags, *decpt, ch, *length; char *sign;{ int mode, dsgn; char *digits, *bp, *rve; if (ch == 'f') { mode = 3; /* ndigits after the decimal point */ } else { /* To obtain ndigits after the decimal point for the 'e' * and 'E' formats, round to ndigits + 1 significant * figures. */ if (ch == 'e' || ch == 'E') { ndigits++; } mode = 2; /* ndigits significant digits */ } if (value < 0) { value = -value; *sign = '-'; } else *sign = '\000'; digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */ bp = digits + ndigits; if (ch == 'f') { if (*digits == '0' && value) *decpt = -ndigits + 1; bp += *decpt; } if (value == 0) /* kludge for __dtoa irregularity */ rve = bp; while (rve < bp) *rve++ = '0'; } *length = rve - digits; return (digits);}static intexponent(p0, exp, fmtch) char *p0; int exp, fmtch;{ register char *p, *t; char expbuf[MAXEXP]; p = p0; *p++ = fmtch; if (exp < 0) { exp = -exp; *p++ = '-'; } else *p++ = '+'; t = expbuf + MAXEXP; if (exp > 9) { do { *--t = to_char(exp % 10); } while ((exp /= 10) > 9); *--t = to_char(exp); for (; t < expbuf + MAXEXP; *p++ = *t++); } else { *p++ = '0'; *p++ = to_char(exp); } return (p - p0);}#endif /* FLOATING_POINT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -