Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 68K/1.0X SOURCES/v103/cpp/cexpr.c
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

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);
}