cfg framework: cfg_select() and cfg_reset() added
authorMiklos Tirpak <miklos@iptel.org>
Mon, 4 Oct 2010 13:35:59 +0000 (15:35 +0200)
committerMiklos Tirpak <miklos@iptel.org>
Mon, 4 Oct 2010 13:35:59 +0000 (15:35 +0200)
cfg_select("group_name", "var_name") can be used to move a group
handle to a specifig group instance in the script. Evey variable
access within that group will be made from the new group instance
until the handle is reset, practically until the end of the script
unless cfg_reset("group_name") is explicitely called.
This is true both for custom, module, and core variables, i.e. every
configuration group can have multiple set of values.

action.c
cfg.lex
cfg.y
route.c
route_struct.h

index 8349ff9..317b192 100644 (file)
--- a/action.c
+++ b/action.c
@@ -93,6 +93,7 @@
 #endif
 #include "switch.h"
 #include "events.h"
+#include "cfg/cfg_struct.h"
 
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -1463,6 +1464,40 @@ match_cleanup:
                        msg->rpl_send_flags.f|= SND_F_CON_CLOSE;
                        ret=1; /* continue processing */
                        break;
+               case CFG_SELECT_T:
+                       if (a->val[0].type != CFG_GROUP_ST) {
+                               BUG("unsupported parameter in CFG_SELECT_T: %d\n",
+                                               a->val[0].type);
+                               ret=-1;
+                               goto error;
+                       }
+                       switch(a->val[1].type) {
+                               case NUMBER_ST:
+                                       v=(int)a->val[1].u.number;
+                                       break;
+                               case RVE_ST:
+                                       if (rval_expr_eval_int(h, msg, &v, (struct rval_expr*)a->val[1].u.data) < 0) {
+                                               ret=-1;
+                                               goto error;
+                                       }
+                                       break;
+                               default:
+                                       BUG("unsupported group id type in CFG_SELECT_T: %d\n",
+                                                       a->val[1].type);
+                                       ret=-1;
+                                       goto error;
+                       }
+                       ret=(cfg_select((cfg_group_t*)a->val[0].u.data, v) == 0) ? 1 : -1;
+                       break;
+               case CFG_RESET_T:
+                       if (a->val[0].type != CFG_GROUP_ST) {
+                               BUG("unsupported parameter in CFG_RESET_T: %d\n",
+                                               a->val[0].type);
+                               ret=-1;
+                               goto error;
+                       }
+                       ret=(cfg_reset((cfg_group_t*)a->val[0].u.data) == 0) ? 1 : -1;
+                       break;
 /*
                default:
                        LOG(L_CRIT, "BUG: do_action: unknown type %d\n", a->type);
diff --git a/cfg.lex b/cfg.lex
index 11822ea..07c7b90 100644 (file)
--- a/cfg.lex
+++ b/cfg.lex
@@ -251,6 +251,9 @@ WHILE                       "while"
 
 INCLUDEFILE     "include_file"
 
+CFG_SELECT     "cfg_select"
+CFG_RESET      "cfg_reset"
+
 /*ACTION LVALUES*/
 URIHOST                        "uri:host"
 URIPORT                        "uri:port"
@@ -635,6 +638,9 @@ SUBST       subst
 
 <INITIAL>{INCLUDEFILE}  { count(); BEGIN(INCLF); }
 
+<INITIAL>{CFG_SELECT}  { count(); yylval.strval=yytext; return CFG_SELECT; }
+<INITIAL>{CFG_RESET}   { count(); yylval.strval=yytext; return CFG_RESET; }
+
 <INITIAL>{URIHOST}     { count(); yylval.strval=yytext; return URIHOST; }
 <INITIAL>{URIPORT}     { count(); yylval.strval=yytext; return URIPORT; }
 
diff --git a/cfg.y b/cfg.y
index c43792b..9f913c6 100644 (file)
--- a/cfg.y
+++ b/cfg.y
  * 2010-02-17  added blacklist imask (DST_BLST_*_IMASK) support (andrei)
 */
 
