Skip to content

Commit

Permalink
core: added selval(evalexpr, valexp1, valexpr2)
Browse files Browse the repository at this point in the history
- this is a core statement that return the 2nd parameter if the 1st
parameter is evaluated to true, or 3rd parameter if the 1st parameter is
evaluated to false
- it can be considered a core function that is equivalent of ternary
condition/operator
- example:
  $var(x) = selval($Ts mod 2, "true/" + $ru, "false/" + $rd);
- the first parameter is a conditional expression, like those used for
IF, the 2nd and 3rd parameters can be expressions like those used in the
right side of assignments
  • Loading branch information
miconda committed Feb 8, 2021
1 parent 120c471 commit d11a125
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/core/cfg.lex
Expand Up @@ -258,6 +258,7 @@ MODULO "mod"
STRLEN "strlen"
STREMPTY "strempty"
DEFINED "defined"
SELVAL "selval"
STREQ eq
INTEQ ieq
STRDIFF ne
Expand Down Expand Up @@ -1041,6 +1042,7 @@ IMPORTFILE "import_file"
<INITIAL>{INTDIFF} { count(); return INTDIFF; }
<INITIAL>{INTCAST} { count(); return INTCAST; }
<INITIAL>{STRCAST} { count(); return STRCAST; }
<INITIAL>{SELVAL} { count(); return SELVAL; }

