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