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

Defined functions

exp_op defined in line 444; used 2 times
expr defined in line 133; used 1 times
exprfind defined in line 258; used 3 times
exprgch defined in line 563; used 6 times
numberget defined in line 523; used 1 times
opfind defined in line 335; used 1 times
popnum defined in line 600; used 2 times
popop defined in line 581; used 2 times
pushnum defined in line 611; used 1 times
pushop defined in line 591; used 2 times
valof defined in line 179; used 2 times

Defined variables

ExprError defined in line 120; used 10 times
ExprNptr defined in line 117; used 4 times
ExprNstack defined in line 116; used 2 times
ExprOptr defined in line 119; used 5 times
ExprOstack defined in line 118; used 2 times
ExprPeek defined in line 121; used 6 times
ExprPrec defined in line 97; used 2 times
  • in line 200(2)

Defined macros

ADD defined in line 90; used 1 times
AND defined in line 83; used 1 times
DIVIDE defined in line 93; used 1 times
END defined in line 80; used 3 times
EQUALS defined in line 84; used 1 times
GEQ defined in line 89; used 1 times
GREATER defined in line 88; used 1 times
LEQ defined in line 87; used 1 times
LESS defined in line 86; used 1 times
MOD defined in line 94; used 1 times
MULTIPLY defined in line 92; used 1 times
NEQ defined in line 85; used 1 times
OR defined in line 82; used 1 times
RIGHTP defined in line 79; used 4 times
SEPERATOR defined in line 81; used 2 times
STACKSZ defined in line 78; used 2 times
SUBTRACT defined in line 91; used 1 times
Last modified: 1995-02-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3148
Valid CSS Valid XHTML 1.0 Strict