Browse code

Merge remote branch 'origin/andrei/rve_f_params'

Automatic support for expressions or variables in lots of module
functions. It applies to all the module functions declared without
a fixup, with a fixup and the corresponding free_fixup function or
with a compatible ser or kamailio style standard fixup (declared
in sr_module.h or mod_fix.h).
E.g.: f($a, "b = " + $b); t_set_fr($v + 2 + $x).
t_set_fr($foo) (equivalent now with t_set_fr("$foo")).

If the expression is constant, then there is no restriction, all the
module functions can take it as parameter.
E.g.: f("7 *" +" 6 = " + 7 * 6) # equivalent to f("7 * 6 = 42")

* origin/andrei/rve_f_params: (21 commits)
NEWS: notes about expressions in function parameters
core: enable RVE fixup support when fixup_free is present
core: automatically fill known fixup_free functions
core: functions to get a fixup corresp. fixup_free function
core: k style fixup_free fixes
core: added generic fparam fixup_free functions
core: pvapi: added pv_spec_free_contents()
core: fix "unsigned" bug in sint2str*()
core: fix auto-deref. for vars in fparam fixups
perl(k): use sr31_cmd_export_t
app_python: use sr31_cmd_export_t
core: internal module interface changes
print(s): fparam fixup example
core: support for RVEs in fparam fixups
core: rval - don't use static buffer for int conversions
core: ut.* - BSD licence
core: ut.h: added sint2strbuf()
perl(k): update api calls: s/MODULE_T/MODULE2_T/
app_python: update api calls: s/MODULE_T/MODULE2_T
print(s): more module function examples
core: support for expressions/variables in function parameters

Conflicts:
NEWS
action.c
modules/app_python/python_msgobj.c
modules_k/perl/openserxs.xs
pkg/kamailio/debian-lenny
pvapi.c
route.c
route_struct.h
sr_module.c

Andrei Pelinescu-Onciul authored on 11/08/2010 20:18:06
Showing 19 changed files
... ...
@@ -12,6 +12,15 @@ core:
12 12
   - networks addresses support in ip comparisons (src_ip, dst_ip, to_ip)
13 13
     with strings or rvalue expressions.
14 14
     E.g.: $ip=10.0.0.0;  if (src_ip == $ip +"/8") ....
15
+  - lots of module functions automatically support now expressions or
16
+      variables in function parameters. This applies to all the module
17
+      functions declared without a fixup, with a fixup and the corresponding
18
+      free_fixup function or with a compatible ser or kamailio style standard
19
+      fixup (declared in sr_module.h or mod_fix.h).
20
+      E.g.: f($a, "b = " + $b);  t_set_fr($v + 2 + $x).
21
+            t_set_fr($foo) (equivalent now with t_set_fr("$foo")).
22
+  - all the module functions can now be called with any constant expression
23
+      as parameters. E.g.: f("7 *" +" 6 = " + 7 * 6);
15 24
   - onreply_route {...} is now equivalent with onreply_route[0] {...}
16 25
   - global, per protocol blacklist ignore masks (via extended send_flags).
17 26
     See dst_blacklist_udp_imask a.s.o (dst_blacklist_*_imask).
... ...
@@ -51,6 +51,8 @@
51 51
  *  2008-12-17  added UDP_MTU_TRY_PROTO_T (andrei)
52 52
  *  2009-05-04  switched IF_T to rval_expr (andrei)
53 53
  *  2009-09-15  added SET_{FWD,RPL}_NO_CONNECT, SET_{FWD,RPL}_CLOSE (andrei)
54
+ *  2010-06-01  special hack/support for fparam fixups so that they can handle
55
+ *               variable RVEs (andrei)
54 56
  */
55 57
 
56 58
 /*!
... ...
@@ -108,6 +110,179 @@
108 108
 int _last_returned_code  = 0;
109 109
 struct onsend_info* p_onsend=0; /* onsend route send info */
110 110
 
