Fix:map_csv:Disable default notification of each deleted item.
[profile/ivi/navit.git] / navit / navit / obj_filter.c
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <stdarg.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <glib.h>
8 #include "obj_filter.h" 
9 #include "item.h" 
10 #include "attr.h" 
11 #include "xmlconfig.h" 
12
13 union result_t {
14   int res_int;
15   int res_bool;
16   char* res_str;
17 };
18
19 enum error_t {ERR_NONE=0, ERR_SYNTAX, ERR_UNKNOWN_ATTRIBUTE, ERR_INTERNAL, ERR_NONTERMINATED_STRING };
20
21 struct ctx {
22   char*expr;
23   union result_t res;
24   enum error_t error;
25   struct attr *navit_obj;
26   struct object_func *obj_func;
27 };
28
29 //prototypes
30 static int parse_numeric_expr(struct ctx*the_ctx);
31 static int parse_cond_expr(struct ctx*the_ctx);
32 static int parse_bool_expr(struct ctx*the_ctx);
33 static enum operator_t get_operator_by_symbol(char*sym);
34 static char* get_opstr_by_op(enum operator_t op);
35 static int whitespace_num(char*str);
36
37 static char*next_sym_ptr;
38
39 /*
40  * parses an input like osd[attr1==2 && attr2==3][2]   or   [attr1==2 && attr2==3]
41  * returns 0 on failure , returns the number of parsed characters on success
42  */ 
43 int parse_obj_filter(const char*input, struct obj_filter_t* out)
44 {
45   char *curr_ch, *itt, *expr;
46   out->idx = 0; //default idx
47
48   //skip whitespaces
49   curr_ch = (char*)input;
50   while(isspace(*curr_ch)) {++curr_ch;}
51
52   //parse attr type for the list(iterator)
53   itt = out->iterator_type; 
54   if(isalpha(*curr_ch) || *curr_ch=='_') {
55     while(isalnum(*curr_ch) || *curr_ch=='_' ) {
56       *itt = *curr_ch;
57       ++itt;
58       ++curr_ch;
59     }
60   }
61   *itt = 0;
62   //skip whitespaces
63   while(isspace(*curr_ch)) {++curr_ch;}
64   //parse the filter expression (first section between[]), ignore [] chars between "" or ''  
65   expr = out->filter_expr;
66   if(*curr_ch++ == '[') {
67     while (*curr_ch && *curr_ch!=']') {
68       *expr = *curr_ch;
69       ++expr;
70       ++curr_ch;
71     }
72   } else {
73     return 0;
74   }
75   *expr = 0;
76   if (*curr_ch==']') {
77     char*end1;
78     ++curr_ch;
79     //skip whitespaces
80     while(isspace(*curr_ch)) {++curr_ch;}
81     end1 = curr_ch; //possible end of expression if no idx specified
82     //parse the optional idx part (another part between [] contains numeric expreession(currently only constant numers are supported)) 
83     if (*curr_ch=='[') {
84       char numstr[64];
85       char*numch;
86       ++curr_ch;
87       //skip whitespaces
88       while(isspace(*curr_ch)) {++curr_ch;}
89
90       numch = numstr;
91       while ('0'<=*curr_ch && *curr_ch<='9') {
92         *numch = *curr_ch;
93         ++numch;
94         ++curr_ch;
95       }
96
97       //skip whitespaces
98       while(isspace(*curr_ch)) {++curr_ch;}
99
100       if (*curr_ch==']') {
101         ++curr_ch;
102         *numch = 0;
103         out->idx = atoi(numstr);
104         return curr_ch-input;
105       } else {
106         return end1-input;
107       }
108     } else {
109       return end1-input;
110     }
111   } else {
112     return 0;
113   }
114 }
115
116 struct attr* filter_object(struct attr* root,char*iter_type,char*expr, int idx)
117 {
118   struct attr_iter *iter;
119   struct attr the_attr;
120   int curr_idx = 0;
121   struct object_func *obj_func_root;
122   struct object_func *obj_func_iter;
123
124   if (!root || !iter_type || !expr) {
125     return NULL;
126   }
127
128   obj_func_root = object_func_lookup(((struct attr*)root)->type);
129   obj_func_iter = object_func_lookup(attr_from_name(iter_type));
130   if(   !obj_func_root || !obj_func_root->get_attr || !obj_func_root->iter_new || !obj_func_root->iter_destroy ||
131         !obj_func_iter || !obj_func_iter->get_attr ) {
132     return NULL;
133   }
134
135   iter = obj_func_root->iter_new(NULL);
136   while ( obj_func_root->get_attr(root->u.data, attr_from_name(iter_type), &the_attr, iter ) ) {
137     struct ctx the_ctx;
138     the_ctx.expr = expr;
139     the_ctx.navit_obj = &the_attr; 
140     the_ctx.obj_func = obj_func_iter; 
141     if (parse_bool_expr(&the_ctx)) { 
142       if(the_ctx.res.res_bool) {
143         if (curr_idx==idx) {
144           return attr_dup(&the_attr);
145         }
146         ++curr_idx;
147       }
148     }
149   } 
150   obj_func_root->iter_destroy(iter);
151
152   return NULL;
153 }
154
155 enum operator_t  {OP_NONE=0, OP_GT, OP_GE, OP_LT, OP_LE, OP_EQ, OP_NE, OP_LOGICAL_AND, OP_LOGICAL_OR, OP_LOGICAL_XOR, OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD};
156
157 struct op_table_entry {
158   char*name;
159   enum operator_t op_type;
160 };
161
162 struct op_table_entry op_table[] = { 
163                     {"<" , OP_GT}, 
164                     {"<=", OP_GE}, 
165                     {">" , OP_LT}, 
166                     {">=", OP_LE}, 
167                     {"!=", OP_NE}, 
168                     {"==", OP_EQ}, 
169                     {"&&", OP_LOGICAL_AND}, 
170                     {"||", OP_LOGICAL_OR}, 
171                     {"^" , OP_LOGICAL_XOR}, 
172                     {"+" , OP_ADD}, 
173                     {"-" , OP_SUB}, 
174                     {"*" , OP_MUL}, 
175                     {"/" , OP_DIV}, 
176                     {"%" , OP_MOD}, 
177                     {NULL, OP_NONE} 
178                   };
179
180 static enum operator_t get_operator_by_symbol(char*sym)
181 {
182   struct op_table_entry* ote = op_table;
183   while(sym && ote->name) {
184     if ( ! strcmp(ote->name, sym)) {
185       return ote->op_type;
186     }
187     ++ote;
188     }
189   return OP_NONE;
190 }
191
192 static char* get_opstr_by_op(enum operator_t op)
193 {
194   struct op_table_entry* ote = op_table;
195   while(ote->name) {
196     if ( ote->op_type == op ) {
197       return ote->name;
198     }
199     ++ote;
200     }
201   return NULL;
202 }
203
204 /*
205 GRAMMAR
206
207 ident = [ [A-Z,a-z][A-Z,a-z,0-9]+ 
208         ] .
209
210 number = [ [A-Z,a-z][A-Z,a-z,0-9]+ 
211         ] .
212
213 numeric_additive_expr = [ 
214         | numeric_mul_operand numeric_mul_operator numeric_mul_expr
215         | numeric_add_operand numeric_add_operator numeric_add_expr
216         | "(" numeric_expr ")"
217         | numeric_operand 
218         ] 
219
220 bool_expr = [ bool_expr bool_operator bool_operand 
221         | "!" bool_operand 
222         | bool_operand 
223         ] 
224
225 cond_expr = [
226         cond_operand cond_operator cond_operand
227         ]
228
229 //TODO support precedence between additive and multiplicative operators (the order of +- and * / evaluation)
230
231 numeric_multiplicative_operator = [ "*" "/" "%"
232         ]
233
234 numeric_additive_operator = [ "+" "-"  
235         ]
236
237 bool_operator = [ "&&" "||" "^" 
238         ]
239
240 cond_operator = [ "==" "!=" "< "> "<=" ">=" 
241         ]
242
243 cond_operand = 
244         [ ident 
245         | number 
246         | numeric_expr
247         ] . 
248
249 numeric_operand = 
250         [ ident 
251         | number 
252         | "(" numeric_expr ")"
253         ] . 
254
255 bool_operand = 
256         | "(" bool_expr ")"
257         | cond_expr
258         | "true"
259         | "false"
260         ] . 
261 */
262
263 static int whitespace_num(char*str)
264 {
265   int ret = 0;
266   while(isspace(*str)) {
267     ++str;
268     ++ret;
269   }
270   return ret;
271 }
272
273 static char *
274 get_op(char *expr, ...)
275 {
276         char *op;
277         char *ret=NULL;
278         va_list ap;
279
280         while (isspace(*expr)) {
281                 expr++;
282         }
283
284         va_start(ap, expr);
285         while ((op = va_arg(ap, char *))) {
286                 if (!strncmp(expr, op, strlen(op))) {
287                         ret = op;
288                         break;
289                 }
290         }
291         va_end(ap);
292         return ret;
293 }
294
295 static int ident_length(char*input)
296 {
297   int ret = 0;
298   if(input[0] != '@') {
299     return 0;
300   }
301   if(isalpha((int)input[1])) {
302     int ii;
303     ++ret;
304     for(ii=2 ; ii<strlen(input) ; ++ii) {
305       if(!isalnum((int)input[ii])) {
306         return ret;
307       } else {
308         ++ret;
309       }
310     }
311     return ret;
312   }
313   return 0;
314 }
315
316 static enum operator_t parse_bool_operator(struct ctx*the_ctx)
317 {
318   char* input = the_ctx->expr;
319   char *sym;
320   enum operator_t op;
321   sym = get_op(input,"&&","||","^",NULL);
322  
323   op = get_operator_by_symbol(sym);
324   switch(op) {
325     case OP_LOGICAL_AND:
326     case OP_LOGICAL_OR:
327     case OP_LOGICAL_XOR:
328       return op;
329       break;
330     default:
331       return OP_NONE;
332       break;
333   };
334 }
335
336 static enum operator_t parse_cond_operator(struct ctx*the_ctx)
337 {
338   char* input = the_ctx->expr;
339   char *sym;
340   enum operator_t op;
341   sym = get_op(input, "==", "<", ">", "<=", ">=", "!=", NULL);
342  
343   op = get_operator_by_symbol(sym);
344   switch(op) {
345     case OP_EQ:
346     case OP_GT:
347     case OP_LT:
348     case OP_GE:
349     case OP_LE:
350     case OP_NE:
351       return op;
352       break;
353     default:
354       return OP_NONE;
355       break;
356   };
357 }
358
359 static enum operator_t parse_numeric_multiplicative_operator(struct ctx*the_ctx)
360 {
361   char* input = the_ctx->expr;
362   char *sym;
363   enum operator_t op;
364   sym = get_op(input, "*", "/", "%", NULL);
365  
366   op = get_operator_by_symbol(sym);
367   switch(op) {
368     case OP_MUL:
369     case OP_DIV:
370     case OP_MOD:
371       return op;
372       break;
373     default:
374       return OP_NONE;
375       break;
376   };
377 }
378
379 static enum operator_t parse_numeric_additive_operator(struct ctx*the_ctx)
380 {
381   char* input = the_ctx->expr;
382   char *sym;
383   enum operator_t op;
384   sym = get_op(input, "+", "-", NULL);
385  
386   op = get_operator_by_symbol(sym);
387   switch(op) {
388     case OP_ADD:
389     case OP_SUB:
390       return op;
391       break;
392     default:
393       return OP_NONE;
394       break;
395   };
396 }
397
398 static int parse_string_operand(struct ctx*the_ctx)
399 {
400   char* input = the_ctx->expr;
401   char sym[256];
402   struct ctx sub_ctx;
403   int ilen;
404   sub_ctx.navit_obj = the_ctx->navit_obj;
405   sub_ctx.obj_func = the_ctx->obj_func;
406   
407   while(isspace(*input)) {++input;}
408
409   if (*input == '"' || *input=='\'') {
410     char delimiter = *input;
411     char* psym = sym;
412     ++input;
413     while(*input != delimiter && *input!='\0') {
414       *psym = *input;
415       ++psym;
416       ++input;
417     }
418     if(*input=='\0') {
419       the_ctx->error = ERR_NONTERMINATED_STRING;
420       return 0;
421     } else { //terminating delimiter found
422       *psym = '\0';
423       the_ctx->res.res_str = g_strdup(sym);
424       the_ctx->error = ERR_NONE;
425       next_sym_ptr = input + 1;
426       return 1;
427     }
428   }
429
430   ilen = ident_length(input);
431   if(ilen) {
432     struct attr the_attr;
433     strncpy(sym,input+1,ilen);
434     sym[ilen] = '\0';
435     if ( attr_from_name(sym)!=attr_none && the_ctx->obj_func->get_attr(the_ctx->navit_obj->u.data, attr_from_name(sym), &the_attr, NULL ) 
436       && attr_type_string_begin<=the_attr.type && the_attr.type <= attr_type_string_end) { 
437       the_ctx->res.res_str = g_strdup(the_attr.u.str);
438       the_ctx->error = ERR_NONE;
439       next_sym_ptr = input+ilen+1;
440       return 1;
441     } else {
442       the_ctx->error = ERR_UNKNOWN_ATTRIBUTE;
443       return 0;
444     }
445   }
446
447   //currently we are not supporting string expressions (eg: concatenation)
448   /*
449   if(get_op(input,"(",NULL)) {
450     sub_ctx.expr = input + 1 + whitespace_num(input);
451     if ( ! parse_string_expr(&sub_ctx)) {
452       the_ctx->error = ERR_SYNTAX;
453       return 0;
454     } else {
455       the_ctx->res.res_int = sub_ctx.res.res_int;
456       the_ctx->error = ERR_NONE;
457     }
458     //expect ")"
459     if ( get_op(next_sym_ptr,")",NULL)) { 
460       next_sym_ptr += 1 + whitespace_num(next_sym_ptr);
461       return 1;
462     } else {
463       the_ctx->res.res_int = 0;
464       the_ctx->error = ERR_SYNTAX;
465       return 0;
466     }
467   }
468   */
469   return 0;
470 }
471
472
473 static int parse_numeric_operand(struct ctx*the_ctx)
474 {
475   char* input = the_ctx->expr;
476   char sym[256];
477   struct ctx sub_ctx;
478   char* endptr = NULL;
479   int res, ilen;
480   sub_ctx.navit_obj = the_ctx->navit_obj;
481   sub_ctx.obj_func = the_ctx->obj_func;
482   
483   res = strtol(input,&endptr,0);
484   if( endptr!=input ) { 
485     the_ctx->res.res_int = res;
486     the_ctx->error = ERR_NONE;
487     next_sym_ptr = endptr;
488     return 1;
489   }
490
491   while(isspace(*input)) {++input;}
492   ilen = ident_length(input);
493   if(ilen) {
494     //get int value from context object and set result member of context argument
495     struct attr the_attr;
496     strncpy(sym,input+1,ilen);
497     sym[ilen] = '\0';
498     if ( attr_from_name(sym)!=attr_none && the_ctx->obj_func->get_attr(the_ctx->navit_obj->u.data, attr_from_name(sym), &the_attr, NULL ) 
499       && attr_type_int_begin<=the_attr.type && the_attr.type <= attr_type_int_end) { //TODO support other numeric types
500       the_ctx->res.res_int = the_attr.u.num; 
501       the_ctx->error = ERR_NONE;
502       next_sym_ptr = input+ilen+1;
503       return 1;
504     } else {
505       the_ctx->error = ERR_UNKNOWN_ATTRIBUTE;
506       return 0;
507     }
508   }
509   if(get_op(input,"(",NULL)) {
510     sub_ctx.expr = input + 1 + whitespace_num(input);
511     if ( ! parse_numeric_expr(&sub_ctx)) {
512       the_ctx->error = ERR_SYNTAX;
513       return 0;
514     } else {
515       the_ctx->res.res_int = sub_ctx.res.res_int;
516       the_ctx->error = ERR_NONE;
517     }
518     //expect ")"
519     if ( get_op(next_sym_ptr,")",NULL)) { 
520       next_sym_ptr += 1 + whitespace_num(next_sym_ptr);
521       return 1;
522     } else {
523       the_ctx->res.res_int = 0;
524       the_ctx->error = ERR_SYNTAX;
525       return 0;
526     }
527   }
528   return 0;
529 }
530
531 static int parse_cond_operand(struct ctx*the_ctx)
532 {
533   char* input = the_ctx->expr;
534   char sym[256];
535   char* endptr = NULL;
536   int res, ilen;
537   struct attr the_attr;
538   struct ctx sub_ctx;
539   sub_ctx.navit_obj = the_ctx->navit_obj;
540   sub_ctx.obj_func = the_ctx->obj_func;
541   sub_ctx.expr = input;
542   if(parse_numeric_expr(&sub_ctx)) {
543     the_ctx->res.res_int = sub_ctx.res.res_int;
544     the_ctx->error = ERR_NONE;
545     return 1;
546   }
547
548   res = strtol(input,&endptr,0);
549   if( endptr!=input ) { 
550     the_ctx->res.res_int = res;
551     the_ctx->error = ERR_NONE;
552     next_sym_ptr = endptr;
553     return 1;
554   }
555   while(isspace(*input)) {++input;}
556   ilen = ident_length(input);
557   strncpy(sym,input+1,ilen);
558   sym[ilen] = '\0';
559   if ( attr_from_name(sym)!=attr_none && the_ctx->obj_func->get_attr(the_ctx->navit_obj->u.data, attr_from_name(sym), &the_attr, NULL ) 
560     && attr_type_int_begin<=the_attr.type && the_attr.type <= attr_type_int_end) { //TODO support other numeric types
561     the_ctx->res.res_int = the_attr.u.num; 
562     the_ctx->error = ERR_NONE;
563     next_sym_ptr = input+ilen+1;
564     return 1;
565   } else {
566     the_ctx->error = ERR_UNKNOWN_ATTRIBUTE;
567     return 0;
568   }
569   the_ctx->error = ERR_SYNTAX;
570   return 0;
571 }
572
573 static int parse_bool_operand(struct ctx*the_ctx)
574 {
575   char* input = the_ctx->expr;
576   struct ctx sub_ctx;
577   sub_ctx.navit_obj = the_ctx->navit_obj;
578   sub_ctx.obj_func = the_ctx->obj_func;
579   if(get_op(input,"true",NULL)) {
580     the_ctx->res.res_bool = 1;
581     the_ctx->error = ERR_NONE;
582     next_sym_ptr += whitespace_num(input)+strlen("true");
583     return 1;
584   }
585   if(get_op(input,"false",NULL)) {
586     the_ctx->res.res_bool = 0;
587     the_ctx->error = ERR_NONE;
588     next_sym_ptr += whitespace_num(input)+strlen("false");
589     return 1;
590   }
591   if(get_op(input,"(",NULL)) {
592     sub_ctx.expr = input + 1 + whitespace_num(input);
593     if ( ! parse_bool_expr(&sub_ctx)) {
594       the_ctx->error = ERR_SYNTAX;
595       return 0;
596     } else {
597       the_ctx->res.res_bool = sub_ctx.res.res_bool;
598       the_ctx->error = ERR_NONE;
599     }
600     //expect ")"
601     if(get_op(next_sym_ptr,"(",NULL)) {
602       next_sym_ptr += 1 + whitespace_num(next_sym_ptr);
603       return 1;
604     } else {
605       the_ctx->error = ERR_SYNTAX;
606       return 0;
607     }
608   }
609   //cond_expr
610   sub_ctx.expr = input;
611   if (parse_cond_expr(&sub_ctx)) {
612       the_ctx->res.res_bool = sub_ctx.res.res_bool;
613       the_ctx->error = ERR_NONE;
614     return 1;
615   }
616   the_ctx->error = ERR_SYNTAX;
617   return 0;
618 }
619
620 static int parse_cond_expr(struct ctx*the_ctx)
621 {
622   char* input = the_ctx->expr;
623   struct ctx sub_ctx;
624   sub_ctx.navit_obj = the_ctx->navit_obj;
625   sub_ctx.obj_func = the_ctx->obj_func;
626   sub_ctx.expr = input;
627
628
629   //expect cond operand
630   if(parse_cond_operand(&sub_ctx)) {
631     enum operator_t op;
632     int op1 = sub_ctx.res.res_int;
633     //expect cond operand
634     sub_ctx.expr = next_sym_ptr;
635     if( (op=parse_cond_operator(&sub_ctx)) ) {
636       next_sym_ptr += whitespace_num(next_sym_ptr) + strlen(get_opstr_by_op(op));
637       sub_ctx.expr = next_sym_ptr;
638       if(parse_cond_operand(&sub_ctx)) {
639         int op2 = sub_ctx.res.res_int;
640         switch(op) {
641           case OP_EQ:
642             the_ctx->res.res_bool = op1==op2;
643             break;
644           case OP_GT:
645             the_ctx->res.res_bool = op1<op2;
646             break;
647           case OP_LT:
648             the_ctx->res.res_bool = op1>op2;
649             break;
650           case OP_GE:
651             the_ctx->res.res_bool = op1<=op2;
652             break;
653           case OP_LE:
654             the_ctx->res.res_bool = op1>=op2;
655             break;
656           case OP_NE:
657             the_ctx->res.res_bool = op1!=op2;
658             break;
659           default:
660             //unknown operator
661             the_ctx->error = ERR_INTERNAL;
662             return 0;
663             break;
664         };
665         the_ctx->error = ERR_NONE;
666         return 1;
667       }
668     }
669   }
670
671
672
673   //expect cond operand
674   if(parse_string_operand(&sub_ctx)) {
675     char* op1 = sub_ctx.res.res_str;
676     enum operator_t op;
677
678     //expect cond operand
679     sub_ctx.expr = next_sym_ptr;
680     if( (op=parse_cond_operator(&sub_ctx)) ) {
681       next_sym_ptr += whitespace_num(next_sym_ptr) + strlen(get_opstr_by_op(op));
682       sub_ctx.expr = next_sym_ptr;
683       if(parse_string_operand(&sub_ctx)) {
684         char* op2 = sub_ctx.res.res_str;
685         switch(op) {
686           case OP_EQ:
687             the_ctx->res.res_bool = !strcmp(op1,op2);
688             break;
689           case OP_GT:
690             the_ctx->res.res_bool = strcmp(op1,op2)<=0;
691             break;
692           case OP_LT:
693             the_ctx->res.res_bool = strcmp(op1,op2)>=0;
694             break;
695           case OP_GE:
696             the_ctx->res.res_bool = strcmp(op1,op2)<0;
697             break;
698           case OP_LE:
699             the_ctx->res.res_bool = strcmp(op1,op2)>0;
700             break;
701           case OP_NE:
702             the_ctx->res.res_bool = !!strcmp(op1,op2);
703             break;
704           default:
705             //unknown operator
706             the_ctx->error = ERR_INTERNAL;
707             return 0;
708             break;
709         };
710         the_ctx->error = ERR_NONE;
711         return 1;
712       }
713     }
714   }
715   the_ctx->error = ERR_SYNTAX;
716   return 0;
717 }
718
719 /*
720 numeric_expr = [ 
721         | numeric_operand numeric_multiplicative_operator numeric_expr
722         | numeric_operand numeric_additive_operator numeric_expr
723         | "(" numeric_expr ")"
724         | numeric_operand 
725         ] 
726 */
727 static int parse_numeric_expr(struct ctx*the_ctx)
728 {
729 char* input = the_ctx->expr;
730 struct ctx sub_ctx;
731 sub_ctx.navit_obj = the_ctx->navit_obj;
732 sub_ctx.obj_func = the_ctx->obj_func;
733 sub_ctx.expr = input;
734 if(parse_numeric_operand(&sub_ctx)) {
735   enum operator_t op;
736   int op1 = sub_ctx.res.res_int;
737   //expect numeric_multiplicative operator
738   sub_ctx.expr = next_sym_ptr;
739   if( (op=parse_numeric_multiplicative_operator(&sub_ctx)) ) {
740     next_sym_ptr += whitespace_num(next_sym_ptr) + strlen(get_opstr_by_op(op));
741     sub_ctx.expr = next_sym_ptr;
742     if(parse_numeric_expr(&sub_ctx)) {
743       int op2 = sub_ctx.res.res_int;
744       switch(op) {
745         case OP_MUL:
746           the_ctx->res.res_int = op1*op2;
747           break;
748         case OP_DIV:
749           the_ctx->res.res_int = op1/op2;
750           break;
751         case OP_MOD:
752           the_ctx->res.res_int = op1%op2;
753           break;
754         default:
755           //unknown operator
756           the_ctx->error = ERR_INTERNAL;
757           return 0;
758           break;
759       };
760       the_ctx->error = ERR_NONE;
761       return 1;
762     }
763   } 
764 }
765
766 sub_ctx.expr = input;
767 if(parse_numeric_operand(&sub_ctx)) {
768   //expect numeric_additive operator
769   enum operator_t op;
770   int op1 = sub_ctx.res.res_int;
771   sub_ctx.expr = next_sym_ptr;
772   if((op=parse_numeric_additive_operator(&sub_ctx))) {
773     next_sym_ptr += whitespace_num(next_sym_ptr) + strlen(get_opstr_by_op(op));
774     sub_ctx.expr = next_sym_ptr;
775     if(parse_numeric_expr(&sub_ctx)) {
776       int op2 = sub_ctx.res.res_int;
777       switch(op) {
778         case OP_ADD:
779           the_ctx->res.res_int = op1+op2;
780           break;
781         case OP_SUB:
782           the_ctx->res.res_int = op1-op2;
783           break;
784         default:
785           //unknown operator
786           the_ctx->error = ERR_INTERNAL;
787           return 0;
788           break;
789       };
790       the_ctx->error = ERR_NONE;
791       return 1;
792     }
793   }
794 }
795
796 sub_ctx.expr = input;
797 if(parse_numeric_operand(&sub_ctx) ) {
798   the_ctx->res.res_int = sub_ctx.res.res_int;
799   the_ctx->error = ERR_NONE;
800   return 1;
801 }
802   the_ctx->error = ERR_SYNTAX;
803   return 0;
804 }
805
806 /*
807 bool_expr = [ bool_operand bool_operator bool_expr
808         | bool_operand 
809         ] 
810 */
811 static int parse_bool_expr(struct ctx*the_ctx)
812 {
813   char* input = the_ctx->expr;
814   struct ctx sub_ctx;
815   sub_ctx.navit_obj = the_ctx->navit_obj;
816   sub_ctx.obj_func = the_ctx->obj_func;
817   sub_ctx.expr = input;
818   if(parse_bool_operand(&sub_ctx)) {
819     enum operator_t op;
820     int op1 = sub_ctx.res.res_bool;
821     //expect bool operator
822     sub_ctx.expr = next_sym_ptr;
823     if((op=parse_bool_operator(&sub_ctx))) {
824       next_sym_ptr += whitespace_num(next_sym_ptr) + strlen(get_opstr_by_op(op));
825       sub_ctx.expr = next_sym_ptr;
826       if(parse_bool_expr(&sub_ctx)) {
827         int op2 = sub_ctx.res.res_bool;
828         switch(op) {
829           case OP_LOGICAL_AND:
830             the_ctx->res.res_bool = op1 && op2;
831             break;
832           case OP_LOGICAL_OR:
833             the_ctx->res.res_bool = op1 || op2;
834             break;
835           case OP_LOGICAL_XOR:
836             the_ctx->res.res_bool = op1 ^ op2;
837             break;
838           default:
839             //unknown operator
840             the_ctx->error = ERR_INTERNAL;
841             return 0;
842             break;
843         };
844         return 1;
845       }
846     } 
847   }
848
849   if(get_op(input,"!",NULL)) {
850     next_sym_ptr += 1 + whitespace_num(input);
851     sub_ctx.expr = next_sym_ptr;
852     if(parse_bool_expr(&sub_ctx)) {
853       the_ctx->res.res_bool = ! sub_ctx.res.res_bool;
854       the_ctx->error = ERR_NONE;
855       return 1;
856     }
857   }
858   sub_ctx.expr = input;
859   if(parse_bool_operand(&sub_ctx) ) {
860     the_ctx->res.res_bool = sub_ctx.res.res_bool;
861     the_ctx->error = ERR_NONE;
862     return 1;
863   }
864   the_ctx->error = ERR_SYNTAX;
865   return 0;
866 }
867