<INITIAL>{SELECT_MARK} { count(); state = SELECT_S; BEGIN(SELECT); return SELECT_MARK; }
<SELECT>{ID} { count(); addstr(&s_buf, yytext, yyleng);
Expand Down
11 changes: 11 additions & 0 deletions src/core/cfg.y
Expand Up @@ -149,6 +149,7 @@ static pv_spec_t* pv_spec = NULL;
static struct action *mod_func_action = NULL;
static struct lvalue* lval_tmp = NULL;
static struct rvalue* rval_tmp = NULL;
static struct rval_expr* rve_tmp = NULL;

static void warn(char* s, ...);
static void warn_at(struct cfg_pos* pos, char* s, ...);
Expand Down Expand Up @@ -560,6 +561,7 @@ extern char *default_routename;
/* no precedence, they use () */
%token STRLEN
%token STREMPTY
%token SELVAL

/* values */
%token <intval> NUMBER
Expand Down Expand Up @@ -3031,6 +3033,14 @@ rval_expr: rval { $$=$1;
| STRLEN LPAREN rval_expr RPAREN { $$=mk_rve1(RVE_STRLEN_OP, $3);}
| STREMPTY LPAREN rval_expr RPAREN {$$=mk_rve1(RVE_STREMPTY_OP, $3);}
| DEFINED rval_expr { $$=mk_rve1(RVE_DEFINED_OP, $2);}
| SELVAL LPAREN rval_expr COMMA rval_expr COMMA rval_expr RPAREN {
rve_tmp=mk_rve2(RVE_SELVALOPT_OP, $5, $7);
if(rve_tmp == NULL) {
$$=0;
yyerror("faild to create tenary target expression");
}
$$=mk_rve2(RVE_SELVALEXP_OP, $3, rve_tmp);
}
| rve_un_op error %prec UNARY { $$=0; yyerror("bad expression"); }
| INTCAST error { $$=0; yyerror("bad expression"); }
| STRCAST error { $$=0; yyerror("bad expression"); }
Expand All @@ -3049,6 +3059,7 @@ rval_expr: rval { $$=$1;
| rval_expr LOG_OR error { $$=0; yyerror("bad expression"); }
| STRLEN LPAREN error RPAREN { $$=0; yyerror("bad expression"); }
| STREMPTY LPAREN error RPAREN { $$=0; yyerror("bad expression"); }
| SELVAL LPAREN error RPAREN { $$=0; yyerror("bad expression"); }
| DEFINED error { $$=0; yyerror("bad expression"); }
;

Expand Down
86 changes: 86 additions & 0 deletions src/core/rvalue.c
Expand Up @@ -527,6 +527,10 @@ enum rval_type rve_guess_type( struct rval_expr* rve)
case RVE_CONCAT_OP:
case RVE_STR_OP:
return RV_STR;
case RVE_SELVALEXP_OP:
break;
case RVE_SELVALOPT_OP:
return rve_guess_type(rve->left.rve);
case RVE_NONE_OP:
break;
}
Expand Down Expand Up @@ -593,6 +597,8 @@ int rve_is_constant(struct rval_expr* rve)
case RVE_PLUS_OP:
case RVE_IPLUS_OP:
case RVE_CONCAT_OP:
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
return rve_is_constant(rve->left.rve) &&
rve_is_constant(rve->right.rve);
case RVE_NONE_OP:
Expand Down Expand Up @@ -658,6 +664,8 @@ static int rve_op_unary(enum rval_expr_op op)
case RVE_PLUS_OP:
case RVE_IPLUS_OP:
case RVE_CONCAT_OP:
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
return 0;
case RVE_NONE_OP:
return -1;
Expand Down Expand Up @@ -692,6 +700,10 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
case RVE_RVAL_OP:
*type=rve_guess_type(rve);
return 1;
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
*type=rve_guess_type(rve);
return 1;
case RVE_UMINUS_OP:
case RVE_BOOL_OP:
case RVE_LNOT_OP:
Expand Down Expand Up @@ -2141,6 +2153,13 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
ret=rval_int_strop1(h, msg, res, rve->op, rv1, 0);
rval_destroy(rv1);
break;
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
LM_BUG("invalid selval int expression operation %d (%d,%d-%d,%d)\n",
rve->op, rve->fpos.s_line, rve->fpos.s_col,
rve->fpos.e_line, rve->fpos.e_col);
ret=-1;
break;
case RVE_NONE_OP:
/*default:*/
LM_BUG("invalid rval int expression operation %d (%d,%d-%d,%d)\n",
Expand Down Expand Up @@ -2288,6 +2307,12 @@ int rval_expr_eval_rvint( struct run_act_ctx* h,
*res_rv=rval_expr_eval(h, msg, rve);
ret=-(*res_rv==0);
break;
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
LM_BUG("invalid rval selval expression operation %d (%d,%d-%d,%d)\n",
rve->op, rve->fpos.s_line, rve->fpos.s_col,
rve->fpos.e_line, rve->fpos.e_col);
goto error;
case RVE_NONE_OP:
/*default:*/
LM_BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
Expand Down Expand Up @@ -2478,6 +2503,59 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
}
ret=rval_convert(h, msg, RV_STR, rv1, 0);
break;
case RVE_SELVALEXP_OP:
/* operator forces integer type */
r=rval_expr_eval_int(h, msg, &i, rve->left.rve);
if (unlikely(r!=0)){
LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
rve->fpos.s_line, rve->fpos.s_col,
rve->fpos.e_line, rve->fpos.e_col);
goto error;
}
if(i>0) {
rv1=rval_expr_eval(h, msg, rve->right.rve->left.rve);
} else {
rv1=rval_expr_eval(h, msg, rve->right.rve->right.rve);
}
if (unlikely(rv1==0)){
LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
goto error;
}
rval_cache_init(&c1);
type=rval_get_btype(h, msg, rv1, &c1);
switch(type){
case RV_INT:
r=rval_get_int(h, msg, &i, rv1, &c1);
rval_get_int_handle_ret(r, "rval expression left side "
"conversion to int failed",
rve);
if (unlikely(r<0)){
rval_cache_clean(&c1);
goto error;
}
v.l=i;
ret=rval_new(RV_INT, &v, 0);
if (unlikely(ret==0)){
rval_cache_clean(&c1);
LM_ERR("rv eval int expression: out of memory\n");
goto error;
}
break;
case RV_STR:
case RV_NONE:
ret=rval_convert(h, msg, RV_STR, rv1, 0);
break;
default:
LM_BUG("rv unsupported basic type %d (%d,%d-%d,%d)\n", type,
rve->fpos.s_line, rve->fpos.s_col,
rve->fpos.e_line, rve->fpos.e_col);
}
rval_cache_clean(&c1);
break;
case RVE_SELVALOPT_OP:
break;
case RVE_NONE_OP:
/*default:*/
LM_BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
Expand Down Expand Up @@ -2673,6 +2751,8 @@ struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
case RVE_STRDIFF_OP:
case RVE_MATCH_OP:
case RVE_CONCAT_OP:
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
break;
default:
LM_BUG("unsupported operator %d\n", op);
Expand Down Expand Up @@ -2742,6 +2822,8 @@ static int rve_op_is_assoc(enum rval_expr_op op)
case RVE_STREQ_OP:
case RVE_STRDIFF_OP:
case RVE_MATCH_OP:
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
return 0;
}
return 0;
Expand Down Expand Up @@ -2796,6 +2878,8 @@ static int rve_op_is_commutative(enum rval_expr_op op)
case RVE_LTE_OP:
case RVE_CONCAT_OP:
case RVE_MATCH_OP:
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
return 0;
case RVE_DIFF_OP:
case RVE_EQ_OP:
Expand Down Expand Up @@ -3847,6 +3931,8 @@ int fix_rval_expr(void* p)
case RVE_STREQ_OP:
case RVE_STRDIFF_OP:
case RVE_CONCAT_OP:
case RVE_SELVALEXP_OP:
case RVE_SELVALOPT_OP:
ret=fix_rval_expr((void*)rve->left.rve);
if (ret<0) goto error;
ret=fix_rval_expr((void*)rve->right.rve);
Expand Down
3 changes: 3 additions & 0 deletions src/core/rvalue.h
Expand Up @@ -76,6 +76,9 @@ enum rval_expr_op{
RVE_STREQ_OP, /**< 2 members, string == , returns left == right (bool)*/
RVE_STRDIFF_OP,/**< 2 members, string != , returns left != right (bool)*/
RVE_MATCH_OP, /**< 2 members, string ~), returns left matches re(right) */
/* tenary expression - (x)?y:z */
RVE_SELVALEXP_OP, /**< selval expresion - selval(exp, ...)*/
RVE_SELVALOPT_OP, /**< selval options - selval(exp, opt1, opt2)*/
/* avp, pvars a.s.o */
RVE_DEFINED_OP, /**< one member, returns is_defined(val) (bool) */
RVE_NOTDEFINED_OP, /**< one member, returns is_not_defined(val) (bool) */
Expand Down

0 comments on commit d11a125

Please sign in to comment.