* fix conffiles
[navit-package] / navit / command.c
index 2fd6382..6872522 100644 (file)
 #include "debug.h"
 #include "callback.h"
 #include "command.h"
+#include "event.h"
+#include "navit_nls.h"
 
 /*
-gui.fullscreen()
+gui.fullscreen=!gui.fullscreen
 gui.menu()
 gui.get_data() 
 zoom_in() 
@@ -78,59 +80,16 @@ result_free(struct result *res)
 
 static int command_register_callbacks(struct command_saved *cs);
 
-static int
-get_next_object(struct context *ctx, struct result *res) {
-       char *op, *tmp;
-       op=ctx->expr;
-       res->varlen=0;
-       res->var=NULL;
-       res->attrnlen=0;
-       res->attrn=NULL;
-       
-       while (*op) {
-               if (op[0] == '"') {
-                       while (*op && (op[0] != '"')) {
-                               op++;
-                       }
-               }
-
-               if (op[0] >= 'a' && op[0] <= 'z') {
-                       res->attr.type=attr_none;
-                       res->var=op;
-                       while ((op[0] >= 'a' && op[0] <= 'z') || op[0] == '_') {
-                               res->varlen++;
-                               op++;
-                       }
-
-                       // If there is a bracket following, this is a function
-                       tmp = op;
-                       while (*tmp && g_ascii_isspace(*tmp)) {
-                               tmp++;
-                       }
-                       if (tmp[0] == '(') {
-                               continue;
-                       }
-
-                       ctx->expr=op;
-
-                       if (op[0] == '.') {
-                               return 2;                               // 2 means "more object names following"
-                       } else {
-                               return 1;                               // 1 means "no more object names following"
-                       }
-               }
-               
-               op++;
-       }
-
-       return 0;
-}
-
 static char *
 get_op(struct context *ctx, int test, ...)
 {
        char *op,*ret=NULL;
        va_list ap;
+
+       while (g_ascii_isspace(*ctx->expr)) {
+               ctx->expr++;
+       }
+
        va_start(ap, test);
        while ((op = va_arg(ap, char *))) {
                if (!strncmp(ctx->expr, op, strlen(op))) {
@@ -144,11 +103,11 @@ get_op(struct context *ctx, int test, ...)
        return ret;
 }
 
-static int
+/*static int
 is_int(struct result *res)
 {
        return 1;
-}
+}*/
 
 static int
 is_double(struct result *res)
@@ -159,6 +118,7 @@ is_double(struct result *res)
 static void
 dump(struct result *res)
 {
+#if 0
        char object[res->varlen+1];
        char attribute[res->attrnlen+1];
        if (res->var)
@@ -169,6 +129,7 @@ dump(struct result *res)
        attribute[res->attrnlen]='\0';
        dbg(0,"type:%s\n", attr_to_name(res->attr.type));
        dbg(0,"attribute '%s' from '%s'\n", attribute, object);
+#endif
 }
 
 static enum attr_type
@@ -238,11 +199,8 @@ static void
 resolve(struct context *ctx, struct result *res, struct attr *parent) //FIXME What is that parent for?
 {
        resolve_object(ctx, res);
-       if (res->attr.type >= attr_type_object_begin && res->attr.type <= attr_type_object_end) {
-               if (res->attrn)
-                       command_get_attr(ctx, res);
-               return;
-       }
+       if (res->attrn)
+               command_get_attr(ctx, res);
 }
 
 static double
