1File: CEXPR.C Page 1 1 /* 2 Copyright 1982 3 Alcyon Corporation 4 8716 Production Ave. 5 San Diego, Ca. 92121 6 */ 7 8 #include "preproc.h" 9 10 #define OPPRI 077 11 #define OPBIN 0100 12 #define STKLEN 64 13 int oprstk[STKLEN]; /*operator stack*/ 14 int opnstk[STKLEN]; /*operand stack*/ 15 int pristk[STKLEN]; /*operator priority stack*/ 16 int *oprptr; /*pointer to operator stack*/ 17 int *opnptr; /*pointer to operand stack*/ 18 int *priptr; /*pointer to priority stack*/ 19 int cvalue; 20 21 int opinfo[] { 22 0, /*EOF=0*/ 23 16|OPBIN, /*SUB=1*/ 24 16|OPBIN, /*ADD=2*/ 25 20, /*NOT=3*/ 26 20, /*NEG=4*/ 27 22, /*LPAREN=5*/ 28 2, /*RPAREN=6*/ 29 6|OPBIN, /*QMARK=7*/ 30 6|OPBIN, /*COLON=8*/ 31 8|OPBIN, /*OR=9*/ 32 10|OPBIN, /*AND=10*/ 33 8|OPBIN, /*XOR=11*/ 34 12|OPBIN, /*EQUAL=12*/ 35 12|OPBIN, /*NEQUAL=13*/ 36 14|OPBIN, /*LESS=14*/ 37 14|OPBIN, /*LSEQUAL=15*/ 38 14|OPBIN, /*GREAT=16*/ 39 14|OPBIN, /*GREQUAL=17*/ 40 4|OPBIN, /*LSHIFT=18*/ 41 4|OPBIN, /*RSHIFT=19*/ 42 18|OPBIN, /*MULT=20*/ 43 18|OPBIN, /*DIV=21*/ 44 18|OPBIN, /*MOD=22*/ 45 20, /*COMPL=23*/ 46 }; 47 48 /* cexpr - constant expression evaluation*/ 49 /* Does priority-driven operator/operand stack evaluation of*/ 50 /* constant expressions.*/ 51 cexpr() /* returns constant evaluated*/ 52 { 53 register int lop, type; 54 55 oprptr = &oprstk[0]; 56 opnptr = &opnstk[0]; 57 priptr = &pristk[0]; 58 *priptr = 0; 59 lop = -1; 1File: CEXPR.C Page 2 60 while(1) { 61 switch( type = getctok() ) { 62 63 case CONST: 64 if( !lop ) /*last was not operator*/ 65 goto syntax; 66 if( opnptr >= &opnstk[STKLEN] ) { 67 error("expression stack overflow"); 68 cexit(); 69 } 70 lop = FALSE; 71 *++opnptr = cvalue; 72 continue; 73 74 case SUB: 75 if( lop ) 76 type = NEG; /*unary minus*/ 77 break; 78 79 case ADD: 80 if( lop ) 81 continue; /*ignore unary +*/ 82 break; 83 84 case COMPL: 85 case LPAREN: 86 case NOT: 87 if( !lop ) 88 goto syntax; 89 break; 90 91 case RPAREN: 92 if( lop ) 93 goto syntax; 94 lop = FALSE; 95 if( !stkop(type) ) 96 goto syntax; 97 continue; 98 99 case NEWL: 100 case EOF: 101 if( lop || !stkop(EOF) || opnptr != &opnstk[1] ) 102 goto syntax; 103 type = opnstk[1]; 104 putback('\n'); 105 return(type); 106 107 default: 108 if( lop || type > LASTOP ) 109 goto syntax; 110 break; 111 } 112 lop = TRUE; 113 if( !stkop(type) ) 114 goto syntax; 115 } 116 syntax: 117 error("expression syntax"); 118 if( type == NEWL ) 1File: CEXPR.C Page 3 119 putback('\n'); 120 return(0); 121 } 122 123 /* getctok - get a constant expression token*/ 124 /* Handles conversion of quoted character strings and numbers.*/ 125 getctok() 126 { 127 register int type, c, count; 128 register char *p; 129 char token[TOKSIZE]; 130 131 while( 1 ) { 132 switch( type = getntok(token) ) { 133 134 case DIGIT: 135 cvalue = const(token); 136 return(CONST); 137 138 case SQUOTE: 139 for( cvalue = 0, p = &token[1], count = 2; --count >= 0; ) { 140 if( (c= *p++) == '\'' ) 141 break; 142 if( c == '\\' ) { 143 if( *p >= '0' && *p <= '7' ) { 144 for( c = 0; *p >= '0' && *p <= '7'; ) 145 c = (c<<3) + (*p++ - '0'); 146 } 147 else switch( c = *p++ ) { 148 149 case 'n': 150 c = '\n'; 151 break; 152 153 case 't': 154 c = '\t'; 155 break; 156 157 case 'b': 158 c = '\b'; 159 break; 160 161 case 'r': 162 c = '\r'; 163 break; 164 165 case 'f': 166 c = '\f'; 167 break; 168 } 169 } 170 cvalue = (cvalue<<8) | c; 171 } 172 return(CONST); 173 174 case ALPHA: 175 if( p = lookup(token) ) 176 expand(p); 177 else 1File: CEXPR.C Page 4 178 return(ALPHA); 179 break; 180 181 default: 182 return(type); 183 } 184 } 185 } 186 187 /* stkop - stack an operator on the operand stack*/ 188 /* Unstack all operators of lower priority, evaluating them as*/ 189 /* they are unstacked.*/ 190 stkop(opr) /* returns 1 if ok, 0 otherwise*/ 191 int opr; /* operator to stack*/ 192 { 193 register int i, j, op1, op2, pri; 194 195 for( pri = opinfo[opr]&OPPRI; pri < *priptr; ) { 196 if( *oprptr == LPAREN ) { 197 if( opr == RPAREN ) { 198 oprptr--; 199 priptr--; 200 return(1); 201 } 202 break; 203 } 204 op1 = *opnptr; 205 if( (i=opinfo[*oprptr]) & OPBIN ) { 206 op2 = op1; 207 op1 = *--opnptr; 208 } 209 switch(*oprptr) { /*operator*/ 210 211 case ADD: 212 op1 =+ op2; 213 break; 214 215 case SUB: 216 op1 =- op2; 217 break; 218 219 case COLON: 220 priptr--; 221 if( *--oprptr != QMARK ) 222 return(0); 223 op1 = (*--opnptr ? op1 : op2); 224 break; 225 226 case QMARK: 227 return(0); 228 229 case XOR: 230 op1 =^ op2; 231 break; 232 233 case OR: 234 op1 =| op2; 235 break; 236 1File: CEXPR.C Page 5 237 case AND: 238 op1 =& op2; 239 break; 240 241 case EQUAL: 242 op1 = (op1 == op2); 243 break; 244 245 case NEQUAL: 246 op1 = (op1 != op2); 247 break; 248 249 case LESS: 250 op1 = (op1 < op2); 251 break; 252 253 case LSEQUAL: 254 op1 = (op1 <= op2); 255 break; 256 257 case GREAT: 258 op1 = (op1 > op2); 259 break; 260 261 case GREQUAL: 262 op1 = (op1 >= op2); 263 break; 264 265 case LSHIFT: 266 op1 = (op1 << op2); 267 break; 268 269 case RSHIFT: 270 op1 = (op1 >> op2); 271 break; 272 273 case NEG: 274 op1 = -op1; 275 break; 276 277 case NOT: 278 op1 = !op1; 279 break; 280 281 case COMPL: 282 op1 = ~ op1; 283 break; 284 285 case MULT: 286 op1 =* op2; 287 break; 288 289 case DIV: 290 op1 =/ op2; 291 break; 292 293 case MOD: 294 op1 =% op2; 295 break; 1File: CEXPR.C Page 6 296 297 } 298 *opnptr = op1; 299 priptr--; 300 oprptr--; 301 } 302 if( priptr >= &pristk[STKLEN-1] ) { 303 error("expression operator stack overflow"); 304 cexit(); 305 } 306 *++oprptr = opr; /*operator value*/ 307 *++priptr = pri; /*operator priority*/ 308 return(1); 309 } 310 311 #define toupper(c) ((c) & ~32) 312 /* const - alpha to int conversion, handles octal and hexidecimal*/ 313 /* Uses Horner's method to evaluate number.*/ 314 const(str) /* returns number evaluated*/ 315 char *str; /* pointer to string to convert*/ 316 { 317 register int c, ch, i, radix; 318 319 i = 0; 320 radix = 10; 321 if( *str == '0' ) { 322 radix = 8; 323 if( *++str == 'x' || *str == 'X' ) { 324 radix = 16; 325 str++; 326 } 327 } 328 while( c = *str++ ) { 329 if( (ch=toupper(c)) >= 'A' && ch <= 'F' ) 330 c = ch - ('A'-10); 331 else if( c >= '0' && c <= '9' ) 332 c =- '0'; 333 else 334 break; 335 if( c >= radix ) 336 break; 337 i = i*radix + c; 338 } 339 return(i); 340 }