Annotation of coherent/b/STREAMS/conf_79/read.c, revision 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.