1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 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
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 #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
471 static const unsigned char flt_nan[] = { _ast_flt_nan_init };
472 static const unsigned char flt_inf[] = { _ast_flt_inf_init };
473 static const unsigned char dbl_nan[] = { _ast_dbl_nan_init };
474 static const unsigned char dbl_inf[] = { _ast_dbl_inf_init };
475 #ifdef _ast_ldbl_nan_init
476 static const unsigned char ldbl_nan[] = { _ast_ldbl_nan_init };
477 static const unsigned char ldbl_inf[] = { _ast_ldbl_inf_init };
478 #endif
479
480 /* function to initialize conversion tables */
sfcvinit()481 static 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