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 110
 int _last_returned_code  = 0;
109 111
 struct onsend_info* p_onsend=0; /* onsend route send info */
110 112
 
113
+
114
+
115
+/* handle the exit code of a module function call.
116
+ * (used internally in do_action())
117
+ * @param h - script handle (h->last_retcode and h->run_flags will be set).
118
+ * @param ret - module function (v0 or v2) retcode
119
+ * Side-effects: sets _last_returned_code
120
+ */
121
+#define MODF_HANDLE_RETCODE(h, ret) \
122
+	do { \
123
+		/* if (unlikely((ret)==0)) (h)->run_flags|=EXIT_R_F; */ \
124
+		(h)->run_flags |= EXIT_R_F & (((ret) != 0) -1); \
125
+		(h)->last_retcode=(ret); \
126
+		_last_returned_code = (h)->last_retcode; \
127
+	} while(0)
128
+
129
+
130
+
131
+/* frees parameters converted using MODF_RVE_PARAM_CONVERT() from dst.
132
+ * (used internally in do_action())
133
+ * Assumes src is unchanged.
134
+ * Side-effects: clobbers i (int).
135
+ */
136
+#define MODF_RVE_PARAM_FREE(cmd, src, dst) \
137
+		for (i=0; i < (dst)[1].u.number; i++) { \
138
+			if ((src)[i+2].type == RVE_ST && (dst)[i+2].u.data) { \
139
+				if ((dst)[i+2].type == RVE_FREE_FIXUP_ST) {\
140
+					/* call free_fixup (which should restore the original
141
+					   string) */ \
142
+					call_fixup((cmd)->free_fixup, &(dst)[i+2].u.data, i+1); \
143
+				} else if ((dst)[i+2].type == FPARAM_DYN_ST) {\
144
+					/* completely frees fparam and restore original string */\
145
+					fparam_free_restore(&(dst)[i+2].u.data); \
146
+				} \
147
+				/* free allocated string */ \
148
+				pkg_free((dst)[i+2].u.data); \
149
+				(dst)[i+2].u.data = 0; \
150
+			} \
151
+		}
152
+
153
+
154
+/* fills dst from src, converting RVE_ST params to STRING_ST.
155
+ * (used internally in do_action())
156
+ * @param src - source action_u_t array, as in the action structure
157
+ * @param dst - destination action_u_t array, will be filled from src.
158
+ * WARNING: dst must be cleaned when done, use MODULE_RVE_PARAM_FREE()
159
+ * Side-effects: clobbers i (int), s (str), rv (rvalue*), might jump to error.
160
+ */
161
+#define MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst) \
162
+	do { \
163
+		(dst)[1]=(src)[1]; \
164
+		for (i=0; i < (src)[1].u.number; i++) { \
165
+			if ((src)[2+i].type == RVE_ST) { \
166
+				rv=rval_expr_eval((h), (msg), (src)[i+2].u.data); \
167
+				if (unlikely(rv == 0 || \
168
+					rval_get_str((h), (msg), &s, rv, 0) < 0)) { \
169
+					rval_destroy(rv); \
170
+					ERR("failed to convert RVE to string\n"); \
171
+					(dst)[1].u.number = i; \
172
+					MODF_RVE_PARAM_FREE(cmd, src, dst); \
173
+					goto error; \
174
+				} \
175
+				(dst)[i+2].type = STRING_RVE_ST; \
176
+				(dst)[i+2].u.string = s.s; \
177
+				(dst)[i+2].u.str.len = s.len; \
178
+				rval_destroy(rv); \
179
+				if ((cmd)->fixup) {\
180
+					if ((cmd)->free_fixup) {\
181
+						if (likely( call_fixup((cmd)->fixup, \
182
+										&(dst)[i+2].u.data, i+1) >= 0) ) { \
183
+							/* success => mark it for calling free fixup */ \
184
+							if (likely((dst)[i+2].u.data != s.s)) \
185
+								(dst)[i+2].type = RVE_FREE_FIXUP_ST; \
186
+						} else { \
187
+							/* error calling fixup => mark conv. parameter \
188
+							   and return error */ \
189
+							(dst)[1].u.number = i; \
190
+							ERR("runtime fixup failed for %s param %d\n", \
191
+									(cmd)->name, i+1); \
192
+							MODF_RVE_PARAM_FREE(cmd, src, dst); \
193
+							goto error; \
194
+						} \
195
+					} else if ((cmd)->fixup_flags & FIXUP_F_FPARAM_RVE) { \
196
+						if (likely( call_fixup((cmd)->fixup, \
197
+										&(dst)[i+2].u.data, i+1) >= 0)) { \
198
+							if ((dst)[i+2].u.data != s.s) \
199
+								(dst)[i+2].type = FPARAM_DYN_ST; \
200
+						} else { \
201
+							/* error calling fixup => mark conv. parameter \
202
+							   and return error */ \
203
+							(dst)[1].u.number = i; \
204
+							ERR("runtime fixup failed for %s param %d\n", \
205
+									(cmd)->name, i+1); \
206
+							MODF_RVE_PARAM_FREE(cmd, src, dst); \
207
+							goto error; \
208
+						}\
209
+					} \
210
+				} \
211
+			} else \
212
+				(dst)[i+2]=(src)[i+2]; \
213
+		} \
214
+	} while(0)
215
+
216
+
217
+
218
+/* call a module function with normal STRING_ST params.
219
+ * (used internally in do_action())
220
+ * @param f_type - cmd_function type
221
+ * @param h
222
+ * @param msg
223
+ * @param src - source action_u_t array (e.g. action->val)
224
+ * @param params... - variable list of parameters, passed to the module
225
+ *               function
226
+ * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), cmd,
227
+ *               might jump to error.
228
+ *
229
+ */
230
+#ifdef __SUNPRO_C
231
+#define MODF_CALL(f_type, h, msg, src, ...) \
232
+	do { \
233
+		cmd=(src)[0].u.data; \
234
+		ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
235
+		MODF_HANDLE_RETCODE(h, ret); \
236
+	} while (0)
237
+#else  /* ! __SUNPRO_C  (gcc, icc a.s.o) */
238
+#define MODF_CALL(f_type, h, msg, src, params...) \
239
+	do { \
240
+		cmd=(src)[0].u.data; \
241
+		ret=((f_type)cmd->function)((msg), ## params ); \
242
+		MODF_HANDLE_RETCODE(h, ret); \
243
+	} while (0)
244
+#endif /* __SUNPRO_C */
245
+
246
+
247
+
248
+/* call a module function with possible RVE params.
249
+ * (used internally in do_action())
250
+ * @param f_type - cmd_function type
251
+ * @param h
252
+ * @param msg
253
+ * @param src - source action_u_t array (e.g. action->val)
254
+ * @param dst - temporary action_u_t array used for conversions. It can be
255
+ *              used for the function parameters. It's contents it's not
256
+ *              valid after the call.
257
+ * @param params... - variable list of parameters, passed to the module
258
+ *               function
259
+ * Side-effects: sets ret, clobbers i (int), s (str), rv (rvalue*), f, dst,
260
+ *               might jump to error.
261
+ *
262
+ */
263
+#ifdef __SUNPRO_C
264
+#define MODF_RVE_CALL(f_type, h, msg, src, dst, ...) \
265
+	do { \
266
+		cmd=(src)[0].u.data; \
267
+		MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
268
+		ret=((f_type)cmd->function)((msg), __VAR_ARGS__); \
269
+		MODF_HANDLE_RETCODE(h, ret); \
270
+		/* free strings allocated by us or fixups */ \
271
+		MODF_RVE_PARAM_FREE(cmd, src, dst); \
272
+	} while (0)
273
+#else  /* ! __SUNPRO_C  (gcc, icc a.s.o) */
274
+#define MODF_RVE_CALL(f_type, h, msg, src, dst, params...) \
275
+	do { \
276
+		cmd=(src)[0].u.data; \
277
+		MODF_RVE_PARAM_CONVERT(h, msg, cmd, src, dst); \
278
+		ret=((f_type)cmd->function)((msg), ## params ); \
279
+		MODF_HANDLE_RETCODE(h, ret); \
280
+		/* free strings allocated by us or fixups */ \
281
+		MODF_RVE_PARAM_FREE(cmd, src, dst); \
282
+	} while (0)
283
+#endif /* __SUNPRO_C */
284
+
285
+
111 286
 /* ret= 0! if action -> end of list(e.g DROP),
112 287
       > 0 to continue processing next actions
113 288
    and <0 on error */
... ...
@@ -118,7 +293,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
118 293
 	struct dest_info dst;
119 294
 	char* tmp;
120 295
 	char *new_uri, *end, *crt;
121
-	void* f;
296
+	sr31_cmd_export_t* cmd;
122 297
 	int len;
123 298
 	int user;
124 299
 	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 310
 	struct rval_cache c1;
136 311
 	str s;
137 312
 	void *srevp[2];
313
+	/* temporary storage space for a struct action.val[] working copy
314
+	 (needed to transform RVE intro STRING before calling module
315
+	   functions). [0] is not used (corresp. to the module export pointer),
316
+	   [1] contains the number of params, and [2..] the param values.
317
+	   We need [1], because some fixup function use it
318
+	  (see fixup_get_param_count()).  */
319
+	static action_u_t mod_f_params[MAX_ACTIONS];
138 320
 
139 321
 	/* reset the value of error to E_UNSPEC so avoid unknowledgable
140 322
 	   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 1082
 										(struct action*)a->val[2].u.data, msg);
901 1083
 					}
902 1084
 			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
-			}
1085
+		case MODULE0_T:
1086
+			MODF_CALL(cmd_function, h, msg, a->val, 0, 0);
917 1087
 			break;
918 1088
 		/* instead of using the parameter number, we use different names
919 1089
 		 * for calls to functions with 3, 4, 5, 6 or variable number of
920 1090
 		 * parameters due to performance reasons */
1091
+		case MODULE1_T:
1092
+			MODF_CALL(cmd_function, h, msg, a->val,
1093
+										(char*)a->val[2].u.data,
1094
+										0
1095
+					);
1096
+			break;
1097
+		case MODULE2_T:
1098
+			MODF_CALL(cmd_function, h, msg, a->val,
1099
+										(char*)a->val[2].u.data,
1100
+										(char*)a->val[3].u.data
1101
+					);
1102
+			break;
921 1103
 		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,
1104
+			MODF_CALL(cmd_function3, h, msg, a->val,
925 1105
 										(char*)a->val[2].u.data,
926 1106
 										(char*)a->val[3].u.data,
927 1107
 										(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
-			}
1108
+					);
936 1109
 			break;
937 1110
 		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,
1111
+			MODF_CALL(cmd_function4, h, msg, a->val,
941 1112
 										(char*)a->val[2].u.data,
942 1113
 										(char*)a->val[3].u.data,
943 1114
 										(char*)a->val[4].u.data,
944 1115
 										(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
-			}
1116
+					);
953 1117
 			break;
954 1118
 		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,
1119
+			MODF_CALL(cmd_function5, h, msg, a->val,
958 1120
 										(char*)a->val[2].u.data,
959 1121
 										(char*)a->val[3].u.data,
960 1122
 										(char*)a->val[4].u.data,
961 1123
 										(char*)a->val[5].u.data,
962 1124
 										(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
-			}
1125
+					);
971 1126
 			break;
972 1127
 		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,
1128
+			MODF_CALL(cmd_function6, h, msg, a->val,
976 1129
 										(char*)a->val[2].u.data,
977 1130
 										(char*)a->val[3].u.data,
978 1131
 										(char*)a->val[4].u.data,
979 1132
 										(char*)a->val[5].u.data,
980 1133
 										(char*)a->val[6].u.data,
981 1134
 										(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
-			}
1135
+					);
990 1136
 			break;
991 1137
 		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
-			}
1138
+			MODF_CALL(cmd_function_var, h, msg, a->val,
1139
+							a->val[1].u.number, &a->val[2]);
1140
+			break;
1141
+		case MODULE1_RVE_T:
1142
+			MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params,
1143
+											(char*)mod_f_params[2].u.data,
1144
+											0
1145
+					);
1146
+			break;
1147
+		case MODULE2_RVE_T:
1148
+			MODF_RVE_CALL(cmd_function, h, msg, a->val, mod_f_params,
1149
+											(char*)mod_f_params[2].u.data,
1150
+											(char*)mod_f_params[3].u.data
1151
+					);
1152
+			break;
1153
+		case MODULE3_RVE_T:
1154
+			MODF_RVE_CALL(cmd_function3, h, msg, a->val, mod_f_params,
1155
+											(char*)mod_f_params[2].u.data,
1156
+											(char*)mod_f_params[3].u.data,
1157
+											(char*)mod_f_params[4].u.data
1158
+					);
1159
+			break;
1160
+		case MODULE4_RVE_T:
1161
+			MODF_RVE_CALL(cmd_function4, h, msg, a->val, mod_f_params,
1162
+											(char*)mod_f_params[2].u.data,
1163
+											(char*)mod_f_params[3].u.data,
1164
+											(char*)mod_f_params[4].u.data,
1165
+											(char*)mod_f_params[5].u.data
1166
+					);
1167
+			break;
1168
+		case MODULE5_RVE_T:
1169
+			MODF_RVE_CALL(cmd_function5, h, msg, a->val, mod_f_params,
1170
+											(char*)mod_f_params[2].u.data,
1171
+											(char*)mod_f_params[3].u.data,
1172
+											(char*)mod_f_params[4].u.data,
1173
+											(char*)mod_f_params[5].u.data,
1174
+											(char*)mod_f_params[6].u.data
1175
+					);
1176
+			break;
1177
+		case MODULE6_RVE_T:
1178
+			MODF_RVE_CALL(cmd_function6, h, msg, a->val, mod_f_params,
1179
+											(char*)mod_f_params[2].u.data,
1180
+											(char*)mod_f_params[3].u.data,
1181
+											(char*)mod_f_params[4].u.data,
1182
+											(char*)mod_f_params[5].u.data,
1183
+											(char*)mod_f_params[6].u.data,
1184
+											(char*)mod_f_params[7].u.data
1185
+					);
1186
+			break;
1187
+		case MODULEX_RVE_T:
1188
+			MODF_RVE_CALL(cmd_function_var, h, msg, a->val, mod_f_params,
1189
+							a->val[1].u.number, &mod_f_params[2]);
1005 1190
 			break;
