mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 08:24:18 +00:00
341 lines
8.2 KiB
C
341 lines
8.2 KiB
C
/*
|
|
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((struct symbol *)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 op1, op2, pri;
|
|
|
|
for( pri = opinfo[opr]&OPPRI; pri < *priptr; ) {
|
|
if( *oprptr == LPAREN ) {
|
|
if( opr == RPAREN ) {
|
|
oprptr--;
|
|
priptr--;
|
|
return(1);
|
|
}
|
|
break;
|
|
}
|
|
op1 = *opnptr;
|
|
if( 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);
|
|
}
|