From d3547c531866a3140188d861bf10ba11791de5e5 Mon Sep 17 00:00:00 2001 From: Thomas Porzelt Date: Sun, 17 Aug 2008 02:28:57 +0200 Subject: [PATCH] added option_copy(); fixed variable statements in config parser where assignments without parser func lead to OPTION_NONE options --- src/config_parser.rl | 22 +++++++++++++++++----- src/options.c | 35 +++++++++++++++++++++++++++++++++++ src/options.h | 2 ++ 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/config_parser.rl b/src/config_parser.rl index 4ea6897..45c9df4 100644 --- a/src/config_parser.rl +++ b/src/config_parser.rl @@ -317,19 +317,21 @@ action actionref { /* varname is on the stack */ - option *o, *r; + option *o, *r, *t; o = g_queue_pop_head(ctx->option_stack); /* action refs starting with "var." are user defined variables */ if (g_str_has_prefix(o->value.opt_string->str, "var.")) { - /* look up var in hashtable, push option onto stack */ - r = g_hash_table_lookup(ctx->uservars, o->value.opt_string); + /* look up var in hashtable, copy and push option onto stack */ + t = g_hash_table_lookup(ctx->uservars, o->value.opt_string); - if (r == NULL) { + if (t == NULL) { log_warning(srv, NULL, "unknown variable '%s'", o->value.opt_string->str); return FALSE; } + + r = option_copy(t); } else { /* real action, lookup hashtable and create new action option */ @@ -471,6 +473,16 @@ option_free(val); } + /* internal functions */ + else if (g_str_equal(name->value.opt_string->str, "__print")) { + g_printerr("%s:%zd type: %s", ctx->filename, ctx->line, option_type_string(val->type)); + switch (val->type) { + case OPTION_INT: g_printerr(", value: %d\n", val->value.opt_int); break; + case OPTION_STRING: g_printerr(", value: %s\n", val->value.opt_string->str); break; + default: g_printerr("\n"); + } + } + /* normal function action */ else { /* TODO */ if (ctx->in_setup_block) { @@ -679,7 +691,7 @@ string = ( '"' (any-'"')* '"' ) %string; # advanced types - varname = ( (alpha ( alnum | [._] )*) - boolean ) >mark %varname; + varname = ( '__' ? (alpha ( alnum | [._] )*) - boolean ) >mark %varname; actionref = ( varname ) %actionref; list = ( '(' >list_start ); hash = ( '[' >hash_start ); diff --git a/src/options.c b/src/options.c index 4998c68..aaab683 100644 --- a/src/options.c +++ b/src/options.c @@ -63,6 +63,41 @@ option* option_new_condition(server *srv, condition *c) { return opt; } +option* option_copy(option* opt) { + option *n; + + switch (opt->type) { + case OPTION_NONE: n = option_new_bool(FALSE); n->type = OPTION_NONE; return n; /* hack */ + case OPTION_BOOLEAN: return option_new_bool(opt->value.opt_bool); + case OPTION_INT: return option_new_int(opt->value.opt_int); + case OPTION_STRING: return option_new_string(g_string_new_len(GSTR_LEN(opt->value.opt_string))); + /* list: we have to copy every option in the list! */ + case OPTION_LIST: + n = option_new_list(); + g_array_set_size(n->value.opt_list, opt->value.opt_list->len); + for (guint i = 0; i < opt->value.opt_list->len; i++) + //g_array_insert_val((*(n->value.opt_list)), i, option_copy(g_array_index(opt->value.opt_list, option*, i))); + g_array_insert_vals(n->value.opt_list, i, option_copy(g_array_index(opt->value.opt_list, option*, i)), 1); + return n; + /* hash: iterate over hashtable, clone each option */ + case OPTION_HASH: + n = option_new_hash(); + { + GHashTableIter iter; + gpointer k, v; + g_hash_table_iter_init(&iter, opt->value.opt_hash); + while (g_hash_table_iter_next(&iter, &k, &v)) + g_hash_table_insert(n->value.opt_hash, g_string_new_len(GSTR_LEN((GString*)k)), option_copy((option*)v)); + } + return n; + /* TODO: does it make sense to clone action and condition options? */ + case OPTION_ACTION: + case OPTION_CONDITION: + assert(NULL); + return NULL; + } +} + void option_free(option* opt) { if (!opt) return; diff --git a/src/options.h b/src/options.h index 14b7537..951097b 100644 --- a/src/options.h +++ b/src/options.h @@ -56,6 +56,8 @@ LI_API option* option_new_list(); LI_API option* option_new_hash(); LI_API option* option_new_action(server *srv, action *a); LI_API option* option_new_condition(server *srv, condition *c); + +LI_API option* option_copy(option* opt); LI_API void option_free(option* opt); LI_API const char* option_type_string(option_type type);