📄 vfprintf.c
字号:
? args[numargs++].val_##type = va_arg (ap, type) \ : va_arg (ap, type))))#else# define GET_ARG(n, ap, type) (va_arg (ap, type))#endif /* * To extend shorts properly, we need both signed and unsigned * argument extraction methods. */#ifndef _NO_LONGLONG#define SARG() \ (flags&QUADINT ? GET_ARG (N, ap, quad_t) : \ flags&LONGINT ? GET_ARG (N, ap, long) : \ flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \ flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \ (long)GET_ARG (N, ap, int))#define UARG() \ (flags&QUADINT ? GET_ARG (N, ap, u_quad_t) : \ flags&LONGINT ? GET_ARG (N, ap, u_long) : \ flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \ flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \ (u_long)GET_ARG (N, ap, u_int))#else#define SARG() \ (flags&LONGINT ? GET_ARG (N, ap, long) : \ flags&SHORTINT ? (long)(short)GET_ARG (N, ap, int) : \ flags&CHARINT ? (long)(signed char)GET_ARG (N, ap, int) : \ (long)GET_ARG (N, ap, int))#define UARG() \ (flags&LONGINT ? GET_ARG (N, ap, u_long) : \ flags&SHORTINT ? (u_long)(u_short)GET_ARG (N, ap, int) : \ flags&CHARINT ? (u_long)(unsigned char)GET_ARG (N, ap, int) : \ (u_long)GET_ARG (N, ap, u_int))#endif CHECK_INIT (data, fp); _flockfile (fp); /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ if (cantwrite (data, fp)) { _funlockfile (fp); return (EOF); } /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) { _funlockfile (fp); return (__sbprintf (data, fp, fmt0, ap)); } fmt = (char *)fmt0; uio.uio_iov = iovp = iov; uio.uio_resid = 0; uio.uio_iovcnt = 0; ret = 0;#ifndef _NO_POS_ARGS arg_index = 0; saved_fmt = NULL; arg_type[0] = -1; numargs = 0; is_pos_arg = 0;#endif /* * Scan the format for conversions (`%' character). */ for (;;) { cp = fmt;#ifdef _MB_CAPABLE while ((n = _mbtowc_r (data, &wc, fmt, MB_CUR_MAX, &state)) > 0) { if (wc == '%') break; fmt += n; }#else while (*fmt != '\0' && *fmt != '%') fmt += 1;#endif if ((m = fmt - cp) != 0) { PRINT (cp, m); ret += m; }#ifdef _MB_CAPABLE if (n <= 0) goto done;#else if (*fmt == '\0') goto done;#endif fmt_anchor = fmt; fmt++; /* skip over '%' */ flags = 0; dprec = 0; width = 0; prec = -1; sign = '\0';#ifndef _NO_POS_ARGS N = arg_index; is_pos_arg = 0;#endifrflag: ch = *fmt++;reswitch: switch (ch) {#ifdef _WANT_IO_C99_FORMATS case '\'': /* The ' flag is required by POSIX, but not C99. In the C locale, LC_NUMERIC requires thousands_sep to be the empty string. And since no other locales are supported (yet), this flag is currently a no-op. */ goto rflag;#endif case ' ': /* * ``If the space and + flags both appear, the space * flag will be ignored.'' * -- ANSI X3J11 */ if (!sign) sign = ' '; goto rflag; case '#': flags |= ALT; goto rflag; case '*':#ifndef _NO_POS_ARGS /* we must check for positional arg used for dynamic width */ n = N; old_is_pos_arg = is_pos_arg; is_pos_arg = 0; if (is_digit (*fmt)) { char *old_fmt = fmt; n = 0; ch = *fmt++; do { n = 10 * n + to_digit (ch); ch = *fmt++; } while (is_digit (ch)); if (ch == '$') { if (n <= MAX_POS_ARGS) { n -= 1; is_pos_arg = 1; } else goto error; } else { fmt = old_fmt; goto rflag; } }#endif /* !_NO_POS_ARGS */ /* * ``A negative field width argument is taken as a * - flag followed by a positive field width.'' * -- ANSI X3J11 * They don't exclude field widths read from args. */ width = GET_ARG (n, ap, int);#ifndef _NO_POS_ARGS is_pos_arg = old_is_pos_arg;#endif if (width >= 0) goto rflag; width = -width; /* FALLTHROUGH */ case '-': flags |= LADJUST; goto rflag; case '+': sign = '+'; goto rflag; case '.': if ((ch = *fmt++) == '*') {#ifndef _NO_POS_ARGS /* we must check for positional arg used for dynamic width */ n = N; old_is_pos_arg = is_pos_arg; is_pos_arg = 0; if (is_digit (*fmt)) { char *old_fmt = fmt; n = 0; ch = *fmt++; do { n = 10 * n + to_digit (ch); ch = *fmt++; } while (is_digit (ch)); if (ch == '$') { if (n <= MAX_POS_ARGS) { n -= 1; is_pos_arg = 1; } else goto error; } else { fmt = old_fmt; goto rflag; } }#endif /* !_NO_POS_ARGS */ prec = GET_ARG (n, ap, int);#ifndef _NO_POS_ARGS is_pos_arg = old_is_pos_arg;#endif if (prec < 0) prec = -1; goto rflag; } n = 0; while (is_digit (ch)) { n = 10 * n + to_digit (ch); ch = *fmt++; } prec = n < 0 ? -1 : n; goto reswitch; case '0': /* * ``Note that 0 is taken as a flag, not as the * beginning of a field width.'' * -- ANSI X3J11 */ flags |= ZEROPAD; 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));#ifndef _NO_POS_ARGS if (ch == '$') { if (n <= MAX_POS_ARGS) { N = n - 1; is_pos_arg = 1; goto rflag; } else goto error; }#endif /* !_NO_POS_ARGS */ width = n; goto reswitch;#ifdef FLOATING_POINT case 'L': flags |= LONGDBL; goto rflag;#endif case 'h':#ifdef _WANT_IO_C99_FORMATS if (*fmt == 'h') { fmt++; flags |= CHARINT; } else#endif flags |= SHORTINT; goto rflag; case 'l':#if defined _WANT_IO_C99_FORMATS || !defined _NO_LONGLONG if (*fmt == 'l') { fmt++; flags |= QUADINT; } else#endif flags |= LONGINT; goto rflag; case 'q': /* extension */ flags |= QUADINT; goto rflag;#ifdef _WANT_IO_C99_FORMATS case 'j': if (sizeof (intmax_t) == sizeof (long)) flags |= LONGINT; else flags |= QUADINT; goto rflag; case 'z': if (sizeof (size_t) < sizeof (int)) /* POSIX states size_t is 16 or more bits, as is short. */ flags |= SHORTINT; else if (sizeof (size_t) == sizeof (int)) /* no flag needed */; else if (sizeof (size_t) <= sizeof (long)) flags |= LONGINT; else /* POSIX states that at least one programming environment must support size_t no wider than long, but that means other environments can have size_t as wide as long long. */ flags |= QUADINT; goto rflag; case 't': if (sizeof (ptrdiff_t) < sizeof (int)) /* POSIX states ptrdiff_t is 16 or more bits, as is short. */ flags |= SHORTINT; else if (sizeof (ptrdiff_t) == sizeof (int)) /* no flag needed */; else if (sizeof (ptrdiff_t) <= sizeof (long)) flags |= LONGINT; else /* POSIX states that at least one programming environment must support ptrdiff_t no wider than long, but that means other environments can have ptrdiff_t as wide as long long. */ flags |= QUADINT; goto rflag; case 'C':#endif /* _WANT_IO_C99_FORMATS */ case 'c': cp = buf;#ifdef _MB_CAPABLE if (ch == 'C' || (flags & LONGINT)) { mbstate_t ps; memset ((_PTR)&ps, '\0', sizeof (mbstate_t)); if ((size = (int)_wcrtomb_r (data, cp, (wchar_t)GET_ARG (N, ap, wint_t), &ps)) == -1) { fp->_flags |= __SERR; goto error; } } else#endif /* _MB_CAPABLE */ { *cp = GET_ARG (N, ap, int); size = 1; } sign = '\0'; break; case 'D': /* extension */ flags |= LONGINT; /*FALLTHROUGH*/ case 'd': case 'i': _uquad = SARG ();#ifndef _NO_LONGLONG if ((quad_t)_uquad < 0)#else if ((long) _uquad < 0)#endif { _uquad = -_uquad; sign = '-'; } base = DEC; goto number;#ifdef FLOATING_POINT# ifdef _WANT_IO_C99_FORMATS case 'a': case 'A': case 'F':# endif case 'e': case 'E': case 'f': case 'g': case 'G':# ifdef _NO_LONGDBL if (flags & LONGDBL) { _fpvalue = (double) GET_ARG (N, ap, _LONG_DOUBLE); } else { _fpvalue = GET_ARG (N, ap, double); } /* do this before tricky precision changes If the output is infinite or NaN, leading zeros are not permitted. Otherwise, scanf could not read what printf wrote. */ if (isinf (_fpvalue)) { if (_fpvalue < 0) sign = '-'; if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */ cp = "INF"; else cp = "inf"; size = 3; flags &= ~ZEROPAD; break; } if (isnan (_fpvalue)) { if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */ cp = "NAN"; else cp = "nan"; size = 3; flags &= ~ZEROPAD; break; }# else /* !_NO_LONGDBL */ if (flags & LONGDBL) { _fpvalue = GET_ARG (N, ap, _LONG_DOUBLE); } else { _fpvalue = (_LONG_DOUBLE)GET_ARG (N, ap, double); } /* do this before tricky precision changes */ expt = _ldcheck (&_fpvalue); if (expt == 2) { if (_fpvalue < 0) sign = '-'; if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */ cp = "INF"; else cp = "inf"; size = 3; flags &= ~ZEROPAD; break; } if (expt == 1) { if (ch <= 'G') /* 'A', 'E', 'F', or 'G' */ cp = "NAN"; else cp = "nan"; size = 3; flags &= ~ZEROPAD; break; }# endif /* !_NO_LONGDBL */# ifdef _WANT_IO_C99_FORMATS if (ch == 'a' || ch == 'A') { ox[0] = '0'; ox[1] = ch == 'a' ? 'x' : 'X'; flags |= HEXPREFIX; if (prec >= BUF) { if ((malloc_buf = (char *)_malloc_r (data, prec + 1)) == NULL) { fp->_flags |= __SERR; goto error; } cp = malloc_buf; } else cp = buf; } else# endif /* _WANT_IO_C99_FORMATS */ if (prec == -1) { prec = DEFPREC; } else if ((ch == 'g' || ch == 'G') && prec == 0) { prec = 1; } flags |= FPT; cp = cvt (data, _fpvalue, prec, flags, &softsign, &expt, ch, &ndig, cp); if (ch == 'g' || ch == 'G') { if (expt <= -4 || expt > prec) ch -= 2; /* 'e' or 'E' */ else ch = 'g'; }# ifdef _WANT_IO_C99_FORMATS else if (ch == 'F') ch = 'f';# endif if (ch <= 'e') { /* 'a', 'A', 'e', or 'E' fmt */ --expt; expsize = exponent (expstr, expt, ch); size = expsize + ndig; if (ndig > 1 || flags & ALT) ++size; } else if (ch == 'f') { /* f fmt */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -