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

📄 sfvprintf.c

📁 su 的源代码库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright (c) Colorado School of Mines, 2006.*//* All rights reserved.                       */#include	"sfhdr.h"/*	The engine for formatting data.**	1. Argument positioning is done in sftable.c so any changes**	   made here should be reflected in sftable.c as well.**	2. For internationalization, Sfio only supports I/O of multibyte strings.**	   However, this code does provide minimal support so that Stdio functions**	   such as fwprintf/swprintf can be emulated (see stdvwprintf()).****	Written by Kiem-Phong Vo.*/#define HIGHBITI	(~((~((uint)0)) >> 1))#define HIGHBITL	(~((~((Sfulong_t)0)) >> 1))#define SFFMT_PREFIX	(SFFMT_MINUS|SFFMT_SIGN|SFFMT_BLANK)#define FPRECIS		6	/* default precision for floats 	*/#if _PACKAGE_ast#include <ccode.h>#else/* characters when using ebcdic or ascii */#if _chr_ebcdic#define CC_vt			013	/* vertical tab	*/#define CC_esc			047	/* escape	*/#define CC_bel			057	/* bell		*/#else#define CC_vt			013	/* vertical tab	*/#define CC_esc			033	/* escape	*/#define CC_bel			007	/* bell		*/#endif /* _chr_ebcdic */#endif /* _PACKAGE_ast */#if __STD_Cstatic int chr2str(char* buf, int v)#elsestatic int chr2str(buf, v)char*	buf;int	v;#endif{	if(isprint(v) && v != '\\')	{	*buf++ = v;		return 1;	}	else	{	*buf++ = '\\';		switch(v)		{ case CC_bel:	*buf++ = 'a'; return 2;		  case CC_vt:	*buf++ = 'v'; return 2;		  case CC_esc:	*buf++ = 'E'; return 2;		  case '\b':	*buf++ = 'b'; return 2;		  case '\f':	*buf++ = 'f'; return 2;		  case '\n':	*buf++ = 'n'; return 2;		  case '\r':	*buf++ = 'r'; return 2;		  case '\t':	*buf++ = 't'; return 2;		  case '\\':	*buf++ = '\\'; return 2;		  default:	*buf++ = '0' + ((v >> 6) & 03);				*buf++ = '0' + ((v >> 3) & 07);				*buf++ = '0' + ((v >> 0) & 07);				return 4;		}	}}/* On some platform(s), large functions are not compilable.** In such a case, the below macro should be defined non-zero so that** some in-lined macros will be made smaller, trading time for space.*/#if !defined(_sffmt_small) && defined(_UTS)#define _sffmt_small	1#endif#if __STD_Cint sfvprintf(Sfio_t* f, const char* form, va_list args)#elseint sfvprintf(f,form,args)Sfio_t*	f;		/* file to print to	*/char*	form;		/* format to use	*/va_list	args;		/* arg list if !argf	*/#endif{	int		n, v, k, n_s, base, fmt, flags;	Sflong_t	lv;	char		*sp, *ssp, *endsp, *ep, *endep;	int		dot, width, precis, sign, decpt;	ssize_t		size;	Sfdouble_t	dval;	char		*tls[2], **ls;	/* for %..[separ]s		*/	char*		t_str;		/* stuff between ()		*/	ssize_t		n_str;		/* its length			*/	Argv_t		argv;		/* for extf to return value	*/	Sffmt_t		*ft;		/* format environment		*/	Fmt_t		*fm, *fmstk;	/* stack contexts		*/	char*		oform;		/* original format string	*/	va_list		oargs;		/* original arg list		*/	Fmtpos_t*	fp;		/* arg position list		*/	int		argp, argn;	/* arg position and number	*/#define SLACK		1024	char		buf[SF_MAXDIGITS+SLACK], tmp[SF_MAXDIGITS], data[SF_GRAIN];	int		decimal = 0, thousand = 0;#if _has_multibyte	wchar_t*	wsp;	SFMBDCL(fmbs)			/* state of format string	*/	SFMBDCL(mbs)			/* state of some string		*/#endif	/* local io system */	int		w, n_output;#define SMputc(f,c)	{ if((w = SFFLSBUF(f,c)) >= 0 ) n_output += 1; \			  else		{ SFBUF(f); goto done; } \			}#define SMnputc(f,c,n)	{ if((w = SFNPUTC(f,c,n)) > 0 ) n_output += 1; \			  if(w != n)	{ SFBUF(f); goto done; } \			}#define SMwrite(f,s,n)	{ if((w = SFWRITE(f,(Void_t*)s,n)) > 0 ) n_output += w; \			  if(w != n)	{ SFBUF(f); goto done; } \			}#if _sffmt_small /* these macros are made smaller at some performance cost */#define SFBUF(f)#define SFINIT(f)	(n_output = 0)#define SFEND(f)#define SFputc(f,c)	SMputc(f,c)#define SFnputc(f,c,n)	SMnputc(f,c,n)#define SFwrite(f,s,n)	SMwrite(f,s,n)#else	uchar	*d, *endd;#define SFBUF(f)	(d = f->next, endd = f->endb)#define SFINIT(f)	(SFBUF(f), n_output = 0)#define SFEND(f)	((n_output += d - f->next), (f->next = d))#define SFputc(f,c)	{ if(d < endd) 	  { *d++ = (uchar)c; } \	  		  else		  { SFEND(f); SMputc(f,c); SFBUF(f); } \	  		}#define SFnputc(f,c,n)	{ if(d+n <= endd) { while(n--) *d++ = (uchar)(c); } \			  else		  { SFEND(f); SMnputc(f,c,n); SFBUF(f); } \			}#define SFwrite(f,s,n)	{ if(d+n <= endd) { while(n--) *d++ = (uchar)(*s++); } \			  else 		  { SFEND(f); SMwrite(f,s,n); SFBUF(f); } \			}#endif /* _sffmt_small */	SFCVINIT();	/* initialize conversion tables */	SFMTXSTART(f,-1);	if(!form)		SFMTXRETURN(f, -1);	/* make sure stream is in write mode and buffer is not NULL */	if(f->mode != SF_WRITE && _sfmode(f,SF_WRITE,0) < 0)		SFMTXRETURN(f, -1);	SFLOCK(f,0);	if(!f->data && !(f->flags&SF_STRING))	{	f->data = f->next = (uchar*)data;		f->endb = f->data+sizeof(data);	}	SFINIT(f);	tls[1] = NIL(char*);	fmstk = NIL(Fmt_t*);	ft = NIL(Sffmt_t*);	oform = (char*)form;	va_copy(oargs,args);	argn = -1;	fp = NIL(Fmtpos_t*);loop_fmt :	SFMBCLR(&fmbs); /* clear multibyte states to parse the format string */	while((n = *form) )	{	if(n != '%') /* collect the non-pattern chars */		{	sp = (char*)form;			for(;;)			{	form += SFMBLEN(form, &fmbs);				if(*form == 0 || *form == '%')					break;			}			n = form-sp;			SFwrite(f,sp,n);			continue;		}		else	form += 1;		flags = 0;		size = width = precis = base = n_s = argp = -1;		ssp = _Sfdigits;		endep = ep = NIL(char*);		endsp = sp = buf+(sizeof(buf)-1);		t_str = NIL(char*);		n_str = dot = 0;	loop_flags:	/* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */		switch((fmt = *form++) )		{		case '\0':			SFputc(f,'%');			goto pop_fmt;		case '%' :			SFputc(f,'%');			continue;		case LEFTP : /* get the type enclosed in balanced parens */			t_str = (char*)form;			for(v = 1;;)			{	switch(*form++)				{				case 0 :	/* not balancable, retract */					form = t_str;					t_str = NIL(char*);					n_str = 0;					goto loop_flags;				case LEFTP :	/* increasing nested level */					v += 1;					continue;				case RIGHTP :	/* decreasing nested level */					if((v -= 1) != 0)						continue;					if(*t_str != '*' )						n_str = (form-1)-t_str;					else					{	t_str = (*_Sffmtintf)(t_str+1,&n);						if(*t_str == '$')						{	if(!fp &&							   !(fp = (*_Sffmtposf)								  (f,oform,oargs,ft,0)) )								goto pop_fmt;							n = FP_SET(n,argn);						}						else	n = FP_SET(-1,argn);						if(fp)						{	t_str = fp[n].argv.s;							n_str = fp[n].ft.size;						}						else if(ft && ft->extf )						{	FMTSET(ft, form,args,								LEFTP, 0, 0, 0,0,0,								NIL(char*),0);							n = (*ft->extf)							      (f,(Void_t*)&argv,ft);							if(n < 0)								goto pop_fmt;							if(!(ft->flags&SFFMT_VALUE) )								goto t_arg;							if((t_str = argv.s) &&							   (n_str = (int)ft->size) < 0)								n_str = strlen(t_str);						}						else						{ t_arg:							if((t_str = va_arg(args,char*)) )								n_str = strlen(t_str);						}					}					goto loop_flags;				}			}		case '-' :			flags = (flags & ~SFFMT_ZERO) | SFFMT_LEFT;			goto loop_flags;		case '0' :			if(!(flags&SFFMT_LEFT) )				flags |= SFFMT_ZERO;			goto loop_flags;		case ' ' :			if(!(flags&SFFMT_SIGN) )				flags |= SFFMT_BLANK;			goto loop_flags;		case '+' :			flags = (flags & ~SFFMT_BLANK) | SFFMT_SIGN;			goto loop_flags;		case '#' :			flags |= SFFMT_ALTER;			goto loop_flags;		case QUOTE:			SFSETLOCALE(&decimal,&thousand);			if(thousand > 0)				flags |= SFFMT_THOUSAND;			goto loop_flags;		case '.' :			dot += 1;			if(dot == 1)			{	/* so base can be defined without setting precis */				if(*form != '.')					precis = 0;			}			else if(dot == 2)			{	base = 0; /* for %s,%c */				v = form[0] == 'l' ? form[1] : form[0];				if(v == 'c' || v == 'C' || v == 's' || v == 'S')					goto loop_flags;				if(*form && !isalnum(*form))				{	v = form[1] == 'l' ? form[2] : form[1];					if(v == 'c' || v == 'C' || v == 's' || v == 'S')					{	if(*form == '*')							goto do_star;						else						{	base = *form++;							goto loop_flags;						}					}				}			}			if(isdigit(*form) )			{	fmt = *form++;				goto dot_size;			}			else if(*form != '*')				goto loop_flags;		do_star:			form += 1; /* fall thru for '*' */		case '*' :			form = (*_Sffmtintf)(form,&n);			if(*form == '$')			{	form += 1;				if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)) )					goto pop_fmt;				n = FP_SET(n,argn);			}			else	n = FP_SET(-1,argn);			if(fp)				v = fp[n].argv.i;			else if(ft && ft->extf)			{	FMTSET(ft, form,args, '.',dot, 0, 0,0,0, NIL(char*), 0);				if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)					goto pop_fmt;				fmt = ft->fmt;				flags = (flags&~SFFMT_TYPES) | (ft->flags&SFFMT_TYPES);				if(ft->flags&SFFMT_VALUE)					v = argv.i;				else	v = (dot <= 2) ? va_arg(args,int) : 0;			}			else	v = dot <= 2 ? va_arg(args,int) : 0;			goto dot_set;		case '1' : case '2' : case '3' :		case '4' : case '5' : case '6' :		case '7' : case '8' : case '9' :		dot_size :			for(v = fmt - '0'; isdigit(*form); ++form)				v = v*10 + (*form - '0');			if(*form == '$')			{	form += 1;				if(!fp && !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)) )					goto pop_fmt;				argp = v-1;				goto loop_flags;			}		dot_set :			if(dot == 0)			{	if((width = v) < 0)				{	width = -width;					flags = (flags & ~SFFMT_ZERO) | SFFMT_LEFT;				}			}			else if(dot == 1)				precis = v;			else if(dot == 2)				base = v;			goto loop_flags;		case 'I' : /* object length */			size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;			if(isdigit(*form) )			{	for(size = 0, n = *form; isdigit(n); n = *++form)					size = size*10 + (n - '0');			}			else if(*form == '*')			{	form = (*_Sffmtintf)(form+1,&n);				if(*form == '$')				{	form += 1;					if(!fp &&					   !(fp = (*_Sffmtposf)(f,oform,oargs,ft,0)))						goto pop_fmt;					n = FP_SET(n,argn);				}				else	n = FP_SET(-1,argn);				if(fp)	/* use position list */					size = fp[n].argv.i;				else if(ft && ft->extf)				{	FMTSET(ft, form,args, 'I',sizeof(int), 0, 0,0,0,						NIL(char*), 0);					if((*ft->extf)(f, (Void_t*)(&argv), ft) < 0)						goto pop_fmt;					if(ft->flags&SFFMT_VALUE)						size = argv.i;					else	size = va_arg(args,int);				}				else	size = va_arg(args,int);			}			goto loop_flags;		case 'l' :			size = -1; flags &= ~SFFMT_TYPES;			if(*form == 'l')			{	form += 1;				flags |= SFFMT_LLONG;			}			else	flags |= SFFMT_LONG;			goto loop_flags;		case 'h' :			size = -1; flags &= ~SFFMT_TYPES;			if(*form == 'h')			{	form += 1;				flags |= SFFMT_SSHORT;			}			else	flags |= SFFMT_SHORT;			goto loop_flags;		case 'L' :			size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;			goto loop_flags;		case 'j' :			size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_JFLAG;			goto loop_flags;		case 'z' :			size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_ZFLAG;			goto loop_flags;		case 't' :			size = -1; flags = (flags&~SFFMT_TYPES) | SFFMT_TFLAG;			goto loop_flags;		default:			break;		}		/* set object size for scalars */		if(flags & SFFMT_TYPES)		{	if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')			{	if(flags&SFFMT_LONG)					size = sizeof(long);				else if(flags&SFFMT_SHORT)					size = sizeof(short);				else if(flags&SFFMT_SSHORT)					size = sizeof(char);				else if(flags&SFFMT_TFLAG)					size = sizeof(ptrdiff_t);				else if(flags&SFFMT_ZFLAG) 					size = sizeof(size_t);				else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )					size = sizeof(Sflong_t);				else if(flags&SFFMT_IFLAG)				{	if(size <= 0 ||					   size == sizeof(Sflong_t)*CHAR_BIT )						size = sizeof(Sflong_t);				}				else if(size < 0)					size = sizeof(int);			}			else if(_Sftype[fmt]&SFFMT_FLOAT)			{	if(flags&(SFFMT_LONG|SFFMT_LLONG))					size = sizeof(double);				else if(flags&SFFMT_LDOUBLE)					size = sizeof(Sfdouble_t);				else if(flags&SFFMT_IFLAG)				{	if(size <= 0)						size = sizeof(Sfdouble_t);				}				else if(size < 0)					size = sizeof(float);			}			else if(_Sftype[fmt]&SFFMT_CHAR)			{#if _has_multibyte				if((flags&SFFMT_LONG) || fmt == 'C')				{	size = sizeof(wchar_t) > sizeof(int) ?						sizeof(wchar_t) : sizeof(int);				} else#endif				if(size < 0)					size = sizeof(int);			}		}		argp = FP_SET(argp,argn);		if(fp)		{	if(ft && ft->extf && fp[argp].ft.fmt != fp[argp].fmt)				fmt = fp[argp].ft.fmt;			argv = fp[argp].argv;			size = fp[argp].ft.size;		}		else if(ft && ft->extf )	/* extended processing */		{	FMTSET(ft, form,args, fmt, size,flags, width,precis,base,				t_str,n_str);			SFEND(f); SFOPEN(f,0);			v = (*ft->extf)(f, (Void_t*)(&argv), ft);			SFLOCK(f,0); SFBUF(f);			if(v < 0)	/* no further processing */				goto pop_fmt;			else if(v > 0)	/* extf output v bytes */			{	n_output += v;				continue;			}			else		/* extf did not output */			{	FMTGET(ft, form,args, fmt, size,flags, width,precis,base);				if(!(ft->flags&SFFMT_VALUE))					goto arg_list;				else if(_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT) )				{	if(size == sizeof(short))					{	if(_Sftype[fmt]&SFFMT_INT)							argv.i = argv.h;						else	argv.i = argv.uh;					}					else if(size == sizeof(char))					{	if(_Sftype[fmt]&SFFMT_INT)							argv.i = argv.c;						else	argv.i = argv.uc;					}				}				else if(_Sftype[fmt]&SFFMT_FLOAT )				{	if(size == sizeof(float) )						argv.d = argv.f;				}				else if(_Sftype[fmt]&SFFMT_CHAR)				{	if(base < 0)						argv.i = (int)argv.c;				}			}		}		else		{ arg_list:			switch(_Sftype[fmt])			{ case SFFMT_INT:			  case SFFMT_UINT:#if !_ast_intmax_long				if(size == sizeof(Sflong_t))					argv.ll = va_arg(args, Sflong_t);				else#endif				if(size == sizeof(long) )					argv.l = va_arg(args, long);				else	argv.i = va_arg(args, int);				break;			 case SFFMT_FLOAT:#if !_ast_fltmax_double				if(size == sizeof(Sfdouble_t))					argv.ld = va_arg(args,Sfdouble_t);				else#endif					argv.d  = va_arg(args,double);				break;			 case SFFMT_POINTER:					argv.vp = va_arg(args,Void_t*);				break;			 case SFFMT_CHAR:				if(base >= 0)					argv.s = va_arg(args,char*);#if _has_multibyte				else if((flags & SFFMT_LONG) || fmt == 'C')				{	if(sizeof(wchar_t) <= sizeof(uint) )						argv.wc = (wchar_t)va_arg(args,uint);					else	argv.wc = va_arg(args,wchar_t);				}#endif				else	argv.i = va_arg(args,int);				break;			 default: /* unknown pattern */				break;			}		}		switch(fmt)	/* PRINTF DIRECTIVES */		{		default :	/* unknown directive */			form -= 1;			argn -= 1;			continue;		case '!' :	/* stacking a new environment */			if(!fp)				fp = (*_Sffmtposf)(f,oform,oargs,ft,0);			else	goto pop_fmt;			if(!argv.ft)				goto pop_fmt;			if(!argv.ft->form && ft ) /* change extension functions */			{	if(ft->eventf &&				   (*ft->eventf)(f,SF_DPOP,(Void_t*)form,ft) < 0)					continue;				fmstk->ft = ft = argv.ft;			}			else			/* stack a new environment */			{	if(!(fm = (Fmt_t*)malloc(sizeof(Fmt_t))) )					goto done;				ft = fm->ft = argv.ft;				SFMBSET(ft->mbs, &fmbs);				if(ft->form)				{	fm->form = (char*)form; SFMBCPY(&fm->mbs,&fmbs);					va_copy(fm->args,args);					fm->oform = oform;					va_copy(fm->oargs,oargs);					fm->argn = argn;					fm->fp = fp;					form = ft->form; SFMBCLR(ft->mbs);					va_copy(args,ft->args);					argn = -1;					fp = NIL(Fmtpos_t*);					oform = (char*)form;					va_copy(oargs,args);				}				else	fm->form = NIL(char*);				fm->eventf = ft->eventf;				fm->next = fmstk;				fmstk = fm;			}

⌨️ 快捷键说明

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