1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin #include	"sfhdr.h"
23*4887Schin #include	"FEATURE/float"
24*4887Schin 
25*4887Schin /*	Dealing with $ argument addressing stuffs.
26*4887Schin **
27*4887Schin **	Written by Kiem-Phong Vo.
28*4887Schin */
29*4887Schin 
30*4887Schin #if __STD_C
31*4887Schin static char* sffmtint(const char* str, int* v)
32*4887Schin #else
33*4887Schin static char* sffmtint(str, v)
34*4887Schin char*	str;
35*4887Schin int*	v;
36*4887Schin #endif
37*4887Schin {
38*4887Schin 	for(*v = 0; isdigit(*str); ++str)
39*4887Schin 		*v = *v * 10 + (*str - '0');
40*4887Schin 	*v -= 1;
41*4887Schin 	return (char*)str;
42*4887Schin }
43*4887Schin 
44*4887Schin #if __STD_C
45*4887Schin static Fmtpos_t* sffmtpos(Sfio_t* f,const char* form,va_list args,Sffmt_t* ft,int type)
46*4887Schin #else
47*4887Schin static Fmtpos_t* sffmtpos(f,form,args,ft,type)
48*4887Schin Sfio_t*		f;
49*4887Schin char*		form;
50*4887Schin va_list		args;
51*4887Schin Sffmt_t*	ft;
52*4887Schin int		type;	/* >0: scanf, =0: printf, -1: internal	*/
53*4887Schin #endif
54*4887Schin {
55*4887Schin 	int		base, fmt, flags, dot, width, precis;
56*4887Schin 	ssize_t		n_str, size;
57*4887Schin 	char		*t_str, *sp;
58*4887Schin 	int		v, n, skip, dollar, decimal, thousand;
59*4887Schin 	Sffmt_t		savft;
60*4887Schin 	Fmtpos_t*	fp;	/* position array of arguments	*/
61*4887Schin 	int		argp, argn, maxp, need[FP_INDEX];
62*4887Schin #if _has_multibyte
63*4887Schin 	SFMBDCL(fmbs)
64*4887Schin #endif
65*4887Schin 
66*4887Schin 	if(type < 0)
67*4887Schin 		fp = NIL(Fmtpos_t*);
68*4887Schin 	else if(!(fp = sffmtpos(f,form,args,ft,-1)) )
69*4887Schin 		return NIL(Fmtpos_t*);
70*4887Schin 
71*4887Schin 	dollar = decimal = thousand = 0; argn = maxp = -1;
72*4887Schin 	SFMBCLR(&fmbs);
73*4887Schin 	while((n = *form) )
74*4887Schin 	{	if(n != '%') /* collect the non-pattern chars */
75*4887Schin 		{	sp = (char*)form;
76*4887Schin 			for(;;)
77*4887Schin 			{	form += SFMBLEN(form, &fmbs);
78*4887Schin 				if(*form == 0 || *form == '%')
79*4887Schin 					break;
80*4887Schin 			}
81*4887Schin 			continue;
82*4887Schin 		}
83*4887Schin 		else	form += 1;
84*4887Schin 		if(*form == 0)
85*4887Schin 			break;
86*4887Schin 		else if(*form == '%')
87*4887Schin 		{	form += 1;
88*4887Schin 			continue;
89*4887Schin 		}
90*4887Schin 
91*4887Schin 		if(*form == '*' && type > 0) /* skip in scanning */
92*4887Schin 		{	skip = 1;
93*4887Schin 			form += 1;
94*4887Schin 			argp = -1;
95*4887Schin 		}
96*4887Schin 		else /* get the position of this argument */
97*4887Schin 		{	skip = 0;
98*4887Schin 			sp = sffmtint(form,&argp);
99*4887Schin 			if(*sp == '$')
100*4887Schin 			{	dollar = 1;
101*4887Schin 				form = sp+1;
102*4887Schin 			}
103*4887Schin 			else	argp = -1;
104*4887Schin 		}
105*4887Schin 
106*4887Schin 		flags = dot = 0;
107*4887Schin 		t_str = NIL(char*); n_str = 0;
108*4887Schin 		size = width = precis = base = -1;
109*4887Schin 		for(n = 0; n < FP_INDEX; ++n)
110*4887Schin 			need[n] = -1;
111*4887Schin 
112*4887Schin 	loop_flags:	/* LOOP FOR \0, %, FLAGS, WIDTH, PRECISION, BASE, TYPE */
113*4887Schin 		switch((fmt = *form++) )
114*4887Schin 		{
115*4887Schin 		case LEFTP : /* get the type enclosed in balanced parens */
116*4887Schin 			t_str = (char*)form;
117*4887Schin 			for(v = 1;;)
118*4887Schin 			{	switch(*form++)
119*4887Schin 				{
120*4887Schin 				case 0 :	/* not balancable, retract */
121*4887Schin 					form = t_str;
122*4887Schin 					t_str = NIL(char*);
123*4887Schin 					n_str = 0;
124*4887Schin 					goto loop_flags;
125*4887Schin 				case LEFTP :	/* increasing nested level */
126*4887Schin 					v += 1;
127*4887Schin 					continue;
128*4887Schin 				case RIGHTP :	/* decreasing nested level */
129*4887Schin 					if((v -= 1) != 0)
130*4887Schin 						continue;
131*4887Schin 					n_str = form-t_str;
132*4887Schin 					if(*t_str == '*')
133*4887Schin 					{	t_str = sffmtint(t_str+1,&n);
134*4887Schin 						if(*t_str == '$')
135*4887Schin 							dollar = 1;
136*4887Schin 						else	n = -1;
137*4887Schin 						if((n = FP_SET(n,argn)) > maxp)
138*4887Schin 							maxp = n;
139*4887Schin 						if(fp && fp[n].ft.fmt == 0)
140*4887Schin 						{	fp[n].ft.fmt = LEFTP;
141*4887Schin 							fp[n].ft.form = (char*)form;
142*4887Schin 						}
143*4887Schin 						need[FP_STR] = n;
144*4887Schin 					}
145*4887Schin 					goto loop_flags;
146*4887Schin 				}
147*4887Schin 			}
148*4887Schin 
149*4887Schin 		case '-' :
150*4887Schin 			flags |= SFFMT_LEFT;
151*4887Schin 			flags &= ~SFFMT_ZERO;
152*4887Schin 			goto loop_flags;
153*4887Schin 		case '0' :
154*4887Schin 			if(!(flags&SFFMT_LEFT) )
155*4887Schin 				flags |= SFFMT_ZERO;
156*4887Schin 			goto loop_flags;
157*4887Schin 		case ' ' :
158*4887Schin 			if(!(flags&SFFMT_SIGN) )
159*4887Schin 				flags |= SFFMT_BLANK;
160*4887Schin 			goto loop_flags;
161*4887Schin 		case '+' :
162*4887Schin 			flags |= SFFMT_SIGN;
163*4887Schin 			flags &= ~SFFMT_BLANK;
164*4887Schin 			goto loop_flags;
165*4887Schin 		case '#' :
166*4887Schin 			flags |= SFFMT_ALTER;
167*4887Schin 			goto loop_flags;
168*4887Schin 		case QUOTE:
169*4887Schin 			SFSETLOCALE(&decimal,&thousand);
170*4887Schin 			if(thousand > 0)
171*4887Schin 				flags |= SFFMT_THOUSAND;
172*4887Schin 			goto loop_flags;
173*4887Schin 
174*4887Schin 		case '.' :
175*4887Schin 			if((dot += 1) == 2)
176*4887Schin 				base = 0; /* for %s,%c */
177*4887Schin 			if(isdigit(*form))
178*4887Schin 			{	fmt = *form++;
179*4887Schin 				goto dot_size;
180*4887Schin 			}
181*4887Schin 			else if(*form != '*')
182*4887Schin 				goto loop_flags;
183*4887Schin 			else	form += 1; /* drop thru below */
184*4887Schin 
185*4887Schin 		case '*' :
186*4887Schin 			form = sffmtint(form,&n);
187*4887Schin 			if(*form == '$' )
188*4887Schin 			{	dollar = 1;
189*4887Schin 				form += 1;
190*4887Schin 			}
191*4887Schin 			else	n = -1;
192*4887Schin 			if((n = FP_SET(n,argn)) > maxp)
193*4887Schin 				maxp = n;
194*4887Schin 			if(fp && fp[n].ft.fmt == 0)
195*4887Schin 			{	fp[n].ft.fmt = '.';
196*4887Schin 				fp[n].ft.size = dot;
197*4887Schin 				fp[n].ft.form = (char*)form;
198*4887Schin 			}
199*4887Schin 			if(dot <= 2)
200*4887Schin 				need[dot] = n;
201*4887Schin 			goto loop_flags;
202*4887Schin 
203*4887Schin 		case '1' : case '2' : case '3' :
204*4887Schin 		case '4' : case '5' : case '6' :
205*4887Schin 		case '7' : case '8' : case '9' :
206*4887Schin 		dot_size :
207*4887Schin 			for(v = fmt - '0', fmt = *form; isdigit(fmt); fmt = *++form)
208*4887Schin 				v = v*10 + (fmt - '0');
209*4887Schin 			if(dot == 0)
210*4887Schin 				width = v;
211*4887Schin 			else if(dot == 1)
212*4887Schin 				precis = v;
213*4887Schin 			else if(dot == 2)
214*4887Schin 				base = v;
215*4887Schin 			goto loop_flags;
216*4887Schin 
217*4887Schin 		case 'I' : /* object length */
218*4887Schin 			size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_IFLAG;
219*4887Schin 			if(isdigit(*form) )
220*4887Schin 			{	for(size = 0, n = *form; isdigit(n); n = *++form)
221*4887Schin 					size = size*10 + (n - '0');
222*4887Schin 			}
223*4887Schin 			else if(*form == '*')
224*4887Schin 			{	form = sffmtint(form+1,&n);
225*4887Schin 				if(*form == '$' )
226*4887Schin 				{	dollar = 1;
227*4887Schin 					form += 1;
228*4887Schin 				}
229*4887Schin 				else	n = -1;
230*4887Schin 				if((n = FP_SET(n,argn)) > maxp)
231*4887Schin 					maxp = n;
232*4887Schin 				if(fp && fp[n].ft.fmt == 0)
233*4887Schin 				{	fp[n].ft.fmt = 'I';
234*4887Schin 					fp[n].ft.size = sizeof(int);
235*4887Schin 					fp[n].ft.form = (char*)form;
236*4887Schin 				}
237*4887Schin 				need[FP_SIZE] = n;
238*4887Schin 			}
239*4887Schin 			goto loop_flags;
240*4887Schin 
241*4887Schin 		case 'l' :
242*4887Schin 			size = -1; flags &= ~SFFMT_TYPES;
243*4887Schin 			if(*form == 'l')
244*4887Schin 			{	form += 1;
245*4887Schin 				flags |= SFFMT_LLONG;
246*4887Schin 			}
247*4887Schin 			else	flags |= SFFMT_LONG;
248*4887Schin 			goto loop_flags;
249*4887Schin 		case 'h' :
250*4887Schin 			size = -1; flags &= ~SFFMT_TYPES;
251*4887Schin 			if(*form == 'h')
252*4887Schin 			{	form += 1;
253*4887Schin 				flags |= SFFMT_SSHORT;
254*4887Schin 			}
255*4887Schin 			else	flags |= SFFMT_SHORT;
256*4887Schin 			goto loop_flags;
257*4887Schin 		case 'L' :
258*4887Schin 			size = -1; flags = (flags & ~SFFMT_TYPES) | SFFMT_LDOUBLE;
259*4887Schin 			goto loop_flags;
260*4887Schin 		}
261*4887Schin 
262*4887Schin 		/* set object size for scalars */
263*4887Schin 		if(flags & SFFMT_TYPES)
264*4887Schin 		{	if((_Sftype[fmt]&(SFFMT_INT|SFFMT_UINT)) || fmt == 'n')
265*4887Schin 			{	if(flags&SFFMT_LONG)
266*4887Schin 					size = sizeof(long);
267*4887Schin 				else if(flags&SFFMT_SHORT)
268*4887Schin 					size = sizeof(short);
269*4887Schin 				else if(flags&SFFMT_SSHORT)
270*4887Schin 					size = sizeof(char);
271*4887Schin 				else if(flags&SFFMT_TFLAG)
272*4887Schin 					size = sizeof(ptrdiff_t);
273*4887Schin 				else if(flags&SFFMT_ZFLAG)
274*4887Schin 					size = sizeof(size_t);
275*4887Schin 				else if(flags&(SFFMT_LLONG|SFFMT_JFLAG) )
276*4887Schin 					size = sizeof(Sflong_t);
277*4887Schin 				else if(flags&SFFMT_IFLAG)
278*4887Schin 				{	if(size <= 0 ||
279*4887Schin 					   size == sizeof(Sflong_t)*CHAR_BIT )
280*4887Schin 						size = sizeof(Sflong_t);
281*4887Schin 				}
282*4887Schin 				else if(size < 0)
283*4887Schin 					size = sizeof(int);
284*4887Schin 			}
285*4887Schin 			else if(_Sftype[fmt]&SFFMT_FLOAT)
286*4887Schin 			{	if(flags&(SFFMT_LONG|SFFMT_LLONG))
287*4887Schin 					size = sizeof(double);
288*4887Schin 				else if(flags&SFFMT_LDOUBLE)
289*4887Schin 					size = sizeof(Sfdouble_t);
290*4887Schin 				else if(flags&SFFMT_IFLAG)
291*4887Schin 				{	if(size <= 0)
292*4887Schin 						size = sizeof(Sfdouble_t);
293*4887Schin 				}
294*4887Schin 				else if(size < 0)
295*4887Schin 					size = sizeof(float);
296*4887Schin 			}
297*4887Schin 			else if(_Sftype[fmt]&SFFMT_CHAR)
298*4887Schin 			{
299*4887Schin #if _has_multibyte
300*4887Schin 				if((flags&SFFMT_LONG) || fmt == 'C')
301*4887Schin 				{	size = sizeof(wchar_t) > sizeof(int) ?
302*4887Schin 						sizeof(wchar_t) : sizeof(int);
303*4887Schin 				} else
304*4887Schin #endif
305*4887Schin 				if(size < 0)
306*4887Schin 					size = sizeof(int);
307*4887Schin 			}
308*4887Schin 		}
309*4887Schin 
310*4887Schin 		if(skip)
311*4887Schin 			continue;
312*4887Schin 
313*4887Schin 		if((argp = FP_SET(argp,argn)) > maxp)
314*4887Schin 			maxp = argp;
315*4887Schin 
316*4887Schin 		if(dollar && fmt == '!')
317*4887Schin 			return NIL(Fmtpos_t*);
318*4887Schin 
319*4887Schin 		if(fp && fp[argp].ft.fmt == 0)
320*4887Schin 		{	fp[argp].ft.form = (char*)form;
321*4887Schin 			fp[argp].ft.fmt = fp[argp].fmt = fmt;
322*4887Schin 			fp[argp].ft.size = size;
323*4887Schin 			fp[argp].ft.flags = flags;
324*4887Schin 			fp[argp].ft.width = width;
325*4887Schin 			fp[argp].ft.precis = precis;
326*4887Schin 			fp[argp].ft.base = base;
327*4887Schin 			fp[argp].ft.t_str = t_str;
328*4887Schin 			fp[argp].ft.n_str = n_str;
329*4887Schin 			for(n = 0; n < FP_INDEX; ++n)
330*4887Schin 				fp[argp].need[n] = need[n];
331*4887Schin 		}
332*4887Schin 	}
333*4887Schin 
334*4887Schin 	if(!fp) /* constructing position array only */
335*4887Schin 	{	if(!dollar || !(fp = (Fmtpos_t*)malloc((maxp+1)*sizeof(Fmtpos_t))) )
336*4887Schin 			return NIL(Fmtpos_t*);
337*4887Schin 		for(n = 0; n <= maxp; ++n)
338*4887Schin 			fp[n].ft.fmt = 0;
339*4887Schin 		return fp;
340*4887Schin 	}
341*4887Schin 
342*4887Schin 	/* get value for positions */
343*4887Schin 	for(n = 0; n <= maxp; ++n)
344*4887Schin 	{	if(fp[n].ft.fmt == 0) /* gap: pretend it's a 'd' pattern */
345*4887Schin 		{	fp[n].ft.fmt = 'd';
346*4887Schin 			fp[n].ft.width = 0;
347*4887Schin 			fp[n].ft.precis = 0;
348*4887Schin 			fp[n].ft.base = 0;
349*4887Schin 			fp[n].ft.size = 0;
350*4887Schin 			fp[n].ft.t_str = 0;
351*4887Schin 			fp[n].ft.n_str = 0;
352*4887Schin 			fp[n].ft.flags = 0;
353*4887Schin 			for(v = 0; v < FP_INDEX; ++v)
354*4887Schin 				fp[n].need[v] = -1;
355*4887Schin 		}
356*4887Schin 
357*4887Schin 		if(ft && ft->extf)
358*4887Schin 		{	fp[n].ft.version = ft->version;
359*4887Schin 			fp[n].ft.extf = ft->extf;
360*4887Schin 			fp[n].ft.eventf = ft->eventf;
361*4887Schin 			if((v = fp[n].need[FP_WIDTH]) >= 0 && v < n)
362*4887Schin 				fp[n].ft.width = fp[v].argv.i;
363*4887Schin 			if((v = fp[n].need[FP_PRECIS]) >= 0 && v < n)
364*4887Schin 				fp[n].ft.precis = fp[v].argv.i;
365*4887Schin 			if((v = fp[n].need[FP_BASE]) >= 0 && v < n)
366*4887Schin 				fp[n].ft.base = fp[v].argv.i;
367*4887Schin 			if((v = fp[n].need[FP_STR]) >= 0 && v < n)
368*4887Schin 				fp[n].ft.t_str = fp[v].argv.s;
369*4887Schin 			if((v = fp[n].need[FP_SIZE]) >= 0 && v < n)
370*4887Schin 				fp[n].ft.size = fp[v].argv.i;
371*4887Schin 
372*4887Schin 			memcpy(ft,&fp[n].ft,sizeof(Sffmt_t));
373*4887Schin 			va_copy(ft->args,args);
374*4887Schin 			ft->flags |= SFFMT_ARGPOS;
375*4887Schin 			v = (*ft->extf)(f, (Void_t*)(&fp[n].argv), ft);
376*4887Schin 			va_copy(args,ft->args);
377*4887Schin 			memcpy(&fp[n].ft,ft,sizeof(Sffmt_t));
378*4887Schin 			if(v < 0)
379*4887Schin 			{	memcpy(ft,&savft,sizeof(Sffmt_t));
380*4887Schin 				ft = NIL(Sffmt_t*);
381*4887Schin 			}
382*4887Schin 
383*4887Schin 			if(!(fp[n].ft.flags&SFFMT_VALUE) )
384*4887Schin 				goto arg_list;
385*4887Schin 			else if(_Sftype[fp[n].ft.fmt]&(SFFMT_INT|SFFMT_UINT) )
386*4887Schin 			{	if(fp[n].ft.size == sizeof(short))
387*4887Schin 				{	if(_Sftype[fp[n].ft.fmt]&SFFMT_INT)
388*4887Schin 						fp[n].argv.i = fp[n].argv.h;
389*4887Schin 					else	fp[n].argv.i = fp[n].argv.uh;
390*4887Schin 				}
391*4887Schin 				else if(fp[n].ft.size == sizeof(char))
392*4887Schin 				{	if(_Sftype[fp[n].ft.fmt]&SFFMT_INT)
393*4887Schin 						fp[n].argv.i = fp[n].argv.c;
394*4887Schin 					else	fp[n].argv.i = fp[n].argv.uc;
395*4887Schin 				}
396*4887Schin 			}
397*4887Schin 			else if(_Sftype[fp[n].ft.fmt]&SFFMT_FLOAT )
398*4887Schin 			{	if(fp[n].ft.size == sizeof(float) )
399*4887Schin 					fp[n].argv.d = fp[n].argv.f;
400*4887Schin 			}
401*4887Schin 		}
402*4887Schin 		else
403*4887Schin 		{ arg_list:
404*4887Schin 			if(fp[n].ft.fmt == LEFTP)
405*4887Schin 			{	fp[n].argv.s = va_arg(args, char*);
406*4887Schin 				fp[n].ft.size = strlen(fp[n].argv.s);
407*4887Schin 			}
408*4887Schin 			else if(fp[n].ft.fmt == '.' || fp[n].ft.fmt == 'I')
409*4887Schin 				fp[n].argv.i = va_arg(args, int);
410*4887Schin 			else if(fp[n].ft.fmt == '!')
411*4887Schin 			{	if(ft)
412*4887Schin 					memcpy(ft,&savft,sizeof(Sffmt_t));
413*4887Schin 				fp[n].argv.ft = ft = va_arg(args, Sffmt_t*);
414*4887Schin 				if(ft->form)
415*4887Schin 					ft = NIL(Sffmt_t*);
416*4887Schin 				if(ft)
417*4887Schin 					memcpy(&savft,ft,sizeof(Sffmt_t));
418*4887Schin 			}
419*4887Schin 			else if(type > 0) /* from sfvscanf */
420*4887Schin 				fp[n].argv.vp = va_arg(args, Void_t*);
421*4887Schin 			else switch(_Sftype[fp[n].ft.fmt])
422*4887Schin 			{ case SFFMT_INT:
423*4887Schin 			  case SFFMT_UINT:
424*4887Schin #if !_ast_intmax_long
425*4887Schin 				if(size == sizeof(Sflong_t) )
426*4887Schin 					fp[n].argv.ll = va_arg(args, Sflong_t);
427*4887Schin 				else
428*4887Schin #endif
429*4887Schin 				if(size == sizeof(long) )
430*4887Schin 					fp[n].argv.l = va_arg(args, long);
431*4887Schin 				else	fp[n].argv.i = va_arg(args, int);
432*4887Schin 				break;
433*4887Schin 			  case SFFMT_FLOAT:
434*4887Schin #if !_ast_fltmax_double
435*4887Schin 				if(size == sizeof(Sfdouble_t) )
436*4887Schin 					fp[n].argv.ld = va_arg(args,Sfdouble_t);
437*4887Schin 				else
438*4887Schin #endif
439*4887Schin 					fp[n].argv.d  = va_arg(args,double);
440*4887Schin 				break;
441*4887Schin 	 		  case SFFMT_POINTER:
442*4887Schin 					fp[n].argv.vp = va_arg(args,Void_t*);
443*4887Schin 				break;
444*4887Schin 			  case SFFMT_CHAR:
445*4887Schin 				if(fp[n].ft.base >= 0)
446*4887Schin 					fp[n].argv.s = va_arg(args,char*);
447*4887Schin #if _has_multibyte
448*4887Schin 				else if((fp[n].ft.flags & SFFMT_LONG) ||
449*4887Schin 					fp[n].ft.fmt == 'C' )
450*4887Schin 				{	if(sizeof(wchar_t) <= sizeof(int) )
451*4887Schin 					     fp[n].argv.wc = (wchar_t)va_arg(args,int);
452*4887Schin 					else fp[n].argv.wc = va_arg(args,wchar_t);
453*4887Schin 				}
454*4887Schin #endif
455*4887Schin 					/* observe promotion rule */
456*4887Schin 				else	fp[n].argv.i = va_arg(args,int);
457*4887Schin 				break;
458*4887Schin 			  default: /* unknown pattern */
459*4887Schin 				break;
460*4887Schin 			}
461*4887Schin 		}
462*4887Schin 	}
463*4887Schin 
464*4887Schin 	if(ft)
465*4887Schin 		memcpy(ft,&savft,sizeof(Sffmt_t));
466*4887Schin 	return fp;
467*4887Schin }
468*4887Schin 
469*4887Schin static const unsigned char	flt_nan[] = { _ast_flt_nan_init };
470*4887Schin static const unsigned char	flt_inf[] = { _ast_flt_inf_init };
471*4887Schin static const unsigned char	dbl_nan[] = { _ast_dbl_nan_init };
472*4887Schin static const unsigned char	dbl_inf[] = { _ast_dbl_inf_init };
473*4887Schin #ifdef _ast_ldbl_nan_init
474*4887Schin static const unsigned char	ldbl_nan[] = { _ast_ldbl_nan_init };
475*4887Schin static const unsigned char	ldbl_inf[] = { _ast_ldbl_inf_init };
476*4887Schin #endif
477*4887Schin 
478*4887Schin /* function to initialize conversion tables */
479*4887Schin static int sfcvinit()
480*4887Schin {	reg int		d, l;
481*4887Schin 
482*4887Schin 	for(d = 0; d <= SF_MAXCHAR; ++d)
483*4887Schin 	{	_Sfcv36[d] = SF_RADIX;
484*4887Schin 		_Sfcv64[d] = SF_RADIX;
485*4887Schin 	}
486*4887Schin 
487*4887Schin 	/* [0-9] */
488*4887Schin 	for(d = 0; d < 10; ++d)
489*4887Schin 	{	_Sfcv36[(uchar)_Sfdigits[d]] = d;
490*4887Schin 		_Sfcv64[(uchar)_Sfdigits[d]] = d;
491*4887Schin 	}
492*4887Schin 
493*4887Schin 	/* [a-z] */
494*4887Schin 	for(; d < 36; ++d)
495*4887Schin 	{	_Sfcv36[(uchar)_Sfdigits[d]] = d;
496*4887Schin 		_Sfcv64[(uchar)_Sfdigits[d]] = d;
497*4887Schin 	}
498*4887Schin 
499*4887Schin 	/* [A-Z] */
500*4887Schin 	for(l = 10; d < 62; ++l, ++d)
501*4887Schin 	{	_Sfcv36[(uchar)_Sfdigits[d]] = l;
502*4887Schin 		_Sfcv64[(uchar)_Sfdigits[d]] = d;
503*4887Schin 	}
504*4887Schin 
505*4887Schin 	/* remaining digits */
506*4887Schin 	for(; d < SF_RADIX; ++d)
507*4887Schin 	{	_Sfcv36[(uchar)_Sfdigits[d]] = d;
508*4887Schin 		_Sfcv64[(uchar)_Sfdigits[d]] = d;
509*4887Schin 	}
510*4887Schin 
511*4887Schin 	_Sftype['d'] = _Sftype['i'] = SFFMT_INT;
512*4887Schin 	_Sftype['u'] = _Sftype['o'] = _Sftype['x'] = _Sftype['X'] = SFFMT_UINT;
513*4887Schin 	_Sftype['e'] = _Sftype['E'] = _Sftype['a'] = _Sftype['A'] =
514*4887Schin 	_Sftype['g'] = _Sftype['G'] = _Sftype['f'] = SFFMT_FLOAT;
515*4887Schin 	_Sftype['s'] = _Sftype['n'] = _Sftype['p'] = _Sftype['!'] = SFFMT_POINTER;
516*4887Schin 	_Sftype['c'] = SFFMT_CHAR;
517*4887Schin 	_Sftype['['] = SFFMT_CLASS;
518*4887Schin #if _has_multibyte
519*4887Schin 	_Sftype['S'] = SFFMT_POINTER;
520*4887Schin 	_Sftype['C'] = SFFMT_CHAR;
521*4887Schin #endif
522*4887Schin 
523*4887Schin 	/* IEEE floating point computed constants */
524*4887Schin 
525*4887Schin 	memcpy((char*)&_Sffnan, (char*)flt_nan, sizeof(_Sffnan));
526*4887Schin 	memcpy((char*)&_Sffinf, (char*)flt_inf, sizeof(_Sffinf));
527*4887Schin 	memcpy((char*)&_Sfdnan, (char*)dbl_nan, sizeof(_Sfdnan));
528*4887Schin 	memcpy((char*)&_Sfdinf, (char*)dbl_inf, sizeof(_Sfdinf));
529*4887Schin #ifdef _ast_ldbl_nan_init
530*4887Schin 	memcpy((char*)&_Sflnan, (char*)ldbl_nan, sizeof(_Sflnan));
531*4887Schin 	memcpy((char*)&_Sflinf, (char*)ldbl_inf, sizeof(_Sflinf));
532*4887Schin #else
533*4887Schin 	memcpy((char*)&_Sflnan, (char*)dbl_nan, sizeof(_Sfdnan));
534*4887Schin 	memcpy((char*)&_Sflinf, (char*)dbl_inf, sizeof(_Sfdinf));
535*4887Schin #endif
536*4887Schin 
537*4887Schin 	return 1;
538*4887Schin }
539*4887Schin 
540*4887Schin /* table for floating point and integer conversions */
541*4887Schin #include	"FEATURE/sfinit"
542