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