Add:Core:Improved commands
[navit-package] / navit / command.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #include <stdlib.h>
5 #include <glib.h>
6 #include "item.h"
7 #include "xmlconfig.h"
8 #include "main.h"
9 #include "navit.h"
10 #include "vehicle.h"
11 #include "speech.h"
12 #include "gui.h"
13 #include "debug.h"
14 #include "callback.h"
15 #include "command.h"
16
17 /*
18 gui.fullscreen()
19 gui.menu()
20 gui.get_data() 
21 zoom_in() 
22 zoom_out()
23 speech.active=!speech.active
24 osd_configuration=1
25 Not yet:
26 osd[type=="xxx"].active=0;osd[type=="yyy"].active=0
27 */
28
29
30 struct result {
31         struct attr attr;
32         double val;
33         char *var;
34         int varlen;
35         char *attrn;
36         int attrnlen;
37         int allocated;
38 };
39
40 struct context {
41         struct attr *attr;
42         int error;
43         char *expr;
44         struct result res;
45 };
46
47 enum error {
48         no_error=0,missing_closing_brace, missing_colon, wrong_type, illegal_number_format, illegal_character, missing_closing_bracket, invalid_type
49 };
50
51 static void eval_comma(struct context *ctx, struct result *res);
52 static struct attr ** eval_list(struct context *ctx);
53
54 static void
55 result_free(struct result *res)
56 {
57 }
58
59 static char *
60 get_op(struct context *ctx, int test, ...)
61 {
62         char *op,*ret=NULL;
63         va_list ap;
64         va_start(ap, test);
65         while ((op = va_arg(ap, char *))) {
66                 if (!strncmp(ctx->expr, op, strlen(op))) {
67                         ret=ctx->expr;
68                         if (! test)
69                                 ctx->expr+=strlen(op);
70                         break;
71                 }
72         }
73         va_end(ap);
74         return ret;
75 }
76
77 static int
78 is_int(struct result *res)
79 {
80         return 1;
81 }
82
83 static int
84 is_double(struct result *res)
85 {
86         return 0;
87 }
88
89 static void
90 dump(struct result *res)
91 {
92         char object[res->varlen+1];
93         char attribute[res->attrnlen+1];
94         if (res->var)
95                 strncpy(object, res->var, res->varlen);
96         object[res->varlen]='\0';
97         if (res->attrn)
98                 strncpy(attribute, res->attrn, res->attrnlen);
99         attribute[res->attrnlen]='\0';
100         dbg(0,"type:%s\n", attr_to_name(res->attr.type));
101         dbg(0,"attribute '%s' from '%s'\n", attribute, object);
102 }
103
104 static enum attr_type
105 command_attr_type(struct result *res)
106 {
107         char attrn[res->attrnlen+1];
108
109         strncpy(attrn, res->attrn, res->attrnlen);
110         attrn[res->attrnlen]='\0';
111         return attr_from_name(attrn);
112 }
113
114 static int
115 command_object_get_attr(struct attr *object, enum attr_type attr_type, struct attr *ret)
116 {
117         struct object_func *func=object_func_lookup(object->type);
118         if (!func || !func->get_attr)
119                 return 0;
120         return func->get_attr(object->u.data, attr_type, ret, NULL);
121 }
122
123 static void
124 command_get_attr(struct context *ctx, struct result *res)
125 {
126         int result;
127         enum attr_type attr_type=command_attr_type(res);
128         result=command_object_get_attr(&res->attr, attr_type, &res->attr);
129         if (result) {
130                 res->var=res->attrn;
131                 res->varlen=res->attrnlen;
132         } else {
133                 res->attr.type=attr_none;
134                 res->var=NULL;
135                 res->varlen=0;
136         }
137         res->attrn=NULL;
138         res->attrnlen=0;
139         dump(res);
140 }
141
142 static void
143 command_set_attr(struct context *ctx, struct result *res, struct result *newres)
144 {
145         int result=0;
146         enum attr_type attr_type=command_attr_type(res);
147         struct object_func *func=object_func_lookup(res->attr.type);
148         if (!func || !func->set_attr)
149                 return;
150         newres->attr.type=attr_type;
151         result=func->set_attr(res->attr.u.data, &newres->attr);
152         *res=*newres;
153 }
154
155 static void
156 resolve_object(struct context *ctx, struct result *res)
157 {
158         if (res->attr.type == attr_none && res->varlen) {
159                 res->attr=*ctx->attr;
160                 res->attrn=res->var;
161                 res->attrnlen=res->varlen;
162                 res->var=NULL;
163                 res->varlen=0;
164         }
165 }
166
167 static void
168 resolve(struct context *ctx, struct result *res, struct attr *parent)
169 {
170         resolve_object(ctx, res);
171         if (res->attr.type >= attr_type_object_begin && res->attr.type <= attr_type_object_end) {
172                 if (res->attrn)
173                         command_get_attr(ctx, res);
174                 return;
175         }
176 }
177
178 static double
179 get_double(struct context *ctx, struct result *res)
180 {
181         resolve(ctx, res, NULL);
182         return res->val;
183 }
184
185
186
187 static int
188 get_int(struct context *ctx, struct result *res)
189 {
190         resolve(ctx, res, NULL);
191         if (res->attr.type == attr_none)
192                 return 0;
193         if (res->attr.type >= attr_type_int_begin && res->attr.type <= attr_type_int_end) {
194                 return res->attr.u.num;
195         }
196         if (res->attr.type >= attr_type_double_begin && res->attr.type <= attr_type_double_end) {
197                 return (int) (*res->attr.u.numd);
198         }
199         ctx->error=wrong_type;
200         return 0;
201 }
202
203
204 static char *
205 get_string(struct context *ctx, struct result *res)
206 {
207         resolve(ctx, res, NULL);
208         return attr_to_text(&res->attr, NULL, 0);
209 }
210
211 static void
212 set_double(struct context *ctx, struct result *res, double val)
213 {
214         result_free(res);
215         res->val=val;
216 }
217
218 static void
219 set_int(struct context *ctx, struct result *res, int val)
220 {
221         result_free(res);
222         res->attr.type=attr_type_int_begin;
223         res->attr.u.num=val;
224 }
225
226
227 static void
228 eval_value(struct context *ctx, struct result *res) {
229         char *op;
230         int len,dots=0;
231         op=ctx->expr;
232         res->varlen=0;
233         res->var=NULL;
234         res->attrnlen=0;
235         res->attrn=NULL;
236         if (op[0] >= 'a' && op[0] <= 'z') {
237                 res->attr.type=attr_none;
238                 res->var=op;
239                 while ((op[0] >= 'a' && op[0] <= 'z') || op[0] == '_') {
240                         res->varlen++;
241                         op++;
242                 }
243                 ctx->expr=op;
244                 return;
245         }
246         if ((op[0] >= '0' && op[0] <= '9') ||
247             (op[0] == '.' && op[1] >= '0' && op[1] <= '9') ||
248             (op[0] == '-' && op[1] >= '0' && op[1] <= '9') ||
249             (op[0] == '-' && op[1] == '.' && op[2] >= '0' && op[2] <= '9')) {
250                 while ((op[0] >= '0' && op[0] <= '9') || op[0] == '.' || (res->varlen == 0 && op[0] == '-')) {
251                         if (op[0] == '.')
252                                 dots++;
253                         if (dots > 1) {
254                                 ctx->error=illegal_number_format;
255                                 return;
256                         }
257                         res->varlen++;
258                         op++;
259                 }
260                 if (dots) {
261                         res->val = strtod(ctx->expr, NULL);
262                         res->attr.type=attr_type_double_begin;
263                         res->attr.u.numd=&res->val;
264                 } else {
265                         res->attr.type=attr_type_int_begin;
266                         res->attr.u.num=atoi(ctx->expr);
267                 }
268                 ctx->expr=op;
269                 return;
270         }
271         if (op[0] == '"') {
272                 do {
273                         op++;
274                 } while (op[0] != '"');
275                 res->attr.type=attr_type_string_begin;
276                 len=op-ctx->expr-1;
277                 res->attr.u.str=g_malloc(len+1);
278                 strncpy(res->attr.u.str, ctx->expr+1, len);
279                 res->attr.u.str[len]='\0';
280                 op++;
281                 ctx->expr=op;
282                 return;
283         }
284         ctx->error=illegal_character;
285 }
286
287 static void
288 eval_brace(struct context *ctx, struct result *res)
289 {
290         if (get_op(ctx,0,"(",NULL)) {
291                 eval_comma(ctx, res);
292                 if (ctx->error) return;
293                 if (!get_op(ctx,0,")",NULL)) 
294                         ctx->error=missing_closing_brace;
295                 return;
296         }
297         eval_value(ctx, res);
298 }
299
300 static void
301 command_call_function(struct context *ctx, struct result *res)
302 {
303         struct attr cbl,**list=NULL;
304         char function[res->attrnlen+1];
305         if (res->attrn)
306                 strncpy(function, res->attrn, res->attrnlen);
307         function[res->attrnlen]='\0';
308         dbg(0,"function=%s\n", function);
309         if (ctx->expr[0] != ')') {
310                 list=eval_list(ctx);    
311                 if (ctx->error) return;
312         }
313         if (!get_op(ctx,0,")",NULL)) {
314                 ctx->error=missing_closing_brace;
315                 return;
316         }
317         if (command_object_get_attr(&res->attr, attr_callback_list, &cbl)) {
318                 int valid;
319                 dbg(0,"function call %s from %s\n",function, attr_to_name(res->attr.type));
320                 callback_list_call_attr_4(cbl.u.callback_list, attr_command, function, list, NULL, &valid);
321         }
322         res->var=NULL;
323         res->varlen=0;
324         res->attrn=NULL;
325         res->attrnlen=0;
326         res->attr.type=attr_none;
327 }
328
329 static void
330 eval_postfix(struct context *ctx, struct result *res)
331 {
332         struct result tmp;
333         char *op;
334
335         eval_brace(ctx, res);
336         if (ctx->error) return;
337         for (;;) {
338                 if (!(op=get_op(ctx,0,"[","(",".",NULL)))
339                         return;
340                 if (op[0] == '.') {
341                         eval_brace(ctx, &tmp);
342                         if (ctx->error) return;
343                         resolve(ctx, res,NULL);
344                         if (ctx->error) return;
345                         res->attrn=tmp.var;
346                         res->attrnlen=tmp.varlen;
347                         dump(res);
348                 } else if (op[0] == '[') {
349                         if (!get_op(ctx,0,"]",NULL)) {
350                                 ctx->error=missing_closing_bracket;
351                                 return;
352                         }
353                 } else if (op[0] == '(') {
354                         dbg(0,"function call\n");
355                         resolve_object(ctx, res);
356                         command_call_function(ctx, res);
357                 }
358         }
359 }
360
361 static void
362 eval_unary(struct context *ctx, struct result *res) 
363 {
364         char *op;
365         op=get_op(ctx,0,"~","!",NULL);
366         if (op) {
367                 eval_unary(ctx, res);
368                 if (ctx->error) return;
369                 if (op[0] == '~')
370                         set_int(ctx, res, ~get_int(ctx, res));
371                 else
372                         set_int(ctx, res, !get_int(ctx, res));
373         } else
374                 eval_postfix(ctx, res);
375 }
376
377 static void
378 eval_multiplicative(struct context *ctx, struct result *res) 
379 {
380         struct result tmp;
381         char *op;
382
383         eval_unary(ctx, res);
384         if (ctx->error) return;
385         for (;;) {
386                 if (!(op=get_op(ctx,0,"*","/","%",NULL))) return;
387                 eval_unary(ctx, &tmp);
388                 if (ctx->error) return;
389                 if (is_double(res) || is_double(&tmp)) {
390                         if (op[0] == '*')
391                                 set_double(ctx, res, get_double(ctx, res) * get_double(ctx, &tmp));
392                         else if (op[0] == '/')
393                                 set_double(ctx, res, get_double(ctx, res) / get_double(ctx, &tmp));
394                         else {
395                                 ctx->error=invalid_type;
396                                 return;
397                         }
398                 } else {
399                         if (op[0] == '*')
400                                 set_int(ctx, res, get_int(ctx, res) * get_int(ctx, &tmp));
401                         else if (op[0] == '/')
402                                 set_int(ctx, res, get_int(ctx, res) / get_int(ctx, &tmp));
403                         else
404                                 set_int(ctx, res, get_int(ctx, res) % get_int(ctx, &tmp));
405                 }
406                 if (ctx->error) return;
407         }
408 }
409
410 static void
411 eval_additive(struct context *ctx, struct result *res) 
412 {
413         struct result tmp;
414         char *op;
415
416         eval_multiplicative(ctx, res);
417         if (ctx->error) return;
418         for (;;) {
419                 if (!(op=get_op(ctx,0,"-","+",NULL))) return;
420                 eval_multiplicative(ctx, &tmp);
421                 if (ctx->error) return;
422                 if (is_double(res) || is_double(&tmp)) {
423                         if (op[0] == '+')
424                                 set_double(ctx, res, get_double(ctx, res) + get_double(ctx, &tmp));
425                         else
426                                 set_double(ctx, res, get_double(ctx, res) - get_double(ctx, &tmp));
427                 } else {
428                         if (op[0] == '+')
429                                 set_int(ctx, res, get_int(ctx, res) + get_int(ctx, &tmp));
430                         else
431                                 set_int(ctx, res, get_int(ctx, res) - get_int(ctx, &tmp));
432                 }
433                 if (ctx->error) return;
434         }
435 }
436
437 static void
438 eval_equality(struct context *ctx, struct result *res) 
439 {
440         struct result tmp;
441         char *op;
442
443         eval_additive(ctx, res);
444         if (ctx->error) return;
445         for (;;) {
446                 if (!(op=get_op(ctx,0,"==","!=",NULL))) return;
447                 eval_additive(ctx, &tmp);
448                 if (ctx->error) return;
449                 if (op[0]  == '=') 
450                         set_int(ctx, res, (get_int(ctx, res) == get_int(ctx, &tmp)));
451                 else
452                         set_int(ctx, res, (get_int(ctx, res) != get_int(ctx, &tmp)));
453                 result_free(&tmp);
454         }
455 }
456
457
458 static void
459 eval_bitwise_and(struct context *ctx, struct result *res) 
460 {
461         struct result tmp;
462
463         eval_equality(ctx, res);
464         if (ctx->error) return;
465         for (;;) {
466                 if (get_op(ctx,1,"&&",NULL)) return;
467                 if (!get_op(ctx,0,"&",NULL)) return;
468                 eval_equality(ctx, &tmp);
469                 if (ctx->error) return;
470                 set_int(ctx, res, get_int(ctx, res) & get_int(ctx, &tmp));
471                 if (ctx->error) return;
472         }
473 }
474
475 static void
476 eval_bitwise_xor(struct context *ctx, struct result *res) 
477 {
478         struct result tmp;
479
480         eval_bitwise_and(ctx, res);
481         if (ctx->error) return;
482         for (;;) {
483                 if (!get_op(ctx,0,"^",NULL)) return;
484                 eval_bitwise_and(ctx, &tmp);
485                 if (ctx->error) return;
486                 set_int(ctx, res, get_int(ctx, res) ^ get_int(ctx, &tmp));
487                 if (ctx->error) return;
488         }
489 }
490
491 static void
492 eval_bitwise_or(struct context *ctx, struct result *res) 
493 {
494         struct result tmp;
495
496         eval_bitwise_xor(ctx, res);
497         if (ctx->error) return;
498         for (;;) {
499                 if (get_op(ctx,1,"||",NULL)) return;
500                 if (!get_op(ctx,0,"|",NULL)) return;
501                 eval_bitwise_xor(ctx, &tmp);
502                 if (ctx->error) return;
503                 set_int(ctx, res, get_int(ctx, res) | get_int(ctx, &tmp));
504                 if (ctx->error) return;
505         }
506 }
507
508 static void
509 eval_logical_and(struct context *ctx, struct result *res) 
510 {
511         struct result tmp;
512
513         eval_bitwise_or(ctx, res);
514         if (ctx->error) return;
515         for (;;) {
516                 if (!get_op(ctx,0,"&&",NULL)) return;
517                 eval_bitwise_or(ctx, &tmp);
518                 if (ctx->error) return;
519                 set_int(ctx, res, get_int(ctx, res) && get_int(ctx, &tmp));
520                 if (ctx->error) return;
521         }
522 }
523
524 static void
525 eval_logical_or(struct context *ctx, struct result *res) 
526 {
527         struct result tmp;
528
529         eval_logical_and(ctx, res);
530         if (ctx->error) return;
531         for (;;) {
532                 if (!get_op(ctx,0,"||",NULL)) return;
533                 eval_logical_and(ctx, &tmp);
534                 if (ctx->error) return;
535                 set_int(ctx, res, get_int(ctx, res) || get_int(ctx, &tmp));
536                 if (ctx->error) return;
537         }
538 }
539
540 static void
541 eval_conditional(struct context *ctx, struct result *res)
542 {
543         struct result tmp;
544         int cond;
545
546         eval_logical_or(ctx, res);
547         if (ctx->error) return;
548         if (!get_op(ctx,0,"?",NULL)) return;
549         cond=!!get_int(ctx, res);
550         if (ctx->error) return;
551         eval_logical_or(ctx, &tmp);
552         if (ctx->error) return;
553         if (cond)
554                 *res=tmp;
555         if (!get_op(ctx,0,":",NULL)) {
556                 ctx->error=missing_colon;
557                 return;
558         }
559         eval_logical_or(ctx, &tmp);
560         if (ctx->error) return;
561         if (!cond)
562                 *res=tmp;
563 }
564
565 /* = *= /= %= += -= >>= <<= &= ^= |= */
566
567 static void
568 eval_assignment(struct context *ctx, struct result *res)
569 {
570         struct result tmp;
571         eval_conditional(ctx, res);
572         if (ctx->error) return;
573         if (!get_op(ctx,0,"=",NULL)) return;
574         eval_conditional(ctx, &tmp);
575         if (ctx->error) return;
576         resolve_object(ctx, res);
577         command_set_attr(ctx, res, &tmp);
578 }
579
580 /* , */
581 static void
582 eval_comma(struct context *ctx, struct result *res)
583 {
584         struct result tmp;
585
586         eval_assignment(ctx, res);
587         if (ctx->error) return;
588         for (;;) {
589                 if (!get_op(ctx,0,",",NULL)) return;
590                 eval_assignment(ctx, &tmp);
591                 if (ctx->error) return;
592                 *res=tmp;
593         }
594 }
595
596 static struct attr **
597 eval_list(struct context *ctx)
598 {
599         struct result tmp;
600
601         struct attr **ret=NULL;
602         for (;;) {
603                 eval_assignment(ctx, &tmp);
604                 if (ctx->error) {
605                         attr_list_free(ret);
606                         return NULL;
607                 }
608                 ret=attr_generic_add_attr(ret, &tmp.attr);
609                 if (!get_op(ctx,0,",",NULL)) return ret;
610         }
611 }
612
613 #if 0
614
615 void command(struct attr *attr, char *expr)
616 {
617         struct result res;
618         struct context ctx;
619         memset(&res, 0, sizeof(res));
620         memset(&ctx, 0, sizeof(ctx));
621         ctx.attr=attr;
622         ctx.error=0;
623         ctx.expr=expr;
624         printf("command='%s'\n", expr);
625         eval_comma(&ctx,&res);
626         printf("err=%d %s\n", ctx.error, ctx.expr);
627         dump(&res);
628         printf("***\n");
629         resolve(&ctx, &res, NULL);
630         dump(&res);
631         printf("%s\n", get_string(&ctx, &res));
632 }
633 #endif
634
635 void
636 command_evaluate_to(struct attr *attr, char *expr, struct context *ctx, struct result *res)
637 {
638         memset(res, 0, sizeof(*res));
639         memset(ctx, 0, sizeof(*ctx));
640         ctx->attr=attr;
641         ctx->expr=expr;
642         eval_comma(ctx,res);
643 }
644
645 void
646 command_evaluate_to_void(struct attr *attr, char *expr, int **error)
647 {
648         struct result res;
649         struct context ctx;
650         command_evaluate_to(attr, expr, &ctx, &res);
651         if (!ctx.error)
652                 resolve(&ctx, &res, NULL);
653         if (error)
654                 *error=ctx.error;
655
656 }
657
658 char *
659 command_evaluate_to_string(struct attr *attr, char *expr, int **error)
660 {
661         struct result res;
662         struct context ctx;
663         char *ret;
664
665         command_evaluate_to(attr, expr, &ctx, &res);
666         if (error)
667                 *error=ctx.error;
668         if (!ctx.error)
669                 ret=get_string(&ctx, &res);
670         if (ctx.error)
671                 return NULL;
672         else
673                 return ret;
674 }
675
676 void
677 command_evaluate(struct attr *attr, char *expr)
678 {
679         struct result res;
680         struct context ctx;
681         memset(&res, 0, sizeof(res));
682         memset(&ctx, 0, sizeof(ctx));
683         ctx.attr=attr;
684         ctx.error=0;
685         ctx.expr=expr;
686         for (;;) {
687                 eval_comma(&ctx,&res);
688                 if (ctx.error)
689                         return;
690                 resolve(&ctx, &res, NULL);
691                 if (ctx.error)
692                         return;
693                 if (!get_op(&ctx,0,";",NULL)) return;
694         }
695 }
696
697 #if 0
698 void
699 command_interpreter(struct attr *attr)
700 {
701                 char buffer[4096];
702                 int size;
703                 for (;;) {
704                 size=read(0, buffer, 4095);
705                 buffer[size]='\0';
706                 if (size) {
707                         buffer[size-1]='\0';
708                 }
709                 command(attr, buffer);
710                 }
711 }
712 #endif
713
714 static void
715 command_table_call(struct command_table *table, int count, void *data, char *command, struct attr **in, struct attr ***out, int *valid)
716 {
717         int i;
718         for (i = 0 ; i < count ; i++) {
719                 if (!strcmp(command,table->command)) {
720                         if (valid)
721                                 *valid=1;
722                         table->func(data, command, in, out);
723                 }
724                 table++;
725         }
726 }
727
728 void
729 command_add_table(struct callback_list *cbl, struct command_table *table, int count, void *data)
730 {
731         struct callback *cb=callback_new_attr_3(callback_cast(command_table_call),attr_command, table, count, data);
732         callback_list_add(cbl, cb);
733 }
734