Browse code

core: added selval(evalexpr, valexp1, valexpr2)

- 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

Daniel-Constantin Mierla authored on 08/02/2021 10:18:44
Showing 4 changed files
... ...
@@ -258,6 +258,7 @@ MODULO	"mod"
258 258
 STRLEN	"strlen"
259 259
 STREMPTY	"strempty"
260 260
 DEFINED		"defined"
261
+SELVAL		"selval"
261 262
 STREQ	eq
262 263
 INTEQ	ieq
263 264
 STRDIFF	ne
... ...
@@ -1041,6 +1042,7 @@ IMPORTFILE      "import_file"
1041 1042
 <INITIAL>{INTDIFF}	{ count(); return INTDIFF; }
1042 1043
 <INITIAL>{INTCAST}	{ count(); return INTCAST; }
1043 1044
 <INITIAL>{STRCAST}	{ count(); return STRCAST; }
1045
+<INITIAL>{SELVAL}	{ count(); return SELVAL; }
1044 1046
 
1045 1047
 <INITIAL>{SELECT_MARK}  { count(); state = SELECT_S; BEGIN(SELECT); return SELECT_MARK; }
1046 1048
 <SELECT>{ID}		{ count(); addstr(&s_buf, yytext, yyleng);
... ...
@@ -149,6 +149,7 @@ static pv_spec_t* pv_spec = NULL;
149 149
 static struct action *mod_func_action = NULL;
150 150
 static struct lvalue* lval_tmp = NULL;
151 151
 static struct rvalue* rval_tmp = NULL;
152
+static struct rval_expr* rve_tmp = NULL;
152 153
 
153 154
 static void warn(char* s, ...);
154 155
 static void warn_at(struct cfg_pos* pos, char* s, ...);
... ...
@@ -560,6 +561,7 @@ extern char *default_routename;
560 561
 /* no precedence, they use () */
561 562
 %token STRLEN
562 563
 %token STREMPTY
564
+%token SELVAL
563 565
 
564 566
 /* values */
565 567
 %token <intval> NUMBER
... ...
@@ -3031,6 +3033,14 @@ rval_expr: rval						{ $$=$1;
3031 3033
 		| STRLEN LPAREN rval_expr RPAREN { $$=mk_rve1(RVE_STRLEN_OP, $3);}
3032 3034
 		| STREMPTY LPAREN rval_expr RPAREN {$$=mk_rve1(RVE_STREMPTY_OP, $3);}
3033 3035
 		| DEFINED rval_expr				{ $$=mk_rve1(RVE_DEFINED_OP, $2);}
3036
+		| SELVAL LPAREN rval_expr COMMA rval_expr COMMA rval_expr RPAREN {
3037
+				rve_tmp=mk_rve2(RVE_SELVALOPT_OP, $5, $7);
3038
+				if(rve_tmp == NULL) {
3039
+					$$=0;
3040
+					yyerror("faild to create tenary target expression");
3041
+				}
3042
+				$$=mk_rve2(RVE_SELVALEXP_OP, $3, rve_tmp);
3043
+		}
3034 3044
 		| rve_un_op error %prec UNARY 		{ $$=0; yyerror("bad expression"); }
3035 3045
 		| INTCAST error					{ $$=0; yyerror("bad expression"); }
3036 3046
 		| STRCAST error					{ $$=0; yyerror("bad expression"); }
... ...
@@ -3049,6 +3059,7 @@ rval_expr: rval						{ $$=$1;
3049 3059
 		| rval_expr LOG_OR error		{ $$=0; yyerror("bad expression"); }
3050 3060
 		| STRLEN LPAREN error RPAREN	{ $$=0; yyerror("bad expression"); }
3051 3061
 		| STREMPTY LPAREN error RPAREN	{ $$=0; yyerror("bad expression"); }
3062
+		| SELVAL LPAREN error RPAREN	{ $$=0; yyerror("bad expression"); }
3052 3063
 		| DEFINED error					{ $$=0; yyerror("bad expression"); }
3053 3064
 		;
3054 3065
 
... ...
@@ -527,6 +527,10 @@ enum rval_type rve_guess_type( struct rval_expr* rve)
527 527
 		case RVE_CONCAT_OP:
528 528
 		case RVE_STR_OP:
529 529
 			return RV_STR;
530
+		case RVE_SELVALEXP_OP:
531
+			break;
532
+		case RVE_SELVALOPT_OP:
533
+			return rve_guess_type(rve->left.rve);
530 534
 		case RVE_NONE_OP:
531 535
 			break;
532 536
 	}
... ...
@@ -593,6 +597,8 @@ int rve_is_constant(struct rval_expr* rve)
593 597
 		case RVE_PLUS_OP:
594 598
 		case RVE_IPLUS_OP:
595 599
 		case RVE_CONCAT_OP:
600
+		case RVE_SELVALEXP_OP:
601
+		case RVE_SELVALOPT_OP:
596 602
 			return rve_is_constant(rve->left.rve) &&
597 603
 					rve_is_constant(rve->right.rve);
598 604
 		case RVE_NONE_OP:
... ...
@@ -658,6 +664,8 @@ static int rve_op_unary(enum rval_expr_op op)
658 664
 		case RVE_PLUS_OP:
659 665
 		case RVE_IPLUS_OP:
660 666
 		case RVE_CONCAT_OP:
667
+		case RVE_SELVALEXP_OP:
668
+		case RVE_SELVALOPT_OP:
661 669
 			return 0;
662 670
 		case RVE_NONE_OP:
663 671
 			return -1;
... ...
@@ -692,6 +700,10 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
692 700
 		case RVE_RVAL_OP:
693 701
 			*type=rve_guess_type(rve);
694 702
 			return 1;
703
+		case RVE_SELVALEXP_OP:
704
+		case RVE_SELVALOPT_OP:
705
+			*type=rve_guess_type(rve);
706
+			return 1;
695 707
 		case RVE_UMINUS_OP:
696 708
 		case RVE_BOOL_OP:
697 709
 		case RVE_LNOT_OP:
... ...
@@ -2141,6 +2153,13 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
2141 2153
 			ret=rval_int_strop1(h, msg, res, rve->op, rv1, 0);
2142 2154
 			rval_destroy(rv1);
2143 2155
 			break;
2156
+		case RVE_SELVALEXP_OP:
2157
+		case RVE_SELVALOPT_OP:
2158
+			LM_BUG("invalid selval int expression operation %d (%d,%d-%d,%d)\n",
2159
+					rve->op, rve->fpos.s_line, rve->fpos.s_col,
2160
+					rve->fpos.e_line, rve->fpos.e_col);
2161
+			ret=-1;
2162
+			break;
2144 2163
 		case RVE_NONE_OP:
2145 2164
 		/*default:*/
2146 2165
 			LM_BUG("invalid rval int expression operation %d (%d,%d-%d,%d)\n",
... ...
@@ -2288,6 +2307,12 @@ int rval_expr_eval_rvint(			struct run_act_ctx* h,
2288 2307
 			*res_rv=rval_expr_eval(h, msg, rve);
2289 2308
 			ret=-(*res_rv==0);
2290 2309
 			break;
2310
+		case RVE_SELVALEXP_OP:
2311
+		case RVE_SELVALOPT_OP:
2312
+			LM_BUG("invalid rval selval expression operation %d (%d,%d-%d,%d)\n",
2313
+					rve->op, rve->fpos.s_line, rve->fpos.s_col,
2314
+					rve->fpos.e_line, rve->fpos.e_col);
2315
+			goto error;
2291 2316
 		case RVE_NONE_OP:
2292 2317
 		/*default:*/
2293 2318
 			LM_BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
... ...
@@ -2478,6 +2503,59 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
2478 2503
 			}
2479 2504
 			ret=rval_convert(h, msg, RV_STR, rv1, 0);
2480 2505
 			break;
2506
+		case RVE_SELVALEXP_OP:
2507
+			/* operator forces integer type */
2508
+			r=rval_expr_eval_int(h, msg, &i, rve->left.rve);
2509
+			if (unlikely(r!=0)){
2510
+				LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2511
+						rve->fpos.s_line, rve->fpos.s_col,
2512
+						rve->fpos.e_line, rve->fpos.e_col);
2513
+				goto error;
2514
+			}
2515
+			if(i>0) {
2516
+				rv1=rval_expr_eval(h, msg, rve->right.rve->left.rve);
2517
+			} else {
2518
+				rv1=rval_expr_eval(h, msg, rve->right.rve->right.rve);
2519
+			}
2520
+			if (unlikely(rv1==0)){
2521
+				LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2522
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2523
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
2524
+				goto error;
2525
+			}
2526
+			rval_cache_init(&c1);
2527
+			type=rval_get_btype(h, msg, rv1, &c1);
2528
+			switch(type){
2529
+				case RV_INT:
2530
+					r=rval_get_int(h, msg, &i, rv1, &c1);
2531
+					rval_get_int_handle_ret(r, "rval expression left side "
2532
+												"conversion to int failed",
2533
+											rve);
2534
+					if (unlikely(r<0)){
2535
+						rval_cache_clean(&c1);
2536
+						goto error;
2537
+					}
2538
+					v.l=i;
2539
+					ret=rval_new(RV_INT, &v, 0);
2540
+					if (unlikely(ret==0)){
2541
+						rval_cache_clean(&c1);
2542
+						LM_ERR("rv eval int expression: out of memory\n");
2543
+						goto error;
2544
+					}
2545
+					break;
2546
+				case RV_STR:
2547
+				case RV_NONE:
2548
+					ret=rval_convert(h, msg, RV_STR, rv1, 0);
2549
+					break;
2550
+				default:
2551
+					LM_BUG("rv unsupported basic type %d (%d,%d-%d,%d)\n", type,
2552
+							rve->fpos.s_line, rve->fpos.s_col,
2553
+							rve->fpos.e_line, rve->fpos.e_col);
2554
+			}
2555
+			rval_cache_clean(&c1);
2556
+			break;
2557
+		case RVE_SELVALOPT_OP:
2558
+			break;
2481 2559
 		case RVE_NONE_OP:
2482 2560
 		/*default:*/
2483 2561
 			LM_BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
... ...
@@ -2673,6 +2751,8 @@ struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
2673 2751
 		case RVE_STRDIFF_OP:
2674 2752
 		case RVE_MATCH_OP:
2675 2753
 		case RVE_CONCAT_OP:
2754
+		case RVE_SELVALEXP_OP:
2755
+		case RVE_SELVALOPT_OP:
2676 2756
 			break;
2677 2757
 		default:
2678 2758
 			LM_BUG("unsupported operator %d\n", op);
... ...
@@ -2742,6 +2822,8 @@ static int rve_op_is_assoc(enum rval_expr_op op)
2742 2822
 		case RVE_STREQ_OP:
2743 2823
 		case RVE_STRDIFF_OP:
2744 2824
 		case RVE_MATCH_OP:
2825
+		case RVE_SELVALEXP_OP:
2826
+		case RVE_SELVALOPT_OP:
2745 2827
 			return 0;
2746 2828
 	}
2747 2829
 	return 0;
... ...
@@ -2796,6 +2878,8 @@ static int rve_op_is_commutative(enum rval_expr_op op)
2796 2878
 		case RVE_LTE_OP:
2797 2879
 		case RVE_CONCAT_OP:
2798 2880
 		case RVE_MATCH_OP:
2881
+		case RVE_SELVALEXP_OP:
2882
+		case RVE_SELVALOPT_OP:
2799 2883
 			return 0;
2800 2884
 		case RVE_DIFF_OP:
2801 2885
 		case RVE_EQ_OP:
... ...
@@ -3847,6 +3931,8 @@ int fix_rval_expr(void* p)
3847 3931
 		case RVE_STREQ_OP:
3848 3932
 		case RVE_STRDIFF_OP:
3849 3933
 		case RVE_CONCAT_OP:
3934
+		case RVE_SELVALEXP_OP:
3935
+		case RVE_SELVALOPT_OP:
3850 3936
 			ret=fix_rval_expr((void*)rve->left.rve);
3851 3937
 			if (ret<0) goto error;
3852 3938
 			ret=fix_rval_expr((void*)rve->right.rve);
... ...
@@ -76,6 +76,9 @@ enum rval_expr_op{
76 76
 	RVE_STREQ_OP,  /**< 2 members, string == , returns left == right (bool)*/
77 77
 	RVE_STRDIFF_OP,/**< 2 members, string != , returns left != right (bool)*/
78 78
 	RVE_MATCH_OP,  /**< 2 members, string ~),  returns left matches re(right) */
79
+	/* tenary expression - (x)?y:z */
80
+	RVE_SELVALEXP_OP,  /**< selval expresion - selval(exp, ...)*/
81
+	RVE_SELVALOPT_OP,  /**< selval options - selval(exp, opt1, opt2)*/
79 82
 	/* avp, pvars a.s.o */
80 83
 	RVE_DEFINED_OP, /**< one member, returns is_defined(val) (bool) */
81 84
 	RVE_NOTDEFINED_OP, /**< one member, returns is_not_defined(val) (bool) */