📄 vfprintf.c
字号:
if (expt > 0) { size = expt; if (prec || flags & ALT) size += prec + 1; } else /* "0.X" */ size = (prec || flags & ALT) ? prec + 2 : 1; } else if (expt >= ndig) { /* fixed g fmt */ size = expt; if (flags & ALT) ++size; } else size = ndig + (expt > 0 ? 1 : 2 - expt); if (softsign) sign = '-'; break;#endif /* FLOATING_POINT */ case 'n':#ifndef _NO_LONGLONG if (flags & QUADINT) *GET_ARG (N, ap, quad_ptr_t) = ret; else #endif if (flags & LONGINT) *GET_ARG (N, ap, long_ptr_t) = ret; else if (flags & SHORTINT) *GET_ARG (N, ap, short_ptr_t) = ret;#ifdef _WANT_IO_C99_FORMATS else if (flags & CHARINT) *GET_ARG (N, ap, char_ptr_t) = ret;#endif else *GET_ARG (N, ap, int_ptr_t) = ret; continue; /* no output */ case 'O': /* extension */ flags |= LONGINT; /*FALLTHROUGH*/ case 'o': _uquad = UARG (); base = OCT; goto nosign; case 'p': /* * ``The argument shall be a pointer to void. The * value of the pointer is converted to a sequence * of printable characters, in an implementation- * defined manner.'' * -- ANSI X3J11 */ /* NOSTRICT */ _uquad = (uintptr_t) GET_ARG (N, ap, void_ptr_t); base = HEX; xdigs = "0123456789abcdef"; flags |= HEXPREFIX; ox[0] = '0'; ox[1] = ch = 'x'; goto nosign; case 's':#ifdef _WANT_IO_C99_FORMATS case 'S':#endif sign = '\0'; cp = GET_ARG (N, ap, char_ptr_t);#ifndef __OPTIMIZE_SIZE__ /* Behavior is undefined if the user passed a NULL string when precision is not 0. However, if we are not optimizing for size, we might as well mirror glibc behavior. */ if (cp == NULL) { cp = "(null)"; size = ((unsigned) prec > 6U) ? 6 : prec; } else#endif /* __OPTIMIZE_SIZE__ */#ifdef _MB_CAPABLE if (ch == 'S' || (flags & LONGINT)) { mbstate_t ps; _CONST wchar_t *wcp; wcp = (_CONST wchar_t *)cp; size = m = 0; memset ((_PTR)&ps, '\0', sizeof (mbstate_t)); /* Count number of bytes needed for multibyte string that will be produced from widechar string. */ if (prec >= 0) { while (1) { if (wcp[m] == L'\0') break; if ((n = (int)_wcrtomb_r (data, buf, wcp[m], &ps)) == -1) { fp->_flags |= __SERR; goto error; } if (n + size > prec) break; m += 1; size += n; if (size == prec) break; } } else { if ((size = (int)_wcsrtombs_r (data, NULL, &wcp, 0, &ps)) == -1) { fp->_flags |= __SERR; goto error; } wcp = (_CONST wchar_t *)cp; } if (size == 0) break; if (size >= BUF) { if ((malloc_buf = (char *)_malloc_r (data, size + 1)) == NULL) { fp->_flags |= __SERR; goto error; } cp = malloc_buf; } else cp = buf; /* Convert widechar string to multibyte string. */ memset ((_PTR)&ps, '\0', sizeof (mbstate_t)); if (_wcsrtombs_r (data, cp, &wcp, size, &ps) != size) { fp->_flags |= __SERR; goto error; } cp[size] = '\0'; } else#endif /* _MB_CAPABLE */ if (prec >= 0) { /* * can't use strlen; can only look for the * NUL in the first `prec' characters, and * strlen () will go further. */ char *p = memchr (cp, 0, prec); if (p != NULL) { size = p - cp; if (size > prec) size = prec; } else size = prec; } else size = strlen (cp); break; case 'U': /* extension */ flags |= LONGINT; /*FALLTHROUGH*/ case 'u': _uquad = UARG (); base = DEC; goto nosign; 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) { ox[0] = '0'; ox[1] = ch; 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; } } /* * ...result is to be converted to an 'alternate form'. * For o conversion, it increases the precision to force * the first digit of the result to be a zero." * -- ANSI X3J11 * * To demonstrate this case, compile and run: * printf ("%#.0o",0); */ else if (base == OCT && (flags & ALT)) *--cp = '0'; 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. * If flags&FPT, ch must be in [aAeEfg]. * * 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++; if (flags & HEXPREFIX) realsz+= 2; /* right-adjusting blank padding */ if ((flags & (LADJUST|ZEROPAD)) == 0) PAD (width - realsz, blanks); /* prefix */ if (sign) PRINT (&sign, 1); if (flags & HEXPREFIX) 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 (_fpvalue == 0) { /* kludge for __dtoa irregularity */ PRINT ("0", 1); if (expt < ndig || flags & ALT) { PRINT (decimal_point, 1); PAD (ndig - 1, zeroes); } } else if (expt <= 0) { PRINT ("0", 1); if (expt || ndig || flags & ALT) { 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 (decimal_point, 1); } else { PRINT (cp, expt); cp += expt; PRINT (decimal_point, 1); PRINT (cp, ndig - expt); } } else { /* 'a', 'A', 'e', or 'E' */ if (ndig > 1 || flags & ALT) { PRINT (cp, 1); cp++; PRINT (decimal_point, 1); if (_fpvalue) { PRINT (cp, ndig - 1); } else /* 0.[0..] */ /* __dtoa irregularity */ PAD (ndig - 1, zeroes); } else /* XeYYY */ PRINT (cp, 1); PRINT (expstr, expsize); } }#else /* !FLOATING_POINT */ 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 */ if (malloc_buf != NULL) { _free_r (data, malloc_buf); malloc_buf = NULL; } }done: FLUSH ();error: if (malloc_buf != NULL) _free_r (data, malloc_buf); _funlockfile (fp); return (__sferror (fp) ? EOF : ret); /* NOTREACHED */}#ifdef FLOATING_POINT/* Using reentrant DATA, convert finite VALUE into a string of digits with no decimal point, using NDIGITS precision and FLAGS as guides to whether trailing zeros must be included. Set *SIGN to nonzero if VALUE was negative. Set *DECPT to the exponent plus one. Set *LENGTH to the length of the returned string. CH must be one of [aAeEfFgG]; if it is [aA], then the return string lives in BUF, otherwise the return value shares the mprec reentrant storage. */static char *cvt(struct _reent *data, _PRINTF_FLOAT_TYPE value, int ndigits, int flags, char *sign, int *decpt, int ch, int *length, char *buf){ int mode, dsgn; char *digits, *bp, *rve;# ifdef _NO_LONGDBL union double_union tmp; tmp.d = value; if (word0 (tmp) & Sign_bit) { /* this will check for < 0 and -0.0 */ value = -value; *sign = '-'; } else *sign = '\000';# else /* !_NO_LONGDBL */ union { struct ldieee ieee; _LONG_DOUBLE val; } ld; ld.val = value; if (ld.ieee.sign) { /* this will check for < 0 and -0.0 */ value = -value; *sign = '-'; } else *sign = '\000';# endif /* !_NO_LONGDBL */# ifdef _WANT_IO_C99_FORMATS if (ch == 'a' || ch == 'A') { /* This code assumes FLT_RADIX is a power of 2. The initial division ensures the digit before the decimal will be less than FLT_RADIX (unless it is rounded later). There is no loss of precision in these calculations. */ value = FREXP (value, decpt) / 8; if (!value) *decpt = 1; digits = ch == 'a' ? "0123456789abcdef" : "0123456789ABCDEF"; bp = buf; do { value *= 16; mode = (int) value; value -= mode; *bp++ = digits[mode]; } while (ndigits-- && value); if (value > 0.5 || (value == 0.5 && mode & 1)) { /* round to even */ rve = bp; while (*--rve == digits[0xf]) { *rve = '0'; } *rve = *rve == '9' ? digits[0xa] : *rve + 1; } else { while (ndigits-- >= 0) { *bp++ = '0'; } } *length = bp - buf; return buf; }# endif /* _WANT_IO_C99_FORMATS */ if (ch == 'f' || 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 */ } digits = _DTOA_R (data, value, mode, ndigits, decpt, &dsgn, &rve); if ((ch != 'g' && ch != 'G') || flags & ALT) { /* Print trailing zeros */ bp = digits + ndigits; if (ch == 'f' || 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(char *p0, int exp, int fmtch){ register char *p, *t; char expbuf[MAXEXPLEN];# ifdef _WANT_IO_C99_FORMATS int isa = fmtch == 'a' || fmtch == 'A';# else# define isa 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -