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: }

Defined functions

boolterm defined in line 233; used 3 times
buildtokensets defined in line 165; used 1 times
combine defined in line 63; used 5 times
exprparse defined in line 215; used 4 times
factor defined in line 261; used 4 times
term defined in line 247; used 3 times
tok_to_name defined in line 485; used 4 times
yukkyexpr defined in line 304; used 3 times

Defined variables

mintab defined in line 38; used 1 times
othtab defined in line 52; used 1 times
pcntrl defined in line 371; used 1 times
pdirect defined in line 367; used 1 times
phunk defined in line 369; used 1 times
pinstr defined in line 368; used 1 times
pltab defined in line 24; used 1 times
psmall defined in line 370; used 1 times
sccsid defined in line 8; never used
tok_desc defined in line 386; used 3 times
tok_name defined in line 384; used 6 times
val defined in line 210; used 23 times

Defined struct's

Tok_Desc defined in line 379; used 8 times

Defined macros

CNTRL defined in line 377; used 8 times
DIRECT defined in line 373; used 31 times
HUNK defined in line 375; used 6 times
INSTR defined in line 374; used 3 times
SMALL defined in line 376; used 29 times
XTXRN defined in line 19; used 4 times
clobber defined in line 167; used 23 times
Last modified: 1985-06-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1950
Valid CSS Valid XHTML 1.0 Strict