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

📄 fltfmt.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * The authors of this software are Rob Pike and Ken Thompson. *              Copyright (c) 2002 by Lucent Technologies. * Permission to use, copy, modify, and distribute this software for any * purpose without fee is hereby granted, provided that this entire notice * is included in all copies of any software which is or includes a copy * or modification of this software and in all copies of the supporting * documentation for such software. * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */#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 "fmtdef.h"#include "nan.h"enum{	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, };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 < (int)(sizeof(pows10)/sizeof(pows10[0])))		d = pows10[n];	else{		d = pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];		for(;;){			n -= sizeof(pows10)/sizeof(pows10[0]) - 1;			if(n < (int)(sizeof(pows10)/sizeof(pows10[0]))){				d *= pows10[n];				break;			}			d *= pows10[sizeof(pows10)/sizeof(pows10[0]) - 1];		}	}	if(neg){		return 1./d;	}	return d;}static intxadd(char *a, int n, int v){	char *b;	int c;	if(n < 0 || n >= NSIGNIF)		return 0;	for(b = a+n; b >= a; b--) {		c = *b + v;		if(c <= '9') {			*b = c;			return 0;		}		*b = '0';		v = 1;	}	*a = '1';	/* overflow adding */	return 1;}static intxsub(char *a, int n, int v){	char *b;	int c;	for(b = a+n; b >= a; b--) {		c = *b - v;		if(c >= '0') {			*b = c;			return 0;		}		*b = '9';		v = 1;	}	*a = '9';	/* underflow subtracting */	return 1;}static voidxaddexp(char *p, int e){	char se[9];	int i;	*p++ = 'e';	if(e < 0) {		*p++ = '-';		e = -e;	}	i = 0;	while(e) {		se[i++] = e % 10 + '0';		e /= 10;	}	if(i == 0) {		*p++ = '0';	} else {		while(i > 0)			*p++ = se[--i];	}	*p++ = '\0';}static char*xdodtoa(char *s1, double f, int chr, int prec, int *decpt, int *rsign){	char s2[NSIGNIF+10];	double g, h;	int e, d, i;	int c2, sign, oerr;	if(chr == 'F')		chr = 'f';	if(prec > NSIGNIF)		prec = NSIGNIF;	if(prec < 0)		prec = 0;	if(__isNaN(f)) {		*decpt = 9999;		*rsign = 0;		strcpy(s1, "nan");		return &s1[3];	}	sign = 0;	if(f < 0) {		f = -f;		sign++;	}	*rsign = sign;	if(__isInf(f, 1) || __isInf(f, -1)) {		*decpt = 9999;		strcpy(s1, "inf");		return &s1[3];	}	e = 0;	g = f;	if(g != 0) {		frexp(f, &e);		e = (int)(e * .301029995664);		if(e >= -150 && e <= +150) {			d = 0;			h = f;		} else {			d = e/2;			h = f * pow10(-d);		}		g = h * pow10(d-e);		while(g < 1) {			e--;			g = h * pow10(d-e);		}		while(g >= 10) {			e++;			g = h * pow10(d-e);		}	}	/*	 * convert NSIGNIF digits and convert	 * back to get accuracy.	 */	for(i=0; i<NSIGNIF; i++) {		d = (int)g;		s1[i] = d + '0';		g = (g - d) * 10;	}	s1[i] = 0;	/*	 * try decimal rounding to eliminate 9s	 */	c2 = prec + 1;	if(chr == 'f')		c2 += e;	oerr = errno;	if(c2 >= NSIGNIF-2) {		strcpy(s2, s1);		d = e;		s1[NSIGNIF-2] = '0';		s1[NSIGNIF-1] = '0';		xaddexp(s1+NSIGNIF, e-NSIGNIF+1);		g = fmtstrtod(s1, nil);		if(g == f)			goto found;		if(xadd(s1, NSIGNIF-3, 1)) {			e++;			xaddexp(s1+NSIGNIF, e-NSIGNIF+1);		}		g = fmtstrtod(s1, nil);		if(g == f)			goto found;		strcpy(s1, s2);		e = d;	}	/*	 * convert back so s1 gets exact answer	 */	for(d = 0; d < 10; d++) {		xaddexp(s1+NSIGNIF, e-NSIGNIF+1);		g = fmtstrtod(s1, nil);		if(f > g) {			if(xadd(s1, NSIGNIF-1, 1))				e--;			continue;		}		if(f < g) {			if(xsub(s1, NSIGNIF-1, 1))				e++;			continue;		}		break;	}found:	errno = oerr;	/*	 * sign	 */	d = 0;	i = 0;	/*	 * round & adjust 'f' digits	 */	c2 = prec + 1;	if(chr == 'f'){		if(xadd(s1, c2+e, 5))			e++;		c2 += e;		if(c2 < 0){			c2 = 0;			e = -prec - 1;		}	}else{		if(xadd(s1, c2, 5))			e++;	}	if(c2 > NSIGNIF){		c2 = NSIGNIF;	}	*decpt = e + 1;	/*	 * terminate the converted digits	 */	s1[c2] = '\0';	return &s1[c2];}/* * this function works like the standard dtoa, if you want it. */#if 0static char*__dtoa(double f, int mode, int ndigits, int *decpt, int *rsign, char **rve){	static char s2[NSIGNIF + 10];	char *es;	int chr, prec;	switch(mode) {	/* like 'e' */	case 2:	case 4:	case 6:	case 8:		chr = 'e';		break;	/* like 'g' */	case 0:	case 1:	default:		chr = 'g';		break;	/* like 'f' */	case 3:	case 5:	case 7:	case 9:		chr = 'f';		break;	}	if(chr != 'f' && ndigits){		ndigits--;	}	prec = ndigits;	if(prec > NSIGNIF)		prec = NSIGNIF;	if(ndigits == 0)		prec = NSIGNIF;	es = xdodtoa(s2, f, chr, prec, decpt, rsign);	/*	 * strip trailing 0	 */	for(; es > s2 + 1; es--){		if(es[-1] != '0'){			break;		}	}	*es = '\0';	if(rve != NULL)		*rve = es;	return s2;}#endifstatic intfmtzdotpad(Fmt *f, int n, int pt){	char *t, *s;	int i;	Rune *rt, *rs;	if(f->runes){		rt = (Rune*)f->to;		rs = (Rune*)f->stop;		for(i = 0; i < n; i++){			if(i == pt){				FMTRCHAR(f, rt, rs, '.');			}			FMTRCHAR(f, rt, rs, '0');		}		f->nfmt += rt - (Rune*)f->to;		f->to = rt;	}else{		t = (char*)f->to;		s = (char*)f->stop;		for(i = 0; i < n; i++){			if(i == pt){				FMTCHAR(f, t, s, '.');			}			FMTCHAR(f, t, s, '0');		}		f->nfmt += t - (char *)f->to;		f->to = t;	}	return 0;}int__efgfmt(Fmt *fmt){	double f;	char s1[NSIGNIF+10];	int e, d, n;	int c1, c2, c3, c4, ucase, sign, chr, prec, fl;	f = va_arg(fmt->args, double);	prec = FDEFLT;	fl = fmt->flags;	fmt->flags = 0;	if(fl & FmtPrec)		prec = fmt->prec;	chr = fmt->r;	ucase = 0;	if(chr == 'E'){		chr = 'e';		ucase = 1;	}else if(chr == 'F'){		chr = 'f';		ucase = 1;	}else if(chr == 'G'){		chr = 'g';		ucase = 1;	}	if(prec > 0 && chr == 'g')		prec--;	if(prec < 0)		prec = 0;	xdodtoa(s1, f, chr, prec, &e, &sign);	e--;	if(*s1 == 'i' || *s1 == 'n'){		if(ucase){			if(*s1 == 'i'){				strcpy(s1, "INF");			}else{				strcpy(s1, "NAN");			}		}		fmt->flags = fl & (FmtWidth|FmtLeft);		return __fmtcpy(fmt, (const void*)s1, 3, 3);	}	/*	 * copy into final place	 * c1 digits of leading '0'	 * c2 digits from conversion	 * c3 digits of trailing '0'	 * c4 digits after '.'	 */	c1 = 0;	c2 = prec + 1;	c3 = 0;	c4 = prec;	switch(chr) {	default:		chr = 'e';		break;	case 'g':		/*		 * decide on 'e' of 'f' style convers		 */		if(e >= -4 && e <= prec) {			c1 = -e;			c4 = prec - e;			chr = 'h';	/* flag for 'f' style */		}		break;	case 'f':		c1 = -e;		if(c1 > prec)			c1 = prec + 1;		c2 += e;		break;	}	/*	 * clean up c1 c2 and c3	 */	if(c1 < 0)		c1 = 0;	if(c2 < 0)		c2 = 0;	if(c2 > NSIGNIF) {		c3 = c2-NSIGNIF;		c2 = NSIGNIF;	}	/*	 * trim trailing zeros for %g	 */	if(!(fl & FmtSharp)	&& (chr == 'g' || chr == 'h')){		if(c4 >= c3){			c4 -= c3;			c3 = 0;		}else{			c3 -= c4;			c4 = 0;		}		while(c4 && c2 > 1 && s1[c2 - 1] == '0'){			c4--;			c2--;		}	}	/*	 * calculate the total length	 */	n = c1 + c2 + c3;	if(sign || (fl & (FmtSign|FmtSpace)))		n++;	if(c4 || (fl & FmtSharp)){		n++;	}	if(chr == 'e' || chr == 'g'){		n += 4;		if(e >= 100)			n++;	}	/*	 * pad to width if right justified	 */	if((fl & (FmtWidth|FmtLeft)) == FmtWidth && n < fmt->width){		if(fl & FmtZero){			c1 += fmt->width - n;		}else{			if(__fmtpad(fmt, fmt->width - n) < 0){				return -1;			}		}	}	/*	 * sign	 */	d = 0;	if(sign)		d = '-';	else if(fl & FmtSign)		d = '+';	else if(fl & FmtSpace)		d = ' ';	if(d && fmtrune(fmt, d) < 0){		return -1;	}	/*	 * copy digits	 */	c4 = c1 + c2 + c3 - c4;	if(c1 > 0){		if(fmtzdotpad(fmt, c1, c4) < 0){			return -1;		}		c4 -= c1;	}	d = 0;	if(c4 >= 0 && c4 < c2){		if(__fmtcpy(fmt, s1, c4, c4) < 0 || fmtrune(fmt, '.') < 0)			return -1;		d = c4;		c2 -= c4;		c4 = -1;	}	if(__fmtcpy(fmt, (const void*)(s1 + d), c2, c2) < 0){		return -1;	}	c4 -= c2;	if(c3 > 0){		if(fmtzdotpad(fmt, c3, c4) < 0){			return -1;		}		c4 -= c3;	}	/*	 * strip trailing '0' on g conv	 */	if((fl & FmtSharp) && c4 == 0 && fmtrune(fmt, '.') < 0){		return -1;	}	if(chr == 'e' || chr == 'g') {		d = 0;		if(ucase)			s1[d++] = 'E';		else			s1[d++] = 'e';		c1 = e;		if(c1 < 0) {			s1[d++] = '-';			c1 = -c1;		} else			s1[d++] = '+';		if(c1 >= 100) {			s1[d++] = c1/100 + '0';			c1 = c1%100;		}		s1[d++] = c1/10 + '0';		s1[d++] = c1%10 + '0';		if(__fmtcpy(fmt, s1, d, d) < 0){			return -1;		}	}	if((fl & (FmtWidth|FmtLeft)) == (FmtWidth|FmtLeft) && n < fmt->width){		if(__fmtpad(fmt, fmt->width - n) < 0){			return -1;		}	}	return 0;}

⌨️ 快捷键说明

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