|
|
1.1 ! root 1: /* ! 2: * Standard I/O Library formatted input ! 3: * Non-portable things: ! 4: * 1) alignment of arguments is assumed to be completely contiguous. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: ! 9: union alltypes { ! 10: char *c; ! 11: short *h; ! 12: int *i; ! 13: unsigned *u; ! 14: long *l; ! 15: double *d; ! 16: char *s; ! 17: }; ! 18: ! 19: ! 20: /* ! 21: * scan standard input ! 22: */ ! 23: ! 24: int ! 25: scanf(args) ! 26: union alltypes args; ! 27: { ! 28: return (xscanf(stdin, &args)); ! 29: } ! 30: ! 31: ! 32: /* ! 33: * scan given file ! 34: */ ! 35: ! 36: int ! 37: fscanf(fp, args) ! 38: FILE *fp; ! 39: union alltypes args; ! 40: { ! 41: return (xscanf(fp, &args)); ! 42: } ! 43: ! 44: ! 45: /* ! 46: * scan given string by handcrafting file structure for getc ! 47: */ ! 48: ! 49: int ! 50: sscanf(sp, args) ! 51: char *sp; ! 52: union alltypes args; ! 53: { ! 54: FILE file; ! 55: ! 56: _stropen(sp, strlen(sp), &file); ! 57: return (xscanf(&file, &args)); ! 58: } ! 59: ! 60: ! 61: static ! 62: int ! 63: xscanf(fp, argp) ! 64: FILE *fp; ! 65: union alltypes *argp; ! 66: { ! 67: register int fc, gc; ! 68: int base, width, gotany, supprf, longf, shortf, retval = 0; ! 69: char *fmt; ! 70: extern char *index(); ! 71: ! 72: fmt = *(char **)argp++; ! 73: for (;;) { ! 74: switch (fc = *fmt++) { ! 75: case '\0': ! 76: break; ! 77: case '\t': ! 78: case '\n': ! 79: case ' ': ! 80: ungetc(gc=skipws(fp), fp); ! 81: if (gc == EOF) ! 82: break; ! 83: else ! 84: continue; ! 85: default: ! 86: matchin: ! 87: if ((gc=getc(fp)) != fc) { ! 88: ungetc(gc, fp); ! 89: break; ! 90: } else ! 91: continue; ! 92: case '%': ! 93: supprf = (fc = *fmt++) == '*'; ! 94: if (supprf) ! 95: fc = *fmt++; ! 96: for (width = 0; '0'<=fc && fc<='9'; fc = *fmt++) ! 97: width = width*10 + fc - '0'; ! 98: longf = fc=='l'; ! 99: shortf = fc=='h'; ! 100: if (longf || shortf) ! 101: fc = *fmt++; ! 102: switch (fc) { ! 103: default: ! 104: fputs("Bad format in scanf\n", stderr); ! 105: abort(); ! 106: case '\0': ! 107: break; ! 108: case '%': ! 109: goto matchin; ! 110: case 'D': ! 111: longf++; ! 112: case 'd': ! 113: base = 10; ! 114: goto fixed; ! 115: case 'O': ! 116: longf++; ! 117: case 'o': ! 118: base = 8; ! 119: goto fixed; ! 120: case 'N': ! 121: longf++; ! 122: case 'n': ! 123: base = 0; ! 124: goto fixed; ! 125: case 'X': ! 126: longf++; ! 127: case 'x': ! 128: base = 16; ! 129: fixed: ! 130: { ! 131: long longn, fgetnum(); ! 132: ! 133: longn = fgetnum(fp, base, width, &gotany); ! 134: if (!gotany) ! 135: break; ! 136: if (supprf) ! 137: continue; ! 138: if (longf) ! 139: **(long **)argp++ = longn; ! 140: else if (shortf) ! 141: **(short **)argp++ = (short)longn; ! 142: else ! 143: **(int **)argp++ = (int)longn; ! 144: retval++; ! 145: continue; ! 146: } ! 147: case 'E': ! 148: case 'F': ! 149: longf++; ! 150: case 'e': ! 151: case 'f': ! 152: { ! 153: double doublen, fgetdbl(); ! 154: ! 155: doublen = fgetdbl(fp, width, &gotany); ! 156: if (!gotany) ! 157: break; ! 158: if (supprf) ! 159: continue; ! 160: if (longf) ! 161: **(double **)argp++ = doublen; ! 162: else ! 163: **(float **)argp++ = doublen; ! 164: retval++; ! 165: continue; ! 166: } ! 167: case '[': ! 168: { ! 169: char ss[64], *s = ss; ! 170: int breakf; ! 171: register char *cp; ! 172: ! 173: breakf = (fc = *fmt++) == '^'; ! 174: if (breakf) ! 175: fc = *fmt++; ! 176: while (fc!='\0' && fc!=']') { ! 177: *s++ = fc; ! 178: fc = *fmt++; ! 179: } ! 180: *s = '\0'; ! 181: s = ss; ! 182: gc = getc(fp); ! 183: goto scanin; ! 184: case 'c': ! 185: if (width==0) ! 186: width = 1; ! 187: gc = getc(fp); ! 188: s = ""; ! 189: breakf = 1; ! 190: goto scanin; ! 191: case 's': ! 192: gc = skipws(fp); ! 193: s = "\t\n "; ! 194: breakf = 1; ! 195: scanin: ! 196: if (!supprf) ! 197: cp = *(char **)argp++; ! 198: gotany = 0; ! 199: while (gc!=EOF ! 200: && (index(s, gc)==NULL)==breakf) { ! 201: gotany++; ! 202: if (!supprf) ! 203: *cp++ = gc; ! 204: if (--width==0) ! 205: gc = EOF; ! 206: else ! 207: gc = getc(fp); ! 208: } ! 209: if (gc!=EOF) ! 210: ungetc(gc, fp); ! 211: if (!gotany) ! 212: break; ! 213: if (supprf) ! 214: continue; ! 215: if (fc!='c') ! 216: *cp = '\0'; ! 217: retval++; ! 218: continue; ! 219: } ! 220: case 'r': ! 221: retval += xscanf(fp, *(union alltypes **)argp++); ! 222: continue; ! 223: } ! 224: break; ! 225: } ! 226: break; ! 227: } ! 228: return (retval==0&&feof(fp) ? EOF : retval); ! 229: } ! 230: ! 231: /* ! 232: * Read a long integer from file fp ! 233: */ ! 234: static ! 235: long ! 236: fgetnum(fp, base, width, got) ! 237: FILE *fp; ! 238: register int base, width; ! 239: int *got; ! 240: { ! 241: long val = 0; ! 242: register int c, i; ! 243: int neg; ! 244: ! 245: if (width <= 0 || 32 < width) ! 246: width = 32; ! 247: *got = 0; ! 248: c = skipws(fp); ! 249: if ((neg=c=='-') || c=='+') ! 250: c = getc(fp), ++*got; ! 251: if (*got>width) ! 252: ; ! 253: else if (base!=0) ! 254: ; ! 255: else if (c!='0') ! 256: base = 10; ! 257: else if (c=getc(fp), ++*got>width) ! 258: ; ! 259: else if (c!='x') ! 260: base = 8; ! 261: else { ! 262: base = 16; ! 263: c = getc(fp), ++*got; ! 264: } ! 265: for (; *got < width; ++*got) { ! 266: if ((10<=(i=c-('a'-10)) ! 267: || 10<=(i=c-('A'-10)) ! 268: || 0<=(i=c-'0') && i<=9) ! 269: && i<base ! 270: || base==16 && val==0L && (i=c-'x')==0) { ! 271: val = val*base - i; ! 272: c = getc(fp); ! 273: } else ! 274: break; ! 275: } ! 276: ungetc(c, fp); ! 277: return (neg ? val : -val); ! 278: } ! 279: ! 280: /* ! 281: * Scan off floating point number into buffer for atof ! 282: * using automaton shown below ! 283: * states in parantheses ! 284: * inputs in brackets ! 285: * for all inputs not shown, transition is to (end) ! 286: * ! 287: * -- ! 288: * / \ ! 289: * v \ ! 290: * ----------> [0-9] -> (3) ! 291: * / ^ | \ ! 292: * / / | \ ! 293: * / / v \ ! 294: * / / [.] \ ->[+-] - ! 295: * / / | \ / \ ! 296: * / / | \ / \ ! 297: * / / v v / v ! 298: * (0) --> [+-] -> (1) (4) --> [Ee] -> (6) -> [0-9] -> (7) ! 299: * \ / / ^ ^ / ! 300: * \ / / / \ / ! 301: * \ / / / -- ! 302: * \ / / / ! 303: * \ / / / ! 304: * \ / / / ! 305: * v v / ! 306: * [.] --> (2) -> [0-9] -> (5) ! 307: * ^ / ! 308: * \ / ! 309: * -- ! 310: * ! 311: */ ! 312: static ! 313: double ! 314: fgetdbl(fp, width, got) ! 315: FILE *fp; ! 316: int width, *got; ! 317: { ! 318: double atof(); ! 319: register int c, state = 0; ! 320: char str[33]; ! 321: register char *s = str; ! 322: ! 323: if (width<=0 || 32<width) ! 324: width = 32; ! 325: for (*got = 0; *got < width; ++*got) { ! 326: switch (c=getc(fp)) { ! 327: case '\t': ! 328: case '\n': ! 329: case ' ': ! 330: if (state!=0) ! 331: break; ! 332: --*got; ! 333: continue; ! 334: case '+': ! 335: case '-': ! 336: if (state!=0 && state!=6) ! 337: break; ! 338: state++; ! 339: *s++ = c; ! 340: continue; ! 341: case '.': ! 342: if (state<=1) ! 343: state = 2; ! 344: else if (state==3) ! 345: state++; ! 346: else ! 347: break; ! 348: *s++ = c; ! 349: continue; ! 350: case '0': ! 351: case '1': ! 352: case '2': ! 353: case '3': ! 354: case '4': ! 355: case '5': ! 356: case '6': ! 357: case '7': ! 358: case '8': ! 359: case '9': ! 360: if (state==0 || state==1 || state==3) ! 361: state = 3; ! 362: else if (state==2 || state==4 || state==5) ! 363: state = 5; ! 364: else if (state==6 || state==7) ! 365: state = 7; ! 366: else ! 367: break; ! 368: *s++ = c; ! 369: continue; ! 370: case 'E': ! 371: case 'e': ! 372: if (state<3 || 5<state) ! 373: break; ! 374: state = 6; ! 375: *s++ = c; ! 376: continue; ! 377: default: ! 378: break; ! 379: } ! 380: ungetc(c, fp); ! 381: break; ! 382: } ! 383: *s = '\0'; ! 384: return (atof(str)); ! 385: } ! 386: ! 387: static ! 388: int ! 389: skipws(fp) ! 390: FILE *fp; ! 391: { ! 392: register int c; ! 393: ! 394: while ((c=getc(fp))==' ' || c=='\n' || c=='\t') ! 395: ; ! 396: return (c); ! 397: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.