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 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 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 */ 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