|
|
1.1 ! root 1: /* ! 2: * pANS stdio -- vfscanf ! 3: */ ! 4: #include "iolib.h" ! 5: #include <stdarg.h> ! 6: #include <math.h> ! 7: #include <stdlib.h> ! 8: #include <ctype.h> ! 9: #ifdef sgi ! 10: #undef getc ! 11: #define getc(p) (--(p)->_cnt>=0? (int)*(p)->_ptr++:xfilbuf(p)) ! 12: ! 13: static int __cnt; ! 14: static int xfilbuf(FILE*); ! 15: ! 16: static int ! 17: xfilbuf(FILE *p) ! 18: { ! 19: int rv; ! 20: if (p->_flag & _IOEOF) ! 21: return EOF; ! 22: if (_us_rsthread_stdio) { ! 23: p->_cnt = __cnt; ! 24: rv = _semgetc(p); ! 25: __cnt = p->_cnt; ! 26: p->_cnt = 0; ! 27: } ! 28: else { ! 29: rv = _filbuf(p); ! 30: if (p->_cnt == 1 && p->_ptr == p->_base) ! 31: p->_cnt = 0; ! 32: } ! 33: return rv; ! 34: } ! 35: #endif ! 36: static int icvt_f(FILE *f, va_list *args, int store, int width, int type); ! 37: static int icvt_x(FILE *f, va_list *args, int store, int width, int type); ! 38: static int icvt_sq(FILE *f, va_list *args, int store, int width, int type); ! 39: static int icvt_c(FILE *f, va_list *args, int store, int width, int type); ! 40: static int icvt_d(FILE *f, va_list *args, int store, int width, int type); ! 41: static int icvt_i(FILE *f, va_list *args, int store, int width, int type); ! 42: static int icvt_n(FILE *f, va_list *args, int store, int width, int type); ! 43: static int icvt_o(FILE *f, va_list *args, int store, int width, int type); ! 44: static int icvt_p(FILE *f, va_list *args, int store, int width, int type); ! 45: static int icvt_s(FILE *f, va_list *args, int store, int width, int type); ! 46: static int icvt_u(FILE *f, va_list *args, int store, int width, int type); ! 47: static int (*icvt[])(FILE *, va_list *, int, int, int)={ ! 48: 0, 0, 0, 0, 0, 0, 0, 0, /* ^@ ^A ^B ^C ^D ^E ^F ^G */ ! 49: 0, 0, 0, 0, 0, 0, 0, 0, /* ^H ^I ^J ^K ^L ^M ^N ^O */ ! 50: 0, 0, 0, 0, 0, 0, 0, 0, /* ^P ^Q ^R ^S ^T ^U ^V ^W */ ! 51: 0, 0, 0, 0, 0, 0, 0, 0, /* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */ ! 52: 0, 0, 0, 0, 0, 0, 0, 0, /* sp ! " # $ % & ' */ ! 53: 0, 0, 0, 0, 0, 0, 0, 0, /* ( ) * + , - . / */ ! 54: 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */ ! 55: 0, 0, 0, 0, 0, 0, 0, 0, /* 8 9 : ; < = > ? */ ! 56: 0, 0, 0, 0, 0, icvt_f, 0, icvt_f, /* @ A B C D E F G */ ! 57: 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */ ! 58: 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */ ! 59: icvt_x, 0, 0, icvt_sq,0, 0, 0, 0, /* X Y Z [ \ ] ^ _ */ ! 60: 0, 0, 0, icvt_c, icvt_d, icvt_f, icvt_f, icvt_f, /* ` a b c d e f g */ ! 61: 0, icvt_i, 0, 0, 0, 0, icvt_n, icvt_o, /* h i j k l m n o */ ! 62: icvt_p, 0, 0, icvt_s, 0, icvt_u, 0, 0, /* p q r s t u v w */ ! 63: icvt_x, 0, 0, 0, 0, 0, 0, 0, /* x y z { | } ~ ^? */ ! 64: ! 65: 0, 0, 0, 0, 0, 0, 0, 0, ! 66: 0, 0, 0, 0, 0, 0, 0, 0, ! 67: 0, 0, 0, 0, 0, 0, 0, 0, ! 68: 0, 0, 0, 0, 0, 0, 0, 0, ! 69: 0, 0, 0, 0, 0, 0, 0, 0, ! 70: 0, 0, 0, 0, 0, 0, 0, 0, ! 71: 0, 0, 0, 0, 0, 0, 0, 0, ! 72: 0, 0, 0, 0, 0, 0, 0, 0, ! 73: 0, 0, 0, 0, 0, 0, 0, 0, ! 74: 0, 0, 0, 0, 0, 0, 0, 0, ! 75: 0, 0, 0, 0, 0, 0, 0, 0, ! 76: 0, 0, 0, 0, 0, 0, 0, 0, ! 77: 0, 0, 0, 0, 0, 0, 0, 0, ! 78: 0, 0, 0, 0, 0, 0, 0, 0, ! 79: 0, 0, 0, 0, 0, 0, 0, 0, ! 80: 0, 0, 0, 0, 0, 0, 0, 0, ! 81: ! 82: }; ! 83: #define ngetc(f) (nread++, getc(f)) ! 84: #define nungetc(c, f) (--nread, ungetc((c), f)) ! 85: #define wgetc(c, f, out) if(width--==0) goto out; (c)=ngetc(f) ! 86: #define wungetc(c, f) (++width, nungetc(c, f)) ! 87: static int nread, ncvt; ! 88: static const char *fmtp; ! 89: ! 90: int vfscanf(FILE *f, const char *s, va_list args){ ! 91: int c, width, type, store; ! 92: #ifdef sgi ! 93: if (_us_rsthread_stdio) { ! 94: __cnt = f->_cnt; ! 95: f->_cnt = 0; ! 96: } ! 97: #endif ! 98: nread=0; ! 99: ncvt=0; ! 100: fmtp=s; ! 101: for(;*fmtp;fmtp++) switch(*fmtp){ ! 102: default: ! 103: if(isspace(*fmtp)){ ! 104: do ! 105: c=ngetc(f); ! 106: while(isspace(c)); ! 107: if(c==EOF) return ncvt?ncvt:EOF; ! 108: nungetc(c, f); ! 109: break; ! 110: } ! 111: NonSpecial: ! 112: c=ngetc(f); ! 113: if(c==EOF) return ncvt?ncvt:EOF; ! 114: if(c!=*fmtp){ ! 115: nungetc(c, f); ! 116: return ncvt; ! 117: } ! 118: break; ! 119: case '%': ! 120: fmtp++; ! 121: if(*fmtp!='*') store=1; ! 122: else{ ! 123: store=0; ! 124: fmtp++; ! 125: } ! 126: if('0'<=*fmtp && *fmtp<='9'){ ! 127: width=0; ! 128: while('0'<=*fmtp && *fmtp<='9') width=width*10 + *fmtp++ - '0'; ! 129: } ! 130: else ! 131: width=-1; ! 132: type=*fmtp=='h' || *fmtp=='l' || *fmtp=='L'?*fmtp++:'n'; ! 133: if(!icvt[*fmtp]) goto NonSpecial; ! 134: if(!(*icvt[*fmtp])(f, &args, store, width, type)) ! 135: return ncvt?ncvt:feof(f)?EOF:0; ! 136: if(*fmtp=='\0') break; ! 137: if(store) ncvt++; ! 138: } ! 139: return ncvt; ! 140: } ! 141: static int icvt_n(FILE *f, va_list *args, int store, int width, int type){ ! 142: #pragma ref f ! 143: #pragma ref width ! 144: if(store){ ! 145: --ncvt; /* this assignment doesn't count! */ ! 146: switch(type){ ! 147: case 'h': *va_arg(*args, short *)=nread; break; ! 148: case 'n': *va_arg(*args, int *)=nread; break; ! 149: case 'l': ! 150: case 'L': *va_arg(*args, long *)=nread; break; ! 151: } ! 152: } ! 153: return 1; ! 154: } ! 155: #define SIGNED 1 ! 156: #define UNSIGNED 2 ! 157: #define POINTER 3 ! 158: /* ! 159: * Generic fixed-point conversion ! 160: * f is the input FILE *; ! 161: * args is the va_list * into which to store the number; ! 162: * store is a flag to enable storing; ! 163: * width is the maximum field width; ! 164: * type is 'h' 'l' or 'L', the scanf type modifier; ! 165: * unsgned is SIGNED, UNSIGNED or POINTER, giving part of the type to store in; ! 166: * base is the number base -- if 0, C number syntax is used. ! 167: */ ! 168: static int icvt_fixed(FILE *f, va_list *args, ! 169: int store, int width, int type, int unsgned, int base){ ! 170: unsigned long int num=0; ! 171: int sign=1, ndig=0, dig; ! 172: int c; ! 173: do ! 174: c=ngetc(f); ! 175: while(isspace(c)); ! 176: if(width--==0){ ! 177: nungetc(c, f); ! 178: goto Done; ! 179: } ! 180: if(c=='+'){ ! 181: wgetc(c, f, Done); ! 182: } ! 183: else if(c=='-'){ ! 184: sign=-1; ! 185: wgetc(c, f, Done); ! 186: } ! 187: switch(base){ ! 188: case 0: ! 189: if(c=='0'){ ! 190: wgetc(c, f, Done); ! 191: if(c=='x' || c=='X'){ ! 192: wgetc(c, f, Done); ! 193: base=16; ! 194: } ! 195: else{ ! 196: ndig=1; ! 197: base=8; ! 198: } ! 199: } ! 200: else ! 201: base=10; ! 202: break; ! 203: case 16: ! 204: if(c=='0'){ ! 205: wgetc(c, f, Done); ! 206: if(c=='x' || c=='X'){ ! 207: wgetc(c, f, Done); ! 208: } ! 209: else ndig=1; ! 210: } ! 211: break; ! 212: } ! 213: while('0'<=c && c<='9' || 'a'<=c && c<='f' || 'A'<=c && c<='F'){ ! 214: dig='0'<=c && c<='9'?c-'0':'a'<=c && c<='f'?c-'a'+10:c-'A'+10; ! 215: if(dig>=base) break; ! 216: ndig++; ! 217: num=num*base+dig; ! 218: wgetc(c, f, Done); ! 219: } ! 220: nungetc(c, f); ! 221: Done: ! 222: if(ndig==0) return 0; ! 223: if(store){ ! 224: switch(unsgned){ ! 225: case SIGNED: ! 226: switch(type){ ! 227: case 'h': *va_arg(*args, short *)=num*sign; break; ! 228: case 'n': *va_arg(*args, int *)=num*sign; break; ! 229: case 'l': ! 230: case 'L': *va_arg(*args, long *)=num*sign; break; ! 231: } ! 232: break; ! 233: case UNSIGNED: ! 234: switch(type){ ! 235: case 'h': *va_arg(*args, unsigned short *)=num*sign; break; ! 236: case 'n': *va_arg(*args, unsigned int *)=num*sign; break; ! 237: case 'l': ! 238: case 'L': *va_arg(*args, unsigned long *)=num*sign; break; ! 239: } ! 240: break; ! 241: case POINTER: ! 242: *va_arg(*args, void **)=(void *)(num*sign); break; ! 243: } ! 244: } ! 245: return 1; ! 246: } ! 247: static int icvt_d(FILE *f, va_list *args, int store, int width, int type){ ! 248: return icvt_fixed(f, args, store, width, type, SIGNED, 10); ! 249: } ! 250: static int icvt_x(FILE *f, va_list *args, int store, int width, int type){ ! 251: return icvt_fixed(f, args, store, width, type, UNSIGNED, 16); ! 252: } ! 253: static int icvt_o(FILE *f, va_list *args, int store, int width, int type){ ! 254: return icvt_fixed(f, args, store, width, type, UNSIGNED, 8); ! 255: } ! 256: static int icvt_i(FILE *f, va_list *args, int store, int width, int type){ ! 257: return icvt_fixed(f, args, store, width, type, SIGNED, 0); ! 258: } ! 259: static int icvt_u(FILE *f, va_list *args, int store, int width, int type){ ! 260: return icvt_fixed(f, args, store, width, type, UNSIGNED, 10); ! 261: } ! 262: static int icvt_p(FILE *f, va_list *args, int store, int width, int type){ ! 263: return icvt_fixed(f, args, store, width, type, POINTER, 16); ! 264: } ! 265: #define NBUF 509 ! 266: static int icvt_f(FILE *f, va_list *args, int store, int width, int type){ ! 267: char buf[NBUF+1]; ! 268: char *s=buf; ! 269: int c, ndig=0, ndpt=0, nexp=1; ! 270: if(width<0 || NBUF<width) width=NBUF; /* bug -- no limit specified in ansi */ ! 271: do ! 272: c=ngetc(f); ! 273: while(isspace(c)); ! 274: if(width--==0){ ! 275: nungetc(c, f); ! 276: goto Done; ! 277: } ! 278: if(c=='+' || c=='-'){ ! 279: *s++=c; ! 280: wgetc(c, f, Done); ! 281: } ! 282: while('0'<=c && c<='9' || ndpt==0 && c=='.'){ ! 283: if(c=='.') ndpt++; ! 284: else ndig++; ! 285: *s++=c; ! 286: wgetc(c, f, Done); ! 287: } ! 288: if(c=='e' || c=='E'){ ! 289: *s++=c; ! 290: nexp=0; ! 291: wgetc(c, f, Done); ! 292: if(c=='+' || c=='-'){ ! 293: *s++=c; ! 294: wgetc(c, f, Done); ! 295: } ! 296: while('0'<=c && c<='9'){ ! 297: *s++=c; ! 298: nexp++; ! 299: wgetc(c, f, Done); ! 300: } ! 301: } ! 302: nungetc(c, f); ! 303: Done: ! 304: if(ndig==0 || nexp==0) return 0; ! 305: *s='\0'; ! 306: if(store) switch(type){ ! 307: case 'h': ! 308: case 'n': *va_arg(*args, float *)=atof(buf); break; ! 309: case 'L': /* bug -- should store in a long double */ ! 310: case 'l': *va_arg(*args, double *)=atof(buf); break; ! 311: } ! 312: return 1; ! 313: } ! 314: static int icvt_s(FILE *f, va_list *args, int store, int width, int type){ ! 315: #pragma ref type ! 316: int c, nn; ! 317: register char *s; ! 318: if(store) s=va_arg(*args, char *); ! 319: do ! 320: c=ngetc(f); ! 321: while(isspace(c)); ! 322: if(width--==0){ ! 323: nungetc(c, f); ! 324: goto Done; ! 325: } ! 326: nn=0; ! 327: while(!isspace(c)){ ! 328: if(c==EOF){ ! 329: if(nn==0) return 0; ! 330: else goto Done; ! 331: } ! 332: nn++; ! 333: if(store) *s++=c; ! 334: wgetc(c, f, Done); ! 335: } ! 336: nungetc(c, f); ! 337: Done: ! 338: if(store) *s='\0'; ! 339: return 1; ! 340: } ! 341: static int icvt_c(FILE *f, va_list *args, int store, int width, int type){ ! 342: #pragma ref type ! 343: int c; ! 344: register char *s; ! 345: if(store) s=va_arg(*args, char *); ! 346: if(width<0) width=1; ! 347: for(;;){ ! 348: wgetc(c, f, Done); ! 349: if(c==EOF) return 0; ! 350: if(store) *s++=c; ! 351: } ! 352: Done: ! 353: return 1; ! 354: } ! 355: static int match(int c, const char *pat){ ! 356: int ok=1; ! 357: if(*pat=='^'){ ! 358: ok=!ok; ! 359: pat++; ! 360: } ! 361: while(pat!=fmtp){ ! 362: if(pat+2<fmtp && pat[1]=='-'){ ! 363: if(pat[0]<=c && c<=pat[2] ! 364: || pat[2]<=c && c<=pat[0]) ! 365: return ok; ! 366: pat+=2; ! 367: } ! 368: else if(c==*pat) return ok; ! 369: pat++; ! 370: } ! 371: return !ok; ! 372: } ! 373: static int icvt_sq(FILE *f, va_list *args, int store, int width, int type){ ! 374: #pragma ref type ! 375: int c, nn; ! 376: register char *s; ! 377: register const char *pat; ! 378: pat=++fmtp; ! 379: if(*fmtp=='^') fmtp++; ! 380: if(*fmtp!='\0') fmtp++; ! 381: while(*fmtp!='\0' && *fmtp!=']') fmtp++; ! 382: if(store) s=va_arg(*args, char *); ! 383: nn=0; ! 384: for(;;){ ! 385: wgetc(c, f, Done); ! 386: if(c==EOF){ ! 387: if(nn==0) return 0; ! 388: else goto Done; ! 389: } ! 390: if(!match(c, pat)) break; ! 391: if(store) *s++=c; ! 392: nn++; ! 393: } ! 394: nungetc(c, f); ! 395: Done: ! 396: if(store) *s='\0'; ! 397: return 1; ! 398: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.