/[zanavi_public1]/navit/navit/command.c
ZANavi

Contents of /navit/navit/command.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (hide annotations) (download)
Wed Mar 4 14:00:54 2015 UTC (9 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 24687 byte(s)
new market version, lots of fixes
1 zoff99 2 #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     #include "event.h"
17     #include "navit_nls.h"
18    
19     /*
20     gui.fullscreen=!gui.fullscreen
21     gui.menu()
22     gui.get_data()
23     zoom_in()
24     zoom_out()
25     speech.active=!speech.active
26     osd_configuration=1
27     Not yet:
28     osd[type=="xxx"].active=0;osd[type=="yyy"].active=0
29     */
30    
31    
32     struct result {
33     struct attr attr;
34     double val;
35     const char *var;
36     int varlen;
37     const char *attrn;
38     int attrnlen;
39     int allocated;
40     };
41    
42     struct context {
43     struct attr *attr;
44     int error;
45     const char *expr;
46     struct result res;
47     };
48    
49     struct command_saved_cb {
50     struct callback *cb;
51     struct attr attr;
52     };
53    
54     struct command_saved {
55     struct context ctx;
56     struct result res;
57     char *command; // The command string itself
58     struct event_idle *idle_ev; // Event to update this command
59     struct callback *idle_cb;
60     struct callback *register_cb; // Callback to register all the callbacks
61     struct event_idle *register_ev; // Idle event to register all the callbacks
62     struct attr navit;
63     int num_cbs;
64     struct command_saved_cb *cbs; // List of callbacks for this saved command
65     struct callback *cb; // Callback that should be called when we re-evaluate
66     int error;
67     };
68    
69     enum error {
70     no_error=0,missing_closing_brace, missing_colon, wrong_type, illegal_number_format, illegal_character, missing_closing_bracket, invalid_type, not_ready
71     };
72    
73     static void eval_comma(struct context *ctx, struct result *res);
74     static struct attr ** eval_list(struct context *ctx);
75    
76     static void
77     result_free(struct result *res)
78     {
79     }
80    
81     static int command_register_callbacks(struct command_saved *cs);
82    
83     static const char *
84     get_op(struct context *ctx, int test, ...)
85     {
86     char *op;
87     const char *ret=NULL;
88     va_list ap;
89    
90     while (g_ascii_isspace(*ctx->expr)) {
91     ctx->expr++;
92     }
93    
94     va_start(ap, test);
95     while ((op = va_arg(ap, char *))) {
96     if (!strncmp(ctx->expr, op, strlen(op))) {
97     ret=ctx->expr;
98     if (! test)
99     ctx->expr+=strlen(op);
100     break;
101     }
102     }
103     va_end(ap);
104     return ret;
105     }
106    
107     /*static int
108     is_int(struct result *res)
109     {
110     return 1;
111     }*/
112    
113     static int
114     is_double(struct result *res)
115     {
116     return 0;
117     }
118    
119     static void
120     dump(struct result *res)
121     {
122     #if 0
123     char object[res->varlen+1];
124     char attribute[res->attrnlen+1];
125     if (res->var)
126     strncpy(object, res->var, res->varlen);
127     object[res->varlen]='\0';
128     if (res->attrn)
129     strncpy(attribute, res->attrn, res->attrnlen);
130     attribute[res->attrnlen]='\0';
131     dbg(0,"type:%s\n", attr_to_name(res->attr.type));
132     dbg(0,"attribute '%s' from '%s'\n", attribute, object);
133     #endif
134     }
135    
136     static enum attr_type
137     command_attr_type(struct result *res)
138     {
139     char *attrn=g_alloca(sizeof(char)*(res->attrnlen+1));
140    
141     strncpy(attrn, res->attrn, res->attrnlen);
142     attrn[res->attrnlen]='\0';
143     return attr_from_name(attrn);
144     }
145    
146     static int
147     command_object_get_attr(struct context *ctx, struct attr *object, enum attr_type attr_type, struct attr *ret)
148     {
149     struct object_func *func=object_func_lookup(object->type);
150     if (!func || !func->get_attr)
151     return 0;
152     return func->get_attr(object->u.data, attr_type, ret, NULL);
153     }
154    
155     static void
156     command_get_attr(struct context *ctx, struct result *res)
157     {
158     int result;
159     enum attr_type attr_type=command_attr_type(res);
160     result=command_object_get_attr(ctx, &res->attr, attr_type, &res->attr);
161     if (result) {
162     res->var=res->attrn;
163     res->varlen=res->attrnlen;
164     } else {
165     res->attr.type=attr_none;
166     res->var=NULL;
167     res->varlen=0;
168     }
169     res->attrn=NULL;
170     res->attrnlen=0;
171     dump(res);
172     }
173    
174     static void
175     command_set_attr(struct context *ctx, struct result *res, struct result *newres)
176     {
177     int result=0;
178     enum attr_type attr_type=command_attr_type(res);
179     struct object_func *func=object_func_lookup(res->attr.type);
180     if (!func || !func->set_attr)
181     return;
182     newres->attr.type=attr_type;
183     result=func->set_attr(res->attr.u.data, &newres->attr);
184     *res=*newres;
185     }
186    
187     static void
188     resolve_object(struct context *ctx, struct result *res)
189     {
190     if (res->attr.type == attr_none && res->varlen) {
191     res->attr=*ctx->attr;
192     res->attrn=res->var;
193     res->attrnlen=res->varlen;
194     res->var=NULL;
195     res->varlen=0;
196     }
197     }
198    
199     static void
200     resolve(struct context *ctx, struct result *res, struct attr *parent) //FIXME What is that parent for?
201     {
202     resolve_object(ctx, res);
203     if (res->attrn)
204     command_get_attr(ctx, res);
205     }
206    
207     static double
208     get_double(struct context *ctx, struct result *res)
209     {
210     resolve(ctx, res, NULL);
211     return res->val;
212     }
213    
214    
215    
216     static int
217     get_int(struct context *ctx, struct result *res)
218     {
219     resolve(ctx, res, NULL);
220     if (res->attr.type == attr_none)
221     return 0;
222     if (res->attr.type >= attr_type_int_begin && res->attr.type <= attr_type_int_end) {
223     return res->attr.u.num;
224     }
225     if (res->attr.type >= attr_type_double_begin && res->attr.type <= attr_type_double_end) {
226     return (int) (*res->attr.u.numd);
227     }
228     ctx->error=wrong_type;
229     return 0;
230     }
231    
232    
233     static char *
234     get_string(struct context *ctx, struct result *res)
235     {
236     resolve(ctx, res, NULL);
237     return attr_to_text(&res->attr, NULL, 0);
238     }
239    
240     static void
241     set_double(struct context *ctx, struct result *res, double val)
242     {
243     result_free(res);
244     res->val=val;
245     }
246    
247     static void
248     set_int(struct context *ctx, struct result *res, int val)
249     {
250     result_free(res);
251     res->attr.type=attr_type_int_begin;
252     res->attr.u.num=val;
253     }
254    
255    
256     static void
257     eval_value(struct context *ctx, struct result *res) {
258     const char *op;
259     int len,dots=0;
260     op=ctx->expr;
261     res->varlen=0;
262     res->var=NULL;
263     res->attrnlen=0;
264     res->attrn=NULL;
265    
266     while (g_ascii_isspace(*op)) {
267     op++;
268     }
269    
270     if ((op[0] >= 'a' && op[0] <= 'z') || op[0] == '_') {
271     res->attr.type=attr_none;
272     res->var=op;
273     for (;;) {
274     while ((op[0] >= 'a' && op[0] <= 'z') || (op[0] >= '0' && op[0] <= '9') || op[0] == '_') {
275     res->varlen++;
276     op++;
277     }
278     if (res->varlen == 3 && !strncmp(res->var,"new",3) && op[0] == ' ') {
279     res->varlen++;
280     op++;
281     } else
282     break;
283     }
284     ctx->expr=op;
285     return;
286     }
287     if ((op[0] >= '0' && op[0] <= '9') ||
288     (op[0] == '.' && op[1] >= '0' && op[1] <= '9') ||
289     (op[0] == '-' && op[1] >= '0' && op[1] <= '9') ||
290     (op[0] == '-' && op[1] == '.' && op[2] >= '0' && op[2] <= '9')) {
291     while ((op[0] >= '0' && op[0] <= '9') || op[0] == '.' || (res->varlen == 0 && op[0] == '-')) {
292     if (op[0] == '.')
293     dots++;
294     if (dots > 1) {
295     ctx->error=illegal_number_format;
296     return;
297     }
298     res->varlen++;
299     op++;
300     }
301     if (dots) {
302     res->val = strtod(ctx->expr, NULL);
303     res->attr.type=attr_type_double_begin;
304     res->attr.u.numd=&res->val;
305     } else {
306     res->attr.type=attr_type_int_begin;
307     res->attr.u.num=atoi(ctx->expr);
308     }
309     ctx->expr=op;
310     return;
311     }
312     if (op[0] == '"') {
313     do {
314     op++;
315     } while (op[0] != '"');
316     res->attr.type=attr_type_string_begin;
317     len=op-ctx->expr-1;
318     res->attr.u.str=g_malloc(len+1);
319     strncpy(res->attr.u.str, ctx->expr+1, len);
320     res->attr.u.str[len]='\0';
321     op++;
322     ctx->expr=op;
323     return;
324     }
325     ctx->error=illegal_character;
326     }
327    
328     static int
329     get_next_object(struct context *ctx, struct result *res) {
330    
331     while (*ctx->expr) {
332     res->varlen = 0;
333     ctx->error = 0;
334    
335     eval_value(ctx,res);
336    
337     if ((res->attr.type == attr_none) && (res->varlen > 0)) {
338     if (ctx->expr[0] != '.') {
339     return 1; // 1 means "this is the final object name"
340     } else {
341     return 2; // 2 means "there are more object names following" (e.g. we just hit 'vehicle' in 'vehicle.position_speed'
342     }
343     }
344    
345     if (ctx->error) {
346     // Probably hit an operator
347     ctx->expr++;
348     }
349     }
350    
351     return 0;
352     }
353    
354     static void
355     eval_brace(struct context *ctx, struct result *res)
356     {
357     if (get_op(ctx,0,"(",NULL)) {
358     eval_comma(ctx, res);
359     if (ctx->error) return;
360     if (!get_op(ctx,0,")",NULL))
361     ctx->error=missing_closing_brace;
362     return;
363     }
364     eval_value(ctx, res);
365     }
366    
367     static void
368     command_call_function(struct context *ctx, struct result *res)
369     {
370     struct attr cbl,**list=NULL;
371     char *function=g_alloca(sizeof(char)*(res->attrnlen+1));
372     if (res->attrn)
373     strncpy(function, res->attrn, res->attrnlen);
374     function[res->attrnlen]='\0';
375     dbg(1,"function=%s\n", function);
376     if (ctx->expr[0] != ')') {
377     list=eval_list(ctx);
378     if (ctx->error) return;
379     }
380     if (!get_op(ctx,0,")",NULL)) {
381     ctx->error=missing_closing_brace;
382     return;
383     }
384     if (!strcmp(function,"_") && list && list[0] && list[0]->type >= attr_type_string_begin && list[0]->type <= attr_type_string_end) {
385     res->attr.type=list[0]->type;
386     res->attr.u.str=g_strdup(gettext(list[0]->u.str));
387    
388     } else if (!strncmp(function,"new ",4)) {
389     enum attr_type attr_type=attr_from_name(function+4);
390     if (attr_type != attr_none) {
391     struct object_func *func=object_func_lookup(attr_type);
392     if (func && func->create) {
393     res->attr.type=attr_type;
394     res->attr.u.data=func->create(NULL, list);
395     }
396     }
397     } else {
398     if (command_object_get_attr(ctx, &res->attr, attr_callback_list, &cbl)) {
399     int valid;
400     struct attr **out=NULL;
401     dbg(1,"function call %s from %s\n",function, attr_to_name(res->attr.type));
402     callback_list_call_attr_4(cbl.u.callback_list, attr_command, function, list, &out, &valid);
403     if (out && out[0]) {
404     attr_dup_content(out[0], &res->attr);
405     attr_list_free(out);
406     } else
407     res->attr.type=attr_none;
408     } else
409     res->attr.type=attr_none;
410     }
411     res->var=NULL;
412     res->varlen=0;
413     res->attrn=NULL;
414     res->attrnlen=0;
415     }
416    
417     static void
418     eval_postfix(struct context *ctx, struct result *res)
419     {
420     struct result tmp;
421     const char *op;
422    
423     eval_brace(ctx, res);
424     if (ctx->error) return;
425     for (;;) {
426     if (!(op=get_op(ctx,0,"[","(",".",NULL)))
427     return;
428     if (op[0] == '.') {
429     eval_brace(ctx, &tmp);
430     if (ctx->error) return;
431     resolve(ctx, res,NULL);
432     if (ctx->error) return;
433     res->attrn=tmp.var;
434     res->attrnlen=tmp.varlen;
435     dump(res);
436     } else if (op[0] == '[') {
437     if (!get_op(ctx,0,"]",NULL)) {
438     ctx->error=missing_closing_bracket;
439     return;
440     }
441     } else if (op[0] == '(') {
442     dbg(1,"function call\n");
443     resolve_object(ctx, res);
444     command_call_function(ctx, res);
445     }
446     }
447     }
448    
449     static void
450     eval_unary(struct context *ctx, struct result *res)
451     {
452     const char *op;
453     op=get_op(ctx,0,"~","!",NULL);
454     if (op) {
455     eval_unary(ctx, res);
456     if (ctx->error) return;
457     if (op[0] == '~')
458     set_int(ctx, res, ~get_int(ctx, res));
459     else
460     set_int(ctx, res, !get_int(ctx, res));
461     } else
462     eval_postfix(ctx, res);
463     }
464    
465     static void
466     eval_multiplicative(struct context *ctx, struct result *res)
467     {
468     struct result tmp;
469     const char *op;
470    
471     eval_unary(ctx, res);
472     if (ctx->error) return;
473     for (;;) {
474     if (!(op=get_op(ctx,0,"*","/","%",NULL))) return;
475     eval_unary(ctx, &tmp);
476     if (ctx->error) return;
477     if (is_double(res) || is_double(&tmp)) {
478     if (op[0] == '*')
479     set_double(ctx, res, get_double(ctx, res) * get_double(ctx, &tmp));
480     else if (op[0] == '/')
481     set_double(ctx, res, get_double(ctx, res) / get_double(ctx, &tmp));
482     else {
483     ctx->error=invalid_type;
484     return;
485     }
486     } else {
487     if (op[0] == '*')
488     set_int(ctx, res, get_int(ctx, res) * get_int(ctx, &tmp));
489     else if (op[0] == '/')
490     set_int(ctx, res, get_int(ctx, res) / get_int(ctx, &tmp));
491     else
492     set_int(ctx, res, get_int(ctx, res) % get_int(ctx, &tmp));
493     }
494     if (ctx->error) return;
495     }
496     }
497    
498     static void
499     eval_additive(struct context *ctx, struct result *res)
500     {
501     struct result tmp;
502     const char *op;
503    
504     eval_multiplicative(ctx, res);
505     if (ctx->error) return;
506     for (;;) {
507     if (!(op=get_op(ctx,0,"-","+",NULL))) return;
508     eval_multiplicative(ctx, &tmp);
509     if (ctx->error) return;
510     if (is_double(res) || is_double(&tmp)) {
511     if (op[0] == '+')
512     set_double(ctx, res, get_double(ctx, res) + get_double(ctx, &tmp));
513     else
514     set_double(ctx, res, get_double(ctx, res) - get_double(ctx, &tmp));
515     } else {
516     if (op[0] == '+')
517     set_int(ctx, res, get_int(ctx, res) + get_int(ctx, &tmp));
518     else
519     set_int(ctx, res, get_int(ctx, res) - get_int(ctx, &tmp));
520     }
521     if (ctx->error) return;
522     }
523     }
524    
525     static void
526     eval_equality(struct context *ctx, struct result *res)
527     {
528     struct result tmp;
529     const char *op;
530    
531     eval_additive(ctx, res);
532     if (ctx->error) return;
533     for (;;) {
534     if (!(op=get_op(ctx,0,"==","!=","<=",">=","<",">",NULL))) return;
535     eval_additive(ctx, &tmp);
536     if (ctx->error) return;
537    
538     switch (op[0]) {
539     case '=':
540     set_int(ctx, res, (get_int(ctx, res) == get_int(ctx, &tmp)));
541     break;
542     case '!':
543     set_int(ctx, res, (get_int(ctx, res) != get_int(ctx, &tmp)));
544     break;
545     case '<':
546     if (op[1] == '=') {
547     set_int(ctx, res, (get_int(ctx, res) <= get_int(ctx, &tmp)));
548     } else {
549     set_int(ctx, res, (get_int(ctx, res) < get_int(ctx, &tmp)));
550     }
551     break;
552     case '>':
553     if (op[1] == '=') {
554     set_int(ctx, res, (get_int(ctx, res) >= get_int(ctx, &tmp)));
555     } else {
556     set_int(ctx, res, (get_int(ctx, res) > get_int(ctx, &tmp)));
557     }
558     break;
559     default:
560     break;
561     }
562     result_free(&tmp);
563     }
564     }
565    
566    
567     static void
568     eval_bitwise_and(struct context *ctx, struct result *res)
569     {
570     struct result tmp;
571    
572     eval_equality(ctx, res);
573     if (ctx->error) return;
574     for (;;) {
575     if (get_op(ctx,1,"&&",NULL)) return;
576     if (!get_op(ctx,0,"&",NULL)) return;
577     eval_equality(ctx, &tmp);
578     if (ctx->error) return;
579     set_int(ctx, res, get_int(ctx, res) & get_int(ctx, &tmp));
580     if (ctx->error) return;
581     }
582     }
583    
584     static void
585     eval_bitwise_xor(struct context *ctx, struct result *res)
586     {
587     struct result tmp;
588    
589     eval_bitwise_and(ctx, res);
590     if (ctx->error) return;
591     for (;;) {
592     if (!get_op(ctx,0,"^",NULL)) return;
593     eval_bitwise_and(ctx, &tmp);
594     if (ctx->error) return;
595     set_int(ctx, res, get_int(ctx, res) ^ get_int(ctx, &tmp));
596     if (ctx->error) return;
597     }
598     }
599    
600     static void
601     eval_bitwise_or(struct context *ctx, struct result *res)
602     {
603     struct result tmp;
604    
605     eval_bitwise_xor(ctx, res);
606     if (ctx->error) return;
607     for (;;) {
608     if (get_op(ctx,1,"||",NULL)) return;
609     if (!get_op(ctx,0,"|",NULL)) return;
610     eval_bitwise_xor(ctx, &tmp);
611     if (ctx->error) return;
612     set_int(ctx, res, get_int(ctx, res) | get_int(ctx, &tmp));
613     if (ctx->error) return;
614     }
615     }
616    
617     static void
618     eval_logical_and(struct context *ctx, struct result *res)
619     {
620     struct result tmp;
621    
622     eval_bitwise_or(ctx, res);
623     if (ctx->error) return;
624     for (;;) {
625     if (!get_op(ctx,0,"&&",NULL)) return;
626     eval_bitwise_or(ctx, &tmp);
627     if (ctx->error) return;
628     set_int(ctx, res, get_int(ctx, res) && get_int(ctx, &tmp));
629     if (ctx->error) return;
630     }
631     }
632    
633     static void
634     eval_logical_or(struct context *ctx, struct result *res)
635     {
636     struct result tmp;
637    
638     eval_logical_and(ctx, res);
639     if (ctx->error) return;
640     for (;;) {
641     if (!get_op(ctx,0,"||",NULL)) return;
642     eval_logical_and(ctx, &tmp);
643     if (ctx->error) return;
644     set_int(ctx, res, get_int(ctx, res) || get_int(ctx, &tmp));
645     if (ctx->error) return;
646     }
647     }
648    
649     static void
650     eval_conditional(struct context *ctx, struct result *res)
651     {
652     struct result tmp;
653     int cond;
654    
655     eval_logical_or(ctx, res);
656     if (ctx->error) return;
657     if (!get_op(ctx,0,"?",NULL)) return;
658     cond=!!get_int(ctx, res);
659     if (ctx->error) return;
660     eval_logical_or(ctx, &tmp);
661     if (ctx->error) return;
662     if (cond)
663     *res=tmp;
664     if (!get_op(ctx,0,":",NULL)) {
665     ctx->error=missing_colon;
666     return;
667     }
668     eval_logical_or(ctx, &tmp);
669     if (ctx->error) return;
670     if (!cond)
671     *res=tmp;
672     }
673    
674     /* = *= /= %= += -= >>= <<= &= ^= |= */
675    
676     static void
677     eval_assignment(struct context *ctx, struct result *res)
678     {
679     struct result tmp;
680     eval_conditional(ctx, res);
681     if (ctx->error) return;
682     if (!get_op(ctx,0,"=",NULL)) return;
683     eval_conditional(ctx, &tmp);
684     if (ctx->error) return;
685     resolve(ctx, &tmp, NULL);
686     if (ctx->error) return;
687     resolve_object(ctx, res);
688     command_set_attr(ctx, res, &tmp);
689     }
690    
691     /* , */
692     static void
693     eval_comma(struct context *ctx, struct result *res)
694     {
695     struct result tmp;
696    
697     eval_assignment(ctx, res);
698     if (ctx->error) return;
699     for (;;) {
700     if (!get_op(ctx,0,",",NULL)) return;
701     eval_assignment(ctx, &tmp);
702     if (ctx->error) return;
703     *res=tmp;
704     }
705     }
706    
707     static struct attr **
708     eval_list(struct context *ctx)
709     {
710     struct result tmp;
711    
712     struct attr **ret=NULL;
713     for (;;) {
714     eval_assignment(ctx, &tmp);
715     if (ctx->error) {
716     attr_list_free(ret);
717     return NULL;
718     }
719     resolve(ctx, &tmp, NULL);
720     ret=attr_generic_add_attr(ret, &tmp.attr);
721     if (!get_op(ctx,0,",",NULL)) return ret;
722     }
723     }
724    
725     #if 0
726    
727     void command(struct attr *attr, char *expr)
728     {
729     struct result res;
730     struct context ctx;
731     memset(&res, 0, sizeof(res));
732     memset(&ctx, 0, sizeof(ctx));
733     ctx.attr=attr;
734     ctx.error=0;
735     ctx.expr=expr;
736     printf("command='%s'\n", expr);
737     eval_comma(&ctx,&res);
738     printf("err=%d %s\n", ctx.error, ctx.expr);
739     dump(&res);
740     printf("***\n");
741     resolve(&ctx, &res, NULL);
742     dump(&res);
743     printf("%s\n", get_string(&ctx, &res));
744     }
745     #endif
746    
747     static void
748     command_evaluate_to(struct attr *attr, const char *expr, struct context *ctx, struct result *res)
749     {
750     memset(res, 0, sizeof(*res));
751     memset(ctx, 0, sizeof(*ctx));
752     ctx->attr=attr;
753     ctx->expr=expr;
754     eval_comma(ctx,res);
755     }
756    
757     enum attr_type
758     command_evaluate_to_attr(struct attr *attr, char *expr, int *error, struct attr *ret)
759     {
760     struct result res;
761     struct context ctx;
762     command_evaluate_to(attr, expr, &ctx, &res);
763     if (ctx.error)
764     return attr_none;
765     resolve_object(&ctx, &res);
766     *ret=res.attr;
767     dbg(0,"type %s\n",attr_to_name(command_attr_type(&res)));
768     return command_attr_type(&res);
769     }
770    
771     void
772     command_evaluate_to_void(struct attr *attr, char *expr, int *error)
773     {
774     struct result res;
775     struct context ctx;
776     command_evaluate_to(attr, expr, &ctx, &res);
777     if (!ctx.error)
778     resolve(&ctx, &res, NULL);
779     if (error)
780     *error=ctx.error;
781    
782     }
783    
784     char *
785     command_evaluate_to_string(struct attr *attr, char *expr, int *error)
786     {
787     struct result res;
788     struct context ctx;
789     char *ret=NULL;
790    
791     command_evaluate_to(attr, expr, &ctx, &res);
792     if (!ctx.error)
793     resolve(&ctx, &res, NULL);
794     if (!ctx.error)
795     ret=get_string(&ctx, &res);
796     if (error)
797     *error=ctx.error;
798     if (ctx.error)
799     return NULL;
800     else
801     return ret;
802     }
803    
804     int
805     command_evaluate_to_int(struct attr *attr, char *expr, int *error)
806     {
807     struct result res;
808     struct context ctx;
809     int ret=0;
810    
811     command_evaluate_to(attr, expr, &ctx, &res);
812     if (!ctx.error)
813     resolve(&ctx, &res, NULL);
814     if (!ctx.error)
815     ret=get_int(&ctx, &res);
816     if (error)
817     *error=ctx.error;
818     if (ctx.error)
819     return 0;
820     else
821     return ret;
822     }
823    
824     int
825     command_evaluate_to_boolean(struct attr *attr, const char *expr, int *error)
826     {
827     struct result res;
828     struct context ctx;
829     int ret=0;
830    
831     command_evaluate_to(attr, expr, &ctx, &res);
832     if (!ctx.error)
833     resolve(&ctx, &res, NULL);
834     if (!ctx.error) {
835     if (res.attr.type == attr_none)
836     ret=0;
837     else if ((res.attr.type >= attr_type_int_begin && res.attr.type <= attr_type_int_end) ||
838     (res.attr.type >= attr_type_double_begin && res.attr.type <= attr_type_double_end))
839     ret=get_int(&ctx, &res);
840     else
841     ret=res.attr.u.data != NULL;
842     }
843     if (error)
844     *error=ctx.error;
845     if (ctx.error)
846     return 0;
847     else
848     return ret;
849     }
850    
851     void
852     command_evaluate(struct attr *attr, const char *expr)
853     {
854     /* Once the eval has started we can't rely anymore on the content of
855     * expr which may be freed when the calling widget is destroyed by a
856     * subsequent command call. Hence the g_strdup. */
857    
858     char *expr_dup;
859     struct result res;
860     struct context ctx;
861     memset(&res, 0, sizeof(res));
862     memset(&ctx, 0, sizeof(ctx));
863     ctx.attr=attr;
864     ctx.error=0;
865     ctx.expr=expr_dup=g_strdup(expr);
866     for (;;) {
867     eval_comma(&ctx,&res);
868     if (ctx.error)
869     break;
870     resolve(&ctx, &res, NULL);
871     if (ctx.error)
872     break;
873     if (!get_op(&ctx,0,";",NULL))
874     break;
875     }
876     g_free(expr_dup);
877     }
878    
879     #if 0
880     void
881     command_interpreter(struct attr *attr)
882     {
883     char buffer[4096];
884     int size;
885     for (;;) {
886     size=read(0, buffer, 4095);
887     buffer[size]='\0';
888     if (size) {
889     buffer[size-1]='\0';
890     }
891     command(attr, buffer);
892     }
893     }
894     #endif
895    
896     static void
897     command_table_call(struct command_table *table, int count, void *data, char *command, struct attr **in, struct attr ***out, int *valid)
898     {
899     int i;
900     for (i = 0 ; i < count ; i++) {
901     if (!strcmp(command,table->command)) {
902     if (valid)
903     *valid=1;
904     table->func(data, command, in, out);
905     }
906     table++;
907     }
908     }
909    
910     void
911     command_add_table_attr(struct command_table *table, int count, void *data, struct attr *attr)
912     {
913     attr->type=attr_callback;
914     attr->u.callback=callback_new_attr_3(callback_cast(command_table_call),attr_command, table, count, data);
915     }
916    
917     void
918     command_add_table(struct callback_list *cbl, struct command_table *table, int count, void *data)
919     {
920     struct attr attr;
921     command_add_table_attr(table, count, data, &attr);
922 zoff99 40 /// -------**++**-- DISABLE --**++**---- callback_list_add(cbl, attr.u.callback);
923 zoff99 2 }
924    
925     void
926     command_saved_set_cb (struct command_saved *cs, struct callback *cb)
927     {
928     cs->cb = cb;
929     }
930    
931     int
932     command_saved_get_int (struct command_saved *cs)
933     {
934     return get_int(&cs->ctx, &cs->res);
935     }
936    
937     int
938     command_saved_error (struct command_saved *cs)
939     {
940     return cs->error;
941     }
942    
943     static void
944     command_saved_evaluate_idle (struct command_saved *cs)
945     {
946     // Only run once at a time
947     if (cs->idle_ev) {
948     event_remove_idle(cs->idle_ev);
949     cs->idle_ev = NULL;
950     }
951    
952     command_evaluate_to(&cs->navit, cs->command, &cs->ctx, &cs->res);
953    
954     if (!cs->ctx.error) {
955     cs->error = 0;
956    
957     if (cs->cb) {
958     callback_call_1(cs->cb, cs);
959     }
960     } else {
961     cs->error = cs->ctx.error;
962     }
963     }
964    
965     static void
966     command_saved_evaluate(struct command_saved *cs)
967     {
968     if (cs->idle_ev) {
969     // We're already scheduled for reevaluation
970     return;
971     }
972    
973     if (!cs->idle_cb) {
974     cs->idle_cb = callback_new_1(callback_cast(command_saved_evaluate_idle), cs);
975     }
976    
977     cs->idle_ev = event_add_idle(100, cs->idle_cb);
978     }
979    
980     static void
981     command_saved_callbacks_changed(struct command_saved *cs)
982     {
983     // For now, we delete each and every callback and then re-create them
984     int i;
985     struct object_func *func;
986     struct attr attr;
987    
988     if (cs->register_ev) {
989     event_remove_idle(cs->register_ev);
990     cs->register_ev = NULL;
991     }
992    
993     attr.type = attr_callback;
994    
995     for (i = 0; i < cs->num_cbs; i++) {
996     func = object_func_lookup(cs->cbs[i].attr.type);
997    
998     if (!func->remove_attr) {
999     dbg(0, "Could not remove command-evaluation callback because remove_attr is missing for type %i!\n", cs->cbs[i].attr.type);
1000     continue;
1001     }
1002    
1003     attr.u.callback = cs->cbs[i].cb;
1004    
1005     func->remove_attr(cs->cbs[i].attr.u.data, &attr);
1006     callback_destroy(cs->cbs[i].cb);
1007     }
1008    
1009     g_free(cs->cbs);
1010     cs->cbs = NULL;
1011     cs->num_cbs = 0;
1012    
1013     // Now, re-create all the callbacks
1014     command_register_callbacks(cs);
1015     }
1016    
1017     static int
1018     command_register_callbacks(struct command_saved *cs)
1019     {
1020     struct attr prev,cb_attr,attr;
1021     int status;
1022     struct object_func *func;
1023     struct callback *cb;
1024    
1025     attr = cs->navit;
1026     cs->ctx.expr = cs->command;
1027     cs->ctx.attr = &attr;
1028     prev = cs->navit;
1029    
1030     while ((status = get_next_object(&cs->ctx, &cs->res)) != 0) {
1031     resolve(&cs->ctx, &cs->res, NULL);
1032    
1033     if (cs->ctx.error || (cs->res.attr.type == attr_none)) {
1034     // We could not resolve an object, perhaps because it has not been created
1035     return 0;
1036     }
1037    
1038     if (prev.type != attr_none) {
1039     func = object_func_lookup(prev.type);
1040    
1041     if (func->add_attr) {
1042     if (status == 2) { // This is not the final attribute name
1043     cb = callback_new_attr_1(callback_cast(command_saved_callbacks_changed), cs->res.attr.type, (void*)cs);
1044     attr = cs->res.attr;
1045     } else if (status == 1) { // This is the final attribute name
1046     cb = callback_new_attr_1(callback_cast(command_saved_evaluate), cs->res.attr.type, (void*)cs);
1047     cs->ctx.attr = &cs->navit;
1048     } else {
1049     dbg(0, "Error: Strange status returned from get_next_object()\n");
1050     }
1051    
1052     cs->num_cbs++;
1053     cs->cbs = g_realloc(cs->cbs, (sizeof(struct command_saved_cb) * cs->num_cbs));
1054     cs->cbs[cs->num_cbs-1].cb = cb;
1055     cs->cbs[cs->num_cbs-1].attr = prev;
1056    
1057     cb_attr.u.callback = cb;
1058     cb_attr.type = attr_callback;
1059    
1060     func->add_attr(prev.u.data, &cb_attr);
1061    
1062     } else {
1063     dbg(0, "Could not add callback because add_attr is missing for type %i}n", prev.type);
1064     }
1065     }
1066    
1067     if (status == 2) {
1068     prev = cs->res.attr;
1069     } else {
1070     prev = cs->navit;
1071     }
1072     }
1073    
1074     command_saved_evaluate_idle(cs);
1075    
1076     return 1;
1077     }
1078    
1079     struct command_saved
1080     *command_saved_new(char *command, struct navit *navit, struct callback *cb)
1081     {
1082     struct command_saved *ret;
1083    
1084     ret = g_new0(struct command_saved, 1);
1085     ret->command = g_strdup(command);
1086     ret->navit.u.navit = navit;
1087     ret->navit.type = attr_navit;
1088     ret->cb = cb;
1089     ret->error = not_ready;
1090    
1091     if (!command_register_callbacks(ret)) {
1092     // We try this as an idle call again
1093     ret->register_cb = callback_new_1(callback_cast(command_saved_callbacks_changed), ret);
1094     ret->register_ev = event_add_idle(300, ret->register_cb);
1095     }
1096    
1097     return ret;
1098     }
1099    
1100     void
1101     command_saved_destroy(struct command_saved *cs)
1102     {
1103     g_free(cs->command);
1104     g_free(cs);
1105     }

   
Visit the ZANavi Wiki