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
sffmtint(const char * str,int * v)31 static char* sffmtint(const char* str, int* v)
32 #else
33 static char* sffmtint(str, v)
34 char* str;
35 int* 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
sffmtpos(Sfio_t * f,const char * form,va_list args,Sffmt_t * ft,int type)45 static Fmtpos_t* sffmtpos(Sfio_t* f,const char* form,va_list args,Sffmt_t* ft,int type)
46 #else
47 static Fmtpos_t* sffmtpos(f,form,args,ft,type)
48 Sfio_t* f;
49 char* form;
50 va_list args;
51 Sffmt_t* ft;
52 int 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 /* FALLTHROUGH */
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
469 static const unsigned char flt_nan[] = { _ast_flt_nan_init };
470 static const unsigned char flt_inf[] = { _ast_flt_inf_init };
471 static const unsigned char dbl_nan[] = { _ast_dbl_nan_init };
472 static const unsigned char dbl_inf[] = { _ast_dbl_inf_init };
473 #ifdef _ast_ldbl_nan_init
474 static const unsigned char ldbl_nan[] = { _ast_ldbl_nan_init };
475 static const unsigned char ldbl_inf[] = { _ast_ldbl_inf_init };
476 #endif
477
478 /* function to initialize conversion tables */
sfcvinit()479 static 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