doprnt.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,011 行 · 第 1/2 页
C
1,011 行
#ifndef lintstatic char *sccsid = "@(#)doprnt.c 4.3 (ULTRIX) 9/10/90";#endif not lint/* ------------------------------------------------------------------ *//* | Copyright Unpublished, MIPS Computer Systems, Inc. All Rights | *//* | Reserved. This software contains proprietary and confidential | *//* | information of MIPS and its suppliers. Use, disclosure or | *//* | reproduction is prohibited without the prior express written | *//* | consent of MIPS. | *//* ------------------------------------------------------------------ *//* $Header: doprnt.c,v 1.1 87/02/16 11:19:12 dce Exp $ *//* * Modification History * * 009 1990-Sep-07, Mike Thomas * DECwest ANSI - remove change 008 * * 008 1990-Aug-23, Mike Thomas * DECwest ANSI - change _flsbuf to __flsbuf for ANSI. * * 007 1990-Aug-22, Dan Smith * Handle short modifier (%h) correctly * * 006 1990-Jul-5, Krishna Varikooty * Added code to omit precision if a negative precision argument * was specified (ANSI C requirement). * * 005 1990-Mar-1, Dan Smith * Added code to override zero flag when precision is specified. * * 004 1989-Dec-01, Reeves * Added eputc function to deal correctly with error returns. * * 003 1989-Jun-14, Reeves * Add ANSI-mandated %p format (treated as %08x), L length modifier * (treated as synonym for l), and %n (output length so far). * * 002 1989-Jun-08, Reeves * Remove excess fwrite declaration, as it conflicts with the new * ANSI standard. * * 001 1988-Sep-19, Jon Reeves * Add _lc_radix internationalization code. * Add undocumented, useless D, O, U format codes for compatibility. * (These duplicate the standard d, o, u formats; for some strange * reason, there is no F.) * Also i and I; i is in ANSI for scanf compatibility, I is useless * like D, O, U. *//* * _doprnt: common code for printf, fprintf, sprintf */#include <stdio.h>#include <ctype.h>#include <varargs.h>#include <values.h>#if defined(mips) && !defined(MOXIE)#include <fp_class.h>#endif#include "print.h"#define eputc(x,p) \ if (--(p)->_cnt>=0) \ *(p)->_ptr++=(x); \ else \ if (_flsbuf((unsigned char)(x),p) == EOF) \ return EOF/* * _NFILE is no longer defined (4.3 allocates FILE structures dynamically). * We define it as 64 here, but that may not be correct. */#ifndef _NFILE#define _NFILE 64#endif#define NDIG 82extern char _lc_radix;static char buffer[NDIG+2];static char *cvt (argsp, ndigits, decpt, sign, f_flag, fp_classp, is_zerop) va_list *argsp; int ndigits, *sign, f_flag; register int *decpt; int *fp_classp, *is_zerop;{ double value;#if defined(mips) && !defined(MOXIE) int fp_class;#endif value = va_arg(*argsp, double);#if defined(mips) && !defined(MOXIE) fp_class = fp_class_d(value); *fp_classp = fp_class; *is_zerop = (value == 0.0); if (fp_class == FP_QNAN || fp_class == FP_SNAN) { *sign = 0; *decpt = strlen("NaN"); strcpy(buffer, "NaN"); return(buffer); } if (fp_class == FP_POS_INF || fp_class == FP_NEG_INF) { *decpt = strlen("Infinity"); strcpy(buffer, "Infinity"); return(buffer); }#endif if (!f_flag) { if (ndigits > 17) { register char *p, *e; *decpt = _dtoa (buffer, 17, value, 0) + 1; for (p = buffer+18, e = buffer + 1 + (ndigits > NDIG ? NDIG : ndigits); p != e; ) *p++ = '0'; *p++ = '\0'; } else if (ndigits <= 0) { *decpt = _dtoa (buffer, 1, value, 0) + 1; buffer[1] = '\0'; } else { *decpt = _dtoa (buffer, ndigits, value, 0) + 1; } *sign = buffer[0] == '-'; return buffer+1; } else { *decpt = _dtoa (buffer, ndigits, value, 1) + 1; *sign = buffer[0] == '-'; return buffer+1; }}#ifdef notdef#define PUT(p, n) { register char *newbufptr; \ if ((newbufptr = bufptr + n) > bufferend) { \ _dowrite(p, n, iop, &bufptr); \ } else { \ (void) memcpy((char *) bufptr, p, n); \ bufptr = newbufptr; \ } \ }#define PAD(s, n) { register int nn; \ for (nn = n; nn > 20; nn -= 20) \ _dowrite(s, 20, iop, &bufptr); \ PUT(s, nn); \ }#endif#define PUT(p, n) { register int nn, cc; \ for (nn = 0; nn < n; nn++) { \ cc = *(p+nn); \ eputc(cc, iop); \ } \ }#define PAD(s, n) { register int nn, cc; \ cc = *s; \ for (nn = n; nn > 0; nn--) { \ eputc (cc, iop); \ } \ }/* bit positions for flags used in doprnt */#define LENGTH 1 /* l */#define FPLUS 2 /* + */#define FMINUS 4 /* - */#define FBLANK 8 /* blank */#define FSHARP 16 /* # */#define PADZERO 32 /* padding zeroes requested via '0' */#define DOTSEEN 64 /* dot appeared in format specification */#define SUFFIX 128 /* a suffix is to appear in the output */#define RZERO 256 /* there will be trailing zeros in output */#define LZERO 512 /* there will be leading zeroes in output */#define DOTSEENFMINUS 1024 /* a minus was seen after a dot */#define SHORT 2048 /* a short modifier was seen *//* * C-Library routines for floating conversion */static char *_bufendtab[_NFILE+1];static int_lowdigit(valptr)long *valptr;{ /* This function computes the decimal low-order digit of the number */ /* pointed to by valptr, and returns this digit after dividing */ /* *valptr by ten. This function is called ONLY to compute the */ /* low-order digit of a long whose high-order bit is set. */ int lowbit = *valptr & 1; long value = (*valptr >> 1) & ~HIBITL; *valptr = value / 5; return(value % 5 * 2 + lowbit + '0');}#ifdef notdef/* The function _dowrite carries out buffer pointer bookkeeping surrounding *//* a call to fwrite. It is called only when the end of the file output *//* buffer is approached or in other unusual situations. */static_dowrite(p, n, iop, ptrptr)register char *p;register int n;register FILE *iop;register char **ptrptr;{ if (iop->_file != _NFILE) { iop->_cnt -= (*ptrptr - iop->_ptr); iop->_ptr = *ptrptr; _bufsync(iop); (void) fwrite(p, 1, n, iop); *ptrptr = iop->_ptr; } else *ptrptr = memcpy((char *) *ptrptr, p, n) + n;}#endifint_doprnt(format, args, iop)register char *format;va_list args;register FILE *iop;{ static char _blanks[] = " "; static char _zeroes[] = "00000000000000000000"; /* bufptr is used inside of doprnt instead of iop->_ptr; */ /* bufferend is a copy of _bufend(iop), if it exists. For */ /* dummy file descriptors (iop->_file = _NFILE), bufferend */ /* may be meaningless. */ char *bufptr, *bufferend; /* This variable counts output characters. */ int count = 0; /* Starting and ending points for value to be printed */ register char *bp; char *p; /* Field width and precision */ int width, prec; /* Format code */ register int fcode; /* Number of padding zeroes required on the left and right */ int lzero, rzero; /* Flags - bit positions defined by LENGTH, FPLUS, FMINUS, FBLANK, */ /* and FSHARP are set if corresponding character is in format */ /* Bit position defined by PADZERO means extra space in the field */ /* should be padded with leading zeroes rather than with blanks */ register int flagword; /* Values are developed in this buffer */ char buf[max(MAXDIGS, 1+max(MAXFCVT+MAXEXP, MAXECVT))]; /* Pointer to sign, "0x", "0X", or empty */ char *prefix; /* Exponent or empty */ char *suffix; /* Buffer to create exponent */ char expbuf[MAXESIZ + 1]; /* Length of prefix and of suffix */ int prefixlength, suffixlength; /* combined length of leading zeroes, trailing zeroes, and suffix */ int otherlength; /* The value being converted, if integer */ long val; /* Output values from fcvt and ecvt */ int decpt, sign, is_zero; /* Pointer to a translate table for digits of whatever radix */ char *tab; /* Work variables */ int k, lradix, mradix; /* class of floating point value */ int fp_class; /* pointer to %n output value */ int *np; /* pointer to %hn and %ln output values respectively */ short *snp; long *lnp; /* initialize buffer pointer and buffer end pointer */ { register int fno = iop->_file; bufptr = iop->_ptr; bufferend = (fno == _NFILE) ? (char *)((long) bufptr | (-1L & ~HIBITL)) : _bufendtab[fno]; } /* * The main loop -- this loop goes through one iteration * for each string of ordinary characters or format specification. */ for ( ; ; ) { register int n; while ((fcode = *format) != '\0' && fcode != '%') { eputc(fcode, iop); format++; count++; }#ifdef notdef if ((fcode = *format) != '\0' && fcode != '%') { bp = format; do { format++; } while ((fcode = *format) != '\0' && fcode != '%'); count += (n = format - bp); /* n = no. of non-% chars */ PUT(bp, n); }#endif if (fcode == '\0') { /* end of format; return */#ifdef notdef register int nn = bufptr - iop->_ptr; iop->_cnt -= nn; iop->_ptr = bufptr; if (bufptr + iop->_cnt > bufferend && /* in case of */ iop->_file != _NFILE) /* interrupt */ _bufsync(iop); /* during last several lines */ if (iop->_flag & (_IONBF | _IOLBF) && (iop->_flag & _IONBF || memchr((char *)(bufptr-count), '\n', count) != NULL)) (void) _xflsbuf(iop);#endif return(ferror(iop) ? EOF : count); } /* * % has been found. * The following switch is used to parse the format * specification and to perform the operation specified * by the format letter. The program repeatedly goes * back to this switch until the format letter is * encountered. */ width = prefixlength = otherlength = flagword = 0; format++; charswitch: switch (fcode = *format++) { case '+': flagword |= FPLUS; goto charswitch; case '-': if (flagword & DOTSEEN) flagword |= DOTSEENFMINUS; else flagword |= FMINUS; goto charswitch; case ' ': flagword |= FBLANK; goto charswitch; case '#': flagword |= FSHARP; goto charswitch; /* Scan the field width and precision */ case '.': flagword |= DOTSEEN; prec = 0; goto charswitch; case '*': if (!(flagword & DOTSEEN)) { width = va_arg(args, int); if (width < 0) { width = -width; flagword ^= FMINUS; } } else { prec = va_arg(args, int); if (prec < 0) flagword ^= DOTSEEN; } goto charswitch; case '0': /* obsolescent spec: leading zero in width */ /* means pad with leading zeros */ if (!(flagword & (DOTSEEN | FMINUS))) flagword |= PADZERO; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { register num = fcode - '0'; while (isdigit(fcode = *format)) { num = num * 10 + fcode - '0'; format++; } if (flagword & DOTSEEN) if (flagword & DOTSEENFMINUS) { flagword ^= DOTSEEN; } else prec = num; else width = num; goto charswitch; } /* Scan the length modifier */ case 'l': case 'L': flagword |= LENGTH; goto charswitch; case 'h': flagword |= SHORT; goto charswitch; /* * The character addressed by format must be * the format letter -- there is nothing * left for it to be. * * The status of the +, -, #, and blank * flags are reflected in the variable * "flagword". "width" and "prec" contain * numbers corresponding to the digit * strings before and after the decimal * point, respectively. If there was no * decimal point, then flagword & DOTSEEN * is false and the value of prec is meaningless. * * The following switch cases set things up * for printing. What ultimately gets * printed will be padding blanks, a * prefix, left padding zeroes, a value, * right padding zeroes, a suffix, and * more padding blanks. Padding blanks * will not appear simultaneously on both * the left and the right. Each case in * this switch will compute the value, and * leave in several variables the informa- * tion necessary to construct what is to * be printed. * * The prefix is a sign, a blank, "0x", * "0X", or null, and is addressed by * "prefix". * * The suffix is either null or an * exponent, and is addressed by "suffix". * If there is a suffix, the flagword bit * SUFFIX will be set. * * The value to be printed starts at "bp" * and continues up to and not including * "p". * * "lzero" and "rzero" will contain the * number of padding zeroes required on * the left and right, respectively. * The flagword bits LZERO and RZERO tell * whether padding zeros are required. * * The number of padding blanks, and * whether they go on the left or the * right, will be computed on exit from * the switch. */ /* * decimal fixed point representations * * HIBITL is 100...000
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?