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

unix.superglobalmegacorp.com

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