|
|
1.1 ! root 1: # include <ingres.h> ! 2: # include <sccs.h> ! 3: ! 4: SCCSID(@(#)expr.c 7.1 2/5/81) ! 5: ! 6: ! 7: ! 8: /* ! 9: ** EXPR -- evaluate expression ! 10: ** ! 11: ** This module evaluates an expression in somewhat standard ! 12: ** infix notation. Several restrictions apply. There are ! 13: ** no variables, since this can be simulated with the macro ! 14: ** processor. No numeric overflow is checked. There may be ! 15: ** no spaces, tabs, or newlines in the expression. ! 16: ** ! 17: ** The text of the expression is read from 'macgetch', so ! 18: ** that must be initialized before calling this routine. ! 19: ** ! 20: ** Operators accepted are + - * / < > >= <= = != % ( ) ! 21: ** & |. ! 22: ** Operands may be signed integers. ! 23: ** Standard precedence applies. ! 24: ** ! 25: ** An expression can be viewed as a sequence of operands, ! 26: ** and operators. If the terminator is considered to be ! 27: ** an operator, then the sequence must be composed ! 28: ** of n matched pairs of operators and operands. NOT and ! 29: ** Negation are considered to be part of the operand and ! 30: ** are treated as such. Thus to evaluate an expression, ! 31: ** n pairs are read until the terminator is found as the ! 32: ** last operator. ! 33: ** ! 34: ** Parameters: ! 35: ** none ! 36: ** ! 37: ** Returns: ! 38: ** value of the expression. Undetermined value ! 39: ** on error. ! 40: ** ! 41: ** Side Effects: ! 42: ** Macro processing can occur. ! 43: ** ! 44: ** Trace Flags: ! 45: ** none ! 46: */ ! 47: ! 48: ! 49: ! 50: # undef STACKSIZE ! 51: # define STACKSIZE 50 ! 52: # define RIGHTP 21 ! 53: # define END 22 ! 54: # define SEPERATOR 0 ! 55: # define OR 1 ! 56: # define AND 2 ! 57: # define EQUALS 3 ! 58: # define NEQ 4 ! 59: # define LESS 5 ! 60: # define LEQ 6 ! 61: # define GREATER 7 ! 62: # define GEQ 8 ! 63: # define ADD 9 ! 64: # define SUBTRACT 10 ! 65: # define MULTIPLY 11 ! 66: # define DIVIDE 12 ! 67: # define MOD 13 ! 68: ! 69: ! 70: int ExprPrec[] = /* Precedence table */ ! 71: { ! 72: 0, /* filler */ ! 73: 1, /* 1 -- OR */ ! 74: 2, /* 2 -- AND */ ! 75: 3, /* 3 -- EQUALS */ ! 76: 3, /* 4 -- NEQ */ ! 77: 4, /* 5 -- LESS */ ! 78: 4, /* 6 -- LEQ */ ! 79: 4, /* 7 -- GREATER */ ! 80: 4, /* 8 -- GEQ */ ! 81: 5, /* 9 -- ADD */ ! 82: 5, /* 10 -- SUBTRACT */ ! 83: 6, /* 11 -- MULTIPLY */ ! 84: 6, /* 12 -- DIVIDE */ ! 85: 6 /* 13 -- MOD */ ! 86: }; ! 87: ! 88: ! 89: int ExprNstack[STACKSIZE]; ! 90: int *ExprNptr; ! 91: int ExprOstack[STACKSIZE]; ! 92: int *ExprOptr; ! 93: int ExprError; ! 94: char ExprPeek; ! 95: ! 96: ! 97: ! 98: ! 99: ! 100: ! 101: ! 102: ! 103: ! 104: ! 105: ! 106: expr() ! 107: { ! 108: ExprNptr = ExprNstack; ! 109: ExprOptr = ExprOstack; ! 110: ExprError = FALSE; ! 111: ExprPeek = -1; ! 112: return(valof(END)); ! 113: } ! 114: /* ! 115: ** VALOF -- compute value of expression ! 116: ** ! 117: ** This is the real expression processor. It handles sequencing ! 118: ** and precedence. ! 119: ** ! 120: ** Parameters: ! 121: ** terminator -- the symbol which should terminate ! 122: ** the expression. ! 123: ** ! 124: ** Returns: ! 125: ** The value of the expression. ! 126: ** ! 127: ** Side Effects: ! 128: ** Gobbles input. ! 129: ** ! 130: ** Requires: ! 131: ** exprfind -- to read operands. ! 132: ** opfind -- to read operators. ! 133: ** exp_op -- to perform operations. ! 134: ** ! 135: ** Called By: ! 136: ** expr ! 137: ** ! 138: ** Diagnostics: ! 139: ** Extra Parenthesis found: assumed typo ! 140: ** An unmatched right parenthesis was read. ! 141: ** It was thrown away. ! 142: ** Insufficient parenthesis found: assumed zero. ! 143: ** An unmatched left parenthesis was left ! 144: ** in the operator stack at the end of the ! 145: ** expression. The value zero was taken ! 146: ** for the expression. ! 147: ** ! 148: ** Syserrs: ! 149: ** none ! 150: */ ! 151: ! 152: valof(terminator) ! 153: int terminator; ! 154: { ! 155: register int number; ! 156: register int operator; ! 157: ! 158: pushop(SEPERATOR); /* initialize the stack */ ! 159: ! 160: for(;;) ! 161: { ! 162: number = exprfind(); ! 163: if (ExprError) ! 164: return(0); ! 165: operator = opfind(); ! 166: if (ExprError) ! 167: return(0); ! 168: ! 169: if (operator == RIGHTP || operator == END) ! 170: break; ! 171: ! 172: /* Do all previous operations with a higher precedence */ ! 173: while (ExprPrec[operator] <= ExprPrec[ExprOptr[-1]]) ! 174: number = exp_op(popop(), popnum(), number); ! 175: pushop(operator); ! 176: pushnum(number); ! 177: } ! 178: if (operator != terminator) /* ExprError in operators */ ! 179: if (operator == RIGHTP) ! 180: printf("Extra parenthesis found: assumed typo.\n"); ! 181: else ! 182: { ! 183: ExprError = TRUE; ! 184: printf("Insufficient parenthesis found: Assumed zero.\n"); ! 185: return(0); ! 186: } ! 187: /* Empty stack for this call of valof */ ! 188: while ((operator = popop()) != SEPERATOR) ! 189: number = exp_op(operator, popnum(), number); ! 190: ! 191: return(number); ! 192: } ! 193: /* ! 194: ** EXPRFIND -- find and chomp operand ! 195: ** ! 196: ** This routine reads the next operand. It generally just ! 197: ** reads numbers, except it also knows about unary operators ! 198: ** ! and - (where it calls itself recursively), and paren- ! 199: ** theses (where it calls valof recursively). ! 200: ** ! 201: ** Parameters: ! 202: ** none ! 203: ** ! 204: ** Returns: ! 205: ** value of operand. ! 206: ** ! 207: ** Side Effects: ! 208: ** Gobbles input. ! 209: ** ! 210: ** Requires: ! 211: ** numberget -- to read numbers. ! 212: ** exprgch. ! 213: ** ! 214: ** Called By: ! 215: ** valof ! 216: ** exprfind (recursively) ! 217: ** ! 218: ** Trace Flags: ! 219: ** none ! 220: ** ! 221: ** Diagnostics: ! 222: ** Expression expected: end of expression found. ! 223: ** Nothing was found. Zero is returned. ! 224: ** Expression expected: %c found; assumed zero. ! 225: ** A syntax error -- nothing was found ! 226: ** which was acceptable. ! 227: */ ! 228: ! 229: ! 230: ! 231: exprfind() ! 232: { ! 233: register int result; ! 234: register int c; ! 235: ! 236: c = exprgch(); ! 237: ! 238: switch(c) ! 239: { ! 240: ! 241: case '0': ! 242: case '1': ! 243: case '2': ! 244: case '3': ! 245: case '4': ! 246: case '5': ! 247: case '6': ! 248: case '7': ! 249: case '8': ! 250: case '9': ! 251: return(numberget(c)); ! 252: ! 253: case '!': ! 254: result = exprfind(); ! 255: return(ExprError ? 0 : (result <= 0)); ! 256: ! 257: case '-': ! 258: result = exprfind(); ! 259: return(ExprError ? 0 : -result); ! 260: ! 261: case '(': ! 262: return(valof(RIGHTP)); ! 263: ! 264: case ' ': ! 265: case '\n': ! 266: case '/t': ! 267: case '\0': ! 268: printf("Expression expected: end of expression found.\n"); ! 269: ExprError = TRUE; ! 270: return(0); ! 271: ! 272: default: ! 273: printf("Expression expected; '%c' found: Assumed zero.\n", c); ! 274: ExprError = TRUE; ! 275: return(0); ! 276: } ! 277: } ! 278: /* ! 279: ** OPFIND -- find and translate operator ! 280: ** ! 281: ** This reads the next operator from the input stream and ! 282: ** returns the internal code for it. ! 283: ** ! 284: ** Parameters: ! 285: ** none ! 286: ** ! 287: ** Returns: ! 288: ** The code for the next operator. ! 289: ** Zero on error. ! 290: ** ! 291: ** Side Effects: ! 292: ** Gobbles input. ! 293: ** ! 294: ** Requires: ! 295: ** exprgch. ! 296: ** ! 297: ** Called By: ! 298: ** valof ! 299: ** ! 300: ** Trace Flags: ! 301: ** none ! 302: ** ! 303: ** Diagnostics: ! 304: ** Operator expected: '%c' found. ! 305: ** Gibberish in input. ! 306: */ ! 307: ! 308: opfind() ! 309: { ! 310: register int c; ! 311: ! 312: c = exprgch(); ! 313: ! 314: switch(c) ! 315: { ! 316: ! 317: case '/': ! 318: return(DIVIDE); ! 319: ! 320: case '=': ! 321: return(EQUALS); ! 322: ! 323: case '&': ! 324: return(AND); ! 325: ! 326: case '|': ! 327: return(OR); ! 328: ! 329: case '+': ! 330: return(ADD); ! 331: ! 332: case '-': ! 333: return(SUBTRACT); ! 334: ! 335: case '*': ! 336: return(MULTIPLY); ! 337: ! 338: case '<': ! 339: c = exprgch(); ! 340: if (c == '=') ! 341: { ! 342: return(LEQ); ! 343: } ! 344: ExprPeek = c; ! 345: return(LESS); ! 346: ! 347: case '>': ! 348: c = exprgch(); ! 349: if (c == '=') ! 350: { ! 351: return(GEQ); ! 352: } ! 353: ExprPeek = c; ! 354: return(GREATER); ! 355: ! 356: case '%': ! 357: return(MOD); ! 358: ! 359: case '!': ! 360: c = exprgch(); ! 361: if (c == '=') ! 362: { ! 363: return(NEQ); ! 364: } ! 365: else ! 366: { ! 367: printf("Operator expected: '!%c' found.\n", c); ! 368: ExprError = TRUE; ! 369: return(0); ! 370: } ! 371: ! 372: case ')': ! 373: return(RIGHTP); ! 374: ! 375: case ' ': ! 376: case '\t': ! 377: case '\n': ! 378: case '\0': ! 379: return(END); ! 380: ! 381: default: ! 382: printf("Operator expected: '%c' found.\n", c); ! 383: ExprError = TRUE; ! 384: return(0); ! 385: ! 386: } ! 387: } ! 388: /* ! 389: ** EXP_OP -- perform operation ! 390: ** ! 391: ** Performs an operation between two values. ! 392: ** ! 393: ** Parameters: ! 394: ** op -- the operation to perform. ! 395: ** lv -- the left operand. ! 396: ** rv -- the right operand. ! 397: ** ! 398: ** Returns: ! 399: ** The value of the operation. ! 400: ** ! 401: ** Side Effects: ! 402: ** none ! 403: ** ! 404: ** Requires: ! 405: ** none ! 406: ** ! 407: ** Called By: ! 408: ** valof. ! 409: ** ! 410: ** Trace Flags: ! 411: ** none ! 412: ** ! 413: ** Diagnostics: ! 414: ** none ! 415: */ ! 416: ! 417: exp_op(op, lv, rv) ! 418: int op; ! 419: int lv; ! 420: int rv; ! 421: { ! 422: switch(op) ! 423: { ! 424: ! 425: case OR: ! 426: return((lv > 0) || (rv > 0)); ! 427: ! 428: case AND: ! 429: return((lv > 0) && (rv > 0)); ! 430: ! 431: case EQUALS: ! 432: return(lv == rv); ! 433: ! 434: case NEQ: ! 435: return(lv != rv); ! 436: ! 437: case LESS: ! 438: return(lv < rv); ! 439: ! 440: case LEQ: ! 441: return(lv <= rv); ! 442: ! 443: case GREATER: ! 444: return(lv > rv); ! 445: ! 446: case GEQ: ! 447: return(lv >= rv); ! 448: ! 449: case ADD: ! 450: return(lv + rv); ! 451: ! 452: case SUBTRACT: ! 453: return(lv - rv); ! 454: ! 455: case MULTIPLY: ! 456: return(lv * rv); ! 457: ! 458: case DIVIDE: ! 459: if (rv == 0) ! 460: { ! 461: printf("Divide by zero: zero assumed.\n"); ! 462: return(0); ! 463: } ! 464: else ! 465: return(lv / rv); ! 466: ! 467: case MOD: ! 468: return(lv % rv); ! 469: ! 470: default: ! 471: syserr("exp_op: bad op %d", op); ! 472: ! 473: } ! 474: } ! 475: /* ! 476: ** NUMBERGET -- read and convert a number ! 477: ** ! 478: ** Reads and converts a signed integer. ! 479: ** ! 480: ** Parameters: ! 481: ** none ! 482: ** ! 483: ** Returns: ! 484: ** The next number in the input stream. ! 485: ** ! 486: ** Side Effects: ! 487: ** Gobbles input. ! 488: ** ! 489: ** Requires: ! 490: ** exprgch. ! 491: ** ! 492: ** Called By: ! 493: ** exprfind. ! 494: */ ! 495: ! 496: numberget(cx) ! 497: char cx; ! 498: { ! 499: register int result; ! 500: register int c; ! 501: ! 502: c = cx; ! 503: ! 504: result = 0; ! 505: do ! 506: { ! 507: result = result * 10 + c - '0'; ! 508: c = exprgch(); ! 509: } while (c >= '0' && c <= '9'); ! 510: ExprPeek = c; ! 511: return(result); ! 512: } ! 513: /* ! 514: ** EXPRGCH -- expression character get ! 515: ** ! 516: ** Gets the next character from the expression input. Takes ! 517: ** a character out of ExprPeek first. Also maps spaces, tabs, ! 518: ** and newlines into zero bytes. ! 519: ** ! 520: ** Parameters: ! 521: ** none ! 522: ** ! 523: ** Returns: ! 524: ** Next character. ! 525: ** ! 526: ** Side Effects: ! 527: ** Gobbles input. ! 528: ** Clears ExprPeek if set. ! 529: ** ! 530: ** Requires: ! 531: ** ExprPeek -- the peek character. ! 532: ** macgetch -- to get the next character if ExprPeek ! 533: ** is not set. ! 534: */ ! 535: ! 536: exprgch() ! 537: { ! 538: register int c; ! 539: ! 540: c = ExprPeek; ! 541: if (c < 0) ! 542: c = macgetch(); ! 543: ExprPeek = -1; ! 544: if (c == ' ' || c == '\n' || c == '\t') ! 545: c = 0; ! 546: return (c); ! 547: } ! 548: /* ! 549: ** Stack operations. ! 550: */ ! 551: ! 552: ! 553: /* Popop returns the top of the operator stack and decrements this stack. */ ! 554: popop() ! 555: { ! 556: if (ExprOptr <= ExprOstack) ! 557: syserr("popop: underflow"); ! 558: return(*--ExprOptr); ! 559: } ! 560: ! 561: ! 562: ! 563: /* Pushop increments the stack pointer and pushes op on the stack. */ ! 564: pushop(op) ! 565: int op; ! 566: { ! 567: *ExprOptr++ = op; ! 568: } ! 569: ! 570: ! 571: ! 572: /* Popnum returns the top of the number stack and decrements the stack pointer. */ ! 573: popnum() ! 574: { ! 575: if (ExprNptr <= ExprNstack) ! 576: syserr("popnum: underflow"); ! 577: return(*--ExprNptr); ! 578: } ! 579: ! 580: ! 581: ! 582: ! 583: /* Pushnum increments the stack pointer and pushes num onto the stack */ ! 584: pushnum(num) ! 585: int num; ! 586: { ! 587: *ExprNptr++ = num; ! 588: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.