Annotation of coherent/d/lib/libc/stdio/scanf.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.