📄 vfprintf.c
字号:
uio.uio_resid += (len); \ iovp++; \ if (++uio.uio_iovcnt >= NIOV) { \ if (__sprint_r(data, fp, &uio)) \ goto error; \ iovp = iov; \ } \}#define PAD(howmany, with) { \ if ((n = (howmany)) > 0) { \ while (n > PADSIZE) { \ PRINT (with, PADSIZE); \ n -= PADSIZE; \ } \ PRINT (with, n); \ } \}#define FLUSH() { \ if (uio.uio_resid && __sprint_r(data, fp, &uio)) \ goto error; \ uio.uio_iovcnt = 0; \ iovp = iov; \} /* Macros to support positional arguments */#ifndef _NO_POS_ARGS#define GET_ARG(n, ap, type) \ ( is_pos_arg \ ? n < numargs \ ? args[n].val_##type \ : get_arg (data, n, fmt_anchor, &ap, &numargs, args, arg_type, &saved_fmt)->val_##type \ : arg_index++ < numargs \ ? args[n].val_##type \ : numargs < MAX_POS_ARGS \ ? 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 (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; arg_index = 0;#ifndef _NO_POS_ARGS 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'; N = arg_index;#ifndef _NO_POS_ARGS is_pos_arg = 0;#endifrflag: ch = *fmt++;reswitch: switch (ch) { case '\'': /* 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; 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 '*': n = N;#ifndef _NO_POS_ARGS /* we must check for positional arg used for dynamic width */ 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++) == '*') { n = N;#ifndef _NO_POS_ARGS /* we must check for positional arg used for dynamic width */ 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': if (*fmt == 'h') { fmt++; flags |= CHARINT; } else { flags |= SHORTINT; } goto rflag; case 'l': if (*fmt == 'l') { fmt++; flags |= QUADINT; } else { flags |= LONGINT; } goto rflag; case 'q': flags |= QUADINT; goto rflag; 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': case 'C': cp = buf; 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 { *cp = GET_ARG (N, ap, int); size = 1; } sign = '\0'; break; case 'D': 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 case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': if (prec == -1) { prec = DEFPREC; } else if ((ch == 'g' || ch == 'G') && prec == 0) { prec = 1; }#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 (isinf (_fpvalue)) { if (_fpvalue < 0) sign = '-'; if (ch == 'E' || ch == 'F' || ch == 'G') cp = "INF"; else cp = "inf"; size = 3; break; } if (isnan (_fpvalue)) { if (ch == 'E' || ch == 'F' || ch == 'G') cp = "NAN"; else cp = "nan"; size = 3; 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 */ tmp = _ldcheck (&_fpvalue); if (tmp == 2) { if (_fpvalue < 0) sign = '-'; if (ch == 'E' || ch == 'F' || ch == 'G') cp = "INF"; else cp = "inf"; size = 3; break; } if (tmp == 1) { if (ch == 'E' || ch == 'F' || ch == 'G') cp = "NAN"; else cp = "nan"; size = 3; break; }#endif /* !_NO_LONGDBL */ flags |= FPT; cp = cvt (data, _fpvalue, prec, flags, &softsign, &expt, ch, &ndig); if (ch == 'g' || ch == 'G') { if (expt <= -4 || expt > prec) ch = (ch == 'g') ? 'e' : 'E'; else ch = 'g'; } if (ch <= 'e') { /* '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 + -