Explorar o código

core: added preprocessor directive #!ifexp stm

- conditional evaluation of the statement as an expression with strings
  and numbers
- example:

 #!ifexp KAMAILIO_VERSION >= 5006000
 ...
 #!else
 ...
 #!endif

- defined IDs can be used inside the expression
  - if not defined, value 0 is used
  - if defined with value, the value is used
  - if defined with no value, value 1 is used
- if expression is evaluated to !=0 or non-empty string, then it is considered true
Daniel-Constantin Mierla %!s(int64=3) %!d(string=hai) anos
pai
achega
a84e96f2e0
Modificáronse 3 ficheiros con 108 adicións e 3 borrados
  1. 17 3
      src/core/cfg.lex
  2. 87 0
      src/core/ppcfg.c
  3. 4 0
      src/core/ppcfg.h

+ 17 - 3
src/core/cfg.lex

@@ -130,8 +130,8 @@
 /* start conditions */
 %x STRING1 STRING2 STR_BETWEEN COMMENT COMMENT_LN ATTR SELECT AVP_PVAR PVAR_P
 %x PVARID INCLF IMPTF EVRTNAME CFGPRINTMODE CFGPRINTLOADMOD DEFENV_ID DEFENVS_ID
-%x TRYDEFENV_ID TRYDEFENVS_ID LINECOMMENT DEFINE_ID DEFINE_EOL DEFINE_DATA 
-%x IFDEF_ID IFDEF_EOL IFDEF_SKIP
+%x TRYDEFENV_ID TRYDEFENVS_ID LINECOMMENT DEFINE_ID DEFINE_EOL DEFINE_DATA
+%x IFDEF_ID IFDEF_EOL IFDEF_SKIP IFEXP_STM
 
 /* config script types : #!SER  or #!KAMAILIO or #!MAX_COMPAT */
 SER_CFG			SER
@@ -571,6 +571,7 @@ PREP_START	"#!"|"!!"
 DEFINE       "define"|"def"
 IFDEF        ifdef
 IFNDEF       ifndef
+IFEXP        ifexp
 ENDIF        endif
 TRYDEF       "trydefine"|"trydef"
 REDEF        "redefine"|"redef"
@@ -1381,6 +1382,9 @@ IMPORTFILE      "import_file"
 <INITIAL,CFGPRINTMODE,IFDEF_SKIP>{PREP_START}{IFNDEF}{EAT_ABLE}+    { count();
 								if (pp_ifdef_type(0)) return 1;
 								state = IFDEF_S; BEGIN(IFDEF_ID); }
+<INITIAL,CFGPRINTMODE,IFDEF_SKIP>{PREP_START}{IFEXP}{EAT_ABLE}+    { count();
+								if (pp_ifdef_type(1)) return 1;
+								state = IFDEF_S; BEGIN(IFEXP_STM); }
 <IFDEF_ID>{ID}{MINUS}           { count();
 									LM_CRIT(
 										"error at %s line %d: '-' not allowed\n",
@@ -1390,6 +1394,11 @@ IMPORTFILE      "import_file"
 <IFDEF_ID>{ID}                { count();
 								pp_ifdef_var(yyleng, yytext);
 								state = IFDEF_EOL_S; BEGIN(IFDEF_EOL); }
+<IFEXP_STM>.*{CR}        { count();
+								pp_ifexp_eval(yytext, yyleng);
+								state = IFDEF_EOL_S; BEGIN(IFDEF_EOL);
+								pp_ifdef();
+								}
 <IFDEF_EOL>{EAT_ABLE}*{CR}    { count(); pp_ifdef(); }
 
 <INITIAL,CFGPRINTMODE,IFDEF_SKIP>{PREP_START}{ELSE}{EAT_ABLE}*{CR}    { count(); pp_else(); }
@@ -2016,7 +2025,7 @@ ksr_ppdefine_t* pp_get_define(int idx)
 	return &pp_defines[idx];
 }
 
-static int pp_lookup(int len, const char *text)
+int pp_lookup(int len, const char *text)
 {
 	str var = {(char *)text, len};
 	int i;
@@ -2245,6 +2254,11 @@ static void pp_ifdef_var(int len, const char *text)
 	pp_ifdef_stack[pp_sptr] ^= (pp_lookup(len, text) < 0);
 }
 
+void pp_ifexp_state(int state)
+{
+	pp_ifdef_stack[pp_sptr] = state;
+}
+
 static void pp_update_state()
 {
 	int i;

+ 87 - 0
src/core/ppcfg.c

@@ -28,11 +28,13 @@
 
 #include "mem/mem.h"
 #include "ut.h"
+#include "trim.h"
 #include "re.h"
 #include "pvar.h"
 #include "pvapi.h"
 #include "str_list.h"
 #include "dprint.h"
+#include "utils/snexpr.h"
 
 #include "ppcfg.h"
 #include "fmsg.h"
@@ -365,4 +367,89 @@ void pp_define_core(void)
 	}
 }
 
