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