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

📄 vsprintf.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
字号:
/* $Id: vsprintf.c,v 1.2 2002/08/09 20:57:00 pefo Exp $ *//* * Copyright (c) 2000-2002 Opsycon AB  (www.opsycon.se) *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Opsycon AB. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#include <stdio.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include <pmon.h>/* *  int vsprintf(d,s,ap) */int vsprintf (char *d, const char *s, va_list ap){	const char *t;	char *p, *dst, tmp[40];	unsigned int n;	int fmt, trunc, haddot, width, base, longlong;#ifdef FLOATINGPT	double dbl;#ifndef NEWFP	EP ex;#endif#endif	dst = d;	for (; *s;) {		if (*s == '%') {			s++;			fmt = FMT_RJUST;			width = trunc = haddot = longlong = 0;			for (; *s; s++) {				if (strchr ("dobpxXulscefg%", *s))					break;				else if (*s == '-')					fmt = FMT_LJUST;				else if (*s == '0')					fmt = FMT_RJUST0;				else if (*s == '~')					fmt = FMT_CENTER;				else if (*s == '*') {					if (haddot)						trunc = va_arg (ap, int);					else						width = va_arg (ap, int);				} else if (*s >= '1' && *s <= '9') {					for (t = s; isdigit (*s); s++);					strncpy (tmp, t, s - t);					tmp[s - t] = '\0';					atob (&n, tmp, 10);					if (haddot)						trunc = n;					else						width = n;					s--;				} else if (*s == '.')					haddot = 1;			}			if (*s == '%') {				*d++ = '%';				*d = 0;			} else if (*s == 's') {				p = va_arg (ap, char *);				if (p)					strcpy (d, p);				else					strcpy (d, "(null)");			} else if (*s == 'c') {				n = va_arg (ap, int);				*d = n;				d[1] = 0;			} else {				if (*s == 'l') {					if (*++s == 'l') {						longlong = 1;						++s;					}				}				if (strchr ("dobpxXu", *s)) {					if (*s == 'd')						base = -10;					else if (*s == 'u')						base = 10;					else if (*s == 'x' || *s == 'X')						base = 16;					else if(*s == 'p') {						base = 16;						*d++ = '0';						*d++ = 'x';						fmt = FMT_RJUST0;						width = 8;					}					else if (*s == 'o')						base = 8;					else if (*s == 'b')						base = 2;#ifdef HAVE_QUAD					if (longlong)						llbtoa(d, va_arg (ap, quad_t),						    base);					else#endif						btoa(d, va_arg (ap, int), base);					if (*s == 'X')						strtoupper(d);				}#ifdef FLOATINGPT				else if (strchr ("eEfgG", *s)) {static void dtoa (char *, double, int, int, int);					dbl = va_arg(ap, double);					dtoa (d, dbl, *s, width, trunc);					trunc = 0;				}#endif			}			if (trunc)				d[trunc] = 0;			if (width)				str_fmt (d, width, fmt);			for (; *d; d++);			s++;		} else			*d++ = *s++;	}	*d = 0;	return (d - dst);}#ifdef FLOATINGPT/* * Floating point output, cvt() onward lifted from BSD sources: * * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#define MAX_FCONVERSION	512	/* largest possible real conversion 	*/#define MAX_EXPT	5	/* largest possible exponent field */#define MAX_FRACT	39	/* largest possible fraction field */#define TESTFLAG(x)	0typedef double rtype;extern double modf(double, double *);#define	to_char(n)	((n) + '0')#define	to_digit(c)	((c) - '0')#define _isNan(arg)	((arg) != (arg))static int cvt (rtype arg, int prec, char *signp, int fmtch,		char *startp, char *endp);static char *round (double fract, int *exp, char *start, char *end, 		    char ch, char *signp);static char *exponent(char *p, int exp, int fmtch);/* * _finite arg not Infinity or Nan */static int _finite(rtype d){#if ENDIAN == ENDIAN_LITTLE    struct IEEEdp {	unsigned manl:32;	unsigned manh:20;	unsigned exp:11;	unsigned sign:1;    } *ip;#else    struct IEEEdp {	unsigned sign:1;	unsigned exp:11;	unsigned manh:20;	unsigned manl:32;    } *ip;#endif    ip = (struct IEEEdp *)&d;    return (ip->exp != 0x7ff);}static void dtoa (char *dbuf, rtype arg, int fmtch, int width, int prec){	char	buf[MAX_FCONVERSION+1], *cp;	char	sign;	int	size;	if( !_finite(arg) ) {		if( _isNan(arg) )			strcpy (dbuf, "NaN");		else if( arg < 0) 			strcpy (dbuf, "-Infinity");		else			strcpy (dbuf, "Infinity");		return;	}	if (prec == 0)		prec = 6;	else if (prec > MAX_FRACT)		prec = MAX_FRACT;	/* leave room for sign at start of buffer */	cp = buf + 1;    /*     * cvt may have to round up before the "start" of     * its buffer, i.e. ``intf("%.2f", (double)9.999);'';     * if the first character is still NUL, it did.     * softsign avoids negative 0 if _double < 0 but     * no significant digits will be shown.     */	*cp = '\0';	size = cvt (arg, prec, &sign, fmtch, cp, buf + sizeof(buf));	if (*cp == '\0')		cp++;	if (sign)		*--cp = sign, size++;	cp[size] = 0;	memcpy (dbuf, cp, size + 1);}static intcvt(rtype number, int prec, char *signp, int fmtch, char *startp, char *endp){	register char *p, *t;	register double fract;	double integer, tmp;	int dotrim, expcnt, gformat;	dotrim = expcnt = gformat = 0;	if (number < 0) {		number = -number;		*signp = '-';	} else		*signp = 0;	fract = modf(number, &integer);	/* get an extra slot for rounding. */	t = ++startp;	/*	 * get integer portion of number; put into the end of the buffer; the	 * .01 is added for modf(356.0 / 10, &integer) returning .59999999...	 */	for (p = endp - 1; integer; ++expcnt) {		tmp = modf(integer / 10, &integer);		*p-- = to_char((int)((tmp + .01) * 10));	}	switch (fmtch) {	case 'f':		/* reverse integer into beginning of buffer */		if (expcnt)			for (; ++p < endp; *t++ = *p);		else			*t++ = '0';		/*		 * if precision required or alternate flag set, add in a		 * decimal point.		 */		if (prec || TESTFLAG(ALTERNATE_FORM))			*t++ = '.';		/* if requires more precision and some fraction left */		if (fract) {			if (prec)				do {					fract = modf(fract * 10, &tmp);					*t++ = to_char((int)tmp);				} while (--prec && fract);			if (fract)				startp = round(fract, (int *)NULL, startp,				    t - 1, (char)0, signp);		}		for (; prec--; *t++ = '0');		break;	case 'e':	case 'E':eformat:	if (expcnt) {			*t++ = *++p;			if (prec || TESTFLAG(ALTERNATE_FORM))				*t++ = '.';			/* if requires more precision and some integer left */			for (; prec && ++p < endp; --prec)				*t++ = *p;			/*			 * if done precision and more of the integer component,			 * round using it; adjust fract so we don't re-round			 * later.			 */			if (!prec && ++p < endp) {				fract = 0;				startp = round((double)0, &expcnt, startp,				    t - 1, *p, signp);			}			/* adjust expcnt for digit in front of decimal */			--expcnt;		}		/* until first fractional digit, decrement exponent */		else if (fract) {			/* adjust expcnt for digit in front of decimal */			for (expcnt = -1;; --expcnt) {				fract = modf(fract * 10, &tmp);				if (tmp)					break;			}			*t++ = to_char((int)tmp);			if (prec || TESTFLAG(ALTERNATE_FORM))				*t++ = '.';		}		else {			*t++ = '0';			if (prec || TESTFLAG(ALTERNATE_FORM))				*t++ = '.';		}		/* if requires more precision and some fraction left */		if (fract) {			if (prec)				do {					fract = modf(fract * 10, &tmp);					*t++ = to_char((int)tmp);				} while (--prec && fract);			if (fract)				startp = round(fract, &expcnt, startp,				    t - 1, (char)0, signp);		}		/* if requires more precision */		for (; prec--; *t++ = '0');		/* unless alternate flag, trim any g/G format trailing 0's */		if (gformat && !TESTFLAG(ALTERNATE_FORM)) {			while (t > startp && *--t == '0');			if (*t == '.')				--t;			++t;		}		t = exponent(t, expcnt, fmtch);		break;	case 'g':	case 'G':		/* a precision of 0 is treated as a precision of 1. */		if (!prec)			++prec;		/*		 * ``The style used depends on the value converted; style e		 * will be used only if the exponent resulting from the		 * conversion is less than -4 or greater than the precision.''		 *	-- ANSI X3J11		 */		if (expcnt > prec || (!expcnt && fract && fract < .0001)) {			/*			 * g/G format counts "significant digits, not digits of			 * precision; for the e/E format, this just causes an			 * off-by-one problem, i.e. g/G considers the digit			 * before the decimal point significant and e/E doesn't			 * count it as precision.			 */			--prec;			fmtch -= 2;		/* G->E, g->e */			gformat = 1;			goto eformat;		}		/*		 * reverse integer into beginning of buffer,		 * note, decrement precision		 */		if (expcnt)			for (; ++p < endp; *t++ = *p, --prec);		else			*t++ = '0';		/*		 * if precision required or alternate flag set, add in a		 * decimal point.  If no digits yet, add in leading 0.		 */		if (prec || TESTFLAG(ALTERNATE_FORM)) {			dotrim = 1;			*t++ = '.';		}		else			dotrim = 0;		/* if requires more precision and some fraction left */		if (fract) {			if (prec) {			        do {				    fract = modf(fract * 10, &tmp);				    *t++ = to_char((int)tmp);				} while(!tmp && !expcnt);				while (--prec && fract) {					fract = modf(fract * 10, &tmp);					*t++ = to_char((int)tmp);				}			}			if (fract)				startp = round(fract, (int *)NULL, startp,				    t - 1, (char)0, signp);		}		/* alternate format, adds 0's for precision, else trim 0's */		if (TESTFLAG(ALTERNATE_FORM))			for (; prec--; *t++ = '0');		else if (dotrim) {			while (t > startp && *--t == '0');			if (*t != '.')				++t;		}	}	return (t - startp);}static char *round(double fract, int *exp, char *start, char *end, char ch, char *signp){	double tmp;	if (fract)		(void)modf(fract * 10, &tmp);	else		tmp = to_digit(ch);	if (tmp > 4)		for (;; --end) {			if (*end == '.')				--end;			if (++*end <= '9')				break;			*end = '0';			if (end == start) {				if (exp) {	/* e/E; increment exponent */					*end = '1';					++*exp;				}				else {		/* f; add extra digit */				*--end = '1';				--start;				}				break;			}		}	/* ``"%.3f", (double)-0.0004'' gives you a negative 0. */	else if (*signp == '-')		for (;; --end) {			if (*end == '.')				--end;			if (*end != '0')				break;			if (end == start)				*signp = 0;		}	return (start);}static char *exponent(char *p, int exp, int fmtch){	char *t;	char expbuf[MAX_FCONVERSION];	*p++ = fmtch;	if (exp < 0) {		exp = -exp;		*p++ = '-';	}	else		*p++ = '+';	t = expbuf + MAX_FCONVERSION;	if (exp > 9) {		do {			*--t = to_char(exp % 10);		} while ((exp /= 10) > 9);		*--t = to_char(exp);		for (; t < expbuf + MAX_FCONVERSION; *p++ = *t++);	}	else {		*p++ = '0';		*p++ = to_char(exp);	}	return (p);}#endif /* FLOATINGPT */

⌨️ 快捷键说明

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