1006 1191
 		case EVAL_T:
1007 1192
 			/* only eval the expression to account for possible
... ...
@@ -1357,11 +1542,8 @@ end:
1357 1542
 	/* process module onbreak handlers if present */
1358 1543
 	if (unlikely(h->rec_lev==0 && ret==0))
1359 1544
 		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);
1545
+			if (unlikely(mod->exports.onbreak_f)) {
1546
+				mod->exports.onbreak_f( msg );
1365 1547
 			}
1366 1548
 	return ret;
1367 1549
 
... ...
@@ -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 2234
 				case RESETFLAG_T:
2233 2235
 				case ISFLAGSET_T:
2234 2236
 				case IF_T:
2235
-				case MODULE_T:
2237
+				case MODULE0_T:
2238
+				case MODULE1_T:
2239
+				case MODULE2_T:
2240
+				case MODULE3_T:
2241
+				case MODULE4_T:
2242
+				case MODULE5_T:
2243
+				case MODULE6_T:
2244
+				case MODULEX_T:
2236 2245
 				case SET_FWD_NO_CONNECT_T:
2237 2246
 				case SET_RPL_NO_CONNECT_T:
2238 2247
 				case SET_FWD_CLOSE_T:
... ...
@@ -2705,7 +2714,7 @@ rval: intno			{$$=mk_rve_rval(RV_INT, (void*)$1); }
2705 2714
 
