1: # include   <ingres.h>
   2: # include   <sccs.h>
   3: 
   4: SCCSID(@(#)expr.c	8.1	12/31/84)
   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: }

Defined functions

exp_op defined in line 417; used 2 times
expr defined in line 106; used 1 times
exprfind defined in line 231; used 3 times
exprgch defined in line 536; used 6 times
numberget defined in line 496; used 1 times
opfind defined in line 308; used 1 times
popnum defined in line 573; used 2 times
popop defined in line 554; used 2 times
pushnum defined in line 584; used 1 times
pushop defined in line 564; used 2 times
valof defined in line 152; used 2 times

Defined variables

ExprError defined in line 93; used 10 times
ExprNptr defined in line 90; used 4 times
ExprNstack defined in line 89; used 2 times
ExprOptr defined in line 92; used 5 times
ExprOstack defined in line 91; used 2 times
ExprPeek defined in line 94; used 6 times
ExprPrec defined in line 70; used 2 times
  • in line 173(2)

Defined macros

ADD defined in line 63; used 1 times
AND defined in line 56; used 1 times
DIVIDE defined in line 66; used 1 times
END defined in line 53; used 3 times
EQUALS defined in line 57; used 1 times
GEQ defined in line 62; used 1 times
GREATER defined in line 61; used 1 times
LEQ defined in line 60; used 1 times
LESS defined in line 59; used 1 times
MOD defined in line 67; used 1 times
MULTIPLY defined in line 65; used 1 times
NEQ defined in line 58; used 1 times
OR defined in line 55; used 1 times
RIGHTP defined in line 52; used 4 times
SEPERATOR defined in line 54; used 2 times
STACKSIZE defined in line 51; used 3 times
SUBTRACT defined in line 64; used 1 times
Last modified: 1986-04-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1089
Valid CSS Valid XHTML 1.0 Strict