diff options
author | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2012-12-24 21:36:24 +0000 |
---|---|---|
committer | martin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220> | 2012-12-24 21:36:24 +0000 |
commit | 87e746a48fe089d81958599e67326660b2dcc447 (patch) | |
tree | 66f022f41bd71f3602f984e4d1d6e5a9eeb70d5c /navit/command.c | |
parent | 0a75890350df9afda3cd107db9a8d41605615cdd (diff) | |
download | navit-87e746a48fe089d81958599e67326660b2dcc447.tar.gz |
Add:Core:Beginning of splitting up command.c into parsing/logic and execution part
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@5316 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'navit/command.c')
-rw-r--r-- | navit/command.c | 572 |
1 files changed, 348 insertions, 224 deletions
diff --git a/navit/command.c b/navit/command.c index 886c4454a..9cbcc9f1f 100644 --- a/navit/command.c +++ b/navit/command.c @@ -24,8 +24,7 @@ zoom_in() zoom_out() speech.active=!speech.active osd_configuration=1 -Not yet: -osd[type=="xxx"].active=0;osd[type=="yyy"].active=0 +osd[@type=="xxx"].active=0;osd[@type=="yyy"].active=0 */ @@ -39,9 +38,14 @@ struct result { int allocated; }; +struct result_list { + struct attr **attrs; +}; + struct context { struct attr *attr; int error; + int skip; const char *expr; struct result res; }; @@ -68,9 +72,19 @@ struct command_saved { }; enum error { - no_error=0,missing_closing_brace, missing_colon, wrong_type, illegal_number_format, illegal_character, missing_closing_bracket, invalid_type, not_ready + no_error=0, missing_double_quote, missing_opening_parenthesis, missing_closing_parenthesis, missing_closing_brace, missing_colon, wrong_type, illegal_number_format, illegal_character, missing_closing_bracket, invalid_type, not_ready, internal +}; + +enum op_type { + op_type_binary, op_type_prefix, op_type_suffix }; +enum set_type { + set_type_symbol, set_type_string, set_type_integer, set_type_float +}; + + + static void eval_comma(struct context *ctx, struct result *res); static struct attr ** eval_list(struct context *ctx); @@ -86,6 +100,8 @@ result_free(struct result *res) } } + + static int command_register_callbacks(struct command_saved *cs); static const char * @@ -190,6 +206,8 @@ command_get_attr(struct context *ctx, struct result *res) int result; struct result tmp={{0,},}; enum attr_type attr_type=command_attr_type(res); + if (ctx->skip) + return; result=command_object_get_attr(ctx, &res->attr, attr_type, &tmp.attr); result_free(res); *res=tmp; @@ -213,6 +231,8 @@ command_set_attr(struct context *ctx, struct result *res, struct result *newres) { enum attr_type attr_type=command_attr_type(res); struct object_func *func=object_func_lookup(res->attr.type); + if (ctx->skip) + return; if (!res->attr.u.data || !func || !func->set_attr) return; if (attr_type == attr_attr_types) { @@ -276,6 +296,12 @@ get_int(struct context *ctx, struct result *res) return 0; } +static int +get_bool(struct context *ctx, struct result *res) +{ + return !!get_int(ctx, res); +} + static char * get_string(struct context *ctx, struct result *res) @@ -301,11 +327,164 @@ set_int(struct context *ctx, struct result *res, int val) res->attr.u.num=val; } +static void +result_op(struct context *ctx, enum op_type op_type, const char *op, struct result *inout, struct result *in) +{ + if (ctx->skip) + return; + switch (op_type) { + case op_type_prefix: + switch ((op[0] << 8) || op[1]) { + case ('!' << 8): + resolve(ctx, inout, NULL); + switch (op[1]) { + case '\0': + set_int(ctx, inout, !get_int(ctx, inout)); + return; + } + break; + case ('~' << 8): + resolve(ctx, inout, NULL); + switch (op[1]) { + case '\0': + set_int(ctx, inout, ~get_int(ctx, inout)); + return; + } + break; + } + case op_type_binary: + resolve(ctx, inout, NULL); + resolve(ctx, in, NULL); + switch ((op[0] << 8) | op[1]) { + case ('=' << 8)|'=': + if (inout->attr.type == attr_none || in->attr.type == attr_none) { + set_int(ctx, inout, 0); + } else if (ATTR_IS_STRING(inout->attr.type) && ATTR_IS_STRING(in->attr.type)) { + char *s1=get_string(ctx, inout),*s2=get_string(ctx, in); + set_int(ctx, inout, (!strcmp(s1,s2))); + g_free(s1); + g_free(s2); + } + else + set_int(ctx, inout, (get_int(ctx, inout) == get_int(ctx, in))); + return; + case ('!' << 8)|'=': + if (inout->attr.type == attr_none || in->attr.type == attr_none) { + set_int(ctx, inout, 1); + } else if (ATTR_IS_STRING(inout->attr.type) && ATTR_IS_STRING(in->attr.type)) { + char *s1=get_string(ctx, inout),*s2=get_string(ctx, in); + set_int(ctx, inout, (!!strcmp(s1,s2))); + g_free(s1); + g_free(s2); + } + else + set_int(ctx, inout, (get_int(ctx, inout) != get_int(ctx, in))); + return; + case ('<' << 8): + set_int(ctx, inout, (get_int(ctx, inout) < get_int(ctx, in))); + return; + case ('<' << 8)|'=': + set_int(ctx, inout, (get_int(ctx, inout) <= get_int(ctx, in))); + return; + case ('>' << 8): + set_int(ctx, inout, (get_int(ctx, inout) > get_int(ctx, in))); + return; + case ('>' << 8)|'=': + set_int(ctx, inout, (get_int(ctx, inout) >= get_int(ctx, in))); + return; + case ('*' << 8): + if (is_double(inout) || is_double(in)) + set_double(ctx, inout, get_double(ctx, inout) * get_double(ctx, in)); + else + set_int(ctx, inout, get_int(ctx, inout) * get_int(ctx, in)); + return; + case ('/' << 8): + if (is_double(inout) || is_double(in)) + set_double(ctx, inout, get_double(ctx, inout) * get_double(ctx, in)); + else + set_int(ctx, inout, get_int(ctx, inout) * get_int(ctx, in)); + return; + case ('%' << 8): + set_int(ctx, inout, get_int(ctx, inout) % get_int(ctx, in)); + return; + case ('+' << 8): + if (is_double(inout) || is_double(in)) + set_double(ctx, inout, get_double(ctx, inout) + get_double(ctx, in)); + else + set_int(ctx, inout, get_int(ctx, inout) + get_int(ctx, in)); + return; + case ('-' << 8): + if (is_double(inout) || is_double(in)) + set_int(ctx, inout, get_int(ctx, inout) - get_int(ctx, in)); + else + set_double(ctx, inout, get_double(ctx, inout) - get_double(ctx, in)); + return; + case ('&' << 8): + set_int(ctx, inout, get_int(ctx, inout) & get_int(ctx, in)); + return; + case ('^' << 8): + set_int(ctx, inout, get_int(ctx, inout) ^ get_int(ctx, in)); + return; + case ('|' << 8): + set_int(ctx, inout, get_int(ctx, inout) | get_int(ctx, in)); + return; + case (('&' << 8) | '&'): + set_int(ctx, inout, get_int(ctx, inout) && get_int(ctx, in)); + return; + case (('|' << 8) | '|'): + set_int(ctx, inout, get_int(ctx, inout) || get_int(ctx, in)); + return; + default: + break; + } + default: + break; + } + dbg(0,"Unkown op %d %s\n",op_type,op); + ctx->error=internal; +} + +static void +result_set(struct context *ctx, enum set_type set_type, const char *op, int len, struct result *out) +{ + if (ctx->skip) + return; + switch (set_type) { + case set_type_symbol: + out->attr.type=attr_none; + out->var=op; + out->varlen=len; + return; + case set_type_integer: + out->attr.type=attr_type_int_begin; + out->attr.u.num=atoi(ctx->expr); + return; + case set_type_float: + out->val = strtod(ctx->expr, NULL); + out->attr.type=attr_type_double_begin; + out->attr.u.numd=&out->val; + return; + case set_type_string: + if (len >= 2) { + out->attr.type=attr_type_string_begin; + out->attr.u.str=g_malloc(len-1); + strncpy(out->attr.u.str, op+1, len-2); + out->attr.u.str[len-2]='\0'; + out->allocated=1; + return; + } + break; + default: + break; + } + dbg(0,"unknown set type %d %s\n",set_type,op); + ctx->error=internal; +} static void eval_value(struct context *ctx, struct result *res) { const char *op; - int len,dots=0; + int dots=0; op=ctx->expr; @@ -320,19 +499,16 @@ eval_value(struct context *ctx, struct result *res) { op++; } if ((op[0] >= 'a' && op[0] <= 'z') || (op[0] >= 'A' && op[0] <= 'Z') || op[0] == '_') { - res->attr.type=attr_none; - res->var=op; for (;;) { while ((op[0] >= 'a' && op[0] <= 'z') || (op[0] >= 'A' && op[0] <= 'Z') || (op[0] >= '0' && op[0] <= '9') || op[0] == '_') { - res->varlen++; op++; } if (res->varlen == 3 && !strncmp(res->var,"new",3) && op[0] == ' ') { - res->varlen++; op++; } else break; } + result_set(ctx, set_type_symbol, ctx->expr, op-ctx->expr, res); ctx->expr=op; return; } @@ -347,17 +523,9 @@ eval_value(struct context *ctx, struct result *res) { ctx->error=illegal_number_format; return; } - res->varlen++; op++; } - if (dots) { - res->val = strtod(ctx->expr, NULL); - res->attr.type=attr_type_double_begin; - res->attr.u.numd=&res->val; - } else { - res->attr.type=attr_type_int_begin; - res->attr.u.num=atoi(ctx->expr); - } + result_set(ctx, dots?set_type_float:set_type_integer, ctx->expr, op-ctx->expr, res); ctx->expr=op; return; } @@ -367,14 +535,12 @@ eval_value(struct context *ctx, struct result *res) { op++; op++; } while (op[0] && op[0] != '"'); - res->attr.type=attr_type_string_begin; - len=op-ctx->expr-1; - res->attr.u.str=g_malloc(len+1); - strncpy(res->attr.u.str, ctx->expr+1, len); - res->attr.u.str[len]='\0'; - res->allocated=1; - if(*op) - op++; + if(!*op) { + ctx->error=missing_double_quote; + return; + } + op++; + result_set(ctx, set_type_string, ctx->expr, op-ctx->expr, res); ctx->expr=op; return; } @@ -414,7 +580,7 @@ eval_brace(struct context *ctx, struct result *res) eval_comma(ctx, res); if (ctx->error) return; if (!get_op(ctx,0,")",NULL)) - ctx->error=missing_closing_brace; + ctx->error=missing_closing_parenthesis; return; } eval_value(ctx, res); @@ -438,53 +604,53 @@ command_call_function(struct context *ctx, struct result *res) } if (!get_op(ctx,0,")",NULL)) { attr_list_free(list); - ctx->error=missing_closing_brace; + ctx->error=missing_closing_parenthesis; return; } - - - if (!strcmp(function,"_") && list && list[0] && list[0]->type >= attr_type_string_begin && list[0]->type <= attr_type_string_end) { - result_free(res); - res->attr.type=list[0]->type; - res->attr.u.str=g_strdup(gettext(list[0]->u.str)); - res->allocated=1; - - } else if (!strncmp(function,"new ",4)) { - enum attr_type attr_type=attr_from_name(function+4); - result_free(res); - if (attr_type != attr_none) { - struct object_func *func=object_func_lookup(attr_type); - if (func && func->create) { - res->attr.type=attr_type; - res->attr.u.data=func->create(list[0], list+1); - /* Setting allocated to 1 here will make object to be destroyed when last reference is destroyed. - So created persistent objects should be stored with set_attr_var command. */ - res->allocated=1; - } - } - } else if (!strcmp(function,"add_attr")) { - command_object_add_attr(ctx, &res->attr, list[0]); - } else if (!strcmp(function,"remove_attr")) { - command_object_remove_attr(ctx, &res->attr, list[0]); - } else { - if (command_object_get_attr(ctx, &res->attr, attr_callback_list, &cbl)) { - int valid =0; - 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 (valid!=1){ - dbg(0, "invalid command ignored: \"%s\"; see http://wiki.navit-project.org/index.php/" - "The_Navit_Command_Interface for valid commands.\n", function); + if (!ctx->skip) { + if (!strcmp(function,"_") && list && list[0] && list[0]->type >= attr_type_string_begin && list[0]->type <= attr_type_string_end) { + result_free(res); + res->attr.type=list[0]->type; + res->attr.u.str=g_strdup(gettext(list[0]->u.str)); + res->allocated=1; + + } else if (!strncmp(function,"new ",4)) { + enum attr_type attr_type=attr_from_name(function+4); + result_free(res); + if (attr_type != attr_none) { + struct object_func *func=object_func_lookup(attr_type); + if (func && func->create) { + res->attr.type=attr_type; + res->attr.u.data=func->create(list[0], list+1); + /* Setting allocated to 1 here will make object to be destroyed when last reference is destroyed. + So created persistent objects should be stored with set_attr_var command. */ + res->allocated=1; + } } - if (out && out[0]) { - result_free(res); - attr_dup_content(out[0], &res->attr); - res->allocated=1; - attr_list_free(out); + } else if (!strcmp(function,"add_attr")) { + command_object_add_attr(ctx, &res->attr, list[0]); + } else if (!strcmp(function,"remove_attr")) { + command_object_remove_attr(ctx, &res->attr, list[0]); + } else { + if (command_object_get_attr(ctx, &res->attr, attr_callback_list, &cbl)) { + int valid =0; + 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 (valid!=1){ + dbg(0, "invalid command ignored: \"%s\"; see http://wiki.navit-project.org/index.php/" + "The_Navit_Command_Interface for valid commands.\n", function); + } + if (out && out[0]) { + result_free(res); + attr_dup_content(out[0], &res->attr); + res->allocated=1; + attr_list_free(out); + } else + result_free(res); } else result_free(res); - } else - result_free(res); + } } attr_list_free(list); res->var=NULL; @@ -516,34 +682,36 @@ eval_postfix(struct context *ctx, struct result *res) resolve_object(ctx, res); if (ctx->error) return; if (get_op(ctx,0,"@",NULL)) { - struct object_func *obj_func=object_func_lookup(res->attr.type); - struct attr_iter *iter; - struct attr attr; - enum attr_type attr_type=command_attr_type(res); - void *obj=res->attr.u.data; - if (!obj) { - dbg(0,"no object\n"); - return; - } - if (!obj_func) { - dbg(0,"no object func\n"); - return; - } - if (!obj_func->iter_new || !obj_func->iter_destroy) { - dbg(0,"no iter func\n"); - return; - } - iter = obj_func->iter_new(NULL); - result_free(res); - res->varlen=0; - res->attrn=NULL; - while (obj_func->get_attr(obj, attr_type, &attr, iter)) { - if (command_evaluate_to_boolean(&attr, ctx->expr, &ctx->error)) { - result_free(res); - res->attr=attr; + if (!ctx->skip) { + struct object_func *obj_func=object_func_lookup(res->attr.type); + struct attr_iter *iter; + struct attr attr; + enum attr_type attr_type=command_attr_type(res); + void *obj=res->attr.u.data; + if (!obj) { + dbg(0,"no object\n"); + return; + } + if (!obj_func) { + dbg(0,"no object func\n"); + return; + } + if (!obj_func->iter_new || !obj_func->iter_destroy) { + dbg(0,"no iter func\n"); + return; + } + iter = obj_func->iter_new(NULL); + result_free(res); + res->varlen=0; + res->attrn=NULL; + while (obj_func->get_attr(obj, attr_type, &attr, iter)) { + if (command_evaluate_to_boolean(&attr, ctx->expr, &ctx->error)) { + result_free(res); + res->attr=attr; + } } + obj_func->iter_destroy(iter); } - obj_func->iter_destroy(iter); if (ctx->error) return; ctx->expr+=command_evaluate_to_length(ctx->expr, &ctx->error); } @@ -567,10 +735,7 @@ eval_unary(struct context *ctx, struct result *res) if (op) { eval_unary(ctx, res); if (ctx->error) return; - if (op[0] == '~') - set_int(ctx, res, ~get_int(ctx, res)); - else - set_int(ctx, res, !get_int(ctx, res)); + result_op(ctx, op_type_prefix, op, res, NULL); } else eval_postfix(ctx, res); } @@ -586,31 +751,10 @@ eval_multiplicative(struct context *ctx, struct result *res) for (;;) { if (!(op=get_op(ctx,0,"*","/","%",NULL))) return; eval_unary(ctx, &tmp); - if (ctx->error) { - result_free(&tmp); - return; - } - if (is_double(res) || is_double(&tmp)) { - if (op[0] == '*') - set_double(ctx, res, get_double(ctx, res) * get_double(ctx, &tmp)); - else if (op[0] == '/') - set_double(ctx, res, get_double(ctx, res) / get_double(ctx, &tmp)); - else { - ctx->error=invalid_type; - result_free(&tmp); - return; - } - } else { - if (op[0] == '*') - set_int(ctx, res, get_int(ctx, res) * get_int(ctx, &tmp)); - else if (op[0] == '/') - set_int(ctx, res, get_int(ctx, res) / get_int(ctx, &tmp)); - else - set_int(ctx, res, get_int(ctx, res) % get_int(ctx, &tmp)); - } + if (!ctx->error) + result_op(ctx, op_type_binary, op, res, &tmp); result_free(&tmp); - if (ctx->error) - return; + if (ctx->error) return; } } @@ -625,21 +769,8 @@ eval_additive(struct context *ctx, struct result *res) for (;;) { if (!(op=get_op(ctx,0,"-","+",NULL))) return; eval_multiplicative(ctx, &tmp); - if (ctx->error) { - result_free(&tmp); - return; - } - if (is_double(res) || is_double(&tmp)) { - if (op[0] == '+') - set_double(ctx, res, get_double(ctx, res) + get_double(ctx, &tmp)); - else - set_double(ctx, res, get_double(ctx, res) - get_double(ctx, &tmp)); - } else { - if (op[0] == '+') - set_int(ctx, res, get_int(ctx, res) + get_int(ctx, &tmp)); - else - set_int(ctx, res, get_int(ctx, res) - get_int(ctx, &tmp)); - } + if (!ctx->error) + result_op(ctx, op_type_binary, op, res, &tmp); result_free(&tmp); if (ctx->error) return; } @@ -656,56 +787,10 @@ eval_equality(struct context *ctx, struct result *res) for (;;) { if (!(op=get_op(ctx,0,"==","!=","<=",">=","<",">",NULL))) return; eval_additive(ctx, &tmp); - if (ctx->error) { - result_free(&tmp); - return; - } - - resolve(ctx, res, NULL); - resolve(ctx, &tmp, NULL); - switch (op[0]) { - case '=': - if (res->attr.type == attr_none || tmp.attr.type == attr_none) { - set_int(ctx, res, 0); - } else if (ATTR_IS_STRING(res->attr.type) && ATTR_IS_STRING(tmp.attr.type)) { - char *s1=get_string(ctx, res),*s2=get_string(ctx, &tmp); - set_int(ctx, res, (!strcmp(s1,s2))); - g_free(s1); - g_free(s2); - } - else - set_int(ctx, res, (get_int(ctx, res) == get_int(ctx, &tmp))); - break; - case '!': - if (res->attr.type == attr_none || tmp.attr.type == attr_none) { - set_int(ctx, res, 1); - } else if (ATTR_IS_STRING(res->attr.type) && ATTR_IS_STRING(tmp.attr.type)) { - char *s1=get_string(ctx, res),*s2=get_string(ctx, &tmp); - set_int(ctx, res, (!!strcmp(s1,s2))); - g_free(s1); - g_free(s2); - } - else - set_int(ctx, res, (get_int(ctx, res) != get_int(ctx, &tmp))); - break; - case '<': - if (op[1] == '=') { - set_int(ctx, res, (get_int(ctx, res) <= get_int(ctx, &tmp))); - } else { - set_int(ctx, res, (get_int(ctx, res) < get_int(ctx, &tmp))); - } - break; - case '>': - if (op[1] == '=') { - set_int(ctx, res, (get_int(ctx, res) >= get_int(ctx, &tmp))); - } else { - set_int(ctx, res, (get_int(ctx, res) > get_int(ctx, &tmp))); - } - break; - default: - break; - } + if (!ctx->error) + result_op(ctx, op_type_binary, op, res, &tmp); result_free(&tmp); + if (ctx->error) return; } } @@ -721,11 +806,8 @@ eval_bitwise_and(struct context *ctx, struct result *res) if (get_op(ctx,1,"&&",NULL)) return; if (!get_op(ctx,0,"&",NULL)) return; eval_equality(ctx, &tmp); - if (ctx->error) { - result_free(&tmp); - return; - } - set_int(ctx, res, get_int(ctx, res) & get_int(ctx, &tmp)); + if (!ctx->error) + result_op(ctx, op_type_binary, "&", res, &tmp); result_free(&tmp); if (ctx->error) return; } @@ -741,11 +823,8 @@ eval_bitwise_xor(struct context *ctx, struct result *res) for (;;) { if (!get_op(ctx,0,"^",NULL)) return; eval_bitwise_and(ctx, &tmp); - if (ctx->error) { - result_free(&tmp); - return; - } - set_int(ctx, res, get_int(ctx, res) ^ get_int(ctx, &tmp)); + if (!ctx->error) + result_op(ctx, op_type_binary, "^", res, &tmp); result_free(&tmp); if (ctx->error) return; } @@ -762,11 +841,8 @@ eval_bitwise_or(struct context *ctx, struct result *res) if (get_op(ctx,1,"||",NULL)) return; if (!get_op(ctx,0,"|",NULL)) return; eval_bitwise_xor(ctx, &tmp); - if (ctx->error) { - result_free(&tmp); - return; - } - set_int(ctx, res, get_int(ctx, res) | get_int(ctx, &tmp)); + if (!ctx->error) + result_op(ctx, op_type_binary, "|", res, &tmp); result_free(&tmp); if (ctx->error) return; } @@ -782,11 +858,8 @@ eval_logical_and(struct context *ctx, struct result *res) for (;;) { if (!get_op(ctx,0,"&&",NULL)) return; eval_bitwise_or(ctx, &tmp); - if (ctx->error) { - result_free(&tmp); - return; - } - set_int(ctx, res, get_int(ctx, res) && get_int(ctx, &tmp)); + if (!ctx->error) + result_op(ctx, op_type_binary, "&&", res, &tmp); result_free(&tmp); if (ctx->error) return; } @@ -802,11 +875,8 @@ eval_logical_or(struct context *ctx, struct result *res) for (;;) { if (!get_op(ctx,0,"||",NULL)) return; eval_logical_and(ctx, &tmp); - if (ctx->error) { - result_free(&tmp); - return; - } - set_int(ctx, res, get_int(ctx, res) || get_int(ctx, &tmp)); + if (!ctx->error) + result_op(ctx, op_type_binary, "||", res, &tmp); result_free(&tmp); if (ctx->error) return; } @@ -816,15 +886,19 @@ static void eval_conditional(struct context *ctx, struct result *res) { struct result tmp={{0,},}; - int cond; + int cond=0; + int skip; eval_logical_or(ctx, res); if (ctx->error) return; if (!get_op(ctx,0,"?",NULL)) return; - cond=!!get_int(ctx, res); + skip=ctx->skip; + cond=get_bool(ctx, res); result_free(res); if (ctx->error) return; + ctx->skip=!cond || skip; eval_logical_or(ctx, &tmp); + ctx->skip=skip; if (ctx->error) { result_free(&tmp); return; @@ -838,7 +912,9 @@ eval_conditional(struct context *ctx, struct result *res) ctx->error=missing_colon; return; } + ctx->skip=cond || skip; eval_logical_or(ctx, &tmp); + ctx->skip=skip; if (ctx->error) { result_free(&tmp); return; @@ -1065,6 +1141,64 @@ command_evaluate_to_length(const char *expr, int *error) return 0; } +int +command_evaluate_single(struct context *ctx) +{ + struct result res={{0,},}; + const char *op; + int cond=0; + int skip=ctx->skip; + if (!(op=get_op(ctx,0,"if","{",NULL))) { + eval_comma(ctx,&res); + if (ctx->error) + return 0; + resolve(ctx, &res, NULL); + result_free(&res); + if (ctx->error) + return 0; + return get_op(ctx,0,";",NULL) != NULL; + } + switch (op[0]) { + case 'i': + if (!get_op(ctx,0,"(",NULL)) { + ctx->error=missing_opening_parenthesis; + return 0; + } + eval_comma(ctx,&res); + if (!skip && !ctx->error) + cond=get_bool(ctx, &res); + result_free(&res); + if (ctx->error) + return 0; + if (!get_op(ctx,0,")",NULL)) { + ctx->error=missing_closing_parenthesis; + return 0; + } + ctx->skip=!cond || skip; + command_evaluate_single(ctx); + ctx->skip=skip; + if (ctx->error) + return 0; + if (get_op(ctx,0,"else",NULL)) { + ctx->skip=cond || skip; + command_evaluate_single(ctx); + ctx->skip=skip; + if (ctx->error) + return 0; + } + return 1; + case '{': + while (command_evaluate_single(ctx)); + if (!get_op(ctx,0,"}",NULL)) { + ctx->error=missing_closing_brace; + return 0; + } + return 1; + default: + return 0; + } +} + void command_evaluate(struct attr *attr, const char *expr) { @@ -1073,22 +1207,12 @@ command_evaluate(struct attr *attr, const char *expr) * subsequent command call. Hence the g_strdup. */ char *expr_dup; - struct result res={{0,},}; struct context ctx={0,}; ctx.attr=attr; ctx.error=0; ctx.expr=expr_dup=g_strdup(expr); for (;;) { - eval_comma(&ctx,&res); - if (ctx.error) - break; - resolve(&ctx, &res, NULL); - - result_free(&res); - - if (ctx.error) - break; - if (!get_op(&ctx,0,";",NULL)) + if (!command_evaluate_single(&ctx)) break; } g_free(expr_dup); |