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