Annotation of 43BSD/bin/as/asexpr.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: static char sccsid[] = "@(#)asexpr.c   5.2 (Berkeley) 6/19/85";
        !             9: #endif not lint
        !            10: 
        !            11: #include <stdio.h>
        !            12: #include "as.h"
        !            13: #include "asscan.h"
        !            14: #include "asexpr.h"
        !            15: 
        !            16: /*
        !            17:  * Tables for combination of operands.
        !            18:  */
        !            19: #define        XTXRN   5<<1            /* indexes last row/column when right shifted */
        !            20: 
        !            21: /*
        !            22:  *     table for +
        !            23:  */
        !            24: readonly char pltab[6][6] = {
        !            25: /*             UND     ABS     TXT     DAT     BSS     EXT */
        !            26: 
        !            27: /*UND*/                XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
        !            28: /*ABS*/                XUNDEF, XABS,   XTEXT,  XDATA,  XBSS,   XXTRN,
        !            29: /*TXT*/                XUNDEF, XTEXT,  ERR,    ERR,    ERR,    ERR,
        !            30: /*DAT*/                XUNDEF, XDATA,  ERR,    ERR,    ERR,    ERR,
        !            31: /*BSS*/                XUNDEF, XBSS,   ERR,    ERR,    ERR,    ERR,
        !            32: /*EXT*/                XUNDEF, XXTRN,  ERR,    ERR,    ERR,    ERR,
        !            33: };
        !            34: 
        !            35: /*
        !            36:  *     table for -
        !            37:  */
        !            38: readonly char mintab[6][6] = {
        !            39: /*             UND     ABS     TXT     DAT     BSS     EXT */
        !            40: 
        !            41: /*UND*/                XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
        !            42: /*ABS*/                XUNDEF, XABS,   ERR,    ERR,    ERR,    ERR,
        !            43: /*TXT*/                XUNDEF, XTEXT,  XABS,   ERR,    ERR,    ERR,
        !            44: /*DAT*/                XUNDEF, XDATA,  ERR,    XABS,   ERR,    ERR,
        !            45: /*BSS*/                XUNDEF, XBSS,   ERR,    ERR,    XABS,   ERR,
        !            46: /*EXT*/                XUNDEF, XXTRN,  ERR,    ERR,    ERR,    ERR,
        !            47: };
        !            48: 
        !            49: /* 
        !            50:  *     table for other operators
        !            51:  */
        !            52: readonly char othtab[6][6] = {
        !            53: /*             UND     ABS     TXT     DAT     BSS     EXT */
        !            54: 
        !            55: /*UND*/                XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF, XUNDEF,
        !            56: /*ABS*/                XUNDEF, XABS,   ERR,    ERR,    ERR,    ERR,
        !            57: /*TXT*/                XUNDEF, ERR,    ERR,    ERR,    ERR,    ERR,
        !            58: /*DAT*/                XUNDEF, ERR,    ERR,    ERR,    ERR,    ERR,
        !            59: /*BSS*/                XUNDEF, ERR,    ERR,    ERR,    ERR,    ERR,
        !            60: /*EXT*/                XUNDEF, ERR,    ERR,    ERR,    ERR,    ERR,
        !            61: };
        !            62: 
        !            63: struct exp *combine(op, exp1, exp2)
        !            64:        reg struct exp *exp1, *exp2;
        !            65: {
        !            66:        reg     e1_type, e2_type;
        !            67:        reg     back_type;
        !            68:        char    *btype = "The assembler can only do arithmetic on 1,2, or 4 byte integers";
        !            69: 
        !            70:        lastnam=0;                      /* kludge for jxxx instructions */
        !            71: 
        !            72:        e1_type = exp1->e_xtype&XTYPE;
        !            73:        e2_type = exp2->e_xtype&XTYPE;
        !            74: 
        !            75:        if (exp1->e_xtype==XXTRN+XUNDEF)
        !            76:                e1_type = XTXRN;
        !            77:        if (exp2->e_xtype==XXTRN+XUNDEF)
        !            78:                e2_type = XTXRN;
        !            79:        if (passno==1)
        !            80:                if (exp1->e_xloc!=exp2->e_xloc && e1_type==e2_type)
        !            81:                        e1_type = e2_type = XTXRN;      /* error on != loc ctrs */
        !            82:        e1_type >>= 1;          /*dispose of the external (XXTRN) bit*/
        !            83:        e2_type >>= 1;
        !            84: 
        !            85:        switch(exp1->e_number.num_tag){
        !            86:        case TYPB:
        !            87:        case TYPW:
        !            88:        case TYPL:
        !            89:                break;
        !            90:        default:
        !            91:                yyerror(btype);
        !            92:                return(exp1);
        !            93:        }
        !            94:        switch(exp2->e_number.num_tag){
        !            95:        case TYPB:
        !            96:        case TYPW:
        !            97:        case TYPL:
        !            98:                break;
        !            99:        default:
        !           100:                yyerror(btype);
        !           101:                return(exp1);
        !           102:        }
        !           103:        switch (op){
        !           104:        case PLUS:
        !           105:                exp1->e_xvalue += exp2->e_xvalue;
        !           106:                back_type = pltab[e1_type][e2_type];
        !           107:                break;
        !           108:        case MINUS:
        !           109:                exp1->e_xvalue -= exp2->e_xvalue;
        !           110:                back_type = mintab[e1_type][e2_type];
        !           111:                break;
        !           112:        case IOR:
        !           113:                exp1->e_xvalue |= exp2->e_xvalue;
        !           114:                goto comm;
        !           115:        case XOR:
        !           116:                exp1->e_xvalue ^= exp2->e_xvalue;
        !           117:                goto comm;
        !           118:        case AND:
        !           119:                exp1->e_xvalue &= exp2->e_xvalue;
        !           120:                goto comm;
        !           121:        case ORNOT:
        !           122:                exp1->e_xvalue |= ~exp2->e_xvalue;
        !           123:                goto comm;
        !           124:        case LSH:
        !           125:                exp1->e_xvalue <<= exp2->e_xvalue;
        !           126:                goto comm;
        !           127:        case RSH:
        !           128:                exp1->e_xvalue >>= exp2->e_xvalue;
        !           129:                goto comm;
        !           130:        case TILDE:
        !           131:                exp1->e_xvalue |= ~ exp2->e_xvalue;
        !           132:                goto comm;
        !           133:        case MUL:
        !           134:                exp1->e_xvalue *= exp2->e_xvalue;
        !           135:                goto comm;
        !           136:        case DIV:
        !           137:                if (exp2->e_xvalue == 0)
        !           138:                        yyerror("Divide check");
        !           139:                else
        !           140:                        exp1->e_xvalue /= exp2->e_xvalue;
        !           141:                goto comm;
        !           142:        case REGOP:
        !           143:                if (exp2->e_xvalue == 0)
        !           144:                        yyerror("Divide check (modulo)");
        !           145:                else
        !           146:                        exp1->e_xvalue %= exp2->e_xvalue;
        !           147:                goto comm;
        !           148:        
        !           149:        comm:
        !           150:                back_type = othtab[e1_type][e2_type];
        !           151:                break;
        !           152:        default:
        !           153:                yyerror("Internal error: unknown operator");
        !           154:        }
        !           155: 
        !           156:        if (e2_type==(XTXRN>>1))
        !           157:                exp1->e_xname = exp2->e_xname;
        !           158:        exp1->e_xtype = back_type | (
        !           159:                        (exp1->e_xtype|exp2->e_xtype) & (XFORW|XXTRN) );
        !           160:        if (back_type==ERR)
        !           161:                yyerror("Relocation error");
        !           162:        return(exp1);
        !           163: }
        !           164: 
        !           165: buildtokensets()
        !           166: {
        !           167: #define clobber(val, set) tokensets[(val)] |= (set)
        !           168: 
        !           169:        clobber(SEMI,   LINSTBEGIN);
        !           170:        clobber(NL,     LINSTBEGIN);
        !           171:        clobber(INT,    LINSTBEGIN);
        !           172: 
        !           173:        clobber(NAME,   YUKKYEXPRBEG + LINSTBEGIN);
        !           174:        clobber(INSTn,  YUKKYEXPRBEG);
        !           175:        clobber(INST0,  YUKKYEXPRBEG);
        !           176:        clobber(REG,    YUKKYEXPRBEG);
        !           177:        clobber(BFINT,  YUKKYEXPRBEG);
        !           178: 
        !           179:        clobber(INT,    SAFEEXPRBEG);
        !           180:        clobber(BIGNUM, SAFEEXPRBEG);
        !           181: 
        !           182:        clobber(PLUS,   ADDOPS);
        !           183:        clobber(MINUS,  ADDOPS + EBEGOPS);
        !           184: 
        !           185:        clobber(LP,     EBEGOPS);
        !           186: 
        !           187:        clobber(IOR,    BOOLOPS);
        !           188:        clobber(XOR,    BOOLOPS);
        !           189:        clobber(AND,    BOOLOPS);
        !           190:        clobber(ORNOT,  BOOLOPS);
        !           191: 
        !           192:        clobber(TILDE,  MULOPS + EBEGOPS);
        !           193:        clobber(LSH,    MULOPS);
        !           194:        clobber(RSH,    MULOPS);
        !           195:        clobber(MUL,    MULOPS);
        !           196:        clobber(DIV,    MULOPS);
        !           197:        clobber(REGOP,  MULOPS);        /* % */
        !           198: 
        !           199: }
        !           200: 
        !           201: /*
        !           202:  *     We keep the current token class in this global variable, so 
        !           203:  *     the recursive descent expression analyzers can talk amongst
        !           204:  *     themselves, and so that we may use the macros shift and shift over
        !           205:  */
        !           206: 
        !           207: extern int     yylval;         /*the value of the lexical value*/
        !           208: extern struct  exp     *xp;    /*the next free expression slot*/
        !           209: 
        !           210: static inttoktype      val;
        !           211: 
        !           212: /*
        !           213:  *     return the value the read head is sitting on
        !           214:  */
        !           215: inttoktype exprparse(inval, backexpr)
        !           216:        inttoktype      inval;
        !           217:        struct  exp **backexpr;
        !           218: {
        !           219:        reg     struct exp *lexpr;
        !           220:        inttoktype      op;
        !           221: 
        !           222:        val = inval;
        !           223:        lexpr = boolterm();
        !           224:        while (INTOKSET(val, ADDOPS)){
        !           225:                op = val;
        !           226:                shift;
        !           227:                lexpr = combine(op, lexpr, boolterm());
        !           228:        }
        !           229:        *backexpr = lexpr;
        !           230:        return(val);
        !           231: }
        !           232: 
        !           233: struct exp *boolterm()
        !           234: {
        !           235:        reg     struct exp *lexpr;
        !           236:        inttoktype      op;
        !           237: 
        !           238:        lexpr = term();
        !           239:        while(INTOKSET(val, BOOLOPS)){
        !           240:                op = val;
        !           241:                shift;
        !           242:                lexpr = combine(op, lexpr, term());
        !           243:        }
        !           244:        return(lexpr);
        !           245: }
        !           246: 
        !           247: struct exp *term()
        !           248: {
        !           249:        reg     struct  exp     *lexpr;
        !           250:        inttoktype      op;
        !           251: 
        !           252:        lexpr = factor();
        !           253:        while(INTOKSET(val, MULOPS)){
        !           254:                op = val;
        !           255:                shift;
        !           256:                lexpr = combine(op, lexpr, factor());
        !           257:        }
        !           258:        return(lexpr);
        !           259: }
        !           260: 
        !           261: struct exp *factor()
        !           262: {
        !           263:        struct  exp *lexpr;
        !           264:        inttoktype      op;
        !           265:        extern          int     droppedLP;      /*called exprparse after consuming an LP*/
        !           266: 
        !           267:        if (val == LP || droppedLP){
        !           268:                if (droppedLP)
        !           269:                        droppedLP = 0;
        !           270:                else
        !           271:                        shift;          /*the LP*/
        !           272:                val = exprparse(val, &lexpr);
        !           273:                if (val != RP)
        !           274:                        yyerror("right parenthesis expected");
        !           275:                else
        !           276:                        shift;
        !           277:        } else
        !           278:        if (INTOKSET(val, YUKKYEXPRBEG)){
        !           279:                lexpr = yukkyexpr(val, yylval);
        !           280:                shift;
        !           281:        }
        !           282:        else if (INTOKSET(val, SAFEEXPRBEG)){
        !           283:                lexpr = (struct exp *)yylval;
        !           284:                shift;
        !           285:        }
        !           286:        else if ( (val == TILDE) || (val == MINUS) ){
        !           287:                op = val;
        !           288:                shift;
        !           289:                lexpr = xp++;
        !           290:                lexpr->e_xtype = XABS;
        !           291:                lexpr->e_number = Znumber;
        !           292:                lexpr->e_number.num_tag = TYPL;
        !           293:                lexpr = combine(op, lexpr, factor());
        !           294:        } else {
        !           295:                yyerror("Bad expression syntax");
        !           296:                lexpr = xp++;
        !           297:                lexpr->e_xtype = XABS;
        !           298:                lexpr->e_number = Znumber;
        !           299:                lexpr->e_number.num_tag = TYPL;
        !           300:        }
        !           301:        return(lexpr);
        !           302: }
        !           303: 
        !           304: struct exp *yukkyexpr(val, np)
        !           305:        int     val;
        !           306:        reg     np;
        !           307: {
        !           308:        reg     struct exp *locxp;
        !           309:        extern  int     exprisname;     /*last factor is a name*/
        !           310:                int     off = 0;
        !           311: 
        !           312:        exprisname = 0;
        !           313:        locxp = xp++;
        !           314:        locxp->e_number = Znumber;
        !           315:        locxp->e_number.num_tag = TYPL;
        !           316: 
        !           317:        switch(val){
        !           318:        case BFINT:
        !           319:                yylval = ((struct exp *)np)->e_xvalue;
        !           320:                if (yylval < 0) {
        !           321:                        yylval = -yylval;
        !           322:                        yylval--;
        !           323:                        off = -1;
        !           324:                        if (lgensym[yylval] == 1)
        !           325:                                yyerror("Reference to undefined local label %db", yylval);
        !           326:                } else {
        !           327:                        yylval--;
        !           328:                        genref[yylval] = 1;
        !           329:                }
        !           330:                (void)sprintf(yytext, "L%d\001%d", yylval, lgensym[yylval] + off);
        !           331:                yylval = np = (int)*lookup(passno == 1);
        !           332:                lastnam = (struct symtab *)np;
        !           333:                /* FALLTHROUGH */
        !           334:        case NAME:
        !           335:                exprisname++;
        !           336:                locxp->e_xtype = ((struct symtab *)np)->s_type;
        !           337:                if (( ((struct symtab *)np)->s_type&XTYPE)==XUNDEF) { /*forward*/
        !           338:                        locxp->e_xname = (struct symtab *)np;
        !           339:                        locxp->e_xvalue = 0;
        !           340:                        if (passno==1)
        !           341:                                ((struct symtab *)np)->s_type |= XFORW;
        !           342:                } else {        /*otherwise, just get the value*/
        !           343:                        locxp->e_xvalue = ((struct symtab *)np)->s_value;
        !           344:                        locxp->e_xname = NULL;
        !           345:                }
        !           346:                break;
        !           347:        default:
        !           348:                yyerror("Internal Error in yukkyexpr");
        !           349:                /* FALLTHROUGH */
        !           350: 
        !           351:        case INSTn:
        !           352:        case INST0:
        !           353:        case REG:
        !           354:                locxp->e_xtype = XABS;
        !           355:                locxp->e_xvalue = ( (int)np) & 0xFF;
        !           356:                locxp->e_xloc = 0;
        !           357:                locxp->e_xname = NULL;
        !           358:                break;
        !           359:        }
        !           360: 
        !           361:        return(locxp);
        !           362: }
        !           363: 
        !           364: /*
        !           365:  *     Print definitions for token kinds
        !           366:  */
        !           367: static char pdirect[]  = "directive";
        !           368: static char pinstr[]   = "instruction";
        !           369: static char phunk[]    = "lexeme";
        !           370: static char psmall[]   = "small symbol";
        !           371: static char pcntrl[]   = "control token";
        !           372: 
        !           373: #define        DIRECT  pdirect
        !           374: #define        INSTR   pinstr
        !           375: #define        HUNK    phunk
        !           376: #define        SMALL   psmall
        !           377: #define        CNTRL   pcntrl
        !           378: 
        !           379: struct Tok_Desc{
        !           380:        int             tok_which;
        !           381:        char            *tok_kind;
        !           382:        char            *tok_name;
        !           383: };
        !           384: struct Tok_Desc *tok_name[LASTTOKEN - FIRSTTOKEN + 1];
        !           385: 
        !           386: struct Tok_Desc tok_desc[] = {
        !           387:        FIRSTTOKEN,     DIRECT, "first token",
        !           388: 
        !           389:        IBYTE,          DIRECT, ".byte",
        !           390:        IWORD,          DIRECT, ".word",
        !           391:        IINT,           DIRECT, ".int",
        !           392:        ILONG,          DIRECT, ".long",
        !           393:        IQUAD,          DIRECT, ".quad",
        !           394:        IOCTA,          DIRECT, ".octa",
        !           395:        IFFLOAT,        DIRECT, ".ffloat",
        !           396:        IDFLOAT,        DIRECT, ".dfloat",
        !           397:        IGFLOAT,        DIRECT, ".gfloat",
        !           398:        IHFLOAT,        DIRECT, ".hfloat",
        !           399:        IASCII,         DIRECT, ".ascii",
        !           400:        IASCIZ,         DIRECT, ".asciz",
        !           401:        IFILL,          DIRECT, ".fill",
        !           402:        ISPACE,         DIRECT, ".space",
        !           403: 
        !           404:        IDATA,          DIRECT, ".data",
        !           405:        ITEXT,          DIRECT, ".text",
        !           406:        IGLOBAL,        DIRECT, ".global",
        !           407:        IALIGN,         DIRECT, ".align",
        !           408: 
        !           409:        ISET,           DIRECT, ".set",
        !           410:        ICOMM,          DIRECT, ".comm",
        !           411:        ILCOMM,         DIRECT, ".lcomm",
        !           412:        IORG,           DIRECT, ".org",
        !           413:        ILSYM,          DIRECT, ".lsym",
        !           414: 
        !           415:        ISTAB,          DIRECT, ".stab",
        !           416:        ISTABSTR,       DIRECT, ".stabstr",
        !           417:        ISTABNONE,      DIRECT, ".stabnone",
        !           418:        ISTABDOT,       DIRECT, ".stabdot",
        !           419: 
        !           420:        IFILE,          DIRECT, ".file",
        !           421:        ILINENO,        DIRECT, ".lineno",
        !           422:        IABORT,         DIRECT, ".abort",
        !           423: 
        !           424:        IJXXX,          INSTR,  "jump pseudo",
        !           425:        INST0,          INSTR,  "0 argument inst",
        !           426:        INSTn,          INSTR,  "n argument inst",
        !           427: 
        !           428:        PARSEEOF,       CNTRL,  "parse end of file",
        !           429:        ILINESKIP,      CNTRL,  "skip lines",
        !           430:        VOID,           CNTRL,  "void",
        !           431:        SKIP,           CNTRL,  "skip",
        !           432:        NL,             CNTRL,  "new line",
        !           433:        SCANEOF,        CNTRL,  "scanner end of file",
        !           434:        BADCHAR,        CNTRL,  "bad character",
        !           435:        SH,             CNTRL,  "comment, #",
        !           436: 
        !           437:        INT,            HUNK,   "int",
        !           438:        BFINT,          HUNK,   "local label",
        !           439:        BIGNUM,         HUNK,   "big number",
        !           440:        NAME,           HUNK,   "name",
        !           441:        STRING,         HUNK,   "string",
        !           442:        REG,            HUNK,   "register specifier",
        !           443: 
        !           444:        SIZESPEC,       SMALL,  "size specifier, [BWLbwl]",
        !           445:        SIZEQUOTE,      SMALL,  "sizequote, [^']",
        !           446:        LITOP,          SMALL,  "litop",
        !           447: 
        !           448:        MP,             SMALL,  "minus parenthesis, -(",
        !           449:        REGOP,          SMALL,  "register operator, %",
        !           450: 
        !           451:        SP,             SMALL,  "space",
        !           452:        ALPH,           SMALL,  "alphabetic character, [A-Za-z_]",
        !           453:        DIG,            SMALL,  "digit character, [A-Fa-f0-9]",
        !           454: 
        !           455:        SQ,             SMALL,  "single quote, '",
        !           456:        DQ,             SMALL,  "double quote, \"",
        !           457: 
        !           458:        LSH,            SMALL,  "arithmetic left shift, <",
        !           459:        RSH,            SMALL,  "arithmetic right shift, >",
        !           460:        XOR,            SMALL,  "exclusive or, ^",
        !           461: 
        !           462:        PLUS,           SMALL,  "plus, +",
        !           463:        MINUS,          SMALL,  "minus, -",
        !           464:        MUL,            SMALL,  "multiply, *",
        !           465:        DIV,            SMALL,  "divide, /",
        !           466:        SEMI,           SMALL,  "semi colon, ;",
        !           467:        COLON,          SMALL,  "colon, :",
        !           468:        IOR,            SMALL,  "inclusive or, |",
        !           469:        AND,            SMALL,  "and, &",
        !           470: 
        !           471:        TILDE,          SMALL,  "one's complement, ~",
        !           472:        ORNOT,          SMALL,  "ornot, !",
        !           473:        CM,             SMALL,  "comma",
        !           474: 
        !           475:        LB,             SMALL,  "left bracket, [",
        !           476:        RB,             SMALL,  "right bracket, ]",
        !           477:        LP,             SMALL,  "left parenthesis, (",
        !           478:        RP,             SMALL,  "right parentheis, )",
        !           479: 
        !           480:        LASTTOKEN,      SMALL,  "last token",
        !           481: };
        !           482: /*
        !           483:  *     turn a token type into a string
        !           484:  */
        !           485: char *tok_to_name(token)
        !           486: {
        !           487:        static  int     fixed = 0;
        !           488:        static  char    buf[64];
        !           489:        static  struct  Tok_Desc        NA = {0, (char *)0, "NOT ASSIGNED"};
        !           490:                int     i;
        !           491:                char    *cp;
        !           492: 
        !           493:        if (!fixed){
        !           494:                for (i = FIRSTTOKEN; i <= LASTTOKEN; i++)
        !           495:                        tok_name[i] = &NA;
        !           496:                for (i = 0; i <= sizeof(tok_desc)/sizeof(struct Tok_Desc); i++){
        !           497:                        tok_name[tok_desc[i].tok_which] = &tok_desc[i];
        !           498:                }
        !           499:                fixed = 1;
        !           500:        }
        !           501:        if (FIRSTTOKEN <= token && token <= LASTTOKEN){
        !           502:                sprintf(buf, "%s %s", tok_name[token]->tok_kind,
        !           503:                        tok_name[token]->tok_name);
        !           504:                return(buf);
        !           505:        } else {
        !           506:                panic("Unknown token number, %d\n", token);
        !           507:                /*NOTREACHED*/
        !           508:        }
        !           509: }

unix.superglobalmegacorp.com

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