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

📄 vfprintf.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * pANS stdio -- vfprintf */#include "iolib.h"/* * Leading flags */#define	SPACE	1		/* ' ' prepend space if no sign printed */#define	ALT	2		/* '#' use alternate conversion */#define	SIGN	4		/* '+' prepend sign, even if positive */#define	LEFT	8		/* '-' left-justify */#define	ZPAD	16		/* '0' zero-pad *//* * Trailing flags */#define	SHORT	32		/* 'h' convert a short integer */#define	LONG	64		/* 'l' convert a long integer */#define	LDBL	128		/* 'L' convert a long double */#define	PTR	256		/*     convert a void * (%p) */static int lflag[] = {	/* leading flags */0,	0,	0,	0,	0,	0,	0,	0,	/* ^@ ^A ^B ^C ^D ^E ^F ^G */0,	0,	0,	0,	0,	0,	0,	0,	/* ^H ^I ^J ^K ^L ^M ^N ^O */0,	0,	0,	0,	0,	0,	0,	0,	/* ^P ^Q ^R ^S ^T ^U ^V ^W */0,	0,	0,	0,	0,	0,	0,	0,	/* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */SPACE,	0,	0,	ALT,	0,	0,	0,	0,	/* sp  !  "  #  $  %  &  ' */0,	0,	0,	SIGN,	0,	LEFT,	0,	0,	/*  (  )  *  +  ,  -  .  / */ZPAD,	0,	0,	0,	0,	0,	0,	0,	/*  0  1  2  3  4  5  6  7 */0,	0,	0,	0,	0,	0,	0,	0,	/*  8  9  :  ;  <  =  >  ? */0,	0,	0,	0,	0,	0,	0,	0,	/*  @  A  B  C  D  E  F  G */0,	0,	0,	0,	0,	0,	0,	0,	/*  H  I  J  K  L  M  N  O */0,	0,	0,	0,	0,	0,	0,	0,	/*  P  Q  R  S  T  U  V  W */0,	0,	0,	0,	0,	0,	0,	0,	/*  X  Y  Z  [  \  ]  ^  _ */0,	0,	0,	0,	0,	0,	0,	0,	/*  `  a  b  c  d  e  f  g */0,	0,	0,	0,	0,	0,	0,	0,	/*  h  i  j  k  l  m  n  o */0,	0,	0,	0,	0,	0,	0,	0,	/*  p  q  r  s  t  u  v  w */0,	0,	0,	0,	0,	0,	0,	0,	/*  x  y  z  {  |  }  ~ ^? */0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,};static int tflag[] = {	/* trailing flags */0,	0,	0,	0,	0,	0,	0,	0,	/* ^@ ^A ^B ^C ^D ^E ^F ^G */0,	0,	0,	0,	0,	0,	0,	0,	/* ^H ^I ^J ^K ^L ^M ^N ^O */0,	0,	0,	0,	0,	0,	0,	0,	/* ^P ^Q ^R ^S ^T ^U ^V ^W */0,	0,	0,	0,	0,	0,	0,	0,	/* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */0,	0,	0,	0,	0,	0,	0,	0,	/* sp  !  "  #  $  %  &  ' */0,	0,	0,	0,	0,	0,	0,	0,	/*  (  )  *  +  ,  -  .  / */0,	0,	0,	0,	0,	0,	0,	0,	/*  0  1  2  3  4  5  6  7 */0,	0,	0,	0,	0,	0,	0,	0,	/*  8  9  :  ;  <  =  >  ? */0,	0,	0,	0,	0,	0,	0,	0,	/*  @  A  B  C  D  E  F  G */0,	0,	0,	0,	LDBL,	0,	0,	0,	/*  H  I  J  K  L  M  N  O */0,	0,	0,	0,	0,	0,	0,	0,	/*  P  Q  R  S  T  U  V  W */0,	0,	0,	0,	0,	0,	0,	0,	/*  X  Y  Z  [  \  ]  ^  _ */0,	0,	0,	0,	0,	0,	0,	0,	/*  `  a  b  c  d  e  f  g */SHORT,	0,	0,	0,	LONG,	0,	0,	0,	/*  h  i  j  k  l  m  n  o */0,	0,	0,	0,	0,	0,	0,	0,	/*  p  q  r  s  t  u  v  w */0,	0,	0,	0,	0,	0,	0,	0,	/*  x  y  z  {  |  }  ~ ^? */0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,};static int ocvt_E(FILE *, va_list *, int, int, int);static int ocvt_G(FILE *, va_list *, int, int, int);static int ocvt_X(FILE *, va_list *, int, int, int);static int ocvt_c(FILE *, va_list *, int, int, int);static int ocvt_d(FILE *, va_list *, int, int, int);static int ocvt_e(FILE *, va_list *, int, int, int);static int ocvt_f(FILE *, va_list *, int, int, int);static int ocvt_g(FILE *, va_list *, int, int, int);static int ocvt_n(FILE *, va_list *, int, int, int);static int ocvt_o(FILE *, va_list *, int, int, int);static int ocvt_p(FILE *, va_list *, int, int, int);static int ocvt_s(FILE *, va_list *, int, int, int);static int ocvt_u(FILE *, va_list *, int, int, int);static int ocvt_x(FILE *, va_list *, int, int, int);static int(*ocvt[])(FILE *, va_list *, int, int, int) = {0,	0,	0,	0,	0,	0,	0,	0,	/* ^@ ^A ^B ^C ^D ^E ^F ^G */0,	0,	0,	0,	0,	0,	0,	0,	/* ^H ^I ^J ^K ^L ^M ^N ^O */0,	0,	0,	0,	0,	0,	0,	0,	/* ^P ^Q ^R ^S ^T ^U ^V ^W */0,	0,	0,	0,	0,	0,	0,	0,	/* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */0,	0,	0,	0,	0,	0,	0,	0,	/* sp  !  "  #  $  %  &  ' */0,	0,	0,	0,	0,	0,	0,	0,	/*  (  )  *  +  ,  -  .  / */0,	0,	0,	0,	0,	0,	0,	0,	/*  0  1  2  3  4  5  6  7 */0,	0,	0,	0,	0,	0,	0,	0,	/*  8  9  :  ;  <  =  >  ? */0,	0,	0,	0,	0,	ocvt_E,	0,	ocvt_G,	/*  @  A  B  C  D  E  F  G */0,	0,	0,	0,	0,	0,	0,	0,	/*  H  I  J  K  L  M  N  O */0,	0,	0,	0,	0,	0,	0,	0,	/*  P  Q  R  S  T  U  V  W */ocvt_X,	0,	0,	0,	0,	0,	0,	0,	/*  X  Y  Z  [  \  ]  ^  _ */0,	0,	0,	ocvt_c,	ocvt_d,	ocvt_e,	ocvt_f,	ocvt_g,	/*  `  a  b  c  d  e  f  g */0,	ocvt_d,	0,	0,	0,	0,	ocvt_n,	ocvt_o,	/*  h  i  j  k  l  m  n  o */ocvt_p,	0,	0,	ocvt_s,	0,	ocvt_u,	0,	0,	/*  p  q  r  s  t  u  v  w */ocvt_x,	0,	0,	0,	0,	0,	0,	0,	/*  x  y  z  {  |  }  ~ ^? */0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,0,	0,	0,	0,	0,	0,	0,	0,};static int nprint;QLock _stdiolk;intvfprintf(FILE *f, const char *s, va_list args){	int flags, width, precision;	qlock(&_stdiolk);	nprint = 0;	while(*s){		if(*s != '%'){			putc(*s++, f);			nprint++;			continue;		}		s++;		flags = 0;		while(lflag[*s&_IO_CHMASK]) flags |= lflag[*s++&_IO_CHMASK];		if(*s == '*'){			width = va_arg(args, int);			s++;			if(width<0){				flags |= LEFT;				width = -width;			}		}		else{			width = 0;			while('0'<=*s && *s<='9') width = width*10 + *s++ - '0';		}		if(*s == '.'){			s++;			if(*s == '*'){				precision = va_arg(args, int);				s++;			}			else{				precision = 0;				while('0'<=*s && *s<='9') precision = precision*10 + *s++ - '0';			}		}		else			precision = -1;		while(tflag[*s&_IO_CHMASK]) flags |= tflag[*s++&_IO_CHMASK];		if(ocvt[*s]) nprint += (*ocvt[*s++])(f, &args, flags, width, precision);		else if(*s){			putc(*s++, f);			nprint++;		}	}	qunlock(&_stdiolk);	if(ferror(f)){		if((f->flags&STRING) && f->wp==f->rp && f->wp>f->buf){			*(f->wp-1) = '\0';			return nprint;		}		return -1;	}	return nprint;}static intocvt_c(FILE *f, va_list *args, int flags, int width, int precision){#pragma ref precision	int i;	if(!(flags&LEFT)) for(i=1; i<width; i++) putc(' ', f);	putc((unsigned char)va_arg(*args, int), f);	if(flags&LEFT) for(i=1; i<width; i++) putc(' ', f);	return width<1 ? 1 : width;}static intocvt_s(FILE *f, va_list *args, int flags, int width, int precision){	int i, n = 0;	char *s;	s = va_arg(*args, char *);	if(!(flags&LEFT)){		if(precision >= 0)			for(i=0; i!=precision && s[i]; i++);		else			for(i=0; s[i]; i++);		for(; i<width; i++){			putc(' ', f);			n++;		}	}	if(precision >= 0){		for(i=0; i!=precision && *s; i++){			putc(*s++, f);			n++;		}	} else{		for(i=0;*s;i++){			putc(*s++, f);			n++;		}	}	if(flags&LEFT){		for(; i<width; i++){			putc(' ', f);			n++;		}	}	return n;}static intocvt_n(FILE *f, va_list *args, int flags, int width, int precision){#pragma ref f#pragma ref width#pragma ref precision	if(flags&SHORT)		*va_arg(*args, short *) = nprint;	else if(flags&LONG)		*va_arg(*args, long *) = nprint;	else		*va_arg(*args, int *) = nprint;	return 0;}/* * Generic fixed-point conversion *	f is the output FILE *; *	args is the va_list * from which to get the number; *	flags, width and precision are the results of printf-cracking; *	radix is the number base to print in; *	alphabet is the set of digits to use; *	prefix is the prefix to print before non-zero numbers when *	using ``alternate form.'' */static intocvt_fixed(FILE *f, va_list *args, int flags, int width, int precision,	int radix, int sgned, char alphabet[], char *prefix){	char digits[128];	/* no reasonable machine will ever overflow this */	char *sign;	char *dp;	long snum;	unsigned long num;	int nout, npad, nlzero;	if(sgned){		if(flags&PTR) snum = (long)va_arg(*args, void *);		else if(flags&SHORT) snum = va_arg(*args, short);		else if(flags&LONG) snum = va_arg(*args, long);		else snum = va_arg(*args, int);		if(snum < 0){			sign = "-";			num = -snum;		} else{			if(flags&SIGN) sign = "+";			else if(flags&SPACE) sign = " ";			else sign = "";			num = snum;		}	} else {		sign = "";		if(flags&PTR) num = (long)va_arg(*args, void *);		else if(flags&SHORT) num = va_arg(*args, unsigned short);		else if(flags&LONG) num = va_arg(*args, unsigned long);		else num = va_arg(*args, unsigned int);	}	if(num == 0) prefix = "";	dp = digits;	do{		*dp++ = alphabet[num%radix];		num /= radix;	}while(num);	if(precision==0 && dp-digits==1 && dp[-1]=='0')		dp--;	nlzero = precision-(dp-digits);	if(nlzero < 0) nlzero = 0;	if(flags&ALT){		if(radix == 8) if(dp[-1]=='0' || nlzero) prefix = "";	}	else prefix = "";	nout = dp-digits+nlzero+strlen(prefix)+strlen(sign);	npad = width-nout;	if(npad < 0) npad = 0;	nout += npad;	if(!(flags&LEFT)){		if(flags&ZPAD && precision <= 0){			fputs(sign, f);			fputs(prefix, f);			while(npad){				putc('0', f);				--npad;			}		} else{			while(npad){				putc(' ', f);				--npad;			}			fputs(sign, f);			fputs(prefix, f);		}		while(nlzero){			putc('0', f);			--nlzero;		}		while(dp!=digits) putc(*--dp, f);	}	else{		fputs(sign, f);		fputs(prefix, f);		while(nlzero){			putc('0', f);			--nlzero;		}		while(dp != digits) putc(*--dp, f);		while(npad){			putc(' ', f);			--npad;		}	}	return nout;	}static intocvt_X(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_fixed(f, args, flags, width, precision, 16, 0, "0123456789ABCDEF", "0X");}static intocvt_d(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_fixed(f, args, flags, width, precision, 10, 1, "0123456789", "");}static intocvt_o(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_fixed(f, args, flags, width, precision, 8, 0, "01234567", "0");}static intocvt_p(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_fixed(f, args, flags|PTR|ALT, width, precision, 16, 0,		"0123456789ABCDEF", "0X");}static intocvt_u(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_fixed(f, args, flags, width, precision, 10, 0, "0123456789", "");}static intocvt_x(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_fixed(f, args, flags, width, precision, 16, 0, "0123456789abcdef", "0x");}static int ocvt_flt(FILE *, va_list *, int, int, int, char);static intocvt_E(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_flt(f, args, flags, width, precision, 'E');}static intocvt_G(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_flt(f, args, flags, width, precision, 'G');}static intocvt_e(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_flt(f, args, flags, width, precision, 'e');}static intocvt_f(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_flt(f, args, flags, width, precision, 'f');}static intocvt_g(FILE *f, va_list *args, int flags, int width, int precision){	return ocvt_flt(f, args, flags, width, precision, 'g');}static intocvt_flt(FILE *f, va_list *args, int flags, int width, int precision, char afmt){	int echr;	char *digits, *edigits;	int exponent;	char fmt;	int sign;	int ndig;	int nout, i;	char ebuf[20];	/* no sensible machine will overflow this */	char *eptr;	double d;	echr = 'e';	fmt = afmt;	d = va_arg(*args, double);	if(precision < 0) precision = 6;	switch(fmt){	case 'f':		digits = dtoa(d, 3, precision, &exponent, &sign, &edigits);		break;	case 'E':		echr = 'E';		fmt = 'e';		/* fall through */	case 'e':		digits = dtoa(d, 2, 1+precision, &exponent, &sign, &edigits);		break;	case 'G':		echr = 'E';		/* fall through */	case 'g':		if (precision > 0)			digits = dtoa(d, 2, precision, &exponent, &sign, &edigits);		else {			digits = dtoa(d, 0, precision, &exponent, &sign, &edigits);			precision = edigits - digits;			if (exponent > precision && exponent <= precision + 4)				precision = exponent;			}		if(exponent >= -3 && exponent <= precision){			fmt = 'f';			precision -= exponent;		}else{			fmt = 'e';			--precision;		}		break;	}	if (exponent == 9999) {		/* Infinity or Nan */		precision = 0;		exponent = edigits - digits;		fmt = 'f';	}	ndig = edigits-digits;	if((afmt=='g' || afmt=='G') && !(flags&ALT)){	/* knock off trailing zeros */		if(fmt == 'f'){			if(precision+exponent > ndig) {				precision = ndig - exponent;				if(precision < 0)					precision = 0;			}		}		else{			if(precision > ndig-1) precision = ndig-1;		}	}	nout = precision;				/* digits after decimal point */	if(precision!=0 || flags&ALT) nout++;		/* decimal point */	if(fmt=='f' && exponent>0) nout += exponent;	/* digits before decimal point */	else nout++;					/* there's always at least one */	if(sign || flags&(SPACE|SIGN)) nout++;		/* sign */	if(fmt != 'f'){					/* exponent */		eptr = ebuf;		for(i=exponent<=0?1-exponent:exponent-1; i; i/=10)			*eptr++ = '0' + i%10;		while(eptr<ebuf+2) *eptr++ = '0';		nout += eptr-ebuf+2;			/* e+99 */	}	if(!(flags&ZPAD) && !(flags&LEFT))		while(nout < width){			putc(' ', f);			nout++;		}	if(sign) putc('-', f);	else if(flags&SIGN) putc('+', f);	else if(flags&SPACE) putc(' ', f);	if(flags&ZPAD)		while(nout < width){			putc('0', f);			nout++;		}	if(fmt == 'f'){		for(i=0; i<exponent; i++) putc(i<ndig?digits[i]:'0', f);		if(i == 0) putc('0', f);		if(precision>0 || flags&ALT) putc('.', f);		for(i=0; i!=precision; i++)			putc(0<=i+exponent && i+exponent<ndig?digits[i+exponent]:'0', f);	}	else{		putc(digits[0], f);		if(precision>0 || flags&ALT) putc('.', f);		for(i=0; i!=precision; i++) putc(i<ndig-1?digits[i+1]:'0', f);	}	if(fmt != 'f'){		putc(echr, f);		putc(exponent<=0?'-':'+', f);		while(eptr>ebuf) putc(*--eptr, f);	}	while(nout < width){		putc(' ', f);		nout++;	}	freedtoa(digits);	return nout;}

⌨️ 快捷键说明

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