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
expr
defined in line
106; used 1 times
Defined variables
Defined macros
ADD
defined in line
63; used 1 times
AND
defined in line
56; used 1 times
END
defined in line
53; used 3 times
GEQ
defined in line
62; 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
NEQ
defined in line
58; used 1 times
OR
defined in line
55; used 1 times