@@ -303,12 +261,24 @@ eval_value(struct context *ctx, struct result *res) {
        res->var=NULL;
        res->attrnlen=0;
        res->attrn=NULL;
-       if (op[0] >= 'a' && op[0] <= 'z') {
+
+       while (g_ascii_isspace(*op)) {
+               op++;
+       }
+
+       if ((op[0] >= 'a' && op[0] <= 'z') || op[0] == '_') {
                res->attr.type=attr_none;
                res->var=op;
-               while ((op[0] >= 'a' && op[0] <= 'z') || op[0] == '_') {
-                       res->varlen++;
-                       op++;
+               for (;;) {
+                       while ((op[0] >= 'a' && op[0] <= 'z') || op[0] == '_') {
+                               res->varlen++;
+                               op++;
+                       }
+                       if (res->varlen == 3 && !strncmp(res->var,"new",3) && op[0] == ' ') {
+                               res->varlen++;
+                               op++;
+                       } else
+                               break;
                }
                ctx->expr=op;
                return;
@@ -354,6 +324,32 @@ eval_value(struct context *ctx, struct result *res) {
        ctx->error=illegal_character;
 }
 
+static int
+get_next_object(struct context *ctx, struct result *res) {
+       
+       while (*ctx->expr) {
+               res->varlen = 0;
+               ctx->error = 0;
+
+               eval_value(ctx,res);
+               
+               if ((res->attr.type == attr_none) && (res->varlen > 0)) {
+                       if (ctx->expr[0] != '.') {
+                               return 1;               // 1 means "this is the final object name"
+                       } else {
+                               return 2;               // 2 means "there are more object names following" (e.g. we just hit 'vehicle' in 'vehicle.position_speed'
+                       }
+               }
+
+               if (ctx->error) {
+                       // Probably hit an operator
+                       ctx->expr++;
+               }
+       }
+
+       return 0;
+}
+
 static void
 eval_brace(struct context *ctx, struct result *res)
 {
@@ -375,7 +371,7 @@ command_call_function(struct context *ctx, struct result *res)
        if (res->attrn)
                strncpy(function, res->attrn, res->attrnlen);
        function[res->attrnlen]='\0';
-       dbg(0,"function=%s\n", function);
+       dbg(1,"function=%s\n", function);
        if (ctx->expr[0] != ')') {
                list=eval_list(ctx);    
                if (ctx->error) return;
@@ -384,16 +380,37 @@ command_call_function(struct context *ctx, struct result *res)
                ctx->error=missing_closing_brace;
                return;
        }
-       if (command_object_get_attr(ctx, &res->attr, attr_callback_list, &cbl)) {
-               int valid;
-               dbg(0,"function call %s from %s\n",function, attr_to_name(res->attr.type));
-               callback_list_call_attr_4(cbl.u.callback_list, attr_command, function, list, NULL, &valid);
+       if (!strcmp(function,"_") && list && list[0] && list[0]->type >= attr_type_string_begin && list[0]->type <= attr_type_string_end) {
+               res->attr.type=list[0]->type;
+               res->attr.u.str=g_strdup(gettext(list[0]->u.str));      
+               
+       } else if (!strncmp(function,"new ",4)) {
+               enum attr_type attr_type=attr_from_name(function+4);
+               if (attr_type != attr_none) {
+                       struct object_func *func=object_func_lookup(attr_type);
+                       if (func && func->new) {
+                               res->attr.type=attr_type;
+                               res->attr.u.data=func->new(NULL, list);
+                       }
+               }
+       } else {
+               if (command_object_get_attr(ctx, &res->attr, attr_callback_list, &cbl)) {
+                       int valid;
+                       struct attr **out=NULL;
+                       dbg(1,"function call %s from %s\n",function, attr_to_name(res->attr.type));
+                       callback_list_call_attr_4(cbl.u.callback_list, attr_command, function, list, &out, &valid);
+                       if (out && out[0]) {
+                               attr_dup_content(out[0], &res->attr);
+                               attr_list_free(out);
+                       } else
+                               res->attr.type=attr_none;
+               } else
+                       res->attr.type=attr_none;
        }
        res->var=NULL;
        res->varlen=0;
        res->attrn=NULL;
        res->attrnlen=0;
-       res->attr.type=attr_none;
 }
 
 static void
@@ -421,7 +438,7 @@ eval_postfix(struct context *ctx, struct result *res)
                                return;
                        }
                } else if (op[0] == '(') {
-                       dbg(0,"function call\n");
+                       dbg(1,"function call\n");
                        resolve_object(ctx, res);
                        command_call_function(ctx, res);
                }
@@ -664,6 +681,8 @@ eval_assignment(struct context *ctx, struct result *res)
        if (!get_op(ctx,0,"=",NULL)) return;
        eval_conditional(ctx, &tmp);
        if (ctx->error) return;
+       resolve(ctx, &tmp, NULL);
+       if (ctx->error) return;
        resolve_object(ctx, res);
        command_set_attr(ctx, res, &tmp);
 }
@@ -696,6 +715,7 @@ eval_list(struct context *ctx)
                        attr_list_free(ret);
                        return NULL;
                }
+               resolve(ctx, &tmp, NULL);
                ret=attr_generic_add_attr(ret, &tmp.attr);
                if (!get_op(ctx,0,",",NULL)) return ret;
        }
