Annotation of GNUtools/libg++/libio/iovfscanf.c, revision 1.1.1.1

1.1       root        1: /* 
                      2: Copyright (C) 1993 Free Software Foundation
                      3: 
                      4: This file is part of the GNU IO Library.  This library is free
                      5: software; you can redistribute it and/or modify it under the
                      6: terms of the GNU General Public License as published by the
                      7: Free Software Foundation; either version 2, or (at your option)
                      8: any later version.
                      9: 
                     10: This library is distributed in the hope that it will be useful,
                     11: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13: GNU General Public License for more details.
                     14: 
                     15: You should have received a copy of the GNU General Public License
                     16: along with GNU CC; see the file COPYING.  If not, write to
                     17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
                     18: 
                     19: As a special exception, if you link this library with files
                     20: compiled with a GNU compiler to produce an executable, this does not cause
                     21: the resulting executable to be covered by the GNU General Public License.
                     22: This exception does not however invalidate any other reasons why
                     23: the executable file might be covered by the GNU General Public License. */
                     24: 
                     25: /*
                     26:  * Copyright (c) 1990 The Regents of the University of California.
                     27:  * All rights reserved.
                     28:  *
                     29:  * Redistribution and use in source and binary forms are permitted
                     30:  * provided that the above copyright notice and this paragraph are
                     31:  * duplicated in all such forms and that any documentation,
                     32:  * advertising materials, and other materials related to such
                     33:  * distribution and use acknowledge that the software was developed
                     34:  * by the University of California, Berkeley.  The name of the
                     35:  * University may not be used to endorse or promote products derived
                     36:  * from this software without specific prior written permission.
                     37:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     38:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     39:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     40:  */
                     41: 
                     42: /* Extensively hacked for GNU iostream by Per Bothner 1991, 1992, 1993.
                     43:    Changes copyright Free Software Foundation 1992, 1993. */
                     44: 
                     45: #if defined(LIBC_SCCS) && !defined(lint)
                     46: static char sccsid[] = "%W% (Berkeley) %G%";
                     47: #endif /* LIBC_SCCS and not lint */
                     48: 
                     49: #include <libioP.h>
                     50: #include <ctype.h>
                     51: #ifdef __STDC__
                     52: #include <stdarg.h>
                     53: #else
                     54: #include <varargs.h>
                     55: #endif
                     56: 
                     57: #ifndef        NO_FLOATING_POINT
                     58: #define FLOATING_POINT
                     59: #endif
                     60: 
                     61: #ifdef FLOATING_POINT
                     62: #include "floatio.h"
                     63: #define        BUF     (MAXEXP+MAXFRACT+3)     /* 3 = sign + decimal point + NUL */
                     64: #else
                     65: #define        BUF     40
                     66: #endif
                     67: 
                     68: /*
                     69:  * Flags used during conversion.
                     70:  */
                     71: #define        LONG            0x01    /* l: long or double */
                     72: #define        LONGDBL         0x02    /* L: long double; unimplemented */
                     73: #define        SHORT           0x04    /* h: short */
                     74: #define        SUPPRESS        0x08    /* suppress assignment */
                     75: #define        POINTER         0x10    /* weird %p pointer (`fake hex') */
                     76: #define        NOSKIP          0x20    /* do not skip blanks */
                     77: 
                     78: /*
                     79:  * The following are used in numeric conversions only:
                     80:  * SIGNOK, NDIGITS, DPTOK, and EXPOK are for floating point;
                     81:  * SIGNOK, NDIGITS, PFXOK, and NZDIGITS are for integral.
                     82:  */
                     83: #define        SIGNOK          0x40    /* +/- is (still) legal */
                     84: #define        NDIGITS         0x80    /* no digits detected */
                     85: 
                     86: #define        DPTOK           0x100   /* (float) decimal point is still legal */
                     87: #define        EXPOK           0x200   /* (float) exponent (e+3, etc) still legal */
                     88: 
                     89: #define        PFXOK           0x100   /* 0x prefix is (still) legal */
                     90: #define        NZDIGITS        0x200   /* no zero digits detected */
                     91: 
                     92: /*
                     93:  * Conversion types.
                     94:  */
                     95: #define        CT_CHAR         0       /* %c conversion */
                     96: #define        CT_CCL          1       /* %[...] conversion */
                     97: #define        CT_STRING       2       /* %s conversion */
                     98: #define        CT_INT          3       /* integer, i.e., strtol or strtoul */
                     99: #define        CT_FLOAT        4       /* floating, i.e., strtod */
                    100: 
                    101: #define u_char unsigned char
                    102: #define u_long unsigned long
                    103: 
                    104: extern u_long strtoul _PARAMS((const char*, char**, int));
                    105: extern long strtol _PARAMS((const char*, char**, int));
                    106: static const u_char *__sccl _PARAMS((char *tab, const u_char *fmt));
                    107: #ifndef USE_DTOA
                    108: extern double atof();
                    109: #endif
                    110: 
                    111: /* If errp != NULL, *errp|=1 if we see a premature EOF;
                    112:    *errp|=2 if we an invalid character. */
                    113: 
                    114: int
                    115: _IO_vfscanf(fp, fmt0, ap, errp)
                    116:      register _IO_FILE *fp;
                    117:      char const *fmt0;
                    118:      _IO_va_list ap;
                    119:      int *errp;
                    120: {
                    121:        register const u_char *fmt = (const u_char *)fmt0;
                    122:        register int c;         /* character from format, or conversion */
                    123:        register _IO_ssize_t width;     /* field width, or 0 */
                    124:        register char *p;       /* points into all kinds of strings */
                    125:        register int n;         /* handy integer */
                    126:        register int flags;     /* flags as defined above */
                    127:        register char *p0;      /* saves original value of p when necessary */
                    128:        int nassigned;          /* number of fields assigned */
                    129:        int nread;              /* number of characters consumed from fp */
                    130:        /* Assignments to base and ccfn are just to suppress warnings from gcc.*/
                    131:        int base = 0;           /* base argument to strtol/strtoul */
                    132:        typedef u_long (*strtoulfn) _PARAMS((const char*, char**, int));
                    133:        strtoulfn ccfn = 0;
                    134:        /* conversion function (strtol/strtoul) */
                    135:        char ccltab[256];       /* character class table for %[...] */
                    136:        char buf[BUF];          /* buffer for numeric conversions */
                    137:        int seen_eof = 0;
                    138: 
                    139:        /* `basefix' is used to avoid `if' tests in the integer scanner */
                    140:        static short basefix[17] =
                    141:                { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
                    142: 
                    143:        nassigned = 0;
                    144:        nread = 0;
                    145:        for (;;) {
                    146:                c = *fmt++;
                    147:                if (c == 0)
                    148:                        goto done;
                    149:                if (isspace(c)) {
                    150:                        for (;;) {
                    151:                                c = _IO_getc(fp);
                    152:                                if (c == EOF) {
                    153:                                  seen_eof++;
                    154:                                  break;
                    155:                                }
                    156:                                if (!isspace(c)) {
                    157:                                    _IO_ungetc (c, fp);
                    158:                                    break;
                    159:                                }
                    160:                                nread++;
                    161:                        }
                    162:                        continue;
                    163:                }
                    164:                if (c != '%')
                    165:                        goto literal;
                    166:                width = 0;
                    167:                flags = 0;
                    168:                /*
                    169:                 * switch on the format.  continue if done;
                    170:                 * break once format type is derived.
                    171:                 */
                    172: again:         c = *fmt++;
                    173:                switch (c) {
                    174:                case '%':
                    175: literal:
                    176:                        n = _IO_getc(fp);
                    177:                        if (n == EOF)
                    178:                            goto eof_failure;
                    179:                        if (n != c) {
                    180:                            _IO_ungetc (n, fp);
                    181:                            goto match_failure;
                    182:                        }
                    183:                        nread++;
                    184:                        continue;
                    185: 
                    186:                case '*':
                    187:                        flags |= SUPPRESS;
                    188:                        goto again;
                    189:                case 'l':
                    190:                        flags |= LONG;
                    191:                        goto again;
                    192:                case 'L':
                    193:                        flags |= LONGDBL;
                    194:                        goto again;
                    195:                case 'h':
                    196:                        flags |= SHORT;
                    197:                        goto again;
                    198: 
                    199:                case '0': case '1': case '2': case '3': case '4':
                    200:                case '5': case '6': case '7': case '8': case '9':
                    201:                        width = width * 10 + c - '0';
                    202:                        goto again;
                    203: 
                    204:                /*
                    205:                 * Conversions.
                    206:                 * Those marked `compat' are for 4.[123]BSD compatibility.
                    207:                 *
                    208:                 * (According to ANSI, E and X formats are supposed
                    209:                 * to the same as e and x.  Sorry about that.)
                    210:                 */
                    211:                case 'D':       /* compat */
                    212:                        flags |= LONG;
                    213:                        /* FALLTHROUGH */
                    214:                case 'd':
                    215:                        c = CT_INT;
                    216:                        ccfn = (strtoulfn)strtol;
                    217:                        base = 10;
                    218:                        break;
                    219: 
                    220:                case 'i':
                    221:                        c = CT_INT;
                    222:                        ccfn = (strtoulfn)strtol;
                    223:                        base = 0;
                    224:                        break;
                    225: 
                    226:                case 'O':       /* compat */
                    227:                        flags |= LONG;
                    228:                        /* FALLTHROUGH */
                    229:                case 'o':
                    230:                        c = CT_INT;
                    231:                        ccfn = strtoul;
                    232:                        base = 8;
                    233:                        break;
                    234: 
                    235:                case 'u':
                    236:                        c = CT_INT;
                    237:                        ccfn = strtoul;
                    238:                        base = 10;
                    239:                        break;
                    240: 
                    241:                case 'X':
                    242:                case 'x':
                    243:                        flags |= PFXOK; /* enable 0x prefixing */
                    244:                        c = CT_INT;
                    245:                        ccfn = strtoul;
                    246:                        base = 16;
                    247:                        break;
                    248: 
                    249: #ifdef FLOATING_POINT
                    250:                case 'E': case 'F':
                    251:                case 'e': case 'f': case 'g':
                    252:                        c = CT_FLOAT;
                    253:                        break;
                    254: #endif
                    255: 
                    256:                case 's':
                    257:                        c = CT_STRING;
                    258:                        break;
                    259: 
                    260:                case '[':
                    261:                        fmt = __sccl(ccltab, fmt);
                    262:                        flags |= NOSKIP;
                    263:                        c = CT_CCL;
                    264:                        break;
                    265: 
                    266:                case 'c':
                    267:                        flags |= NOSKIP;
                    268:                        c = CT_CHAR;
                    269:                        break;
                    270: 
                    271:                case 'p':       /* pointer format is like hex */
                    272:                        flags |= POINTER | PFXOK;
                    273:                        c = CT_INT;
                    274:                        ccfn = strtoul;
                    275:                        base = 16;
                    276:                        break;
                    277: 
                    278:                case 'n':
                    279:                        if (flags & SUPPRESS)   /* ??? */
                    280:                                continue;
                    281:                        if (flags & SHORT)
                    282:                                *va_arg(ap, short *) = nread;
                    283:                        else if (flags & LONG)
                    284:                                *va_arg(ap, long *) = nread;
                    285:                        else
                    286:                                *va_arg(ap, int *) = nread;
                    287:                        continue;
                    288: 
                    289:                /*
                    290:                 * Disgusting backwards compatibility hacks.    XXX
                    291:                 */
                    292:                case '\0':      /* compat */
                    293:                        nassigned = EOF;
                    294:                        goto done;
                    295: 
                    296:                default:        /* compat */
                    297:                        if (isupper(c))
                    298:                                flags |= LONG;
                    299:                        c = CT_INT;
                    300:                        ccfn = (strtoulfn)strtol;
                    301:                        base = 10;
                    302:                        break;
                    303:                }
                    304: 
                    305:                /*
                    306:                 * We have a conversion that requires input.
                    307:                 */
                    308:                if (_IO_peekc(fp) == EOF)
                    309:                        goto eof_failure;
                    310: 
                    311:                /*
                    312:                 * Consume leading white space, except for formats
                    313:                 * that suppress this.
                    314:                 */
                    315:                if ((flags & NOSKIP) == 0) {
                    316:                    n = (unsigned char)*fp->_IO_read_ptr;
                    317:                    while (isspace(n)) {
                    318:                        fp->_IO_read_ptr++;
                    319:                        nread++;
                    320:                        n = _IO_peekc(fp);
                    321:                        if (n == EOF)
                    322:                            goto eof_failure;
                    323:                    }
                    324:                    /* Note that there is at least one character in
                    325:                       the buffer, so conversions that do not set NOSKIP
                    326:                       can no longer result in an input failure. */
                    327:                }
                    328: 
                    329:                /*
                    330:                 * Do the conversion.
                    331:                 */
                    332:                switch (c) {
                    333: 
                    334:                case CT_CHAR:
                    335:                        /* scan arbitrary characters (sets NOSKIP) */
                    336:                        if (width == 0) /* FIXME! */
                    337:                                width = 1;
                    338:                        if (flags & SUPPRESS) {
                    339:                            _IO_size_t sum = 0;
                    340:                            for (;;) {
                    341:                                n = fp->_IO_read_end - fp->_IO_read_ptr;
                    342:                                if (n < (int)width) {
                    343:                                    sum += n;
                    344:                                    width -= n;
                    345:                                    fp->_IO_read_ptr += n;
                    346:                                    if (__underflow(fp) == EOF)
                    347:                                        if (sum == 0)
                    348:                                            goto eof_failure;
                    349:                                        else {
                    350:                                            seen_eof++;
                    351:                                            break;
                    352:                                        }
                    353:                                } else {
                    354:                                    sum += width;
                    355:                                    fp->_IO_read_ptr += width;
                    356:                                    break;
                    357:                                }
                    358:                            }
                    359:                            nread += sum;
                    360:                        } else {
                    361:                            _IO_size_t r =
                    362:                              (*fp->_jumps->__xsgetn)(fp,
                    363:                                                      (char*)va_arg(ap, char*),
                    364:                                                      width);
                    365:                            if (r != width)
                    366:                                goto eof_failure;
                    367:                            nread += r;
                    368:                            nassigned++;
                    369:                        }
                    370:                        break;
                    371: 
                    372:                case CT_CCL:
                    373:                        /* scan a (nonempty) character class (sets NOSKIP) */
                    374:                        if (width == 0)
                    375:                                width = ~0;     /* `infinity' */
                    376:                        /* take only those things in the class */
                    377:                        if (flags & SUPPRESS) {
                    378:                                n = 0;
                    379:                                while (ccltab[(unsigned char)*fp->_IO_read_ptr]) {
                    380:                                    n++, fp->_IO_read_ptr++;
                    381:                                    if (--width == 0)
                    382:                                        break;
                    383:                                    if (_IO_peekc(fp) == EOF) {
                    384:                                        if (n == 0)
                    385:                                            goto eof_failure;
                    386:                                        seen_eof++;
                    387:                                        break;
                    388:                                    }
                    389:                                }
                    390:                                if (n == 0)
                    391:                                        goto match_failure;
                    392:                        } else {
                    393:                            p0 = p = va_arg(ap, char *);
                    394:                            while (ccltab[(unsigned char)*fp->_IO_read_ptr]) {
                    395:                                *p++ = *fp->_IO_read_ptr++;
                    396:                                if (--width == 0)
                    397:                                    break;
                    398:                                if (_IO_peekc(fp) == EOF) {
                    399:                                    if (p == p0)
                    400:                                        goto eof_failure;
                    401:                                    seen_eof++;
                    402:                                    break;
                    403:                                }
                    404:                            }
                    405:                            n = p - p0;
                    406:                            if (n == 0)
                    407:                                goto match_failure;
                    408:                            *p = 0;
                    409:                            nassigned++;
                    410:                        }
                    411:                        nread += n;
                    412:                        break;
                    413: 
                    414:                case CT_STRING:
                    415:                        /* like CCL, but zero-length string OK, & no NOSKIP */
                    416:                        if (width == 0)
                    417:                                width = ~0;
                    418:                        if (flags & SUPPRESS) {
                    419:                                n = 0;
                    420:                                while (!isspace((unsigned char)*fp->_IO_read_ptr)) {
                    421:                                        n++, fp->_IO_read_ptr++;
                    422:                                        if (--width == 0)
                    423:                                                break;
                    424:                                        if (_IO_peekc(fp) == EOF) {
                    425:                                            seen_eof++;
                    426:                                            break;
                    427:                                        }
                    428:                                }
                    429:                                nread += n;
                    430:                        } else {
                    431:                                p0 = p = va_arg(ap, char *);
                    432:                                while (!isspace((unsigned char)*fp->_IO_read_ptr)) {
                    433:                                        *p++ = *fp->_IO_read_ptr++;
                    434:                                        if (--width == 0)
                    435:                                                break;
                    436:                                        if (_IO_peekc(fp) == EOF) {
                    437:                                            seen_eof++;
                    438:                                            break;
                    439:                                        }
                    440:                                }
                    441:                                *p = 0;
                    442:                                nread += p - p0;
                    443:                                nassigned++;
                    444:                        }
                    445:                        continue;
                    446: 
                    447:                case CT_INT:
                    448:                        /* scan an integer as if by strtol/strtoul */
                    449:                        if (width == 0 || width > sizeof(buf) - 1)
                    450:                                width = sizeof(buf) - 1;
                    451:                        flags |= SIGNOK | NDIGITS | NZDIGITS;
                    452:                        for (p = buf; width; width--) {
                    453:                                c = (unsigned char)*fp->_IO_read_ptr;
                    454:                                /*
                    455:                                 * Switch on the character; `goto ok'
                    456:                                 * if we accept it as a part of number.
                    457:                                 */
                    458:                                switch (c) {
                    459: 
                    460:                                /*
                    461:                                 * The digit 0 is always legal, but is
                    462:                                 * special.  For %i conversions, if no
                    463:                                 * digits (zero or nonzero) have been
                    464:                                 * scanned (only signs), we will have
                    465:                                 * base==0.  In that case, we should set
                    466:                                 * it to 8 and enable 0x prefixing.
                    467:                                 * Also, if we have not scanned zero digits
                    468:                                 * before this, do not turn off prefixing
                    469:                                 * (someone else will turn it off if we
                    470:                                 * have scanned any nonzero digits).
                    471:                                 */
                    472:                                case '0':
                    473:                                        if (base == 0) {
                    474:                                                base = 8;
                    475:                                                flags |= PFXOK;
                    476:                                        }
                    477:                                        if (flags & NZDIGITS)
                    478:                                            flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
                    479:                                        else
                    480:                                            flags &= ~(SIGNOK|PFXOK|NDIGITS);
                    481:                                        goto ok;
                    482: 
                    483:                                /* 1 through 7 always legal */
                    484:                                case '1': case '2': case '3':
                    485:                                case '4': case '5': case '6': case '7':
                    486:                                        base = basefix[base];
                    487:                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
                    488:                                        goto ok;
                    489: 
                    490:                                /* digits 8 and 9 ok iff decimal or hex */
                    491:                                case '8': case '9':
                    492:                                        base = basefix[base];
                    493:                                        if (base <= 8)
                    494:                                                break;  /* not legal here */
                    495:                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
                    496:                                        goto ok;
                    497: 
                    498:                                /* letters ok iff hex */
                    499:                                case 'A': case 'B': case 'C':
                    500:                                case 'D': case 'E': case 'F':
                    501:                                case 'a': case 'b': case 'c':
                    502:                                case 'd': case 'e': case 'f':
                    503:                                        /* no need to fix base here */
                    504:                                        if (base <= 10)
                    505:                                                break;  /* not legal here */
                    506:                                        flags &= ~(SIGNOK | PFXOK | NDIGITS);
                    507:                                        goto ok;
                    508: 
                    509:                                /* sign ok only as first character */
                    510:                                case '+': case '-':
                    511:                                        if (flags & SIGNOK) {
                    512:                                                flags &= ~SIGNOK;
                    513:                                                goto ok;
                    514:                                        }
                    515:                                        break;
                    516: 
                    517:                                /* x ok iff flag still set & 2nd char */
                    518:                                case 'x': case 'X':
                    519:                                        if (flags & PFXOK && p == buf + 1) {
                    520:                                                base = 16;      /* if %i */
                    521:                                                flags &= ~PFXOK;
                    522:                                                goto ok;
                    523:                                        }
                    524:                                        break;
                    525:                                }
                    526: 
                    527:                                /*
                    528:                                 * If we got here, c is not a legal character
                    529:                                 * for a number.  Stop accumulating digits.
                    530:                                 */
                    531:                                break;
                    532:                ok:
                    533:                                /*
                    534:                                 * c is legal: store it and look at the next.
                    535:                                 */
                    536:                                *p++ = c;
                    537:                                fp->_IO_read_ptr++;
                    538:                                if (_IO_peekc(fp) == EOF) {
                    539:                                    seen_eof++;
                    540:                                    break;              /* EOF */
                    541:                                }
                    542:                        }
                    543:                        /*
                    544:                         * If we had only a sign, it is no good; push
                    545:                         * back the sign.  If the number ends in `x',
                    546:                         * it was [sign] '0' 'x', so push back the x
                    547:                         * and treat it as [sign] '0'.
                    548:                         */
                    549:                        if (flags & NDIGITS) {
                    550:                                if (p > buf)
                    551:                                        (void) _IO_ungetc(*(u_char *)--p, fp);
                    552:                                goto match_failure;
                    553:                        }
                    554:                        c = ((u_char *)p)[-1];
                    555:                        if (c == 'x' || c == 'X') {
                    556:                                --p;
                    557:                                (void) _IO_ungetc (c, fp);
                    558:                        }
                    559:                        if ((flags & SUPPRESS) == 0) {
                    560:                                u_long res;
                    561: 
                    562:                                *p = 0;
                    563:                                res = (*ccfn)(buf, (char **)NULL, base);
                    564:                                if (flags & POINTER)
                    565:                                        *va_arg(ap, void **) = (void *)res;
                    566:                                else if (flags & SHORT)
                    567:                                        *va_arg(ap, short *) = res;
                    568:                                else if (flags & LONG)
                    569:                                        *va_arg(ap, long *) = res;
                    570:                                else
                    571:                                        *va_arg(ap, int *) = res;
                    572:                                nassigned++;
                    573:                        }
                    574:                        nread += p - buf;
                    575:                        break;
                    576: 
                    577: #ifdef FLOATING_POINT
                    578:                case CT_FLOAT:
                    579:                        /* scan a floating point number as if by strtod */
                    580:                        if (width == 0 || width > sizeof(buf) - 1)
                    581:                                width = sizeof(buf) - 1;
                    582:                        flags |= SIGNOK | NDIGITS | DPTOK | EXPOK;
                    583:                        for (p = buf; width; width--) {
                    584:                                c = (unsigned char)*fp->_IO_read_ptr;
                    585:                                /*
                    586:                                 * This code mimicks the integer conversion
                    587:                                 * code, but is much simpler.
                    588:                                 */
                    589:                                switch (c) {
                    590: 
                    591:                                case '0': case '1': case '2': case '3':
                    592:                                case '4': case '5': case '6': case '7':
                    593:                                case '8': case '9':
                    594:                                        flags &= ~(SIGNOK | NDIGITS);
                    595:                                        goto fok;
                    596: 
                    597:                                case '+': case '-':
                    598:                                        if (flags & SIGNOK) {
                    599:                                                flags &= ~SIGNOK;
                    600:                                                goto fok;
                    601:                                        }
                    602:                                        break;
                    603:                                case '.':
                    604:                                        if (flags & DPTOK) {
                    605:                                                flags &= ~(SIGNOK | DPTOK);
                    606:                                                goto fok;
                    607:                                        }
                    608:                                        break;
                    609:                                case 'e': case 'E':
                    610:                                        /* no exponent without some digits */
                    611:                                        if ((flags&(NDIGITS|EXPOK)) == EXPOK) {
                    612:                                                flags =
                    613:                                                    (flags & ~(EXPOK|DPTOK)) |
                    614:                                                    SIGNOK | NDIGITS;
                    615:                                                goto fok;
                    616:                                        }
                    617:                                        break;
                    618:                                }
                    619:                                break;
                    620:                fok:
                    621:                                *p++ = c;
                    622:                                fp->_IO_read_ptr++;
                    623:                                if (_IO_peekc(fp) == EOF) {
                    624:                                    seen_eof++;
                    625:                                    break;      /* EOF */
                    626:                                }
                    627:                        }
                    628:                        /*
                    629:                         * If no digits, might be missing exponent digits
                    630:                         * (just give back the exponent) or might be missing
                    631:                         * regular digits, but had sign and/or decimal point.
                    632:                         */
                    633:                        if (flags & NDIGITS) {
                    634:                                if (flags & EXPOK) {
                    635:                                        /* no digits at all */
                    636:                                        while (p > buf)
                    637:                                            _IO_ungetc (*(u_char *)--p, fp);
                    638:                                        goto match_failure;
                    639:                                }
                    640:                                /* just a bad exponent (e and maybe sign) */
                    641:                                c = *(u_char *)--p;
                    642:                                if (c != 'e' && c != 'E') {
                    643:                                        (void) _IO_ungetc (c, fp);/* sign */
                    644:                                        c = *(u_char *)--p;
                    645:                                }
                    646:                                (void) _IO_ungetc (c, fp);
                    647:                        }
                    648:                        if ((flags & SUPPRESS) == 0) {
                    649:                                double res;
                    650:                                *p = 0;
                    651: #ifdef USE_DTOA
                    652:                                res = _IO_strtod(buf, NULL);
                    653: #else
                    654:                                res = atof(buf);
                    655: #endif
                    656:                                if (flags & LONG)
                    657:                                        *va_arg(ap, double *) = res;
                    658:                                else
                    659:                                        *va_arg(ap, float *) = res;
                    660:                                nassigned++;
                    661:                        }
                    662:                        nread += p - buf;
                    663:                        break;
                    664: #endif /* FLOATING_POINT */
                    665:                }
                    666:        }
                    667: eof_failure:
                    668:        seen_eof++;
                    669: input_failure:
                    670:        if (nassigned == 0)
                    671:            nassigned = -1;
                    672: match_failure:
                    673:        if (errp)
                    674:            *errp |= 2;
                    675: done:
                    676:        if (errp && seen_eof)
                    677:                *errp |= 1;
                    678:        return (nassigned);
                    679: }
                    680: 
                    681: /*
                    682:  * Fill in the given table from the scanset at the given format
                    683:  * (just after `[').  Return a pointer to the character past the
                    684:  * closing `]'.  The table has a 1 wherever characters should be
                    685:  * considered part of the scanset.
                    686:  */
                    687: static const u_char *__sccl(tab, fmt)
                    688:      register char *tab;
                    689:      register const u_char *fmt;
                    690: {
                    691:        register int c, n, v;
                    692: 
                    693:        /* first `clear' the whole table */
                    694:        c = *fmt++;             /* first char hat => negated scanset */
                    695:        if (c == '^') {
                    696:                v = 1;          /* default => accept */
                    697:                c = *fmt++;     /* get new first char */
                    698:        } else
                    699:                v = 0;          /* default => reject */
                    700:        /* should probably use memset here */
                    701:        for (n = 0; n < 256; n++)
                    702:                tab[n] = v;
                    703:        if (c == 0)
                    704:                return (fmt - 1);/* format ended before closing ] */
                    705: 
                    706:        /*
                    707:         * Now set the entries corresponding to the actual scanset
                    708:         * to the opposite of the above.
                    709:         *
                    710:         * The first character may be ']' (or '-') without being special;
                    711:         * the last character may be '-'.
                    712:         */
                    713:        v = 1 - v;
                    714:        for (;;) {
                    715:                tab[c] = v;             /* take character c */
                    716: doswitch:
                    717:                n = *fmt++;             /* and examine the next */
                    718:                switch (n) {
                    719: 
                    720:                case 0:                 /* format ended too soon */
                    721:                        return (fmt - 1);
                    722: 
                    723:                case '-':
                    724:                        /*
                    725:                         * A scanset of the form
                    726:                         *      [01+-]
                    727:                         * is defined as `the digit 0, the digit 1,
                    728:                         * the character +, the character -', but
                    729:                         * the effect of a scanset such as
                    730:                         *      [a-zA-Z0-9]
                    731:                         * is implementation defined.  The V7 Unix
                    732:                         * scanf treats `a-z' as `the letters a through
                    733:                         * z', but treats `a-a' as `the letter a, the
                    734:                         * character -, and the letter a'.
                    735:                         *
                    736:                         * For compatibility, the `-' is not considerd
                    737:                         * to define a range if the character following
                    738:                         * it is either a close bracket (required by ANSI)
                    739:                         * or is not numerically greater than the character
                    740:                         * we just stored in the table (c).
                    741:                         */
                    742:                        n = *fmt;
                    743:                        if (n == ']' || n < c) {
                    744:                                c = '-';
                    745:                                break;  /* resume the for(;;) */
                    746:                        }
                    747:                        fmt++;
                    748:                        do {            /* fill in the range */
                    749:                                tab[++c] = v;
                    750:                        } while (c < n);
                    751: #if 1  /* XXX another disgusting compatibility hack */
                    752:                        /*
                    753:                         * Alas, the V7 Unix scanf also treats formats
                    754:                         * such as [a-c-e] as `the letters a through e'.
                    755:                         * This too is permitted by the standard....
                    756:                         */
                    757:                        goto doswitch;
                    758: #else
                    759:                        c = *fmt++;
                    760:                        if (c == 0)
                    761:                                return (fmt - 1);
                    762:                        if (c == ']')
                    763:                                return (fmt);
                    764: #endif
                    765:                        break;
                    766: 
                    767:                case ']':               /* end of scanset */
                    768:                        return (fmt);
                    769: 
                    770:                default:                /* just another character */
                    771:                        c = n;
                    772:                        break;
                    773:                }
                    774:        }
                    775:        /* NOTREACHED */
                    776: }

unix.superglobalmegacorp.com

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