1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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 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 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 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 */ 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