📄 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; else if (flags & CHARINT) *GET_ARG (N, ap, char_ptr_t) = ret; else *GET_ARG (N, ap, int_ptr_t) = ret; continue; /* no output */ case 'O': 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 = (u_long)(unsigned _POINTER_INT)GET_ARG (N, ap, void_ptr_t); base = HEX; xdigs = "0123456789abcdef"; flags |= HEXPREFIX; ch = 'x'; goto nosign; case 's': case 'S': sign = '\0'; if ((cp = GET_ARG (N, ap, char_ptr_t)) == NULL) { cp = "(null)"; size = 6; } else 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 ((malloc_buf = (char *)_malloc_r (data, size + 1)) == NULL) { fp->_flags |= __SERR; goto error; } /* Convert widechar string to multibyte string. */ memset ((_PTR)&ps, '\0', sizeof (mbstate_t)); if (_wcsrtombs_r (data, malloc_buf, &wcp, size, &ps) != size) { fp->_flags |= __SERR; goto error; } cp = malloc_buf; cp[size] = '\0'; } else 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': 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) 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. * * 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 (_fpvalue == 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); if(expt || ndig) { 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 (_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 */ 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#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)#endif#ifdef _NO_LONGDBLstatic char *_DEFUN(cvt, (data, value, ndigits, flags, sign, decpt, ch, length), struct _reent *data _AND double value _AND int ndigits _AND int flags _AND char *sign _AND int *decpt _AND int ch _AND int *length)#elsestatic char *_DEFUN(cvt, (data, value, ndigits, flags, sign, decpt, ch, length), struct _reent *data _AND _LONG_DOUBLE value _AND int ndigits _AND int flags _AND char *sign _AND int *decpt _AND int ch _AND int *length)#endif{ int mode, dsgn; char *digits, *bp, *rve;#ifdef _NO_LONGDBL union double_union tmp;#else union { struct ldieee ieee; _LONG_DOUBLE val; } ld;#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 */ ld.val = value; if (ld.ieee.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 int_DEFUN(exponent, (p0, exp, fmtch), char *p0 _AND int exp _AND int 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -