⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 doprnt.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#if !defined(lint) && defined(SCCSIDS)static	char sccsid[] = "@(#)doprnt.c 1.1 92/07/30 SMI";#endif/* * Copyright (c) 1988 by Sun Microsystems, Inc. *//* *	_doprnt: common code for printf, fprintf, sprintf *	Floating-point code is included or not, depending *	on whether the preprocessor variable FLOAT is 1 or 0. */#define MAXARGS 50#ifndef FLOAT#define	FLOAT	1	/* YES! we want floating */#endif#include <stdio.h>#include <ctype.h>#include <varargs.h>#include <values.h>#include <locale.h>#include "doprnt.h"#include "stdiom.h"#define max(a,b)	((a) > (b) ? (a) : (b))#define min(a,b)	((a) < (b) ? (a) : (b))/* If this symbol is nonzero, allow '0' as a flag *//* If this symbol is nonzero, allow '0' as a flag */#define FZERO 1#if FLOAT/* *	libc/gen/common functions for floating-point conversion */#include <floatingpoint.h>extern void _fourdigitsquick();#endifvoid _mkarglst();void _getarg();static char *_check_dol();char *strchr();#define emitchar(c)   { if (--filecnt < 0) { \				register FILE *iop = file; \				if (((iop->_flag & (_IOLBF|_IONBF)) == 0 \				    || -filecnt >= iop->_bufsiz)) { \					iop->_ptr = fileptr; \					(void) _xflsbuf(iop); \					fileptr = iop->_ptr; \					filecnt = iop->_cnt; \					filecnt--; \				    } \			} \			*fileptr++ = (unsigned)(c); \			count++; \                      }static char *nullstr = "(null)";static char *lowerhex = "0123456789abcdef";static char *upperhex = "0123456789ABCDEF";/* stva_list is used to subvert C's restriction that a variable with an * array type can not appear on the left hand side of an assignment operator. * By putting the array inside a structure, the functionality of assigning to * the whole array through a simple assignment is achieved..*/typedef struct stva_list {	va_list ap;} stva_list;_doprnt(format, in_args, file)	char *format;	va_list in_args;	FILE *file;{	char convertbuffer[1024] ;		/* Current position in format */	register char *cp;	/* Starting and ending points for value to be printed */	register char *bp;	char *p;	/* Pointer and count for I/O buffer */	register unsigned char *fileptr;	register int filecnt;	/* Field width and precision */	int width;	register int prec;	/* Format code */	char fcode;	/* Number of padding zeroes required on the left */	int lzero;	/* Flags - nonzero if corresponding character appears in format */	bool fplus;		/* + */	bool fminus;		/* - */	bool fblank;		/* blank */	bool fsharp;		/* # */#if FZERO	bool fzero;		/* 0 */#endif	bool Lsize;             /* Capital L for size = long double = quadruple */	/* Pointer to sign, "0x", "0X", or empty */	char *prefix;	/* Scratch */	int nblank;#if FLOAT	/* Exponent or empty */	char *suffix;	/* Buffer to create exponent */	char expbuf[7];  /* "e+xxxx\0" */	/* Number of padding zeroes required on the right */	int rzero;	/* Length of exponent suffix. */	int suffixlength;	/* The value being converted, if real or quadruple */	double dval;	quadruple qval;	/* Output values from fconvert and econvert */	int decpt, sign;	/* Values are developed in this buffer */	char buf[1034];		/* Size of convertbuffer, plus some for exponent and sign. */	/* Current locale's decimal point */	char decpt_char = *(localeconv()->decimal_point);#else	/* Values are developed in this buffer */	char buf[MAXDIGS];#endif	/* The value being converted, if integer */	register unsigned long val;	/* Work variables */	register int n;	register char c;	char radix;	int svswitch = 0;	/* count of output characters */	register int count;	/* variables for positional parameters */	char    *sformat = format;      /* save the beginning of the format */	int     fpos = 1;               /* 1 if first positional parameter */	stva_list       args,   /* used to step through the argument list */			args_width, 	/* for width */			args_prec, 	/* for prec */			sargs;  /* used to save the start of the argument list */	stva_list       arglst[MAXARGS];/* array giving the approriate values					 * for va_arg() to retrieve the				  	 * corresponding argument:					 * arglst[0] is the first argument				         * arglst[1] is the second argument, etc.				         */											      int index = 0;			/* argument placeolder */											     /* Initialize args and sargs to the start of the argument list.        * Note that ANSI guarantees that the address of the first member of        * a structure will be the same as the address of the structure. */											       args_width = args_prec = args = sargs = *(struct stva_list *)&in_args;	cp = format;	if ((c = *cp++) != '\0') {		/*		 * We know we're going to write something; make sure		 * we can write and set up buffers, etc..		 */		if (_WRTCHK(file))			return(EOF);	} else		return(0);	/* no fault, no error */	count = 0;	fileptr = file->_ptr;	filecnt = file->_cnt;	/*	 *	The main loop -- this loop goes through one iteration	 *	for each ordinary character or format specification.	 */	do {		if (c != '%') {			/* Ordinary (non-%) character */			emitchar(c);		} else {			/*			 *	% has been spotted!			 *			 *	First, try the 99% cases.			 *	then parse the format specification.			 *			 *	Note that this code assumes the Sun			 *	Workstation environment (all params			 *	passed as int == long, no interrupts			 *	for fixed point overflow from negating			 *	the most negative number).			 */		skipit:			switch(c = *cp++) {			case 'l':			case 'h':				/* Quickly ignore long & short specifiers */				goto skipit;			case 's':				bp = va_arg(args.ap, char *);				if (bp == NULL)					bp = nullstr;				while (c = *bp++)					emitchar(c);				continue;			case 'c':				c = va_arg(args.ap, int);			emitc:				emitchar(c);				continue;			case 'i':			case 'd':			case 'D':				val = va_arg(args.ap, int);				if ((long) val < 0) {					emitchar('-');					val = -val;				}				goto udcommon;			case 'U':			case 'u':				val = va_arg(args.ap, unsigned);			udcommon:                                {                                register char *stringp = lowerhex;                                bp = buf+MAXDIGS;                                stringp = lowerhex;                                do {                                        *--bp = stringp[val%10];                                        val /= 10;                                } while (val);				}                                goto intout;			case 'X':				{				register char *stringp = upperhex;				val = va_arg(args.ap, unsigned);				bp = buf + MAXDIGS;				if (val == 0)					goto zero;				while (val) {					*--bp = stringp[val%16];					val /= 16;				}				}				goto intout;			case 'x':			case 'p':				{				register char *stringp = lowerhex;				val = va_arg(args.ap, unsigned);				bp = buf + MAXDIGS;				if (val == 0)					goto zero;				while (val) {					*--bp = stringp[val%16];					val /= 16;				}				}				goto intout;			case 'O':			case 'o':				{				register char *stringp = lowerhex;				val = va_arg(args.ap, unsigned);				bp = buf + MAXDIGS;				if (val == 0)					goto zero;				while (val) {					*--bp = stringp[val%8];					val /= 8;				}				}				/* Common code to output integers */			intout:				p = buf + MAXDIGS;				while (bp < p) {					c = *bp++;					emitchar(c);				}				continue;			zero:				c = '0';				goto emitc;			default:				/*				 * let AT&T deal with it				 */				cp-= 2;			}			Lsize = 0;      /* Not long double unless we say so. */                        /* Scan the <flags> */			fplus = 0;			fminus = 0;			fblank = 0;			fsharp = 0;#if FZERO			fzero = 0;#endif		scan:	switch (*++cp) {			case '+':				fplus = 1;				goto scan;			case '-':				fminus = 1;				goto scan;			case ' ':				fblank = 1;				goto scan;			case '#':				fsharp = 1;				goto scan;#if FZERO			case '0':				fzero = 1;				goto scan;#endif			}			/* Scan the field width */found_dol:			if (*cp == '*') {				char *p;				int val;				p = _check_dol(cp+1, &val);				if (p != (char *)NULL) {					/*					 * argument re-order					 */					if (fpos) {						_mkarglst(sformat, sargs, arglst);						fpos = 0;					}					if (val <= MAXARGS) {						args_width = arglst[val - 1];					} else {						args_width = arglst[MAXARGS - 1];						_getarg(sformat, &args_width, val);					}					width = va_arg(args_width.ap, int);					if (width < 0) {						width = -width;						fminus = 1;					}					cp = p;				}				else {					width = va_arg(args.ap, int);					if (width < 0) {						width = -width;						fminus = 1;					}					cp++;				}			} else {				index = width = 0;				while (isdigit(*cp)) {					n = tonumber(*cp++);					index = width = width * 10 + n;				}			}			/* Scan the precision */			if (*cp == '.') {				/* '*' instead of digits? */				if (*++cp == '*') {					char *p;					int val;					p = _check_dol(cp+1, &val);					if (p != (char *)NULL) {						/*						 * argument re-order						 */						if (fpos) {							_mkarglst(sformat, sargs, arglst);							fpos = 0;						}						if (val <= MAXARGS) {							args_prec = arglst[val - 1];						} else {							args_prec = arglst[MAXARGS - 1];							_getarg(sformat, &args_prec, val);						}						prec = va_arg(args_prec.ap, int);						cp = p;					}					else {						prec = va_arg(args.ap, int);						cp++;					}				} else {					prec = 0;					while (isdigit(*cp)) {						n = tonumber(*cp++);						prec = prec * 10 + n;					}				}			} else				prec = -1;			if (*cp == '$') {				if (fpos) {					_mkarglst(sformat, sargs, arglst);					fpos = 0;				}				if (index <= MAXARGS) {					args = arglst[index - 1];				} else {					args = arglst[MAXARGS - 1];					_getarg(sformat, &args, index);				}				cp++;				goto found_dol;			}			/*			 *	The character addressed by cp must be the			 *	format letter -- there is nothing left for			 *	it to be.			 *			 *	The status of the +, -, #, blank, and 0			 *	flags are reflected in the variables			 *	"fplus", "fminus", "fsharp", "fblank",			 *	and "fzero", respectively.			 *	"width" and "prec" contain numbers			 *	corresponding to the digit strings			 *	before and after the decimal point,			 *	respectively. If there was no decimal			 *	point, "prec" is -1.			 *			 *	The following switch sets 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 information 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".			 *			 *	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.  If either of			 *	these variables is negative, it will be			 *	treated as if it were zero.			 *			 *	The number of padding blanks, and whether			 *	they go on the left or the right, will be			 *	computed on exit from the switch.			 */						lzero = 0;			prefix = "";#if FLOAT			rzero = 0;			suffix = prefix;#endif		next:			switch (fcode = *cp++) {			/* toss the length modifier, if any */			case 'l':			case 'h':				goto next;                       	case 'L':                      		Lsize = 1;      /* Remember long double size. */                         	goto next;			/*			 *	fixed point representations			 *			 *	"radix" is the radix for the conversion.			 *	Conversion is unsigned unless fcode is 'd'.			 *	We assume a 2's complement machine and			 *	that fixed point overflow (from negating			 *	the largest negative int) is ignored.			 */			case 'i':			case 'D':			case 'U':			case 'd':			case 'u':				radix = 10;				goto fixed;			case 'O':			case 'o':				radix = 8;				goto fixed;			case 'X':			case 'x':				radix = 16;			fixed:				/* Establish default precision */				if (prec < 0)					prec = 1;				/* Fetch the argument to be printed */				val = va_arg(args.ap, unsigned);				/* If signed conversion, establish sign */				if (fcode == 'd' || fcode == 'D' || fcode == 'i') {					if ((long) val < 0) {						prefix = "-";						val = -val;					} else if (fplus)						prefix = "+";					else if (fblank)						prefix = " ";				}#if FZERO				if (fzero) {					n = width - strlen(prefix);					if (n > prec)						prec = n;				}#endif				/* Set translate table for digits */				{				register char *stringp;				if (fcode == 'X')					stringp = upperhex;				else					stringp = lowerhex;				/* Develop the digits of the value */				bp = buf + MAXDIGS;				switch(radix) {				case 8:	/*octal*/					while (val) {						*--bp = stringp[val%8];						val /= 8;					}					break;				case 16:/*hex*/					while (val) {						*--bp = stringp[val%16];						val /= 16;					}					break;				default:					while (val) {						*--bp = stringp[val%10];						val /= 10;					}					break;				} /* switch */				}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -