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

Contents of /navit/navit/command.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (8 years, 2 months ago) by zoff99
File MIME type: text/plain
File size: 24645 byte(s)
import files
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 #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 callback_list_add(cbl, attr.u.callback);
923 }
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