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 + -
显示快捷键?