111
+
112
+
113
+/* handle the exit code of a module function call.
114
+ * (used internally in do_action())
115
+ * @param h - script handle (h->last_retcode and h->run_flags will be set).
116
+ * @param ret - module function (v0 or v2) retcode
117
+ * Side-effects: sets _last_returned_code
118
+ */
119
+#define MODF_HANDLE_RETCODE(h, ret) \
120
+	do { \
121
+		/* if (unlikely((ret)==0)) (h)->run_flags|=EXIT_R_F; */ \
122
+		(h)->run_flags |= EXIT_R_F & (((ret) != 0) -1); \
123
+		(h)->last_retcode=(ret); \
124
+		_last_returned_code = (h)->last_retcode; \
125
+	} while(0)
126
+
127
+
128
+
129
+/* frees parameters converted using MODF_RVE_PARAM_CONVERT() from dst.
130
+ * (used internally in do_action())
131
+ * Assumes src is unchanged.
132
+ * Side-effects: clobbers i (int).
133
+ */
134
+#define MODF_RVE_PARAM_FREE(cmd, src, dst) \
135
+		for (i=0; i < (dst)[1].u.number; i++) { \
136
+			if ((src)[i+2].type == RVE_ST && (dst)[i+2].u.data) { \
137
+				if ((dst)[i+2].type == RVE_FREE_FIXUP_ST) {\
138
+					/* call free_fixup (which should restore the original
139
+					   string) */ \
140
+					call_fixup((cmd)->free_fixup, &(dst)[i+2].u.data, i+1); \
141
+				} else if ((dst)[i+2].type == FPARAM_DYN_ST) {\
142
+					/* completely frees fparam and restore original string */\
143
+					fparam_free_restore(&(dst)[i+2].u.data); \
144
+				} \
145
+				/* free allocated string */ \
146
+				pkg_free((dst)[i+2].u.data); \
147
+				(dst)[i+2].u.data = 0; \
148
+			} \
149
+		}
150
+
151
+
152
+/* fills dst from src, converting RVE_ST params to STRING_ST.
153
+ * (used internally in do_action())
154
+ * @param src - source action_u_t array, as in the action structure
155
+ * @param dst - destination action_u_t array, will be filled from src.
156
+ * WARNING: dst must be cleaned when done, use MODULE_RVE_PARAM_FREE()
157
+ * Side-effects: clobbers i (int), s (str), rv (rvalue*), might jump to error.
158
+ */
159
+#define MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst) \
160
+	do { \
161
+		(dst)[1]=(src)[1]; \
162
+		for (i=0; i < (src)[1].u.number; i++) { \
163
+			if ((src)[2+i].type == RVE_ST) { \
164
+				rv=rval_expr_eval((h), (msg), (src)[i+2].u.data); \
165
+				if (unlikely(rv == 0 || \
166
+					rval_get_str((h), (msg), &s, rv, 0) < 0)) { \
167
+					rval_destroy(rv); \
168
+					ERR("failed to convert RVE to string\n"); \
169
+					(dst)[1].u.number = i; \
170
+					MODF_RVE_PARAM_FREE(cmd, src, dst); \
171
+					goto error; \
172
+				} \
173
+				(dst)[i+2].type = STRING_RVE_ST; \
174
+				(dst)[i+2].u.string = s.s; \
175
+				(dst)[i+2].u.str.len = s.len; \
176
+				rval_destroy(rv); \
177
+				if ((cmd)->fixup) {\
178
+					if ((cmd)->free_fixup) {\
179
+						if (likely( call_fixup((cmd)->fixup, \
180
+										&(dst)[i+2].u.data, i+1) >= 0) ) { \
181
+							/* success => mark it for calling free fixup */ \
182
+							if (likely((dst)[i+2].u.data != s.s)) \
183
+								(dst)[i+2].type = RVE_FREE_FIXUP_ST; \
184
+						} else { \
185
+							/* error calling fixup => mark conv. parameter \
186
+							   and return error */ \
187
+							(dst)[1].u.number = i; \
188
+							ERR("runtime fixup failed for %s param %d\n", \
189
+									(cmd)->name, i+1); \
190
+							MODF_RVE_PARAM_FREE(cmd, src, dst); \
191
+							goto error; \
192
+						} \
193
+					} else if ((cmd)->fixup_flags & FIXUP_F_FPARAM_RVE) { \
194
+						if (likely( call_fixup((cmd)->fixup, \
195
+										&(dst)[i+2].u.data, i+1) >= 0)) { \
196
+							if ((dst)[i+2].u.data != s.s) \
197
+								(dst)[i+2].type = FPARAM_DYN_ST; \
198
+						} else { \
199
+							/* error calling fixup => mark conv. parameter \
200
+							   and return error */ \
201
+							(dst)[1].u.number = i; \
202
+							ERR("runtime fixup failed for %s param %d\n", \
203
+									(cmd)->name, i+1); \
204
+							MODF_RVE_PARAM_FREE(cmd, src, dst); \
205
+							goto error; \
206
+						}\
207
+					} \
208
+				} \
209
+			} else \
210
+				(dst)[i+2]=(src)[i+2]; \
211
+		} \
212
+	} while(0)
213
+
214
+
215
+
216
+/* call a module function with normal STRING_ST params.
217
+ * (used internally in do_action())
218
+ * @param f_type - cmd_function type
219
+ * @param h
220
+ * @param msg
221
+ * @param src - source action_u_t array (e.g. action->val)
222
+ * @param params... - variable list of parameters, passed to the module
223
+ *               function
224
+ * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), cmd,
225
+ *               might jump to error.
226
+ *
227
+ */
228
+#ifdef __SUNPRO_C
229
+#define MODF_CALL(f_type, h, msg, src, ...) \
230
+	do { \
231
+		cmd=(src)[0].u.data; \
232
+		ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
233
+		MODF_HANDLE_RETCODE(h, ret); \
234
+	} while (0)
235
+#else  /* ! __SUNPRO_C  (gcc, icc a.s.o) */
236
+#define MODF_CALL(f_type, h, msg, src, params...) \
237
+	do { \
238
+		cmd=(src)[0].u.data; \
239
+		ret=((f_type)cmd->function)((msg), ## params ); \
240
+		MODF_HANDLE_RETCODE(h, ret); \
241
+	} while (0)
242
+#endif /* __SUNPRO_C */
243
+
244
+
245
+
246
+/* call a module function with possible RVE params.
247
+ * (used internally in do_action())
248
+ * @param f_type - cmd_function type
249
+ * @param h
250
+ * @param msg
251
+ * @param src - source action_u_t array (e.g. action->val)
252
+ * @param dst - temporary action_u_t array used for conversions. It can be
253
+ *              used for the function parameters. It's contents it's not
254
+ *              valid after the call.
255
+ * @param params... - variable list of parameters, passed to the module
256
+ *               function
257
+ * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), f, dst,
258
+ *               might jump to error.
259
+ *
260
+ */
261
+#ifdef __SUNPRO_C
262
+#define MODF_RVE_CALL(f_type, h, msg, src, dst, ...) \
263
+	do { \
264
+		cmd=(src)[0].u.data; \
265
+		MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
266
+		ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
267
+		MODF_HANDLE_RETCODE(h, ret); \
268
+		/* free strings allocated by us or fixups */ \
269
+		MODF_RVE_PARAM_FREE(cmd, src, dst); \
270
+	} while (0)
271
+#else  /* ! __SUNPRO_C  (gcc, icc a.s.o) */
272
+#define MODF_RVE_CALL(f_type, h, msg, src, dst, params...) \
273
+	do { \
274
+		cmd=(src)[0].u.data; \
275
+		MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
276
+		ret=((f_type)cmd->function)((msg), ## params ); \
277
+		MODF_HANDLE_RETCODE(h, ret); \
278
+		/* free strings allocated by us or fixups */ \
279
+		MODF_RVE_PARAM_FREE(cmd, src, dst); \
280
+	} while (0)
281
+#endif /* __SUNPRO_C */
282
+
283
+
111 284
 /* ret= 0! if action -> end of list(e.g DROP),
112 285
       > 0 to continue processing next actions
113 286
    and <0 on error */
... ...
@@ -118,7 +293,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
118 118
 	struct dest_info dst;
119 119
 	char* tmp;
120 120
 	char *new_uri, *end, *crt;
121
-	void* f;
121
+	sr31_cmd_export_t* cmd;
122 122
 	int len;
123 123
 	int user;
124 124
 	struct sip_uri uri, next_hop;
... ...
@@ -135,6 +310,13 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
135 135
 	struct rval_cache c1;
136 136
 	str s;
137 137
 	void *srevp[2];
138
+	/* temporary storage space for a struct action.val[] working copy
139
+	 (needed to transform RVE intro STRING before calling module
140
+	   functions). [0] is not used (corresp. to the module export pointer),
141
+	   [1] contains the number of params, and [2..] the param values.
142
+	   We need [1], because some fixup function use it
143
+	  (see fixup_get_param_count()).  */
144
+	static action_u_t mod_f_params[MAX_ACTIONS];
138 145
 
139 146
 	/* reset the value of error to E_UNSPEC so avoid unknowledgable
140 147
 	   functions to return with error (status<0) and not setting it
... ...
@@ -900,108 +1082,111 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
900 900
 										(struct action*)a->val[2].u.data, msg);
901 901
 					}
902 902
 			break;
903
-		case MODULE_T:
904
-			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
905
-					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
906
-				ret=((cmd_function)f)(msg,
907
-										(char*)a->val[2].u.data,
908
-										(char*)a->val[3].u.data
909
-									);
910
-				if (ret==0) h->run_flags|=EXIT_R_F;
911
-				h->last_retcode=ret;
912
-				_last_returned_code = h->last_retcode;
913
-			} else {
914
-				LOG(L_CRIT,"BUG: do_action: bad module call\n");
915
-				goto error;
916
-			}
903
+		case MODULE0_T:
904
+			MODF_CALL(cmd_function, h, msg, a->val, 0, 0);
917 905
 			break;
918 906
 		/* instead of using the parameter number, we use different names
919 907
 		 * for calls to functions with 3, 4, 5, 6 or variable number of
920 908
 		 * parameters due to performance reasons */
909
+		case MODULE1_T:
910
+			MODF_CALL(cmd_function, h, msg, a->val,
911
+										(char*)a->val[2].u.data,
912
+										0
913
+					);
914
+			break;
915
+		case MODULE2_T:
916
+			MODF_CALL(cmd_function, h, msg, a->val,
917
+										(char*)a->val[2].u.data,
918
+										(char*)a->val[3].u.data
919
+					);
920
+			break;
921 921
 		case MODULE3_T:
922
-			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
923
-					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
924
-				ret=((cmd_function3)f)(msg,
922
+			MODF_CALL(cmd_function3, h, msg, a->val,
925 923
 										(char*)a->val[2].u.data,
926 924
 										(char*)a->val[3].u.data,
927 925
 										(char*)a->val[4].u.data
928
-									);
929
-				if (ret==0) h->run_flags|=EXIT_R_F;
930
-				h->last_retcode=ret;
931
-				_last_returned_code = h->last_retcode;
932
-			} else {
933
-				LOG(L_CRIT,"BUG: do_action: bad module call\n");
934
-				goto error;
935
-			}
926
+					);
936 927
 			break;
937 928
 		case MODULE4_T:
938
-			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
939
-					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
940
-				ret=((cmd_function4)f)(msg,
929
+			MODF_CALL(cmd_function4, h, msg, a->val,
941 930
 										(char*)a->val[2].u.data,
942 931
 										(char*)a->val[3].u.data,
943 932
 										(char*)a->val[4].u.data,
944 933
 										(char*)a->val[5].u.data
945
-									);
946
-				if (ret==0) h->run_flags|=EXIT_R_F;
947
-				h->last_retcode=ret;
948
-				_last_returned_code = h->last_retcode;
949
-			} else {
950
-				LOG(L_CRIT,"BUG: do_action: bad module call\n");
951
-				goto error;
952
-			}
934
+					);
953 935
 			break;
954 936
 		case MODULE5_T:
955
-			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
956
-					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
957
-				ret=((cmd_function5)f)(msg,
937
+			MODF_CALL(cmd_function5, h, msg, a->val,
958 938
 										(char*)a->val[2].u.data,
959 939
 										(char*)a->val[3].u.data,
960 940
 										(char*)a->val[4].u.data,
961 941
 										(char*)a->val[5].u.data,
962 942
 										(char*)a->val[6].u.data
963
-									);
964
-				if (ret==0) h->run_flags|=EXIT_R_F;
965
-				h->last_retcode=ret;
966
-				_last_returned_code = h->last_retcode;
967
-			} else {
968
-				LOG(L_CRIT,"BUG: do_action: bad module call\n");
969
-				goto error;
970
-			}
943
+					);
971 944
 			break;
