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

📄 fmt.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 5 页
字号:
				excess += bytelen - len;				p -= bytelen;				memmove(p+1, thousands, bytelen);			}			*p-- = conv[i];			n++;		}	}	if(n == 0){		/*		 * "The result of converting a zero value with		 * a precision of zero is no characters."  - ANSI		 *		 * "For o conversion, # increases the precision, if and only if		 * necessary, to force the first digit of the result to be a zero		 * (if the value and precision are both 0, a single 0 is printed)." - ANSI		 */		if(!(fl & FmtPrec) || f->prec != 0 || (f->r == 'o' && (fl & FmtSharp))){			*p-- = '0';			n = 1;			if(fl & FmtApost)				__needsep(&ndig, &grouping);		}				/*		 * Zero values don't get 0x.		 */		if(f->r == 'x' || f->r == 'X')			fl &= ~FmtSharp;	}	for(w = f->prec; n < w && p > buf+3; n++){		if((fl & FmtApost) && __needsep(&ndig, &grouping)){			n += len;			excess += bytelen - len;			p -= bytelen;			memmove(p+1, thousands, bytelen);		}		*p-- = '0';	}	if(neg || (fl & (FmtSign|FmtSpace)))		n++;	if(fl & FmtSharp){		if(base == 16)			n += 2;		else if(base == 8){			if(p[1] == '0')				fl &= ~FmtSharp;			else				n++;		}	}	if((fl & FmtZero) && !(fl & (FmtLeft|FmtPrec))){		w = 0;		if(fl & FmtWidth)			w = f->width;		for(; n < w && p > buf+3; n++){			if((fl & FmtApost) && __needsep(&ndig, &grouping)){				n += len;				excess += bytelen - len;				p -= bytelen;				memmove(p+1, thousands, bytelen);			}			*p-- = '0';		}		f->flags &= ~FmtWidth;	}	if(fl & FmtSharp){		if(base == 16)			*p-- = f->r;		if(base == 16 || base == 8)			*p-- = '0';	}	if(neg)		*p-- = '-';	else if(fl & FmtSign)		*p-- = '+';	else if(fl & FmtSpace)		*p-- = ' ';	f->flags &= ~FmtPrec;	return __fmtcpy(f, p + 1, n, n + excess);}int__countfmt(Fmt *f){	void *p;	ulong fl;	fl = f->flags;	p = va_arg(f->args, void*);	if(fl & FmtVLong){		*(vlong*)p = f->nfmt;	}else if(fl & FmtLong){		*(long*)p = f->nfmt;	}else if(fl & FmtByte){		*(char*)p = f->nfmt;	}else if(fl & FmtShort){		*(short*)p = f->nfmt;	}else{		*(int*)p = f->nfmt;	}	return 0;}int__flagfmt(Fmt *f){	switch(f->r){	case ',':		f->flags |= FmtComma;		break;	case '-':		f->flags |= FmtLeft;		break;	case '+':		f->flags |= FmtSign;		break;	case '#':		f->flags |= FmtSharp;		break;	case '\'':		f->flags |= FmtApost;		break;	case ' ':		f->flags |= FmtSpace;		break;	case 'u':		f->flags |= FmtUnsigned;		break;	case 'h':		if(f->flags & FmtShort)			f->flags |= FmtByte;		f->flags |= FmtShort;		break;	case 'L':		f->flags |= FmtLDouble;		break;	case 'l':		if(f->flags & FmtLong)			f->flags |= FmtVLong;		f->flags |= FmtLong;		break;	}	return 1;}/* default error format */int__badfmt(Fmt *f){	char x[3];	x[0] = '%';	x[1] = f->r;	x[2] = '%';	f->prec = 3;	__fmtcpy(f, (const void*)x, 3, 3);	return 0;}/* -------------- fltfmt.c --------------- *//* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */// #include <stdio.h>// #include <math.h>// #include <float.h>// #include <string.h>// #include <stdlib.h>// #include <errno.h>// #include <stdarg.h>// #include <fmt.h>// #include <assert.h>// #include "plan9.h"// #include "fmt.h"// #include "fmtdef.h"// #include "nan.h"enum{	FDIGIT	= 30,	FDEFLT	= 6,	NSIGNIF	= 17};/* * first few powers of 10, enough for about 1/2 of the * total space for doubles. */static double pows10[] ={	  1e0,   1e1,   1e2,   1e3,   1e4,   1e5,   1e6,   1e7,   1e8,   1e9,  	 1e10,  1e11,  1e12,  1e13,  1e14,  1e15,  1e16,  1e17,  1e18,  1e19,  	 1e20,  1e21,  1e22,  1e23,  1e24,  1e25,  1e26,  1e27,  1e28,  1e29,  	 1e30,  1e31,  1e32,  1e33,  1e34,  1e35,  1e36,  1e37,  1e38,  1e39,  	 1e40,  1e41,  1e42,  1e43,  1e44,  1e45,  1e46,  1e47,  1e48,  1e49,  	 1e50,  1e51,  1e52,  1e53,  1e54,  1e55,  1e56,  1e57,  1e58,  1e59,  	 1e60,  1e61,  1e62,  1e63,  1e64,  1e65,  1e66,  1e67,  1e68,  1e69,  	 1e70,  1e71,  1e72,  1e73,  1e74,  1e75,  1e76,  1e77,  1e78,  1e79,  	 1e80,  1e81,  1e82,  1e83,  1e84,  1e85,  1e86,  1e87,  1e88,  1e89,  	 1e90,  1e91,  1e92,  1e93,  1e94,  1e95,  1e96,  1e97,  1e98,  1e99,  	1e100, 1e101, 1e102, 1e103, 1e104, 1e105, 1e106, 1e107, 1e108, 1e109, 	1e110, 1e111, 1e112, 1e113, 1e114, 1e115, 1e116, 1e117, 1e118, 1e119, 	1e120, 1e121, 1e122, 1e123, 1e124, 1e125, 1e126, 1e127, 1e128, 1e129, 	1e130, 1e131, 1e132, 1e133, 1e134, 1e135, 1e136, 1e137, 1e138, 1e139, 	1e140, 1e141, 1e142, 1e143, 1e144, 1e145, 1e146, 1e147, 1e148, 1e149, 	1e150, 1e151, 1e152, 1e153, 1e154, 1e155, 1e156, 1e157, 1e158, 1e159, };#define	npows10 ((int)(sizeof(pows10)/sizeof(pows10[0])))#define	pow10(x)  fmtpow10(x)static doublepow10(int n){	double d;	int neg;	neg = 0;	if(n < 0){		if(n < DBL_MIN_10_EXP)			return 0.;		neg = 1;		n = -n;	}else if(n > DBL_MAX_10_EXP)		return HUGE_VAL;	if(n < npows10)		d = pows10[n];	else{		d = pows10[npows10-1];		for(;;){			n -= npows10 - 1;			if(n < npows10){				d *= pows10[n];				break;			}			d *= pows10[npows10 - 1];		}	}	if(neg)		return 1./d;	return d;}/* * add 1 to the decimal integer string a of length n. * if 99999 overflows into 10000, return 1 to tell caller * to move the virtual decimal point. */static intxadd1(char *a, int n){	char *b;	int c;	if(n < 0 || n > NSIGNIF)		return 0;	for(b = a+n-1; b >= a; b--) {		c = *b + 1;		if(c <= '9') {			*b = c;			return 0;		}		*b = '0';	}	/*	 * need to overflow adding digit.	 * shift number down and insert 1 at beginning.	 * decimal is known to be 0s or we wouldn't	 * have gotten this far.  (e.g., 99999+1 => 00000)	 */	a[0] = '1';	return 1;}/* * subtract 1 from the decimal integer string a. * if 10000 underflows into 09999, make it 99999 * and return 1 to tell caller to move the virtual  * decimal point.  this way, xsub1 is inverse of xadd1. */static intxsub1(char *a, int n){	char *b;	int c;	if(n < 0 || n > NSIGNIF)		return 0;	for(b = a+n-1; b >= a; b--) {		c = *b - 1;		if(c >= '0') {			if(c == '0' && b == a) {				/*				 * just zeroed the top digit; shift everyone up.				 * decimal is known to be 9s or we wouldn't				 * have gotten this far.  (e.g., 10000-1 => 09999)				 */				*b = '9';				return 1;			}			*b = c;			return 0;		}		*b = '9';	}	/*	 * can't get here.  the number a is always normalized	 * so that it has a nonzero first digit.	 */	abort();}/* * format exponent like sprintf(p, "e%+02d", e) */static voidxfmtexp(char *p, int e, int ucase){	char se[9];	int i;	*p++ = ucase ? 'E' : 'e';	if(e < 0) {		*p++ = '-';		e = -e;	} else		*p++ = '+';	i = 0;	while(e) {		se[i++] = e % 10 + '0';		e /= 10;	}	while(i < 2)		se[i++] = '0';	while(i > 0)		*p++ = se[--i];	*p++ = '\0';}/* * compute decimal integer m, exp such that: *	f = m*10^exp *	m is as short as possible with losing exactness * assumes special cases (NaN, +Inf, -Inf) have been handled. */static voidxdtoa(double f, char *s, int *exp, int *neg, int *ns){	int c, d, e2, e, ee, i, ndigit, oerrno;	char tmp[NSIGNIF+10];	double g;	oerrno = errno; /* in case strtod smashes errno */	/*	 * make f non-negative.	 */	*neg = 0;	if(f < 0) {		f = -f;		*neg = 1;	}	/*	 * must handle zero specially.	 */	if(f == 0){		*exp = 0;		s[0] = '0';		s[1] = '\0';		*ns = 1;		return;	}			/*	 * find g,e such that f = g*10^e.	 * guess 10-exponent using 2-exponent, then fine tune.	 */	frexp(f, &e2);	e = (int)(e2 * .301029995664);	g = f * pow10(-e);	while(g < 1) {		e--;		g = f * pow10(-e);	}	while(g >= 10) {		e++;		g = f * pow10(-e);	}	/*	 * convert NSIGNIF digits as a first approximation.	 */	for(i=0; i<NSIGNIF; i++) {		d = (int)g;		s[i] = d+'0';		g = (g-d) * 10;	}	s[i] = 0;	/*	 * adjust e because s is 314159... not 3.14159...	 */	e -= NSIGNIF-1;	xfmtexp(s+NSIGNIF, e, 0);	/*	 * adjust conversion until strtod(s) == f exactly.	 */	for(i=0; i<10; i++) {		g = strtod(s, nil);		if(f > g) {			if(xadd1(s, NSIGNIF)) {				/* gained a digit */				e--;				xfmtexp(s+NSIGNIF, e, 0);			}			continue;		}		if(f < g) {			if(xsub1(s, NSIGNIF)) {				/* lost a digit */				e++;				xfmtexp(s+NSIGNIF, e, 0);			}			continue;		}		break;	}	/*	 * play with the decimal to try to simplify.	 */	/*	 * bump last few digits up to 9 if we can	 */	for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {		c = s[i];		if(c != '9') {			s[i] = '9';			g = strtod(s, nil);			if(g != f) {				s[i] = c;				break;			}		}	}	/*	 * add 1 in hopes of turning 9s to 0s	 */	if(s[NSIGNIF-1] == '9') {		strcpy(tmp, s);		ee = e;		if(xadd1(tmp, NSIGNIF)) {			ee--;			xfmtexp(tmp+NSIGNIF, ee, 0);		}		g = strtod(tmp, nil);		if(g == f) {			strcpy(s, tmp);			e = ee;		}	}		/*	 * bump last few digits down to 0 as we can.	 */	for(i=NSIGNIF-1; i>=NSIGNIF-3; i--) {		c = s[i];		if(c != '0') {			s[i] = '0';			g = strtod(s, nil);			if(g != f) {				s[i] = c;				break;			}		}	}	/*	 * remove trailing zeros.	 */	ndigit = NSIGNIF;	while(ndigit > 1 && s[ndigit-1] == '0'){		e++;		--ndigit;	}	s[ndigit] = 0;	*exp = e;	*ns = ndigit;	errno = oerrno;}#ifdef PLAN9PORTstatic char *special[] = { "NaN", "NaN", "+Inf", "+Inf", "-Inf", "-Inf" };#elsestatic char *special[] = { "nan", "NAN", "inf", "INF", "-inf", "-INF" };#endifint__efgfmt(Fmt *fmt){	char buf[NSIGNIF+10], *dot, *digits, *p, *s, suf[10], *t;	double f;	int c, chr, dotwid, e, exp, fl, ndigits, neg, newndigits;	int pad, point, prec, realchr, sign, sufwid, ucase, wid, z1, z2;	Rune r, *rs, *rt;		f = va_arg(fmt->args, double);		/* 	 * extract formatting flags	 */	fl = fmt->flags;	fmt->flags = 0;	prec = FDEFLT;	if(fl & FmtPrec)		prec = fmt->prec;	chr = fmt->r;	ucase = 0;	switch(chr) {	case 'A':	case 'E':	case 'F':	case 'G':		chr += 'a'-'A';		ucase = 1;		break;	}	/*	 * pick off special numbers.	 */	if(__isNaN(f)) {		s = special[0+ucase];	special:		fmt->flags = fl & (FmtWidth|FmtLeft);		return __fmtcpy(fmt, s, strlen(s), strlen(s));	}	if(__isInf(f, 1)) {		s = special[2+ucase];		goto special;	}	if(__isInf(f, -1)) {		s = special[4+ucase];		goto special;	}	/*	 * get exact representation.	 */	digits = buf;	xdtoa(f, digits, &exp, &neg, &ndigits);	/*	 * get locale's decimal point.	 */	dot = fmt->decimal;	if(dot == nil)		dot = ".";	dotwid = utflen(dot);	/*	 * now the formatting fun begins.	 * compute parameters for actual fmt:	 *	 *	pad: number of spaces to insert before/after field.	 *	z1: number of zeros to insert before digits	 *	z2: number of zeros to insert after digits	 *	point: number of digits to print before decimal point	 *	ndigits: number of digits to use from digits[]	 *	suf: trailing suffix, like "e-5"	 */	realchr = chr;	switch(chr){	case 'g':		/*		 * convert to at most prec significant digits. (prec=0 means 1)		 */		if(prec == 0)			prec = 1;		if(ndigits > prec) {			if(digits[prec] >= '5' && xadd1(digits, prec))				exp++;			exp += ndigits-prec;			ndigits = prec;		}				/*		 * extra rules for %g (implemented below):		 *	trailing zeros removed after decimal unless FmtSharp.		 *	decimal point only if digit follows.		 */		/* fall through to %e */	default:	case 'e':		/* 		 * one significant digit before decimal, no leading zeros.		 */		point = 1;		z1 = 0;				/*		 * decimal point is after ndigits digits right now.		 * slide to be after first.		 */		e  = exp + (ndigits-1);		/*		 * if this is %g, check exponent and convert prec		 */		if(realchr == 'g') {			if(-4 <= e && e < prec)				goto casef;			prec--;	/* one digit before decimal; rest after */		}		/*		 * compute trailing zero padding or truncate digits.		 */		if(1+prec >= ndigits)			z2 = 1+prec - ndigits;		else {			/*			 * truncate digits			 */			assert(realchr != 'g');			newndigits = 1+prec;			if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {				/*				 * had 999e4, now have 100e5				 */				e++;			}			ndigits = newndigits;			z2 = 0;		}		xfmtexp(suf, e, ucase);		sufwid = strlen(suf);		break;	casef:	case 'f':		/*		 * determine where digits go with respect to decimal point		 */		if(ndigits+exp > 0) {			point = ndigits+exp;			z1 = 0;		} else {			point = 1;			z1 = 1 + -(ndigits+exp);		}		/*		 * %g specifies prec = number of significant digits		 * convert to number of digits after decimal point		 */		if(realchr == 'g')			prec += z1 - point;		/*		 * compute trailing zero padding or truncate digits.		 */		if(point+prec >= z1+ndigits)			z2 = point+prec - (z1+ndigits);		else {			/*			 * truncate digits			 */			assert(realchr != 'g');			newndigits = point+prec - z1;			if(newndigits < 0) {				z1 += newndigits;				newndigits = 0;			} else if(newndigits == 0) {				/* perhaps round up */				if(digits[0] >= '5'){					digits[0] = '1';					newndigits = 1;					goto newdigit;				}			} else if(digits[newndigits] >= '5' && xadd1(digits, newndigits)) {				/*				 * digits was 999, is now 100; make it 1000				 */				digits[newndigits++] = '0';			newdigit:				/*

⌨️ 快捷键说明

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