-%expect 5
+%expect 6
 
 %{
 
@@ -347,6 +347,8 @@ extern char *finame;
 %token CASE
 %token DEFAULT
 %token WHILE
+%token CFG_SELECT
+%token CFG_RESET
 %token URIHOST
 %token URIPORT
 %token MAX_LEN
@@ -3259,6 +3261,19 @@ cmd:
        | SET_RPL_CLOSE {
                $$=mk_action(SET_RPL_CLOSE_T, 0); set_cfg_pos($$);
        }
+       | CFG_SELECT LPAREN STRING COMMA NUMBER RPAREN {
+               $$=mk_action(CFG_SELECT_T, 2, STRING_ST, $3, NUMBER_ST, (void*)$5); set_cfg_pos($$);
+       }
+       | CFG_SELECT LPAREN STRING COMMA rval_expr RPAREN {
+               $$=mk_action(CFG_SELECT_T, 2, STRING_ST, $3, RVE_ST, $5); set_cfg_pos($$);
+       }
+       | CFG_SELECT error { $$=0; yyerror("missing '(' or ')' ?"); }
+       | CFG_SELECT LPAREN error RPAREN { $$=0; yyerror("bad arguments, string and number expected"); }
+       | CFG_RESET LPAREN STRING RPAREN {
+               $$=mk_action(CFG_RESET_T, 1, STRING_ST, $3); set_cfg_pos($$);
+       }
+       | CFG_RESET error { $$=0; yyerror("missing '(' or ')' ?"); }
+       | CFG_RESET LPAREN error RPAREN { $$=0; yyerror("bad arguments, string expected"); }
        | ID {mod_func_action = mk_action(MODULE0_T, 2, MODEXP_ST, NULL, NUMBER_ST,
                        0); } LPAREN func_params RPAREN {
                mod_func_action->val[0].u.data =
diff --git a/route.c b/route.c
index 45de184..dbdbf78 100644 (file)
--- a/route.c
+++ b/route.c
@@ -94,6 +94,7 @@
 #include "ut.h"
 #include "rvalue.h"
 #include "switch.h"
+#include "cfg/cfg_struct.h"
 
 #define RT_HASH_SIZE   8 /* route names hash */
 
@@ -1149,6 +1150,60 @@ int fix_actions(struct action* a)
                                        goto error;
                                }
                                break;
+                       case CFG_SELECT_T:
+                               if (t->val[1].type == RVE_ST) {
+                                       rve = t->val[1].u.data;
+                                       if (rve_is_constant(rve)) {
+                                               /* if expression is constant => evaluate it
+                                                  as integer and replace it with the corresp.
+                                                  int */
+                                               rv = rval_expr_eval(0, 0, rve);
+                                               if (rv == 0 ||
+                                                               rval_get_int( 0, 0, &i, rv, 0) < 0 ) {
+                                                       ERR("failed to fix constant rve");
+                                                       if (rv) rval_destroy(rv);
+                                                       ret = E_BUG;
+                                                       goto error;
+                                               }
+                                               rval_destroy(rv);
+                                               rve_destroy(rve);
+                                               t->val[1].type = NUMBER_ST;
+                                               t->val[1].u.number = i;
+                                       } else {
+                                               /* expression is not constant => fixup &
+                                                  optimize it */
+                                               if ((ret=fix_rval_expr(rve))
+                                                               < 0) {
+                                                       ERR("rve fixup failed\n");
+                                                       ret = E_BUG;
+                                                       goto error;
+                                               }
+                                       }
+                               } else if (t->val[1].type != NUMBER_ST) {
+                                       BUG("invalid subtype %d for cfg_select()\n",
+                                                               t->val[1].type);
+                                       ret = E_BUG;
+                                       goto error;
+                               }
+
+                       case CFG_RESET_T:
+                               if (t->val[0].type != STRING_ST) {
+                                       BUG("invalid subtype %d for cfg_select() or cfg_reset()\n",
+                                                               t->val[0].type);
+                                       ret = E_BUG;
+                                       goto error;
+                               }
+                               tmp_p = (void *)cfg_lookup_group(t->val[0].u.string, strlen(t->val[0].u.string));
+                               if (!tmp_p) {
+                                       ERR("configuration group \"%s\" not found\n",
+                                               t->val[0].u.string);
+                                       ret = E_SCRIPT;
+                                       goto error;
+                               }
+                               pkg_free(t->val[0].u.string);
+                               t->val[0].u.data = tmp_p;
+                               t->val[0].type = CFG_GROUP_ST;
+                               break;
                        default:
                                /* no fixup required for the rest */
                                break;
index 2d4a643..9c504d1 100644 (file)
@@ -115,7 +115,9 @@ enum action_type{
                SET_FWD_NO_CONNECT_T,
                SET_RPL_NO_CONNECT_T,
                SET_FWD_CLOSE_T,
-               SET_RPL_CLOSE_T
+               SET_RPL_CLOSE_T,
+               CFG_SELECT_T,
+               CFG_RESET_T
 };
 /* parameter types for actions or types for expression right operands
    (WARNING right operands only, not working for left operands) */
@@ -130,7 +132,8 @@ enum _operand_subtype{
                SELECT_UNFIXED_ST,
                STRING_RVE_ST /* RVE converted to a string (fparam hack) */,
                RVE_FREE_FIXUP_ST /* (str)RVE fixed up by a reversable fixup */,
-               FPARAM_DYN_ST /* temporary only (fparam hack) */
+               FPARAM_DYN_ST /* temporary only (fparam hack) */,
+               CFG_GROUP_ST
 };
 
 typedef enum _expr_l_type expr_l_type;