Annotation of coherent/b/STREAMS/conf_79/read.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *-IMPORTS:
                      3:  *     <sys/compat.h>
                      4:  *             USE_PROTO
                      5:  *             LOCAL
                      6:  *             ARGS ()
                      7:  *     <limits.h>
                      8:  *             LONG_MAX
                      9:  *             LONG_MIN
                     10:  *             ULONG_MAX
                     11:  *     <string.h>
                     12:  *             memchr ()
                     13:  *     "buildobj.h"
                     14:  *             BUILD_OK
                     15:  *             build_t
                     16:  *             builder_alloc ()
                     17:  *             build_addchar ()
                     18:  *             build_begin ()
                     19:  *             build_end ()
                     20:  *             build_error ()
                     21:  *             build_release ()
                     22:  *     "ehand.h"
                     23:  *             ehand_t
                     24:  *             CHAIN_ERROR ()
                     25:  *             POP_HANDLER ()
                     26:  *             PUSH_HANDLER ()
                     27:  *             throw_error ()
                     28:  *     "input.h"
                     29:  *             IN_EOF
                     30:  *             input_t
                     31:  *     "lex.h"
                     32:  *             CLASS_FLUSH
                     33:  *             CLASS_SEP
                     34:  *             lex_t
                     35:  *             classify ()
                     36:  */
                     37: 
                     38: #include <sys/compat.h>
                     39: #include <limits.h>
                     40: #include <string.h>
                     41: 
                     42: #include "buildobj.h"
                     43: #include "ehand.h"
                     44: #include "input.h"
                     45: #include "lex.h"
                     46: 
                     47: #include "read.h"
                     48: 
                     49: 
                     50: /*
                     51:  * Simple glue functions to encapsulate the input system.
                     52:  */
                     53: 
                     54: #ifdef USE_PROTO
                     55: int (read_char) (input_t * input)
                     56: #else
                     57: int
                     58: read_char ARGS ((input))
                     59: input_t              * input;
                     60: #endif
                     61: {
                     62:        if (input == NULL)
                     63:                throw_error ("NULL parameter passed to read_char ()");
                     64: 
                     65:        return (* input->in_read) (input);
                     66: }
                     67: 
                     68: 
                     69: #ifdef USE_PROTO
                     70: void (unread_char) (input_t * input)
                     71: #else
                     72: void
                     73: unread_char ARGS ((input))
                     74: input_t              * input;
                     75: #endif
                     76: {
                     77:        if (input == NULL)
                     78:                throw_error ("NULL parameter passed to unread_char ()");
                     79: 
                     80:        (* input->in_unread) (input);
                     81: }
                     82: 
                     83: 
                     84: #ifdef USE_PROTO
                     85: void (read_error) (input_t * input)
                     86: #else
                     87: void
                     88: read_error ARGS ((input))
                     89: input_t              * input;
                     90: #endif
                     91: {
                     92:        if (input == NULL)
                     93:                throw_error ("NULL parameter passed to read_error ()");
                     94: 
                     95:        (* input->in_error) (input);
                     96: }
                     97: 
                     98: 
                     99: #ifdef USE_PROTO
                    100: void (read_close) (input_t * input)
                    101: #else
                    102: void
                    103: read_close ARGS ((input))
                    104: input_t              * input;
                    105: #endif
                    106: {
                    107:        if (input == NULL)
                    108:                throw_error ("NULL parameter passed to read_close ()");
                    109: 
                    110:        (* input->in_close) (input);
                    111: }
                    112: 
                    113: 
                    114: /*
                    115:  * Simple helper to ensure that we don't bump into EOF or EOL too early.
                    116:  */
                    117: 
                    118: #ifdef USE_PROTO
                    119: void (check_not_eol) (int ch)
                    120: #else
                    121: void
                    122: check_not_eol ARGS ((ch))
                    123: int            ch;
                    124: #endif
                    125: {
                    126:        if (ch == '\n')
                    127:                throw_error ("premature end of line");
                    128: 
                    129:        if (ch == READ_EOF)
                    130:                throw_error ("premature end of file");
                    131: }
                    132: 
                    133: 
                    134: /*
                    135:  * We use this function to eat anything that the lexical specification
                    136:  * considers flushable until we see an end-of-line or end-of-file.
                    137:  */
                    138: 
                    139: #ifdef USE_PROTO
                    140: int (expect_eol) (input_t * input, lex_t * lexp, int ch)
                    141: #else
                    142: int
                    143: expect_eol ARGS ((input, lexp, ch))
                    144: input_t              * input;
                    145: lex_t        * lexp;
                    146: int            ch;
                    147: #endif
                    148: {
                    149:        if (ch != '\n' && ch != READ_EOF)
                    150:                while ((ch = (* input->in_read) (input)) != '\n') {
                    151: 
                    152:                        if (ch == IN_EOF)
                    153:                                return READ_EOF;
                    154: 
                    155:                        if (classify (lexp, ch, 1) != CLASS_FLUSH)
                    156:                                break;
                    157:                }
                    158: 
                    159:        return ch;
                    160: }
                    161: 
                    162: 
                    163: /*
                    164:  * Read a token from a file; this function may use the subclassed version to
                    165:  * support more efficient tokenization if possible.
                    166:  *
                    167:  * Note that we don't null-terminate the data or do any other funky stuff. If
                    168:  * our caller wants to to that, well that's fine, and we don't finish the
                    169:  * object so that the caller can extend it. Note that by returning the token
                    170:  * length that we built, this function can be used to incrementally extend
                    171:  * variable-length data and allow the positions of the subparts to be properly
                    172:  * recovered.
                    173:  */
                    174: 
                    175: #ifdef USE_PROTO
                    176: int (read_token) (input_t * input, lex_t * lexp, build_t * heap,
                    177:                  token_t * tokenp)
                    178: #else
                    179: int
                    180: read_token ARGS ((input, lexp, heap, tokenp))
                    181: input_t              * input;
                    182: lex_t        * lexp;
                    183: build_t              * heap;
                    184: token_t              * tokenp;
                    185: #endif
                    186: {
                    187:        int             ch;
                    188:        int             err;
                    189: 
                    190:        if (input == NULL || lexp == NULL || heap == NULL || tokenp == NULL)
                    191:                throw_error ("invalid parameters in read_token ()");
                    192: 
                    193:        if (input->in_readtok != NULL) {
                    194:                /*
                    195:                 * Use the subclassed version.
                    196:                 */
                    197: 
                    198:                tokenp->tok_heap = NULL;
                    199: 
                    200:                tokenp->tok_data = (* input->in_readtok) (input, lexp,
                    201:                                                          & tokenp->tok_len);
                    202: 
                    203:                return (* input->in_read) (input);
                    204:        }
                    205: 
                    206: 
                    207:        tokenp->tok_heap = heap;
                    208:        tokenp->tok_data = NULL;
                    209:        tokenp->tok_len = 0;
                    210: 
                    211:        for (;;) {
                    212:                if ((ch = (* input->in_read) (input)) == IN_EOF)
                    213:                        return ch;
                    214: 
                    215:                switch (classify (lexp, ch, tokenp->tok_len == 0)) {
                    216: 
                    217:                case CLASS_FLUSH:
                    218:                        continue;
                    219: 
                    220:                case CLASS_SEP:
                    221:                        return ch;
                    222: 
                    223:                default:
                    224:                        break;
                    225:                }
                    226: 
                    227: 
                    228:                /*
                    229:                 * We have read a valid non-separator character, add it to the
                    230:                 * current input symbol.
                    231:                 */
                    232: 
                    233:                tokenp->tok_len ++;
                    234: 
                    235:                if ((err = build_addchar (heap, ch)) != BUILD_OK)
                    236:                        throw_error ("build_addchar () reported %d (%s)", err,
                    237:                                     build_error (err));
                    238:        }
                    239: }
                    240: 
                    241: 
                    242: /*
                    243:  * Handy function for clients of read_token () to finish up any build-heap
                    244:  * allocation in the usual case where read_token () is simply expected to copy
                    245:  * data to the heap.
                    246:  *
                    247:  * If it was adding data to the heap, add a NULL terminator for the usual case
                    248:  * where we would also like the object to be useable as a string.
                    249:  */
                    250: 
                    251: #ifdef USE_PROTO
                    252: void (token_end) (token_t * tok)
                    253: #else
                    254: void
                    255: token_end ARGS ((tok))
                    256: token_t              * tok;
                    257: #endif
                    258: {
                    259:        char            null;
                    260: 
                    261:        if (tok->tok_heap == NULL)
                    262:                return;
                    263: 
                    264:        null = 0;
                    265: 
                    266:        if (tok->tok_len != 0 ?
                    267:                        (build_add (tok->tok_heap, 1, & null) != 0) ||
                    268:                         (tok->tok_data =
                    269:                                build_end (tok->tok_heap, NULL)) == NULL :
                    270:                        build_end (tok->tok_heap, NULL) != NULL)
                    271:                throw_error ("Error ending token construction");
                    272: }
                    273: 
                    274: 
                    275: /*
                    276:  * In the case where a token was able to be scanned in-place, it is often
                    277:  * necessary to copy it to a heap, even if only temporarily. As with the above
                    278:  * token_end, we terminate the token as if it was a string.
                    279:  *
                    280:  * If the token is actually in a different heap from the one given, we move it
                    281:  * to the new heap. This works in with some special behaviour in the build
                    282:  * system where object building can be temporarily suspended, allowing some
                    283:  * kinds of recursive operations to work on borrowed heap space.
                    284:  */
                    285: 
                    286: #ifdef USE_PROTO
                    287: void (token_copy) (token_t * tok, build_t * heap)
                    288: #else
                    289: void
                    290: token_copy ARGS ((tok, heap))
                    291: token_t              * tok;
                    292: build_t              * heap;
                    293: #endif
                    294: {
                    295:        char            null;
                    296:        unsigned char * data;
                    297:        int             err;
                    298: 
                    299:        if (tok->tok_heap == heap)
                    300:                return;
                    301: 
                    302:        null = 0;
                    303: 
                    304:        if ((err = build_begin (heap, tok->tok_len, tok->tok_data)) != 0 ||
                    305:            (err = build_add (heap, 1, & null)) != 0 ||
                    306:            (err = BUILD_NO_OBJECT,
                    307:             (data = build_end (heap, NULL)) == NULL))
                    308:                throw_error ("Cannot copy token data to heap, error %s",
                    309:                             build_error (err));
                    310: 
                    311:        if (tok->tok_heap != NULL &&
                    312:            (err = build_release (heap, tok->tok_data)) != 0)
                    313:                throw_error ("Cannot release data from old heap, error %s",
                    314:                             build_error (err));
                    315: 
                    316:        tok->tok_data = data;
                    317:        tok->tok_heap = heap;
                    318: }
                    319: 
                    320: 
                    321: /*
                    322:  * If a read token has been found to be not needed, it may be discarded with
                    323:  * this function. If it was copied to a heap, then the heap memory is
                    324:  * released.
                    325:  */
                    326: 
                    327: #ifdef USE_PROTO
                    328: void (token_discard) (token_t * tok)
                    329: #else
                    330: void
                    331: token_discard ARGS ((tok))
                    332: token_t              * tok;
                    333: #endif
                    334: {
                    335:        int             err;
                    336: 
                    337:        if (tok->tok_heap != NULL &&
                    338:            (err = build_release (tok->tok_heap, tok->tok_data)) != 0)
                    339:                throw_error ("Cannot release token data, error %s",
                    340:                             build_error (err));
                    341: }
                    342: 
                    343: 
                    344: /*
                    345:  * Simply discard flushable input until the next non-flushable input
                    346:  * character.
                    347:  */
                    348: 
                    349: #ifdef USE_PROTO
                    350: void (read_flush) (input_t * input, lex_t * lexp)
                    351: #else
                    352: void
                    353: read_flush ARGS ((input, lexp))
                    354: input_t              * input;
                    355: lex_t        * lexp;
                    356: #endif
                    357: {
                    358:        int             ch;
                    359: 
                    360:        while ((ch = (* input->in_read) (input)) != IN_EOF) {
                    361: 
                    362:                if (classify (lexp, ch, 1) != CLASS_FLUSH) {
                    363: 
                    364:                        (* input->in_unread) (input);
                    365:                        break;
                    366:                }
                    367:        }
                    368: }
                    369: 
                    370: 
                    371: /*
                    372:  * To help with the numeric conversions, here we define a simple conversion
                    373:  * utility that converts a character to a digit independent of character set
                    374:  * and digit case.
                    375:  *
                    376:  * ... a truly general way of doing this would be nice ... maybe some kind of
                    377:  * virtual-machine interpreter would be up to it ... hmmm.
                    378:  */
                    379: 
                    380: enum {
                    381:        NOT_DIGIT = -1
                    382: };
                    383: 
                    384: #ifdef USE_PROTO
                    385: LOCAL int (char_to_digit) (int ch, int radix)
                    386: #else
                    387: LOCAL int
                    388: char_to_digit ARGS ((ch, radix))
                    389: int            ch;
                    390: int            radix;
                    391: #endif
                    392: {
                    393:        static CONST char digits [] = {
                    394:                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                    395:                'A', 'B', 'C', 'D', 'E', 'F',
                    396:                'a', 'b', 'c', 'd', 'e', 'f'
                    397:        };
                    398:        static CONST char values [sizeof (digits)] = {
                    399:                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
                    400:                10, 11, 12, 13, 14, 15,
                    401:                10, 11, 12, 13, 14, 15
                    402:        };
                    403:        CONST char    * temp;
                    404: 
                    405: 
                    406:        if ((temp = (CONST char *) memchr (digits, ch,
                    407:                                           sizeof (digits))) == NULL ||
                    408:            (ch = values [temp - digits]) >= radix)
                    409:                return -1;
                    410: 
                    411:        return ch;
                    412: }
                    413: 
                    414: 
                    415: /*
                    416:  * Both read_ulong () and read_long () need to be able to select a radix for
                    417:  * the number in question based on an explicit radix prefix. This code does
                    418:  * that for both functions; under certain circumstances, the numeric input
                    419:  * might be completed by this code.
                    420:  */
                    421: 
                    422: #ifdef USE_PROTO
                    423: LOCAL int (choose_radix) (input_t * input, unsigned long * ulongp,
                    424:                          int * radixp)
                    425: #else
                    426: LOCAL int
                    427: choose_radix ARGS ((input, ulongp, radixp))
                    428: input_t              * input;
                    429: unsigned long *        ulongp;
                    430: int          * radixp;
                    431: #endif
                    432: {
                    433:        int             ch;
                    434:        int             errflag;
                    435: 
                    436:        * ulongp = 0;
                    437: 
                    438:        /*
                    439:         * Perform a radix-selection step, looking for 0, 1-9, 0X, or 0x as
                    440:         * indications of what radix to read the rest of the number in.
                    441:         */
                    442: 
                    443:        switch (ch = (* input->in_read) (input)) {
                    444: 
                    445:        case IN_EOF:
                    446:                return 0;
                    447: 
                    448:        case '0':       /* octal or hexadecimal */
                    449:                switch (ch = (* input->in_read) (input)) {
                    450: 
                    451:                case IN_EOF:
                    452:                        return 1;
                    453: 
                    454:                case 'x':
                    455:                case 'X':
                    456:                        /*
                    457:                         * For the case of radix-16 numbers with an explicit
                    458:                         * radix in the text, we have a special error case,
                    459:                         * consisting of an 0x or 0X followed by something
                    460:                         * that is not a valid digit.
                    461:                         *
                    462:                         * The easiest way to test for this is to try
                    463:                         * converting the first digit right here.
                    464:                         */
                    465: 
                    466:                        * radixp = 16;
                    467:                        errflag = -1;
                    468: 
                    469:                        if ((ch = (* input->in_read) (input))
                    470:                                                    == IN_EOF)
                    471:                                return -1;
                    472:                        break;
                    473: 
                    474:                default:
                    475:                        * radixp = 8;
                    476:                        errflag = 1;
                    477:                        break;
                    478:                }
                    479:                break;
                    480: 
                    481:        default:
                    482:                * radixp = 10;
                    483:                errflag = 0;
                    484:                break;
                    485:        }
                    486: 
                    487: 
                    488:        /*
                    489:         * The need for the extra error check required by hexadecimal numbers
                    490:         * could have made life difficult for the caller in terms of working
                    491:         * out whether this function actually began reading a number or not.
                    492:         *
                    493:         * To simplify this, we ensure that this function always consumes at
                    494:         * least the first digit. Of course, the actual response to the next
                    495:         * character not being a valid digit is different in each case, so we
                    496:         * also deal with that.
                    497:         */
                    498: 
                    499:        if ((ch = char_to_digit (ch, * radixp)) == -1) {
                    500: 
                    501:                (* input->in_unread) (input);
                    502:                return errflag;
                    503:        }
                    504: 
                    505:        * ulongp = ch;
                    506:        return 0;
                    507: }
                    508: 
                    509: 
                    510: /*
                    511:  * Read an unsigned long number from the input. No initial whitespace is
                    512:  * skipped, no sign character is permitted, and the first value that is not
                    513:  * valid for a number of the given radix ends conversion.
                    514:  *
                    515:  * If "radix" is 0, the usual C radix specifiers are recognized. This version
                    516:  * of the code has a maximum "radix" value of 16.
                    517:  *
                    518:  * A return value of 0 indicates no number was seen, a return value of -1
                    519:  * indicates an invalid number was seen (such as 0xZ, or a number that is too
                    520:  * large to be represented accurately with an unsigned long), and a return
                    521:  * value of 1 indicates a number was successfully read.
                    522:  */
                    523: 
                    524: #ifdef USE_PROTO
                    525: int (read_ulong) (input_t * input, unsigned long * ulongp, int radix)
                    526: #else
                    527: int
                    528: read_ulong ARGS ((input, ulongp, radix))
                    529: input_t              * input;
                    530: unsigned long *        ulongp;
                    531: int            radix;
                    532: #endif
                    533: {
                    534:        char            ch;
                    535:        unsigned long   temp;
                    536:        unsigned long   radix_max;
                    537:        int             read_something;
                    538: 
                    539:        if (input == NULL || ulongp == NULL || radix < 0 || radix > 16)
                    540:                throw_error ("Invalid parameter passed to read_ulong ()");
                    541: 
                    542:        * ulongp = 0;
                    543: 
                    544:        if (radix == 0) {
                    545: 
                    546:                switch (ch = choose_radix (input, ulongp, & radix)) {
                    547: 
                    548:                case 0:
                    549:                        break;
                    550: 
                    551:                default:
                    552:                        return ch;
                    553:                }
                    554: 
                    555:                read_something = 1;
                    556:        } else
                    557:                read_something = 0;
                    558: 
                    559:        /*
                    560:         * In order to detect overflow portably, we figure out the smallest
                    561:         * value that will cause overflow when multiplied by the radix, and
                    562:         * test against that before the multiplication. If the addition of the
                    563:         * value of "ch" causes overflow, that can be detected by a value of
                    564:         * "temp" that is smaller after the addition, according to the rules
                    565:         * of ANSI/ISO unsigned arithmetic. Note that unsigned overflow is
                    566:         * required to be non-signalling in an ANSI/ISO environment.
                    567:         */
                    568: 
                    569:        temp = * ulongp;
                    570:        radix_max = ULONG_MAX / radix;
                    571: 
                    572:        for (;;) {
                    573: 
                    574:                if ((ch = (* input->in_read) (input)) == IN_EOF)
                    575:                        break;
                    576: 
                    577:                if ((ch = char_to_digit (ch, radix)) == -1) {
                    578: 
                    579:                        (* input->in_unread) (input);
                    580:                        break;
                    581:                }
                    582: 
                    583:                if (temp > radix_max) {
                    584:                        /*
                    585:                         * Will overflow during the multiplication.
                    586:                         */
                    587: 
                    588:                        read_something = -1;
                    589:                        temp = ULONG_MAX;
                    590: 
                    591:                        continue;
                    592:                }
                    593: 
                    594:                read_something = 1;
                    595:                temp = (temp * radix) + ch;
                    596: 
                    597:                if (temp < ch) {
                    598:                        /*
                    599:                         * Overflowed during the addition.
                    600:                         */
                    601: 
                    602:                        read_something = -1;
                    603:                        temp = ULONG_MAX;
                    604: 
                    605:                        continue;
                    606:                }
                    607:        }
                    608: 
                    609:        * ulongp = temp;
                    610: 
                    611:        return read_something;
                    612: }
                    613: 
                    614: 
                    615: /*
                    616:  * Read a signed long number from the input. No initial whitespace is skipped,
                    617:  * and the sign character must immediately precede the digits of the number
                    618:  * (or the redix specifier), and the first value that is not valid for a
                    619:  * number of the given radix ends conversion.
                    620:  *
                    621:  * If "radix" is 0, the usual C radix specifiers are recognized. This version
                    622:  * of the code has a maximum "radix" value of 16.
                    623:  *
                    624:  * A return value of 0 indicates no number was seen, a return value of -1
                    625:  * indicates an invalid number was seen (such as 0xZ, or a number that is too
                    626:  * large to be represented accurately with a signed long), and a return value
                    627:  * of 1 indicates a number was successfully read.
                    628:  */
                    629: 
                    630: #ifdef USE_PROTO
                    631: int (read_long) (input_t * input, long * longp, int radix)
                    632: #else
                    633: int
                    634: read_long ARGS ((input, longp, radix))
                    635: input_t              * input;
                    636: long         * longp;
                    637: int            radix;
                    638: #endif
                    639: {
                    640:        int             ch;
                    641:        unsigned long   temp;
                    642:        int             sign;
                    643: 
                    644:        /*
                    645:         * To save time and effort, we simply test for an initial sign flag,
                    646:         * use read_ulong () to convert a number, and then range check the
                    647:         * result before converting it to signed form.
                    648:         */
                    649: 
                    650:        switch (ch = (* input->in_read) (input)) {
                    651: 
                    652:        case IN_EOF:
                    653:                return 1;
                    654: 
                    655:        case '-':
                    656:                sign = -1;
                    657:                break;
                    658: 
                    659:        case '+':
                    660:                sign = 1;
                    661:                break;
                    662: 
                    663:        default:
                    664:                /*
                    665:                 * There is no sign character that we can see, return the
                    666:                 * lookahead character to the input source so that it will be
                    667:                 * checked by read_ulong ().
                    668:                 */
                    669: 
                    670:                sign = 0;
                    671:                (* input->in_unread) (input);
                    672:        }
                    673: 
                    674:        ch = read_ulong (input, & temp, radix);
                    675: 
                    676: 
                    677:        /*
                    678:         * Before we range-check the result that we are going to return, it
                    679:         * pays to note that the range of signed numbers may well not be
                    680:         * symmetric. Typically, there are more negative numbers than non-zero
                    681:         * positive numbers, so that "- LONG_MIN" is not a legal long integer.
                    682:         *
                    683:         * Producing a value of LONG_MIN without getting into implementation-
                    684:         * defined (or undefined, in K&R) territory is tricky because of the
                    685:         * integral promotions. We'll work around it by subtracting from -1
                    686:         * rather than zero.
                    687:         *
                    688:         * We'd better test that the range of negative integers is at most one
                    689:         * greater than the range of non-zero positive integers. We can't do
                    690:         * the test if the preprocessor does arithmetic wrong, though, and
                    691:         * many do.
                    692:         */
                    693: 
                    694: #if    -23UL > 0
                    695: # if   (- (LONG_MIN + 0UL)) - 1 > LONG_MAX
                    696: #  error       There are too many negative integers!
                    697: # endif
                    698: #else
                    699:        /* Your preprocessor does arithmetic wrong */
                    700: #endif
                    701: 
                    702: 
                    703:        if (sign < 0 && temp != 0) {
                    704: 
                    705:                temp -= 1;
                    706: 
                    707:                if (temp > - (unsigned long) LONG_MIN - 1) {
                    708: 
                    709:                        * longp = LONG_MIN;
                    710:                        return -1;
                    711:                } else
                    712:                        * longp = -1 - (long) temp;
                    713: 
                    714:        } else if (temp > LONG_MAX) {
                    715: 
                    716:                * longp = LONG_MAX;
                    717:                return -1;
                    718:        } else
                    719:                * longp = temp;
                    720: 
                    721: 
                    722:        /*
                    723:         * If we saw a sign (of either kind) and nothing else, that's an
                    724:         * error.
                    725:         */
                    726: 
                    727:        return (sign != 0 && ch == 0) ? -1 : ch;
                    728: }
                    729: 
                    730: 
                    731: /*
                    732:  * Read a single unsigned long or a numeric range (indicated by a pair of
                    733:  * unsigned longs separated by a hyphen without any intervening whitespace).
                    734:  */
                    735: 
                    736: #ifdef USE_PROTO
                    737: int (read_ulongs) (input_t * input, lex_t * lexp, unsigned long * number,
                    738:                   int rangeflag)
                    739: #else
                    740: int
                    741: read_ulongs ARGS ((input, lexp, number, rangeflag))
                    742: input_t              * input;
                    743: lex_t        * lexp;
                    744: unsigned long *        number;
                    745: int            rangeflag;
                    746: #endif
                    747: {
                    748:        if ((rangeflag != RANGE && rangeflag != NO_RANGE) ||
                    749:            input == NULL || lexp == NULL || number == NULL)
                    750:                throw_error ("Invalid parameter to read_ulongs ()");
                    751: 
                    752:        /*
                    753:         * We permit initial whitespace according to the current lexical
                    754:         * idea of what whitespace is.
                    755:         */
                    756: 
                    757:        read_flush (input, lexp);
                    758: 
                    759:        if (read_ulong (input, number, 0) != 1)
                    760:                throw_error ("Illegal unsigned long number");
                    761: 
                    762:        if (rangeflag == RANGE) {
                    763:                int             ch;
                    764: 
                    765:                if ((ch = (* input->in_read) (input)) != IN_EOF &&
                    766:                    ((* input->in_unread) (input),      /* for effect */
                    767:                     ch == '-')) {
                    768:                        /*
                    769:                         * Read the second part of the range.
                    770:                         */
                    771: 
                    772:                        if (read_ulong (input, number + 1, 0) != 1)
                    773:                                throw_error ("Illegal second half of unsigned long range");
                    774:                } else
                    775:                        number [1] = number [0];
                    776:        }
                    777: 
                    778:        return (* input->in_read) (input);
                    779: }
                    780: 
                    781: 
                    782: /*
                    783:  * Read a single integer or a numeric range (indicated by a pair of integers
                    784:  * separated by a hyphen without any intervening whitespace).
                    785:  */
                    786: 
                    787: #ifdef USE_PROTO
                    788: int (read_ints) (input_t * input, lex_t * lexp, int * number, int rangeflag)
                    789: #else
                    790: int
                    791: read_ints ARGS ((input, lexp, number, rangeflag))
                    792: input_t              * input;
                    793: lex_t        * lexp;
                    794: int          * number;
                    795: int            rangeflag;
                    796: #endif
                    797: {
                    798:        long            value;
                    799: 
                    800:        if ((rangeflag != RANGE && rangeflag != NO_RANGE) ||
                    801:            input == NULL || lexp == NULL || number == NULL)
                    802:                throw_error ("Invalid parameter to read_ints ()");
                    803: 
                    804:        /*
                    805:         * We permit initial whitespace according to the current lexical
                    806:         * idea of what whitespace is.
                    807:         */
                    808: 
                    809:        read_flush (input, lexp);
                    810: 
                    811:        if (read_long (input, & value, 0) != 1 ||
                    812: #ifdef __COHERENT__
                    813:                0)      /* Coherent compiles the test below to bad code */
                    814: #else
                    815:            value > INT_MAX || value < INT_MIN)
                    816: #endif
                    817:                throw_error ("Illegal integer number");
                    818: 
                    819:        number [0] = (int) value;
                    820: 
                    821:        if (rangeflag == RANGE) {
                    822:                int             ch;
                    823: 
                    824:                if ((ch = (* input->in_read) (input)) != IN_EOF &&
                    825:                    ((* input->in_unread) (input),      /* for effect */
                    826:                     ch == '-')) {
                    827:                        /*
                    828:                         * Read the second part of the range.
                    829:                         */
                    830: 
                    831:                        if (read_long (input, & value, 0) != 1 ||
                    832: #ifdef __COHERENT__
                    833:                                0)      /* Coherent compiles to bad code */
                    834: #else
                    835:                            value > INT_MAX || value < INT_MIN)
                    836: #endif
                    837:                                throw_error ("Illegal second half of integer range");
                    838:                }
                    839: 
                    840:                number [1] = (int) value;
                    841:        }
                    842: 
                    843:        return (* input->in_read) (input);
                    844: }
                    845: 
                    846: 
                    847: /*
                    848:  * Read a single integer or a numeric range (indicated by a pair of integers
                    849:  * separated by a hyphen without any intervening whitespace).
                    850:  */
                    851: 
                    852: #ifdef USE_PROTO
                    853: int (read_longs) (input_t * input, lex_t * lexp, long * number, int rangeflag)
                    854: #else
                    855: int
                    856: read_longs ARGS ((input, lexp, number, rangeflag))
                    857: input_t              * input;
                    858: lex_t        * lexp;
                    859: long         * number;
                    860: int            rangeflag;
                    861: #endif
                    862: {
                    863:        if ((rangeflag != RANGE && rangeflag != NO_RANGE) ||
                    864:            input == NULL || lexp == NULL || number == NULL)
                    865:                throw_error ("Invalid parameter to read_longs ()");
                    866: 
                    867:        /*
                    868:         * We permit initial whitespace according to the current lexical
                    869:         * idea of what whitespace is.
                    870:         */
                    871: 
                    872:        read_flush (input, lexp);
                    873: 
                    874:        if (read_long (input, number, 0) != 1)
                    875:                throw_error ("Illegal long-integer number");
                    876: 
                    877:        if (rangeflag == RANGE) {
                    878:                int             ch;
                    879: 
                    880:                if ((ch = (* input->in_read) (input)) != IN_EOF &&
                    881:                    ((* input->in_unread) (input),      /* for effect */
                    882:                     ch == '-')) {
                    883:                        /*
                    884:                         * Read the second part of the range.
                    885:                         */
                    886: 
                    887:                        if (read_long (input, number + 1, 0) != 1)
                    888:                                throw_error ("Illegal second half of long-integer range");
                    889:                }
                    890:        }
                    891: 
                    892:        return (* input->in_read) (input);
                    893: }
                    894: 
                    895: 
                    896: /*
                    897:  * Read a single unsigned integer or a numeric range (indicated by a pair of
                    898:  * unsigned integers separated by a hyphen without any intervening
                    899:  * whitespace).
                    900:  */
                    901: 
                    902: #ifdef USE_PROTO
                    903: int (read_uints) (input_t * input, lex_t * lexp, unsigned int * number,
                    904:                  int rangeflag)
                    905: #else
                    906: int
                    907: read_uints ARGS ((input, lexp, number, rangeflag))
                    908: input_t              * input;
                    909: lex_t        * lexp;
                    910: unsigned int  *        number;
                    911: int            rangeflag;
                    912: #endif
                    913: {
                    914:        unsigned long   value;
                    915: 
                    916:        if ((rangeflag != RANGE && rangeflag != NO_RANGE) ||
                    917:            input == NULL || lexp == NULL || number == NULL)
                    918:                throw_error ("Invalid parameter to read_ints ()");
                    919: 
                    920:        /*
                    921:         * We permit initial whitespace according to the current lexical
                    922:         * idea of what whitespace is.
                    923:         */
                    924: 
                    925:        read_flush (input, lexp);
                    926: 
                    927:        if (read_ulong (input, & value, 0) != 1 || value > UINT_MAX)
                    928:                throw_error ("Illegal unsigned integer number");
                    929: 
                    930:        number [0] = (unsigned int) value;
                    931: 
                    932:        if (rangeflag == RANGE) {
                    933:                int             ch;
                    934: 
                    935:                if ((ch = (* input->in_read) (input)) != IN_EOF &&
                    936:                    ((* input->in_unread) (input),      /* for effect */
                    937:                     ch == '-')) {
                    938:                        /*
                    939:                         * Read the second part of the range.
                    940:                         */
                    941: 
                    942:                        if (read_ulong (input, & value, 0) != 1 ||
                    943:                            value > UINT_MAX)
                    944:                                throw_error ("Illegal second half of unsigned integer range");
                    945:                }
                    946: 
                    947:                number [1] = (unsigned int) value;
                    948:        }
                    949: 
                    950:        return (* input->in_read) (input);
                    951: }

unix.superglobalmegacorp.com

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