@@ -723,7 +743,7 @@ void command(struct attr *attr, char *expr)
 }
 #endif
 
-void
+static void
 command_evaluate_to(struct attr *attr, char *expr, struct context *ctx, struct result *res)
 {
        memset(res, 0, sizeof(*res));
@@ -742,7 +762,7 @@ command_evaluate_to_void(struct attr *attr, char *expr, int **error)
        if (!ctx.error)
                resolve(&ctx, &res, NULL);
        if (error)
-               *error=ctx.error;
+               *error=&ctx.error;
 
 }
 
@@ -751,13 +771,15 @@ command_evaluate_to_string(struct attr *attr, char *expr, int **error)
 {
        struct result res;
        struct context ctx;
-       char *ret;
+       char *ret=NULL;
 
        command_evaluate_to(attr, expr, &ctx, &res);
        if (!ctx.error)
+               resolve(&ctx, &res, NULL);
+       if (!ctx.error)
                ret=get_string(&ctx, &res);
        if (error)
-               *error=ctx.error;
+               *error=&ctx.error;
        if (ctx.error)
                return NULL;
        else
@@ -769,19 +791,48 @@ command_evaluate_to_int(struct attr *attr, char *expr, int **error)
 {
        struct result res;
        struct context ctx;
-       char *ret;
+       int ret=0;
 
        command_evaluate_to(attr, expr, &ctx, &res);
        if (!ctx.error)
+               resolve(&ctx, &res, NULL);
+       if (!ctx.error)
                ret=get_int(&ctx, &res);
        if (error)
-               *error=ctx.error;
+               *error=&ctx.error;
        if (ctx.error)
                return 0;
        else
                return ret;
 }
 
+int
+command_evaluate_to_boolean(struct attr *attr, char *expr, int **error)
+{
+       struct result res;
+       struct context ctx;
+       int ret=0;
+
+       command_evaluate_to(attr, expr, &ctx, &res);
+       if (!ctx.error)
+               resolve(&ctx, &res, NULL);
+       if (!ctx.error) {
+               if (res.attr.type == attr_none)
+                       ret=0;
+               else if ((res.attr.type >= attr_type_int_begin && res.attr.type <= attr_type_int_end) ||
+                        (res.attr.type >= attr_type_double_begin && res.attr.type <= attr_type_double_end))
+                       ret=get_int(&ctx, &res);
+               else 
+                       ret=res.attr.u.data != NULL;
+       }
+       if (error)
+               *error=&ctx.error;
+       if (ctx.error)
+               return 0;
+       else    
+               return ret;
+}
+
 void
 command_evaluate(struct attr *attr, char *expr)
 {
@@ -835,10 +886,18 @@ command_table_call(struct command_table *table, int count, void *data, char *com
 }
 
 void
+command_add_table_attr(struct command_table *table, int count, void *data, struct attr *attr)
+{
+       attr->type=attr_callback;
+       attr->u.callback=callback_new_attr_3(callback_cast(command_table_call),attr_command, table, count, data);
+}
+
+void
 command_add_table(struct callback_list *cbl, struct command_table *table, int count, void *data)
 {
-       struct callback *cb=callback_new_attr_3(callback_cast(command_table_call),attr_command, table, count, data);
-       callback_list_add(cbl, cb);
+       struct attr attr;
+       command_add_table_attr(table, count, data, &attr);
+       callback_list_add(cbl, attr.u.callback);
 }
 
 void