Ticket #897: obj_filter.c

File obj_filter.c, 20.5 KB (added by tegzed, 10 years ago)

object filter for the command system

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