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

1.1       root        1: /*
                      2:  * This is the controlling loop in the assembler.
                      3:  *
                      4:  */
                      5: #include <utype.h>
                      6: #include <asm.h>
                      7: #include <asflags.h>
                      8: #include <y_tab.h>
                      9: #include <symtab.h>
                     10: 
                     11: /* states */
                     12: #define INITIAL        0
                     13: #define INSYM   1
                     14: #define INCHAR 2       /* in char constant */
                     15: #define LTS    3
                     16: #define GTS    4
                     17: #define BSLP   5       /* back slash while reading parms */
                     18: #define WHITE  6       /* in white space */
                     19: #define ENDLINE 7
                     20: #define CSTATE 8       /* Pick up parms in macro expansion */
                     21: #define INTOKEN 9
                     22: 
                     23: #define OPONLY1        10      /* search for operator only */
                     24: #define OPONLY2 11
                     25: #define OPONLY3        12
                     26: #define OPONLY4        13
                     27: 
                     28: #define INSTR  14      /* string detected */
                     29: #define BSL    15      /* back slash */
                     30: #define BSLDIG  16     /* digit after back slash */
                     31: 
                     32: #define CMSTATE 17     /* pick up names in macro definition */
                     33: #define INNAME 18
                     34: 
                     35: #define LZERO  19      /* lead zero */
                     36: #define XNUM   20      /* hex number */
                     37: #define DNUM   21      /* decimal number */
                     38: #define ONUM   22      /* octal number */
                     39: #define BNUM   23      /* binary number */
                     40: 
                     41: #define BANGS   24     /* ! seen */
                     42: #define EQUS    25     /* = seen */
                     43: 
                     44: #define DSTATE  26     /* eat whole line for S_EQUS */
                     45: 
                     46: /* positions */
                     47: #define LABEL  0
                     48: #define OPCODE 1
                     49: #define OPERAND        2
                     50: #define COMMENT 3
                     51: 
                     52: /* comparisons */
                     53: #define LT 1
                     54: #define GT 2
                     55: #define EQ 4
                     56: 
                     57: #define RET(toYacc) return(lastToken = (toYacc))
                     58: #define RSTATE(toYacc, newstate) { state = newstate; RET(toYacc); }
                     59: #define NEWS(newstate) { state = newstate; continue; }
                     60: 
                     61: static unsigned short state = INITIAL;
                     62: static unsigned short pstate;  /* previous state when \ detected */
                     63: static unsigned short pos = LABEL;
                     64: 
                     65: static unsigned short ctype;   /* current logic type */
                     66: 
                     67: static char buf[1024], *bp = buf;
                     68: static char *backOff;  /* start of decimal number */
                     69: static char fromMac = ' ';             /* ' ' or '+' */
                     70: static short opIx;     /* index of current opcode */
                     71: static psw = 0;
                     72: static long number = 0;
                     73: static char token[1024], *tp;
                     74: 
                     75: static int lastChar;   /* last Character in */
                     76: static short vctr, scnt, dcnt;
                     77: static symt *stype;
                     78: static short ytype;
                     79: 
                     80: /*
                     81:  * Invalid character message.
                     82:  */
                     83: static void
                     84: invChar(c, s)
                     85: register short c;
                     86: char *s;
                     87: {
                     88:        unsigned short p;
                     89: 
                     90:        p = bp - lastL;
                     91:        if (isprint(c))
                     92:                yyerror("Invalid character '%c' %s at position %d", c, s, p);
                     93:                /**/
                     94:        else
                     95:                yyerror("Invalid character 0x%02x %s at position %d",
                     96:                        c & 255, s, p); /**/
                     97: }
                     98: 
                     99: /*
                    100:  * Expand parms in macro line.
                    101:  * # as first char of line foils replacment.
                    102:  */
                    103: static char *
                    104: expand(s, recurs)
                    105: register char *s;
                    106: {
                    107:        register char c;
                    108:        char *tp, *rep, *newl, *start;
                    109:        macro *mac;
                    110:        short sav, pb;
                    111:        unsigned short point;
                    112: 
                    113:        start = s;
                    114:        pb = 0;
                    115:        for(state = WHITE; ; ) {
                    116:                switch(state) {
                    117:                case WHITE:
                    118:                        if (isalpha(c = *s++)) {
                    119:                                state = INSYM;
                    120:                                tp = token;
                    121:                                *tp++ = c;
                    122:                                break;
                    123:                        }
                    124:                        pb = 0;
                    125:                        break;
                    126:                case INSYM:
                    127:                        if (isalnum(c = *s++)) {
                    128:                                *tp++ = c;
                    129:                                break;
                    130:                        }
                    131:                        mac = NULL;
                    132:                        *tp = '\0';
                    133:                        if ((!recurs && (NULL != trueMac) &&
                    134:                            (NULL != (rep = lookList(token)))) ||
                    135:                           (NULL != (mac = macLookUp(token, MACSTR)))) {
                    136:                                tp = --s - (strlen(token) + pb);
                    137:                                sav = *tp;      /* stomp parm name */
                    138:                                *tp = '\0';
                    139:                                if (NULL == mac)        /* parm match */
                    140:                                        rep = expand(rep, 1);
                    141:                                else {  /* equs match */
                    142:                                        rep = mac->names->str;
                    143:                                        mac->type = MACSCAN;
                    144:                                        rep = expand(rep, 1);
                    145:                                        mac->type = MACSTR;
                    146:                                }
                    147:                                point = strlen(start) + strlen(rep);
                    148:                                newl = galloc(point + strlen(s) + 1);
                    149:                                sprintf(newl, "%s%s%s", start, rep, s);
                    150:                                *tp = sav;      /* Un stomp parm name */
                    151:                                start = newl;
                    152:                                s = start + point; /* don't rescan */
                    153:                        }
                    154:                        pb = (c == '\\');
                    155:                        state = WHITE;
                    156:                }
                    157:                if (!c)
                    158:                        break;
                    159:        }
                    160:        return(start);
                    161: }
                    162: 
                    163: /*
                    164:  * Get next line from macro or while.
                    165:  */
                    166: static char *
                    167: nextMac()
                    168: {
                    169:        macctl *tmp;
                    170:        macline *l;
                    171:        extern char *strcpy();
                    172: 
                    173:        for(;;) {
                    174:                if (NULL == macExp) {   /* not in a macro */
                    175:                        fromMac = ' ';
                    176:                        return(NULL);
                    177:                }
                    178:                if (NULL != (l = macExp->curr)) {
                    179:                        fromMac = '+';
                    180:                        macExp->curr =  l->next;
                    181:                        return(strcpy(buf, l->line));
                    182:                }
                    183: 
                    184:                if ((tmp = macExp) == trueMac) { /* popping macro */
                    185:                        freeList(macExp->parms);
                    186: 
                    187:                        while(logic->expno == trueMac->expno) {
                    188:                                if ((logic->type == INWDEF) ||
                    189:                                   (logic->type == INPWDEF))
                    190:                                        yyerror("End of macro building .while");
                    191:                                /* A \fB.macro\fR ended while reading in a
                    192:                                 * \fB.while\fR loop. */
                    193:                                freeLevel();
                    194:                        }
                    195: 
                    196:                        do {
                    197:                                trueMac = trueMac->prev;
                    198:                        } while((NULL != trueMac) &&
                    199:                                (trueMac->type != MACTYPE));
                    200:                }
                    201: 
                    202:                macExp = macExp->prev;          /* pop a level */
                    203:                free((char *)tmp);
                    204:        }
                    205: }
                    206: 
                    207: /*
                    208:  * Save a line in a macro.
                    209:  */
                    210: saveLine()
                    211: {
                    212:        macline *newl;
                    213: 
                    214:        newl = (macline *)alloc((unsigned)(sizeof(*newl) + strlen(lastL)));
                    215:        strcpy(newl->line, lastL);
                    216:        if (NULL == inMacDef->first)
                    217:                lastDef = inMacDef->first = newl;
                    218:        else {
                    219:                lastDef->next = newl;
                    220:                lastDef = newl;
                    221:        }
                    222: }
                    223: 
                    224: /*
                    225:  * Get a line off a file.
                    226:  */
                    227: static char *
                    228: getLine()
                    229: {
                    230:        register char *line;
                    231: 
                    232:        ++statement;            /* increment statement number */
                    233:        if (NULL != (line = nextMac()))
                    234:                return(line);
                    235: 
                    236:        while(NULL == (fgets(line = buf, sizeof(buf), inpc->fp))) {
                    237:                if (NULL != inpc->prev) {
                    238:                        inpctl *tmp;
                    239: 
                    240:                        fclose(inpc->fp);
                    241:                        inpc = (tmp = inpc)->prev;
                    242:                        free((char *)tmp);
                    243:                }
                    244:                else {  /* end of pass */
                    245:                        for(;NORMAL != logic->type; freeLevel()) {
                    246:                                switch(logic->type) {
                    247:                                case INMACDEF:
                    248:                                case PMACDEF:
                    249:                                        yyerror("Missing .endm");
                    250:                                 /* Input ended leaving \fB.macro\fR open. */
                    251:                                        break;
                    252:                                case INIF0:
                    253:                                case INIF1:
                    254:                                case INIFX:
                    255:                                        yyerror("Missing .endi");
                    256:                                 /* Input ended leaving \fB.if\fR open. */
                    257:                                        break;
                    258:                                case INWDEF:
                    259:                                case INPWDEF:
                    260:                                        yyerror("Missing .endw");
                    261:                                 /* Input ended leaving \fB.while\fR open. */
                    262:                                }
                    263:                        }
                    264:                        if (2 == pass) {
                    265:                                cleanUp();
                    266: 
                    267:                                switch (errCt) {
                    268:                                case 0:
                    269:                                        exit(0);
                    270:                                case 1:
                    271:                                        fprintf(errdev, "1 Error\n");
                    272:                                        break;
                    273:                                default:
                    274:                                        fprintf(errdev, "%d Errors\n", errCt);
                    275:                                }
                    276:                                unlink(outName);
                    277:                                exit(1);
                    278:                        }
                    279:                        else {  /* avoid close & open */
                    280:                                rewind(inpc->fp);
                    281:                                inpc->lineNo = 0;
                    282:                                statement = 1;
                    283: 
                    284:                                newPass(outName);
                    285: 
                    286:                                /* reset compiler switches to initial state */
                    287:                                alignon = alignonX;
                    288:                                lswitch = lswitchX;
                    289:                                nswitch = nswitchX;
                    290:                                wswitch = wswitchX;
                    291:                                fswitch = fswitchX;
                    292:                                bswitch = bswitchX;
                    293: 
                    294:                                dodefs();
                    295:                                outLine((char *)NULL, 0);
                    296:                                continue;
                    297:                        }
                    298:                }
                    299:        }
                    300:        inpc->lineNo++;
                    301:        return(line);
                    302: }
                    303: 
                    304: /*
                    305:  * In OPONLY3 we found an op process it.
                    306:  * separated to keep from crashing Coherent compiler in cc2.
                    307:  */
                    308: static unsigned short
                    309: procOp()
                    310: {
                    311:        register opc *op;
                    312: 
                    313:        *tp = '\0';
                    314:        bp--;
                    315:        if (-1 == (opIx = opLookUp(token)))
                    316:                return(OPONLY4);
                    317: 
                    318:        if (INIF1 <= ctype)
                    319:                fatal("Logic error in macro def '%s' %d", token, ctype); /* TECH */
                    320: 
                    321:        op = prefTab + opIx;
                    322:        switch(op->kind) {      /* switch on function type */   
                    323:        case S_MACRO:
                    324:                if (ctype < INIF0)
                    325:                        newLevel(PMACDEF);
                    326:                break;
                    327:        case S_ENDM:
                    328:                switch(ctype) {
                    329:                case INMACDEF:
                    330:                        inMacDef = (macro *)NULL;
                    331:                        lastDef = (macline *)NULL;
                    332:                        freeLevel();
                    333:                        return(INITIAL);
                    334:                case PMACDEF:
                    335:                        freeLevel();
                    336:                }
                    337:                break;
                    338:        case S_WHILE:
                    339:                switch(ctype) {
                    340:                case INWDEF:
                    341:                case INPWDEF:
                    342:                        newLevel(INPWDEF);
                    343:                }
                    344:                break;
                    345:        case S_ENDW:
                    346:                switch(ctype) {
                    347:                case INWDEF: {
                    348:                        macctl *tmp;
                    349:                                saveLine();
                    350:                        logic = (tmp = logic)->prev;
                    351:                        tmp->type  = WHILETYPE;
                    352:                        tmp->curr = tmp->first = inMacDef->first;
                    353:                        tmp->parms = tmp->names = NULL;
                    354:                        tmp->prev = macExp;
                    355:                        macExp = tmp;
                    356:                        free((char *)inMacDef);
                    357:                        lastDef  = (macline *)NULL;
                    358:                        inMacDef = (macro *)NULL;
                    359:                        return(INITIAL);
                    360:                }
                    361:                case INPWDEF:
                    362:                        freeLevel();
                    363:                        break;
                    364:                }
                    365:                break;
                    366:        case S_IF:
                    367:                switch(ctype) {
                    368:                case INIF0:
                    369:                case INIFX:
                    370:                        newLevel(INIFX);
                    371:                }
                    372:                break;
                    373:        case S_ELSE:
                    374:                switch(ctype) {
                    375:                case INIF0:
                    376:                        logic->type = INIF1;
                    377:                        return(INITIAL);
                    378:                }
                    379:                break;
                    380:        case S_ENDI:
                    381:                switch(ctype) {
                    382:                case INIF0:
                    383:                case INIFX:
                    384:                        freeLevel();
                    385:                }
                    386:                break;
                    387:        }
                    388:        return(OPONLY4);
                    389: }
                    390: 
                    391: /*
                    392:  * Read line and start processing.
                    393:  * separated from yylex() to keep from crashing compiler in cc2.
                    394:  */
                    395: static unsigned short
                    396: startLine()
                    397: {
                    398:        register short c;
                    399: 
                    400:        do {    /* GNU outputs # line numbers */
                    401:                if (';' != lastChar) {
                    402:                        outLine(lastL, fromMac);
                    403:                        bp = lastL = getLine();
                    404:                }
                    405:                if (COMMA != lastToken)
                    406:                        freel();        /* trash free space from last line */
                    407:        } while ('#' == *bp);
                    408: 
                    409:        ctype = logic->type;
                    410: 
                    411:        if (('#' != *bp) &&
                    412:           (';' != lastChar) &&
                    413:           (defCt || (NULL != trueMac)) &&
                    414:           ((ctype > INPWDEF) || (ctype < INWDEF))) {
                    415:                bp = lastL = expand(bp, 0);
                    416: 
                    417:                if ((lastL != buf) && (fromMac != '+')) {
                    418:                        outLine(buf, fromMac);
                    419:                        fromMac = '@';
                    420:                }
                    421:        }
                    422: 
                    423:        if ('#' == *bp) /* don't lex noexpand */
                    424:                bp++;
                    425: 
                    426:        if (COMMA == lastToken) /* continuation line ? */
                    427:                return(psw);
                    428: 
                    429:        lastChar = c = *bp;     /* get a char */
                    430:        if (ctype < INIF1) {
                    431:                if ((' ' == c) || ('\t' == c))
                    432:                        return(OPONLY1);
                    433:                else if (isalpha(c))
                    434:                        return(OPONLY2);
                    435:                else
                    436:                        return(OPONLY4);
                    437:        }
                    438:        if ((' ' == c) || ('\t' == c)) {
                    439:                pos = OPCODE;
                    440:                return(WHITE);
                    441:        }
                    442:        if (isalpha(c)) {
                    443:                pos = LABEL;
                    444:                tp = token;
                    445:                *tp++ = c;
                    446:                return(INSYM);
                    447:        }
                    448:        switch(c) {
                    449:        case '/': case '\n': case 0: case ';':
                    450:                break;
                    451:        default:
                    452:                invChar(c, "");
                    453:        }
                    454:        return(INITIAL);
                    455: }
                    456: 
                    457: /*
                    458:  * Got an opcode, set it up.
                    459:  */
                    460: static
                    461: doOp(opIx)
                    462: {
                    463:        register opc *op;
                    464: 
                    465:        lflags = 0;
                    466:        stype = typTab + (kind = (op = prefTab + opIx)->kind);
                    467:        yylval.o = op;
                    468:        pos = OPERAND;
                    469:        /* op code determines operand syntax */
                    470:        switch(ytype = stype->type) {
                    471:        case NCMD:
                    472:                RSTATE(ytype, ENDLINE)
                    473:        case OP:
                    474:                if (stype->bldr & REP_INSTR)
                    475:                        pos = OPCODE;
                    476:        case ICMD:
                    477:        case DATA:
                    478:                RSTATE(ytype, WHITE)
                    479:        case ECMD:
                    480:        case ECMDX:
                    481:        case CMD:
                    482:                if (S_EQUS == kind) {
                    483:                        tp = token;
                    484:                        scnt = dcnt = 0;
                    485:                        RSTATE(ytype, DSTATE)
                    486:                }
                    487:                RSTATE(ytype, CSTATE)
                    488:        case DCMD:
                    489:                RSTATE(ytype, CMSTATE)
                    490:        default:
                    491:                fatal("Optype %d in lex", ytype); /* TECH */
                    492:        }
                    493: }
                    494: 
                    495: /*
                    496:  * get tokens
                    497:  */
                    498: yylex()
                    499: {
                    500:     register short c;
                    501: 
                    502:     for(;;) {
                    503:        /*
                    504:         * Allow Japaneese comments and strings, catch other non ascii
                    505:         * and abort the line.
                    506:         */
                    507:        if ((state != INITIAL) &&
                    508:           !isascii(lastChar = c = *bp++) &&
                    509:           (state != INSTR) &&
                    510:           (state != INCHAR)) {
                    511:                invChar(c, "");
                    512:                RSTATE(NL, INITIAL)
                    513:        }
                    514: 
                    515:        switch(state) {
                    516:        case INITIAL:           /* start of line */
                    517:                bcnt = pcnt = 0;
                    518:                psw = startLine();
                    519:                lastChar = c = *bp++;
                    520:                if (!isascii(c)) {
                    521:                        invChar(c, "");
                    522:                        RSTATE(NL, INITIAL)
                    523:                }
                    524:                NEWS(psw);
                    525:                
                    526:        case OPONLY1:   /* find start of opcode */
                    527:                switch(c) {
                    528:                case ' ':
                    529:                case '\t':
                    530:                        continue;
                    531:                default:
                    532:                        if (!islower(c))
                    533:                                NEWS(OPONLY4)
                    534:                        tp = token;
                    535:                        *tp++ = c;
                    536:                        NEWS(OPONLY3)
                    537:                }
                    538: 
                    539:        case OPONLY2:                   /* bypass label */
                    540:                if (isalnum(c))
                    541:                        continue;
                    542:                --bp;
                    543:                if ((' ' == c) || ('\t' == c))
                    544:                        NEWS(OPONLY1)
                    545:                NEWS(OPONLY4)
                    546:                
                    547:        case OPONLY3:
                    548:                if (isalnum(c)) {       /* accumulate opcode */
                    549:                        *tp++ = c;
                    550:                        continue;
                    551:                }
                    552:                NEWS(procOp());
                    553: 
                    554:        case OPONLY4:   /* default processing */
                    555:                if (logic->type < INIF0)
                    556:                        saveLine();
                    557:                NEWS(INITIAL)
                    558: 
                    559:        case INSYM:
                    560:                if (isalnum(c)) {
                    561:                        *tp++ = c;
                    562:                        continue;
                    563:                }
                    564:                *tp = '\0';
                    565:                --bp;
                    566:                if (pos == OPERAND) {
                    567:                        sym *sp;
                    568: 
                    569:                        sp = symLookUp(token, S_UNDEF, 0L, 0);
                    570:                        switch(sp->type) {
                    571:                        case IDENTIFIER:
                    572:                        case REG:
                    573:                        case LEN:
                    574:                                yylval.s = sp;
                    575:                                break;
                    576:                        case NUMBER:
                    577:                                yylval.val = sp->loc;
                    578:                        }
                    579:                        RSTATE(sp->type, WHITE)
                    580:                }
                    581: 
                    582:                /* pos != OPERAND may be opcode or label */
                    583:                if (':' != c) {
                    584:                        if (-1 != (opIx = opLookUp(token)))
                    585:                                return(doOp(opIx));
                    586: 
                    587:                        if (NULL != (macFound = macLookUp(token, MACTYPE))) {
                    588:                                static opc smac = { /* fake opcode */
                    589:                                        0, S_MAC
                    590:                                };
                    591: 
                    592:                                yylval.o = &smac; /* macro expansion */
                    593:                                RSTATE(CMD, CSTATE)
                    594:                        }
                    595: 
                    596:                        if (!strcmp(token, ".")) {
                    597:                                yylval.t = token;
                    598:                                pos = OPCODE;
                    599:                                RSTATE(TOKEN, WHITE)
                    600:                        }
                    601:                }
                    602: 
                    603:                if ((pos == LABEL) || (':' == c)) {
                    604:                        yylval.t = token;
                    605:                        pos = OPCODE;
                    606:                        RSTATE(TOKEN, WHITE)
                    607:                }
                    608: 
                    609:                yyerror("Invalid opcode: '%s'", token);
                    610:                /* The string in the opcode position is
                    611:                 * not one of our opcodes or one of
                    612:                 * your macros. */
                    613:                RSTATE(NL, INITIAL)
                    614: 
                    615:        case DSTATE:    /* eat whole line for define */
                    616:                switch(c) {
                    617:                case '"':
                    618:                        if (dcnt)
                    619:                                dcnt = 0;
                    620:                        else if (!scnt)
                    621:                                dcnt = 1;
                    622:                        break;
                    623:                case '\'':
                    624:                        if (scnt)
                    625:                                scnt = 0;
                    626:                        else if (!dcnt)
                    627:                                scnt = 1;
                    628:                        break;
                    629:                case '\\':
                    630:                        *tp++ = c;
                    631:                        psw = state;
                    632:                        NEWS(BSLP)
                    633:                case '/':
                    634:                        if (scnt | dcnt)
                    635:                                break;
                    636:                case 0:         /* let # define take semicolon */
                    637:                case '\n':
                    638:                        *tp = '\0';
                    639:                        yylval.t = trim(token);
                    640:                        RSTATE(TOKEN, ENDLINE)
                    641:                }
                    642:                *tp++ = c;
                    643:                continue;
                    644: 
                    645:        case CSTATE: /* pick up parms on macro expansion */
                    646:                state = psw = INTOKEN;
                    647:                *(tp = token) = '\0';
                    648:                scnt = dcnt = pcnt = bcnt = 0;
                    649:                vctr = 1;
                    650:                switch(c) {
                    651:                case 0:
                    652:                case ';':
                    653:                case '\n':
                    654:                case '/':
                    655:                        if (COMMA == lastToken)
                    656:                                NEWS(INITIAL)
                    657:                        RSTATE(NL, INITIAL)
                    658:                case ',':
                    659:                        switch(lastToken) {
                    660:                        case CMD:
                    661:                        case COMMA:
                    662:                                bp--;
                    663:                                yylval.t = token;
                    664:                                RSTATE(TOKEN, CSTATE)
                    665:                        }
                    666:                        RSTATE(COMMA, CSTATE)
                    667:                }
                    668: 
                    669:        case INTOKEN:   /* pick up parms on macro expansion */
                    670:                switch(c) {
                    671:                case '(':
                    672:                        pcnt += vctr; break;
                    673:                case ')':
                    674:                        if (pcnt)
                    675:                                pcnt -= vctr;
                    676:                        break;
                    677:                case '[':
                    678:                        bcnt += vctr; break;
                    679:                case ']':
                    680:                        if (bcnt)
                    681:                                bcnt -= vctr;
                    682:                        break;
                    683:                case '"':
                    684:                        if (dcnt)
                    685:                                dcnt = 0;
                    686:                        else if (!scnt)
                    687:                                dcnt = 1;
                    688:                        vctr = (dcnt | scnt) ^ 1;
                    689:                        break;
                    690:                case '\'':
                    691:                        if (scnt)
                    692:                                scnt = 0;
                    693:                        else if (!dcnt)
                    694:                                scnt = 1;
                    695:                        vctr = (dcnt | scnt) ^ 1;
                    696:                        break;
                    697:                case '\\':
                    698:                        *tp++ = c;
                    699:                        psw = state;
                    700:                        NEWS(BSLP)
                    701: 
                    702:                case ';':
                    703:                case '/':
                    704:                        if (!vctr)
                    705:                                break;
                    706:                case 0:
                    707:                case '\n':
                    708:                        if (pcnt | bcnt | scnt | dcnt) {
                    709:                                yyerror("Unmatched bracket in parmeter");
                    710:                /* Line ended leaving an open bracket or parenthesis. */
                    711:                                RSTATE(NL, INITIAL)
                    712:                        }
                    713:                        --bp;
                    714:                        *tp = '\0';
                    715:                        if (*(yylval.t = trim(token)))
                    716:                                RSTATE(TOKEN, CSTATE)
                    717:                        NEWS(CSTATE)
                    718:                case ',':
                    719:                        if (pcnt | bcnt | scnt | dcnt)
                    720:                                break;
                    721:                        --bp;
                    722:                        *tp = '\0';
                    723:                        yylval.t = trim(token);
                    724:                        switch(ytype) {
                    725:                        case ECMD:
                    726:                        case ECMDX:
                    727:                                RSTATE(TOKEN, WHITE)
                    728:                        }
                    729:                        RSTATE(TOKEN, CSTATE)
                    730:                }
                    731:                *tp++ = c;
                    732:                continue;
                    733: 
                    734:        case BSLP:      /* back slash while reading parm */
                    735:                switch(c) {
                    736:                case 0:
                    737:                case '\n':
                    738:                        --bp;
                    739:                        yyerror("End of line after backslash reading parm");
                    740:                /* Macro parmeters may not be broken up with backslash. */
                    741:                        break;
                    742:                }
                    743:                *tp++ = c;
                    744:                NEWS(psw)
                    745: 
                    746:        case CMSTATE: /* pick up names on macro definition */
                    747:                psw = state = INNAME;
                    748:                tp = token;
                    749:                switch(c) {
                    750:                case ',':
                    751:                        RET(COMMA);
                    752:                case 0:
                    753:                case ';':
                    754:                case '\n':
                    755:                case '/':
                    756:                        if (COMMA == lastToken)
                    757:                                NEWS(INITIAL)
                    758:                        RSTATE(NL, INITIAL)
                    759:                }
                    760:        case INNAME:    /* pick up parms on macro definition */
                    761:                switch(c) {
                    762:                case 0:
                    763:                case ';':
                    764:                case '\n':
                    765:                case '/':
                    766:                case ',':
                    767:                        --bp;
                    768:                        *tp = '\0';
                    769:                        if (*(yylval.t = trim(token)))
                    770:                                RSTATE(TOKEN, CMSTATE)
                    771:                        NEWS(CMSTATE)
                    772:                default:
                    773:                        if (ispunct(c)) {
                    774:                                invChar(c, "in macro name");
                    775:                                RSTATE(NL, INITIAL)
                    776:                        }
                    777:                }
                    778:                *tp++ = c;
                    779:                continue;
                    780: 
                    781: 
                    782:        case WHITE:
                    783:                /*
                    784:                 * This piece of code is heavily trafficked.
                    785:                 * Force the fastest form of switch statement
                    786:                 * by covering many cases.
                    787:                 */
                    788:                switch(c) {
                    789:                case '1':       case '2':       case '3':       case '4':
                    790:                case '5':       case '6':       case '7':       case '8':
                    791:                case '9':       case '0':
                    792:                        backOff = bp - 1;
                    793:                        if (number = c - '0')
                    794:                                NEWS(DNUM)
                    795:                        NEWS(LZERO);
                    796: 
                    797:                /* % allowed as first char only */
                    798:                case 'a':       case 'b':       case 'c':       case 'd':
                    799:                case 'e':       case 'f':       case 'g':       case 'h':
                    800:                case 'i':       case 'j':       case 'k':       case 'l':
                    801:                case 'm':       case 'n':       case 'o':       case 'p':
                    802:                case 'q':       case 'r':       case 's':       case 't':
                    803:                case 'u':       case 'v':       case 'w':       case 'x':
                    804:                case 'y':       case 'z':
                    805:                case 'A':       case 'B':       case 'C':       case 'D':
                    806:                case 'E':       case 'F':       case 'G':       case 'H':
                    807:                case 'I':       case 'J':       case 'K':       case 'L':
                    808:                case 'M':       case 'N':       case 'O':       case 'P':
                    809:                case 'Q':       case 'R':       case 'S':       case 'T':
                    810:                case 'U':       case 'V':       case 'W':       case 'X':
                    811:                case 'Y':       case 'Z':       case '?':       case '_':
                    812:                case '%':       case '.':
                    813:                        tp = token;
                    814:                        *tp++ = c;
                    815:                        NEWS(INSYM)
                    816: 
                    817:                case ' ':
                    818:                case '\t':
                    819:                        continue;
                    820:                case 0:
                    821:                case ';':
                    822:                case '\n':
                    823:                case '/':
                    824:                        if (COMMA == lastToken)
                    825:                                NEWS(INITIAL)
                    826:                        RSTATE(NL, INITIAL)
                    827:                case '<':
                    828:                        NEWS(LTS)
                    829:                case '>':
                    830:                        NEWS(GTS)
                    831:                case '!':
                    832:                        NEWS(BANGS)
                    833:                case '=':
                    834:                        NEWS(EQUS)
                    835:                case '+':
                    836:                        RET(PLUS);
                    837:                case '-':
                    838:                        RET(MINUS);
                    839:                case '*':
                    840:                        RET(TIMES);
                    841:                case ':':
                    842:                        if (OPERAND == pos)
                    843:                                RET(COLON);
                    844:                        pos = OPCODE;
                    845:                        RSTATE(NL, WHITE)
                    846:        
                    847:                case '&':
                    848:                        RET(AND);
                    849:                case '|':
                    850:                        RET(OR);
                    851:                case '^':
                    852:                        RET(XOR);
                    853:                case '#':
                    854:                        RET(P_SIGN);
                    855:                case '$':
                    856:                        RET(D_SIGN);
                    857:                case '~':
                    858:                        RET(NOT);
                    859:                case ',':
                    860:                        psw = WHITE;
                    861:                        RET(COMMA);
                    862:                /*
                    863:                 * This assembler may reverse the normal usage of
                    864:                 * brackets and parentheses. That is expressions
                    865:                 * are put in []. 5(%eax) is 5 past %eax.
                    866:                 * bswitch flips this back. Keeps counts to improve
                    867:                 * the syntax error message.
                    868:                 */
                    869:                case '[':
                    870:                        bcnt++;
                    871:                        RET(bswitch ? LBRACK : LPAREN);
                    872:                case ']':
                    873:                        bcnt--;
                    874:                        RET(bswitch ? RBRACK : RPAREN);
                    875:                case '(':
                    876:                        pcnt++;
                    877:                        RET(bswitch ? LPAREN : LBRACK);
                    878:                case ')':
                    879:                        pcnt--;
                    880:                        RET(bswitch ? RPAREN : RBRACK);
                    881:                case '@':
                    882:                        RET(AT);
                    883:                case '"':
                    884:                        psw = WHITE;
                    885:                        tp = token;
                    886:                        NEWS(INSTR)
                    887:                case '\'':
                    888:                        psw = WHITE;
                    889:                        tp = token;
                    890:                        NEWS(INCHAR)
                    891:                default:
                    892:                        invChar(c, "as token start");
                    893:                        RSTATE(NL, INITIAL)
                    894:                }
                    895: 
                    896:        case ONUM:
                    897:                if (isdigit(c)) {
                    898:                        if (c > '7')
                    899:                                yyerror("Error in octal number"); /**/
                    900:                        number *= 8;
                    901:                        number += c - '0';
                    902:                        continue;
                    903:                }
                    904:                bp--;
                    905:                yylval.val = number;
                    906:                RSTATE(NUMBER, WHITE)
                    907: 
                    908:        case BNUM:
                    909:                if (isdigit(c)) {
                    910:                        if (c > '1')
                    911:                                yyerror("Error in binary number"); /**/
                    912:                        number *= 2;
                    913:                        number += c - '0';
                    914:                        continue;
                    915:                }
                    916:                bp--;
                    917:                yylval.val = number;
                    918:                RSTATE(NUMBER, WHITE)
                    919: 
                    920:        case XNUM:
                    921:                if (isxdigit(c)) {
                    922:                        number *= 16;
                    923:                        if (isdigit(c))
                    924:                                number += c - '0';
                    925:                        else if (islower(c))
                    926:                                number += c - ('a' - 10);
                    927:                        else
                    928:                                number += c - ('A' - 10);
                    929:                        continue;
                    930:                }
                    931:                bp--;
                    932:                yylval.val = number;
                    933:                RSTATE(NUMBER, WHITE)
                    934:                
                    935:        case DNUM:
                    936:                if (isdigit(c)) {
                    937:                        number *= 10;
                    938:                        number += c - '0';
                    939:                        continue;
                    940:                }
                    941:                if (('.' == c) || ('e' == c) || ('E' == c)) {
                    942:                        yylval.dbl = strtod(backOff, &bp);
                    943:                        RSTATE(FNUM, WHITE)
                    944:                }
                    945:                bp--;
                    946:                yylval.val = number;
                    947:                RSTATE(NUMBER, WHITE)
                    948: 
                    949:        case LZERO:
                    950:                switch(c) {
                    951:                case '.':
                    952:                        yylval.dbl = strtod(backOff, &bp);
                    953:                        RSTATE(FNUM, WHITE)
                    954:                case 'x':
                    955:                case 'X':
                    956:                        NEWS(XNUM)
                    957:                case 'b':
                    958:                case 'B':
                    959:                        NEWS(BNUM)
                    960:                default:
                    961:                        bp--;
                    962:                        if (isdigit(c))
                    963:                                NEWS(ONUM)
                    964:                        yylval.val = number;
                    965:                        RSTATE(NUMBER, WHITE)
                    966:                }
                    967: 
                    968:        case LTS:       /* < seen */
                    969:                switch(c) {
                    970:                case '<':
                    971:                        RSTATE(LSHIFT, WHITE)
                    972:                case '=':
                    973:                        yylval.val = (LT|EQ);
                    974:                        break;
                    975:                default:
                    976:                        --bp;
                    977:                        yylval.val = LT;
                    978:                }
                    979:                RSTATE(COMPARISON, WHITE)               
                    980: 
                    981:        case GTS:       /* > seen */
                    982:                switch(c) {
                    983:                case '=':
                    984:                        yylval.val = (GT|EQ);
                    985:                        break;
                    986:                case '>':
                    987:                        RSTATE(RSHIFT, WHITE)
                    988:                default:
                    989:                        --bp;
                    990:                        yylval.val = GT;
                    991:                }
                    992:                RSTATE(COMPARISON, WHITE)
                    993: 
                    994:        case EQUS:      /* = seen take = or == */
                    995:                if (OPCODE == pos) {
                    996:                        --bp;
                    997:                        opIx = opLookUp(".equ");
                    998:                        return(doOp(opIx));
                    999:                }
                   1000:                if ('=' != c)   
                   1001:                        --bp;
                   1002:                yylval.val = EQ;
                   1003:                RSTATE(COMPARISON, WHITE)
                   1004: 
                   1005:        case BANGS:     /* ! seen */
                   1006:                if ('=' == c) {
                   1007:                        yylval.val = (GT|LT);
                   1008:                        RSTATE(COMPARISON, WHITE)
                   1009:                }
                   1010:                --bp;
                   1011:                RSTATE(BANG, WHITE)
                   1012: 
                   1013:        case INSTR:
                   1014:        case INCHAR:
                   1015:                switch(c) {
                   1016:                case 0:
                   1017:                case '\n':
                   1018:                        --bp;
                   1019:                        if (state == INSTR) {
                   1020:                                yyerror("End of line detected in string"); /**/
                   1021:                                *tp = '\0';
                   1022:                                yylval.t = token;
                   1023:                                RSTATE(TOKEN, psw)
                   1024:                        }
                   1025:                        yyerror("End of line detected in character constant");
                   1026:                        /**/
                   1027:                case '\'':
                   1028:                        if (state != INCHAR)
                   1029:                                break;
                   1030:                        *tp = '\0';
                   1031:                        if (strlen(token) != 1)
                   1032:                                yyerror("Character constant %d long",
                   1033:                                        strlen(token));
                   1034:                                /* Character constants must be one byte long. */
                   1035:                        yylval.val = token[0];
                   1036:                        RSTATE(NUMBER, psw)
                   1037:                case '"':
                   1038:                        if (state != INSTR)
                   1039:                                break;
                   1040:                        *tp = '\0';
                   1041:                        yylval.t = token;
                   1042:                        RSTATE(TOKEN, psw)
                   1043:                case '\\':
                   1044:                        pstate = state;
                   1045:                        NEWS(BSL)
                   1046:                }
                   1047:                *tp++ = c;
                   1048:                continue;
                   1049: 
                   1050:        case BSL:       /* back slash */
                   1051:                switch(c) {
                   1052:                case 0:
                   1053:                case '\n':
                   1054:                        --bp;
                   1055:                        yyerror("End of line after backslash");
                   1056:                        /**/
                   1057:                        break;
                   1058:                case 'n':
                   1059:                        *tp++ = '\n'; break;
                   1060:                case 'r':
                   1061:                        *tp++ = '\r'; break;
                   1062:                case 't':
                   1063:                        *tp++ = '\t'; break;
                   1064:                case 'b':
                   1065:                        *tp++ = '\b'; break;
                   1066:                case 'f':
                   1067:                        *tp++ = '\f'; break;
                   1068:                default:
                   1069:                        if ((c >= '0') && (c <= '7')) {
                   1070:                                number = 0;
                   1071:                                bp--;
                   1072:                                NEWS(BSLDIG)
                   1073:                        }
                   1074:                        *tp++ = c;
                   1075:                }
                   1076:                NEWS(pstate)
                   1077: 
                   1078:        case BSLDIG:    /* accumulate octal number */
                   1079:                if ((c >= '0') && (c <= '7')) {
                   1080:                        number *= 8;
                   1081:                        number += c - '0';
                   1082:                        continue;
                   1083:                }
                   1084:                if (number > 255) {
                   1085:                        yyerror("Octal number %ld truncated to char", number);
                   1086:                        /* An octal number in a string was too big. */
                   1087:                        number &= 255;
                   1088:                }
                   1089:                if (!number) {
                   1090:                        yyerror("Cannot insert \\0 in string");
                   1091:                        /* NUL (\e0) terminates strings.
                   1092:                         * Instead of
                   1093:                         * .DM
                   1094:                         *      .byte   "hello\en\e0"
                   1095:                         * .DE
                   1096:                         * use:
                   1097:                         * .DM
                   1098:                         *      .byte   "hello\en", 0
                   1099:                         * .DE */
                   1100:                }
                   1101:                *tp++ = number;
                   1102:                bp--;
                   1103:                NEWS(pstate)
                   1104: 
                   1105:        case ENDLINE:
                   1106:                RSTATE(NL, INITIAL)
                   1107:        }
                   1108:     }
                   1109: }

unix.superglobalmegacorp.com

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