14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*8462SApril.Chin@Sun.COM *          Copyright (c) 1985-2008 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
7*8462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #include	"sfhdr.h"
234887Schin #include	"FEATURE/float"
244887Schin 
254887Schin /*	Dealing with $ argument addressing stuffs.
264887Schin **
274887Schin **	Written by Kiem-Phong Vo.
284887Schin */
294887Schin 
304887Schin #if __STD_C
314887Schin static char* sffmtint(const char* str, int* v)
324887Schin #else
334887Schin static char* sffmtint(str, v)
344887Schin char*	str;
354887Schin int*	v;
364887Schin #endif
374887Schin {
384887Schin 	for(*v = 0; isdigit(*str); ++str)
394887Schin 		*v = *v * 10 + (*str - '0');
404887Schin 	*v -= 1;
414887Schin 	return (char*)str;
424887Schin }
434887Schin 
444887Schin #if __STD_C
454887Schin static Fmtpos_t* sffmtpos(Sfio_t* f,const char* form,va_list args,Sffmt_t* ft,int type)
464887Schin #else
474887Schin static Fmtpos_t* sffmtpos(f,form,args,ft,type)
484887Schin Sfio_t*		f;
494887Schin char*		form;
504887Schin va_list		args;
514887Schin Sffmt_t*	ft;
524887Schin int		type;	/* >0: scanf, =0: printf, -1: internal	*/
534887Schin #endif
544887Schin {
554887Schin 	int		base, fmt, flags, dot, width, precis;
564887Schin 	ssize_t		n_str, size;
574887Schin 	char		*t_str, *sp;
584887Schin 	int		v, n, skip, dollar, decimal, thousand;
594887Schin 	Sffmt_t		savft;
604887Schin 	Fmtpos_t*	fp;	/* position array of arguments	*/
614887Schin 	int		argp, argn, maxp, need[FP_INDEX];
624887Schin #if _has_multibyte
634887Schin 	SFMBDCL(fmbs)
644887Schin #endif
654887Schin 
664887Schin 	if(type < 0)
674887Schin 		fp = NIL(Fmtpos_t*);
684887Schin 	else if(!(fp = sffmtpos(f,form,args,ft,-1)) )
694887Schin 		return NIL(Fmtpos_t*);
704887Schin 
714887Schin 	dollar = decimal = thousand = 0; argn = maxp = -1;
724887Schin 	SFMBCLR(&fmbs);
734887Schin 	while((n = *form) )
744887Schin 	{	if(n != '%') /* collect the non-pattern chars */
754887Schin 		{	sp = (char*)form;
764887Schin 			for(;;)
774887Schin 			{	form += SFMBLEN(form, &fmbs);
784887Schin 				if(*form == 0 || *form == '%')
794887Schin 					break;
804887Schin 			}
814887Schin 			continue;
824887Schin 		}
834887Schin 		else	form += 1;
844887Schin 		if(*form == 0)
854887Schin 			break;
864887Schin 		else if(*form == '%')
874887Schin 		{	form += 1;
884887Schin 			continue;
894887Schin 		}
904887Schin 
914887Schin 		if(*form == '*' && type > 0) /* skip in scanning */
924887Schin 		{	skip = 1;
934887Schin 			form += 1;
944887Schin 			argp = -1;
954887Schin 		}
964887Schin 		else /* get the position of this argument */
974887Schin 		{	skip = 0;
984887Schin 			sp = sffmtint(form,&argp);
994887Schin 			if(*sp == '$')
1004887Schin 			{	dollar = 1;
1014887Schin 				form = sp+1;
1024887Schin 			}
1034887Schin 			else	argp = -1;
1044887Schin 		}
1054887Schin 
1064887Schin 		flags = dot = 0;
1074887Schin 		t_str = NIL(char*); n_str = 0;
1084887Schin 		size = width = precis = base = -1;
1094887Schin 		for(n = 0; n < FP_INDEX; ++n)
1104887Schin 			need[n] = -1;
1114887Schin 
1124887Schin 	loop_flags:	/* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
1134887Schin 		switch((fmt = *form++) )
1144887Schin 		{
1154887Schin 		case LEFTP : /* get the type enclosed in balanced parens */
1164887Schin 			t_str = (char*)form;
1174887Schin 			for(v = 1;;)
1184887Schin 			{	switch(*form++)
1194887Schin 				{
1204887Schin 				case 0 :	/* not balancable, retract */
1214887Schin 					form = t_str;
1224887Schin 					t_str = NIL(char*);
1234887Schin 					n_str = 0;
1244887Schin 					goto loop_flags;
1254887Schin 				case LEFTP :	/* increasing nested level */
1264887Schin 					v += 1;
1274887Schin 					continue;
1284887Schin 				case RIGHTP :	/* decreasing nested level */
1294887Schin 					if((v -= 1) != 0)
1304887Schin 						continue;
1314887Schin 					n_str = form-t_str;
1324887Schin 					if(*t_str == '*')
1334887Schin 					{	t_str = sffmtint(t_str+1,&n);
1344887Schin 						if(*t_str == '$')
1354887Schin 							dollar = 1;
1364887Schin 						else	n = -1;
1374887Schin 						if((n = FP_SET(n,argn)) > maxp)
1384887Schin 							maxp = n;
1394887Schin 						if(fp && fp[n].ft.fmt == 0)
1404887Schin 						{	fp[n].ft.fmt = LEFTP;
1414887Schin 							fp[n].ft.form = (char*)form;
1424887Schin 						}
1434887Schin 						need[FP_STR] = n;
1444887Schin 					}
1454887Schin 					goto loop_flags;
1464887Schin 				}
1474887Schin 			}
1484887Schin 
1494887Schin 		case '-' :
1504887Schin 			flags |= SFFMT_LEFT;
1514887Schin 			flags &= ~SFFMT_ZERO;
1524887Schin 			goto loop_flags;
1534887Schin 		case '0' :
1544887Schin 			if(!(flags&SFFMT_LEFT) )
1554887Schin 				flags |= SFFMT_ZERO;
1564887Schin 			goto loop_flags;
1574887Schin 		case ' ' :
1584887Schin 			if(!(flags&SFFMT_SIGN) )
1594887Schin 				flags |= SFFMT_BLANK;
1604887Schin 			goto loop_flags;
1614887Schin 		case '+' :
1624887Schin 			flags |= SFFMT_SIGN;
1634887Schin 			flags &= ~SFFMT_BLANK;
1644887Schin 			goto loop_flags;
1654887Schin 		case '#' :
1664887Schin 			flags |= SFFMT_ALTER;
1674887Schin 			goto loop_flags;
1684887Schin 		case QUOTE:
1694887Schin 			SFSETLOCALE(&decimal,&thousand);
1704887Schin 			if(thousand > 0)
1714887Schin 				flags |= SFFMT_THOUSAND;
1724887Schin 			goto loop_flags;
1734887Schin 
1744887Schin 		case '.' :
1754887Schin 			if((dot += 1) == 2)
1764887Schin 				base = 0; /* for %s,%c */
1774887Schin 			if(isdigit(*form))
1784887Schin 			{	fmt = *form++;
1794887Schin 				goto dot_size;
1804887Schin 			}
1814887Schin 			else if(*form != '*')
1824887Schin 				goto loop_flags;
1834887Schin 			else	form += 1; /* drop thru below */
1844887Schin 
1854887Schin 		case '*' :
1864887Schin 			form = sffmtint(form,&n);
1874887Schin 			if(*form == '$' )
1884887Schin 			{	dollar = 1;
1894887Schin 				form += 1;
1904887Schin 			}
1914887Schin 			else	n = -1;
1924887Schin 			if((n = FP_SET(n,argn)) > maxp)
1934887Schin 				maxp = n;
1944887Schin 			if(fp && fp[n].ft.fmt == 0)
1954887Schin 			{	fp[n].ft.fmt = '.';
1964887Schin 				fp[n].ft.size = dot;
1974887Schin 				fp[n].ft.form = (char*)form;
1984887Schin 			}
1994887Schin 			if(dot <= 2)
2004887Schin 				need[dot] = n;
2014887Schin 			goto loop_flags;
2024887Schin 
2034887Schin 		case '1' : case '2' : case '3' :
2044887Schin 		case '4' : case '5' : case '6' :
2054887Schin 		case '7' : case '8' : case '9' :
2064887Schin 		dot_size :
2074887Schin 			for(v = fmt - '0', fmt = *form; isdigit(fmt); fmt = *++form)
2084887Schin 				v = v*10 + (fmt - '0');
2094887Schin 			if(dot == 0)
2104887Schin 				width = v;
2114887Schin 			else if(dot == 1)
2124887Schin 				precis = v;
2134887Schin 			else if(dot == 2)
2144887Schin 				base = v;
2154887Schin 			goto loop_flags;
2164887Schin 
2174887Schin 		case 'I' : /* object length */
2184887Schin 			size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
2194887Schin 			if(isdigit(*form) )
2204887Schin 			{	for(size = 0, n = *form; isdigit(n); n = *++form)
2214887Schin 					size = size*10 + (n - '0');
2224887Schin 			}
2234887Schin 			else if(*form == '*')
2244887Schin 			{	form = sffmtint(form+1,&n);
2254887Schin 				if(*form == '$' )
2264887Schin 				{	dollar = 1;
2274887Schin 					form += 1;
2284887Schin 				}
2294887Schin 				else	n = -1;
2304887Schin 				if((n = FP_SET(n,argn)) > maxp)
2314887Schin 					maxp = n;
2324887Schin 				if(fp && fp[n].ft.fmt == 0)
2334887Schin 				{	fp[n].ft.fmt = 'I';
2344887Schin 					fp[n].ft.size = sizeof(int);
2354887Schin 					fp[n].ft.form = (char*)form;
2364887Schin 				}
2374887Schin 				need[FP_SIZE] = n;
2384887Schin 			}
2394887Schin 			goto loop_flags;
2404887Schin 
2414887Schin 		case 'l' :
2424887Schin 			size = -1; flags &= ~SFFMT_TYPES;
2434887Schin 			if(*form == 'l')
2444887Schin 			{	form += 1;
2454887Schin 				flags |= SFFMT_LLONG;
2464887Schin 			}
2474887Schin 			else	flags |= SFFMT_LONG;
2484887Schin 			goto loop_flags;
2494887Schin 		case 'h' :
2504887Schin 			size = -1; flags &= ~SFFMT_TYPES;
2514887Schin 			if(*form == 'h')
2524887Schin 			{	form += 1;
2534887Schin 				flags |= SFFMT_SSHORT;
2544887Schin 			}
2554887Schin 			else	flags |= SFFMT_SHORT;
2564887Schin 			goto loop_flags;
2574887Schin 		case 'L' :
2584887Schin 			size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
2594887Schin 			goto loop_flags;
2604887Schin 		}
2614887Schin 
2624887Schin 		/* set object size for scalars */
2634887Schin 		if(flags & SFFMT_TYPES)
2644887Schin 		{	if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
2654887Schin 			{	if(flags&SFFMT_LONG)
2664887Schin 					size = sizeof(long);
2674887Schin 				else if(flags&SFFMT_SHORT)
2684887Schin 					size = sizeof(short);
2694887Schin 				else if(flags&SFFMT_SSHORT)
2704887Schin 					size = sizeof(char);
2714887Schin 				else if(flags&SFFMT_TFLAG)
2724887Schin 					size = sizeof(ptrdiff_t);
2734887Schin 				else if(flags&SFFMT_ZFLAG)
2744887Schin 					size = sizeof(size_t);
2754887Schin 				else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )
2764887Schin 					size = sizeof(Sflong_t);
2774887Schin 				else if(flags&SFFMT_IFLAG)
2784887Schin 				{	if(size <= 0 ||
2794887Schin 					   size == sizeof(Sflong_t)*CHAR_BIT )
2804887Schin 						size = sizeof(Sflong_t);
2814887Schin 				}
2824887Schin 				else if(size < 0)
2834887Schin 					size = sizeof(int);
2844887Schin 			}
2854887Schin 			else if(_Sftype[fmt]&SFFMT_FLOAT)
2864887Schin 			{	if(flags&(SFFMT_LONG|SFFMT_LLONG))
2874887Schin 					size = sizeof(double);
2884887Schin 				else if(flags&SFFMT_LDOUBLE)
2894887Schin 					size = sizeof(Sfdouble_t);
2904887Schin 				else if(flags&SFFMT_IFLAG)
2914887Schin 				{	if(size <= 0)
2924887Schin 						size = sizeof(Sfdouble_t);
2934887Schin 				}
2944887Schin 				else if(size < 0)
2954887Schin 					size = sizeof(float);
2964887Schin 			}
2974887Schin 			else if(_Sftype[fmt]&SFFMT_CHAR)
2984887Schin 			{
2994887Schin #if _has_multibyte
3004887Schin 				if((flags&SFFMT_LONG) || fmt == 'C')
3014887Schin 				{	size = sizeof(wchar_t) > sizeof(int) ?
3024887Schin 						sizeof(wchar_t) : sizeof(int);
3034887Schin 				} else
3044887Schin #endif
3054887Schin 				if(size < 0)
3064887Schin 					size = sizeof(int);
3074887Schin 			}
3084887Schin 		}
3094887Schin 
3104887Schin 		if(skip)
3114887Schin 			continue;
3124887Schin 
3134887Schin 		if((argp = FP_SET(argp,argn)) > maxp)
3144887Schin 			maxp = argp;
3154887Schin 
3164887Schin 		if(dollar && fmt == '!')
3174887Schin 			return NIL(Fmtpos_t*);
3184887Schin 
3194887Schin 		if(fp && fp[argp].ft.fmt == 0)
3204887Schin 		{	fp[argp].ft.form = (char*)form;
3214887Schin 			fp[argp].ft.fmt = fp[argp].fmt = fmt;
3224887Schin 			fp[argp].ft.size = size;
3234887Schin 			fp[argp].ft.flags = flags;
3244887Schin 			fp[argp].ft.width = width;
3254887Schin 			fp[argp].ft.precis = precis;
3264887Schin 			fp[argp].ft.base = base;
3274887Schin 			fp[argp].ft.t_str = t_str;
3284887Schin 			fp[argp].ft.n_str = n_str;
3294887Schin 			for(n = 0; n < FP_INDEX; ++n)
3304887Schin 				fp[argp].need[n] = need[n];
3314887Schin 		}
3324887Schin 	}
3334887Schin 
3344887Schin 	if(!fp) /* constructing position array only */
3354887Schin 	{	if(!dollar || !(fp = (Fmtpos_t*)malloc((maxp+1)*sizeof(Fmtpos_t))) )
3364887Schin 			return NIL(Fmtpos_t*);
3374887Schin 		for(n = 0; n <= maxp; ++n)
3384887Schin 			fp[n].ft.fmt = 0;
3394887Schin 		return fp;
3404887Schin 	}
3414887Schin 
3424887Schin 	/* get value for positions */
3434887Schin 	for(n = 0; n <= maxp; ++n)
3444887Schin 	{	if(fp[n].ft.fmt == 0) /* gap: pretend it's a 'd' pattern */
3454887Schin 		{	fp[n].ft.fmt = 'd';
3464887Schin 			fp[n].ft.width = 0;
3474887Schin 			fp[n].ft.precis = 0;
3484887Schin 			fp[n].ft.base = 0;
3494887Schin 			fp[n].ft.size = 0;
3504887Schin 			fp[n].ft.t_str = 0;
3514887Schin 			fp[n].ft.n_str = 0;
3524887Schin 			fp[n].ft.flags = 0;
3534887Schin 			for(v = 0; v < FP_INDEX; ++v)
3544887Schin 				fp[n].need[v] = -1;
3554887Schin 		}
3564887Schin 
3574887Schin 		if(ft && ft->extf)
3584887Schin 		{	fp[n].ft.version = ft->version;
3594887Schin 			fp[n].ft.extf = ft->extf;
3604887Schin 			fp[n].ft.eventf = ft->eventf;
3614887Schin 			if((v = fp[n].need[FP_WIDTH]) >= 0 && v < n)
3624887Schin 				fp[n].ft.width = fp[v].argv.i;
3634887Schin 			if((v = fp[n].need[FP_PRECIS]) >= 0 && v < n)
3644887Schin 				fp[n].ft.precis = fp[v].argv.i;
3654887Schin 			if((v = fp[n].need[FP_BASE]) >= 0 && v < n)
3664887Schin 				fp[n].ft.base = fp[v].argv.i;
3674887Schin 			if((v = fp[n].need[FP_STR]) >= 0 && v < n)
3684887Schin 				fp[n].ft.t_str = fp[v].argv.s;
3694887Schin 			if((v = fp[n].need[FP_SIZE]) >= 0 && v < n)
3704887Schin 				fp[n].ft.size = fp[v].argv.i;
3714887Schin 
3724887Schin 			memcpy(ft,&fp[n].ft,sizeof(Sffmt_t));
3734887Schin 			va_copy(ft->args,args);
3744887Schin 			ft->flags |= SFFMT_ARGPOS;
3754887Schin 			v = (*ft->extf)(f, (Void_t*)(&fp[n].argv), ft);
3764887Schin 			va_copy(args,ft->args);
3774887Schin 			memcpy(&fp[n].ft,ft,sizeof(Sffmt_t));
3784887Schin 			if(v < 0)
3794887Schin 			{	memcpy(ft,&savft,sizeof(Sffmt_t));
3804887Schin 				ft = NIL(Sffmt_t*);
3814887Schin 			}
3824887Schin 
3834887Schin 			if(!(fp[n].ft.flags&SFFMT_VALUE) )
3844887Schin 				goto arg_list;
3854887Schin 			else if(_Sftype[fp[n].ft.fmt]&(SFFMT_INT|SFFMT_UINT) )
3864887Schin 			{	if(fp[n].ft.size == sizeof(short))
3874887Schin 				{	if(_Sftype[fp[n].ft.fmt]&SFFMT_INT)
3884887Schin 						fp[n].argv.i = fp[n].argv.h;
3894887Schin 					else	fp[n].argv.i = fp[n].argv.uh;
3904887Schin 				}
3914887Schin 				else if(fp[n].ft.size == sizeof(char))
3924887Schin 				{	if(_Sftype[fp[n].ft.fmt]&SFFMT_INT)
3934887Schin 						fp[n].argv.i = fp[n].argv.c;
3944887Schin 					else	fp[n].argv.i = fp[n].argv.uc;
3954887Schin 				}
3964887Schin 			}
3974887Schin 			else if(_Sftype[fp[n].ft.fmt]&SFFMT_FLOAT )
3984887Schin 			{	if(fp[n].ft.size == sizeof(float) )
3994887Schin 					fp[n].argv.d = fp[n].argv.f;
4004887Schin 			}
4014887Schin 		}
4024887Schin 		else
4034887Schin 		{ arg_list:
4044887Schin 			if(fp[n].ft.fmt == LEFTP)
4054887Schin 			{	fp[n].argv.s = va_arg(args, char*);
4064887Schin 				fp[n].ft.size = strlen(fp[n].argv.s);
4074887Schin 			}
4084887Schin 			else if(fp[n].ft.fmt == '.' || fp[n].ft.fmt == 'I')
4094887Schin 				fp[n].argv.i = va_arg(args, int);
4104887Schin 			else if(fp[n].ft.fmt == '!')
4114887Schin 			{	if(ft)
4124887Schin 					memcpy(ft,&savft,sizeof(Sffmt_t));
4134887Schin 				fp[n].argv.ft = ft = va_arg(args, Sffmt_t*);
4144887Schin 				if(ft->form)
4154887Schin 					ft = NIL(Sffmt_t*);
4164887Schin 				if(ft)
4174887Schin 					memcpy(&savft,ft,sizeof(Sffmt_t));
4184887Schin 			}
4194887Schin 			else if(type > 0) /* from sfvscanf */
4204887Schin 				fp[n].argv.vp = va_arg(args, Void_t*);
4214887Schin 			else switch(_Sftype[fp[n].ft.fmt])
4224887Schin 			{ case SFFMT_INT:
4234887Schin 			  case SFFMT_UINT:
4244887Schin #if !_ast_intmax_long
4254887Schin 				if(size == sizeof(Sflong_t) )
4264887Schin 					fp[n].argv.ll = va_arg(args, Sflong_t);
4274887Schin 				else
4284887Schin #endif
4294887Schin 				if(size == sizeof(long) )
4304887Schin 					fp[n].argv.l = va_arg(args, long);
4314887Schin 				else	fp[n].argv.i = va_arg(args, int);
4324887Schin 				break;
4334887Schin 			  case SFFMT_FLOAT:
4344887Schin #if !_ast_fltmax_double
4354887Schin 				if(size == sizeof(Sfdouble_t) )
4364887Schin 					fp[n].argv.ld = va_arg(args,Sfdouble_t);
4374887Schin 				else
4384887Schin #endif
4394887Schin 					fp[n].argv.d  = va_arg(args,double);
4404887Schin 				break;
4414887Schin 	 		  case SFFMT_POINTER:
4424887Schin 					fp[n].argv.vp = va_arg(args,Void_t*);
4434887Schin 				break;
4444887Schin 			  case SFFMT_CHAR:
4454887Schin 				if(fp[n].ft.base >= 0)
4464887Schin 					fp[n].argv.s = va_arg(args,char*);
4474887Schin #if _has_multibyte
4484887Schin 				else if((fp[n].ft.flags & SFFMT_LONG) ||
4494887Schin 					fp[n].ft.fmt == 'C' )
4504887Schin 				{	if(sizeof(wchar_t) <= sizeof(int) )
4514887Schin 					     fp[n].argv.wc = (wchar_t)va_arg(args,int);
4524887Schin 					else fp[n].argv.wc = va_arg(args,wchar_t);
4534887Schin 				}
4544887Schin #endif
4554887Schin 					/* observe promotion rule */
4564887Schin 				else	fp[n].argv.i = va_arg(args,int);
4574887Schin 				break;
4584887Schin 			  default: /* unknown pattern */
4594887Schin 				break;
4604887Schin 			}
4614887Schin 		}
4624887Schin 	}
4634887Schin 
4644887Schin 	if(ft)
4654887Schin 		memcpy(ft,&savft,sizeof(Sffmt_t));
4664887Schin 	return fp;
4674887Schin }
4684887Schin 
4694887Schin static const unsigned char	flt_nan[] = { _ast_flt_nan_init };
4704887Schin static const unsigned char	flt_inf[] = { _ast_flt_inf_init };
4714887Schin static const unsigned char	dbl_nan[] = { _ast_dbl_nan_init };
4724887Schin static const unsigned char	dbl_inf[] = { _ast_dbl_inf_init };
4734887Schin #ifdef _ast_ldbl_nan_init
4744887Schin static const unsigned char	ldbl_nan[] = { _ast_ldbl_nan_init };
4754887Schin static const unsigned char	ldbl_inf[] = { _ast_ldbl_inf_init };
4764887Schin #endif
4774887Schin 
4784887Schin /* function to initialize conversion tables */
4794887Schin static int sfcvinit()
4804887Schin {	reg int		d, l;
4814887Schin 
4824887Schin 	for(d = 0; d <= SF_MAXCHAR; ++d)
4834887Schin 	{	_Sfcv36[d] = SF_RADIX;
4844887Schin 		_Sfcv64[d] = SF_RADIX;
4854887Schin 	}
4864887Schin 
4874887Schin 	/* [0-9] */
4884887Schin 	for(d = 0; d < 10; ++d)
4894887Schin 	{	_Sfcv36[(uchar)_Sfdigits[d]] = d;
4904887Schin 		_Sfcv64[(uchar)_Sfdigits[d]] = d;
4914887Schin 	}
4924887Schin 
4934887Schin 	/* [a-z] */
4944887Schin 	for(; d < 36; ++d)
4954887Schin 	{	_Sfcv36[(uchar)_Sfdigits[d]] = d;
4964887Schin 		_Sfcv64[(uchar)_Sfdigits[d]] = d;
4974887Schin 	}
4984887Schin 
4994887Schin 	/* [A-Z] */
5004887Schin 	for(l = 10; d < 62; ++l, ++d)
5014887Schin 	{	_Sfcv36[(uchar)_Sfdigits[d]] = l;
5024887Schin 		_Sfcv64[(uchar)_Sfdigits[d]] = d;
5034887Schin 	}
5044887Schin 
5054887Schin 	/* remaining digits */
5064887Schin 	for(; d < SF_RADIX; ++d)
5074887Schin 	{	_Sfcv36[(uchar)_Sfdigits[d]] = d;
5084887Schin 		_Sfcv64[(uchar)_Sfdigits[d]] = d;
5094887Schin 	}
5104887Schin 
5114887Schin 	_Sftype['d'] = _Sftype['i'] = SFFMT_INT;
5124887Schin 	_Sftype['u'] = _Sftype['o'] = _Sftype['x'] = _Sftype['X'] = SFFMT_UINT;
5134887Schin 	_Sftype['e'] = _Sftype['E'] = _Sftype['a'] = _Sftype['A'] =
5144887Schin 	_Sftype['g'] = _Sftype['G'] = _Sftype['f'] = SFFMT_FLOAT;
5154887Schin 	_Sftype['s'] = _Sftype['n'] = _Sftype['p'] = _Sftype['!'] = SFFMT_POINTER;
5164887Schin 	_Sftype['c'] = SFFMT_CHAR;
5174887Schin 	_Sftype['['] = SFFMT_CLASS;
5184887Schin #if _has_multibyte
5194887Schin 	_Sftype['S'] = SFFMT_POINTER;
5204887Schin 	_Sftype['C'] = SFFMT_CHAR;
5214887Schin #endif
5224887Schin 
5234887Schin 	/* IEEE floating point computed constants */
5244887Schin 
5254887Schin 	memcpy((char*)&_Sffnan, (char*)flt_nan, sizeof(_Sffnan));
5264887Schin 	memcpy((char*)&_Sffinf, (char*)flt_inf, sizeof(_Sffinf));
5274887Schin 	memcpy((char*)&_Sfdnan, (char*)dbl_nan, sizeof(_Sfdnan));
5284887Schin 	memcpy((char*)&_Sfdinf, (char*)dbl_inf, sizeof(_Sfdinf));
5294887Schin #ifdef _ast_ldbl_nan_init
5304887Schin 	memcpy((char*)&_Sflnan, (char*)ldbl_nan, sizeof(_Sflnan));
5314887Schin 	memcpy((char*)&_Sflinf, (char*)ldbl_inf, sizeof(_Sflinf));
5324887Schin #else
5334887Schin 	memcpy((char*)&_Sflnan, (char*)dbl_nan, sizeof(_Sfdnan));
5344887Schin 	memcpy((char*)&_Sflinf, (char*)dbl_inf, sizeof(_Sfdinf));
5354887Schin #endif
5364887Schin 
5374887Schin 	return 1;
5384887Schin }
5394887Schin 
5404887Schin /* table for floating point and integer conversions */
5414887Schin #include	"FEATURE/sfinit"
542