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