import source from 1.3.40
[external/swig.git] / Source / Preprocessor / expr.c
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.
4  *
5  * expr.c
6  *
7  * Integer arithmetic expression evaluator used to handle expressions
8  * encountered during preprocessing.
9  * ----------------------------------------------------------------------------- */
10
11 char cvsroot_expr_c[] = "$Id: expr.c 10310 2008-03-17 00:36:35Z olly $";
12
13 #include "swig.h"
14 #include "preprocessor.h"
15
16 static Scanner *scan = 0;
17
18 typedef struct {
19   int op;
20   long value;
21   String *svalue;
22 } exprval;
23
24 #define  EXPR_TOP      1
25 #define  EXPR_VALUE    2
26 #define  EXPR_OP       3
27 #define  EXPR_GROUP    4
28 #define  EXPR_UMINUS   100
29
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       */
35
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;
59   expr_init = 1;
60 }
61
62 #define UNARY_OP(token) (((token) == SWIG_TOKEN_NOT) || \
63                          ((token) == SWIG_TOKEN_LNOT) || \
64                          ((token) == EXPR_UMINUS))
65
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;
70   assert(sp > 0);
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";
75     return 0;
76   }
77   if (UNARY_OP(op_token)) {
78     if (stack[sp].svalue) {
79       errmsg = "Syntax error: attempt to apply unary operator to string";
80       return 0;
81     }
82   } else {
83     /* binary operator: */
84     if (sp == 1) {
85       /* top of stack: don't attempt to use sp-2! */
86       errmsg = "Missing left-hand side for binary operator";
87       return 0;
88     }
89     if (stack[sp].op != EXPR_VALUE) {
90       errmsg = "Left-hand side of binary operator is not a value";
91       return 0;
92     }
93     if ((!stack[sp - 2].svalue) != (!stack[sp].svalue)) {
94       errmsg = "Can't mix strings and integers in expression";
95       return 0;
96     }
97   }
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);
105       sp -= 2;
106       break;
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);
111       sp -= 2;
112       break;
113     default:
114       errmsg = "Syntax error: bad binary operator for strings";
115       return 0;
116       break;
117     }
118   } else {
119     switch (op_token) {
120     case SWIG_TOKEN_STAR:
121       stack[sp - 2].value = stack[sp - 2].value * stack[sp].value;
122       sp -= 2;
123       break;
124     case SWIG_TOKEN_EQUALTO:
125       stack[sp - 2].value = stack[sp - 2].value == stack[sp].value;
126       sp -= 2;
127       break;
128     case SWIG_TOKEN_NOTEQUAL:
129       stack[sp - 2].value = stack[sp - 2].value != stack[sp].value;
130       sp -= 2;
131       break;
132     case SWIG_TOKEN_PLUS:
133       stack[sp - 2].value = stack[sp - 2].value + stack[sp].value;
134       sp -= 2;
135       break;
136     case SWIG_TOKEN_MINUS:
137       stack[sp - 2].value = stack[sp - 2].value - stack[sp].value;
138       sp -= 2;
139       break;
140     case SWIG_TOKEN_AND:
141       stack[sp - 2].value = stack[sp - 2].value & stack[sp].value;
142       sp -= 2;
143       break;
144     case SWIG_TOKEN_LAND:
145       stack[sp - 2].value = stack[sp - 2].value && stack[sp].value;
146       sp -= 2;
147       break;
148     case SWIG_TOKEN_OR:
149       stack[sp - 2].value = stack[sp - 2].value | stack[sp].value;
150       sp -= 2;
151       break;
152     case SWIG_TOKEN_LOR:
153       stack[sp - 2].value = stack[sp - 2].value || stack[sp].value;
154       sp -= 2;
155       break;
156     case SWIG_TOKEN_XOR:
157       stack[sp - 2].value = stack[sp - 2].value ^ stack[sp].value;
158       sp -= 2;
159       break;
160     case SWIG_TOKEN_LESSTHAN:
161       stack[sp - 2].value = stack[sp - 2].value < stack[sp].value;
162       sp -= 2;
163       break;
164     case SWIG_TOKEN_GREATERTHAN:
165       stack[sp - 2].value = stack[sp - 2].value > stack[sp].value;
166       sp -= 2;
167       break;
168     case SWIG_TOKEN_LTEQUAL:
169       stack[sp - 2].value = stack[sp - 2].value <= stack[sp].value;
170       sp -= 2;
171       break;
172     case SWIG_TOKEN_GTEQUAL:
173       stack[sp - 2].value = stack[sp - 2].value >= stack[sp].value;
174       sp -= 2;
175       break;
176     case SWIG_TOKEN_NOT:
177       stack[sp - 1].value = ~stack[sp].value;
178       sp--;
179       break;
180     case SWIG_TOKEN_LNOT:
181       stack[sp - 1].value = !stack[sp].value;
182       sp--;
183       break;
184     case EXPR_UMINUS:
185       stack[sp - 1].value = -stack[sp].value;
186       sp--;
187       break;
188     case SWIG_TOKEN_SLASH:
189       stack[sp - 2].value = stack[sp - 2].value / stack[sp].value;
190       sp -= 2;
191       break;
192     case SWIG_TOKEN_PERCENT:
193       stack[sp - 2].value = stack[sp - 2].value % stack[sp].value;
194       sp -= 2;
195       break;
196     case SWIG_TOKEN_LSHIFT:
197       stack[sp - 2].value = stack[sp - 2].value << stack[sp].value;
198       sp -= 2;
199       break;
200     case SWIG_TOKEN_RSHIFT:
201       stack[sp - 2].value = stack[sp - 2].value >> stack[sp].value;
202       sp -= 2;
203       break;
204     default:
205       errmsg = "Syntax error: bad operator";
206       return 0;
207       break;
208     }
209   }
210   stack[sp].op = EXPR_VALUE;
211   stack[sp].svalue = 0;         /* ensure it's not a string! */
212   return 1;
213 }
214
215 /* -----------------------------------------------------------------------------
216  * Preprocessor_expr_init()
217  *
218  * Initialize the expression evaluator
219  * ----------------------------------------------------------------------------- */
220
221 void Preprocessor_expr_init(void) {
222   if (!expr_init)
223     init_precedence();
224   if (!scan)
225     scan = NewScanner();
226 }
227
228 void Preprocessor_expr_delete(void) {
229   DelScanner(scan);
230 }
231
232
233 /* -----------------------------------------------------------------------------
234  * Tokenizer 
235  * ----------------------------------------------------------------------------- */
236
237 static int expr_token(Scanner * s) {
238   int t;
239   while (1) {
240     t = Scanner_token(s);
241     if (!((t == SWIG_TOKEN_BACKSLASH) || (t == SWIG_TOKEN_ENDLINE) || (t == SWIG_TOKEN_COMMENT)))
242       break;
243   }
244   return t;
245 }
246
247 /* -----------------------------------------------------------------------------
248  * Preprocessor_expr()
249  *
250  * Evaluates an arithmetic expression.  Returns the result and sets an error code.
251  * ----------------------------------------------------------------------------- */
252
253 int Preprocessor_expr(DOH *s, int *error) {
254   int token = 0;
255   int op = 0;
256
257   sp = 0;
258   assert(s);
259   assert(scan);
260
261   Seek(s, 0, SEEK_SET);
262   /* Printf(stdout,"evaluating : '%s'\n", s); */
263   *error = 0;
264   Scanner_clear(scan);
265   Scanner_push(scan, s);
266
267   /* Put initial state onto the stack */
268   stack[sp].op = EXPR_TOP;
269   stack[sp].value = 0;
270
271   while (1) {
272     /* Look at the top of the stack */
273     switch (stack[sp].op) {
274     case EXPR_TOP:
275       /* An expression.   Can be a number or another expression enclosed in parens */
276       token = expr_token(scan);
277       if (!token) {
278         errmsg = "Expected an expression";
279         *error = 1;
280         return 0;
281       }
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)
292           token = EXPR_UMINUS;
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;
300         stack[sp].value = 0;
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)) {
307         stack[sp].value = 0;
308         stack[sp].svalue = 0;
309         stack[sp].op = EXPR_VALUE;
310       } else
311         goto syntax_error;
312       break;
313     case 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);
316       if (!token) {
317         /* End of input. Might have to reduce if an operator is on stack */
318         while (sp > 0) {
319           if (stack[sp - 1].op == EXPR_OP) {
320             if (!reduce_op())
321               goto reduce_error;
322           } else if (stack[sp - 1].op == EXPR_GROUP) {
323             errmsg = "Missing \')\'";
324             *error = 1;
325             return 0;
326           } else
327             goto syntax_error;
328         }
329         return stack[sp].value;
330       }
331       /* Token must be an operator */
332       switch (token) {
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:
338       case SWIG_TOKEN_AND:
339       case SWIG_TOKEN_LAND:
340       case SWIG_TOKEN_OR:
341       case SWIG_TOKEN_LOR:
342       case SWIG_TOKEN_XOR:
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 */
353           sp++;
354           stack[sp].op = EXPR_OP;
355           stack[sp].value = token;
356           sp++;
357           stack[sp].op = EXPR_TOP;
358           stack[sp].value = 0;
359         } else {
360           if (stack[sp - 1].op != EXPR_OP)
361             goto syntax_error_expected_operator;
362           op = stack[sp - 1].value;     /* Previous operator */
363
364           /* Now, depending on the precedence relationship between the last operator and the current
365              we will reduce or push */
366
367           if (prec[op] <= prec[token]) {
368             /* Reduce the previous operator */
369             if (!reduce_op())
370               goto reduce_error;
371           }
372           sp++;
373           stack[sp].op = EXPR_OP;
374           stack[sp].value = token;
375           sp++;
376           stack[sp].op = EXPR_TOP;
377           stack[sp].value = 0;
378         }
379         break;
380       case SWIG_TOKEN_RPAREN:
381         if (sp == 0)
382           goto extra_rparen;
383
384         /* Might have to reduce operators first */
385         while ((sp > 0) && (stack[sp - 1].op == EXPR_OP)) {
386           if (!reduce_op())
387             goto reduce_error;
388         }
389         if ((sp == 0) || (stack[sp - 1].op != EXPR_GROUP))
390           goto extra_rparen;
391         stack[sp - 1].op = EXPR_VALUE;
392         stack[sp - 1].value = stack[sp].value;
393         sp--;
394         break;
395       default:
396         goto syntax_error_expected_operator;
397         break;
398       }
399       break;
400
401     default:
402       fprintf(stderr, "Internal error in expression evaluator.\n");
403       abort();
404     }
405   }
406
407 syntax_error:
408   errmsg = "Syntax error";
409   *error = 1;
410   return 0;
411
412 syntax_error_expected_operator:
413   errmsg = "Syntax error: expected operator";
414   *error = 1;
415   return 0;
416
417 reduce_error:
418   /*  errmsg has been set by reduce_op */
419   *error = 1;
420   return 0;
421
422 extra_rparen:
423   errmsg = "Extra \')\'";
424   *error = 1;
425   return 0;
426 }
427
428 /* -----------------------------------------------------------------------------
429  * Preprocessor_expr_error()
430  *
431  * Return error message set by the evaluator (if any)
432  * ----------------------------------------------------------------------------- */
433
434 char *Preprocessor_expr_error() {
435   return errmsg;
436 }