972 945
 		case MODULE6_T:
973
-			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
974
-					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
975
-				ret=((cmd_function6)f)(msg,
946
+			MODF_CALL(cmd_function6, h, msg, a->val,
976 947
 										(char*)a->val[2].u.data,
977 948
 										(char*)a->val[3].u.data,
978 949
 										(char*)a->val[4].u.data,
979 950
 										(char*)a->val[5].u.data,
980 951
 										(char*)a->val[6].u.data,
981 952
 										(char*)a->val[7].u.data
982
-									);
983
-				if (ret==0) h->run_flags|=EXIT_R_F;
984
-				h->last_retcode=ret;
985
-				_last_returned_code = h->last_retcode;
986
-			} else {
987
-				LOG(L_CRIT,"BUG: do_action: bad module call\n");
988
-				goto error;
989
-			}
953
+					);
990 954
 			break;
991 955
 		case MODULEX_T:
992
-			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
993
-					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
994
-				ret=((cmd_function_var)f)(msg,
995
-											a->val[1].u.number,
996
-											&a->val[2]
997
-										);
998
-				if (ret==0) h->run_flags|=EXIT_R_F;
999
-				h->last_retcode=ret;
1000
-				_last_returned_code = h->last_retcode;
1001
-			} else {
1002
-				LOG(L_CRIT,"BUG: do_action: bad module call\n");
1003
-				goto error;
1004
-			}
956
+			MODF_CALL(cmd_function_var, h, msg, a->val,
957
+							a->val[1].u.number, &a->val[2]);
958
+			break;
959
+		case MODULE1_RVE_T:
960
+			MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params,
961
+											(char*)mod_f_params[2].u.data,
962
+											0
963
+					);
964
+			break;
965
+		case MODULE2_RVE_T:
966
+			MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params,
967
+											(char*)mod_f_params[2].u.data,
968
+											(char*)mod_f_params[3].u.data
969
+					);
970
+			break;
971
+		case MODULE3_RVE_T:
972
+			MODF_RVE_CALL(cmd_function3, h, msg, a->val, mod_f_params,
973
+											(char*)mod_f_params[2].u.data,
974
+											(char*)mod_f_params[3].u.data,
975
+											(char*)mod_f_params[4].u.data
976
+					);
977
+			break;
978
+		case MODULE4_RVE_T:
979
+			MODF_RVE_CALL(cmd_function4, h, msg, a->val, mod_f_params,
980
+											(char*)mod_f_params[2].u.data,
981
+											(char*)mod_f_params[3].u.data,
982
+											(char*)mod_f_params[4].u.data,
983
+											(char*)mod_f_params[5].u.data
984
+					);
985
+			break;
986
+		case MODULE5_RVE_T:
987
+			MODF_RVE_CALL(cmd_function5, h, msg, a->val, mod_f_params,
988
+											(char*)mod_f_params[2].u.data,
989
+											(char*)mod_f_params[3].u.data,
990
+											(char*)mod_f_params[4].u.data,
991
+											(char*)mod_f_params[5].u.data,
992
+											(char*)mod_f_params[6].u.data
993
+					);
994
+			break;
995
+		case MODULE6_RVE_T:
996
+			MODF_RVE_CALL(cmd_function6, h, msg, a->val, mod_f_params,
997
+											(char*)mod_f_params[2].u.data,
998
+											(char*)mod_f_params[3].u.data,
999
+											(char*)mod_f_params[4].u.data,
1000
+											(char*)mod_f_params[5].u.data,
1001
+											(char*)mod_f_params[6].u.data,
1002
+											(char*)mod_f_params[7].u.data
1003
+					);
1004
+			break;
1005
+		case MODULEX_RVE_T:
1006
+			MODF_RVE_CALL(cmd_function_var, h, msg, a->val, mod_f_params,
1007
+							a->val[1].u.number, &mod_f_params[2]);
1005 1008
 			break;
1006 1009
 		case EVAL_T:
1007 1010
 			/* only eval the expression to account for possible
... ...
@@ -1357,11 +1542,8 @@ end:
1357 1357
 	/* process module onbreak handlers if present */
1358 1358
 	if (unlikely(h->rec_lev==0 && ret==0))
1359 1359
 		for (mod=modules;mod;mod=mod->next)