2706 2715
 
2707 2716
 rve_un_op: NOT	{ $$=RVE_LNOT_OP; }
2708
-		|  MINUS %prec UNARY	{ $$=RVE_UMINUS_OP; } 
2717
+		|  MINUS %prec UNARY	{ $$=RVE_UMINUS_OP; }
2709 2718
 		/* TODO: RVE_BOOL_OP, RVE_NOT_OP? */
2710 2719
 	;
2711 2720
 
... ...
@@ -3221,9 +3230,9 @@ cmd:
3221 3230
 	| SET_RPL_CLOSE	{
3222 3231
 		$$=mk_action(SET_RPL_CLOSE_T, 0); set_cfg_pos($$);
3223 3232
 	}
3224
-	| ID {mod_func_action = mk_action(MODULE_T, 2, MODEXP_ST, NULL, NUMBER_ST,
3233
+	| ID {mod_func_action = mk_action(MODULE0_T, 2, MODEXP_ST, NULL, NUMBER_ST,
3225 3234
 			0); } LPAREN func_params RPAREN	{
3226
-		mod_func_action->val[0].u.data = 
3235
+		mod_func_action->val[0].u.data =
3227 3236
 			find_export_record($1, mod_func_action->val[1].u.number, rt,
3228 3237
 								&u_tmp);
3229 3238
 		if (mod_func_action->val[0].u.data == 0) {
... ...
@@ -3233,34 +3242,14 @@ cmd:
3233 3242
 			} else {
3234 3243
 				yyerror("unknown command, missing loadmodule?\n");
3235 3244
 			}
3236
-			pkg_free(mod_func_action);
3245
+			free_mod_func_action(mod_func_action);
3237 3246
 			mod_func_action=0;
3238 3247
 		}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;
3248
+			if (mod_func_action && mod_f_params_pre_fixup(mod_func_action)<0) {
3249
+				/* error messages are printed inside the function */
3250
+				free_mod_func_action(mod_func_action);
3251
+				mod_func_action = 0;
3252
+				YYERROR;
3264 3253
 			}
3265 3254
 		}
3266 3255
 		$$ = mod_func_action;
... ...
@@ -3272,27 +3261,20 @@ func_params:
3272 3261
 	/* empty */
3273 3262
 	| func_params COMMA func_param { }
3274 3263
 	| func_param {}
3275
-	| func_params error { yyerror("call params error\n"); }
3276 3264
 	;
3277 3265
 func_param:
3278
-        intno {
3279
-		if (mod_func_action->val[1].u.number < MAX_ACTIONS-2) {
3266
+	rval_expr {
3267
+		if ($1 && mod_func_action->val[1].u.number < MAX_ACTIONS-2) {
3280 3268
 			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 =
3269
+				RVE_ST;
3270
+			mod_func_action->val[mod_func_action->val[1].u.number+2].u.data =
3283 3271
 				$1;
3284 3272
 			mod_func_action->val[1].u.number++;
3285
-		} else {
3273
+		} else if ($1) {
3286 3274
 			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++;
3275
+			YYERROR;
3294 3276
 		} else {
3295
-			yyerror("Too many arguments\n");
3277
+			YYERROR;
3296 3278
 		}
3297 3279
 	}
3298 3280
 	;
... ...
@@ -3735,6 +3717,125 @@ static int case_check_default(struct case_stms* stms)
3735 3717
 
3736 3718
 
3737 3719
 
3720
+/** fixes the parameters and the type of a module function call.
3721
+ * It is done here instead of fix action, to have quicker feedback
3722
+ * on error cases (e.g. passing a non constant to a function with a 
3723
+ * declared fixup) 
3724
+ * The rest of the fixup is done inside do_action().
3725
+ * @param a - filled module function call (MODULE*_T) action structure
3726
+ *            complete with parameters, starting at val[2] and parameter
3727
+ *            number at val[1].
3728
+ * @return 0 on success, -1 on error (it will also print the error msg.).
3729
+ *
3730
+ */
3731
+static int mod_f_params_pre_fixup(struct action* a)
3732
+{
3733
+	sr31_cmd_export_t* cmd_exp;
3734
+	action_u_t* params;
3735
+	int param_no;
3736
+	struct rval_expr* rve;
3737
+	struct rvalue* rv;
3738
+	int r;
3739
+	str s;
3740
+	
3741
+	cmd_exp = a->val[0].u.data;
3742
+	param_no = a->val[1].u.number;
3743
+	params = &a->val[2];
3744
+	
3745
+	switch(cmd_exp->param_no) {
3746
+		case 0:
3747
+			a->type = MODULE0_T;
3748
+			break;
3749
+		case 1:
3750
+			a->type = MODULE1_T;
3751
+			break;
3752
+		case 2:
3753
+			a->type = MODULE2_T;
3754
+			break;
3755
+		case 3:
3756
+			a->type = MODULE3_T;
3757
+			break;
3758
+		case 4:
3759
+			a->type = MODULE4_T;
3760
+			break;
3761
+		case 5:
3762
+			a->type = MODULE5_T;
3763
+			break;
3764
+		case 6:
3765
+			a->type = MODULE6_T;
3766
+			break;
3767
+		case VAR_PARAM_NO:
3768
+			a->type = MODULEX_T;
3769
+			break;
3770
+		default:
3771
+			yyerror("function %s: bad definition"
3772
+					" (invalid number of parameters)", cmd_exp->name);
3773
+			return -1;
3774
+	}
3775
+	
3776
+	if ( cmd_exp->fixup) {
3777
+		if (is_fparam_rve_fixup(cmd_exp->fixup))
3778
+			/* mark known fparam rve safe fixups */
3779
+			cmd_exp->fixup_flags  |= FIXUP_F_FPARAM_RVE;
3780
+		else if (!(cmd_exp->fixup_flags & FIXUP_F_FPARAM_RVE) &&
3781
+				 cmd_exp->free_fixup == 0) {
3782
+			/* v0 or v1 functions that have fixups and no coresp. fixup_free
3783
+			   functions, need constant, string params.*/
3784
+			for (r=0; r < param_no; r++) {
3785
+				rve=params[r].u.data;
3786
+				if (!rve_is_constant(rve)) {
3787
+					yyerror_at(&rve->fpos, "function %s: parameter %d is not"
3788
+								" constant\n", cmd_exp->name, r+1);
3789
+					return -1;
3790
+				}
3791
+				if ((rv = rval_expr_eval(0, 0, rve)) == 0 ||
3792
+						rval_get_str(0, 0, &s, rv, 0) < 0 ) {
3793
+					/* out of mem or bug ? */
3794
+					rval_destroy(rv);
3795
+					yyerror_at(&rve->fpos, "function %s: bad parameter %d"
3796
+									" expression\n", cmd_exp->name, r+1);
3797
+					return -1;
3798
+				}
3799
+				rval_destroy(rv);
3800
+				rve_destroy(rve);
3801
+				params[r].type = STRING_ST; /* asciiz */
3802
+				params[r].u.string = s.s;
3803
+				params[r].u.str.len = s.len; /* not used right now */
3804
+			}
3805
+		}
3806
+	}/* else
3807
+		if no fixups are present, the RVEs can be transformed
3808
+		into strings at runtime, allowing seamless var. use
3809
+		even with old functions.
3810
+		Further optimizations -> in fix_actions()
3811
+		*/
3812
+	return 0;
3813
+}
3814
+
3815
+
3816
+
3817
+/** frees a filled module function call action structure.
3818
+ * @param a - filled module function call action structure
3819
+ *            complete with parameters, starting at val[2] and parameter
3820
+ *            number at val[1].
3821
+ */
3822
+static void free_mod_func_action(struct action* a)
3823
+{
3824
+	action_u_t* params;
3825
+	int param_no;
3826
+	int r;
3827
+	
3828
+	param_no = a->val[1].u.number;
3829
+	params = &a->val[2];
3830
+	
3831
+	for (r=0; r < param_no; r++)
3832
+		if (params[r].u.data)
3833
+			rve_destroy(params[r].u.data);
3834
+	pkg_free(a);
3835
+}
3836
+
3837
+
3838
+
3738 3839
 /*
3739 3840
 int main(int argc, char ** argv)
3740 3841
 {
... ...
@@ -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 51
 	{ \
51 52
 		if ((param_no > (maxp)) || (param_no < (minp))) \
52 53
 			return E_UNSPEC; \
53
-		if (*param){ \
54
-			fparam_free_contents((fparam_t*)*param); \
55
-			pkg_free(*param); \
56
-			*param=0; \
57
-		} \
54
+		if (*param) \
55
+			fparam_free_restore(param); \
58 56
 		return 0; \
59 57
 	}
60 58
 
... ...
@@ -149,7 +147,7 @@ int fixup_regexpNL_none(void** param, int param_no); /* textops */
149 147
 		int ret; \
150 148
 		if (param && *param){ \
151 149
 			p=(param_no>(no1))? *param - (long)&((fparam_t*)0)->v : *param;\
152
-			if ((ret=fixup_free_fpt_##suffix(&p, param_no))==0) *param=0; \
150
+			if ((ret=fixup_free_fpt_##suffix(&p, param_no))==0) *param=p; \
153 151
 			return ret; \
154 152
 		} \
155 153
 		return 0; \
... ...
@@ -168,24 +166,288 @@ int fixup_regexpNL_none(void** param, int param_no); /* textops */
168 166
 
169 167
 FIXUP_F1T(str_null, 1, 1, FPARAM_STR)
170 168
 FIXUP_F1T(str_str, 1, 2,  FPARAM_STR)
169
+FIXUP_F1T(str_all, 1, 100,  FPARAM_STR)
171 170
 
172
-/* TODO: int can be converted in place, no need for pkg_malloc'ed fparam_t*/
171
+/*
172
+  no free fixups possible for unit_*
173
+  (they overwrite the pointer with the converted number => the original
174
+   value cannot be recovered)
173 175
 FIXUP_F1T(uint_null, 1, 1, FPARAM_INT)
174 176
 FIXUP_F1T(uint_uint, 1, 2, FPARAM_INT)
177
+*/
178
+
179
+
180
+
181
+int fixup_uint_uint(void** param, int param_no)
182
+{
183
+	str s;
184
+	unsigned int num;
185
+	
186
+	s.s = *param;
187
+	s.len = strlen(s.s);
188
+	if (likely(str2int(&s, &num) == 0)) {
189
+		*param = (void*)(long)num;
190
+	} else
191
+		/* not a number */
192
+		return E_UNSPEC;
193
+	return 0;
194
+}
195
+
196
+
197
+
198
+int fixup_uint_null(void** param, int param_no)
199
+{
200
+	if (param_no == 1)
201
+		return fixup_uint_uint(param, param_no);
202
+	return E_UNSPEC;
203
+}
204
+
175 205
 
206
+/* fixup_regexp_null() has to be written "by hand", since
207
+   it needs to save the original pointer (the fixup users expects
208
+   a pointer to the regex in *param and hence the original value
209
+   needed on free cannot be recovered directly).
176 210
 FIXUP_F1T(regexp_null, 1, 1, FPARAM_REGEX)
211
+*/
177 212
 
213
+struct regex_fixup {
214
+	regex_t regex; /* compiled regex */
215
+	void* orig;    /* original pointer */
216
+};
217
+
218
+int fixup_regexp_null(void** param, int param_no)
219
+{
220
+	struct regex_fixup* re;
221
+	
222
+	if (param_no != 1)
223
+		return E_UNSPEC;
224
+	if ((re=pkg_malloc(sizeof(*re))) ==0) {
225
+		ERR("No memory left\n");
226
+		goto error;
227
+	}
228
+	if (regcomp(&re->regex, *param,
229
+				REG_EXTENDED|REG_ICASE|REG_NEWLINE))
230
+		goto error;
231
+	re->orig = *param;
232
+	*param = re;
233
+	return 0;
234
+error:
235
+	if (re)
236
+		pkg_free(re);
237
+	return E_UNSPEC;
238
+}
239
+
240
+
241
+int fixup_free_regexp_null(void** param, int param_no)
242
+{
243
+	struct regex_fixup* re;
244
+	
245
+	if (param_no != 1)
246
+		return E_UNSPEC;
247
+	if (*param) {
248
+		re = *param;
249
+		*param = re->orig;
250
+		regfree(&re->regex);
251
+		pkg_free(re);
252
+	}
253
+	return 0;
254
+}
255
+
256
+/* fixup_pvar_*() has to be written "by hand", since
257
+   it needs to save the original pointer (the fixup users expects
258
+   a pointer to the pv_spec_t in *param and hence the original value
259
+   needed on free cannot be recovered directly).
178 260
 FIXUP_F1T(pvar_null, 1, 1, FPARAM_PVS)
179 261
 FIXUP_F1T(pvar_pvar, 1, 2, FPARAM_PVS)
262
+*/
263
+
264
+struct pvs_fixup {
265
+	pv_spec_t pvs; /* parsed pv spec */
266
+	void* orig;    /* original pointer */
267
+};
268
+
269
+int fixup_pvar_all(void** param, int param_no)
270
+{
271
+	struct pvs_fixup* pvs_f;
272
+	str name;
273
+	
274
+	pvs_f = 0;
275
+	name.s = *param;
276
+	name.len = strlen(name.s);
277
+	trim(&name);
278
+	if (name.len == 0 || name.s[0] != '$')
279
+		/* not a pvs id */
280
+		goto error;
281
+	if ((pvs_f=pkg_malloc(sizeof(*pvs_f))) == 0) {
282
+		ERR("No memory left\n");
283
+		goto error;
284
+	}
285
+	if (pv_parse_spec2(&name, &pvs_f->pvs, 1) == 0)
286
+		/* not a valid pvs identifier */
287
+		goto error;
288
+	pvs_f->orig = *param;
289
+	*param = pvs_f;
290
+	return 0;
291
+error:
292
+	if (pvs_f)
293
+		pkg_free(pvs_f);
294
+	return E_UNSPEC;
295
+}
296
+
297
+
298
+
299
+int fixup_free_pvar_all(void** param, int param_no)
300
+{
301
+	struct pvs_fixup* pvs_f;
302
+	
303
+	if (*param) {
304
+		pvs_f = *param;
305
+		*param = pvs_f->orig;
306
+		/* free only the contents (don't attempt to free &pvs_f->pvs)*/
307
+		pv_spec_destroy(&pvs_f->pvs);
308
+		/* free the whole pvs_fixup */
309
+		pkg_free(pvs_f);
310
+	}
311
+	return 0;
312
+}
313
+
314
+
315
+
316
+int fixup_pvar_pvar(void** param, int param_no)
317
+{
318
+	if (param_no > 2)
319
+		return E_UNSPEC;
320
+	return fixup_free_pvar_all(param, param_no);
321
+}
322
+
323
+
324
+
325
+int fixup_free_pvar_pvar(void** param, int param_no)
326
+{
327
+	if (param_no > 2)
328
+		return E_UNSPEC;
329
+	return fixup_free_pvar_all(param, param_no);
330
+}
331
+
332
+
333
+
334
+int fixup_pvar_null(void** param, int param_no)
335
+{
336
+	if (param_no != 1)
337
+		return E_UNSPEC;
338
+	return fixup_pvar_all(param, param_no);
339
+}
340
+
180 341
 
342
+
343
+int fixup_free_pvar_null(void** param, int param_no)
344
+{
345
+	if (param_no != 1)
346
+		return E_UNSPEC;
347
+	return fixup_free_pvar_all(param, param_no);
348
+}
349
+
350
+/* must be written "by hand", see above (fixup_pvar_pvar).
181 351
 FIXUP_F2T(pvar_str, 1, 2, 1, FPARAM_PVS, FPARAM_STR)
182 352
 FIXUP_F2T(pvar_str_str, 1, 3, 1, FPARAM_PVS, FPARAM_STR)
353
+*/
354
+
355
+int fixup_pvar_str(void** param, int param_no)
356
+{
357
+	if (param_no == 1)
358
+		return fixup_pvar_all(param, param_no);
359
+	else if (param_no == 2)
360
+		return fixup_str_str(param, param_no);
361
+	return E_UNSPEC;
362
+}
363
+
364
+
365
+
366
+int fixup_free_pvar_str(void** param, int param_no)
367
+{
368
+	if (param_no == 1)
369
+		return fixup_free_pvar_all(param, param_no);
370
+	else if (param_no == 2)
371
+		return fixup_free_str_str(param, param_no);
372
+	return E_UNSPEC;
373
+}
374
+
375
+
376
+
377
+int fixup_pvar_str_str(void** param, int param_no)
378
+{
379
+	if (param_no == 1)
380
+		return fixup_pvar_all(param, param_no);
381
+	else if (param_no == 2 || param_no == 3)
382
+		return fixup_str_all(param, param_no);
383
+	return E_UNSPEC;
384
+}
385
+
386
+
387
+
388
+int fixup_free_pvar_str_str(void** param, int param_no)
389
+{
390
+	if (param_no == 1)
391
+		return fixup_free_pvar_all(param, param_no);
392
+	else if (param_no == 2 || param_no == 3)
393
+		return fixup_free_str_all(param, param_no);
394
+	return E_UNSPEC;
395
+}
396
+
397
+
183 398
 
184 399
 FIXUP_F2FP(igp_null, 1, 1, 1, FPARAM_INT|FPARAM_PVS, 0)
185 400
 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 401
 
402
+/* must be declared by hand, because of the pvar special handling
403
+   (see above)
404
+FIXUP_F2FP(igp_pvar, 1, 2, 1,  FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
188 405
 FIXUP_F2FP_T(igp_pvar_pvar, 1, 3, 1, FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
406
+*/
407
+
408
+int fixup_igp_pvar(void** param, int param_no)
409
+{
410
+	if (param_no == 1)
411
+		return fixup_igp_null(param, param_no);
412
+	else if (param_no == 2)
413
+		return fixup_pvar_all(param, param_no);
414
+	return E_UNSPEC;
415
+}
416
+
417
+
418
+
419
+int fixup_free_igp_pvar(void** param, int param_no)
420
+{
421
+	if (param_no == 1)
422
+		return fixup_free_igp_null(param, param_no);
423
+	else if (param_no == 2)
424
+		return fixup_free_pvar_all(param, param_no);
425
+	return E_UNSPEC;
426
+}
427
+
428
+
429
+
430
+int fixup_igp_pvar_pvar(void** param, int param_no)
431
+{
432
+	if (param_no == 1)
433
+		return fixup_igp_null(param, param_no);
434
+	else if (param_no == 2 || param_no == 3)
435
+		return fixup_pvar_all(param, param_no);
436
+	return E_UNSPEC;
437
+}
438
+
439
+
440
+
441
+int fixup_free_igp_pvar_pvar(void** param, int param_no)
442
+{
443
+	if (param_no == 1)
444
+		return fixup_free_igp_null(param, param_no);
445
+	else if (param_no == 2 || param_no == 3)
446
+		return fixup_free_pvar_all(param, param_no);
447
+	return E_UNSPEC;
448
+}
449
+
450
+
189 451
 
190 452
 /** macro for declaring a spve fixup and the corresponding free_fixup
191 453
   * 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 464
 	int fixup_##suffix (void** param, int param_no) \
203 465
 	{ \
204 466
 		int ret; \
205
-		char * bkp; \
206 467
 		fparam_t* fp; \
207 468
 		if (param_no<=(no1)){ \
208 469
 			if ((ret=fix_param_types(FPARAM_PVE, param))<0){ \
209
-				ERR("Cannot convert function parameter %d to" #type2 "\n", \
470
+				ERR("Cannot convert function parameter %d to spve \n", \
210 471
 						param_no);\
211 472
 				return E_UNSPEC; \
212 473
 			} else{ \
213 474
 				fp=(fparam_t*)*param; \
214 475
 				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; \
476
+					fparam_free_restore(param); \
220 477
 					return fix_param_types(FPARAM_STR, param); \
221 478
 				} else if (ret==1) \
222 479
 					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 485
 	int fixup_free_##suffix (void** param, int param_no) \
229 486
 	{ \
230 487
 		if (param && *param){ \
231
-			if (param_no<=(no1)){ \
232
-				fparam_free_contents((fparam_t*)*param); \
233
-				pkg_free(*param); \
234
-				*param=0; \
235
-			} else \
488
+			if (param_no<=(no1)) \
489
+				fparam_free_restore(param); \
490
+			else \
236 491
 				return fixup_free_spvet_##suffix(param, param_no); \
237 492
 		} \
238 493
 		return 0; \
... ...
@@ -244,3 +499,33 @@ FIXUP_F_SPVE_T(spve_spve, 1, 2, 2, 0)
244 499
 FIXUP_F_SPVE_T(spve_uint, 1, 2, 1, FPARAM_INT)
245 500
 FIXUP_F_SPVE_T(spve_str, 1, 2, 1, FPARAM_STR)
246 501
 FIXUP_F_SPVE_T(spve_null, 1, 1, 1, 0)
502
+
503
+/** get the corresp. fixup_free* function.
504
+ * @param f -fixup function pointer.
505
+ * @return  - pointer to free_fixup function if known, 0 otherwise.
506
+ */
507
+free_fixup_function mod_fix_get_fixup_free(fixup_function f)
508
+{
509
+	if (f == fixup_str_null) return fixup_free_str_null;
510
+	if (f == fixup_str_str) return fixup_free_str_str;
511
+	/* no free fixup for fixup_uint_* (they overwrite the pointer
512
+	   value with a number and the original value cannot be recovered) */
513
+	if (f == fixup_uint_null) return 0;
514
+	if (f == fixup_uint_uint) return 0;
515
+	if (f == fixup_regexp_null) return fixup_free_regexp_null;
516
+	if (f == fixup_pvar_null) return fixup_free_pvar_null;
517
+	if (f == fixup_pvar_pvar) return fixup_free_pvar_pvar;
518
+	if (f == fixup_pvar_str) return fixup_free_pvar_str;
519
+	if (f == fixup_pvar_str_str) return fixup_free_pvar_str_str;
520
+	if (f == fixup_igp_igp) return fixup_free_igp_igp;
521
+	if (f == fixup_igp_null) return fixup_free_igp_null;
522
+	if (f == fixup_igp_pvar) return fixup_free_igp_pvar;
523
+	if (f == fixup_igp_pvar_pvar) return fixup_free_igp_pvar_pvar;
524
+	if (f == fixup_spve_spve) return fixup_free_spve_spve;
525
+	if (f == fixup_spve_null) return fixup_free_spve_null;
526
+	/* no free fixup, because of the uint part (the uint cannot be freed,
527
+	   see above fixup_uint_null) */
528
+	if (f == fixup_spve_uint) return 0;
529
+	if (f == fixup_spve_str) return fixup_free_spve_str;
530
+	return 0;
531
+}
... ...
@@ -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 118
 int fixup_free_igp_pvar_pvar(void** param, int param_no);
117 119
 
118 120
 int fixup_spve_spve(void** param, int param_no);
121
+int fixup_free_spve_spve(void** param, int param_no);
119 122
 int fixup_spve_null(void** param, int param_no);
123
+int fixup_free_spve_null(void** param, int param_no);
120 124
 int fixup_spve_uint(void** param, int param_no);
121 125
 int fixup_spve_str(void** param, int param_no);
126
+int fixup_free_spve_str(void** param, int param_no);
127
+
128
+
129
+/** get the corresp. free fixup function.*/
130
+free_fixup_function mod_fix_get_fixup_free(fixup_function f);
122 131
 
123 132
 #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 64
 	{"print", print_f_0, 0, 0, REQUEST_ROUTE},   // overload test
61 65
 	{"print", print_f_1, 1, print_fixup_f_1, REQUEST_ROUTE},
62 66
 	{"print", print_f_2, 2, print_fixup_f_2, REQUEST_ROUTE},
67
+	{"print1", print_f1, 1, 0, REQUEST_ROUTE},
68
+	{"print2", print_f2, 2, fixup_var_str_12, REQUEST_ROUTE},
69
+	{"print3", (cmd_function)print_f3, 3, 0, REQUEST_ROUTE},
70
+	{"printv", (cmd_function)print_f_var, VAR_PARAM_NO, 0, REQUEST_ROUTE},
63 71
 	{0, 0, 0, 0, 0}
64 72
 };
65 73
 
... ...
@@ -90,6 +98,7 @@ static int mod_init(void)
90 98
 	DBG("print: string_param = '%s'\n", string_param);
91 99
 	DBG("print: str_param = '%.*s'\n", str_param.len, str_param.s);
92 100
 	DBG("print: int_param = %d\n", int_param);
101
+	WARN("this is an example module, it has no practical use\n");
93 102
 	return 0;
94 103
 }
95 104
 
... ...
@@ -132,3 +141,45 @@ static int print_fixup_f_2(void **param, int param_no) {
132 141
 	DBG("print: print_fixup_f_2('%s')\n", (char*)*param);
133 142
 	return print_fixup_f(param, param_no);
134 143
 }
144
+
145
+
146
+
147
+/* 1 parameter, no fixup version */
148
+static int print_f1(struct sip_msg* msg, char* s1, char* not_used)
149
+{
150
+	printf("%s\n", s1);
151
+	return 1;
152
+}
153
+
154
+
155
+/* 2 parameters, fparam fixup version */
156
+static int print_f2(struct sip_msg* msg, char* s1, char* s2)
157
+{
158
+	str a, b;
159
+	if (get_str_fparam(&a, msg, (fparam_t*)s1) !=0 ||
160
+		 get_str_fparam(&b, msg, (fparam_t*)s2) !=0) {
161
+		BUG("get_str_fparam failed\n");
162
+		return -1;
163
+	}
164
+	printf("%.*s%.*s\n", a.len, a.s, b.len, b.s);
165
+	return 1;
166
+}
167
+
168
+
169
+/* 3 parameters, no fixup version */
170
+static int print_f3(struct sip_msg* msg, char* s1, char* s2, char* s3)
171
+{
172
+	printf("%s%s%s\n", s1, s2, s3);
173
+	return 1;
174
+}
175
+
176
+
177
+/* variable number of parameters, no fixup version */
178
+static int print_f_var(struct sip_msg* msg, int argc, action_u_t argv[])
179
+{
180
+	int i;
181
+	for (i = 0; i < argc; i++)
182
+		printf("%s", argv[i].u.string);
183
+	printf("\n");
184
+	return 1;
185
+}
... ...
@@ -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 1161
 		tr_free((trans_t*)spec->trans);
1161 1162
 }
1162 1163
 
1163
-/**
1164
- * free the pv_spec_t structure
1164
+/** free the pv_spec_t structure.
1165 1165
  */
1166 1166
 void pv_spec_free(pv_spec_t *spec)
1167 1167
 {
... ...
@@ -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 636
 	struct action *t;
635 637
 	struct proxy_l* p;
636 638
 	char *tmp;
639
+	void *tmp_p;
637 640
 	int ret;
638 641
 	int i;
639
-	union cmd_export_u* cmd;
642
+	sr31_cmd_export_t* cmd;
640 643
 	str s;
641 644
 	struct hostent* he;
642 645
 	struct ip_addr ip;
... ...
@@ -644,11 +647,9 @@ int fix_actions(struct action* a)
644 647
 	struct lvalue* lval;
645 648
 	struct rval_expr* rve;
646 649
 	struct rval_expr* err_rve;
647
-	struct rvalue* rv;
648 650
 	enum rval_type rve_type, err_type, expected_type;
649
-
650
-	
651
-	char buf[30]; /* tmp buffer needed for module param fixups */
651
+	struct rvalue* rv;
652
+	int rve_param_no;
652 653
 
653 654
 	if (a==0){
654 655
 		LOG(L_CRIT,"BUG: fix_actions: null pointer\n");
... ...
@@ -913,47 +914,119 @@ int fix_actions(struct action* a)
913 914
 					goto error;
914 915
 				break;
915 916
 
916
-			case MODULE_T:
917
+			case MODULE0_T:
918
+			case MODULE1_T:
919
+			case MODULE2_T:
917 920
 			case MODULE3_T:
918 921
 			case MODULE4_T:
919 922
 			case MODULE5_T:
920 923
 			case MODULE6_T:
921 924
 			case MODULEX_T:
922 925
 				cmd = t->val[0].u.data;
923
-				if (cmd && cmd->c.fixup) {
924
-					DBG("fixing %s()\n", cmd->c.name);
926
+				rve_param_no = 0;
927
+				if (cmd) {
928
+					DBG("fixing %s()\n", cmd->name);
925 929
 					if (t->val[1].u.number==0) {
926
-						ret = cmd->c.fixup(0, 0);
930
+						ret = call_fixup(cmd->fixup, 0, 0);
927 931
 						if (ret < 0)
928 932
 							goto error;
929 933
 					}
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;
934
+					for (i=0; i < t->val[1].u.number; i++) {
935
+						if (t->val[i+2].type == RVE_ST) {
936
+							rve = t->val[i+2].u.data;
937
+							if (rve_is_constant(rve)) {
938
+								/* if expression is constant => evaluate it
939
+								   as string and replace it with the corresp.
940
+								   string */
941
+								rv = rval_expr_eval(0, 0, rve);
942
+								if (rv == 0 ||
943
+										rval_get_str( 0, 0, &s, rv, 0) < 0 ) {
944
+									ERR("failed to fix constant rve");
945
+									if (rv) rval_destroy(rv);
946
+									ret = E_BUG;
947
+									goto error;
948