1 /* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
7 * Integer arithmetic expression evaluator used to handle expressions
8 * encountered during preprocessing.
9 * ----------------------------------------------------------------------------- */
11 char cvsroot_expr_c[] = "$Id: expr.c 10310 2008-03-17 00:36:35Z olly $";
14 #include "preprocessor.h"
16 static Scanner *scan = 0;
28 #define EXPR_UMINUS 100
30 static exprval stack[256]; /* Parsing stack */
31 static int sp = 0; /* Stack pointer */
32 static int prec[256]; /* Precedence rules */
33 static int expr_init = 0; /* Initialization flag */
34 static char *errmsg = 0; /* Parsing error */
36 /* Initialize the precedence table for various operators. Low values have higher precedence */
37 static void init_precedence() {
38 prec[SWIG_TOKEN_NOT] = 10;
39 prec[EXPR_UMINUS] = 10;
40 prec[SWIG_TOKEN_STAR] = 20;
41 prec[SWIG_TOKEN_SLASH] = 20;
42 prec[SWIG_TOKEN_PERCENT] = 20;
43 prec[SWIG_TOKEN_PLUS] = 30;
44 prec[SWIG_TOKEN_MINUS] = 30;
45 prec[SWIG_TOKEN_LSHIFT] = 40;
46 prec[SWIG_TOKEN_RSHIFT] = 40;
47 prec[SWIG_TOKEN_AND] = 50;
48 prec[SWIG_TOKEN_XOR] = 60;
49 prec[SWIG_TOKEN_OR] = 70;
50 prec[SWIG_TOKEN_EQUALTO] = 80;
51 prec[SWIG_TOKEN_NOTEQUAL] = 80;
52 prec[SWIG_TOKEN_LESSTHAN] = 80;
53 prec[SWIG_TOKEN_GREATERTHAN] = 80;
54 prec[SWIG_TOKEN_LTEQUAL] = 80;
55 prec[SWIG_TOKEN_GTEQUAL] = 80;
56 prec[SWIG_TOKEN_LNOT] = 90;
57 prec[SWIG_TOKEN_LAND] = 100;
58 prec[SWIG_TOKEN_LOR] = 110;
62 #define UNARY_OP(token) (((token) == SWIG_TOKEN_NOT) || \
63 ((token) == SWIG_TOKEN_LNOT) || \
64 ((token) == EXPR_UMINUS))
66 /* Reduce a single operator on the stack */
67 /* return 0 on failure, 1 on success */
68 static int reduce_op() {
69 long op_token = stack[sp - 1].value;
71 assert(stack[sp - 1].op == EXPR_OP);
72 /* do some basic checking first: */
73 if (stack[sp].op != EXPR_VALUE) {
74 errmsg = "Right-hand side is not value";
77 if (UNARY_OP(op_token)) {
78 if (stack[sp].svalue) {
79 errmsg = "Syntax error: attempt to apply unary operator to string";
83 /* binary operator: */
85 /* top of stack: don't attempt to use sp-2! */
86 errmsg = "Missing left-hand side for binary operator";
89 if (stack[sp].op != EXPR_VALUE) {
90 errmsg = "Left-hand side of binary operator is not a value";
93 if ((!stack[sp - 2].svalue) != (!stack[sp].svalue)) {
94 errmsg = "Can't mix strings and integers in expression";
98 if (stack[sp].svalue) {
99 /* A binary string expression */
100 switch (stack[sp - 1].value) {
101 case SWIG_TOKEN_EQUALTO:
102 stack[sp - 2].value = (Strcmp(stack[sp - 2].svalue, stack[sp].svalue) == 0);
103 Delete(stack[sp - 2].svalue);
104 Delete(stack[sp].svalue);
107 case SWIG_TOKEN_NOTEQUAL:
108 stack[sp - 2].value = (Strcmp(stack[sp - 2].svalue, stack[sp].svalue) != 0);
109 Delete(stack[sp - 2].svalue);
110 Delete(stack[sp].svalue);
114 errmsg = "Syntax error: bad binary operator for strings";
120 case SWIG_TOKEN_STAR:
121 stack[sp - 2].value = stack[sp - 2].value * stack[sp].value;
124 case SWIG_TOKEN_EQUALTO:
125 stack[sp - 2].value = stack[sp - 2].value == stack[sp].value;
128 case SWIG_TOKEN_NOTEQUAL:
129 stack[sp - 2].value = stack[sp - 2].value != stack[sp].value;
132 case SWIG_TOKEN_PLUS:
133 stack[sp - 2].value = stack[sp - 2].value + stack[sp].value;
136 case SWIG_TOKEN_MINUS:
137 stack[sp - 2].value = stack[sp - 2].value - stack[sp].value;
141 stack[sp - 2].value = stack[sp - 2].value & stack[sp].value;
144 case SWIG_TOKEN_LAND:
145 stack[sp - 2].value = stack[sp - 2].value && stack[sp].value;
149 stack[sp - 2].value = stack[sp - 2].value | stack[sp].value;
153 stack[sp - 2].value = stack[sp - 2].value || stack[sp].value;
157 stack[sp - 2].value = stack[sp - 2].value ^ stack[sp].value;
160 case SWIG_TOKEN_LESSTHAN:
161 stack[sp - 2].value = stack[sp - 2].value < stack[sp].value;
164 case SWIG_TOKEN_GREATERTHAN:
165 stack[sp - 2].value = stack[sp - 2].value > stack[sp].value;
168 case SWIG_TOKEN_LTEQUAL:
169 stack[sp - 2].value = stack[sp - 2].value <= stack[sp].value;
172 case SWIG_TOKEN_GTEQUAL:
173 stack[sp - 2].value = stack[sp - 2].value >= stack[sp].value;
177 stack[sp - 1].value = ~stack[sp].value;
180 case SWIG_TOKEN_LNOT:
181 stack[sp - 1].value = !stack[sp].value;
185 stack[sp - 1].value = -stack[sp].value;
188 case SWIG_TOKEN_SLASH:
189 stack[sp - 2].value = stack[sp - 2].value / stack[sp].value;
192 case SWIG_TOKEN_PERCENT:
193 stack[sp - 2].value = stack[sp - 2].value % stack[sp].value;
196 case SWIG_TOKEN_LSHIFT:
197 stack[sp - 2].value = stack[sp - 2].value << stack[sp].value;
200 case SWIG_TOKEN_RSHIFT:
201 stack[sp - 2].value = stack[sp - 2].value >> stack[sp].value;
205 errmsg = "Syntax error: bad operator";
210 stack[sp].op = EXPR_VALUE;
211 stack[sp].svalue = 0; /* ensure it's not a string! */
215 /* -----------------------------------------------------------------------------
216 * Preprocessor_expr_init()
218 * Initialize the expression evaluator
219 * ----------------------------------------------------------------------------- */
221 void Preprocessor_expr_init(void) {
228 void Preprocessor_expr_delete(void) {
233 /* -----------------------------------------------------------------------------
235 * ----------------------------------------------------------------------------- */
237 static int expr_token(Scanner * s) {
240 t = Scanner_token(s);
241 if (!((t == SWIG_TOKEN_BACKSLASH) || (t == SWIG_TOKEN_ENDLINE) || (t == SWIG_TOKEN_COMMENT)))
247 /* -----------------------------------------------------------------------------
248 * Preprocessor_expr()
250 * Evaluates an arithmetic expression. Returns the result and sets an error code.
251 * ----------------------------------------------------------------------------- */
253 int Preprocessor_expr(DOH *s, int *error) {
261 Seek(s, 0, SEEK_SET);
262 /* Printf(stdout,"evaluating : '%s'\n", s); */
265 Scanner_push(scan, s);
267 /* Put initial state onto the stack */
268 stack[sp].op = EXPR_TOP;
272 /* Look at the top of the stack */
273 switch (stack[sp].op) {
275 /* An expression. Can be a number or another expression enclosed in parens */
276 token = expr_token(scan);
278 errmsg = "Expected an expression";
282 if ((token == SWIG_TOKEN_INT) || (token == SWIG_TOKEN_UINT) || (token == SWIG_TOKEN_LONG) || (token == SWIG_TOKEN_ULONG)) {
283 /* A number. Reduce EXPR_TOP to an EXPR_VALUE */
284 char *c = Char(Scanner_text(scan));
285 stack[sp].value = (long) strtol(c, 0, 0);
286 stack[sp].svalue = 0;
287 /* stack[sp].value = (long) atol(Char(Scanner_text(scan))); */
288 stack[sp].op = EXPR_VALUE;
289 } else if (token == SWIG_TOKEN_PLUS) {
290 } else if ((token == SWIG_TOKEN_MINUS) || (token == SWIG_TOKEN_LNOT) || (token == SWIG_TOKEN_NOT)) {
291 if (token == SWIG_TOKEN_MINUS)
293 stack[sp].value = token;
294 stack[sp++].op = EXPR_OP;
295 stack[sp].op = EXPR_TOP;
296 stack[sp].svalue = 0;
297 } else if ((token == SWIG_TOKEN_LPAREN)) {
298 stack[sp++].op = EXPR_GROUP;
299 stack[sp].op = EXPR_TOP;
301 stack[sp].svalue = 0;
302 } else if (token == SWIG_TOKEN_ENDLINE) {
303 } else if ((token == SWIG_TOKEN_STRING)) {
304 stack[sp].svalue = NewString(Scanner_text(scan));
305 stack[sp].op = EXPR_VALUE;
306 } else if ((token == SWIG_TOKEN_ID)) {
308 stack[sp].svalue = 0;
309 stack[sp].op = EXPR_VALUE;
314 /* A value is on the stack. We may reduce or evaluate depending on what the next token is */
315 token = expr_token(scan);
317 /* End of input. Might have to reduce if an operator is on stack */
319 if (stack[sp - 1].op == EXPR_OP) {
322 } else if (stack[sp - 1].op == EXPR_GROUP) {
323 errmsg = "Missing \')\'";
329 return stack[sp].value;
331 /* Token must be an operator */
333 case SWIG_TOKEN_STAR:
334 case SWIG_TOKEN_EQUALTO:
335 case SWIG_TOKEN_NOTEQUAL:
336 case SWIG_TOKEN_PLUS:
337 case SWIG_TOKEN_MINUS:
339 case SWIG_TOKEN_LAND:
343 case SWIG_TOKEN_LESSTHAN:
344 case SWIG_TOKEN_GREATERTHAN:
345 case SWIG_TOKEN_LTEQUAL:
346 case SWIG_TOKEN_GTEQUAL:
347 case SWIG_TOKEN_SLASH:
348 case SWIG_TOKEN_PERCENT:
349 case SWIG_TOKEN_LSHIFT:
350 case SWIG_TOKEN_RSHIFT:
351 if ((sp == 0) || (stack[sp - 1].op == EXPR_GROUP)) {
352 /* No possibility of reduce. Push operator and expression */
354 stack[sp].op = EXPR_OP;
355 stack[sp].value = token;
357 stack[sp].op = EXPR_TOP;
360 if (stack[sp - 1].op != EXPR_OP)
361 goto syntax_error_expected_operator;
362 op = stack[sp - 1].value; /* Previous operator */
364 /* Now, depending on the precedence relationship between the last operator and the current
365 we will reduce or push */
367 if (prec[op] <= prec[token]) {
368 /* Reduce the previous operator */
373 stack[sp].op = EXPR_OP;
374 stack[sp].value = token;
376 stack[sp].op = EXPR_TOP;
380 case SWIG_TOKEN_RPAREN:
384 /* Might have to reduce operators first */
385 while ((sp > 0) && (stack[sp - 1].op == EXPR_OP)) {
389 if ((sp == 0) || (stack[sp - 1].op != EXPR_GROUP))
391 stack[sp - 1].op = EXPR_VALUE;
392 stack[sp - 1].value = stack[sp].value;
396 goto syntax_error_expected_operator;
402 fprintf(stderr, "Internal error in expression evaluator.\n");
408 errmsg = "Syntax error";
412 syntax_error_expected_operator:
413 errmsg = "Syntax error: expected operator";
418 /* errmsg has been set by reduce_op */
423 errmsg = "Extra \')\'";
428 /* -----------------------------------------------------------------------------
429 * Preprocessor_expr_error()
431 * Return error message set by the evaluator (if any)
432 * ----------------------------------------------------------------------------- */
434 char *Preprocessor_expr_error() {