1360
-			if (unlikely((mod->mod_interface_ver==0) && mod->exports && 
1361
-					mod->exports->v0.onbreak_f)) {
1362
-				mod->exports->v0.onbreak_f( msg );
1363
-				DBG("DEBUG: %s onbreak handler called\n",
1364
-						mod->exports->c.name);
1360
+			if (unlikely(mod->exports.onbreak_f)) {
1361
+				mod->exports.onbreak_f( msg );
1365 1362
 			}
1366 1363
 	return ret;
1367 1364
 
... ...
@@ -243,6 +243,8 @@ static struct case_stms* mk_case_stm(struct rval_expr* ct, int is_re,
243 243
 									struct action* a, int* err);
244 244
 static int case_check_type(struct case_stms* stms);
245 245
 static int case_check_default(struct case_stms* stms);
246
+static int mod_f_params_pre_fixup(struct action* a);
247
+static void free_mod_func_action(struct action* a);
246 248
 
247 249
 
248 250
 extern int line;
... ...
@@ -2232,7 +2234,14 @@ fcmd:
2232 2232
 				case RESETFLAG_T:
2233 2233
 				case ISFLAGSET_T:
2234 2234
 				case IF_T:
2235
-				case MODULE_T:
2235
+				case MODULE0_T:
2236
+				case MODULE1_T:
2237
+				case MODULE2_T:
2238
+				case MODULE3_T:
2239
+				case MODULE4_T:
2240
+				case MODULE5_T:
2241
+				case MODULE6_T:
2242
+				case MODULEX_T:
2236 2243
 				case SET_FWD_NO_CONNECT_T:
2237 2244
 				case SET_RPL_NO_CONNECT_T:
2238 2245
 				case SET_FWD_CLOSE_T:
... ...
@@ -2705,7 +2714,7 @@ rval: intno			{$$=mk_rve_rval(RV_INT, (void*)$1); }
2705 2705
 
2706 2706
 
2707 2707
 rve_un_op: NOT	{ $$=RVE_LNOT_OP; }
2708
-		|  MINUS %prec UNARY	{ $$=RVE_UMINUS_OP; } 
2708
+		|  MINUS %prec UNARY	{ $$=RVE_UMINUS_OP; }
2709 2709
 		/* TODO: RVE_BOOL_OP, RVE_NOT_OP? */
2710 2710
 	;
2711 2711
 
... ...
@@ -3221,9 +3230,9 @@ cmd:
3221 3221
 	| SET_RPL_CLOSE	{
3222 3222
 		$$=mk_action(SET_RPL_CLOSE_T, 0); set_cfg_pos($$);
3223 3223
 	}
3224
-	| ID {mod_func_action = mk_action(MODULE_T, 2, MODEXP_ST, NULL, NUMBER_ST,
3224
+	| ID {mod_func_action = mk_action(MODULE0_T, 2, MODEXP_ST, NULL, NUMBER_ST,
3225 3225
 			0); } LPAREN func_params RPAREN	{
3226
-		mod_func_action->val[0].u.data = 
3226
+		mod_func_action->val[0].u.data =
3227 3227
 			find_export_record($1, mod_func_action->val[1].u.number, rt,
3228 3228
 								&u_tmp);
3229 3229
 		if (mod_func_action->val[0].u.data == 0) {
... ...
@@ -3233,34 +3242,14 @@ cmd:
3233 3233
 			} else {
3234 3234
 				yyerror("unknown command, missing loadmodule?\n");
3235 3235
 			}
3236
-			pkg_free(mod_func_action);
3236
+			free_mod_func_action(mod_func_action);
3237 3237
 			mod_func_action=0;
3238 3238
 		}else{
3239
-			switch( ((union cmd_export_u*)
3240
-						mod_func_action->val[0].u.data)->c.param_no){
3241
-				case 0:
3242
-				case 1:
3243
-				case 2:
3244
-					/* MODULE_T used for 0-2 params */
3245
-					break;
3246
-				case 3:
3247
-					mod_func_action->type=MODULE3_T;
3248
-					break;
3249
-				case 4:
3250
-					mod_func_action->type=MODULE4_T;
3251
-					break;
3252
-				case 5:
3253
-					mod_func_action->type=MODULE5_T;
3254
-					break;
3255
-				case 6:
3256
-					mod_func_action->type=MODULE6_T;
3257
-					break;
3258
-				case VAR_PARAM_NO:
3259
-					mod_func_action->type=MODULEX_T;
3260
-					break;
3261
-				default:
3262
-					yyerror("too many parameters for function\n");
3263
-					break;
3239
+			if (mod_func_action && mod_f_params_pre_fixup(mod_func_action)<0) {
3240
+				/* error messages are printed inside the function */
3241
+				free_mod_func_action(mod_func_action);
3242
+				mod_func_action = 0;
3243
+				YYERROR;
3264 3244
 			}
3265 3245
 		}
3266 3246
 		$$ = mod_func_action;
... ...
@@ -3272,27 +3261,20 @@ func_params:
3272 3272
 	/* empty */
3273 3273
 	| func_params COMMA func_param { }
3274 3274
 	| func_param {}
3275
-	| func_params error { yyerror("call params error\n"); }
3276 3275
 	;
3277 3276
 func_param:
3278
-        intno {
3279
-		if (mod_func_action->val[1].u.number < MAX_ACTIONS-2) {
3277
+	rval_expr {
3278
+		if ($1 && mod_func_action->val[1].u.number < MAX_ACTIONS-2) {
3280 3279
 			mod_func_action->val[mod_func_action->val[1].u.number+2].type =
3281
-				NUMBER_ST;
3282
-			mod_func_action->val[mod_func_action->val[1].u.number+2].u.number =
3280
+				RVE_ST;
3281
+			mod_func_action->val[mod_func_action->val[1].u.number+2].u.data =
3283 3282
 				$1;
3284 3283
 			mod_func_action->val[1].u.number++;
3285
-		} else {
3284
+		} else if ($1) {
3286 3285
 			yyerror("Too many arguments\n");
3287
-		}
3288
-	}
3289
-	| STRING {
3290
-		if (mod_func_action->val[1].u.number < MAX_ACTIONS-2) {
3291
-			mod_func_action->val[mod_func_action->val[1].u.number+2].type = STRING_ST;
3292
-			mod_func_action->val[mod_func_action->val[1].u.number+2].u.string = $1;
3293
-			mod_func_action->val[1].u.number++;
3286
+			YYERROR;
3294 3287
 		} else {
3295
-			yyerror("Too many arguments\n");
3288
+			YYERROR;
3296 3289
 		}
3297 3290
 	}
3298 3291
 	;
... ...
@@ -3735,6 +3717,125 @@ static int case_check_default(struct case_stms* stms)
3735 3735
 
3736 3736
 
3737 3737
 
3738
+/** fixes the parameters and the type of a module function call.
3739
+ * It is done here instead of fix action, to have quicker feedback
3740
+ * on error cases (e.g. passing a non constant to a function with a 
3741
+ * declared fixup) 
3742
+ * The rest of the fixup is done inside do_action().
3743
+ * @param a - filled module function call (MODULE*_T) action structure
3744
+ *            complete with parameters, starting at val[2] and parameter
3745
+ *            number at val[1].
3746
+ * @return 0 on success, -1 on error (it will also print the error msg.).
3747
+ *
3748
+ */
3749
+static int mod_f_params_pre_fixup(struct action* a)
3750
+{
3751
+	sr31_cmd_export_t* cmd_exp;
3752
+	action_u_t* params;
3753
+	int param_no;
3754
+	struct rval_expr* rve;
3755
+	struct rvalue* rv;
3756
+	int r;
3757
+	str s;
3758
+	
3759
+	cmd_exp = a->val[0].u.data;
3760
+	param_no = a->val[1].u.number;
3761
+	params = &a->val[2];
3762
+	
3763
+	switch(cmd_exp->param_no) {
3764
+		case 0:
3765
+			a->type = MODULE0_T;
3766
+			break;
3767
+		case 1:
3768
+			a->type = MODULE1_T;
3769
+			break;
3770
+		case 2:
3771
+			a->type = MODULE2_T;
3772
+			break;
3773
+		case 3:
3774
+			a->type = MODULE3_T;
3775
+			break;
3776
+		case 4:
3777
+			a->type = MODULE4_T;
3778
+			break;
3779
+		case 5:
3780
+			a->type = MODULE5_T;
3781
+			break;
3782
+		case 6:
3783
+			a->type = MODULE6_T;
3784
+			break;
3785
+		case VAR_PARAM_NO:
3786
+			a->type = MODULEX_T;
3787
+			break;
3788
+		default:
3789
+			yyerror("function %s: bad definition"
3790
+					" (invalid number of parameters)", cmd_exp->name);
3791
+			return -1;
3792
+	}
3793
+	
3794
+	if ( cmd_exp->fixup) {
3795
+		if (is_fparam_rve_fixup(cmd_exp->fixup))
3796
+			/* mark known fparam rve safe fixups */
3797
+			cmd_exp->fixup_flags  |= FIXUP_F_FPARAM_RVE;
3798
+		else if (!(cmd_exp->fixup_flags & FIXUP_F_FPARAM_RVE) &&
3799
+				 cmd_exp->free_fixup == 0) {
3800
+			/* v0 or v1 functions that have fixups and no coresp. fixup_free
3801
+			   functions, need constant, string params.*/
3802
+			for (r=0; r < param_no; r++) {
3803
+				rve=params[r].u.data;
3804
+				if (!rve_is_constant(rve)) {
3805
+					yyerror_at(&rve->fpos, "function %s: parameter %d is not"
3806
+								" constant\n", cmd_exp->name, r+1);
3807
+					return -1;
3808
+				}
3809
+				if ((rv = rval_expr_eval(0, 0, rve)) == 0 ||
3810
+						rval_get_str(0, 0, &s, rv, 0) < 0 ) {
3811
+					/* out of mem or bug ? */
3812
+					rval_destroy(rv);
3813
+					yyerror_at(&rve->fpos, "function %s: bad parameter %d"
3814
+									" expression\n", cmd_exp->name, r+1);
3815
+					return -1;
3816
+				}
3817
+				rval_destroy(rv);
3818
+				rve_destroy(rve);
3819
+				params[r].type = STRING_ST; /* asciiz */
3820
+				params[r].u.string = s.s;
3821
+				params[r].u.str.len = s.len; /* not used right now */
3822
+			}
3823
+		}
3824
+	}/* else
3825
+		if no fixups are present, the RVEs can be transformed
3826
+		into strings at runtime, allowing seamless var. use
3827
+		even with old functions.
3828
+		Further optimizations -> in fix_actions()
3829
+		*/
3830
+	return 0;
3831
+}
3832
+
3833
+
3834
+
3835
+/** frees a filled module function call action structure.
3836
+ * @param a - filled module function call action structure
3837
+ *            complete with parameters, starting at val[2] and parameter
3838
+ *            number at val[1].
3839
+ */
3840
+static void free_mod_func_action(struct action* a)
3841
+{
3842
+	action_u_t* params;
3843
+	int param_no;
3844
+	int r;
3845
+	
3846
+	param_no = a->val[1].u.number;
3847
+	params = &a->val[2];
3848
+	
3849
+	for (r=0; r < param_no; r++)
3850
+		if (params[r].u.data)
3851
+			rve_destroy(params[r].u.data);
3852
+	pkg_free(a);
3853
+}
3854
+
3855
+
3856
+
3738 3857
 /*
3739 3858
 int main(int argc, char ** argv)
3740 3859
 {
... ...
@@ -34,6 +34,7 @@
34 34
 
35 35
 #include "mod_fix.h"
36 36
 #include "mem/mem.h"
37
+#include "trim.h"
37 38
 
38 39
 
39 40
 
... ...
@@ -50,11 +51,8 @@ int fixup_regexpNL_none(void** param, int param_no); /* textops */
50 50
 	{ \
51 51
 		if ((param_no > (maxp)) || (param_no < (minp))) \
52 52
 			return E_UNSPEC; \
53
-		if (*param){ \
54
-			fparam_free_contents((fparam_t*)*param); \
55
-			pkg_free(*param); \
56
-			*param=0; \
57
-		} \
53
+		if (*param) \
54
+			fparam_free_restore(param); \
58 55
 		return 0; \
59 56
 	}
60 57
 
... ...
@@ -149,7 +147,7 @@ int fixup_regexpNL_none(void** param, int param_no); /* textops */
149 149
 		int ret; \
150 150
 		if (param && *param){ \
151 151
 			p=(param_no>(no1))? *param - (long)&((fparam_t*)0)->v : *param;\
152
-			if ((ret=fixup_free_fpt_##suffix(&p, param_no))==0) *param=0; \
152
+			if ((ret=fixup_free_fpt_##suffix(&p, param_no))==0) *param=p; \
153 153
 			return ret; \
154 154
 		} \
155 155
 		return 0; \
... ...
@@ -168,24 +166,288 @@ int fixup_regexpNL_none(void** param, int param_no); /* textops */
168 168
 
169 169
 FIXUP_F1T(str_null, 1, 1, FPARAM_STR)
170 170
 FIXUP_F1T(str_str, 1, 2,  FPARAM_STR)
171
+FIXUP_F1T(str_all, 1, 100,  FPARAM_STR)
171 172
 
172
-/* TODO: int can be converted in place, no need for pkg_malloc'ed fparam_t*/
173
+/*
174
+  no free fixups possible for unit_*
175
+  (they overwrite the pointer with the converted number => the original
176
+   value cannot be recovered)
173 177
 FIXUP_F1T(uint_null, 1, 1, FPARAM_INT)
174 178
 FIXUP_F1T(uint_uint, 1, 2, FPARAM_INT)
179
+*/
180
+
181
+
182
+
183
+int fixup_uint_uint(void** param, int param_no)
184
+{
185
+	str s;
186
+	unsigned int num;
187
+	
188
+	s.s = *param;
189
+	s.len = strlen(s.s);
190
+	if (likely(str2int(&s, &num) == 0)) {
191
+		*param = (void*)(long)num;
192
+	} else
193
+		/* not a number */
194
+		return E_UNSPEC;
195
+	return 0;
196
+}
197
+
198
+
199
+
200
+int fixup_uint_null(void** param, int param_no)
201
+{
202
+	if (param_no == 1)
203
+		return fixup_uint_uint(param, param_no);
204
+	return E_UNSPEC;
205
+}
206
+
175 207
 
208
+/* fixup_regexp_null() has to be written "by hand", since
209
+   it needs to save the original pointer (the fixup users expects
210
+   a pointer to the regex in *param and hence the original value
211
+   needed on free cannot be recovered directly).
176 212
 FIXUP_F1T(regexp_null, 1, 1, FPARAM_REGEX)
213
+*/
177 214
 
215
+struct regex_fixup {
216
+	regex_t regex; /* compiled regex */
217
+	void* orig;    /* original pointer */
218
+};
219
+
220
+int fixup_regexp_null(void** param, int param_no)
221
+{
222
+	struct regex_fixup* re;
223
+	
224
+	if (param_no != 1)
225
+		return E_UNSPEC;
226
+	if ((re=pkg_malloc(sizeof(*re))) ==0) {
227
+		ERR("No memory left\n");
228
+		goto error;
229
+	}
230
+	if (regcomp(&re->regex, *param,
231
+				REG_EXTENDED|REG_ICASE|REG_NEWLINE))
232
+		goto error;
233
+	re->orig = *param;
234
+	*param = re;
235
+	return 0;
236
+error:
237
+	if (re)
238
+		pkg_free(re);
239
+	return E_UNSPEC;
240
+}
241
+
242
+
243
+int fixup_free_regexp_null(void** param, int param_no)
244
+{
245
+	struct regex_fixup* re;
246
+	
247
+	if (param_no != 1)
248
+		return E_UNSPEC;
249
+	if (*param) {
250
+		re = *param;
251
+		*param = re->orig;
252
+		regfree(&re->regex);
253
+		pkg_free(re);
254
+	}
255
+	return 0;
256
+}
257
+
258
+/* fixup_pvar_*() has to be written "by hand", since
259
+   it needs to save the original pointer (the fixup users expects
260
+   a pointer to the pv_spec_t in *param and hence the original value
261
+   needed on free cannot be recovered directly).
178 262
 FIXUP_F1T(pvar_null, 1, 1, FPARAM_PVS)
179 263
 FIXUP_F1T(pvar_pvar, 1, 2, FPARAM_PVS)
264
+*/
265
+
266
+struct pvs_fixup {
267
+	pv_spec_t pvs; /* parsed pv spec */
268
+	void* orig;    /* original pointer */
269
+};
270
+
271
+int fixup_pvar_all(void** param, int param_no)
272
+{
273
+	struct pvs_fixup* pvs_f;
274
+	str name;
275
+	
276
+	pvs_f = 0;
277
+	name.s = *param;
278
+	name.len = strlen(name.s);
279
+	trim(&name);
280
+	if (name.len == 0 || name.s[0] != '$')
281
+		/* not a pvs id */
282
+		goto error;
283
+	if ((pvs_f=pkg_malloc(sizeof(*pvs_f))) == 0) {
284
+		ERR("No memory left\n");
285
+		goto error;
286
+	}
287
+	if (pv_parse_spec2(&name, &pvs_f->pvs, 1) == 0)
288
+		/* not a valid pvs identifier */
289
+		goto error;
290
+	pvs_f->orig = *param;
291
+	*param = pvs_f;
292
+	return 0;
293
+error:
294
+	if (pvs_f)
295
+		pkg_free(pvs_f);
296
+	return E_UNSPEC;
297
+}
298
+
299
+
300
+
301
+int fixup_free_pvar_all(void** param, int param_no)
302
+{
303
+	struct pvs_fixup* pvs_f;
304
+	
305
+	if (*param) {
306
+		pvs_f = *param;
307
+		*param = pvs_f->orig;
308
+		/* free only the contents (don't attempt to free &pvs_f->pvs)*/
309
+		pv_spec_destroy(&pvs_f->pvs);
310
+		/* free the whole pvs_fixup */
311
+		pkg_free(pvs_f);
312
+	}
313
+	return 0;
314
+}
315
+
316
+
317
+
318
+int fixup_pvar_pvar(void** param, int param_no)
319
+{
320
+	if (param_no > 2)
321
+		return E_UNSPEC;
322
+	return fixup_free_pvar_all(param, param_no);
323
+}
324
+
325
+
326
+
327
+int fixup_free_pvar_pvar(void** param, int param_no)
328
+{
329
+	if (param_no > 2)
330
+		return E_UNSPEC;
331
+	return fixup_free_pvar_all(param, param_no);
332
+}
333
+
334
+
335
+
336
+int fixup_pvar_null(void** param, int param_no)
337
+{
338
+	if (param_no != 1)
339
+		return E_UNSPEC;
340
+	return fixup_pvar_all(param, param_no);
341
+}
342
+
180 343
 
344
+
345
+int fixup_free_pvar_null(void** param, int param_no)
346
+{
347
+	if (param_no != 1)
348
+		return E_UNSPEC;
349
+	return fixup_free_pvar_all(param, param_no);
350
+}
351
+
352
+/* must be written "by hand", see above (fixup_pvar_pvar).
181 353
 FIXUP_F2T(pvar_str, 1, 2, 1, FPARAM_PVS, FPARAM_STR)
182 354
 FIXUP_F2T(pvar_str_str, 1, 3, 1, FPARAM_PVS, FPARAM_STR)
355
+*/
356
+
357
+int fixup_pvar_str(void** param, int param_no)
358
+{
359
+	if (param_no == 1)
360
+		return fixup_pvar_all(param, param_no);
361
+	else if (param_no == 2)
362
+		return fixup_str_str(param, param_no);
363
+	return E_UNSPEC;
364
+}
365
+
366
+
367
+
368
+int fixup_free_pvar_str(void** param, int param_no)
369
+{
370
+	if (param_no == 1)
371
+		return fixup_free_pvar_all(param, param_no);
372
+	else if (param_no == 2)
373
+		return fixup_free_str_str(param, param_no);
374
+	return E_UNSPEC;
375
+}
376
+
377
+
378
+
379
+int fixup_pvar_str_str(void** param, int param_no)
380
+{
381
+	if (param_no == 1)
382
+		return fixup_pvar_all(param, param_no);
383
+	else if (param_no == 2 || param_no == 3)
384
+		return fixup_str_all(param, param_no);
385
+	return E_UNSPEC;
386
+}
387
+
388
+
389
+
390
+int fixup_free_pvar_str_str(void** param, int param_no)
391
+{
392
+	if (param_no == 1)
393
+		return fixup_free_pvar_all(param, param_no);
394
+	else if (param_no == 2 || param_no == 3)
395
+		return fixup_free_str_all(param, param_no);
396
+	return E_UNSPEC;
397
+}
398
+
399
+
183 400
 
184 401
 FIXUP_F2FP(igp_null, 1, 1, 1, FPARAM_INT|FPARAM_PVS, 0)
185 402
 FIXUP_F2FP(igp_igp, 1, 2, 2,  FPARAM_INT|FPARAM_PVS, 0)
186
-FIXUP_F2FP(igp_pvar, 1, 2, 1,  FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
187 403
 
404
+/* must be declared by hand, because of the pvar special handling
405
+   (see above)
406
+FIXUP_F2FP(igp_pvar, 1, 2, 1,  FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
188 407
 FIXUP_F2FP_T(igp_pvar_pvar, 1, 3, 1, FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
408
+*/
409
+
410
+int fixup_igp_pvar(void** param, int param_no)
411
+{
412
+	if (param_no == 1)
413
+		return fixup_igp_null(param, param_no);
414
+	else if (param_no == 2)
415
+		return fixup_pvar_all(param, param_no);
416
+	return E_UNSPEC;
417
+}
418
+
419
+
420
+
421
+int fixup_free_igp_pvar(void** param, int param_no)
422
+{
423
+	if (param_no == 1)
424
+		return fixup_free_igp_null(param, param_no);
425
+	else if (param_no == 2)
426
+		return fixup_free_pvar_all(param, param_no);
427
+	return E_UNSPEC;
428
+}
429
+
430
+
431
+
432
+int fixup_igp_pvar_pvar(void** param, int param_no)
433
+{
434
+	if (param_no == 1)
435
+		return fixup_igp_null(param, param_no);
436
+	else if (param_no == 2 || param_no == 3)
437
+		return fixup_pvar_all(param, param_no);
438
+	return E_UNSPEC;
439
+}
440
+
441
+
442
+
443
+int fixup_free_igp_pvar_pvar(void** param, int param_no)
444
+{
445
+	if (param_no == 1)
446
+		return fixup_free_igp_null(param, param_no);
447
+	else if (param_no == 2 || param_no == 3)
448
+		return fixup_free_pvar_all(param, param_no);
449
+	return E_UNSPEC;
450
+}
451
+
452
+
189 453
 
190 454
 /** macro for declaring a spve fixup and the corresponding free_fixup
191 455
   * for a function expecting first no1 params as fparam converted spve 
... ...
@@ -202,21 +464,16 @@ FIXUP_F2FP_T(igp_pvar_pvar, 1, 3, 1, FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
202 202
 	int fixup_##suffix (void** param, int param_no) \
203 203
 	{ \
204 204
 		int ret; \
205
-		char * bkp; \
206 205
 		fparam_t* fp; \
207 206
 		if (param_no<=(no1)){ \
208 207
 			if ((ret=fix_param_types(FPARAM_PVE, param))<0){ \
209
-				ERR("Cannot convert function parameter %d to" #type2 "\n", \
208
+				ERR("Cannot convert function parameter %d to spve \n", \
210 209
 						param_no);\
211 210
 				return E_UNSPEC; \
212 211
 			} else{ \
213 212
 				fp=(fparam_t*)*param; \
214 213
 				if ((ret==0) && (fp->v.pve->spec.getf==0)){ \
215
-					bkp=fp->orig; \
216
-					fp->orig=0; /* make sure orig string is not freed */ \
217
-					fparam_free_contents(fp); \
218
-					pkg_free(fp); \
219
-					*param=bkp; \
214
+					fparam_free_restore(param); \
220 215
 					return fix_param_types(FPARAM_STR, param); \
221 216
 				} else if (ret==1) \
222 217
 					return fix_param_types(FPARAM_STR, param); \
... ...
@@ -228,11 +485,9 @@ FIXUP_F2FP_T(igp_pvar_pvar, 1, 3, 1, FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
228 228
 	int fixup_free_##suffix (void** param, int param_no) \
229 229
 	{ \
230 230
 		if (param && *param){ \
231
-			if (param_no<=(no1)){ \
232
-				fparam_free_contents((fparam_t*)*param); \
233
-				pkg_free(*param); \
234
-				*param=0; \
235
-			} else \
231
+			if (param_no<=(no1)) \
232
+				fparam_free_restore(param); \
233
+			else \
236 234
 				return fixup_free_spvet_##suffix(param, param_no); \
237 235
 		} \
238 236
 		return 0; \
... ...
@@ -244,3 +499,33 @@ FIXUP_F_SPVE_T(spve_spve, 1, 2, 2, 0)
244 244
 FIXUP_F_SPVE_T(spve_uint, 1, 2, 1, FPARAM_INT)
245 245
 FIXUP_F_SPVE_T(spve_str, 1, 2, 1, FPARAM_STR)
246 246
 FIXUP_F_SPVE_T(spve_null, 1, 1, 1, 0)
247
+
248
+/** get the corresp. fixup_free* function.
249
+ * @param f -fixup function pointer.
250
+ * @return  - pointer to free_fixup function if known, 0 otherwise.
251
+ */
252
+free_fixup_function mod_fix_get_fixup_free(fixup_function f)
253
+{
254
+	if (f == fixup_str_null) return fixup_free_str_null;
255
+	if (f == fixup_str_str) return fixup_free_str_str;
256
+	/* no free fixup for fixup_uint_* (they overwrite the pointer
257
+	   value with a number and the original value cannot be recovered) */
258
+	if (f == fixup_uint_null) return 0;
259
+	if (f == fixup_uint_uint) return 0;
260
+	if (f == fixup_regexp_null) return fixup_free_regexp_null;
261
+	if (f == fixup_pvar_null) return fixup_free_pvar_null;
262
+	if (f == fixup_pvar_pvar) return fixup_free_pvar_pvar;
263
+	if (f == fixup_pvar_str) return fixup_free_pvar_str;
264
+	if (f == fixup_pvar_str_str) return fixup_free_pvar_str_str;
265
+	if (f == fixup_igp_igp) return fixup_free_igp_igp;
266
+	if (f == fixup_igp_null) return fixup_free_igp_null;
267
+	if (f == fixup_igp_pvar) return fixup_free_igp_pvar;
268
+	if (f == fixup_igp_pvar_pvar) return fixup_free_igp_pvar_pvar;
269
+	if (f == fixup_spve_spve) return fixup_free_spve_spve;
270
+	if (f == fixup_spve_null) return fixup_free_spve_null;
271
+	/* no free fixup, because of the uint part (the uint cannot be freed,
272
+	   see above fixup_uint_null) */
273
+	if (f == fixup_spve_uint) return 0;
274
+	if (f == fixup_spve_str) return fixup_free_spve_str;
275
+	return 0;
276
+}
... ...
@@ -106,7 +106,9 @@ int fixup_pvar_str_str(void** param, int param_no);
106 106
 int fixup_free_pvar_str_str(void** param, int param_no);
107 107
 
108 108
 int fixup_igp_igp(void** param, int param_no);
109
+int fixup_free_igp_igp(void** param, int param_no);
109 110
 int fixup_igp_null(void** param, int param_no);
111
+int fixup_free_igp_null(void** param, int param_no);
110 112
 int fixup_get_ivalue(struct sip_msg* msg, gparam_p gp, int *val);
111 113
 
112 114
 int fixup_igp_pvar(void** param, int param_no);
... ...
@@ -116,8 +118,15 @@ int fixup_igp_pvar_pvar(void** param, int param_no);
116 116
 int fixup_free_igp_pvar_pvar(void** param, int param_no);
117 117
 
118 118
 int fixup_spve_spve(void** param, int param_no);
119
+int fixup_free_spve_spve(void** param, int param_no);
119 120
 int fixup_spve_null(void** param, int param_no);
121
+int fixup_free_spve_null(void** param, int param_no);
120 122
 int fixup_spve_uint(void** param, int param_no);
121 123
 int fixup_spve_str(void** param, int param_no);
124
+int fixup_free_spve_str(void** param, int param_no);
125
+
126
+
127
+/** get the corresp. free fixup function.*/
128
+free_fixup_function mod_fix_get_fixup_free(fixup_function f);
122 129
 
123 130
 #endif
... ...
@@ -91,9 +91,9 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
91 91
 
92 92
 	mod_found = 0;
93 93
 	for(t = modules; t; t = t->next) {
94
-		if (regexec(&preg, t->exports->c.name, 0, 0, 0) == 0) {
94
+		if (regexec(&preg, t->exports.name, 0, 0, 0) == 0) {
95 95
 			DBG("set_mod_param_regex: '%s' matches module '%s'\n",
96
-					regex, t->exports->c.name);
96
+					regex, t->exports.name);
97 97
 			mod_found = 1;
98 98
 			/* PARAM_STR (PARAM_STRING) may be assigned also to PARAM_STRING(PARAM_STR) so let get both module param */
99 99
 			ptr = find_param_export(t, name, type | ((type & (PARAM_STR|PARAM_STRING))?PARAM_STR|PARAM_STRING:0), &param_type);
... ...
@@ -109,7 +109,7 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
109 109
 					val2 = val;
110 110
 				}
111 111
 				DBG("set_mod_param_regex: found <%s> in module %s [%s]\n",
112
-						name, t->exports->c.name, t->path);
112
+						name, t->exports.name, t->path);
113 113
 				if (param_type & PARAM_USE_FUNC) {
114 114
 					if ( ((param_func_t)(ptr))(param_type, val2) < 0) {
115 115
 						regfree(&preg);
... ...
@@ -147,7 +147,7 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
147 147
 			}
148 148
 			else {
149 149
 				LOG(L_ERR, "set_mod_param_regex: parameter <%s> not found in"
150
-							" module <%s>\n", name, t->exports->c.name);
150
+							" module <%s>\n", name, t->exports.name);
151 151
 				regfree(&preg);
152 152
 				pkg_free(reg);
153 153
 				return -3;
... ...
@@ -193,7 +193,7 @@ msg_call_function(msgobject *self, PyObject *args)
193 193
 {
194 194
     int i, rval;
195 195
     char *fname, *arg1, *arg2;
196
-    union cmd_export_u* fexport;
196
+    sr31_cmd_export_t* fexport;
197 197
     struct action *act;
198 198
     struct run_act_ctx ra_ctx;
199 199
     unsigned mod_ver;
... ...
@@ -222,7 +222,7 @@ msg_call_function(msgobject *self, PyObject *args)
222 222
         return Py_None;
223 223
     }
224 224
 
225
-    act = mk_action(MODULE_T, 4 /* number of (type, value) pairs */,
225
+    act = mk_action(MODULE2_T, 4 /* number of (type, value) pairs */,
226 226
                     MODEXP_ST, fexport, /* function */
227 227
                     NUMBER_ST, 2,       /* parameter number */
228 228
                     STRING_ST, arg1,    /* param. 1 */
... ...
@@ -236,9 +236,9 @@ msg_call_function(msgobject *self, PyObject *args)
236 236
         return Py_None;
237 237
     }
238 238
 
239
-    if (fexport->v1.fixup != NULL) {
239
+    if (fexport->fixup != NULL) {
240 240
         if (i >= 3) {
241
-            rval = fexport->v1.fixup(&(act->val[3].u.data), 2);
241
+            rval = fexport->fixup(&(act->val[3].u.data), 2);
242 242
             if (rval < 0) {
243 243
                 PyErr_SetString(PyExc_RuntimeError, "Error in fixup (2)");
244 244
                 Py_INCREF(Py_None);
... ...
@@ -247,7 +247,7 @@ msg_call_function(msgobject *self, PyObject *args)
247 247
             act->val[3].type = MODFIXUP_ST;
248 248
         }
249 249
         if (i >= 2) {
250
-            rval = fexport->v1.fixup(&(act->val[2].u.data), 1);
250
+            rval = fexport->fixup(&(act->val[2].u.data), 1);
251 251
             if (rval < 0) {
252 252
                 PyErr_SetString(PyExc_RuntimeError, "Error in fixup (1)");
253 253
                 Py_INCREF(Py_None);
... ...
@@ -256,7 +256,7 @@ msg_call_function(msgobject *self, PyObject *args)
256 256
             act->val[2].type = MODFIXUP_ST;
257 257
         }
258 258
         if (i == 1) {
259
-            rval = fexport->v1.fixup(0, 0);
259
+            rval = fexport->fixup(0, 0);
260 260
             if (rval < 0) {
261 261
                 PyErr_SetString(PyExc_RuntimeError, "Error in fixup (0)");
262 262
                 Py_INCREF(Py_None);
... ...
@@ -215,7 +215,7 @@ int moduleFunc(struct sip_msg *m, char *func,
215 215
 	       char *param1, char *param2,
216 216
 	       int *retval) {
217 217
 
218
-    union cmd_export_u* exp_func_struct;
218
+	sr31_cmd_export_t* exp_func_struct;
219 219
 	struct action *act;
220 220
 	unsigned mod_ver;
221 221
 	char *argv[2];
... ...
@@ -259,7 +259,7 @@ int moduleFunc(struct sip_msg *m, char *func,
259 259
 		return -1;
260 260
 	}
261 261
 
262
-	act = mk_action(MODULE_T, 4 /* number of (type, value) pairs */,
262
+	act = mk_action(MODULE2_T, 4 /* number of (type, value) pairs */,
263 263
 					MODEXP_ST, exp_func_struct, /* function */
264 264
 					NUMBER_ST, 2,  /* parameter number */
265 265
 					STRING_ST, argv[0], /* param. 1 */
... ...
@@ -275,7 +275,7 @@ int moduleFunc(struct sip_msg *m, char *func,
275 275
 	}
276 276
 
277 277
 
278
-	if (exp_func_struct->v1.fixup) {
278
+	if (exp_func_struct->fixup) {
279 279
 		if (!unsafemodfnc) {
280 280
 			LM_ERR("Module function '%s' is unsafe. Call is refused.\n", func);
281 281
 			if (argv[0]) pkg_free(argv[0]);
... ...
@@ -285,7 +285,7 @@ int moduleFunc(struct sip_msg *m, char *func,
285 285
 		}
286 286
 
287 287
 		if (argc>=2) {
288
-			*retval = exp_func_struct->v1.fixup(&(act->val[3].u.data), 2);
288
+			*retval = exp_func_struct->fixup(&(act->val[3].u.data), 2);
289 289
 			if (*retval < 0) {
290 290
 				LM_ERR("Error in fixup (2)\n");
291 291
 				return -1;
... ...
@@ -293,7 +293,7 @@ int moduleFunc(struct sip_msg *m, char *func,
293 293
 			act->val[3].type = MODFIXUP_ST;
294 294
 		}
295 295
 		if (argc>=1) {
296
-			*retval = exp_func_struct->v1.fixup(&(act->val[2].u.data), 1);
296
+			*retval = exp_func_struct->fixup(&(act->val[2].u.data), 1);
297 297
 			if (*retval < 0) {
298 298
 				LM_ERR("Error in fixup (1)\n");
299 299
 				return -1;
... ...
@@ -301,7 +301,7 @@ int moduleFunc(struct sip_msg *m, char *func,
301 301
 			act->val[2].type = MODFIXUP_ST;
302 302
 		}
303 303
 		if (argc==0) {
304
-			*retval = exp_func_struct->v1.fixup(0, 0);
304
+			*retval = exp_func_struct->fixup(0, 0);
305 305
 			if (*retval < 0) {
306 306
 				LM_ERR("Error in fixup (0)\n");
307 307
 				return -1;
... ...
@@ -46,9 +46,13 @@ MODULE_VERSION
46 46
 
47 47
 static int print_fixup_f_1(void **param, int param_no);
48 48
 static int print_fixup_f_2(void **param, int param_no);
49
-static int print_f_0(struct sip_msg*, char*,char*);
50
-static int print_f_1(struct sip_msg*, char*,char*);
51
-static int print_f_2(struct sip_msg*, char*,char*);
49
+static int print_f_0(struct sip_msg*, char*, char*);
50
+static int print_f_1(struct sip_msg*, char*, char*);
51
+static int print_f_2(struct sip_msg*, char*, char*);
52
+static int print_f1(struct sip_msg*, char*, char*);
53
+static int print_f2(struct sip_msg*, char*, char*);
54
+static int print_f3(struct sip_msg*, char*, char*, char*);
55
+static int print_f_var(struct sip_msg*, int argc, action_u_t argv[]);
52 56
 static int mod_init(void);
53 57
 
54 58
 /* the parameters are not used, they are only meant as an example*/
... ...
@@ -60,6 +64,10 @@ static cmd_export_t cmds[]={
60 60
 	{"print", print_f_0, 0, 0, REQUEST_ROUTE},   // overload test
61 61
 	{"print", print_f_1, 1, print_fixup_f_1, REQUEST_ROUTE},
62 62
 	{"print", print_f_2, 2, print_fixup_f_2, REQUEST_ROUTE},
63
+	{"print1", print_f1, 1, 0, REQUEST_ROUTE},
64
+	{"print2", print_f2, 2, fixup_var_str_12, REQUEST_ROUTE},
65
+	{"print3", (cmd_function)print_f3, 3, 0, REQUEST_ROUTE},
66
+	{"printv", (cmd_function)print_f_var, VAR_PARAM_NO, 0, REQUEST_ROUTE},
63 67
 	{0, 0, 0, 0, 0}
64 68
 };
65 69
 
... ...
@@ -90,6 +98,7 @@ static int mod_init(void)
90 90
 	DBG("print: string_param = '%s'\n", string_param);
91 91
 	DBG("print: str_param = '%.*s'\n", str_param.len, str_param.s);
92 92
 	DBG("print: int_param = %d\n", int_param);
93
+	WARN("this is an example module, it has no practical use\n");
93 94
 	return 0;
94 95
 }
95 96
 
... ...
@@ -132,3 +141,45 @@ static int print_fixup_f_2(void **param, int param_no) {
132 132
 	DBG("print: print_fixup_f_2('%s')\n", (char*)*param);
133 133
 	return print_fixup_f(param, param_no);
134 134
 }
135
+
136
+
137
+
138
+/* 1 parameter, no fixup version */
139
+static int print_f1(struct sip_msg* msg, char* s1, char* not_used)
140
+{
141
+	printf("%s\n", s1);
142
+	return 1;
143
+}
144
+
145
+
146
+/* 2 parameters, fparam fixup version */
147
+static int print_f2(struct sip_msg* msg, char* s1, char* s2)
148
+{
149
+	str a, b;
150
+	if (get_str_fparam(&a, msg, (fparam_t*)s1) !=0 ||
151
+		 get_str_fparam(&b, msg, (fparam_t*)s2) !=0) {
152
+		BUG("get_str_fparam failed\n");
153
+		return -1;
154
+	}
155
+	printf("%.*s%.*s\n", a.len, a.s, b.len, b.s);
156
+	return 1;
157
+}
158
+
159
+
160
+/* 3 parameters, no fixup version */
161
+static int print_f3(struct sip_msg* msg, char* s1, char* s2, char* s3)
162
+{
163
+	printf("%s%s%s\n", s1, s2, s3);
164
+	return 1;
165
+}
166
+
167
+
168
+/* variable number of parameters, no fixup version */
169
+static int print_f_var(struct sip_msg* msg, int argc, action_u_t argv[])
170
+{
171
+	int i;
172
+	for (i = 0; i < argc; i++)
173
+		printf("%s", argv[i].u.string);
174
+	printf("\n");
175
+	return 1;
176
+}
... ...
@@ -1147,8 +1147,9 @@ error:
1147 1147
 	return NULL;
1148 1148
 }
1149 1149
 
1150
-/**
1151
- * destroy the content of pv_spec_t structure
1150
+
1151
+
1152
+/** destroy the content of pv_spec_t structure.
1152 1153
  */
1153 1154
 void pv_spec_destroy(pv_spec_t *spec)
1154 1155
 {
... ...
@@ -1160,8 +1161,7 @@ void pv_spec_destroy(pv_spec_t *spec)
1160 1160
 		tr_free((trans_t*)spec->trans);
1161 1161
 }
1162 1162
 
1163
-/**
1164
- * free the pv_spec_t structure
1163
+/** free the pv_spec_t structure.
1165 1164
  */
1166 1165
 void pv_spec_free(pv_spec_t *spec)
1167 1166
 {
... ...
@@ -50,6 +50,8 @@
50 50
  *  		unless the operator is DIFF_OP (Miklos)
51 51
  *  2008-12-03  fixups for rvalues in assignments (andrei)
52 52
  *  2009-05-04  switched IF_T to rval_expr (andrei)
53
+ *  2010-06-01  special hack/support for fparam fixups so that they can handle
54
+ *               variable RVEs (andrei)
53 55
  *  2010-06-18  ip comparison (comp_ip()) normalizes strings to
54 56
  *              ip/netmask  (andrei)
55 57
  */
... ...
@@ -634,9 +636,10 @@ int fix_actions(struct action* a)
634 634
 	struct action *t;
635 635
 	struct proxy_l* p;
636 636
 	char *tmp;
637
+	void *tmp_p;
637 638
 	int ret;
638 639
 	int i;
639
-	union cmd_export_u* cmd;
640
+	sr31_cmd_export_t* cmd;
640 641
 	str s;
641 642
 	struct hostent* he;
642 643
 	struct ip_addr ip;
... ...
@@ -644,11 +647,9 @@ int fix_actions(struct action* a)
644 644
 	struct lvalue* lval;
645 645
 	struct rval_expr* rve;
646 646
 	struct rval_expr* err_rve;
647
-	struct rvalue* rv;
648 647
 	enum rval_type rve_type, err_type, expected_type;
649
-
650
-	
651
-	char buf[30]; /* tmp buffer needed for module param fixups */
648
+	struct rvalue* rv;
649
+	int rve_param_no;
652 650
 
653 651
 	if (a==0){
654 652
 		LOG(L_CRIT,"BUG: fix_actions: null pointer\n");
... ...
@@ -913,47 +914,119 @@ int fix_actions(struct action* a)
913 913
 					goto error;
914 914
 				break;
915 915
 
916
-			case MODULE_T:
916
+			case MODULE0_T:
917
+			case MODULE1_T:
918
+			case MODULE2_T:
917 919
 			case MODULE3_T:
918 920
 			case MODULE4_T:
919 921
 			case MODULE5_T:
920 922
 			case MODULE6_T:
921 923
 			case MODULEX_T:
922 924
 				cmd = t->val[0].u.data;
923
-				if (cmd && cmd->c.fixup) {
924
-					DBG("fixing %s()\n", cmd->c.name);
925
+				rve_param_no = 0;
926
+				if (cmd) {
927
+					DBG("fixing %s()\n", cmd->name);
925 928
 					if (t->val[1].u.number==0) {
926
-						ret = cmd->c.fixup(0, 0);
929
+						ret = call_fixup(cmd->fixup, 0, 0);
927 930
 						if (ret < 0)
928 931
 							goto error;
929 932
 					}
930
-					/* type cast NUMBER to STRING, old modules may expect
931
-					 * all STRING params during fixup */
932
-					for (i=0; i<t->val[1].u.number; i++) {
933
-						if (t->val[i+2].type == NUMBER_ST) {
934
-							snprintf(buf, sizeof(buf)-1, "%ld", 
935
-										t->val[i+2].u.number);
936
-							/* fixup currently requires string pkg_malloced*/
937
-							t->val[i+2].u.string = pkg_malloc(strlen(buf)+1);
938
-							if (!t->val[i+2].u.string) {
939
-								LOG(L_CRIT, "ERROR: cannot translate NUMBER"
940
-											" to STRING\n");
941
-								ret = E_OUT_OF_MEM;
942
-								goto error;
933
+					for (i=0; i < t->val[1].u.number; i++) {
934
+						if (t->val[i+2].type == RVE_ST) {
935
+							rve = t->val[i+2].u.data;
936
+							if (rve_is_constant(rve)) {
937
+								/* if expression is constant => evaluate it
938
+								   as string and replace it with the corresp.
939
+								   string */
940
+								rv = rval_expr_eval(0, 0, rve);
941
+								if (rv == 0 ||
942
+										rval_get_str( 0, 0, &s, rv, 0) < 0 ) {
943
+									ERR("failed to fix constant rve");
944
+									if (rv) rval_destroy(rv);
945
+									ret = E_BUG;
946
+									goto error;
947
+								}
948 </