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
expr
defined in line
133; used 1 times
Defined variables
Defined macros
ADD
defined in line
90; used 1 times
AND
defined in line
83; used 1 times
END
defined in line
80; used 3 times
GEQ
defined in line
89; 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
NEQ
defined in line
85; used 1 times
OR
defined in line
82; used 1 times