Annotation of coherent/b/bin/c/n0/lex.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * This file contains all of the lexical analysis routines
                      3:  * for the portable C compiler.
                      4:  */
                      5: #ifdef   vax
                      6: #include "INC$LIB:cc0.h"
                      7: #else
                      8: #include "cc0.h"
                      9: #endif
                     10: 
                     11: /*
                     12:  * Character classes.
                     13:  * Indexed by ASCII character code.
                     14:  */
                     15: unsigned char ct[] = {
                     16:        JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,
                     17:        JUNK,   SKIP,   SKIP,   SKIP,   SKIP,   SKIP,   JUNK,   JUNK,
                     18:        JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,
                     19:        JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,   JUNK,
                     20:        SKIP,   NOT,    STRING, SHARP,  JUNK,   REM,    AND,    QUOTE,
                     21:        LPAREN, RPAREN, MUL,    ADD,    COMMA,  SUB,    DOT,    DIV,
                     22:        CON,    CON,    CON,    CON,    CON,    CON,    CON,    CON,
                     23:        CON,    CON,    COLON,  SEMI,   LT,     ASSIGN, GT,     QUEST,
                     24:        JUNK,   ID,     ID,     ID,     ID,     ID,     ID,     ID,
                     25:        ID,     ID,     ID,     ID,     ID,     ID,     ID,     ID,
                     26:        ID,     ID,     ID,     ID,     ID,     ID,     ID,     ID,
                     27:        ID,     ID,     ID,     LBRACK, BACKDIV,RBRACK, XOR,    ID,
                     28:        JUNK,   ID,     ID,     ID,     ID,     ID,     ID,     ID,
                     29:        ID,     ID,     ID,     ID,     ID,     ID,     ID,     ID,
                     30:        ID,     ID,     ID,     ID,     ID,     ID,     ID,     ID,
                     31:        ID,     ID,     ID,     LBRACE, OR,     RBRACE, COM,    JUNK,
                     32:        HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,
                     33:        HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,
                     34:        HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,
                     35:        HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,  HIGH0,
                     36:        HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,
                     37:        HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,
                     38:        HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,
                     39:        HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,  HIGH1,
                     40:        HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,
                     41:        HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,
                     42:        HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,
                     43:        HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,  HIGH2,
                     44:        HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,
                     45:        HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,
                     46:        HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,
                     47:        HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3,  HIGH3
                     48: };
                     49: 
                     50: /*
                     51:  * Read and decode the next token of the input.
                     52:  * The token is returned and stored in 's'.
                     53:  * Identifiers are packed into 'id'
                     54:  * and their hash table slot is stashed in 'idhash'.
                     55:  * Integers are returned in 'ival',
                     56:  * long integers in 'lval' and doubles in 'dval'.
                     57:  */
                     58: lex()
                     59: {
                     60:        register SYM    *sp;
                     61:        register int    c;
                     62:        register int    n;
                     63: 
                     64:        for (;;) {
                     65:                if ((c=get()) < 0)
                     66:                        return (s = EOF);
                     67:                switch (s = ct[c]) {
                     68: 
                     69:                case SKIP:
                     70:                        continue;
                     71: 
                     72:                case QUOTE:
                     73:                        n = 0;
                     74:                        lval = 0;
                     75:                        instring = c;           /* to allow high-bit chars */
                     76:                        while ((c = getmap('\'')) >= 0) {
                     77:                                lval <<= 8;
                     78:                                lval |= c;
                     79:                                ++n;
                     80:                        }
                     81:                        instring = 0;
                     82:                        ival = lval;
                     83:                        tval = T_INT;
                     84:                        s = ICON;
                     85: #if 0
                     86:                        switch (n) {
                     87:                        case 0:
                     88:                                cwarn("empty character constant");
                     89:                                break;
                     90:                        case 2:
                     91:                                cwarn("multiple character constant");
                     92:                                tval = T_INT;
                     93:                                break;
                     94:                        case 1:
                     95:                                break;
                     96:                        case 3:
                     97:                        case 4:
                     98:                                cwarn("character constant promoted to long");
                     99:                                tval = T_LONG;
                    100:                                s = LCON;
                    101:                                break;
                    102:                        default:
                    103:                                cerror("character constant overflows long");
                    104:                                tval = T_LONG;
                    105:                                s = LCON;
                    106:                                break;
                    107:                        }
                    108: #else
                    109:                        if (n != 1)
                    110:                                cerror("multiple character constant");
                    111: #endif
                    112:                        break;
                    113: 
                    114:                case ADD:
                    115:                        if (nextis('+'))
                    116:                                s = INCBEF;
                    117:                        break;
                    118: 
                    119:                case SUB:
                    120:                        if (nextis('-'))
                    121:                                s = DECBEF;
                    122:                        else if (nextis('>'))
                    123:                                s = ARROW;
                    124:                        break;
                    125: 
                    126:                case LT:
                    127:                        if (nextis('='))
                    128:                                s = LE;
                    129:                        else if (nextis('<'))
                    130:                                s = SHL;
                    131:                        break;
                    132: 
                    133:                case GT:
                    134:                        if (nextis('='))
                    135:                                s = GE;
                    136:                        else if (nextis('>'))
                    137:                                s = SHR;
                    138:                        break;
                    139: 
                    140:                case ASSIGN:
                    141:                        if (nextis('='))
                    142:                                s = EQ;
                    143:                        break;
                    144: 
                    145:                case NOT:
                    146:                        if (nextis('='))
                    147:                                s = NE;
                    148:                        break;
                    149: 
                    150:                case AND:
                    151:                        if (nextis('&'))
                    152:                                s = ANDAND;
                    153:                        break;
                    154: 
                    155:                case OR:
                    156:                        if (nextis('|'))
                    157:                                s = OROR;
                    158:                        break;
                    159: 
                    160:                case DOT:
                    161:                        c = get();
                    162:                        if (c<0 || ct[c]!=CON) {
                    163:                                unget(c);
                    164:                                break;
                    165:                        }
                    166:                        getnum(c, 1);
                    167:                        break;
                    168: 
                    169:                case CON:
                    170:                        getnum(c, 0);
                    171:                        break;
                    172: 
                    173:                case ID:
                    174:                        if (expand(c))
                    175:                                continue;
                    176:                        for (sp = idp->t_sym; sp != NULL; sp = sp->s_sp)
                    177:                                if (sp->s_slevel == SL_KEY) {
                    178:                                        s = sp->s_value;
                    179:                                        break;
                    180:                                }
                    181:                        break;
                    182: 
                    183:                case JUNK:
                    184:                case HIGH0:
                    185:                case HIGH1:
                    186:                case HIGH2:
                    187:                case HIGH3:
                    188:                        cerror("illegal character (%d decimal)", c);
                    189:                        continue;
                    190: 
                    191:                }
                    192:                if ((s>=ADD && s<=SHR) && nextis('='))
                    193:                        s += AADD-ADD;
                    194:                return (s);
                    195:        }
                    196: }
                    197: 
                    198: /*
                    199:  * Test if the next character in the input is 'n'.
                    200:  * If it is, eat it up and return true;
                    201:  * otherwise put it back and return false.
                    202:  */
                    203: nextis(n) int n;
                    204: {
                    205:        register int    c;
                    206: 
                    207:        if ((c = get()) == n)
                    208:                return (1);
                    209:        unget(c);
                    210:        return (0);
                    211: }
                    212: 
                    213: /*
                    214:  * Get the next non blank character from the input.
                    215:  * This is for cpp, so we do not pass newline.
                    216:  */
                    217: getnb()
                    218: {
                    219:        register int c;
                    220: 
                    221:        while ((c = get())==' ' || c=='\t')
                    222:                ;
                    223:        return (c);
                    224: }
                    225: 
                    226: /*
                    227:  * Get the next non-skip character.
                    228:  * Different from getnb() which chokes
                    229:  * on newline.
                    230:  */
                    231: getskip()
                    232: {
                    233:        register int c;
                    234: 
                    235:        while ((c = get()) > 0 && ct[c] == SKIP)
                    236:                ;
                    237:        return c;
                    238: }
                    239: 
                    240: /*
                    241:  * Peek ahead in the input (ignoring whitespace)
                    242:  * to see if the next character is 'n'.
                    243:  * True return it it is.
                    244:  * The character is left in the input stream.
                    245:  * This routine is used to look for the ':' after labels
                    246:  * and the '(' after undefined names in expressions.
                    247:  */
                    248: spnextis(n) int n;
                    249: {
                    250:        register int    c;
                    251: 
                    252:        while ((c=get()) >= 0) {
                    253:                if (ct[c] != SKIP) {
                    254:                        unget(c);
                    255:                        if (c == n)
                    256:                                return (1);
                    257:                        return (0);
                    258:                }
                    259:        }
                    260:        return (0);
                    261: }
                    262: 
                    263: /*
                    264:  * This routine is like lex(), except that it correctly skips
                    265:  * over any strings in the input.
                    266:  * Used during error recovery.
                    267:  */
                    268: skip()
                    269: {
                    270:        if (s == STRING)
                    271:                while (getmap('\"') >= 0)
                    272:                        ;
                    273:        lex();
                    274: }
                    275: 
                    276: /*
                    277:  * Read the next character from a string or a character constant.
                    278:  * Return -1 when either end of file or the delimiter 'd' is encountered.
                    279:  */
                    280: getmap(d) int d;
                    281: {
                    282:        register int    c, n, v;
                    283: 
                    284:        if ((c=get()) == d)
                    285:                return (-1);
                    286:        if (c<0 || c=='\n') {
                    287:                unget(c);
                    288:                cerror("nonterminated string or character constant");
                    289:                return (-1);
                    290:        }
                    291:        if (c == '\\') {
                    292:                c = get();
                    293:                switch (c) {
                    294: 
                    295:                case 'a':
                    296:                        c = '\07';
                    297:                        break;
                    298: 
                    299:                case 'b':
                    300:                        c = '\b';
                    301:                        break;
                    302: 
                    303:                case 'f':
                    304:                        c = '\f';
                    305:                        break;
                    306: 
                    307:                case 'n':
                    308:                        c = '\n';
                    309:                        break;
                    310: 
                    311:                case 'r':
                    312:                        c = '\r';
                    313:                        break;
                    314: 
                    315:                case 't':
                    316:                        c = '\t';
                    317:                        break;
                    318: 
                    319:                case 'v':
                    320:                        c = '\013';
                    321:                        break;
                    322: 
                    323:                case 'x':
                    324:                        notbook();
                    325:                        c = get();
                    326:                        n = 0;
                    327:                        v = 0;
                    328:                        while (++n<=3
                    329:                                && ( (c>='0' && c<='9')
                    330:                                  || (c>='A' && c<='F')
                    331:                                  || (c>='a' && c<='f') )) {
                    332:                                v <<= 4;
                    333:                                if (c>='0' && c<='9')
                    334:                                        v += c - '0';
                    335:                                else if (c>='A' && c<='F')
                    336:                                        v += c - 'A' + 10;
                    337:                                else
                    338:                                        v += c - 'a' + 10;
                    339:                                c = get();
                    340:                        }
                    341:                        unget(c);
                    342:                        c = v;
                    343:                        break;
                    344: 
                    345:                case '0':
                    346:                case '1':
                    347:                case '2':
                    348:                case '3':
                    349:                case '4':
                    350:                case '5':
                    351:                case '6':
                    352:                case '7':
                    353:                        n = 0;
                    354:                        v = 0;
                    355:                        while (++n<=3 && c>='0' && c<='7') {
                    356:                                v = (v<<3) + c - '0';
                    357:                                c = get();
                    358:                        }
                    359:                        unget(c);
                    360:                        c = v;
                    361:                        break;
                    362:                }
                    363:        }
                    364:        return (c);
                    365: }
                    366: 
                    367: /*
                    368:  * Read an identifier into id[]
                    369:  * and set idhash.
                    370:  */
                    371: getid(ch) int ch;
                    372: {
                    373:        {
                    374:                register char *p;
                    375:                register int c;
                    376:                c = ch;
                    377:                p = id;
                    378:                idhash = 0;
                    379:                idsize = 0;
                    380:                idhide = -1;    /* Universal */
                    381:                do {
                    382:                        if (p < &id[NCSYMB-1]) {
                    383:                                *p++ = c;
                    384:                                idhash += c;
                    385:                                idsize += 1;
                    386:                        }
                    387:                        if ((c = get()) >= SET0) {
                    388:                                idhide = hideint(c, idhide);
                    389:                                c = get();
                    390:                        }
                    391:                } while (c>=0 && (ct[c]==ID || ct[c]==CON));
                    392:                unget(c);
                    393:                if (idhide == -1)
                    394:                        idhide = SET0;  /* Empty */
                    395:                *p++ = 0;
                    396:                *p++ = 0;
                    397:                *p++ = 0;
                    398:        }
                    399:        {
                    400:                register TOK *tp, **tpp;
                    401: 
                    402:                idhash %= NHASH;
                    403:                for (tpp = hash0+idhash; (tp = *tpp) != NULL; tpp = &tp->t_tp)
                    404:                        if (ideq(tp))
                    405:                                break;
                    406:                if (tp == NULL)
                    407:                        *tpp = tp = newtoken();
                    408:                idp = tp;
                    409:        }
                    410: }
                    411: 
                    412: setid(cp) char *cp;
                    413: {
                    414:        {
                    415:                register char *p1, *p2;
                    416:                register int c;
                    417: 
                    418:                p1 = cp;
                    419:                p2 = id;
                    420:                idhash = 0;
                    421:                idsize = 0;
                    422:                while (c = *p1++) {
                    423:                        if (p2 < &id[NCSYMB-1]) {
                    424:                                *p2++ = c;
                    425:                                idhash += c;
                    426:                                idsize += 1;
                    427:                        }
                    428:                }
                    429:                *p2 = 0;
                    430:        }
                    431:        {
                    432:                register TOK *tp, **tpp;
                    433: 
                    434:                idhash %= NHASH;
                    435:                for (tpp = hash0+idhash; (tp = *tpp) != NULL; tpp = &tp->t_tp)
                    436:                        if (ideq(tp))
                    437:                                break;
                    438:                if (tp == NULL)
                    439:                        *tpp = tp = newtoken();
                    440:                idp = tp;
                    441:        }
                    442: }
                    443: 
                    444: /*
                    445:  * Read number into id[].
                    446:  * Set 's' appropriately.
                    447:  */
                    448: getnum(c, dotf) register int c; int dotf;
                    449: {
                    450:        register char   *np;
                    451:        int             expf, sgnf, ntlf, base;
                    452:        int             islong, isunsigned, isfloat;
                    453:        long            n;
                    454:        static char ulong[] = "unsigned long";
                    455: #      define slong    (ulong+9)
                    456: #if    NATIVEFP
                    457:        double          d;
                    458:        char            *cp, *dp;
                    459:        extern double   atof();
                    460: #endif
                    461: 
                    462:        expf = 0;
                    463:        ntlf = 0;
                    464:        sgnf = 1;
                    465:        base = 10;
                    466:        islong = 0;
                    467:        isunsigned = 0;
                    468:        isfloat = 0;
                    469:        np = id;
                    470:        n = 0;
                    471:        if (dotf)
                    472:                *np++ = '.';
                    473:        if (dotf==0 && c=='0') {
                    474:                base = 8;
                    475:                if ((c = get()) == 'x' || c == 'X') {
                    476:                        *np++ = '0';
                    477:                        *np++ = c;
                    478:                        base = 16;
                    479:                        c = get();
                    480:                } else {
                    481:                        unget(c);
                    482:                        c = '0';
                    483:                }
                    484:        }
                    485:        do {
                    486:                if (base!=16 && c=='.') {
                    487:                        if (dotf++)
                    488:                                break;
                    489:                } else if (c=='+' || c=='-') {
                    490:                        if (sgnf++)
                    491:                                break;
                    492:                } else if (base!=16 && (c=='e' || c=='E')) {
                    493:                        if (expf++)
                    494:                                break;
                    495:                        sgnf = 0;
                    496:                } else if (c<'0' || c>'9') {
                    497:                        if (base != 16)
                    498:                                break;
                    499:                        if (!((c>='A' && c<='F') || (c>='a' && c<='f')))
                    500:                                break;
                    501:                } else
                    502:                        ++sgnf;
                    503:                if (np < &id[NCSYMB-1])
                    504:                        *np++ = c;
                    505:                else
                    506:                        ntlf = 1;
                    507:                if (base == 8)
                    508:                        n <<= 3;
                    509:                else if (base == 10)
                    510:                        n = (n<<3) + (n<<1);
                    511:                else
                    512:                        n <<= 4;
                    513:                if (c>='A' && c<='F')
                    514:                        c -= 'A'-10;
                    515:                else if (c>='a' && c<='f')
                    516:                        c -= 'a'-10;
                    517:                else
                    518:                        c -= '0';
                    519:                n += c;
                    520:        } while ((c = get()) >= 0);
                    521:        for (;;) {
                    522:                if (c=='l' || c=='L') {
                    523:                        ++islong;
                    524:                        *np++ = c;
                    525:                        c = get();
                    526:                } else if (c == 'u' || c == 'U') {
                    527:                        ++isunsigned;
                    528:                        *np++ = c;
                    529:                        c = get();
                    530:                } else if (c == 'f' || c == 'F') {
                    531:                        ++isfloat;
                    532:                        *np++ = c;
                    533:                        c = get();
                    534:                } else {
                    535:                        unget(c);
                    536:                        *np = 0;
                    537:                        break;
                    538:                }
                    539:        }
                    540:        s = ICON;
                    541:        tval = T_INT;
                    542:        ival = lval = n;
                    543:        if (ntlf) {
                    544:                cerror("number has too many digits");
                    545:                return;
                    546:        }
                    547:        if (dotf || expf || isfloat) {
                    548:                if (isunsigned || (isfloat+islong > 1)) {
                    549:                        cerror("illegal floating constant suffix");
                    550:                        return;
                    551:                }
                    552:                tval = isfloat ? T_FLOAT : islong ? T_LDOUBLE : T_DOUBLE;
                    553: #if    NATIVEFP
                    554:                d = atof(id);
                    555:                for (dp = (char *)dval, cp = ((char *)&d)+sizeof(double)-1; cp >= &d; )
                    556:                        *dp++ = *cp--;
                    557: #else
                    558:                dvalread((char *)dval, id);
                    559: #endif
                    560:                s = DCON;
                    561:                return;
                    562:        }
                    563:        if (isunsigned > 1 || islong > 1) {
                    564:                cerror("illegal integer constant suffix");
                    565:                return;
                    566:        }
                    567:        np = NULL;
                    568:        if (islong) {
                    569:                s = LCON;
                    570:                tval = T_LONG;
                    571:                if (isunsigned || (n&SLMASK) != 0)
                    572:                        tval = T_ULONG;
                    573:        } else if (isunsigned) {
                    574:                tval = T_UINT;
                    575:                if ((n&UIMASK) != 0) {
                    576:                        s = LCON;
                    577:                        tval = T_ULONG;
                    578:                        np = ulong;
                    579:                }
                    580:        } else if (base == 10 && (n&SIMASK) != 0) {
                    581:                s = LCON;
                    582:                tval = T_LONG;
                    583:                np = slong;
                    584:                if ((n&SLMASK) != 0) {
                    585:                        tval = T_ULONG;
                    586:                        np = ulong;
                    587:                }
                    588:        } else if ((n&SIMASK) != 0) {
                    589:                tval = T_UINT;
                    590:                if ((n&UIMASK) != 0) {
                    591:                        s = LCON;
                    592:                        tval = T_LONG;
                    593:                        np = slong;
                    594:                        if ((n&SLMASK) != 0) {
                    595:                                tval = T_ULONG;
                    596:                                np = ulong;
                    597:                        }
                    598:                }
                    599:        }
                    600:        if (tval == T_ULONG) {
                    601:                /* Test for unsigned long overflow */
                    602:                /* and set np = NULL if a diagnostic is given */
                    603:                ;
                    604:        }
                    605:        if (incpp == 0 && np != NULL && isvariant(VSLCON))
                    606:                cwarn("\"%s\" promoted to %s", id, np);
                    607: }

unix.superglobalmegacorp.com

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