+static struct snexpr* pp_snexpr_defval(char *vname)
+{
+	int idx = 0;
+	ksr_ppdefine_t *pd = NULL;
+
+	if(vname==NULL) {
+		return NULL;
+	}
+
+	idx = pp_lookup(strlen(vname), vname);
+	if(idx < 0) {
+		LM_DBG("define id [%s] not found - return 0\n", vname);
+		return snexpr_convert_num(0, SNE_OP_CONSTNUM);
+	}
+	pd = pp_get_define(idx);
+	if(pd == NULL) {
+		LM_DBG("define id [%s] at index [%d] not found - return 0\n", vname, idx);
+		return snexpr_convert_num(0, SNE_OP_CONSTNUM);
+	}
+
+	if(pd->value.s != NULL) {
+		LM_DBG("define id [%s] at index [%d] found with value - return [%.*s]\n",
+				vname, idx, pd->value.len, pd->value.s);
+		return snexpr_convert_stzl(pd->value.s, pd->value.len, SNE_OP_CONSTSTZ);
+	} else {
+		LM_DBG("define id [%s] at index [%d] found without value - return 1\n",
+				vname, idx);
+		return snexpr_convert_num(1, SNE_OP_CONSTNUM);
+	}
+
+}
+
+void pp_ifexp_eval(char *exval, int exlen)
+{
+	str exstr;
+	struct snexpr_var_list vars = {0};
+	struct snexpr *e = NULL;
+	struct snexpr *result = NULL;
+	int b = 0;
+
+	exstr.s = exval;
+	exstr.len = exlen;
+	trim(&exstr);
+
+	LM_DBG("evaluating [%.*s]\n", exstr.len, exstr.s);
+
+	e = snexpr_create(exstr.s, exstr.len, &vars, NULL, pp_snexpr_defval);
+	if(e == NULL) {
+		LM_ERR("failed to create expression [%.*s]\n", exstr.len, exstr.s);
+		pp_ifexp_state(0);
+		return;
+	}
+
+	result = snexpr_eval(e);
+
+	if(result==NULL) {
+		LM_ERR("expression evaluation [%.*s] is null\n", exstr.len, exstr.s);
+		pp_ifexp_state(0);
+		goto end;
+	}
+
+	if(result->type == SNE_OP_CONSTNUM) {
+		if(result->param.num.nval) {
+			b = 1;
+		} else {
+			b = 0;
+		}
+	} else if(result->type == SNE_OP_CONSTSTZ) {
+		if(result->param.stz.sval==NULL || strlen(result->param.stz.sval)==0) {
+			b = 0;
+		} else {
+			b = 1;
+		}
+	}
+
+	LM_DBG("expression evaluation [%.*s] is [%s]\n", exstr.len, exstr.s,
+			(b)?"true":"false");
+
+	pp_ifexp_state(b);
+
+	snexpr_result_free(result);
+end:
+	snexpr_destroy(e, &vars);
+}
+
 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */

+ 4 - 0
src/core/ppcfg.h

@@ -40,6 +40,7 @@ int pp_def_qvalue(str *defval, str *outval);
 
 str* pp_get_define_name(int idx);
 ksr_ppdefine_t* pp_get_define(int idx);
+int pp_lookup(int len, const char *text);
 
 int pp_subst_add(char *data);
 int pp_substdef_add(char *data, int mode);
@@ -59,6 +60,9 @@ void pp_define_core(void);
 
 void ksr_cfg_print_initial_state(void);
 
+void pp_ifexp_eval(char *exval, int exlen);
+void pp_ifexp_state(int state);
+
 #endif /*_PPCFG_H_*/
 
 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */