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

📄 vfprintf.c

📁 基于4个mips核的noc设计
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * lib-src/ansi/stdio/vfprintf.c * int vfprintf(FILE *stream, const char *format, va_list arg) * ANSI/ISO 9899-1990, Section 7.9.6.7. * * Copyright (c) 1990 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley.  The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#include <stdio.h>#include <ctype.h>#include <float.h>#include <math.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <ieee.h>#if	defined(__TCS__)#include <ops/custom_ops.h>#endif	/* defined(__TCS__) */#include "local.h"#include "fvwrite.h"#include "shared_libc.h"/* N.B. DBL_EXP_10_DIG should be (int)(log10(DBL_MAX_10_EXP) + 1) *//* N.B. Also change fpcvt() exponent code if exponent can be > 999! */#define	DBL_EXP_10_DIG	3			/* max decimal digits in double exponent */#define	DEFPREC	6				/* default precision */#define LOG2_10 3.3219280948873623		/* log2(10) *//* * Maximum precision: * DBL_DIG is (int)floor((DBL_MANT_DIG - 1) * log10(FLT_RADIX)), * which gives the maximum precision in decimal digits. * Digits after DBL_DIG + 1 significant digits are noise. * The last of the DBL_DIG + 1 digits may be partially noise but * we convert it anyway rather than throw away some valid precision. */#define	MAXPREC	(DBL_DIG + 1)/* * Output conversion buffer size: * the buffer needs to hold the largest fp "%f" value, which contains * DBL_MAX_10_EXP + 1 digits, then decimal point, then MAXPREC digits. */#define	NBUF	(DBL_MAX_10_EXP + 1 + 1 + MAXPREC)/* Local function prototypes. */static	int	fpcvt(double d, char *buf, int fmtch, int prec, int flags,	       char *signp, char *expbuf, int *expsizep, int *fppadp);static	double	frexp10(double d, int *expp);static	int	significand(double d, int fmtch, int prec, char *buf, int *expp);/* Flags used during conversion. */#define	LONGINT		0x01		/* long integer			*/#define	LONGDBL		0x02		/* long double			*/#define	SHORTINT	0x04		/* short integer		*/#define	ALT		0x08		/* alternate form		*/#define	LADJUST		0x10		/* left adjustment		*/#define	ZEROPAD		0x20		/* zero (as opposed to blank) pad */#define	HEXPREFIX	0x40		/* add 0x or 0X prefix		*//* Macros for testing/setting/clearing conversion flags. */#define	is_flag(flag)	((flags & flag) != 0)#define	set_flag(flag)	flags |= flag#define	clr_flag(flag)	flags &= ~flag/* * Choose PADSIZE to trade efficiency vs size.  If larger * printf fields occur frequently, increase PADSIZE (and make * the initializers below longer). */#define	PADSIZE	16			/* pad chunk size */static	const	char	*blanks  = "                ";static	const	char	*zeroes  = "0000000000000000";static	const	char	*xdigits = "0123456789abcdef";static	const	char	*Xdigits = "0123456789ABCDEF";/* * BEWARE, these macros `goto error' on error, and PAD uses `n'. */#define NIOV 8#define	PRINT(ptr, len) { \	iovp->iov_base = (ptr); \	iovp->iov_len = (len); \	uio.uio_resid += (len); \	iovp++; \	if (++uio.uio_iovcnt >= NIOV) { \		if (__sprint(stream, &uio)) \			goto error; \		iovp = iov; \	} \}#define	PAD(howmany, with) { \	if ((n = (howmany)) > 0) { \		while (n > PADSIZE) { \			PRINT(((char *)with), PADSIZE); \			n -= PADSIZE; \		} \		PRINT(((char *)with), n); \	} \}#define	FLUSH() { \	if (uio.uio_resid && __sprint(stream, &uio)) \		goto error; \	uio.uio_iovcnt = 0; \	iovp = iov; \}/* * To extend shorts properly, we need both signed and unsigned * argument extraction methods. */#define	SARG() \	(is_flag(LONGINT) ? va_arg(arg, long) : \	    is_flag(SHORTINT) ? (long)(short)va_arg(arg, int) : \	    (long)va_arg(arg, int))#define	UARG() \	(is_flag(LONGINT) ? va_arg(arg, unsigned long) : \	    is_flag(SHORTINT) ? (unsigned long)(unsigned short)va_arg(arg, int) : \	    (unsigned long)va_arg(arg, unsigned int))/* * Flush out all the vectors defined by the given uio, * then reset it so that it can be reused. *//* static */int__sprint(FILE *fp, register struct __suio *uio){	register int err;	if (uio->uio_resid == 0) {		uio->uio_iovcnt = 0;		return (0);	}	err = __sfvwrite(fp, uio);	uio->uio_resid = 0;	uio->uio_iovcnt = 0;	return (err);}/* * Helper function for `fprintf to unbuffered unix file': creates a * temporary buffer.  We only work on write-only files; this avoids * worries about ungetc buffers and so forth. *//* static */int__sbprintf(register FILE *fp, char const *fmt, va_list ap){	int ret;	FILE fake;	unsigned char buf[BUFSIZ];	/* copy the important variables */	fake._flags = fp->_flags & ~__SNBF;	fake._file = fp->_file;	fake._cookie = fp->_cookie;	fake._write = fp->_write;	/* set up the buffer */	fake._bf._base = fake._p = buf;	fake._bf._size = fake._w = sizeof(buf);	fake._lbfsize = 0;	/* not actually used, but Just In Case */	/* do the work, then copy any error status */	ret = vfprintf(&fake, fmt, ap);	if (ret >= 0 && _fflush(&fake))		ret = EOF;	if (fake._flags & __SERR)		fp->_flags |= __SERR;	return (ret);}intvfprintf(FILE *stream, const char *format, va_list arg){	char *fmt;		/* format string */	int ch;			/* character from fmt */	int n;			/* handy integer (short term usage) */	char *cp;		/* handy char pointer (short term usage) */	struct __siov *iovp;	/* for PRINT macro */	int flags;		/* flags as above */	int ret;		/* return value accumulator */	int width;		/* width from format (%8d), or 0 */	int prec;		/* precision from format (%.3d), or -1 */	int negflag;		/* iff negative precision */	char sign;		/* sign prefix (' ', '+', '-', or 0) */	double d;		/* double precision arguments %[eEfgG] */	unsigned long _ulong;	/* integer arguments %[diouxX] */	enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */	int fieldsz;		/* field size expanded by sign, etc */	int realsz;		/* field size expanded by dprec */	int size;		/* size of converted field or string */	int expsize;		/* size of fp exponent */	int fppad;		/* trailing 0-padding required for fp */	const char *xdigs;	/* digits for [xX] conversion */	struct __suio uio;	/* output information: summary */	struct __siov iov[NIOV];/* ... and individual io vectors */	char buf[NBUF];		/* buffer for %c, %[diouxX], %[eEfgG] */	char expbuf[DBL_EXP_10_DIG + 3];	/* buffer for E + sign + digits + NUL */	char ox[2];		/* buffer for 0x hex-prefix */        int  result;        EXCL_START(&stream->_file_lock);	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */	if (cantwrite(stream)) {		EXCL_END(&stream->_file_lock);		return EOF;	}	/* optimise fprintf(stderr) (and other unbuffered Unix files) */	if ((stream->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&	    stream->_file >= 0) {                result= (__sbprintf(stream, format, arg));		EXCL_END(&stream->_file_lock);		return result;	}	fmt = (char *)format;	uio.uio_iov = iovp = iov;	uio.uio_resid = 0;	uio.uio_iovcnt = 0;	ret = 0;	/*	 * Scan the format for conversions (`%' character).	 */	for (;;) {		/* UNDONE: multibyte characters in format string. */		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)			/* void */;		if ((n = fmt - cp) != 0) {			PRINT(cp, n);			ret += n;		}		if (ch == '\0')			goto done;		fmt++;		/* skip over '%' */		sign = 0;		size = flags = dprec = width = fppad = expsize = 0;		prec = -1;rflag:		ch = *fmt++;reswitch:	switch (ch) {		case ' ':			/*			 * ``If the space and + flags both appear, the space			 * flag will be ignored.''			 *	-- ANSI/ISO 9899-1990.			 */			if (!sign)				sign = ' ';			goto rflag;		case '#':			set_flag(ALT);			goto rflag;		case '*':			/*			 * ``A negative field width argument is taken as a			 * - flag followed by a positive field width.''			 *	-- ANSI/ISO 9899-1990.			 * They don't exclude field widths read from args.			 */			if ((width = va_arg(arg, int)) >= 0)				goto rflag;			width = -width;			/* FALLTHROUGH */		case '-':			set_flag(LADJUST);			goto rflag;		case '+':			sign = '+';			goto rflag;		case '.':			if ((ch = *fmt++) == '*') {				n = va_arg(arg, int);				prec = n < 0 ? -1 : n;				goto rflag;			}			negflag = (ch == '-');			if (negflag)				ch = *fmt++;			for (n = 0; isdigit(ch); ch = *fmt++)				n = 10 * n + ch - '0';			if (negflag)				n = -n;			prec = n < 0 ? -1 : n;			goto reswitch;		case '0':			/*			 * ``Note that 0 is taken as a flag, not as the			 * beginning of a field width.''			 *	-- ANSI/ISO 9899-1990.			 */			set_flag(ZEROPAD);			goto rflag;		case '1': case '2': case '3': case '4':		case '5': case '6': case '7': case '8': case '9':			n = 0;			do {				n = 10 * n + ch - '0';				ch = *fmt++;			} while (isdigit(ch));			width = n;			goto reswitch;		case 'L':			set_flag(LONGDBL);			goto rflag;		case 'h':			set_flag(SHORTINT);			goto rflag;		case 'l':			set_flag(LONGINT);			goto rflag;		case 'c':			*(cp = buf) = va_arg(arg, int);			size = 1;			sign = 0;			break;		case 'D':			set_flag(LONGINT);			/*FALLTHROUGH*/		case 'd':		case 'i':			_ulong = SARG();			if ((long)_ulong < 0) {				_ulong = -_ulong;				sign = '-';			}			base = DEC;			goto number;		case 'e':		case 'E':		case 'f':		case 'g':		case 'G':			/*			 * Floating point output, what fun.			 * For now, we truncate long double to double.			 * If long double were actually longer than double,			 * to do long double output to full precision we would			 * instead widen the double to long double here, pass			 * long doubles down to fpcvt()/significand()/frexp10()/_pow10(),			 * and pass the flags down to significand() so it can know			 * whether to use DBL_DIG or LDBL_DIG.			 */			if (is_flag(LONGDBL))				d = (double)va_arg(arg, long double);			else				d = va_arg(arg, double);			cp = buf;			size = fpcvt(d, cp, ch, prec, flags,				     &sign, expbuf, &expsize, &fppad);			break;		case 'n':			if (is_flag(LONGINT))				*va_arg(arg, long *) = ret;			else if (is_flag(SHORTINT))				*va_arg(arg, short *) = ret;			else				*va_arg(arg, int *) = ret;			continue;	/* no output */		case 'O':			set_flag(LONGINT);			/*FALLTHROUGH*/		case 'o':			_ulong = 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/ISO 9899-1990.			 */			/* NOSTRICT */			_ulong = (unsigned long)va_arg(arg, void *);			base = HEX;			xdigs = xdigits;			set_flag(HEXPREFIX);			ch = 'x';			goto nosign;		case 's':			if ((cp = va_arg(arg, char *)) == NULL)				cp = "{NULL}";			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);			sign = 0;			break;		case 'U':			set_flag(LONGINT);			/*FALLTHROUGH*/		case 'u':			_ulong = UARG();			base = DEC;			goto nosign;		case 'X':			xdigs = Xdigits;			goto hex;		case 'x':			xdigs = xdigits;hex:			_ulong = UARG();			base = HEX;			/* leading 0x/X only if non-zero */			if (is_flag(ALT) && _ulong != 0)				set_flag(HEXPREFIX);			/* unsigned conversions */nosign:			sign = 0;			/*			 * ``... diouXx conversions ... if a precision is			 * specified, the 0 flag will be ignored.''			 *	-- ANSI/ISO 9899-1990.			 */number:			if ((dprec = prec) >= 0)				clr_flag(ZEROPAD);			/*			 * ``The result of converting a zero value with an			 * explicit precision of zero is no characters.''			 *	-- ANSI/ISO 9899-1990.			 */			cp = buf + NBUF;			if (_ulong != 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 = (_ulong & 7) + '0';						_ulong >>= 3;

⌨️ 快捷键说明

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