/* Copyright 1982 Alcyon Corporation 8716 Production Ave. San Diego, Ca. 92121 */ #include "preproc.h" #define OPPRI 077 #define OPBIN 0100 #define STKLEN 64 int oprstk[STKLEN]; /*operator stack*/ int opnstk[STKLEN]; /*operand stack*/ int pristk[STKLEN]; /*operator priority stack*/ int *oprptr; /*pointer to operator stack*/ int *opnptr; /*pointer to operand stack*/ int *priptr; /*pointer to priority stack*/ int cvalue; int opinfo[] { 0, /*EOF=0*/ 16|OPBIN, /*SUB=1*/ 16|OPBIN, /*ADD=2*/ 20, /*NOT=3*/ 20, /*NEG=4*/ 22, /*LPAREN=5*/ 2, /*RPAREN=6*/ 6|OPBIN, /*QMARK=7*/ 6|OPBIN, /*COLON=8*/ 8|OPBIN, /*OR=9*/ 10|OPBIN, /*AND=10*/ 8|OPBIN, /*XOR=11*/ 12|OPBIN, /*EQUAL=12*/ 12|OPBIN, /*NEQUAL=13*/ 14|OPBIN, /*LESS=14*/ 14|OPBIN, /*LSEQUAL=15*/ 14|OPBIN, /*GREAT=16*/ 14|OPBIN, /*GREQUAL=17*/ 4|OPBIN, /*LSHIFT=18*/ 4|OPBIN, /*RSHIFT=19*/ 18|OPBIN, /*MULT=20*/ 18|OPBIN, /*DIV=21*/ 18|OPBIN, /*MOD=22*/ 20, /*COMPL=23*/ }; /* cexpr - constant expression evaluation*/ /* Does priority-driven operator/operand stack evaluation of*/ /* constant expressions.*/ cexpr() /* returns constant evaluated*/ { register int lop, type; oprptr = &oprstk[0]; opnptr = &opnstk[0]; priptr = &pristk[0]; *priptr = 0; lop = -1; while(1) { switch( type = getctok() ) { case CONST: if( !lop ) /*last was not operator*/ goto syntax; if( opnptr >= &opnstk[STKLEN] ) { error("expression stack overflow"); cexit(); } lop = FALSE; *++opnptr = cvalue; continue; case SUB: if( lop ) type = NEG; /*unary minus*/ break; case ADD: if( lop ) continue; /*ignore unary +*/ break; case COMPL: case LPAREN: case NOT: if( !lop ) goto syntax; break; case RPAREN: if( lop ) goto syntax; lop = FALSE; if( !stkop(type) ) goto syntax; continue; case NEWL: case EOF: if( lop || !stkop(EOF) || opnptr != &opnstk[1] ) goto syntax; type = opnstk[1]; putback('\n'); return(type); default: if( lop || type > LASTOP ) goto syntax; break; } lop = TRUE; if( !stkop(type) ) goto syntax; } syntax: error("expression syntax"); if( type == NEWL ) putback('\n'); return(0); } /* getctok - get a constant expression token*/ /* Handles conversion of quoted character strings and numbers.*/ getctok() { register int type, c, count; register char *p; char token[TOKSIZE]; while( 1 ) { switch( type = getntok(token) ) { case DIGIT: cvalue = const(token); return(CONST); case SQUOTE: for( cvalue = 0, p = &token[1], count = 2; --count >= 0; ) { if( (c= *p++) == '\'' ) break; if( c == '\\' ) { if( *p >= '0' && *p <= '7' ) { for( c = 0; *p >= '0' && *p <= '7'; ) c = (c<<3) + (*p++ - '0'); } else switch( c = *p++ ) { case 'n': c = '\n'; break; case 't': c = '\t'; break; case 'b': c = '\b'; break; case 'r': c = '\r'; break; case 'f': c = '\f'; break; } } cvalue = (cvalue<<8) | c; } return(CONST); case ALPHA: if( p = lookup(token) ) expand(p); else return(ALPHA); break; default: return(type); } } } /* stkop - stack an operator on the operand stack*/ /* Unstack all operators of lower priority, evaluating them as*/ /* they are unstacked.*/ stkop(opr) /* returns 1 if ok, 0 otherwise*/ int opr; /* operator to stack*/ { register int i, j, op1, op2, pri; for( pri = opinfo[opr]&OPPRI; pri < *priptr; ) { if( *oprptr == LPAREN ) { if( opr == RPAREN ) { oprptr--; priptr--; return(1); } break; } op1 = *opnptr; if( (i=opinfo[*oprptr]) & OPBIN ) { op2 = op1; op1 = *--opnptr; } switch(*oprptr) { /*operator*/ case ADD: op1 =+ op2; break; case SUB: op1 =- op2; break; case COLON: priptr--; if( *--oprptr != QMARK ) return(0); op1 = (*--opnptr ? op1 : op2); break; case QMARK: return(0); case XOR: op1 =^ op2; break; case OR: op1 =| op2; break; case AND: op1 =& op2; break; case EQUAL: op1 = (op1 == op2); break; case NEQUAL: op1 = (op1 != op2); break; case LESS: op1 = (op1 < op2); break; case LSEQUAL: op1 = (op1 <= op2); break; case GREAT: op1 = (op1 > op2); break; case GREQUAL: op1 = (op1 >= op2); break; case LSHIFT: op1 = (op1 << op2); break; case RSHIFT: op1 = (op1 >> op2); break; case NEG: op1 = -op1; break; case NOT: op1 = !op1; break; case COMPL: op1 = ~ op1; break; case MULT: op1 =* op2; break; case DIV: op1 =/ op2; break; case MOD: op1 =% op2; break; } *opnptr = op1; priptr--; oprptr--; } if( priptr >= &pristk[STKLEN-1] ) { error("expression operator stack overflow"); cexit(); } *++oprptr = opr; /*operator value*/ *++priptr = pri; /*operator priority*/ return(1); } #define toupper(c) ((c) & ~32) /* const - alpha to int conversion, handles octal and hexidecimal*/ /* Uses Horner's method to evaluate number.*/ const(str) /* returns number evaluated*/ char *str; /* pointer to string to convert*/ { register int c, ch, i, radix; i = 0; radix = 10; if( *str == '0' ) { radix = 8; if( *++str == 'x' || *str == 'X' ) { radix = 16; str++; } } while( c = *str++ ) { if( (ch=toupper(c)) >= 'A' && ch <= 'F' ) c = ch - ('A'-10); else if( c >= '0' && c <= '9' ) c =- '0'; else break; if( c >= radix ) break; i = i*radix + c; } return(i); }