📄 vfprintf.c
字号:
PRINT(".", 1); PRINT(cp, ndig-expt); } } else { /* 'e' or 'E' */ if (ndig > 1 || flags & ALT) { ox[0] = *cp++; ox[1] = '.'; PRINT(ox, 2); if (_fpvalue) { 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: return (__sferror(fp) ? EOF : ret); /* NOTREACHED */}#ifdef FLOATING_POINT#ifdef _NO_LONGDBLextern char *_dtoa_r _PARAMS((struct _reent *, double, int, int, int *, int *, char **));#elseextern char *_ldtoa_r _PARAMS((struct _reent *, _LONG_DOUBLE, int, int, int *, int *, char **));#undef word0#define word0(x) ldword0(x)#endifstatic char *cvt(data, value, ndigits, flags, sign, decpt, ch, length) struct _reent *data;#ifdef _NO_LONGDBL double value;#else _LONG_DOUBLE value;#endif int ndigits, flags, *decpt, ch, *length; char *sign;{ int mode, dsgn; char *digits, *bp, *rve;#ifdef _NO_LONGDBL union double_union tmp;#else struct ldieee *ldptr;#endif 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 */ }#ifdef _NO_LONGDBL tmp.d = value; if (word0(tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */ value = -value; *sign = '-'; } else *sign = '\000'; digits = _dtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve);#else /* !_NO_LONGDBL */ ldptr = (struct ldieee *)&value; if (ldptr->sign) { /* this will check for < 0 and -0.0 */ value = -value; *sign = '-'; } else *sign = '\000'; digits = _ldtoa_r(data, value, mode, ndigits, decpt, &dsgn, &rve);#endif /* !_NO_LONGDBL */ 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[40]; p = p0; *p++ = fmtch; if (exp < 0) { exp = -exp; *p++ = '-'; } else *p++ = '+'; t = expbuf + 40; if (exp > 9) { do { *--t = to_char(exp % 10); } while ((exp /= 10) > 9); *--t = to_char(exp); for (; t < expbuf + 40; *p++ = *t++); } else { *p++ = '0'; *p++ = to_char(exp); } return (p - p0);}#endif /* FLOATING_POINT */#ifndef _NO_POS_ARGS/* Positional argument support. Written by Jeff Johnston Copyright (c) 2002 Red Hat Incorporated. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The name of Red Hat Incorporated may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */typedef enum { ZERO, /* '0' */ DIGIT, /* '1-9' */ DOLLAR, /* '$' */ MODFR, /* spec modifier */ SPEC, /* format specifier */ DOT, /* '.' */ STAR, /* '*' */ FLAG, /* format flag */ OTHER, /* all other chars */ MAX_CH_CLASS /* place-holder */} CH_CLASS;typedef enum { START, /* start */ SFLAG, /* seen a flag */ WDIG, /* seen digits in width area */ WIDTH, /* processed width */ SMOD, /* seen spec modifier */ SDOT, /* seen dot */ VARW, /* have variable width specifier */ VARP, /* have variable precision specifier */ PREC, /* processed precision */ VWDIG, /* have digits in variable width specification */ VPDIG, /* have digits in variable precision specification */ DONE, /* done */ MAX_STATE, /* place-holder */ } STATE;typedef enum { NOOP, /* do nothing */ NUMBER, /* build a number from digits */ SKIPNUM, /* skip over digits */ GETMOD, /* get and process format modifier */ GETARG, /* get and process argument */ GETPW, /* get variable precision or width */ GETPWB, /* get variable precision or width and pushback fmt char */ GETPOS, /* get positional parameter value */ PWPOS, /* get positional parameter value for variable width or precision */} ACTION;const static CH_CLASS chclass[256] = { /* 00-07 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 08-0f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 10-17 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 18-1f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 20-27 */ FLAG, OTHER, OTHER, FLAG, DOLLAR, OTHER, OTHER, OTHER, /* 28-2f */ OTHER, OTHER, STAR, FLAG, OTHER, FLAG, DOT, OTHER, /* 30-37 */ ZERO, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, /* 38-3f */ DIGIT, DIGIT, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 40-47 */ OTHER, OTHER, OTHER, OTHER, SPEC, SPEC, OTHER, SPEC, /* 48-4f */ OTHER, OTHER, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC, /* 50-57 */ OTHER, OTHER, OTHER, OTHER, OTHER, SPEC, OTHER, SPEC, /* 58-5f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 60-67 */ OTHER, OTHER, OTHER, SPEC, SPEC, SPEC, SPEC, SPEC, /* 68-6f */ MODFR, SPEC, OTHER, OTHER, MODFR, OTHER, OTHER, SPEC, /* 70-77 */ SPEC, MODFR, OTHER, SPEC, OTHER, SPEC, OTHER, OTHER, /* 78-7f */ SPEC, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 80-87 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 88-8f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 90-97 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* 98-9f */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* a0-a7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* a8-af */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* b0-b7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* b8-bf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* c0-c7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* c8-cf */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* d0-d7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* d8-df */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* e0-e7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* e8-ef */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* f0-f7 */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, /* f8-ff */ OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER, OTHER,};const static STATE state_table[MAX_STATE][MAX_CH_CLASS] = { /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */ /* START */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE }, /* SFLAG */ { SFLAG, WDIG, DONE, SMOD, DONE, SDOT, VARW, SFLAG, DONE }, /* WDIG */ { DONE, DONE, WIDTH, SMOD, DONE, SDOT, DONE, DONE, DONE }, /* WIDTH */ { DONE, DONE, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE }, /* SMOD */ { DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE, DONE }, /* SDOT */ { SDOT, PREC, DONE, SMOD, DONE, DONE, VARP, DONE, DONE }, /* VARW */ { DONE, VWDIG, DONE, SMOD, DONE, SDOT, DONE, DONE, DONE }, /* VARP */ { DONE, VPDIG, DONE, SMOD, DONE, DONE, DONE, DONE, DONE }, /* PREC */ { DONE, DONE, DONE, SMOD, DONE, DONE, DONE, DONE, DONE }, /* VWDIG */ { DONE, DONE, WIDTH, DONE, DONE, DONE, DONE, DONE, DONE }, /* VPDIG */ { DONE, DONE, PREC, DONE, DONE, DONE, DONE, DONE, DONE },};const static ACTION action_table[MAX_STATE][MAX_CH_CLASS] = { /* '0' '1-9' '$' MODFR SPEC '.' '*' FLAG OTHER */ /* START */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP }, /* SFLAG */ { NOOP, NUMBER, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP }, /* WDIG */ { NOOP, NOOP, GETPOS, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP }, /* WIDTH */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP }, /* SMOD */ { NOOP, NOOP, NOOP, NOOP, GETARG, NOOP, NOOP, NOOP, NOOP }, /* SDOT */ { NOOP, SKIPNUM, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP }, /* VARW */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, GETPW, NOOP, NOOP, NOOP }, /* VARP */ { NOOP, NUMBER, NOOP, GETPW, GETPWB, NOOP, NOOP, NOOP, NOOP }, /* PREC */ { NOOP, NOOP, NOOP, GETMOD, GETARG, NOOP, NOOP, NOOP, NOOP }, /* VWDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP }, /* VPDIG */ { NOOP, NOOP, PWPOS, NOOP, NOOP, NOOP, NOOP, NOOP, NOOP },};/* function to get positional parameter N where n = N - 1 */static union arg_val *get_arg (int n, char *fmt, va_list *ap, int *numargs_p, union arg_val *args, int *arg_type, char **last_fmt) { int ch; wchar_t wc; int nbytes, number, flags; int spec_type; int numargs = *numargs_p; CH_CLASS chtype; STATE state, next_state; ACTION action; int pos, last_arg; mbstate_t wc_state; int max_pos_arg = n; enum types { INT, LONG_INT, SHORT_INT, QUAD_INT, CHAR, CHAR_PTR, DOUBLE, LONG_DOUBLE }; /* if this isn't the first call, pick up where we left off last time */ if (*last_fmt != NULL) fmt = *last_fmt; memset (&wc_state, '\0', sizeof (wc_state)); /* we need to process either to end of fmt string or until we have actually read the desired parameter from the vararg list. */ while (*fmt && n >= numargs) { while ((nbytes = _mbtowc_r(_REENT, &wc, fmt, MB_CUR_MAX, &wc_state)) > 0) { fmt += nbytes; if (wc == '%') break; } if (nbytes <= 0) break; state = START; flags = 0; pos = -1; number = 0; spec_type = INT; /* Use state/action table to process format specifiers. We ignore invalid formats and we are only interested in information that tells us how to read the vararg list. */ while (state != DONE) { ch = *fmt++; chtype = chclass[ch]; next_state = state_table[state][chtype]; action = action_table[state][chtype]; state = next_state; switch (action) { case GETMOD: /* we have format modifier */ switch (ch) { case 'h': flags |= SHORTINT; break; case 'L': flags |= LONGDBL; break; case 'q': flags |= QUADINT; break; case 'l': default: if (*fmt == 'l') { flags |= QUADINT; ++fmt; } else flags |= LONGINT; break; } break; case GETARG: /* we have format specifier */ { numargs &= (MAX_POS_ARGS - 1); /* process the specifier and translate it to a type to fetch from varargs */ switch (ch) { case 'd': case 'i': case 'o': case 'x': case 'X': case 'u': if (flags & LONGINT) spec_type = LONG_INT; else if (flags & SHORTINT) spec_type = SHORT_INT;#ifndef _NO_LONG_LONG else if (flags & QUADINT) spec_type = QUAD_INT;#endif else spec_type = INT; break; case 'D': case 'U': case 'O': spec_type = LONG_INT; break; case 'f': case 'g': case 'G': case 'E': case 'e':#ifndef _NO_LONGDBL if (flags & LONGDBL) spec_type = LONG_DOUBLE; else#endif spec_type = DOUBLE; break; case 's': case 'p': spec_type = CHAR_PTR; break; case 'c': spec_type = CHAR; break; } /* if we have a positional parameter, just store the type, otherwise fetch the parameter from the vararg list */ if (pos != -1) arg_type[pos] = spec_type; else { switch (spec_type) { case LONG_INT: args[numargs++].val_long = va_arg(*ap, long); break; case QUAD_INT: args[numargs++].val_quad_t = va_arg(*ap, quad_t); break; case CHAR: case SHORT_INT: case INT: args[numargs++].val_int = va_arg(*ap, int); break; case CHAR_PTR: args[numargs++].val_char_ptr_t = va_arg(*ap, char *); break; case DOUBLE: args[numargs++].val_double = va_arg(*ap, double); break; case LONG_DOUBLE: args[numargs++].val__LONG_DOUBLE = va_arg(*ap, _LONG_DOUBLE); break; } } } break; case GETPOS: /* we have positional specifier */ if (arg_type[0] == -1) memset (arg_type, 0, sizeof(int) * MAX_POS_ARGS); pos = number - 1; max_pos_arg = (max_pos_arg > pos ? max_pos_arg : pos); break; case PWPOS: /* we have positional specifier for width or precision */ if (arg_type[0] == -1) memset (arg_type, 0, sizeof(int) * MAX_POS_ARGS); number -= 1; arg_type[number] = INT; max_pos_arg = (max_pos_arg > number ? max_pos_arg : number); break; case GETPWB: /* we require format pushback */ --fmt; /* fallthrough */ case GETPW: /* we have a variable precision or width to acquire */ args[numargs++].val_int = va_arg(*ap, int); break; case NUMBER: /* we have a number to process */ number = (ch - '0'); while ((ch = *fmt) != '\0' && is_digit(ch)) { number = number * 10 + (ch - '0'); ++fmt; } break; case SKIPNUM: /* we have a number to skip */ while ((ch = *fmt) != '\0' && is_digit(ch)) ++fmt; break; case NOOP: default: break; /* do nothing */ } } } /* process all arguments up to at least the one we are looking for and if we have seen the end of the string, then process up to the max argument needed */ if (*fmt == '\0') last_arg = max_pos_arg; else last_arg = n; while (numargs <= last_arg) { switch (arg_type[numargs]) { case LONG_INT: args[numargs++].val_long = va_arg(*ap, long); break; case QUAD_INT: args[numargs++].val_quad_t = va_arg(*ap, quad_t); break; case CHAR_PTR: args[numargs++].val_char_ptr_t = va_arg(*ap, char *); break; case DOUBLE: args[numargs++].val_double = va_arg(*ap, double); break; case LONG_DOUBLE: args[numargs++].val__LONG_DOUBLE = va_arg(*ap, _LONG_DOUBLE); break; case INT: case SHORT_INT: case CHAR: default: args[numargs++].val_int = va_arg(*ap, int); break; } } /* alter the global numargs value and keep a reference to the last bit of the fmt string we processed here because the caller will continue processing where we started */ *numargs_p = numargs; *last_fmt = fmt; return &args[n];}#endif /* !_NO_POS_ARGS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -