/src/kamailio/src/core/rvalue.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2008 iptelorg GmbH |
3 | | * |
4 | | * Permission to use, copy, modify, and distribute this software for any |
5 | | * purpose with or without fee is hereby granted, provided that the above |
6 | | * copyright notice and this permission notice appear in all copies. |
7 | | * |
8 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | | */ |
16 | | |
17 | | /** |
18 | | * @file |
19 | | * @brief Kamailio core :: rvalue expressions |
20 | | * @ingroup core |
21 | | * Module: \ref core |
22 | | */ |
23 | | |
24 | | /** special defines: |
25 | | * |
26 | | * UNDEF_EQ_* - how to behave when undef is on the right side of a generic |
27 | | * compare operator |
28 | | * UNDEF_EQ_ALWAYS_FALSE: undef == something is always false |
29 | | * UNDEF_EQ_UNDEF_TRUE : undef == something false except for undef==undef |
30 | | * which is true |
31 | | * no UNDEF_EQ* define : undef == expr => convert undef to typeof(expr) |
32 | | * and perform normal ==. undef == undef will be |
33 | | * converted to string and it will be true |
34 | | * ("" == "") |
35 | | * NOTE: expr == undef, with defined(expr) is always evaluated this way: |
36 | | * expr == (type_of(expr))undef |
37 | | * RV_STR2INT_VERBOSE_ERR - if a string conversion to int fails, log (L_WARN) |
38 | | * the string that caused it (only the string, not |
39 | | * the expression position). |
40 | | * RV_STR2INT_ERR - if a string conversion to int fails, don't ignore |
41 | | * the error (return error). |
42 | | * RVAL_GET_INT_ERR_WARN - if a conversion to int fails, log a warning with |
43 | | * the expression position. |
44 | | * Depends on RV_STR2INT_ERR. |
45 | | * RVAL_GET_INT_ERR_IGN - if a conversion to int fails, ignore the error |
46 | | * (the result will be 0). Can be combined with |
47 | | * RVAL_GET_INT_ERR_WARN. |
48 | | * Depends on RV_STR2INT_ERR. |
49 | | */ |
50 | | |
51 | | |
52 | | #include "rvalue.h" |
53 | | |
54 | | #include <stdlib.h> /* abort() */ |
55 | | |
56 | | /* if defined warn when str2int conversions fail */ |
57 | | #define RV_STR2INT_VERBOSE_ERR |
58 | | |
59 | | /* if defined rval_get_int will fail if str2int conversion fail |
60 | | * (else convert to 0) */ |
61 | | #define RV_STR2INT_ERR |
62 | | |
63 | | /* if a rval_get_int fails (conversion to int), warn |
64 | | * Depends on RV_STR2INT_ERR. |
65 | | */ |
66 | | #define RVAL_GET_INT_ERR_WARN |
67 | | |
68 | | /* if a rval_get_int fails, ignore it (expression evaluation will not fail, |
69 | | * the int conversion will result in 0). |
70 | | * Can be combined with RVAL_GET_INT_ERR_WARN. |
71 | | * Depends on RV_STR2INT_ERR. |
72 | | */ |
73 | | #define RVAL_GET_INT_ERR_IGN |
74 | | |
75 | | /* minimum size alloc'ed for STR RVs (to accommodate |
76 | | * strops without reallocs) */ |
77 | 0 | #define RV_STR_EXTRA 80 |
78 | | |
79 | 0 | #define rv_ref(rv) ((rv)->refcnt++) |
80 | | |
81 | | /** unref rv and returns true if 0 */ |
82 | 0 | #define rv_unref(rv) ((--(rv)->refcnt) == 0) |
83 | | |
84 | | |
85 | | /* control return code evaluation mode */ |
86 | | int ksr_return_mode = 0; |
87 | | |
88 | | inline static void rval_force_clean(struct rvalue *rv) |
89 | 0 | { |
90 | 0 | if(rv->flags & RV_CNT_ALLOCED_F) { |
91 | 0 | switch(rv->type) { |
92 | 0 | case RV_STR: |
93 | 0 | pkg_free(rv->v.s.s); |
94 | 0 | rv->v.s.s = 0; |
95 | 0 | rv->v.s.len = 0; |
96 | 0 | break; |
97 | 0 | default: |
98 | 0 | LM_BUG("RV_CNT_ALLOCED_F not supported for type %d\n", |
99 | 0 | rv->type); |
100 | 0 | } |
101 | 0 | rv->flags &= ~RV_CNT_ALLOCED_F; |
102 | 0 | } |
103 | 0 | if(rv->flags & RV_RE_ALLOCED_F) { |
104 | 0 | if(rv->v.re.regex) { |
105 | 0 | if(unlikely(rv->type != RV_STR || !(rv->flags & RV_RE_F))) { |
106 | 0 | LM_BUG("RV_RE_ALLOCED_F not supported for type %d or " |
107 | 0 | "bad flags %x\n", |
108 | 0 | rv->type, rv->flags); |
109 | 0 | } |
110 | 0 | regfree(rv->v.re.regex); |
111 | 0 | pkg_free(rv->v.re.regex); |
112 | 0 | rv->v.re.regex = 0; |
113 | 0 | } |
114 | 0 | rv->flags &= ~(RV_RE_ALLOCED_F | RV_RE_F); |
115 | 0 | } |
116 | 0 | } |
117 | | |
118 | | |
119 | | static inline void rval_destroy_helper(struct rvalue *rv, int allocated) |
120 | 0 | { |
121 | 0 | if(rv && rv_unref(rv)) { |
122 | 0 | rval_force_clean(rv); |
123 | | /* still an un-regfreed RE ? */ |
124 | 0 | if((rv->flags & RV_RE_F) && rv->v.re.regex) { |
125 | 0 | if(unlikely(rv->type != RV_STR)) |
126 | 0 | LM_BUG("RV_RE_F not supported for type %d\n", rv->type); |
127 | 0 | regfree(rv->v.re.regex); |
128 | 0 | } |
129 | 0 | if(rv->flags & RV_RV_ALLOCED_F) { |
130 | 0 | if(likely(allocated)) { |
131 | 0 | pkg_free(rv); |
132 | 0 | } else { |
133 | | /* not expected to be allocated */ |
134 | 0 | abort(); /* abort, otherwise is lost - find bugs quicker */ |
135 | 0 | } |
136 | 0 | } |
137 | 0 | } |
138 | 0 | } |
139 | | |
140 | | |
141 | | /** frees a rval returned by rval_new(), rval_convert() or rval_expr_eval(). |
142 | | * Note: it will be freed only when refcnt reaches 0 |
143 | | */ |
144 | | void rval_destroy(struct rvalue *rv) |
145 | 0 | { |
146 | 0 | rval_destroy_helper(rv, 1); |
147 | 0 | } |
148 | | |
149 | | |
150 | | /** frees content of rval which is not allocated, otherwise aborts. |
151 | | * Note: it will be freed only when refcnt reaches 0 |
152 | | */ |
153 | | void rval_destroy_content(struct rvalue *rv) |
154 | 0 | { |
155 | 0 | rval_destroy_helper(rv, 0); |
156 | 0 | } |
157 | | |
158 | | |
159 | | void rval_clean(struct rvalue *rv) |
160 | 0 | { |
161 | 0 | if(rv_unref(rv)) |
162 | 0 | rval_force_clean(rv); |
163 | 0 | } |
164 | | |
165 | | |
166 | | void rve_destroy(struct rval_expr *rve) |
167 | 0 | { |
168 | 0 | if(rve) { |
169 | 0 | if(rve->op == RVE_RVAL_OP) { |
170 | 0 | if(rve->left.rval.refcnt) { |
171 | 0 | if(rve->left.rval.refcnt == 1) |
172 | 0 | rval_destroy(&rve->left.rval); |
173 | 0 | else |
174 | 0 | LM_BUG("rval expr rval with invalid refcnt: %d " |
175 | 0 | "(%d,%d-%d,%d)" |
176 | 0 | "\n", |
177 | 0 | rve->left.rval.refcnt, rve->fpos.s_line, |
178 | 0 | rve->fpos.s_col, rve->fpos.e_line, rve->fpos.e_col); |
179 | 0 | } |
180 | 0 | if(rve->right.rval.refcnt) { |
181 | 0 | if(rve->right.rval.refcnt == 1) |
182 | 0 | rval_destroy(&rve->right.rval); |
183 | 0 | else |
184 | 0 | LM_BUG("rval expr rval with invalid refcnt: %d " |
185 | 0 | "(%d,%d-%d,%d)" |
186 | 0 | "\n", |
187 | 0 | rve->right.rval.refcnt, rve->fpos.s_line, |
188 | 0 | rve->fpos.s_col, rve->fpos.e_line, rve->fpos.e_col); |
189 | 0 | } |
190 | 0 | } else { |
191 | 0 | if(rve->left.rve) |
192 | 0 | rve_destroy(rve->left.rve); |
193 | 0 | if(rve->right.rve) |
194 | 0 | rve_destroy(rve->right.rve); |
195 | 0 | } |
196 | 0 | pkg_free(rve); |
197 | 0 | } |
198 | 0 | } |
199 | | |
200 | | |
201 | | void rval_cache_clean(struct rval_cache *rvc) |
202 | 0 | { |
203 | 0 | if((rvc->cache_type == RV_CACHE_PVAR) && (rvc->val_type != RV_NONE)) { |
204 | 0 | pv_value_destroy(&rvc->c.pval); |
205 | 0 | } |
206 | 0 | rvc->cache_type = RV_CACHE_EMPTY; |
207 | 0 | rvc->val_type = RV_NONE; |
208 | 0 | } |
209 | | |
210 | | |
211 | 0 | #define rv_chg_in_place(rv) ((rv)->refcnt == 1) |
212 | | |
213 | | |
214 | | /** init a rvalue structure. |
215 | | * Note: not needed if the structure is allocate with one of the |
216 | | * rval_new* functions |
217 | | */ |
218 | | void rval_init( |
219 | | struct rvalue *rv, enum rval_type t, union rval_val *v, int flags) |
220 | 0 | { |
221 | 0 | rv->flags = flags; |
222 | 0 | rv->refcnt = 1; |
223 | 0 | rv->type = t; |
224 | 0 | if(v) { |
225 | 0 | rv->v = *v; |
226 | 0 | } else { |
227 | 0 | memset(&rv->v, 0, sizeof(rv->v)); |
228 | 0 | } |
229 | 0 | } |
230 | | |
231 | | |
232 | | /** create a new pk_malloc'ed empty rvalue. |
233 | | * |
234 | | * @param extra_size - extra space to allocate |
235 | | * (e.g.: so that future string operation can reuse |
236 | | * the space) |
237 | | * @return new rv or 0 on error |
238 | | */ |
239 | | struct rvalue *rval_new_empty(int extra_size) |
240 | 0 | { |
241 | 0 | struct rvalue *rv; |
242 | 0 | int size; /* extra size at the end */ |
243 | |
|
244 | 0 | size = ROUND_LONG( |
245 | 0 | sizeof(*rv) - sizeof(rv->buf) + extra_size); /* round up */ |
246 | 0 | rv = pkg_malloc(size); |
247 | 0 | if(likely(rv)) { |
248 | 0 | rv->bsize = size - sizeof(*rv) |
249 | 0 | - sizeof(rv->buf); /* remaining size->buffer*/ |
250 | 0 | rv->flags = RV_RV_ALLOCED_F; |
251 | 0 | rv->refcnt = 1; |
252 | 0 | rv->type = RV_NONE; |
253 | 0 | } else { |
254 | 0 | PKG_MEM_ERROR; |
255 | 0 | return 0; |
256 | 0 | } |
257 | 0 | return rv; |
258 | 0 | } |
259 | | |
260 | | |
261 | | /** create a new pk_malloc'ed rv from a str. |
262 | | * |
263 | | * @param s - pointer to str, must be non-null |
264 | | * @param extra_size - extra space to allocate |
265 | | * (so that future string operation can reuse |
266 | | * the space) |
267 | | * @return new rv or 0 on error |
268 | | */ |
269 | | struct rvalue *rval_new_str(str *s, int extra_size) |
270 | 0 | { |
271 | 0 | struct rvalue *rv; |
272 | |
|
273 | 0 | rv = rval_new_empty(extra_size + s->len + 1 /* 0 term */); |
274 | 0 | if(likely(rv)) { |
275 | 0 | rv->type = RV_STR; |
276 | 0 | rv->v.s.s = &rv->buf[0]; |
277 | 0 | rv->v.s.len = s->len; |
278 | 0 | memcpy(rv->v.s.s, s->s, s->len); |
279 | 0 | rv->v.s.s[s->len] = 0; |
280 | 0 | } |
281 | 0 | return rv; |
282 | 0 | } |
283 | | |
284 | | |
285 | | /** create a new pk_malloc'ed RE rv from a str re. |
286 | | * It acts as rval_new_str, but also compiles a RE from the str |
287 | | * and sets v->re.regex. |
288 | | * @param s - pointer to str, must be non-null, zero-term'ed and a valid RE. |
289 | | * @return new rv or 0 on error |
290 | | */ |
291 | | struct rvalue *rval_new_re(str *s) |
292 | 0 | { |
293 | 0 | struct rvalue *rv; |
294 | 0 | long offs; |
295 | |
|
296 | 0 | offs = (long)&((struct rvalue *)0)->buf[0]; /* offset of the buf. member */ |
297 | | /* make sure we reserve enough space so that we can satisfy any regex_t |
298 | | * alignment requirement (pointer) */ |
299 | 0 | rv = rval_new_empty(ROUND_POINTER(offs) - offs + sizeof(*rv->v.re.regex) |
300 | 0 | + s->len + 1 /* 0 */); |
301 | 0 | if(likely(rv)) { |
302 | 0 | rv->type = RV_STR; |
303 | | /* make sure regex points to a properly aligned address |
304 | | * (use max./pointer alignment to be sure ) */ |
305 | 0 | rv->v.re.regex = |
306 | 0 | (regex_t *)((char *)&rv->buf[0] + ROUND_POINTER(offs) - offs); |
307 | 0 | rv->v.s.s = (char *)rv->v.re.regex + sizeof(*rv->v.re.regex); |
308 | 0 | rv->v.s.len = s->len; |
309 | 0 | memcpy(rv->v.s.s, s->s, s->len); |
310 | 0 | rv->v.s.s[s->len] = 0; |
311 | | /* compile the regex */ |
312 | | /* same flags as for expr. =~ (fix_expr()) */ |
313 | 0 | if(unlikely(regcomp(rv->v.re.regex, s->s, |
314 | 0 | REG_EXTENDED | REG_NOSUB | REG_ICASE))) { |
315 | | /* error */ |
316 | 0 | pkg_free(rv); |
317 | 0 | rv = 0; |
318 | 0 | } else /* success */ |
319 | 0 | rv->flags |= RV_RE_F; |
320 | 0 | } |
321 | 0 | return rv; |
322 | 0 | } |
323 | | |
324 | | |
325 | | /** get string name for a type. |
326 | | * |
327 | | * @return - null terminated name of the type |
328 | | */ |
329 | | char *rval_type_name(enum rval_type type) |
330 | 0 | { |
331 | 0 | switch(type) { |
332 | 0 | case RV_NONE: |
333 | 0 | return "none"; |
334 | 0 | case RV_LONG: |
335 | 0 | return "int"; |
336 | 0 | case RV_STR: |
337 | 0 | return "str"; |
338 | 0 | case RV_BEXPR: |
339 | 0 | return "bexpr_t"; |
340 | 0 | case RV_ACTION_ST: |
341 | 0 | return "action_t"; |
342 | 0 | case RV_PVAR: |
343 | 0 | return "pvar"; |
344 | 0 | case RV_AVP: |
345 | 0 | return "avp"; |
346 | 0 | break; |
347 | 0 | case RV_SEL: |
348 | 0 | return "select"; |
349 | 0 | } |
350 | 0 | return "error_unknown_type"; |
351 | 0 | } |
352 | | |
353 | | |
354 | | /** |
355 | | * @brief create a new pk_malloc'ed rvalue from a rval_val union |
356 | | * @param t rvalue type |
357 | | * @param v rvalue value |
358 | | * @param extra_size extra space to allocate |
359 | | * (so that future string operation can reuse the space) |
360 | | * @return new rv or 0 on error |
361 | | */ |
362 | | struct rvalue *rval_new(enum rval_type t, union rval_val *v, int extra_size) |
363 | 0 | { |
364 | 0 | struct rvalue *rv; |
365 | |
|
366 | 0 | if(t == RV_STR && v && v->s.s) |
367 | 0 | return rval_new_str(&v->s, extra_size); |
368 | 0 | rv = rval_new_empty(extra_size); |
369 | 0 | if(likely(rv)) { |
370 | 0 | rv->type = t; |
371 | 0 | if(likely(v && t != RV_STR)) { |
372 | 0 | rv->v = *v; |
373 | 0 | } else if(t == RV_STR) { |
374 | 0 | rv->v.s.s = &rv->buf[0]; |
375 | 0 | rv->v.s.len = 0; |
376 | 0 | if(likely(extra_size)) |
377 | 0 | rv->v.s.s[0] = 0; |
378 | 0 | } else |
379 | 0 | memset(&rv->v, 0, sizeof(rv->v)); |
380 | 0 | } |
381 | 0 | return rv; |
382 | 0 | } |
383 | | |
384 | | |
385 | | /** |
386 | | * @brief get rvalue basic type (RV_LONG or RV_STR) |
387 | | * |
388 | | * Given a rvalue it tries to determine its basic type. |
389 | | * Fills val_cache if non-null and empty (can be used in other rval* |
390 | | * function calls, to avoid re-resolving avps or pvars). It must be |
391 | | * rval_cache_clean()'en when no longer needed. |
392 | | * |
393 | | * @param h run action context |
394 | | * @param msg SIP message |
395 | | * @param rv target rvalue |
396 | | * @param val_cache write-only value cache, might be filled if non-null, |
397 | | * it _must_ be rval_cache_clean()'en when done. |
398 | | * @return basic type or RV_NONE on error |
399 | | */ |
400 | | inline static enum rval_type rval_get_btype(struct run_act_ctx *h, |
401 | | struct sip_msg *msg, struct rvalue *rv, struct rval_cache *val_cache) |
402 | 0 | { |
403 | 0 | avp_t *r_avp; |
404 | 0 | int_str tmp_avp_val; |
405 | 0 | int_str *avpv; |
406 | 0 | pv_value_t tmp_pval; |
407 | 0 | pv_value_t *pv; |
408 | 0 | enum rval_type tmp; |
409 | 0 | enum rval_type *ptype; |
410 | |
|
411 | 0 | switch(rv->type) { |
412 | 0 | case RV_LONG: |
413 | 0 | case RV_STR: |
414 | 0 | return rv->type; |
415 | 0 | case RV_BEXPR: |
416 | 0 | case RV_ACTION_ST: |
417 | 0 | return RV_LONG; |
418 | 0 | case RV_PVAR: |
419 | 0 | if(likely(val_cache && val_cache->cache_type == RV_CACHE_EMPTY)) { |
420 | 0 | pv = &val_cache->c.pval; |
421 | 0 | val_cache->cache_type = RV_CACHE_PVAR; |
422 | 0 | } else { |
423 | 0 | val_cache = 0; |
424 | 0 | pv = &tmp_pval; |
425 | 0 | } |
426 | 0 | memset(pv, 0, sizeof(tmp_pval)); |
427 | 0 | if(likely(pv_get_spec_value(msg, &rv->v.pvs, pv) == 0)) { |
428 | 0 | if(pv->flags & PV_TYPE_INT) { |
429 | 0 | if(likely(val_cache != 0)) |
430 | 0 | val_cache->val_type = RV_LONG; |
431 | 0 | else |
432 | 0 | pv_value_destroy(pv); |
433 | 0 | return RV_LONG; |
434 | 0 | } else if(pv->flags & PV_VAL_STR) { |
435 | 0 | if(likely(val_cache != 0)) |
436 | 0 | val_cache->val_type = RV_STR; |
437 | 0 | else |
438 | 0 | pv_value_destroy(pv); |
439 | 0 | return RV_STR; |
440 | 0 | } else { |
441 | 0 | pv_value_destroy(pv); |
442 | 0 | if(likely(val_cache != 0)) |
443 | 0 | val_cache->val_type = RV_NONE; /* undefined */ |
444 | 0 | goto error; |
445 | 0 | } |
446 | 0 | } else { |
447 | 0 | if(likely(val_cache != 0)) |
448 | 0 | val_cache->val_type = RV_NONE; /* undefined */ |
449 | 0 | goto error; |
450 | 0 | } |
451 | 0 | break; |
452 | 0 | case RV_AVP: |
453 | 0 | if(likely(val_cache && val_cache->cache_type == RV_CACHE_EMPTY)) { |
454 | 0 | ptype = &val_cache->val_type; |
455 | 0 | avpv = &val_cache->c.avp_val; |
456 | 0 | val_cache->cache_type = RV_CACHE_AVP; |
457 | 0 | } else { |
458 | 0 | ptype = &tmp; |
459 | 0 | avpv = &tmp_avp_val; |
460 | 0 | } |
461 | 0 | r_avp = search_avp_by_index( |
462 | 0 | rv->v.avps.type, rv->v.avps.name, avpv, rv->v.avps.index); |
463 | 0 | if(likely(r_avp)) { |
464 | 0 | if(r_avp->flags & AVP_VAL_STR) { |
465 | 0 | *ptype = RV_STR; |
466 | 0 | return RV_STR; |
467 | 0 | } else { |
468 | 0 | *ptype = RV_LONG; |
469 | 0 | return RV_LONG; |
470 | 0 | } |
471 | 0 | } else { |
472 | 0 | *ptype = RV_NONE; |
473 | 0 | goto error; |
474 | 0 | } |
475 | 0 | break; |
476 | 0 | case RV_SEL: |
477 | 0 | return RV_STR; |
478 | 0 | default: |
479 | 0 | LM_BUG("rv type %d not handled\n", rv->type); |
480 | 0 | } |
481 | 0 | error: |
482 | 0 | return RV_NONE; |
483 | 0 | } |
484 | | |
485 | | |
486 | | /** guess the type of an expression. |
487 | | * @return RV_LONG, RV_STR or RV_NONE (when type could not be found, |
488 | | * e.g. avp or pvar) |
489 | | */ |
490 | | enum rval_type rve_guess_type(struct rval_expr *rve) |
491 | 0 | { |
492 | 0 | switch(rve->op) { |
493 | 0 | case RVE_RVAL_OP: |
494 | 0 | switch(rve->left.rval.type) { |
495 | 0 | case RV_STR: |
496 | 0 | case RV_SEL: |
497 | 0 | return RV_STR; |
498 | 0 | case RV_LONG: |
499 | 0 | case RV_BEXPR: |
500 | 0 | case RV_ACTION_ST: |
501 | 0 | return RV_LONG; |
502 | 0 | case RV_PVAR: |
503 | 0 | case RV_AVP: |
504 | 0 | case RV_NONE: |
505 | 0 | return RV_NONE; |
506 | 0 | } |
507 | 0 | break; |
508 | 0 | case RVE_UMINUS_OP: |
509 | 0 | case RVE_BOOL_OP: |
510 | 0 | case RVE_LNOT_OP: |
511 | 0 | case RVE_BNOT_OP: |
512 | 0 | case RVE_MINUS_OP: |
513 | 0 | case RVE_MUL_OP: |
514 | 0 | case RVE_DIV_OP: |
515 | 0 | case RVE_MOD_OP: |
516 | 0 | case RVE_BOR_OP: |
517 | 0 | case RVE_BAND_OP: |
518 | 0 | case RVE_BXOR_OP: |
519 | 0 | case RVE_BLSHIFT_OP: |
520 | 0 | case RVE_BRSHIFT_OP: |
521 | 0 | case RVE_LAND_OP: |
522 | 0 | case RVE_LOR_OP: |
523 | 0 | case RVE_GT_OP: |
524 | 0 | case RVE_GTE_OP: |
525 | 0 | case RVE_LT_OP: |
526 | 0 | case RVE_LTE_OP: |
527 | 0 | case RVE_EQ_OP: |
528 | 0 | case RVE_DIFF_OP: |
529 | 0 | case RVE_IEQ_OP: |
530 | 0 | case RVE_IDIFF_OP: |
531 | 0 | case RVE_STREQ_OP: |
532 | 0 | case RVE_STRDIFF_OP: |
533 | 0 | case RVE_MATCH_OP: |
534 | 0 | case RVE_IPLUS_OP: |
535 | 0 | case RVE_STRLEN_OP: |
536 | 0 | case RVE_STREMPTY_OP: |
537 | 0 | case RVE_DEFINED_OP: |
538 | 0 | case RVE_NOTDEFINED_OP: |
539 | 0 | case RVE_LONG_OP: |
540 | 0 | return RV_LONG; |
541 | 0 | case RVE_PLUS_OP: |
542 | | /* '+' evaluates to the type of the left operand */ |
543 | 0 | return rve_guess_type(rve->left.rve); |
544 | 0 | case RVE_CONCAT_OP: |
545 | 0 | case RVE_STR_OP: |
546 | 0 | return RV_STR; |
547 | 0 | case RVE_SELVALEXP_OP: |
548 | 0 | break; |
549 | 0 | case RVE_SELVALOPT_OP: |
550 | 0 | return rve_guess_type(rve->left.rve); |
551 | 0 | case RVE_NONE_OP: |
552 | 0 | break; |
553 | 0 | } |
554 | 0 | return RV_NONE; |
555 | 0 | } |
556 | | |
557 | | |
558 | | /** returns true if expression is constant. |
559 | | * @return 0 or 1 on |
560 | | * non constant type |
561 | | */ |
562 | | int rve_is_constant(struct rval_expr *rve) |
563 | 0 | { |
564 | 0 | switch(rve->op) { |
565 | 0 | case RVE_RVAL_OP: |
566 | 0 | switch(rve->left.rval.type) { |
567 | 0 | case RV_STR: |
568 | 0 | return 1; |
569 | 0 | case RV_LONG: |
570 | 0 | return 1; |
571 | 0 | case RV_SEL: |
572 | 0 | case RV_BEXPR: |
573 | 0 | case RV_ACTION_ST: |
574 | 0 | case RV_PVAR: |
575 | 0 | case RV_AVP: |
576 | 0 | case RV_NONE: |
577 | 0 | return 0; |
578 | 0 | } |
579 | 0 | break; |
580 | 0 | case RVE_UMINUS_OP: |
581 | 0 | case RVE_BOOL_OP: |
582 | 0 | case RVE_LNOT_OP: |
583 | 0 | case RVE_BNOT_OP: |
584 | 0 | case RVE_STRLEN_OP: |
585 | 0 | case RVE_STREMPTY_OP: |
586 | 0 | case RVE_DEFINED_OP: |
587 | 0 | case RVE_NOTDEFINED_OP: |
588 | 0 | case RVE_LONG_OP: |
589 | 0 | case RVE_STR_OP: |
590 | 0 | return rve_is_constant(rve->left.rve); |
591 | 0 | case RVE_MINUS_OP: |
592 | 0 | case RVE_MUL_OP: |
593 | 0 | case RVE_DIV_OP: |
594 | 0 | case RVE_MOD_OP: |
595 | 0 | case RVE_BOR_OP: |
596 | 0 | case RVE_BAND_OP: |
597 | 0 | case RVE_BXOR_OP: |
598 | 0 | case RVE_BLSHIFT_OP: |
599 | 0 | case RVE_BRSHIFT_OP: |
600 | 0 | case RVE_LAND_OP: |
601 | 0 | case RVE_LOR_OP: |
602 | 0 | case RVE_GT_OP: |
603 | 0 | case RVE_GTE_OP: |
604 | 0 | case RVE_LT_OP: |
605 | 0 | case RVE_LTE_OP: |
606 | 0 | case RVE_EQ_OP: |
607 | 0 | case RVE_DIFF_OP: |
608 | 0 | case RVE_IEQ_OP: |
609 | 0 | case RVE_IDIFF_OP: |
610 | 0 | case RVE_STREQ_OP: |
611 | 0 | case RVE_STRDIFF_OP: |
612 | 0 | case RVE_MATCH_OP: |
613 | 0 | case RVE_PLUS_OP: |
614 | 0 | case RVE_IPLUS_OP: |
615 | 0 | case RVE_CONCAT_OP: |
616 | 0 | case RVE_SELVALEXP_OP: |
617 | 0 | case RVE_SELVALOPT_OP: |
618 | 0 | return rve_is_constant(rve->left.rve) |
619 | 0 | && rve_is_constant(rve->right.rve); |
620 | 0 | case RVE_NONE_OP: |
621 | 0 | break; |
622 | 0 | } |
623 | 0 | return 0; |
624 | 0 | } |
625 | | |
626 | | |
627 | | /** returns true if the expression has side-effects. |
628 | | * @return 1 for possible side-effects, 0 for no side-effects |
629 | | * TODO: add better checks |
630 | | */ |
631 | | int rve_has_side_effects(struct rval_expr *rve) |
632 | 0 | { |
633 | 0 | return !rve_is_constant(rve); |
634 | 0 | } |
635 | | |
636 | | |
637 | | /** returns true if operator is unary (takes only 1 arg). |
638 | | * @return 0 or 1 on |
639 | | */ |
640 | | static int rve_op_unary(enum rval_expr_op op) |
641 | 0 | { |
642 | 0 | switch(op) { |
643 | 0 | case RVE_RVAL_OP: /* not really an operator */ |
644 | 0 | return -1; |
645 | 0 | case RVE_UMINUS_OP: |
646 | 0 | case RVE_BOOL_OP: |
647 | 0 | case RVE_LNOT_OP: |
648 | 0 | case RVE_BNOT_OP: |
649 | 0 | case RVE_STRLEN_OP: |
650 | 0 | case RVE_STREMPTY_OP: |
651 | 0 | case RVE_DEFINED_OP: |
652 | 0 | case RVE_NOTDEFINED_OP: |
653 | 0 | case RVE_LONG_OP: |
654 | 0 | case RVE_STR_OP: |
655 | 0 | return 1; |
656 | 0 | case RVE_MINUS_OP: |
657 | 0 | case RVE_MUL_OP: |
658 | 0 | case RVE_DIV_OP: |
659 | 0 | case RVE_MOD_OP: |
660 | 0 | case RVE_BOR_OP: |
661 | 0 | case RVE_BAND_OP: |
662 | 0 | case RVE_BXOR_OP: |
663 | 0 | case RVE_BLSHIFT_OP: |
664 | 0 | case RVE_BRSHIFT_OP: |
665 | 0 | case RVE_LAND_OP: |
666 | 0 | case RVE_LOR_OP: |
667 | 0 | case RVE_GT_OP: |
668 | 0 | case RVE_GTE_OP: |
669 | 0 | case RVE_LT_OP: |
670 | 0 | case RVE_LTE_OP: |
671 | 0 | case RVE_EQ_OP: |
672 | 0 | case RVE_DIFF_OP: |
673 | 0 | case RVE_IEQ_OP: |
674 | 0 | case RVE_IDIFF_OP: |
675 | 0 | case RVE_STREQ_OP: |
676 | 0 | case RVE_STRDIFF_OP: |
677 | 0 | case RVE_MATCH_OP: |
678 | 0 | case RVE_PLUS_OP: |
679 | 0 | case RVE_IPLUS_OP: |
680 | 0 | case RVE_CONCAT_OP: |
681 | 0 | case RVE_SELVALEXP_OP: |
682 | 0 | case RVE_SELVALOPT_OP: |
683 | 0 | return 0; |
684 | 0 | case RVE_NONE_OP: |
685 | 0 | return -1; |
686 | 0 | break; |
687 | 0 | } |
688 | 0 | return 0; |
689 | 0 | } |
690 | | |
691 | | |
692 | | /** |
693 | | * @brief Returns 1 if expression is valid (type-wise) |
694 | | * @param type filled with the type of the expression (RV_LONG, RV_STR or |
695 | | * RV_NONE if it's dynamic) |
696 | | * @param rve checked expression |
697 | | * @param bad_rve set on failure to the subexpression for which the |
698 | | * type check failed |
699 | | * @param bad_t set on failure to the type of the bad subexpression |
700 | | * @param exp_t set on failure to the expected type for the bad |
701 | | * subexpression |
702 | | * @return 0 or 1 and sets *type to the resulting type |
703 | | * (RV_LONG, RV_STR or RV_NONE if it can be found only at runtime) |
704 | | */ |
705 | | int rve_check_type(enum rval_type *type, struct rval_expr *rve, |
706 | | struct rval_expr **bad_rve, enum rval_type *bad_t, |
707 | | enum rval_type *exp_t) |
708 | 0 | { |
709 | 0 | enum rval_type type1, type2; |
710 | |
|
711 | 0 | switch(rve->op) { |
712 | 0 | case RVE_RVAL_OP: |
713 | 0 | *type = rve_guess_type(rve); |
714 | 0 | return 1; |
715 | 0 | case RVE_SELVALEXP_OP: |
716 | 0 | case RVE_SELVALOPT_OP: |
717 | 0 | *type = rve_guess_type(rve); |
718 | 0 | return 1; |
719 | 0 | case RVE_UMINUS_OP: |
720 | 0 | case RVE_BOOL_OP: |
721 | 0 | case RVE_LNOT_OP: |
722 | 0 | case RVE_BNOT_OP: |
723 | 0 | *type = RV_LONG; |
724 | 0 | if(rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)) { |
725 | 0 | if(type1 == RV_STR) { |
726 | 0 | if(bad_rve) |
727 | 0 | *bad_rve = rve->left.rve; |
728 | 0 | if(bad_t) |
729 | 0 | *bad_t = type1; |
730 | 0 | if(exp_t) |
731 | 0 | *exp_t = RV_LONG; |
732 | 0 | return 0; |
733 | 0 | } |
734 | 0 | return 1; |
735 | 0 | } |
736 | 0 | return 0; |
737 | 0 | break; |
738 | 0 | case RVE_MINUS_OP: |
739 | 0 | case RVE_MUL_OP: |
740 | 0 | case RVE_DIV_OP: |
741 | 0 | case RVE_MOD_OP: |
742 | 0 | case RVE_BOR_OP: |
743 | 0 | case RVE_BAND_OP: |
744 | 0 | case RVE_BXOR_OP: |
745 | 0 | case RVE_BLSHIFT_OP: |
746 | 0 | case RVE_BRSHIFT_OP: |
747 | 0 | case RVE_LAND_OP: |
748 | 0 | case RVE_LOR_OP: |
749 | 0 | case RVE_GT_OP: |
750 | 0 | case RVE_GTE_OP: |
751 | 0 | case RVE_LT_OP: |
752 | 0 | case RVE_LTE_OP: |
753 | 0 | case RVE_IEQ_OP: |
754 | 0 | case RVE_IDIFF_OP: |
755 | 0 | case RVE_IPLUS_OP: |
756 | 0 | *type = RV_LONG; |
757 | 0 | if(rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)) { |
758 | 0 | if(type1 == RV_STR) { |
759 | 0 | if(bad_rve) |
760 | 0 | *bad_rve = rve->left.rve; |
761 | 0 | if(bad_t) |
762 | 0 | *bad_t = type1; |
763 | 0 | if(exp_t) |
764 | 0 | *exp_t = RV_LONG; |
765 | 0 | return 0; |
766 | 0 | } |
767 | 0 | if(rve_check_type( |
768 | 0 | &type2, rve->right.rve, bad_rve, bad_t, exp_t)) { |
769 | 0 | if(type2 == RV_STR) { |
770 | 0 | if(bad_rve) |
771 | 0 | *bad_rve = rve->right.rve; |
772 | 0 | if(bad_t) |
773 | 0 | *bad_t = type2; |
774 | 0 | if(exp_t) |
775 | 0 | *exp_t = RV_LONG; |
776 | 0 | return 0; |
777 | 0 | } |
778 | 0 | return 1; |
779 | 0 | } |
780 | 0 | } |
781 | 0 | return 0; |
782 | 0 | case RVE_EQ_OP: |
783 | 0 | case RVE_DIFF_OP: |
784 | 0 | *type = RV_LONG; |
785 | 0 | if(rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)) { |
786 | 0 | if(rve_check_type( |
787 | 0 | &type2, rve->right.rve, bad_rve, bad_t, exp_t)) { |
788 | 0 | if((type2 != type1) && (type1 != RV_NONE) |
789 | 0 | && (type2 != RV_NONE) |
790 | 0 | && !(type1 == RV_STR && type2 == RV_LONG)) { |
791 | 0 | if(bad_rve) |
792 | 0 | *bad_rve = rve->right.rve; |
793 | 0 | if(bad_t) |
794 | 0 | *bad_t = type2; |
795 | 0 | if(exp_t) |
796 | 0 | *exp_t = type1; |
797 | 0 | return 0; |
798 | 0 | } |
799 | 0 | return 1; |
800 | 0 | } |
801 | 0 | } |
802 | 0 | return 0; |
803 | 0 | case RVE_PLUS_OP: |
804 | 0 | *type = RV_NONE; |
805 | 0 | if(rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)) { |
806 | 0 | if(rve_check_type( |
807 | 0 | &type2, rve->right.rve, bad_rve, bad_t, exp_t)) { |
808 | 0 | if((type2 != type1) && (type1 != RV_NONE) |
809 | 0 | && (type2 != RV_NONE) |
810 | 0 | && !(type1 == RV_STR && type2 == RV_LONG)) { |
811 | 0 | if(bad_rve) |
812 | 0 | *bad_rve = rve->right.rve; |
813 | 0 | if(bad_t) |
814 | 0 | *bad_t = type2; |
815 | 0 | if(exp_t) |
816 | 0 | *exp_t = type1; |
817 | 0 | return 0; |
818 | 0 | } |
819 | 0 | *type = type1; |
820 | 0 | return 1; |
821 | 0 | } |
822 | 0 | } |
823 | 0 | break; |
824 | 0 | case RVE_CONCAT_OP: |
825 | 0 | *type = RV_STR; |
826 | 0 | if(rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)) { |
827 | 0 | if(rve_check_type( |
828 | 0 | &type2, rve->right.rve, bad_rve, bad_t, exp_t)) { |
829 | 0 | if((type2 != type1) && (type1 != RV_NONE) |
830 | 0 | && (type2 != RV_NONE) |
831 | 0 | && !(type1 == RV_STR && type2 == RV_LONG)) { |
832 | 0 | if(bad_rve) |
833 | 0 | *bad_rve = rve->right.rve; |
834 | 0 | if(bad_t) |
835 | 0 | *bad_t = type2; |
836 | 0 | if(exp_t) |
837 | 0 | *exp_t = type1; |
838 | 0 | return 0; |
839 | 0 | } |
840 | 0 | if(type1 == RV_LONG) { |
841 | 0 | if(bad_rve) |
842 | 0 | *bad_rve = rve->left.rve; |
843 | 0 | if(bad_t) |
844 | 0 | *bad_t = type1; |
845 | 0 | if(exp_t) |
846 | 0 | *exp_t = RV_STR; |
847 | 0 | return 0; |
848 | 0 | } |
849 | 0 | return 1; |
850 | 0 | } |
851 | 0 | } |
852 | 0 | break; |
853 | 0 | case RVE_STREQ_OP: |
854 | 0 | case RVE_STRDIFF_OP: |
855 | 0 | case RVE_MATCH_OP: |
856 | 0 | *type = RV_LONG; |
857 | 0 | if(rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)) { |
858 | 0 | if(rve_check_type( |
859 | 0 | &type2, rve->right.rve, bad_rve, bad_t, exp_t)) { |
860 | 0 | if((type2 != type1) && (type1 != RV_NONE) |
861 | 0 | && (type2 != RV_NONE) |
862 | 0 | && !(type1 == RV_STR && type2 == RV_LONG)) { |
863 | 0 | if(bad_rve) |
864 | 0 | *bad_rve = rve->right.rve; |
865 | 0 | if(bad_t) |
866 | 0 | *bad_t = type2; |
867 | 0 | if(exp_t) |
868 | 0 | *exp_t = type1; |
869 | 0 | return 0; |
870 | 0 | } |
871 | 0 | if(type1 == RV_LONG) { |
872 | 0 | if(bad_rve) |
873 | 0 | *bad_rve = rve->left.rve; |
874 | 0 | if(bad_t) |
875 | 0 | *bad_t = type1; |
876 | 0 | if(exp_t) |
877 | 0 | *exp_t = RV_STR; |
878 | 0 | return 0; |
879 | 0 | } |
880 | 0 | return 1; |
881 | 0 | } |
882 | 0 | } |
883 | 0 | break; |
884 | 0 | case RVE_STRLEN_OP: |
885 | 0 | case RVE_STREMPTY_OP: |
886 | 0 | case RVE_DEFINED_OP: |
887 | 0 | case RVE_NOTDEFINED_OP: |
888 | 0 | *type = RV_LONG; |
889 | 0 | if(rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)) { |
890 | 0 | if(type1 == RV_LONG) { |
891 | 0 | if(bad_rve) |
892 | 0 | *bad_rve = rve->left.rve; |
893 | 0 | if(bad_t) |
894 | 0 | *bad_t = type1; |
895 | 0 | if(exp_t) |
896 | 0 | *exp_t = RV_STR; |
897 | 0 | return 0; |
898 | 0 | } |
899 | 0 | return 1; |
900 | 0 | } |
901 | 0 | break; |
902 | 0 | case RVE_LONG_OP: |
903 | 0 | *type = RV_LONG; |
904 | 0 | return 1; |
905 | 0 | break; |
906 | 0 | case RVE_STR_OP: |
907 | 0 | *type = RV_STR; |
908 | 0 | return 1; |
909 | 0 | break; |
910 | 0 | case RVE_NONE_OP: |
911 | 0 | default: |
912 | 0 | LM_BUG("unexpected rve op %d (%d,%d-%d,%d)\n", rve->op, |
913 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
914 | 0 | rve->fpos.e_col); |
915 | 0 | if(bad_rve) |
916 | 0 | *bad_rve = rve; |
917 | 0 | if(bad_t) |
918 | 0 | *bad_t = RV_NONE; |
919 | 0 | if(exp_t) |
920 | 0 | *exp_t = RV_STR; |
921 | 0 | break; |
922 | 0 | } |
923 | 0 | return 0; |
924 | 0 | } |
925 | | |
926 | | |
927 | | /** get the long int value of an rvalue. |
928 | | * *i=(long int)rv |
929 | | * if rv == undefined select, avp or pvar, return 0. |
930 | | * if an error occurs while evaluating a select, avp or pvar, behave as |
931 | | * for the undefined case (and return success). |
932 | | * @param h - script context handle |
933 | | * @param msg - sip msg |
934 | | * @param i - pointer to int, where the conversion result will be stored |
935 | | * @param rv - rvalue to be converted |
936 | | * @param cache - cached rv value (read-only), can be 0 |
937 | | * |
938 | | * @return 0 on success, \<0 on error and EXPR_DROP on drop |
939 | | */ |
940 | | long rval_get_long(struct run_act_ctx *h, struct sip_msg *msg, long *i, |
941 | | struct rvalue *rv, struct rval_cache *cache) |
942 | 0 | { |
943 | 0 | avp_t *r_avp; |
944 | 0 | int_str avp_val; |
945 | 0 | pv_value_t pval; |
946 | 0 | str tmp; |
947 | 0 | str *s; |
948 | 0 | int r, ret; |
949 | 0 | int destroy_pval; |
950 | |
|
951 | 0 | destroy_pval = 0; |
952 | 0 | s = 0; |
953 | 0 | ret = 0; |
954 | 0 | switch(rv->type) { |
955 | 0 | case RV_LONG: |
956 | 0 | *i = rv->v.l; |
957 | 0 | break; |
958 | 0 | case RV_STR: |
959 | 0 | s = &rv->v.s; |
960 | 0 | goto rv_str; |
961 | 0 | case RV_BEXPR: |
962 | 0 | *i = eval_expr(h, rv->v.bexpr, msg); |
963 | 0 | if(*i == EXPR_DROP) { |
964 | 0 | *i = 0; /* false */ |
965 | 0 | return EXPR_DROP; |
966 | 0 | } |
967 | 0 | break; |
968 | 0 | case RV_ACTION_ST: |
969 | 0 | if(rv->v.action) { |
970 | 0 | if(unlikely(ksr_return_mode == 1)) { |
971 | 0 | *i = run_actions_safe(h, rv->v.action, msg); |
972 | 0 | } else { |
973 | 0 | *i = (run_actions_safe(h, rv->v.action, msg) > 0); |
974 | 0 | } |
975 | 0 | h->run_flags &= ~(RETURN_R_F | BREAK_R_F); |
976 | | /* catch return & break in expr*/ |
977 | 0 | } else |
978 | 0 | *i = 0; |
979 | 0 | break; |
980 | 0 | case RV_SEL: |
981 | 0 | r = run_select(&tmp, &rv->v.sel, msg); |
982 | 0 | if(unlikely(r != 0)) { |
983 | 0 | if(r < 0) |
984 | 0 | goto eval_error; |
985 | 0 | else /* i>0 => undefined */ |
986 | 0 | goto undef; |
987 | 0 | } |
988 | 0 | s = &tmp; |
989 | 0 | goto rv_str; |
990 | 0 | case RV_AVP: |
991 | 0 | if(unlikely(cache && cache->cache_type == RV_CACHE_AVP)) { |
992 | 0 | if(likely(cache->val_type == RV_LONG)) { |
993 | 0 | *i = cache->c.avp_val.n; |
994 | 0 | } else if(cache->val_type == RV_STR) { |
995 | 0 | s = &cache->c.avp_val.s; |
996 | 0 | goto rv_str; |
997 | 0 | } else if(cache->val_type == RV_NONE) |
998 | 0 | goto undef; |
999 | 0 | else |
1000 | 0 | goto error_cache; |
1001 | 0 | } else { |
1002 | 0 | r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name, |
1003 | 0 | &avp_val, rv->v.avps.index); |
1004 | 0 | if(likely(r_avp)) { |
1005 | 0 | if(unlikely(r_avp->flags & AVP_VAL_STR)) { |
1006 | 0 | s = &avp_val.s; |
1007 | 0 | goto rv_str; |
1008 | 0 | } else { |
1009 | 0 | *i = avp_val.n; |
1010 | 0 | } |
1011 | 0 | } else { |
1012 | 0 | goto undef; |
1013 | 0 | } |
1014 | 0 | } |
1015 | 0 | break; |
1016 | 0 | case RV_PVAR: |
1017 | 0 | if(unlikely(cache && cache->cache_type == RV_CACHE_PVAR)) { |
1018 | 0 | if(likely((cache->val_type == RV_LONG) |
1019 | 0 | || (cache->c.pval.flags & PV_VAL_INT))) { |
1020 | 0 | *i = cache->c.pval.ri; |
1021 | 0 | } else if(cache->val_type == RV_STR) { |
1022 | 0 | s = &cache->c.pval.rs; |
1023 | 0 | goto rv_str; |
1024 | 0 | } else if(cache->val_type == RV_NONE) |
1025 | 0 | goto undef; |
1026 | 0 | else |
1027 | 0 | goto error_cache; |
1028 | 0 | } else { |
1029 | 0 | memset(&pval, 0, sizeof(pval)); |
1030 | 0 | if(likely(pv_get_spec_value(msg, &rv->v.pvs, &pval) == 0)) { |
1031 | 0 | if(likely(pval.flags & PV_VAL_INT)) { |
1032 | 0 | *i = pval.ri; |
1033 | 0 | pv_value_destroy(&pval); |
1034 | 0 | } else if(likely(pval.flags & PV_VAL_STR)) { |
1035 | 0 | destroy_pval = 1; /* we must pv_value_destroy() later*/ |
1036 | 0 | s = &pval.rs; |
1037 | 0 | goto rv_str; |
1038 | 0 | } else { |
1039 | | /* no PV_VAL_STR and no PV_VAL_INT => undef |
1040 | | * (PV_VAL_NULL) */ |
1041 | 0 | pv_value_destroy(&pval); |
1042 | 0 | goto undef; |
1043 | 0 | } |
1044 | 0 | } else { |
1045 | 0 | goto eval_error; |
1046 | 0 | } |
1047 | 0 | } |
1048 | 0 | break; |
1049 | 0 | default: |
1050 | 0 | LM_BUG("rv type %d not handled\n", rv->type); |
1051 | 0 | goto error; |
1052 | 0 | } |
1053 | 0 | return ret; |
1054 | 0 | undef: |
1055 | 0 | eval_error: /* same as undefined */ |
1056 | | /* handle undefined => result 0, return success */ |
1057 | 0 | *i = 0; |
1058 | 0 | return 0; |
1059 | 0 | rv_str: |
1060 | | /* rv is of string type => try to convert it to int */ |
1061 | | /* if "" => 0 (most likely case) */ |
1062 | 0 | if(likely(s->len == 0)) |
1063 | 0 | *i = 0; |
1064 | 0 | else if(unlikely(str2slong(s, i) != 0)) { |
1065 | | /* dec to int failed, try hex to int */ |
1066 | 0 | if(!(s->len > 2 && s->s[0] == '0' && (s->s[1] == 'x' || s->s[1] == 'X') |
1067 | 0 | && (hexstr2int(s->s + 2, s->len - 2, (unsigned int *)i) |
1068 | 0 | == 0))) { |
1069 | | /* error converting to int => non numeric => 0 */ |
1070 | 0 | *i = 0; |
1071 | 0 | #ifdef RV_STR2INT_VERBOSE_ERR |
1072 | 0 | LM_WARN("automatic string to int conversion for \"%.*s\" failed\n", |
1073 | 0 | s->len, ZSW(s->s)); |
1074 | | /* return an error code */ |
1075 | 0 | #endif |
1076 | 0 | #ifdef RV_STR2INT_ERR |
1077 | 0 | ret = -1; |
1078 | 0 | #endif |
1079 | 0 | } |
1080 | 0 | } |
1081 | 0 | if(destroy_pval) |
1082 | 0 | pv_value_destroy(&pval); |
1083 | 0 | return ret; |
1084 | 0 | error_cache: |
1085 | 0 | LM_BUG("invalid cached value:cache type %d, value type %d\n", |
1086 | 0 | cache ? cache->cache_type : 0, cache ? cache->val_type : 0); |
1087 | 0 | error: |
1088 | 0 | if(destroy_pval) |
1089 | 0 | pv_value_destroy(&pval); |
1090 | 0 | *i = 0; |
1091 | 0 | return -1; |
1092 | 0 | } |
1093 | | |
1094 | | |
1095 | | /** log a message, appending rve position and a '\n'.*/ |
1096 | | #define RVE_LOG(lev, rve, txt) \ |
1097 | | LOG((lev), txt " (%d,%d-%d,%d)\n", (rve)->fpos.s_line, rve->fpos.s_col, \ |
1098 | | (rve)->fpos.e_line, rve->fpos.e_col) |
1099 | | |
1100 | | |
1101 | | /** macro for checking and handling rval_get_long() retcode. |
1102 | | * check if the return code is an rval_get_long error and if so |
1103 | | * handle the error (e.g. print a log message, ignore the error by |
1104 | | * setting ret to 0 a.s.o.) |
1105 | | * @param ret - retcode as returned by rval_get_long() (might be changed) |
1106 | | * @param txt - warning message txt (no pointer allowed) |
1107 | | * @param rve - rval_expr, used to access the config. pos |
1108 | | */ |
1109 | | #if defined RVAL_GET_LONG_ERR_WARN && defined RVAL_GET_LONG_ERR_IGN |
1110 | | #define rval_get_LONG_handle_ret(ret, txt, rve) \ |
1111 | | do { \ |
1112 | | if(unlikely((ret) < 0)) { \ |
1113 | | RVE_LOG(L_WARN, rve, txt); \ |
1114 | | (ret) = 0; \ |
1115 | | } \ |
1116 | | } while(0) |
1117 | | #elif defined RVAL_GET_LONG_ERR_WARN |
1118 | | #define rval_get_long_handle_ret(ret, txt, rve) \ |
1119 | | do { \ |
1120 | | if(unlikely((ret) < 0)) \ |
1121 | | RVE_LOG(L_WARN, rve, txt); \ |
1122 | | } while(0) |
1123 | | #elif defined RVAL_GET_LONG_ERR_IGN |
1124 | | #define rval_get_long_handle_ret(ret, txt, rve) \ |
1125 | | do { \ |
1126 | | if(unlikely((ret) < 0)) \ |
1127 | | (ret) = 0; \ |
1128 | | } while(0) |
1129 | | #else |
1130 | | #define rval_get_long_handle_ret(ret, txt, rve) /* do nothing */ |
1131 | | #endif |
1132 | | |
1133 | | |
1134 | | /** get the string value of an rv in a tmp variable |
1135 | | * *s=(str)rv |
1136 | | * if rv == undefined select, avp or pvar, return "". |
1137 | | * if an error occurs while evaluating a select, avp or pvar, behave as |
1138 | | * for the undefined case (and return success). |
1139 | | * The result points either inside the passed rv, inside |
1140 | | * new_cache or inside an avp. new_cache must be non zero, |
1141 | | * initialized previously and it _must_ be rval_cache_clean(...)'ed when |
1142 | | * done. |
1143 | | * WARNING: it's not intended for general use. It might return a pointer |
1144 | | * inside rv so the result _must_ be treated as read-only. rv and new_cache |
1145 | | * must not be released/freed until the result is no longer needed. |
1146 | | * For general use see rval_get_str(). |
1147 | | * @param h - script context handle |
1148 | | * @param msg - sip msg |
1149 | | * @param tmpv - str return value (pointer to a str struct that will be |
1150 | | * be filled with the conversion result) |
1151 | | * @param rv - rvalue to be converted |
1152 | | * @param cache - cached rv value (read-only), can be 0 |
1153 | | * @param tmp_cache - used for temporary storage (so that tmpv will not |
1154 | | * point to possible freed data), it must be non-null, |
1155 | | * initialized and cleaned afterwards. |
1156 | | * @return 0 on success, <0 on error and EXPR_DROP on drop |
1157 | | */ |
1158 | | int rval_get_tmp_str(struct run_act_ctx *h, struct sip_msg *msg, str *tmpv, |
1159 | | struct rvalue *rv, struct rval_cache *cache, |
1160 | | struct rval_cache *tmp_cache) |
1161 | 0 | { |
1162 | 0 | avp_t *r_avp; |
1163 | 0 | int i; |
1164 | |
|
1165 | 0 | if(rv == NULL) { |
1166 | 0 | return -1; |
1167 | 0 | } |
1168 | | |
1169 | 0 | switch(rv->type) { |
1170 | 0 | case RV_LONG: |
1171 | 0 | tmpv->s = sint2strbuf(rv->v.l, tmp_cache->i2s, |
1172 | 0 | sizeof(tmp_cache->i2s), &tmpv->len); |
1173 | 0 | tmp_cache->cache_type = RV_CACHE_INT2STR; |
1174 | 0 | break; |
1175 | 0 | case RV_STR: |
1176 | 0 | *tmpv = rv->v.s; |
1177 | 0 | break; |
1178 | 0 | case RV_ACTION_ST: |
1179 | 0 | if(rv->v.action) { |
1180 | 0 | i = (run_actions_safe(h, rv->v.action, msg) > 0); |
1181 | 0 | h->run_flags &= ~(RETURN_R_F | BREAK_R_F); |
1182 | | /* catch return & break in expr*/ |
1183 | 0 | } else |
1184 | 0 | i = 0; |
1185 | 0 | tmpv->s = sint2strbuf( |
1186 | 0 | i, tmp_cache->i2s, sizeof(tmp_cache->i2s), &tmpv->len); |
1187 | 0 | tmp_cache->cache_type = RV_CACHE_INT2STR; |
1188 | 0 | break; |
1189 | 0 | case RV_BEXPR: |
1190 | 0 | i = eval_expr(h, rv->v.bexpr, msg); |
1191 | 0 | if(i == EXPR_DROP) { |
1192 | 0 | i = 0; /* false */ |
1193 | 0 | tmpv->s = sint2strbuf( |
1194 | 0 | i, tmp_cache->i2s, sizeof(tmp_cache->i2s), &tmpv->len); |
1195 | 0 | tmp_cache->cache_type = RV_CACHE_INT2STR; |
1196 | 0 | return EXPR_DROP; |
1197 | 0 | } |
1198 | 0 | tmpv->s = sint2strbuf( |
1199 | 0 | i, tmp_cache->i2s, sizeof(tmp_cache->i2s), &tmpv->len); |
1200 | 0 | tmp_cache->cache_type = RV_CACHE_INT2STR; |
1201 | 0 | break; |
1202 | 0 | case RV_SEL: |
1203 | 0 | i = run_select(tmpv, &rv->v.sel, msg); |
1204 | 0 | if(unlikely(i != 0)) { |
1205 | 0 | if(i < 0) { |
1206 | 0 | goto eval_error; |
1207 | 0 | } else { /* i>0 => undefined */ |
1208 | 0 | goto undef; |
1209 | 0 | } |
1210 | 0 | } |
1211 | 0 | break; |
1212 | 0 | case RV_AVP: |
1213 | 0 | if(likely(cache && cache->cache_type == RV_CACHE_AVP)) { |
1214 | 0 | if(likely(cache->val_type == RV_STR)) { |
1215 | 0 | *tmpv = cache->c.avp_val.s; |
1216 | 0 | } else if(cache->val_type == RV_LONG) { |
1217 | 0 | i = cache->c.avp_val.n; |
1218 | 0 | tmpv->s = sint2strbuf(i, tmp_cache->i2s, |
1219 | 0 | sizeof(tmp_cache->i2s), &tmpv->len); |
1220 | 0 | tmp_cache->cache_type = RV_CACHE_INT2STR; |
1221 | 0 | } else if(cache->val_type == RV_NONE) { |
1222 | 0 | goto undef; |
1223 | 0 | } else |
1224 | 0 | goto error_cache; |
1225 | 0 | } else { |
1226 | 0 | r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name, |
1227 | 0 | &tmp_cache->c.avp_val, rv->v.avps.index); |
1228 | 0 | if(likely(r_avp)) { |
1229 | 0 | if(likely(r_avp->flags & AVP_VAL_STR)) { |
1230 | 0 | tmp_cache->cache_type = RV_CACHE_AVP; |
1231 | 0 | tmp_cache->val_type = RV_STR; |
1232 | 0 | *tmpv = tmp_cache->c.avp_val.s; |
1233 | 0 | } else { |
1234 | 0 | i = tmp_cache->c.avp_val.n; |
1235 | 0 | tmpv->s = sint2strbuf(i, tmp_cache->i2s, |
1236 | 0 | sizeof(tmp_cache->i2s), &tmpv->len); |
1237 | 0 | tmp_cache->cache_type = RV_CACHE_INT2STR; |
1238 | 0 | } |
1239 | 0 | } else |
1240 | 0 | goto undef; |
1241 | 0 | } |
1242 | 0 | break; |
1243 | 0 | case RV_PVAR: |
1244 | 0 | if(likely(cache && cache->cache_type == RV_CACHE_PVAR)) { |
1245 | 0 | if(likely(cache->val_type == RV_STR)) { |
1246 | 0 | *tmpv = cache->c.pval.rs; |
1247 | 0 | } else if(cache->val_type == RV_LONG) { |
1248 | 0 | i = cache->c.pval.ri; |
1249 | 0 | tmpv->s = sint2strbuf(i, tmp_cache->i2s, |
1250 | 0 | sizeof(tmp_cache->i2s), &tmpv->len); |
1251 | 0 | tmp_cache->cache_type = RV_CACHE_INT2STR; |
1252 | 0 | } else if(cache->val_type == RV_NONE) { |
1253 | 0 | goto undef; |
1254 | 0 | } else |
1255 | 0 | goto error_cache; |
1256 | 0 | } else { |
1257 | 0 | memset(&tmp_cache->c.pval, 0, sizeof(tmp_cache->c.pval)); |
1258 | 0 | if(likely(pv_get_spec_value(msg, &rv->v.pvs, &tmp_cache->c.pval) |
1259 | 0 | == 0)) { |
1260 | 0 | if(likely(tmp_cache->c.pval.flags & PV_VAL_STR)) { |
1261 | | /* the value is not destroyed, but saved instead |
1262 | | in tmp_cache so that it can be destroyed later |
1263 | | when no longer needed */ |
1264 | 0 | tmp_cache->cache_type = RV_CACHE_PVAR; |
1265 | 0 | tmp_cache->val_type = RV_STR; |
1266 | 0 | *tmpv = tmp_cache->c.pval.rs; |
1267 | 0 | } else if(likely(tmp_cache->c.pval.flags & PV_VAL_INT)) { |
1268 | 0 | i = tmp_cache->c.pval.ri; |
1269 | 0 | pv_value_destroy(&tmp_cache->c.pval); |
1270 | 0 | tmpv->s = sint2strbuf(i, tmp_cache->i2s, |
1271 | 0 | sizeof(tmp_cache->i2s), &tmpv->len); |
1272 | 0 | tmp_cache->cache_type = RV_CACHE_INT2STR; |
1273 | 0 | } else { |
1274 | | /* no PV_VAL_STR and no PV_VAL_INT => undef |
1275 | | * (PV_VAL_NULL) */ |
1276 | 0 | pv_value_destroy(&tmp_cache->c.pval); |
1277 | 0 | goto undef; |
1278 | 0 | } |
1279 | 0 | } else { |
1280 | 0 | goto eval_error; |
1281 | 0 | } |
1282 | 0 | } |
1283 | 0 | break; |
1284 | 0 | default: |
1285 | 0 | LM_BUG("rv type %d not handled\n", rv->type); |
1286 | 0 | goto error; |
1287 | 0 | } |
1288 | 0 | return 0; |
1289 | 0 | undef: |
1290 | 0 | eval_error: /* same as undefined */ |
1291 | | /* handle undefined => result "", return success */ |
1292 | 0 | tmpv->s = ""; |
1293 | 0 | tmpv->len = 0; |
1294 | 0 | return 0; |
1295 | 0 | error_cache: |
1296 | 0 | LM_BUG("invalid cached value:cache type %d, value type %d\n", |
1297 | 0 | cache ? cache->cache_type : 0, cache ? cache->val_type : 0); |
1298 | 0 | error: |
1299 | 0 | tmpv->s = ""; |
1300 | 0 | tmpv->len = 0; |
1301 | 0 | return -1; |
1302 | 0 | } |
1303 | | |
1304 | | |
1305 | | /** get the string value of an rv. |
1306 | | * *s=(str)rv |
1307 | | * The result is pkg malloc'ed (so it should be pkg_free()'ed when finished. |
1308 | | * @return 0 on success, <0 on error and EXPR_DROP on drop |
1309 | | */ |
1310 | | int rval_get_str(struct run_act_ctx *h, struct sip_msg *msg, str *s, |
1311 | | struct rvalue *rv, struct rval_cache *cache) |
1312 | 0 | { |
1313 | 0 | str tmp; |
1314 | 0 | struct rval_cache tmp_cache; |
1315 | |
|
1316 | 0 | rval_cache_init(&tmp_cache); |
1317 | 0 | if(unlikely(rval_get_tmp_str(h, msg, &tmp, rv, cache, &tmp_cache) < 0)) |
1318 | 0 | goto error; |
1319 | 0 | s->s = pkg_malloc(tmp.len + 1 /* 0 term */); |
1320 | 0 | if(unlikely(s->s == 0)) { |
1321 | 0 | PKG_MEM_ERROR; |
1322 | 0 | goto error; |
1323 | 0 | } |
1324 | 0 | s->len = tmp.len; |
1325 | 0 | memcpy(s->s, tmp.s, tmp.len); |
1326 | 0 | s->s[tmp.len] = 0; /* 0 term */ |
1327 | 0 | rval_cache_clean(&tmp_cache); |
1328 | 0 | return 0; |
1329 | 0 | error: |
1330 | 0 | rval_cache_clean(&tmp_cache); |
1331 | 0 | return -1; |
1332 | 0 | } |
1333 | | |
1334 | | |
1335 | | /** |
1336 | | * @brief Convert a rvalue to another rvalue, of a specific type |
1337 | | * |
1338 | | * Convert a rvalue to another rvalue, of a specific type. |
1339 | | * The result is read-only in most cases (can be a reference |
1340 | | * to another rvalue, can be checked by using rv_chg_in_place()) and |
1341 | | * _must_ be rval_destroy()'ed. |
1342 | | * |
1343 | | * @param h run action context |
1344 | | * @param msg SIP mesasge |
1345 | | * @param type - type to convert to |
1346 | | * @param v - rvalue to convert |
1347 | | * @param c - rval_cache (cached v value if known/filled by another |
1348 | | * function), can be 0 (unknown/not needed) |
1349 | | * @return pointer to a rvalue (reference to an existing one or a new |
1350 | | * one, @see rv_chg_in_place() and the above comment), or 0 on error. |
1351 | | */ |
1352 | | struct rvalue *rval_convert(struct run_act_ctx *h, struct sip_msg *msg, |
1353 | | enum rval_type type, struct rvalue *v, struct rval_cache *c) |
1354 | 0 | { |
1355 | 0 | long i; |
1356 | 0 | struct rval_cache tmp_cache; |
1357 | 0 | str tmp; |
1358 | 0 | struct rvalue *ret; |
1359 | 0 | union rval_val val; |
1360 | |
|
1361 | 0 | if(v->type == type) { |
1362 | 0 | rv_ref(v); |
1363 | 0 | return v; |
1364 | 0 | } |
1365 | 0 | switch(type) { |
1366 | 0 | case RV_LONG: |
1367 | 0 | if(unlikely(rval_get_long(h, msg, &i, v, c) < 0)) |
1368 | 0 | return 0; |
1369 | 0 | val.l = i; |
1370 | 0 | return rval_new(RV_LONG, &val, 0); |
1371 | 0 | case RV_STR: |
1372 | 0 | rval_cache_init(&tmp_cache); |
1373 | 0 | if(unlikely(rval_get_tmp_str(h, msg, &tmp, v, c, &tmp_cache) < 0)) { |
1374 | 0 | rval_cache_clean(&tmp_cache); |
1375 | 0 | return 0; |
1376 | 0 | } |
1377 | 0 | ret = rval_new_str(&tmp, RV_STR_EXTRA); |
1378 | 0 | rval_cache_clean(&tmp_cache); |
1379 | 0 | return ret; |
1380 | 0 | case RV_NONE: |
1381 | 0 | default: |
1382 | 0 | LM_BUG("unsupported conversion to type %d\n", type); |
1383 | 0 | return 0; |
1384 | 0 | } |
1385 | 0 | return 0; |
1386 | 0 | } |
1387 | | |
1388 | | |
1389 | | /** integer operation: *res= op v. |
1390 | | * @return 0 on success, \<0 on error |
1391 | | */ |
1392 | | inline static int long_longop1(long *res, enum rval_expr_op op, long v) |
1393 | 0 | { |
1394 | 0 | switch(op) { |
1395 | 0 | case RVE_UMINUS_OP: |
1396 | 0 | *res = -v; |
1397 | 0 | break; |
1398 | 0 | case RVE_BOOL_OP: |
1399 | 0 | *res = !!v; |
1400 | 0 | break; |
1401 | 0 | case RVE_LNOT_OP: |
1402 | 0 | *res = !v; |
1403 | 0 | break; |
1404 | 0 | case RVE_BNOT_OP: |
1405 | 0 | *res = ~v; |
1406 | 0 | break; |
1407 | 0 | default: |
1408 | 0 | LM_BUG("rv unsupported intop1 %d\n", op); |
1409 | 0 | return -1; |
1410 | 0 | } |
1411 | 0 | return 0; |
1412 | 0 | } |
1413 | | |
1414 | | |
1415 | | /** integer operation: *res= v1 op v2 |
1416 | | * @return 0 on success, \<0 on error |
1417 | | */ |
1418 | | inline static int long_longop2( |
1419 | | long *res, enum rval_expr_op op, long v1, long v2) |
1420 | 0 | { |
1421 | 0 | switch(op) { |
1422 | 0 | case RVE_PLUS_OP: |
1423 | 0 | case RVE_IPLUS_OP: |
1424 | 0 | *res = v1 + v2; |
1425 | 0 | break; |
1426 | 0 | case RVE_MINUS_OP: |
1427 | 0 | *res = v1 - v2; |
1428 | 0 | break; |
1429 | 0 | case RVE_MUL_OP: |
1430 | 0 | *res = v1 * v2; |
1431 | 0 | break; |
1432 | 0 | case RVE_DIV_OP: |
1433 | 0 | if(unlikely(v2 == 0)) { |
1434 | 0 | LM_ERR("rv div by 0\n"); |
1435 | 0 | return -1; |
1436 | 0 | } |
1437 | 0 | *res = v1 / v2; |
1438 | 0 | break; |
1439 | 0 | case RVE_MOD_OP: |
1440 | 0 | if(unlikely(v2 == 0)) { |
1441 | 0 | LM_ERR("rv mod by 0\n"); |
1442 | 0 | return -1; |
1443 | 0 | } |
1444 | 0 | *res = v1 % v2; |
1445 | 0 | break; |
1446 | 0 | case RVE_BOR_OP: |
1447 | 0 | *res = v1 | v2; |
1448 | 0 | break; |
1449 | 0 | case RVE_BAND_OP: |
1450 | 0 | *res = v1 & v2; |
1451 | 0 | break; |
1452 | 0 | case RVE_BXOR_OP: |
1453 | 0 | *res = v1 ^ v2; |
1454 | 0 | break; |
1455 | 0 | case RVE_BLSHIFT_OP: |
1456 | 0 | *res = v1 << v2; |
1457 | 0 | break; |
1458 | 0 | case RVE_BRSHIFT_OP: |
1459 | 0 | *res = v1 >> v2; |
1460 | 0 | break; |
1461 | 0 | case RVE_LAND_OP: |
1462 | 0 | *res = v1 && v2; |
1463 | 0 | break; |
1464 | 0 | case RVE_LOR_OP: |
1465 | 0 | *res = v1 || v2; |
1466 | 0 | break; |
1467 | 0 | case RVE_GT_OP: |
1468 | 0 | *res = v1 > v2; |
1469 | 0 | break; |
1470 | 0 | case RVE_GTE_OP: |
1471 | 0 | *res = v1 >= v2; |
1472 | 0 | break; |
1473 | 0 | case RVE_LT_OP: |
1474 | 0 | *res = v1 < v2; |
1475 | 0 | break; |
1476 | 0 | case RVE_LTE_OP: |
1477 | 0 | *res = v1 <= v2; |
1478 | 0 | break; |
1479 | 0 | case RVE_EQ_OP: |
1480 | 0 | case RVE_IEQ_OP: |
1481 | 0 | *res = v1 == v2; |
1482 | 0 | break; |
1483 | 0 | case RVE_DIFF_OP: |
1484 | 0 | case RVE_IDIFF_OP: |
1485 | 0 | *res = v1 != v2; |
1486 | 0 | break; |
1487 | 0 | case RVE_CONCAT_OP: |
1488 | 0 | *res = 0; |
1489 | | /* invalid operand for int */ |
1490 | 0 | return -1; |
1491 | 0 | default: |
1492 | 0 | LM_BUG("rv unsupported intop %d\n", op); |
1493 | 0 | return -1; |
1494 | 0 | } |
1495 | 0 | return 0; |
1496 | 0 | } |
1497 | | |
1498 | | |
1499 | | /** internal helper: compare 2 RV_STR RVs. |
1500 | | * Warning: rv1 & rv2 must be RV_STR |
1501 | | * @return 0 on success, -1 on error |
1502 | | */ |
1503 | | inline static int bool_rvstrop2( |
1504 | | enum rval_expr_op op, long *res, struct rvalue *rv1, struct rvalue *rv2) |
1505 | 0 | { |
1506 | 0 | str *s1; |
1507 | 0 | str *s2; |
1508 | 0 | regex_t tmp_re; |
1509 | |
|
1510 | 0 | s1 = &rv1->v.s; |
1511 | 0 | s2 = &rv2->v.s; |
1512 | 0 | switch(op) { |
1513 | 0 | case RVE_EQ_OP: |
1514 | 0 | case RVE_STREQ_OP: |
1515 | 0 | *res = (s1->len == s2->len) && (memcmp(s1->s, s2->s, s1->len) == 0); |
1516 | 0 | break; |
1517 | 0 | case RVE_DIFF_OP: |
1518 | 0 | case RVE_STRDIFF_OP: |
1519 | 0 | *res = (s1->len != s2->len) || (memcmp(s1->s, s2->s, s1->len) != 0); |
1520 | 0 | break; |
1521 | 0 | case RVE_MATCH_OP: |
1522 | 0 | if(likely(rv2->flags & RV_RE_F)) { |
1523 | 0 | *res = (regexec(rv2->v.re.regex, rv1->v.s.s, 0, 0, 0) == 0); |
1524 | 0 | } else { |
1525 | | /* we need to compile the RE on the fly */ |
1526 | 0 | if(unlikely(regcomp(&tmp_re, s2->s, |
1527 | 0 | REG_EXTENDED | REG_NOSUB | REG_ICASE))) { |
1528 | | /* error */ |
1529 | 0 | LM_ERR("Bad regular expression \"%s\"\n", s2->s); |
1530 | 0 | goto error; |
1531 | 0 | } |
1532 | 0 | *res = (regexec(&tmp_re, s1->s, 0, 0, 0) == 0); |
1533 | 0 | regfree(&tmp_re); |
1534 | 0 | } |
1535 | 0 | break; |
1536 | 0 | default: |
1537 | 0 | LM_BUG("rv unsupported intop %d\n", op); |
1538 | 0 | goto error; |
1539 | 0 | } |
1540 | 0 | return 0; |
1541 | 0 | error: |
1542 | 0 | *res = 0; /* false */ |
1543 | 0 | return -1; |
1544 | 0 | } |
1545 | | |
1546 | | |
1547 | | /** integer returning operation on string: *res= op str (returns integer) |
1548 | | * @return 0 on success, \<0 on error |
1549 | | */ |
1550 | | inline static int long_strop1(long *res, enum rval_expr_op op, str *s1) |
1551 | 0 | { |
1552 | 0 | switch(op) { |
1553 | 0 | case RVE_STRLEN_OP: |
1554 | 0 | *res = s1->len; |
1555 | 0 | break; |
1556 | 0 | case RVE_STREMPTY_OP: |
1557 | 0 | *res = (s1->len == 0); |
1558 | 0 | break; |
1559 | 0 | default: |
1560 | 0 | LM_BUG("rv unsupported int_strop1 %d\n", op); |
1561 | 0 | *res = 0; |
1562 | 0 | return -1; |
1563 | 0 | } |
1564 | 0 | return 0; |
1565 | 0 | } |
1566 | | |
1567 | | |
1568 | | /** string add operation: ret= l . r (returns a rvalue). |
1569 | | * Can use cached rvalues (c1 & c2). |
1570 | | * @return rvalue on success, 0 on error |
1571 | | */ |
1572 | | inline static struct rvalue *rval_str_add2(struct run_act_ctx *h, |
1573 | | struct sip_msg *msg, struct rvalue *l, struct rval_cache *c1, |
1574 | | struct rvalue *r, struct rval_cache *c2) |
1575 | 0 | { |
1576 | 0 | struct rvalue *rv1; |
1577 | 0 | struct rvalue *rv2; |
1578 | 0 | struct rvalue *ret; |
1579 | 0 | str *s1; |
1580 | 0 | str *s2; |
1581 | 0 | str tmp; |
1582 | 0 | short flags; |
1583 | 0 | int len; |
1584 | |
|
1585 | 0 | rv2 = rv1 = 0; |
1586 | 0 | ret = 0; |
1587 | 0 | flags = 0; |
1588 | 0 | s1 = 0; |
1589 | 0 | s2 = 0; |
1590 | 0 | if((rv1 = rval_convert(h, msg, RV_STR, l, c1)) == 0) |
1591 | 0 | goto error; |
1592 | 0 | if((rv2 = rval_convert(h, msg, RV_STR, r, c2)) == 0) |
1593 | 0 | goto error; |
1594 | | |
1595 | 0 | len = rv1->v.s.len + rv2->v.s.len + 1 /* 0 */; |
1596 | |
|
1597 | 0 | if(rv_chg_in_place(rv1) && (rv1->bsize >= len)) { |
1598 | | /* try reusing rv1 */ |
1599 | 0 | ret = rv1; |
1600 | 0 | rv_ref(ret); |
1601 | 0 | s2 = &rv2->v.s; |
1602 | 0 | if(ret->v.s.s == &ret->buf[0]) |
1603 | 0 | s1 = 0; |
1604 | 0 | else { |
1605 | 0 | tmp = ret->v.s; |
1606 | 0 | flags = ret->flags; |
1607 | 0 | ret->flags &= ~RV_CNT_ALLOCED_F; |
1608 | 0 | ret->v.s.s = &ret->buf[0]; |
1609 | 0 | ret->v.s.len = 0; |
1610 | 0 | s1 = &tmp; |
1611 | 0 | } |
1612 | 0 | } else if(rv_chg_in_place(rv2) && (rv2->bsize >= len)) { |
1613 | | /* try reusing rv2 */ |
1614 | 0 | ret = rv2; |
1615 | 0 | rv_ref(ret); |
1616 | 0 | s1 = &rv1->v.s; |
1617 | 0 | if(ret->v.s.s == &ret->buf[0]) |
1618 | 0 | s2 = &ret->v.s; |
1619 | 0 | else { |
1620 | 0 | tmp = ret->v.s; |
1621 | 0 | flags = ret->flags; |
1622 | 0 | ret->flags &= ~RV_CNT_ALLOCED_F; |
1623 | 0 | ret->v.s.s = &ret->buf[0]; |
1624 | 0 | ret->v.s.len = 0; |
1625 | 0 | s2 = &tmp; |
1626 | 0 | } |
1627 | 0 | } else if((l->type == RV_STR) && (rv_chg_in_place(l)) |
1628 | 0 | && (l->bsize >= len)) { |
1629 | 0 | ret = l; |
1630 | 0 | rv_ref(ret); |
1631 | 0 | s2 = &rv2->v.s; |
1632 | 0 | if(ret->v.s.s == &ret->buf[0]) |
1633 | 0 | s1 = 0; |
1634 | 0 | else { |
1635 | 0 | tmp = ret->v.s; |
1636 | 0 | flags = ret->flags; |
1637 | 0 | ret->flags &= ~RV_CNT_ALLOCED_F; |
1638 | 0 | ret->v.s.s = &ret->buf[0]; |
1639 | 0 | ret->v.s.len = 0; |
1640 | 0 | s1 = &tmp; |
1641 | 0 | } |
1642 | 0 | } else if((r->type == RV_STR) |
1643 | 0 | && (rv_chg_in_place(r) && (r->bsize >= len))) { |
1644 | 0 | ret = r; |
1645 | 0 | rv_ref(ret); |
1646 | 0 | s1 = &rv1->v.s; |
1647 | 0 | if(ret->v.s.s == &ret->buf[0]) |
1648 | 0 | s2 = &ret->v.s; |
1649 | 0 | else { |
1650 | 0 | tmp = ret->v.s; |
1651 | 0 | flags = ret->flags; |
1652 | 0 | ret->flags &= ~RV_CNT_ALLOCED_F; |
1653 | 0 | ret->v.s.s = &ret->buf[0]; |
1654 | 0 | ret->v.s.len = 0; |
1655 | 0 | s2 = &tmp; |
1656 | 0 | } |
1657 | 0 | } else { |
1658 | 0 | ret = rval_new(RV_STR, &rv1->v, len + RV_STR_EXTRA); |
1659 | 0 | if(unlikely(ret == 0)) { |
1660 | 0 | LM_ERR("rv eval out of memory\n"); |
1661 | 0 | goto error; |
1662 | 0 | } |
1663 | 0 | s1 = 0; |
1664 | 0 | s2 = &rv2->v.s; |
1665 | 0 | } |
1666 | | /* do the actual copy */ |
1667 | 0 | memmove(ret->buf + rv1->v.s.len, s2->s, s2->len); |
1668 | 0 | if(s1) { |
1669 | 0 | memcpy(ret->buf, s1->s, s1->len); |
1670 | 0 | } |
1671 | 0 | ret->v.s.len = rv1->v.s.len + s2->len; |
1672 | 0 | ret->v.s.s[ret->v.s.len] = 0; |
1673 | | /* cleanup if needed */ |
1674 | 0 | if(flags & RV_CNT_ALLOCED_F) |
1675 | 0 | pkg_free(tmp.s); |
1676 | 0 | rval_destroy(rv1); |
1677 | 0 | rval_destroy(rv2); |
1678 | 0 | return ret; |
1679 | 0 | error: |
1680 | 0 | rval_destroy(rv1); |
1681 | 0 | rval_destroy(rv2); |
1682 | 0 | return 0; |
1683 | 0 | } |
1684 | | |
1685 | | |
1686 | | /** bool operation on rval evaluated as strings. |
1687 | | * Can use cached rvalues (c1 & c2). |
1688 | | * @return 0 success, -1 on error |
1689 | | */ |
1690 | | inline static int rval_str_lop2(struct run_act_ctx *h, struct sip_msg *msg, |
1691 | | long *res, enum rval_expr_op op, struct rvalue *l, |
1692 | | struct rval_cache *c1, struct rvalue *r, struct rval_cache *c2) |
1693 | 0 | { |
1694 | 0 | struct rvalue *rv1; |
1695 | 0 | struct rvalue *rv2; |
1696 | 0 | int ret; |
1697 | |
|
1698 | 0 | rv2 = rv1 = 0; |
1699 | 0 | ret = 0; |
1700 | 0 | if((rv1 = rval_convert(h, msg, RV_STR, l, c1)) == 0) |
1701 | 0 | goto error; |
1702 | 0 | if((rv2 = rval_convert(h, msg, RV_STR, r, c2)) == 0) |
1703 | 0 | goto error; |
1704 | 0 | ret = bool_rvstrop2(op, res, rv1, rv2); |
1705 | 0 | rval_destroy(rv1); |
1706 | 0 | rval_destroy(rv2); |
1707 | 0 | return ret; |
1708 | 0 | error: |
1709 | 0 | rval_destroy(rv1); |
1710 | 0 | rval_destroy(rv2); |
1711 | 0 | return 0; |
1712 | 0 | } |
1713 | | |
1714 | | |
1715 | | /** |
1716 | | * @brief Integer operation on rval evaluated as string |
1717 | | * |
1718 | | * Integer operation on rval evaluated as string, can use cached |
1719 | | * rvalues (c1 & c2). |
1720 | | * @param h run action context |
1721 | | * @param msg SIP message |
1722 | | * @param res will be set to the result |
1723 | | * @param op rvalue expression operation |
1724 | | * @param l rvalue |
1725 | | * @param c1 rvalue cache |
1726 | | * @return 0 success, -1 on error |
1727 | | */ |
1728 | | inline static int rval_long_strop1(struct run_act_ctx *h, struct sip_msg *msg, |
1729 | | long *res, enum rval_expr_op op, struct rvalue *l, |
1730 | | struct rval_cache *c1) |
1731 | 0 | { |
1732 | 0 | struct rvalue *rv1; |
1733 | 0 | int ret; |
1734 | |
|
1735 | 0 | rv1 = 0; |
1736 | 0 | ret = 0; |
1737 | 0 | if((rv1 = rval_convert(h, msg, RV_STR, l, c1)) == 0) |
1738 | 0 | goto error; |
1739 | 0 | ret = long_strop1(res, op, &rv1->v.s); |
1740 | 0 | rval_destroy(rv1); |
1741 | 0 | return ret; |
1742 | 0 | error: |
1743 | 0 | *res = 0; |
1744 | 0 | rval_destroy(rv1); |
1745 | 0 | return -1; |
1746 | 0 | } |
1747 | | |
1748 | | |
1749 | | /** |
1750 | | * @brief Checks if rv is defined |
1751 | | * @param h run action context |
1752 | | * @param msg SIP message |
1753 | | * @param res set to the result 1 is defined, 0 not defined |
1754 | | * @param rv rvalue |
1755 | | * @param cache rvalue cache |
1756 | | * @return 0 on success, -1 on error |
1757 | | * @note Can use cached rvalues (cache). A rv can be undefined if it's |
1758 | | * an undefined avp or pvar or select or if it's NONE |
1759 | | * @note An error in the avp, pvar or select search is equivalent to |
1760 | | * undefined (and it's not reported) |
1761 | | */ |
1762 | | inline static int rv_defined(struct run_act_ctx *h, struct sip_msg *msg, |
1763 | | long *res, struct rvalue *rv, struct rval_cache *cache) |
1764 | 0 | { |
1765 | 0 | avp_t *r_avp; |
1766 | 0 | int_str avp_val; |
1767 | 0 | pv_value_t pval; |
1768 | 0 | str tmp; |
1769 | |
|
1770 | 0 | *res = 1; |
1771 | 0 | switch(rv->type) { |
1772 | 0 | case RV_SEL: |
1773 | 0 | if(unlikely(cache && cache->cache_type == RV_CACHE_SELECT)) { |
1774 | 0 | *res = (cache->val_type != RV_NONE); |
1775 | 0 | } else |
1776 | | /* run select returns 0 on success, -1 on error and >0 on |
1777 | | * undefined. error is considered undefined */ |
1778 | 0 | *res = (run_select(&tmp, &rv->v.sel, msg) == 0); |
1779 | 0 | break; |
1780 | 0 | case RV_AVP: |
1781 | 0 | if(unlikely(cache && cache->cache_type == RV_CACHE_AVP)) { |
1782 | 0 | *res = (cache->val_type != RV_NONE); |
1783 | 0 | } else { |
1784 | 0 | r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name, |
1785 | 0 | &avp_val, rv->v.avps.index); |
1786 | 0 | if(unlikely(r_avp == 0)) { |
1787 | 0 | *res = 0; |
1788 | 0 | } |
1789 | 0 | } |
1790 | 0 | break; |
1791 | 0 | case RV_PVAR: |
1792 | | /* PV_VAL_NULL or pv_get_spec_value error => undef */ |
1793 | 0 | if(unlikely(cache && cache->cache_type == RV_CACHE_PVAR)) { |
1794 | 0 | *res = (cache->val_type != RV_NONE); |
1795 | 0 | } else { |
1796 | 0 | memset(&pval, 0, sizeof(pval)); |
1797 | 0 | if(likely(pv_get_spec_value(msg, &rv->v.pvs, &pval) == 0)) { |
1798 | 0 | if((pval.flags & PV_VAL_NULL) |
1799 | 0 | && !(pval.flags & (PV_VAL_INT | PV_VAL_STR))) { |
1800 | 0 | *res = 0; |
1801 | 0 | } |
1802 | 0 | pv_value_destroy(&pval); |
1803 | 0 | } else { |
1804 | 0 | *res = 0; /* in case of error, consider it undef */ |
1805 | 0 | } |
1806 | 0 | } |
1807 | 0 | break; |
1808 | 0 | case RV_NONE: |
1809 | 0 | *res = 0; |
1810 | 0 | break; |
1811 | 0 | default: |
1812 | 0 | break; |
1813 | 0 | } |
1814 | 0 | return 0; |
1815 | 0 | } |
1816 | | |
1817 | | |
1818 | | /** |
1819 | | * @brief Defined (integer) operation on rve |
1820 | | * @param h run action context |
1821 | | * @param msg SIP message |
1822 | | * @param res - set to 1 defined, 0 not defined |
1823 | | * @param rve rvalue expression |
1824 | | * @return 0 on success, -1 on error |
1825 | | */ |
1826 | | inline static int long_rve_defined(struct run_act_ctx *h, struct sip_msg *msg, |
1827 | | long *res, struct rval_expr *rve) |
1828 | 0 | { |
1829 | | /* only a rval can be undefined, any expression consisting on more |
1830 | | * then one rval => defined */ |
1831 | 0 | if(likely(rve->op == RVE_RVAL_OP)) |
1832 | 0 | return rv_defined(h, msg, res, &rve->left.rval, 0); |
1833 | 0 | *res = 1; |
1834 | 0 | return 0; |
1835 | 0 | } |
1836 | | |
1837 | | |
1838 | | /** evals a long expr to a long. |
1839 | | * |
1840 | | * *res=(int)eval(rve) |
1841 | | * @return 0 on success, \<0 on error |
1842 | | */ |
1843 | | int rval_expr_eval_long(struct run_act_ctx *h, struct sip_msg *msg, long *res, |
1844 | | struct rval_expr *rve) |
1845 | 0 | { |
1846 | 0 | long i1, i2, ret; |
1847 | 0 | struct rval_cache c1, c2; |
1848 | 0 | struct rvalue *rv1; |
1849 | 0 | struct rvalue *rv2; |
1850 | |
|
1851 | 0 | ret = -1; |
1852 | 0 | switch(rve->op) { |
1853 | 0 | case RVE_RVAL_OP: |
1854 | 0 | ret = rval_get_long(h, msg, res, &rve->left.rval, 0); |
1855 | 0 | rval_get_long_handle_ret(ret, |
1856 | 0 | "rval expression conversion to int" |
1857 | 0 | " failed", |
1858 | 0 | rve); |
1859 | 0 | break; |
1860 | 0 | case RVE_UMINUS_OP: |
1861 | 0 | case RVE_BOOL_OP: |
1862 | 0 | case RVE_LNOT_OP: |
1863 | 0 | case RVE_BNOT_OP: |
1864 | 0 | if(unlikely((ret = rval_expr_eval_long(h, msg, &i1, rve->left.rve)) |
1865 | 0 | < 0)) |
1866 | 0 | break; |
1867 | 0 | ret = long_longop1(res, rve->op, i1); |
1868 | 0 | break; |
1869 | 0 | case RVE_LONG_OP: |
1870 | 0 | ret = rval_expr_eval_long(h, msg, res, rve->left.rve); |
1871 | 0 | break; |
1872 | 0 | case RVE_MUL_OP: |
1873 | 0 | case RVE_DIV_OP: |
1874 | 0 | case RVE_MOD_OP: |
1875 | 0 | case RVE_MINUS_OP: |
1876 | 0 | case RVE_PLUS_OP: |
1877 | 0 | case RVE_IPLUS_OP: |
1878 | 0 | case RVE_BOR_OP: |
1879 | 0 | case RVE_BAND_OP: |
1880 | 0 | case RVE_BXOR_OP: |
1881 | 0 | case RVE_BLSHIFT_OP: |
1882 | 0 | case RVE_BRSHIFT_OP: |
1883 | 0 | case RVE_GT_OP: |
1884 | 0 | case RVE_GTE_OP: |
1885 | 0 | case RVE_LT_OP: |
1886 | 0 | case RVE_LTE_OP: |
1887 | 0 | case RVE_IEQ_OP: |
1888 | 0 | case RVE_IDIFF_OP: |
1889 | 0 | if(unlikely((ret = rval_expr_eval_long(h, msg, &i1, rve->left.rve)) |
1890 | 0 | < 0)) |
1891 | 0 | break; |
1892 | 0 | if(unlikely((ret = rval_expr_eval_long(h, msg, &i2, rve->right.rve)) |
1893 | 0 | < 0)) |
1894 | 0 | break; |
1895 | 0 | ret = long_longop2(res, rve->op, i1, i2); |
1896 | 0 | break; |
1897 | 0 | case RVE_LAND_OP: |
1898 | 0 | if(unlikely((ret = rval_expr_eval_long(h, msg, &i1, rve->left.rve)) |
1899 | 0 | < 0)) |
1900 | 0 | break; |
1901 | 0 | if(i1 == 0) { |
1902 | 0 | *res = 0; |
1903 | 0 | } else { |
1904 | 0 | if(unlikely((ret = rval_expr_eval_long( |
1905 | 0 | h, msg, &i2, rve->right.rve)) |
1906 | 0 | < 0)) |
1907 | 0 | break; |
1908 | 0 | *res = i1 && i2; |
1909 | 0 | } |
1910 | 0 | ret = 0; |
1911 | 0 | break; |
1912 | 0 | case RVE_LOR_OP: |
1913 | 0 | if(unlikely((ret = rval_expr_eval_long(h, msg, &i1, rve->left.rve)) |
1914 | 0 | < 0)) |
1915 | 0 | break; |
1916 | 0 | if(i1) { |
1917 | 0 | *res = 1; |
1918 | 0 | } else { |
1919 | 0 | if(unlikely((ret = rval_expr_eval_long( |
1920 | 0 | h, msg, &i2, rve->right.rve)) |
1921 | 0 | < 0)) |
1922 | 0 | break; |
1923 | 0 | *res = i1 || i2; |
1924 | 0 | } |
1925 | 0 | ret = 0; |
1926 | 0 | break; |
1927 | 0 | case RVE_EQ_OP: |
1928 | 0 | case RVE_DIFF_OP: |
1929 | | /* if left is string, eval left & right as string and |
1930 | | * use string diff. |
1931 | | * if left is int eval as int using int diff |
1932 | | * if left is undef, look at right and convert to right type |
1933 | | */ |
1934 | 0 | rval_cache_init(&c1); |
1935 | 0 | if(unlikely((ret = rval_expr_eval_rvlong( |
1936 | 0 | h, msg, &rv1, &i1, rve->left.rve, &c1)) |
1937 | 0 | < 0)) { |
1938 | | /* error */ |
1939 | 0 | rval_cache_clean(&c1); |
1940 | 0 | break; |
1941 | 0 | } |
1942 | 0 | if(likely(rv1 == 0)) { |
1943 | | /* int */ |
1944 | 0 | rval_cache_clean(&c1); |
1945 | 0 | if(unlikely((ret = rval_expr_eval_long( |
1946 | 0 | h, msg, &i2, rve->right.rve)) |
1947 | 0 | < 0)) |
1948 | 0 | break; /* error */ |
1949 | 0 | ret = long_longop2(res, rve->op, i1, i2); |
1950 | 0 | } else { |
1951 | | /* not int => str or undef */ |
1952 | | /* check for undefined left operand */ |
1953 | 0 | if(unlikely(c1.cache_type != RV_CACHE_EMPTY |
1954 | 0 | && c1.val_type == RV_NONE)) { |
1955 | | #ifdef UNDEF_EQ_ALWAYS_FALSE |
1956 | | /* undef == something always false |
1957 | | * undef != something always true*/ |
1958 | | ret = (rve->op == RVE_DIFF_OP); |
1959 | | #elif defined UNDEF_EQ_UNDEF_TRUE |
1960 | | /* undef == something defined always false |
1961 | | * undef == undef true */ |
1962 | | if(int_rve_defined(h, msg, &i2, rve->right.rve) < 0) { |
1963 | | /* error */ |
1964 | | rval_cache_clean(&c1); |
1965 | | rval_destroy(rv1); |
1966 | | break; |
1967 | | } |
1968 | | ret = (!i2) ^ (rve->op == RVE_DIFF_OP); |
1969 | | #else /* ! UNDEF_EQ_* */ |
1970 | | /* undef == val |
1971 | | * => convert to (type_of(val)) (undef) == val */ |
1972 | 0 | rval_cache_init(&c2); |
1973 | 0 | if(unlikely((ret = rval_expr_eval_rvlong(h, msg, &rv2, &i2, |
1974 | 0 | rve->right.rve, &c2)) |
1975 | 0 | < 0)) { |
1976 | | /* error */ |
1977 | 0 | rval_cache_clean(&c1); |
1978 | 0 | rval_cache_clean(&c2); |
1979 | 0 | rval_destroy(rv1); |
1980 | 0 | break; |
1981 | 0 | } |
1982 | 0 | if(rv2 == 0) { |
1983 | | /* int */ |
1984 | 0 | ret = long_longop2(res, rve->op, 0 /* undef */, i2); |
1985 | 0 | } else { |
1986 | | /* str or undef */ |
1987 | 0 | ret = rval_str_lop2( |
1988 | 0 | h, msg, res, rve->op, rv1, &c1, rv2, &c2); |
1989 | 0 | rval_cache_clean(&c2); |
1990 | 0 | rval_destroy(rv2); |
1991 | 0 | } |
1992 | 0 | #endif /* UNDEF_EQ_* */ |
1993 | 0 | rval_cache_clean(&c1); |
1994 | 0 | rval_destroy(rv1); |
1995 | 0 | } else { |
1996 | | /* left value == defined and != int => str |
1997 | | * => lval == (str) val */ |
1998 | 0 | if(unlikely((rv2 = rval_expr_eval(h, msg, rve->right.rve)) |
1999 | 0 | == 0)) { |
2000 | | /* error */ |
2001 | 0 | rval_destroy(rv1); |
2002 | 0 | rval_cache_clean(&c1); |
2003 | 0 | break; |
2004 | 0 | } |
2005 | 0 | ret = rval_str_lop2(h, msg, res, rve->op, rv1, &c1, rv2, 0); |
2006 | 0 | rval_cache_clean(&c1); |
2007 | 0 | rval_destroy(rv1); |
2008 | 0 | rval_destroy(rv2); |
2009 | 0 | } |
2010 | 0 | } |
2011 | 0 | break; |
2012 | 0 | case RVE_CONCAT_OP: |
2013 | | /* eval expression => string */ |
2014 | 0 | if(unlikely((rv1 = rval_expr_eval(h, msg, rve)) == 0)) { |
2015 | 0 | ret = -1; |
2016 | 0 | break; |
2017 | 0 | } |
2018 | | /* convert to int */ |
2019 | 0 | ret = rval_get_long(h, msg, res, rv1, 0); /* convert to int */ |
2020 | 0 | rval_get_long_handle_ret(ret, |
2021 | 0 | "rval expression conversion to int" |
2022 | 0 | " failed", |
2023 | 0 | rve); |
2024 | 0 | rval_destroy(rv1); |
2025 | 0 | break; |
2026 | 0 | case RVE_STR_OP: |
2027 | | /* (str)expr => eval expression */ |
2028 | 0 | rval_cache_init(&c1); |
2029 | 0 | if(unlikely((ret = rval_expr_eval_rvlong( |
2030 | 0 | h, msg, &rv1, res, rve->left.rve, &c1)) |
2031 | 0 | < 0)) { |
2032 | | /* error */ |
2033 | 0 | rval_cache_clean(&c1); |
2034 | 0 | break; |
2035 | 0 | } |
2036 | 0 | if(unlikely(rv1)) { |
2037 | | /* expr evaluated to string => (int)(str)v == (int)v */ |
2038 | 0 | ret = rval_get_long(h, msg, res, rv1, &c1); /* convert to int */ |
2039 | 0 | rval_get_long_handle_ret(ret, |
2040 | 0 | "rval expression conversion" |
2041 | 0 | " to int failed", |
2042 | 0 | rve); |
2043 | 0 | rval_destroy(rv1); |
2044 | 0 | rval_cache_clean(&c1); |
2045 | 0 | } |
2046 | 0 | break; |
2047 | | |
2048 | 0 | case RVE_DEFINED_OP: |
2049 | 0 | ret = long_rve_defined(h, msg, res, rve->left.rve); |
2050 | 0 | break; |
2051 | 0 | case RVE_NOTDEFINED_OP: |
2052 | 0 | ret = long_rve_defined(h, msg, res, rve->left.rve); |
2053 | 0 | *res = !(*res); |
2054 | 0 | break; |
2055 | 0 | case RVE_STREQ_OP: |
2056 | 0 | case RVE_STRDIFF_OP: |
2057 | 0 | case RVE_MATCH_OP: |
2058 | 0 | if(unlikely((rv1 = rval_expr_eval(h, msg, rve->left.rve)) == 0)) { |
2059 | 0 | ret = -1; |
2060 | 0 | break; |
2061 | 0 | } |
2062 | 0 | if(unlikely((rv2 = rval_expr_eval(h, msg, rve->right.rve)) == 0)) { |
2063 | 0 | rval_destroy(rv1); |
2064 | 0 | ret = -1; |
2065 | 0 | break; |
2066 | 0 | } |
2067 | 0 | ret = rval_str_lop2(h, msg, res, rve->op, rv1, 0, rv2, 0); |
2068 | 0 | rval_destroy(rv1); |
2069 | 0 | rval_destroy(rv2); |
2070 | 0 | break; |
2071 | 0 | case RVE_STRLEN_OP: |
2072 | 0 | case RVE_STREMPTY_OP: |
2073 | 0 | if(unlikely((rv1 = rval_expr_eval(h, msg, rve->left.rve)) == 0)) { |
2074 | 0 | ret = -1; |
2075 | 0 | break; |
2076 | 0 | } |
2077 | 0 | ret = rval_long_strop1(h, msg, res, rve->op, rv1, 0); |
2078 | 0 | rval_destroy(rv1); |
2079 | 0 | break; |
2080 | 0 | case RVE_SELVALEXP_OP: |
2081 | 0 | case RVE_SELVALOPT_OP: |
2082 | 0 | LM_BUG("invalid selval int expression operation %d (%d,%d-%d,%d)\n", |
2083 | 0 | rve->op, rve->fpos.s_line, rve->fpos.s_col, |
2084 | 0 | rve->fpos.e_line, rve->fpos.e_col); |
2085 | 0 | ret = -1; |
2086 | 0 | break; |
2087 | 0 | case RVE_NONE_OP: |
2088 | | /*default:*/ |
2089 | 0 | LM_BUG("invalid rval int expression operation %d (%d,%d-%d,%d)\n", |
2090 | 0 | rve->op, rve->fpos.s_line, rve->fpos.s_col, |
2091 | 0 | rve->fpos.e_line, rve->fpos.e_col); |
2092 | 0 | ret = -1; |
2093 | 0 | }; |
2094 | 0 | return ret; |
2095 | 0 | } |
2096 | | |
2097 | | |
2098 | | /** |
2099 | | * @brief Evals a rval expression into an int or another rv(str) |
2100 | | * @warning rv result (rv_res) must be rval_destroy()'ed if non-null |
2101 | | * (it might be a reference to another rval). The result can be |
2102 | | * modified only if rv_chg_in_place() returns true. |
2103 | | * @param h run action context |
2104 | | * @param msg SIP message |
2105 | | * @param res_rv pointer to rvalue result, if non-null it means the |
2106 | | * expression evaluated to a non-int (str), which will be stored here. |
2107 | | * @param res_i pointer to int result, if res_rv==0 and the function |
2108 | | * returns success => the result is an int which will be stored here. |
2109 | | * @param rve expression that will be evaluated. |
2110 | | * @param cache write-only value cache, it might be filled if non-null and |
2111 | | * empty (rval_cache_init()). If non-null, it _must_ be rval_cache_clean()'ed |
2112 | | * when done. |
2113 | | * @return 0 on success, -1 on error, sets *res_rv or *res_i. |
2114 | | */ |
2115 | | int rval_expr_eval_rvlong(struct run_act_ctx *h, struct sip_msg *msg, |
2116 | | struct rvalue **res_rv, long *res_i, struct rval_expr *rve, |
2117 | | struct rval_cache *cache) |
2118 | 0 | { |
2119 | 0 | struct rvalue *rv1; |
2120 | 0 | struct rvalue *rv2; |
2121 | 0 | struct rval_cache c1; /* local cache */ |
2122 | 0 | int ret; |
2123 | 0 | long r, i, j; |
2124 | 0 | enum rval_type type; |
2125 | |
|
2126 | 0 | rv1 = 0; |
2127 | 0 | rv2 = 0; |
2128 | 0 | ret = -1; |
2129 | 0 | switch(rve->op) { |
2130 | 0 | case RVE_RVAL_OP: |
2131 | 0 | rv1 = &rve->left.rval; |
2132 | 0 | rv_ref(rv1); |
2133 | 0 | type = rval_get_btype(h, msg, rv1, cache); |
2134 | 0 | if(type == RV_LONG) { |
2135 | 0 | r = rval_get_long(h, msg, res_i, rv1, cache); |
2136 | 0 | rval_get_long_handle_ret(r, |
2137 | 0 | "rval expression conversion" |
2138 | 0 | " to int failed", |
2139 | 0 | rve); |
2140 | 0 | *res_rv = 0; |
2141 | 0 | ret = r; /* equiv. to if (r<0) goto error */ |
2142 | 0 | } else { |
2143 | | /* RV_STR, RV_PVAR, RV_AVP a.s.o => return rv1 and the |
2144 | | * cached resolved value in cache*/ |
2145 | 0 | *res_rv = rv1; |
2146 | 0 | rv_ref(rv1); |
2147 | 0 | ret = 0; |
2148 | 0 | } |
2149 | 0 | break; |
2150 | 0 | case RVE_UMINUS_OP: |
2151 | 0 | case RVE_BOOL_OP: |
2152 | 0 | case RVE_LNOT_OP: |
2153 | 0 | case RVE_BNOT_OP: |
2154 | 0 | case RVE_MINUS_OP: |
2155 | 0 | case RVE_MUL_OP: |
2156 | 0 | case RVE_DIV_OP: |
2157 | 0 | case RVE_MOD_OP: |
2158 | 0 | case RVE_BOR_OP: |
2159 | 0 | case RVE_BAND_OP: |
2160 | 0 | case RVE_BXOR_OP: |
2161 | 0 | case RVE_BLSHIFT_OP: |
2162 | 0 | case RVE_BRSHIFT_OP: |
2163 | 0 | case RVE_LAND_OP: |
2164 | 0 | case RVE_LOR_OP: |
2165 | 0 | case RVE_GT_OP: |
2166 | 0 | case RVE_GTE_OP: |
2167 | 0 | case RVE_LT_OP: |
2168 | 0 | case RVE_LTE_OP: |
2169 | 0 | case RVE_EQ_OP: |
2170 | 0 | case RVE_DIFF_OP: |
2171 | 0 | case RVE_IEQ_OP: |
2172 | 0 | case RVE_IDIFF_OP: |
2173 | 0 | case RVE_IPLUS_OP: |
2174 | 0 | case RVE_STREQ_OP: |
2175 | 0 | case RVE_STRDIFF_OP: |
2176 | 0 | case RVE_MATCH_OP: |
2177 | 0 | case RVE_STRLEN_OP: |
2178 | 0 | case RVE_STREMPTY_OP: |
2179 | 0 | case RVE_DEFINED_OP: |
2180 | 0 | case RVE_NOTDEFINED_OP: |
2181 | 0 | case RVE_LONG_OP: |
2182 | | /* operator forces integer type */ |
2183 | 0 | ret = rval_expr_eval_long(h, msg, res_i, rve); |
2184 | 0 | *res_rv = 0; |
2185 | 0 | break; |
2186 | 0 | case RVE_PLUS_OP: |
2187 | 0 | rval_cache_init(&c1); |
2188 | 0 | r = rval_expr_eval_rvlong(h, msg, &rv1, &i, rve->left.rve, &c1); |
2189 | 0 | if(unlikely(r < 0)) { |
2190 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2191 | 0 | rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col, |
2192 | 0 | rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col); |
2193 | 0 | rval_cache_clean(&c1); |
2194 | 0 | goto error; |
2195 | 0 | } |
2196 | 0 | if(rv1 == 0) { |
2197 | 0 | if(unlikely( |
2198 | 0 | (r = rval_expr_eval_long(h, msg, &j, rve->right.rve)) |
2199 | 0 | < 0)) { |
2200 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)" |
2201 | 0 | "\n", |
2202 | 0 | rve->right.rve->fpos.s_line, |
2203 | 0 | rve->right.rve->fpos.s_col, |
2204 | 0 | rve->right.rve->fpos.e_line, |
2205 | 0 | rve->right.rve->fpos.e_col); |
2206 | 0 | rval_cache_clean(&c1); |
2207 | 0 | goto error; |
2208 | 0 | } |
2209 | 0 | ret = long_longop2(res_i, rve->op, i, j); |
2210 | 0 | *res_rv = 0; |
2211 | 0 | } else { |
2212 | 0 | rv2 = rval_expr_eval(h, msg, rve->right.rve); |
2213 | 0 | if(unlikely(rv2 == 0)) { |
2214 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2215 | 0 | rve->right.rve->fpos.s_line, |
2216 | 0 | rve->right.rve->fpos.s_col, |
2217 | 0 | rve->right.rve->fpos.e_line, |
2218 | 0 | rve->right.rve->fpos.e_col); |
2219 | 0 | rval_cache_clean(&c1); |
2220 | 0 | goto error; |
2221 | 0 | } |
2222 | 0 | *res_rv = rval_str_add2(h, msg, rv1, &c1, rv2, 0); |
2223 | 0 | ret = -(*res_rv == 0); |
2224 | 0 | } |
2225 | 0 | rval_cache_clean(&c1); |
2226 | 0 | break; |
2227 | 0 | case RVE_CONCAT_OP: |
2228 | 0 | case RVE_STR_OP: |
2229 | 0 | *res_rv = rval_expr_eval(h, msg, rve); |
2230 | 0 | ret = -(*res_rv == 0); |
2231 | 0 | break; |
2232 | 0 | case RVE_SELVALEXP_OP: |
2233 | 0 | case RVE_SELVALOPT_OP: |
2234 | 0 | LM_BUG("invalid rval selval expression operation %d " |
2235 | 0 | "(%d,%d-%d,%d)\n", |
2236 | 0 | rve->op, rve->fpos.s_line, rve->fpos.s_col, |
2237 | 0 | rve->fpos.e_line, rve->fpos.e_col); |
2238 | 0 | goto error; |
2239 | 0 | case RVE_NONE_OP: |
2240 | | /*default:*/ |
2241 | 0 | LM_BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n", |
2242 | 0 | rve->op, rve->fpos.s_line, rve->fpos.s_col, |
2243 | 0 | rve->fpos.e_line, rve->fpos.e_col); |
2244 | 0 | goto error; |
2245 | 0 | }; |
2246 | 0 | rval_destroy(rv1); |
2247 | 0 | rval_destroy(rv2); |
2248 | 0 | return ret; |
2249 | 0 | error: |
2250 | 0 | rval_destroy(rv1); |
2251 | 0 | rval_destroy(rv2); |
2252 | 0 | return -1; |
2253 | 0 | } |
2254 | | |
2255 | | |
2256 | | /** |
2257 | | * @brief Evals a rval expression |
2258 | | * @warning result must be rval_destroy()'ed if non-null (it might be |
2259 | | * a reference to another rval). The result can be modified only |
2260 | | * if rv_chg_in_place() returns true. |
2261 | | * @param h run action context |
2262 | | * @param msg SIP message |
2263 | | * @param rve rvalue expression |
2264 | | * @return rvalue on success, 0 on error |
2265 | | */ |
2266 | | struct rvalue *rval_expr_eval( |
2267 | | struct run_act_ctx *h, struct sip_msg *msg, struct rval_expr *rve) |
2268 | 0 | { |
2269 | 0 | struct rvalue *rv1; |
2270 | 0 | struct rvalue *rv2; |
2271 | 0 | struct rvalue *ret; |
2272 | 0 | struct rval_cache c1; |
2273 | 0 | union rval_val v; |
2274 | 0 | long r, i, j; |
2275 | 0 | enum rval_type type; |
2276 | |
|
2277 | 0 | rv1 = 0; |
2278 | 0 | rv2 = 0; |
2279 | 0 | ret = 0; |
2280 | 0 | switch(rve->op) { |
2281 | 0 | case RVE_RVAL_OP: |
2282 | 0 | rv_ref(&rve->left.rval); |
2283 | 0 | return &rve->left.rval; |
2284 | 0 | break; |
2285 | 0 | case RVE_UMINUS_OP: |
2286 | 0 | case RVE_BOOL_OP: |
2287 | 0 | case RVE_LNOT_OP: |
2288 | 0 | case RVE_BNOT_OP: |
2289 | 0 | case RVE_MINUS_OP: |
2290 | 0 | case RVE_MUL_OP: |
2291 | 0 | case RVE_DIV_OP: |
2292 | 0 | case RVE_MOD_OP: |
2293 | 0 | case RVE_BOR_OP: |
2294 | 0 | case RVE_BAND_OP: |
2295 | 0 | case RVE_BXOR_OP: |
2296 | 0 | case RVE_BLSHIFT_OP: |
2297 | 0 | case RVE_BRSHIFT_OP: |
2298 | 0 | case RVE_LAND_OP: |
2299 | 0 | case RVE_LOR_OP: |
2300 | 0 | case RVE_GT_OP: |
2301 | 0 | case RVE_GTE_OP: |
2302 | 0 | case RVE_LT_OP: |
2303 | 0 | case RVE_LTE_OP: |
2304 | 0 | case RVE_EQ_OP: |
2305 | 0 | case RVE_DIFF_OP: |
2306 | 0 | case RVE_IEQ_OP: |
2307 | 0 | case RVE_IDIFF_OP: |
2308 | 0 | case RVE_IPLUS_OP: |
2309 | 0 | case RVE_STREQ_OP: |
2310 | 0 | case RVE_STRDIFF_OP: |
2311 | 0 | case RVE_MATCH_OP: |
2312 | 0 | case RVE_STRLEN_OP: |
2313 | 0 | case RVE_STREMPTY_OP: |
2314 | 0 | case RVE_DEFINED_OP: |
2315 | 0 | case RVE_NOTDEFINED_OP: |
2316 | 0 | case RVE_LONG_OP: |
2317 | | /* operator forces integer type */ |
2318 | 0 | r = rval_expr_eval_long(h, msg, &i, rve); |
2319 | 0 | if(likely(r == 0)) { |
2320 | 0 | v.l = i; |
2321 | 0 | ret = rval_new(RV_LONG, &v, 0); |
2322 | 0 | if(unlikely(ret == 0)) { |
2323 | 0 | LM_ERR("rv eval int expression: out of memory\n"); |
2324 | 0 | goto error; |
2325 | 0 | } |
2326 | 0 | return ret; |
2327 | 0 | } else { |
2328 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2329 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
2330 | 0 | rve->fpos.e_col); |
2331 | 0 | goto error; |
2332 | 0 | } |
2333 | 0 | break; |
2334 | 0 | case RVE_PLUS_OP: |
2335 | 0 | rv1 = rval_expr_eval(h, msg, rve->left.rve); |
2336 | 0 | if(unlikely(rv1 == 0)) { |
2337 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2338 | 0 | rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col, |
2339 | 0 | rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col); |
2340 | 0 | goto error; |
2341 | 0 | } |
2342 | 0 | rval_cache_init(&c1); |
2343 | 0 | type = rval_get_btype(h, msg, rv1, &c1); |
2344 | 0 | switch(type) { |
2345 | 0 | case RV_LONG: |
2346 | 0 | r = rval_get_long(h, msg, &i, rv1, &c1); |
2347 | 0 | rval_get_long_handle_ret(r, |
2348 | 0 | "rval expression left side " |
2349 | 0 | "conversion to int failed", |
2350 | 0 | rve); |
2351 | 0 | if(unlikely(r < 0)) { |
2352 | 0 | rval_cache_clean(&c1); |
2353 | 0 | goto error; |
2354 | 0 | } |
2355 | 0 | if(unlikely((r = rval_expr_eval_long( |
2356 | 0 | h, msg, &j, rve->right.rve)) |
2357 | 0 | < 0)) { |
2358 | 0 | rval_cache_clean(&c1); |
2359 | 0 | LM_ERR("rval expression evaluation failed " |
2360 | 0 | "(%d,%d-%d,%d):" |
2361 | 0 | " could not evaluate right side to int\n", |
2362 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
2363 | 0 | rve->fpos.e_line, rve->fpos.e_col); |
2364 | 0 | goto error; |
2365 | 0 | } |
2366 | 0 | long_longop2(&r, rve->op, i, j); |
2367 | 0 | if(rv_chg_in_place(rv1)) { |
2368 | 0 | rv1->v.l = r; |
2369 | 0 | ret = rv1; |
2370 | 0 | rv_ref(ret); |
2371 | 0 | } else { |
2372 | 0 | v.l = r; |
2373 | 0 | ret = rval_new(RV_LONG, &v, 0); |
2374 | 0 | if(unlikely(ret == 0)) { |
2375 | 0 | rval_cache_clean(&c1); |
2376 | 0 | LM_ERR("rv eval int expression: out of memory\n"); |
2377 | 0 | goto error; |
2378 | 0 | } |
2379 | 0 | } |
2380 | 0 | break; |
2381 | 0 | case RV_STR: |
2382 | 0 | case RV_NONE: |
2383 | 0 | rv2 = rval_expr_eval(h, msg, rve->right.rve); |
2384 | 0 | if(unlikely(rv2 == 0)) { |
2385 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)" |
2386 | 0 | "\n", |
2387 | 0 | rve->right.rve->fpos.s_line, |
2388 | 0 | rve->right.rve->fpos.s_col, |
2389 | 0 | rve->right.rve->fpos.e_line, |
2390 | 0 | rve->right.rve->fpos.e_col); |
2391 | 0 | rval_cache_clean(&c1); |
2392 | 0 | goto error; |
2393 | 0 | } |
2394 | 0 | ret = rval_str_add2(h, msg, rv1, &c1, rv2, 0); |
2395 | 0 | break; |
2396 | 0 | default: |
2397 | 0 | LM_BUG("rv unsupported basic type %d (%d,%d-%d,%d)\n", type, |
2398 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
2399 | 0 | rve->fpos.e_col); |
2400 | 0 | } |
2401 | 0 | rval_cache_clean(&c1); |
2402 | 0 | break; |
2403 | 0 | case RVE_CONCAT_OP: |
2404 | 0 | rv1 = rval_expr_eval(h, msg, rve->left.rve); |
2405 | 0 | if(unlikely(rv1 == 0)) { |
2406 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2407 | 0 | rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col, |
2408 | 0 | rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col); |
2409 | 0 | goto error; |
2410 | 0 | } |
2411 | 0 | rv2 = rval_expr_eval(h, msg, rve->right.rve); |
2412 | 0 | if(unlikely(rv2 == 0)) { |
2413 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2414 | 0 | rve->right.rve->fpos.s_line, rve->right.rve->fpos.s_col, |
2415 | 0 | rve->right.rve->fpos.e_line, |
2416 | 0 | rve->right.rve->fpos.e_col); |
2417 | 0 | goto error; |
2418 | 0 | } |
2419 | 0 | ret = rval_str_add2(h, msg, rv1, 0, rv2, 0); |
2420 | 0 | break; |
2421 | 0 | case RVE_STR_OP: |
2422 | 0 | rv1 = rval_expr_eval(h, msg, rve->left.rve); |
2423 | 0 | if(unlikely(rv1 == 0)) { |
2424 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2425 | 0 | rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col, |
2426 | 0 | rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col); |
2427 | 0 | goto error; |
2428 | 0 | } |
2429 | 0 | ret = rval_convert(h, msg, RV_STR, rv1, 0); |
2430 | 0 | break; |
2431 | 0 | case RVE_SELVALEXP_OP: |
2432 | | /* operator forces integer type */ |
2433 | 0 | r = rval_expr_eval_long(h, msg, &i, rve->left.rve); |
2434 | 0 | if(unlikely(r != 0)) { |
2435 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2436 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
2437 | 0 | rve->fpos.e_col); |
2438 | 0 | goto error; |
2439 | 0 | } |
2440 | 0 | if(i > 0) { |
2441 | 0 | rv1 = rval_expr_eval(h, msg, rve->right.rve->left.rve); |
2442 | 0 | } else { |
2443 | 0 | rv1 = rval_expr_eval(h, msg, rve->right.rve->right.rve); |
2444 | 0 | } |
2445 | 0 | if(unlikely(rv1 == 0)) { |
2446 | 0 | LM_ERR("rval expression evaluation failed (%d,%d-%d,%d)\n", |
2447 | 0 | rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col, |
2448 | 0 | rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col); |
2449 | 0 | goto error; |
2450 | 0 | } |
2451 | 0 | rval_cache_init(&c1); |
2452 | 0 | type = rval_get_btype(h, msg, rv1, &c1); |
2453 | 0 | switch(type) { |
2454 | 0 | case RV_LONG: |
2455 | 0 | r = rval_get_long(h, msg, &i, rv1, &c1); |
2456 | 0 | rval_get_long_handle_ret(r, |
2457 | 0 | "rval expression left side " |
2458 | 0 | "conversion to int failed", |
2459 | 0 | rve); |
2460 | 0 | if(unlikely(r < 0)) { |
2461 | 0 | rval_cache_clean(&c1); |
2462 | 0 | goto error; |
2463 | 0 | } |
2464 | 0 | v.l = i; |
2465 | 0 | ret = rval_new(RV_LONG, &v, 0); |
2466 | 0 | if(unlikely(ret == 0)) { |
2467 | 0 | rval_cache_clean(&c1); |
2468 | 0 | LM_ERR("rv eval int expression: out of memory\n"); |
2469 | 0 | goto error; |
2470 | 0 | } |
2471 | 0 | break; |
2472 | 0 | case RV_STR: |
2473 | 0 | case RV_NONE: |
2474 | 0 | ret = rval_convert(h, msg, RV_STR, rv1, 0); |
2475 | 0 | break; |
2476 | 0 | default: |
2477 | 0 | LM_BUG("rv unsupported basic type %d (%d,%d-%d,%d)\n", type, |
2478 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
2479 | 0 | rve->fpos.e_col); |
2480 | 0 | } |
2481 | 0 | rval_cache_clean(&c1); |
2482 | 0 | break; |
2483 | 0 | case RVE_SELVALOPT_OP: |
2484 | 0 | break; |
2485 | 0 | case RVE_NONE_OP: |
2486 | | /*default:*/ |
2487 | 0 | LM_BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n", |
2488 | 0 | rve->op, rve->fpos.s_line, rve->fpos.s_col, |
2489 | 0 | rve->fpos.e_line, rve->fpos.e_col); |
2490 | 0 | goto error; |
2491 | 0 | }; |
2492 | 0 | rval_destroy(rv1); |
2493 | 0 | rval_destroy(rv2); |
2494 | 0 | return ret; |
2495 | 0 | error: |
2496 | 0 | rval_destroy(rv1); |
2497 | 0 | rval_destroy(rv2); |
2498 | 0 | return 0; |
2499 | 0 | } |
2500 | | |
2501 | | |
2502 | | /** evals a rval expr and always returns a new rval. |
2503 | | * like rval_expr_eval, but always returns a new rvalue (never a reference |
2504 | | * to an existing one). |
2505 | | * WARNING: result must be rval_destroy()'ed if non-null (it might be |
2506 | | * a reference to another rval). The result can be modified only |
2507 | | * if rv_chg_in_place() returns true. |
2508 | | * @result rvalue on success, 0 on error |
2509 | | */ |
2510 | | struct rvalue *rval_expr_eval_new( |
2511 | | struct run_act_ctx *h, struct sip_msg *msg, struct rval_expr *rve) |
2512 | 0 | { |
2513 | 0 | struct rvalue *ret; |
2514 | 0 | struct rvalue *rv; |
2515 | |
|
2516 | 0 | ret = rval_expr_eval(h, msg, rve); |
2517 | 0 | if(ret && !rv_chg_in_place(ret)) { |
2518 | 0 | rv = ret; |
2519 | | /* create a new rv */ |
2520 | 0 | ret = rval_new(rv->type, &rv->v, 0); |
2521 | 0 | rval_destroy(rv); |
2522 | 0 | } |
2523 | 0 | return ret; |
2524 | 0 | } |
2525 | | |
2526 | | |
2527 | | /** create a RVE_RVAL_OP rval_expr, containing a single rval of the given type. |
2528 | | * |
2529 | | * @param rv_type - rval type |
2530 | | * @param val - rval value |
2531 | | * @param pos - config position |
2532 | | * @return new pkg_malloc'ed rval_expr or 0 on error. |
2533 | | */ |
2534 | | struct rval_expr *mk_rval_expr_v( |
2535 | | enum rval_type rv_type, void *val, struct cfg_pos *pos) |
2536 | 0 | { |
2537 | 0 | struct rval_expr *rve; |
2538 | 0 | union rval_val v; |
2539 | 0 | str *s; |
2540 | 0 | int flags; |
2541 | |
|
2542 | 0 | rve = pkg_malloc(sizeof(*rve)); |
2543 | 0 | if(rve == 0) { |
2544 | 0 | PKG_MEM_ERROR; |
2545 | 0 | return 0; |
2546 | 0 | } |
2547 | 0 | memset(rve, 0, sizeof(*rve)); |
2548 | 0 | flags = 0; |
2549 | 0 | switch(rv_type) { |
2550 | 0 | case RV_LONG: |
2551 | 0 | v.l = (long)val; |
2552 | 0 | break; |
2553 | 0 | case RV_STR: |
2554 | 0 | s = (str *)val; |
2555 | 0 | v.s.s = pkg_malloc(s->len + 1 /*0*/); |
2556 | 0 | if(v.s.s == 0) { |
2557 | 0 | pkg_free(rve); |
2558 | 0 | PKG_MEM_ERROR; |
2559 | 0 | return 0; |
2560 | 0 | } |
2561 | 0 | v.s.len = s->len; |
2562 | 0 | memcpy(v.s.s, s->s, s->len); |
2563 | 0 | v.s.s[s->len] = 0; |
2564 | 0 | flags = RV_CNT_ALLOCED_F; |
2565 | 0 | break; |
2566 | 0 | case RV_AVP: |
2567 | 0 | v.avps = *(avp_spec_t *)val; |
2568 | 0 | break; |
2569 | 0 | case RV_PVAR: |
2570 | 0 | v.pvs = *(pv_spec_t *)val; |
2571 | 0 | break; |
2572 | 0 | case RV_SEL: |
2573 | 0 | v.sel = *(select_t *)val; |
2574 | 0 | break; |
2575 | 0 | case RV_BEXPR: |
2576 | 0 | v.bexpr = (struct expr *)val; |
2577 | 0 | break; |
2578 | 0 | case RV_ACTION_ST: |
2579 | 0 | v.action = (struct action *)val; |
2580 | 0 | break; |
2581 | 0 | default: |
2582 | 0 | LM_BUG("unsupported rv type %d\n", rv_type); |
2583 | 0 | pkg_free(rve); |
2584 | 0 | return 0; |
2585 | 0 | } |
2586 | 0 | rval_init(&rve->left.rval, rv_type, &v, flags); |
2587 | 0 | rve->op = RVE_RVAL_OP; |
2588 | 0 | if(pos) |
2589 | 0 | rve->fpos = *pos; |
2590 | 0 | return rve; |
2591 | 0 | } |
2592 | | |
2593 | | |
2594 | | /** |
2595 | | * @brief Create an unary op. rval_expr |
2596 | | * ret= op rve1 |
2597 | | * @param op - rval expr. unary operator |
2598 | | * @param rve1 - rval expr. on which the operator will act. |
2599 | | * @param pos configuration position |
2600 | | * @return new pkg_malloc'ed rval_expr or 0 on error. |
2601 | | */ |
2602 | | struct rval_expr *mk_rval_expr1( |
2603 | | enum rval_expr_op op, struct rval_expr *rve1, struct cfg_pos *pos) |
2604 | 0 | { |
2605 | 0 | struct rval_expr *ret; |
2606 | |
|
2607 | 0 | switch(op) { |
2608 | 0 | case RVE_UMINUS_OP: |
2609 | 0 | case RVE_BOOL_OP: |
2610 | 0 | case RVE_LNOT_OP: |
2611 | 0 | case RVE_BNOT_OP: |
2612 | 0 | case RVE_STRLEN_OP: |
2613 | 0 | case RVE_STREMPTY_OP: |
2614 | 0 | case RVE_DEFINED_OP: |
2615 | 0 | case RVE_NOTDEFINED_OP: |
2616 | 0 | case RVE_LONG_OP: |
2617 | 0 | case RVE_STR_OP: |
2618 | 0 | break; |
2619 | 0 | default: |
2620 | 0 | LM_BUG("unsupported unary operator %d\n", op); |
2621 | 0 | return 0; |
2622 | 0 | } |
2623 | 0 | ret = pkg_malloc(sizeof(*ret)); |
2624 | 0 | if(ret == 0) { |
2625 | 0 | PKG_MEM_ERROR; |
2626 | 0 | return 0; |
2627 | 0 | } |
2628 | 0 | memset(ret, 0, sizeof(*ret)); |
2629 | 0 | ret->op = op; |
2630 | 0 | ret->left.rve = rve1; |
2631 | 0 | if(pos) |
2632 | 0 | ret->fpos = *pos; |
2633 | 0 | return ret; |
2634 | 0 | } |
2635 | | |
2636 | | |
2637 | | /** |
2638 | | * @brief Create a rval_expr. from 2 other rval exprs, using op |
2639 | | * ret = rve1 op rve2 |
2640 | | * @param op - rval expr. operator |
2641 | | * @param rve1 - rval expr. on which the operator will act. |
2642 | | * @param rve2 - rval expr. on which the operator will act. |
2643 | | * @param pos configuration position |
2644 | | * @return new pkg_malloc'ed rval_expr or 0 on error. |
2645 | | */ |
2646 | | struct rval_expr *mk_rval_expr2(enum rval_expr_op op, struct rval_expr *rve1, |
2647 | | struct rval_expr *rve2, struct cfg_pos *pos) |
2648 | 0 | { |
2649 | 0 | struct rval_expr *ret; |
2650 | |
|
2651 | 0 | switch(op) { |
2652 | 0 | case RVE_MUL_OP: |
2653 | 0 | case RVE_DIV_OP: |
2654 | 0 | case RVE_MOD_OP: |
2655 | 0 | case RVE_MINUS_OP: |
2656 | 0 | case RVE_BOR_OP: |
2657 | 0 | case RVE_BAND_OP: |
2658 | 0 | case RVE_BXOR_OP: |
2659 | 0 | case RVE_BLSHIFT_OP: |
2660 | 0 | case RVE_BRSHIFT_OP: |
2661 | 0 | case RVE_LAND_OP: |
2662 | 0 | case RVE_LOR_OP: |
2663 | 0 | case RVE_GT_OP: |
2664 | 0 | case RVE_GTE_OP: |
2665 | 0 | case RVE_LT_OP: |
2666 | 0 | case RVE_LTE_OP: |
2667 | 0 | case RVE_PLUS_OP: |
2668 | 0 | case RVE_IPLUS_OP: |
2669 | 0 | case RVE_EQ_OP: |
2670 | 0 | case RVE_DIFF_OP: |
2671 | 0 | case RVE_IEQ_OP: |
2672 | 0 | case RVE_IDIFF_OP: |
2673 | 0 | case RVE_STREQ_OP: |
2674 | 0 | case RVE_STRDIFF_OP: |
2675 | 0 | case RVE_MATCH_OP: |
2676 | 0 | case RVE_CONCAT_OP: |
2677 | 0 | case RVE_SELVALEXP_OP: |
2678 | 0 | case RVE_SELVALOPT_OP: |
2679 | 0 | break; |
2680 | 0 | default: |
2681 | 0 | LM_BUG("unsupported operator %d\n", op); |
2682 | 0 | return 0; |
2683 | 0 | } |
2684 | 0 | ret = pkg_malloc(sizeof(*ret)); |
2685 | 0 | if(ret == 0) { |
2686 | 0 | PKG_MEM_ERROR; |
2687 | 0 | return 0; |
2688 | 0 | } |
2689 | 0 | memset(ret, 0, sizeof(*ret)); |
2690 | 0 | ret->op = op; |
2691 | 0 | ret->left.rve = rve1; |
2692 | 0 | ret->right.rve = rve2; |
2693 | 0 | if(pos) |
2694 | 0 | ret->fpos = *pos; |
2695 | 0 | return ret; |
2696 | 0 | } |
2697 | | |
2698 | | |
2699 | | /** returns true if the operator is associative. */ |
2700 | | static int rve_op_is_assoc(enum rval_expr_op op) |
2701 | 0 | { |
2702 | 0 | switch(op) { |
2703 | 0 | case RVE_NONE_OP: |
2704 | 0 | case RVE_RVAL_OP: |
2705 | 0 | case RVE_UMINUS_OP: |
2706 | 0 | case RVE_BOOL_OP: |
2707 | 0 | case RVE_LNOT_OP: |
2708 | 0 | case RVE_BNOT_OP: |
2709 | 0 | case RVE_STRLEN_OP: |
2710 | 0 | case RVE_STREMPTY_OP: |
2711 | 0 | case RVE_DEFINED_OP: |
2712 | 0 | case RVE_NOTDEFINED_OP: |
2713 | 0 | case RVE_LONG_OP: |
2714 | 0 | case RVE_STR_OP: |
2715 | | /* one operand expression => cannot be assoc. */ |
2716 | 0 | return 0; |
2717 | 0 | case RVE_DIV_OP: |
2718 | 0 | case RVE_MOD_OP: |
2719 | 0 | case RVE_MINUS_OP: |
2720 | 0 | case RVE_BLSHIFT_OP: |
2721 | 0 | case RVE_BRSHIFT_OP: |
2722 | 0 | return 0; |
2723 | 0 | case RVE_PLUS_OP: |
2724 | | /* the generic plus is not assoc, e.g. |
2725 | | * "a" + 1 + "2" => "a12" in one case and "a3" in the other */ |
2726 | 0 | return 0; |
2727 | 0 | case RVE_IPLUS_OP: |
2728 | 0 | case RVE_CONCAT_OP: |
2729 | 0 | case RVE_MUL_OP: |
2730 | 0 | case RVE_BAND_OP: |
2731 | 0 | case RVE_BOR_OP: |
2732 | 0 | case RVE_BXOR_OP: |
2733 | 0 | return 1; |
2734 | 0 | case RVE_LAND_OP: |
2735 | 0 | case RVE_LOR_OP: |
2736 | 0 | return 1; |
2737 | 0 | case RVE_GT_OP: |
2738 | 0 | case RVE_GTE_OP: |
2739 | 0 | case RVE_LT_OP: |
2740 | 0 | case RVE_LTE_OP: |
2741 | 0 | case RVE_EQ_OP: |
2742 | 0 | case RVE_DIFF_OP: |
2743 | 0 | case RVE_IEQ_OP: |
2744 | 0 | case RVE_IDIFF_OP: |
2745 | 0 | case RVE_STREQ_OP: |
2746 | 0 | case RVE_STRDIFF_OP: |
2747 | 0 | case RVE_MATCH_OP: |
2748 | 0 | case RVE_SELVALEXP_OP: |
2749 | 0 | case RVE_SELVALOPT_OP: |
2750 | 0 | return 0; |
2751 | 0 | } |
2752 | 0 | return 0; |
2753 | 0 | } |
2754 | | |
2755 | | |
2756 | | /** returns true if the operator is commutative. */ |
2757 | | static int rve_op_is_commutative(enum rval_expr_op op) |
2758 | 0 | { |
2759 | 0 | switch(op) { |
2760 | 0 | case RVE_NONE_OP: |
2761 | 0 | case RVE_RVAL_OP: |
2762 | 0 | case RVE_UMINUS_OP: |
2763 | 0 | case RVE_BOOL_OP: |
2764 | 0 | case RVE_LNOT_OP: |
2765 | 0 | case RVE_BNOT_OP: |
2766 | 0 | case RVE_STRLEN_OP: |
2767 | 0 | case RVE_STREMPTY_OP: |
2768 | 0 | case RVE_DEFINED_OP: |
2769 | 0 | case RVE_NOTDEFINED_OP: |
2770 | 0 | case RVE_LONG_OP: |
2771 | 0 | case RVE_STR_OP: |
2772 | | /* one operand expression => cannot be commut. */ |
2773 | 0 | return 0; |
2774 | 0 | case RVE_DIV_OP: |
2775 | 0 | case RVE_MOD_OP: |
2776 | 0 | case RVE_MINUS_OP: |
2777 | 0 | case RVE_BLSHIFT_OP: |
2778 | 0 | case RVE_BRSHIFT_OP: |
2779 | 0 | return 0; |
2780 | 0 | case RVE_PLUS_OP: |
2781 | | /* non commut. when diff. type |
2782 | | * (e.g 1 + "2" != "2" + 1 ) => non commut. in general |
2783 | | * (specific same type versions are covered by IPLUS & CONCAT) */ |
2784 | 0 | return 0; |
2785 | 0 | case RVE_IPLUS_OP: |
2786 | 0 | case RVE_MUL_OP: |
2787 | 0 | case RVE_BAND_OP: |
2788 | 0 | case RVE_BOR_OP: |
2789 | 0 | case RVE_BXOR_OP: |
2790 | 0 | case RVE_LAND_OP: |
2791 | 0 | case RVE_LOR_OP: |
2792 | 0 | case RVE_IEQ_OP: |
2793 | 0 | case RVE_IDIFF_OP: |
2794 | 0 | case RVE_STREQ_OP: |
2795 | 0 | case RVE_STRDIFF_OP: |
2796 | 0 | return 1; |
2797 | 0 | case RVE_GT_OP: |
2798 | 0 | case RVE_GTE_OP: |
2799 | 0 | case RVE_LT_OP: |
2800 | 0 | case RVE_LTE_OP: |
2801 | 0 | case RVE_CONCAT_OP: |
2802 | 0 | case RVE_MATCH_OP: |
2803 | 0 | case RVE_SELVALEXP_OP: |
2804 | 0 | case RVE_SELVALOPT_OP: |
2805 | 0 | return 0; |
2806 | 0 | case RVE_DIFF_OP: |
2807 | 0 | case RVE_EQ_OP: |
2808 | | /* non. commut. in general, only for same type e.g.: |
2809 | | * "" == 0 diff. 0 == "" ( "" == "0" and 0 == 0) |
2810 | | * same type versions are covered by IEQ, IDIFF, STREQ, STRDIFF |
2811 | | */ |
2812 | 0 | return 0 /* asymmetrical undef handling */; |
2813 | 0 | } |
2814 | 0 | return 0; |
2815 | 0 | } |
2816 | | |
2817 | | |
2818 | | static int fix_rval(struct rvalue *rv, struct rval_expr *rve) |
2819 | 0 | { |
2820 | 0 | LM_DBG("RV fixing type %d\n", rv->type); |
2821 | 0 | switch(rv->type) { |
2822 | 0 | case RV_LONG: |
2823 | | /*nothing to do*/ |
2824 | 0 | LM_DBG("RV is int: %d\n", (int)rv->v.l); |
2825 | 0 | return 0; |
2826 | 0 | case RV_STR: |
2827 | | /*nothing to do*/ |
2828 | 0 | LM_DBG("RV is str: \"%s\"\n", rv->v.s.s); |
2829 | 0 | return 0; |
2830 | 0 | case RV_BEXPR: |
2831 | 0 | return fix_expr(rv->v.bexpr); |
2832 | 0 | case RV_ACTION_ST: |
2833 | 0 | return fix_actions(rv->v.action); |
2834 | 0 | case RV_SEL: |
2835 | 0 | if(resolve_select(&rv->v.sel) < 0) { |
2836 | 0 | if(rve == NULL) { |
2837 | 0 | LM_ERR("Unable to resolve select\n"); |
2838 | 0 | } else { |
2839 | 0 | LM_ERR("Unable to resolve select in cfg at line: %d col: " |
2840 | 0 | "%d\n", |
2841 | 0 | rve->fpos.s_line, rve->fpos.s_col); |
2842 | 0 | } |
2843 | 0 | err_select(&rv->v.sel); |
2844 | 0 | } |
2845 | 0 | return 0; |
2846 | 0 | case RV_AVP: |
2847 | | /* nothing to do, resolved at runtime */ |
2848 | 0 | return 0; |
2849 | 0 | case RV_PVAR: |
2850 | | /* nothing to do, resolved at parsing time */ |
2851 | 0 | return 0; |
2852 | 0 | case RV_NONE: |
2853 | 0 | LM_BUG("uninitialized rvalue\n"); |
2854 | 0 | return -1; |
2855 | 0 | } |
2856 | 0 | LM_BUG("unknown rvalue type %d\n", rv->type); |
2857 | 0 | return -1; |
2858 | 0 | } |
2859 | | |
2860 | | |
2861 | | /** |
2862 | | * @brief Helper function: replace a rve (in-place) with a constant rval_val |
2863 | | * @warning since it replaces in-place, one should make sure that if |
2864 | | * rve is in fact a rval (rve->op==RVE_RVAL_OP), no reference is kept |
2865 | | * to the rval! |
2866 | | * @param rve expression to be replaced (in-place) |
2867 | | * @param type rvalue type |
2868 | | * @param v pointer to a rval_val union containing the replacement value. |
2869 | | * @param flags value flags (how it was alloc'ed, e.g.: RV_CNT_ALLOCED_F) |
2870 | | * @return 0 on success, -1 on error |
2871 | | */ |
2872 | | static int rve_replace_with_val(struct rval_expr *rve, enum rval_type type, |
2873 | | union rval_val *v, int flags) |
2874 | 0 | { |
2875 | 0 | int refcnt; |
2876 | |
|
2877 | 0 | refcnt = 1; /* replaced-in-place rval refcnt */ |
2878 | 0 | if(rve->op != RVE_RVAL_OP) { |
2879 | 0 | rve_destroy(rve->left.rve); |
2880 | 0 | if(rve_op_unary(rve->op) == 0) |
2881 | 0 | rve_destroy(rve->right.rve); |
2882 | 0 | } else { |
2883 | 0 | if(rve->left.rval.refcnt != 1) { |
2884 | 0 | LM_BUG("trying to replace a referenced rval! (refcnt=%d)\n", |
2885 | 0 | rve->left.rval.refcnt); |
2886 | | /* try to recover */ |
2887 | 0 | refcnt = rve->left.rval.refcnt; |
2888 | 0 | abort(); /* find bugs quicker -- andrei */ |
2889 | 0 | } |
2890 | 0 | rval_destroy_content(&rve->left.rval); |
2891 | 0 | } |
2892 | 0 | rval_init(&rve->left.rval, type, v, flags); |
2893 | 0 | rve->left.rval.refcnt = refcnt; |
2894 | 0 | rval_init(&rve->right.rval, RV_NONE, 0, 0); |
2895 | 0 | rve->op = RVE_RVAL_OP; |
2896 | 0 | return 0; |
2897 | 0 | } |
2898 | | |
2899 | | |
2900 | | /** helper function: replace a rve (in-place) with a constant rvalue. |
2901 | | * @param rve - expression to be replaced (in-place) |
2902 | | * @param rv - pointer to the replacement _constant_ rvalue structure |
2903 | | * @return 0 on success, -1 on error */ |
2904 | | static int rve_replace_with_ct_rv(struct rval_expr *rve, struct rvalue *rv) |
2905 | 0 | { |
2906 | 0 | enum rval_type type; |
2907 | 0 | int flags; |
2908 | 0 | long i; |
2909 | 0 | union rval_val v; |
2910 | |
|
2911 | 0 | type = rv->type; |
2912 | 0 | flags = 0; |
2913 | 0 | if(rv->type == RV_LONG) { |
2914 | 0 | if(rval_get_long(0, 0, &i, rv, 0) != 0) { |
2915 | 0 | LM_BUG("unexpected int evaluation failure (%d,%d-%d,%d)\n", |
2916 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
2917 | 0 | rve->fpos.e_col); |
2918 | 0 | return -1; |
2919 | 0 | } |
2920 | 0 | v.l = i; |
2921 | 0 | } else if(rv->type == RV_STR) { |
2922 | 0 | if(rval_get_str(0, 0, &v.s, rv, 0) < 0) { |
2923 | 0 | LM_BUG("unexpected str evaluation failure(%d,%d-%d,%d)\n", |
2924 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
2925 | 0 | rve->fpos.e_col); |
2926 | 0 | return -1; |
2927 | 0 | } |
2928 | 0 | flags |= RV_CNT_ALLOCED_F; |
2929 | 0 | } else { |
2930 | 0 | LM_BUG("unknown constant expression type %d (%d,%d-%d,%d)\n", rv->type, |
2931 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
2932 | 0 | rve->fpos.e_col); |
2933 | 0 | return -1; |
2934 | 0 | } |
2935 | 0 | return rve_replace_with_val(rve, type, &v, flags); |
2936 | 0 | } |
2937 | | |
2938 | | |
2939 | | /** try to replace the right side of the rve with a compiled regex. |
2940 | | * @return 0 on success and -1 on error. |
2941 | | */ |
2942 | | static int fix_match_rve(struct rval_expr *rve) |
2943 | 0 | { |
2944 | 0 | struct rvalue *rv; |
2945 | 0 | regex_t *re; |
2946 | 0 | union rval_val v; |
2947 | 0 | int flags; |
2948 | 0 | int ret; |
2949 | |
|
2950 | 0 | rv = 0; |
2951 | 0 | v.s.s = 0; |
2952 | 0 | v.re.regex = 0; |
2953 | | /* normal fix-up for the left side */ |
2954 | 0 | ret = fix_rval_expr((void *)rve->left.rve); |
2955 | 0 | if(ret < 0) |
2956 | 0 | return ret; |
2957 | | |
2958 | | /* fixup the right side (RE) */ |
2959 | 0 | if(rve_is_constant(rve->right.rve)) { |
2960 | 0 | if((rve_guess_type(rve->right.rve) != RV_STR)) { |
2961 | 0 | LM_ERR("fixup failure(%d,%d-%d,%d): right side of =~ is not string" |
2962 | 0 | " (%d,%d)\n", |
2963 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
2964 | 0 | rve->fpos.e_col, rve->right.rve->fpos.s_line, |
2965 | 0 | rve->right.rve->fpos.s_col); |
2966 | 0 | goto error; |
2967 | 0 | } |
2968 | 0 | if((rv = rval_expr_eval(0, 0, rve->right.rve)) == 0) { |
2969 | 0 | LM_ERR("fixup failure(%d,%d-%d,%d): bad RE expression\n", |
2970 | 0 | rve->right.rve->fpos.s_line, rve->right.rve->fpos.s_col, |
2971 | 0 | rve->right.rve->fpos.e_line, rve->right.rve->fpos.e_col); |
2972 | 0 | goto error; |
2973 | 0 | } |
2974 | 0 | if(rval_get_str(0, 0, &v.s, rv, 0) < 0) { |
2975 | 0 | LM_BUG("fixup unexpected failure (%d,%d-%d,%d)\n", rve->fpos.s_line, |
2976 | 0 | rve->fpos.s_col, rve->fpos.e_line, rve->fpos.e_col); |
2977 | 0 | goto error; |
2978 | 0 | } |
2979 | | /* we have the str, we don't need the rv anymore */ |
2980 | 0 | rval_destroy(rv); |
2981 | 0 | rv = 0; |
2982 | 0 | re = pkg_malloc(sizeof(*re)); |
2983 | 0 | if(re == 0) { |
2984 | 0 | PKG_MEM_ERROR; |
2985 | 0 | goto error; |
2986 | 0 | } |
2987 | | /* same flags as for expr. =~ (fix_expr()) */ |
2988 | 0 | if(regcomp(re, v.s.s, REG_EXTENDED | REG_NOSUB | REG_ICASE)) { |
2989 | 0 | pkg_free(re); |
2990 | 0 | LM_ERR("Bad regular expression \"%s\"(%d,%d-%d,%d)\n", v.s.s, |
2991 | 0 | rve->right.rve->fpos.s_line, rve->right.rve->fpos.s_col, |
2992 | 0 | rve->right.rve->fpos.e_line, rve->right.rve->fpos.e_col); |
2993 | 0 | goto error; |
2994 | 0 | } |
2995 | 0 | v.re.regex = re; |
2996 | 0 | flags = RV_RE_F | RV_RE_ALLOCED_F | RV_CNT_ALLOCED_F; |
2997 | 0 | if(rve_replace_with_val(rve->right.rve, RV_STR, &v, flags) < 0) |
2998 | 0 | goto error; |
2999 | 0 | } else { |
3000 | | /* right side is not constant => normal fixup */ |
3001 | 0 | return fix_rval_expr((void *)rve->right.rve); |
3002 | 0 | } |
3003 | 0 | return 0; |
3004 | 0 | error: |
3005 | 0 | if(rv) |
3006 | 0 | rval_destroy(rv); |
3007 | 0 | if(v.s.s) |
3008 | 0 | pkg_free(v.s.s); |
3009 | 0 | if(v.re.regex) { |
3010 | 0 | regfree(v.re.regex); |
3011 | 0 | pkg_free(v.re.regex); |
3012 | 0 | } |
3013 | 0 | return -1; |
3014 | 0 | } |
3015 | | |
3016 | | |
3017 | | /** optimize op($v, 0) or op($v, 1). |
3018 | | * Note: internal use only from rve_optimize |
3019 | | * It should be called after ct optimization, for non-constant |
3020 | | * expressions (the left or right side is not constant). |
3021 | | * @return 1 on success (rve was changed), 0 on failure and -1 on error |
3022 | | */ |
3023 | | static int rve_opt_01(struct rval_expr *rve, enum rval_type rve_type) |
3024 | 0 | { |
3025 | 0 | struct rvalue *rv; |
3026 | 0 | struct rval_expr *ct_rve; |
3027 | 0 | struct rval_expr *v_rve; |
3028 | 0 | struct rval_expr *r_rve = NULL; |
3029 | 0 | int i; |
3030 | 0 | int ret; |
3031 | 0 | enum rval_expr_op op; |
3032 | 0 | struct cfg_pos pos; |
3033 | 0 | int right; /* debugging msg */ |
3034 | 0 | int dbg; /* debugging msg on/off */ |
3035 | | |
3036 | | /* helper macro: replace in-place a <ctype> type rve with v (another rve). |
3037 | | * if type_of(v)== <ctype> => rve:=*v (copy v contents into rve and free v) |
3038 | | * else if type_of(v)!=<ctype> => rve:= (ctype) v (casts v to <ctype>) |
3039 | | * Uses pos. |
3040 | | * ctype can be INT or STR |
3041 | | * WARNING: - v might be pkg_free()'d |
3042 | | * - rve members _are_ _not_ freed or destroyed |
3043 | | */ |
3044 | 0 | #define replace_rve_type_cast(e, v, ctype) \ |
3045 | 0 | do { \ |
3046 | 0 | if(rve_guess_type((v)) == RV_##ctype) { \ |
3047 | | /* if type_of($v)==int we don't need to add an \ |
3048 | | * int cast operator => replace with v */ \ |
3049 | 0 | pos = (e)->fpos; \ |
3050 | 0 | *(e) = *(v); /* replace e with v (in-place) */ \ |
3051 | 0 | (e)->fpos = pos; \ |
3052 | 0 | r_rve = v; /* link to free it */ \ |
3053 | 0 | } else { \ |
3054 | | /* unknown type or str => (int) $v */ \ |
3055 | 0 | (e)->op = RVE_##ctype##_OP; \ |
3056 | 0 | (e)->left.rve = (v); \ |
3057 | 0 | (e)->right.rve = 0; \ |
3058 | 0 | } \ |
3059 | 0 | } while(0) |
3060 | | |
3061 | | /* helper macro: replace in-place an int type rve with v (another rve).*/ |
3062 | 0 | #define replace_long_rve(e, v) replace_rve_type_cast(e, v, LONG) |
3063 | | /* helper macro: replace in-place a str type rve with v (another rve).*/ |
3064 | 0 | #define replace_str_rve(e, v) replace_rve_type_cast(e, v, STR) |
3065 | |
|
3066 | 0 | rv = 0; |
3067 | 0 | ret = 0; |
3068 | 0 | right = 0; |
3069 | 0 | dbg = 1; |
3070 | |
|
3071 | 0 | if(rve_is_constant(rve->right.rve)) { |
3072 | 0 | ct_rve = rve->right.rve; |
3073 | 0 | v_rve = rve->left.rve; |
3074 | 0 | right = 1; |
3075 | 0 | } else if(rve_is_constant(rve->left.rve)) { |
3076 | 0 | ct_rve = rve->left.rve; |
3077 | 0 | v_rve = rve->right.rve; |
3078 | 0 | right = 0; |
3079 | 0 | } else |
3080 | 0 | return 0; /* op($v, $w) */ |
3081 | | |
3082 | | /* rval_expr_eval_new() instead of rval_expr_eval() to avoid |
3083 | | * referencing a ct_rve->left.rval if ct_rve is a rval, which |
3084 | | * would prevent rve_destroy(ct_rve) from working */ |
3085 | 0 | if((rv = rval_expr_eval_new(0, 0, ct_rve)) == 0) { |
3086 | 0 | LM_ERR("optimization failure, bad expression (%d,%d-%d,%d)\n", |
3087 | 0 | ct_rve->fpos.s_line, ct_rve->fpos.s_col, ct_rve->fpos.e_line, |
3088 | 0 | ct_rve->fpos.e_col); |
3089 | 0 | goto error; |
3090 | 0 | } |
3091 | 0 | op = rve->op; |
3092 | 0 | if(rv->type == RV_LONG) { |
3093 | 0 | i = rv->v.l; |
3094 | 0 | switch(op) { |
3095 | 0 | case RVE_MUL_OP: |
3096 | 0 | if(i == 0) { |
3097 | | /* $v * 0 -> 0 |
3098 | | * 0 * $v -> 0 */ |
3099 | 0 | if(rve_replace_with_ct_rv(rve, rv) < 0) |
3100 | 0 | goto error; |
3101 | 0 | ret = 1; |
3102 | 0 | } else if(i == 1) { |
3103 | | /* $v * 1 -> (int)$v |
3104 | | * 1 * $v -> (int)$v */ |
3105 | 0 | rve_destroy(ct_rve); |
3106 | 0 | replace_long_rve(rve, v_rve); |
3107 | 0 | ret = 1; |
3108 | 0 | } |
3109 | 0 | break; |
3110 | 0 | case RVE_DIV_OP: |
3111 | 0 | if(i == 0) { |
3112 | 0 | if(ct_rve == rve->left.rve) { |
3113 | | /* 0 / $v -> 0 */ |
3114 | 0 | if(rve_replace_with_ct_rv(rve, rv) < 0) |
3115 | 0 | goto error; |
3116 | 0 | ret = 1; |
3117 | 0 | } else { |
3118 | | /* $v / 0 */ |
3119 | 0 | LM_ERR("RVE divide by 0 at %d,%d\n", |
3120 | 0 | ct_rve->fpos.s_line, ct_rve->fpos.s_col); |
3121 | 0 | } |
3122 | 0 | } else if(i == 1) { |
3123 | 0 | if(ct_rve == rve->right.rve) { |
3124 | | /* $v / 1 -> (int)$v */ |
3125 | 0 | rve_destroy(ct_rve); |
3126 | 0 | replace_long_rve(rve, v_rve); |
3127 | 0 | ret = 1; |
3128 | 0 | } |
3129 | 0 | } |
3130 | 0 | break; |
3131 | 0 | case RVE_MOD_OP: |
3132 | 0 | if(i == 0) { |
3133 | 0 | if(ct_rve == rve->left.rve) { |
3134 | | /* 0 % $v -> 0 */ |
3135 | 0 | if(rve_replace_with_ct_rv(rve, rv) < 0) |
3136 | 0 | goto error; |
3137 | 0 | ret = 1; |
3138 | 0 | } else { |
3139 | | /* $v % 0 */ |
3140 | 0 | LM_ERR("RVE modulo by 0 at %d,%d\n", |
3141 | 0 | ct_rve->fpos.s_line, ct_rve->fpos.s_col); |
3142 | 0 | } |
3143 | 0 | } |
3144 | | /* $v % 1 -> 0 ? */ |
3145 | 0 | break; |
3146 | 0 | case RVE_MINUS_OP: |
3147 | 0 | if(i == 0) { |
3148 | 0 | if(ct_rve == rve->right.rve) { |
3149 | | /* $v - 0 -> $v */ |
3150 | 0 | rve_destroy(ct_rve); |
3151 | 0 | replace_long_rve(rve, v_rve); |
3152 | 0 | ret = 1; |
3153 | 0 | } |
3154 | | /* ? 0 - $v -> -($v) ? */ |
3155 | 0 | } |
3156 | 0 | break; |
3157 | 0 | case RVE_BAND_OP: |
3158 | 0 | if(i == 0) { |
3159 | | /* $v & 0 -> 0 |
3160 | | * 0 & $v -> 0 */ |
3161 | 0 | if(rve_replace_with_ct_rv(rve, rv) < 0) |
3162 | 0 | goto error; |
3163 | 0 | ret = 1; |
3164 | 0 | } |
3165 | | /* no 0xffffff optimization for now (haven't decided on |
3166 | | * the number of bits ) */ |
3167 | 0 | break; |
3168 | 0 | case RVE_BOR_OP: |
3169 | 0 | if(i == 0) { |
3170 | | /* $v | 0 -> (int)$v |
3171 | | * 0 | $v -> (int)$v */ |
3172 | 0 | rve_destroy(ct_rve); |
3173 | 0 | replace_long_rve(rve, v_rve); |
3174 | 0 | ret = 1; |
3175 | 0 | } |
3176 | 0 | break; |
3177 | 0 | case RVE_LAND_OP: |
3178 | 0 | if(i == 0) { |
3179 | | /* $v && 0 -> 0 |
3180 | | * 0 && $v -> 0 */ |
3181 | 0 | if(rve_replace_with_ct_rv(rve, rv) < 0) |
3182 | 0 | goto error; |
3183 | 0 | ret = 1; |
3184 | 0 | } else if(i == 1) { |
3185 | | /* $v && 1 -> (int)$v |
3186 | | * 1 && $v -> (int)$v */ |
3187 | 0 | rve_destroy(ct_rve); |
3188 | 0 | replace_long_rve(rve, v_rve); |
3189 | 0 | ret = 1; |
3190 | 0 | } |
3191 | 0 | break; |
3192 | 0 | case RVE_LOR_OP: |
3193 | 0 | if(i == 1) { |
3194 | | /* $v || 1 -> 1 |
3195 | | * 1 || $v -> 1 */ |
3196 | 0 | if(rve_replace_with_ct_rv(rve, rv) < 0) |
3197 | 0 | goto error; |
3198 | 0 | ret = 1; |
3199 | 0 | } else if(i == 0) { |
3200 | | /* $v || 0 -> (int)$v |
3201 | | * 0 && $v -> (int)$v */ |
3202 | 0 | rve_destroy(ct_rve); |
3203 | 0 | replace_long_rve(rve, v_rve); |
3204 | 0 | ret = 1; |
3205 | 0 | } |
3206 | 0 | break; |
3207 | 0 | case RVE_PLUS_OP: |
3208 | 0 | case RVE_IPLUS_OP: |
3209 | | /* we must make sure that this is an int PLUS |
3210 | | * (because "foo"+0 is valid => "foo0") => |
3211 | | * check if it's an IPLUS or the result is an integer |
3212 | | * (which generally means unoptimized <int> + <something>). |
3213 | | */ |
3214 | 0 | if((i == 0) |
3215 | 0 | && ((op == RVE_IPLUS_OP) || (rve_type == RV_LONG))) { |
3216 | | /* $v + 0 -> (int)$v |
3217 | | * 0 + $v -> (int)$v */ |
3218 | 0 | rve_destroy(ct_rve); |
3219 | 0 | replace_long_rve(rve, v_rve); |
3220 | 0 | ret = 1; |
3221 | 0 | } |
3222 | 0 | break; |
3223 | 0 | default: |
3224 | | /* do nothing */ |
3225 | 0 | break; |
3226 | 0 | } |
3227 | | /* debugging messages */ |
3228 | 0 | if(ret == 1 && dbg) { |
3229 | 0 | if(right) { |
3230 | 0 | if(rve->op == RVE_RVAL_OP) { |
3231 | 0 | if(rve->left.rval.type == RV_LONG) |
3232 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3233 | 0 | " op%d($v, %d) -> %d\n", |
3234 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3235 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, i, |
3236 | 0 | (int)rve->left.rval.v.l); |
3237 | 0 | else |
3238 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3239 | 0 | " op%d($v, %d) -> $v (rval)\n", |
3240 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3241 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, i); |
3242 | 0 | } else if(rve->op == RVE_LONG_OP) { |
3243 | 0 | if(rve->left.rve->op == RVE_RVAL_OP |
3244 | 0 | && rve->left.rve->left.rval.type == RV_LONG) |
3245 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3246 | 0 | " op%d($v, %d) -> (int)%d\n", |
3247 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3248 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, i, |
3249 | 0 | (int)rve->left.rve->left.rval.v.l); |
3250 | 0 | else |
3251 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3252 | 0 | " op%d($v, %d) -> (int)$v\n", |
3253 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3254 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, i); |
3255 | 0 | } else { |
3256 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3257 | 0 | " op%d($v, %d) -> $v\n", |
3258 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3259 | 0 | rve->fpos.e_col, op, i); |
3260 | 0 | } |
3261 | 0 | } else { |
3262 | 0 | if(rve->op == RVE_RVAL_OP) { |
3263 | 0 | if(rve->left.rval.type == RV_LONG) |
3264 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3265 | 0 | " op%d(%d, $v) -> %d\n", |
3266 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3267 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, i, |
3268 | 0 | (int)rve->left.rval.v.l); |
3269 | 0 | else |
3270 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3271 | 0 | " op%d(%d, $v) -> $v (rval)\n", |
3272 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3273 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, i); |
3274 | 0 | } else if(rve->op == RVE_LONG_OP) { |
3275 | 0 | if(rve->left.rve->op == RVE_RVAL_OP |
3276 | 0 | && rve->left.rve->left.rval.type == RV_LONG) |
3277 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3278 | 0 | " op%d(%d, $v) -> (int)%d\n", |
3279 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3280 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, i, |
3281 | 0 | (int)rve->left.rve->left.rval.v.l); |
3282 | 0 | else |
3283 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3284 | 0 | " op%d(%d, $v) -> (int)$v\n", |
3285 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3286 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, i); |
3287 | 0 | } else { |
3288 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3289 | 0 | " op%d(%d, $v) -> $v\n", |
3290 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3291 | 0 | rve->fpos.e_col, op, i); |
3292 | 0 | } |
3293 | 0 | } |
3294 | 0 | } |
3295 | 0 | } else if(rv->type == RV_STR) { |
3296 | 0 | switch(op) { |
3297 | 0 | case RVE_CONCAT_OP: |
3298 | 0 | if(rv->v.s.len == 0) { |
3299 | | /* $v . "" -> (str)$v |
3300 | | * "" . $v -> (str)$v */ |
3301 | 0 | rve_destroy(ct_rve); |
3302 | 0 | replace_str_rve(rve, v_rve); |
3303 | 0 | ret = 1; |
3304 | 0 | } |
3305 | 0 | break; |
3306 | 0 | case RVE_EQ_OP: |
3307 | 0 | case RVE_STREQ_OP: |
3308 | 0 | if(rv->v.s.len == 0) { |
3309 | | /* $v == "" -> strempty($v) |
3310 | | * "" == $v -> strempty ($v) */ |
3311 | 0 | rve_destroy(ct_rve); |
3312 | | /* replace current expr. with strempty(rve) */ |
3313 | 0 | rve->op = RVE_STREMPTY_OP; |
3314 | 0 | rve->left.rve = v_rve; |
3315 | 0 | rve->right.rve = 0; |
3316 | 0 | ret = 1; |
3317 | 0 | if(dbg) |
3318 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3319 | 0 | " op%d($v, \"\") -> strempty($v)\n", |
3320 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3321 | 0 | rve->fpos.e_line, rve->fpos.e_col, op); |
3322 | 0 | dbg = 0; |
3323 | 0 | } |
3324 | 0 | break; |
3325 | 0 | default: |
3326 | 0 | break; |
3327 | 0 | } |
3328 | | /* no optimization for generic RVE_PLUS_OP for now, only for RVE_CONCAT_OP |
3329 | | * (RVE_PLUS_OP should be converted to RVE_CONCAT_OP if it's supposed |
3330 | | * to work on strings. If it's not converted/optimized it means its type |
3331 | | * can be determined only at runtime => we cannot optimize */ |
3332 | | /* debugging messages */ |
3333 | 0 | if(ret == 1 && dbg) { |
3334 | 0 | if(right) { |
3335 | 0 | if(rve->op == RVE_RVAL_OP) { |
3336 | 0 | if(rve->left.rval.type == RV_STR) |
3337 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3338 | 0 | " op%d($v, <string>) -> \"%s\"\n", |
3339 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3340 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, |
3341 | 0 | rve->left.rval.v.s.s); |
3342 | 0 | else |
3343 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3344 | 0 | " op%d($v, <string>) -> $v (rval)\n", |
3345 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3346 | 0 | rve->fpos.e_line, rve->fpos.e_col, op); |
3347 | 0 | } else if(rve->op == RVE_STR_OP) { |
3348 | 0 | if(rve->left.rve->op == RVE_RVAL_OP |
3349 | 0 | && rve->left.rve->left.rval.type == RV_STR) |
3350 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3351 | 0 | " op%d($v, <string>) -> (str)\"%s\"\n", |
3352 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3353 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, |
3354 | 0 | rve->left.rve->left.rval.v.s.s); |
3355 | 0 | else |
3356 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3357 | 0 | " op%d($v, <string>) -> (str)$v\n", |
3358 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3359 | 0 | rve->fpos.e_line, rve->fpos.e_col, op); |
3360 | 0 | } else { |
3361 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3362 | 0 | " op%d($v, <string>) -> $v\n", |
3363 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3364 | 0 | rve->fpos.e_col, op); |
3365 | 0 | } |
3366 | 0 | } else { |
3367 | 0 | if(rve->op == RVE_RVAL_OP) { |
3368 | 0 | if(rve->left.rval.type == RV_STR) |
3369 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3370 | 0 | " op%d(<string>, $v) -> \"%s\"\n", |
3371 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3372 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, |
3373 | 0 | rve->left.rval.v.s.s); |
3374 | 0 | else |
3375 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3376 | 0 | " op%d(<string>, $v) -> $v (rval)\n", |
3377 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3378 | 0 | rve->fpos.e_line, rve->fpos.e_col, op); |
3379 | 0 | } else if(rve->op == RVE_STR_OP) { |
3380 | 0 | if(rve->left.rve->op == RVE_RVAL_OP |
3381 | 0 | && rve->left.rve->left.rval.type == RV_STR) |
3382 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3383 | 0 | " op%d(<string>, $v) -> (str)\"%s\"\n", |
3384 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3385 | 0 | rve->fpos.e_line, rve->fpos.e_col, op, |
3386 | 0 | rve->left.rve->left.rval.v.s.s); |
3387 | 0 | else |
3388 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3389 | 0 | " op%d(<string>, $v) -> (str)$v\n", |
3390 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3391 | 0 | rve->fpos.e_line, rve->fpos.e_col, op); |
3392 | 0 | } else { |
3393 | 0 | LM_DBG("FIXUP RVE: (%d,%d-%d,%d) optimized" |
3394 | 0 | " op%d(<string>, $v) -> $v\n", |
3395 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3396 | 0 | rve->fpos.e_col, op); |
3397 | 0 | } |
3398 | 0 | } |
3399 | 0 | } |
3400 | 0 | } |
3401 | 0 | if(rv) |
3402 | 0 | rval_destroy(rv); |
3403 | 0 | if(r_rve) |
3404 | 0 | pkg_free(r_rve); /* rve_destroy(v_rve) would free everything*/ |
3405 | 0 | return ret; |
3406 | 0 | error: |
3407 | 0 | if(rv) |
3408 | 0 | rval_destroy(rv); |
3409 | 0 | if(r_rve) |
3410 | 0 | pkg_free(r_rve); /* rve_destroy(v_rve) would free everything*/ |
3411 | 0 | return -1; |
3412 | 0 | } |
3413 | | |
3414 | | |
3415 | | /** tries to optimize a rval_expr. */ |
3416 | | static int rve_optimize(struct rval_expr *rve) |
3417 | 0 | { |
3418 | 0 | int ret; |
3419 | 0 | struct rvalue *rv; |
3420 | 0 | struct rvalue *trv; /* used only for DBG() */ |
3421 | 0 | enum rval_expr_op op; |
3422 | 0 | struct rval_expr tmp_rve; |
3423 | 0 | enum rval_type type, l_type; |
3424 | 0 | struct rval_expr *bad_rve; |
3425 | 0 | enum rval_type bad_type, exp_type; |
3426 | |
|
3427 | 0 | ret = 0; |
3428 | 0 | rv = 0; |
3429 | 0 | if(scr_opt_lev < 1) |
3430 | 0 | return 0; |
3431 | 0 | if(rve->op == RVE_RVAL_OP) /* if rval, nothing to do */ |
3432 | 0 | return 0; |
3433 | 0 | if(rve_is_constant(rve)) { |
3434 | 0 | if((rv = rval_expr_eval_new(0, 0, rve)) == 0) { |
3435 | 0 | LM_ERR("optimization failure, bad expression (%d,%d-%d,%d)\n", |
3436 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3437 | 0 | rve->fpos.e_col); |
3438 | 0 | goto error; |
3439 | 0 | } |
3440 | 0 | op = rve->op; |
3441 | 0 | if(rve_replace_with_ct_rv(rve, rv) < 0) |
3442 | 0 | goto error; |
3443 | 0 | rval_destroy(rv); |
3444 | 0 | rv = 0; |
3445 | 0 | trv = &rve->left.rval; |
3446 | 0 | if(trv->type == RV_LONG) |
3447 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized constant int rve " |
3448 | 0 | "(old op %d) to %d\n", |
3449 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3450 | 0 | rve->fpos.e_col, op, (int)trv->v.l); |
3451 | 0 | else if(trv->type == RV_STR) |
3452 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized constant str rve " |
3453 | 0 | "(old op %d) to \"%.*s\"\n", |
3454 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3455 | 0 | rve->fpos.e_col, op, trv->v.s.len, trv->v.s.s); |
3456 | 0 | ret = 1; |
3457 | 0 | } else { |
3458 | | /* expression is not constant */ |
3459 | | /* if unary => nothing to do */ |
3460 | 0 | if(rve_op_unary(rve->op)) |
3461 | 0 | return rve_optimize(rve->left.rve); |
3462 | 0 | rve_optimize(rve->left.rve); |
3463 | 0 | rve_optimize(rve->right.rve); |
3464 | 0 | if(!rve_check_type(&type, rve, &bad_rve, &bad_type, &exp_type)) { |
3465 | 0 | LM_ERR("optimization failure while optimizing %d,%d-%d,%d:" |
3466 | 0 | " type mismatch in expression (%d,%d-%d,%d), " |
3467 | 0 | "type %s, but expected %s\n", |
3468 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3469 | 0 | rve->fpos.e_col, bad_rve->fpos.s_line, bad_rve->fpos.s_col, |
3470 | 0 | bad_rve->fpos.e_line, bad_rve->fpos.e_col, |
3471 | 0 | rval_type_name(bad_type), rval_type_name(exp_type)); |
3472 | 0 | return 0; |
3473 | 0 | } |
3474 | | /* $v - a => $v + (-a) (easier to optimize)*/ |
3475 | 0 | if((rve->op == RVE_MINUS_OP) && (rve_is_constant(rve->right.rve))) { |
3476 | 0 | if((rv = rval_expr_eval_new(0, 0, rve->right.rve)) == 0) { |
3477 | 0 | LM_ERR("optimization failure, bad expression (%d,%d-%d,%d)\n", |
3478 | 0 | rve->right.rve->fpos.s_line, rve->right.rve->fpos.s_col, |
3479 | 0 | rve->right.rve->fpos.e_line, |
3480 | 0 | rve->right.rve->fpos.e_col); |
3481 | 0 | goto error; |
3482 | 0 | } |
3483 | 0 | if(rv->type == RV_LONG) { |
3484 | 0 | rv->v.l = -rv->v.l; |
3485 | 0 | if(rve_replace_with_ct_rv(rve->right.rve, rv) < 0) |
3486 | 0 | goto error; |
3487 | 0 | rve->op = RVE_IPLUS_OP; |
3488 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized $v - an into " |
3489 | 0 | "$v + (%d)\n", |
3490 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3491 | 0 | rve->fpos.e_col, (int)rve->right.rve->left.rval.v.l); |
3492 | 0 | } |
3493 | 0 | rval_destroy(rv); |
3494 | 0 | rv = 0; |
3495 | 0 | } |
3496 | | |
3497 | | /* e1 PLUS_OP e2 -> change op if we know e1 basic type */ |
3498 | 0 | if(rve->op == RVE_PLUS_OP) { |
3499 | 0 | l_type = rve_guess_type(rve->left.rve); |
3500 | 0 | if(l_type == RV_LONG) { |
3501 | 0 | rve->op = RVE_IPLUS_OP; |
3502 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): changed + into integer plus\n", |
3503 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3504 | 0 | rve->fpos.e_col); |
3505 | 0 | } else if(l_type == RV_STR) { |
3506 | 0 | rve->op = RVE_CONCAT_OP; |
3507 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): changed + into string " |
3508 | 0 | "concat\n", |
3509 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3510 | 0 | rve->fpos.e_col); |
3511 | 0 | } |
3512 | 0 | } |
3513 | | /* e1 EQ_OP e2 -> change op if we know e1 basic type |
3514 | | * e1 DIFF_OP e2 -> change op if we know e2 basic type */ |
3515 | 0 | if(rve->op == RVE_EQ_OP || rve->op == RVE_DIFF_OP) { |
3516 | 0 | l_type = rve_guess_type(rve->left.rve); |
3517 | 0 | if(l_type == RV_LONG) { |
3518 | 0 | rve->op = (rve->op == RVE_EQ_OP) ? RVE_IEQ_OP : RVE_IDIFF_OP; |
3519 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): changed ==/!= into integer" |
3520 | 0 | " ==/!=\n", |
3521 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3522 | 0 | rve->fpos.e_col); |
3523 | 0 | } else if(l_type == RV_STR) { |
3524 | 0 | rve->op = |
3525 | 0 | (rve->op == RVE_EQ_OP) ? RVE_STREQ_OP : RVE_STRDIFF_OP; |
3526 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): changed ==/!= into string" |
3527 | 0 | " ==/!=\n", |
3528 | 0 | rve->fpos.s_line, rve->fpos.s_col, rve->fpos.e_line, |
3529 | 0 | rve->fpos.e_col); |
3530 | 0 | } |
3531 | 0 | } |
3532 | | |
3533 | | /* $v * 0 => 0; $v * 1 => $v (for *, /, &, |, &&, ||, +, -) */ |
3534 | 0 | if(rve_opt_01(rve, type) == 1) { |
3535 | | /* success, rve was changed => return now |
3536 | | * (since this is recursively invoked the "new" rve |
3537 | | * is already optimized) */ |
3538 | 0 | ret = 1; |
3539 | 0 | goto end; |
3540 | 0 | } |
3541 | | |
3542 | | /* op(op($v, a), b) => op($v, op(a,b)) */ |
3543 | 0 | if(rve_is_constant(rve->right.rve)) { |
3544 | | /* op1(op2(...), b) */ |
3545 | 0 | if((rve->op == rve->left.rve->op) && rve_op_is_assoc(rve->op)) { |
3546 | | /* op(op(...), b) */ |
3547 | 0 | if(rve_is_constant(rve->left.rve->right.rve)) { |
3548 | | /* op(op($v, a), b) => op($v, op(a, b)) */ |
3549 | | /* rv= op(a, b) */ |
3550 | 0 | tmp_rve.op = rve->op; |
3551 | 0 | tmp_rve.left.rve = rve->left.rve->right.rve; |
3552 | 0 | tmp_rve.right.rve = rve->right.rve; |
3553 | | /* hack for RVE_PLUS_OP which can work on string, ints |
3554 | | * or a combination of them */ |
3555 | 0 | if((rve->op == RVE_PLUS_OP) |
3556 | 0 | && (rve_guess_type(tmp_rve.left.rve) != RV_STR)) { |
3557 | 0 | LM_DBG("RVE optimization failed (%d,%d-%d,%d): cannot " |
3558 | 0 | "optimize +(+($v, a), b) when typeof(a)==INT\n", |
3559 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3560 | 0 | rve->fpos.e_line, rve->fpos.e_col); |
3561 | 0 | return 0; |
3562 | 0 | } |
3563 | 0 | if((rv = rval_expr_eval_new(0, 0, &tmp_rve)) == 0) { |
3564 | 0 | LM_ERR("optimization failure, bad expression\n"); |
3565 | 0 | goto error; |
3566 | 0 | } |
3567 | | /* op($v, rv) */ |
3568 | 0 | if(rve_replace_with_ct_rv(rve->right.rve, rv) < 0) |
3569 | 0 | goto error; |
3570 | 0 | rval_destroy(rv); |
3571 | 0 | rv = 0; |
3572 | 0 | rve_destroy(tmp_rve.left.rve); |
3573 | 0 | rve->left.rve = rve->left.rve->left.rve; |
3574 | 0 | trv = &rve->right.rve->left.rval; |
3575 | 0 | if(trv->type == RV_LONG) |
3576 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: " |
3577 | 0 | "op(op($v, a), b) with op($v, %d); op=%d\n", |
3578 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3579 | 0 | rve->fpos.e_line, rve->fpos.e_col, |
3580 | 0 | (int)trv->v.l, rve->op); |
3581 | 0 | else if(trv->type == RV_STR) |
3582 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve " |
3583 | 0 | "op(op($v, a), b) with op($v, \"%.*s\");" |
3584 | 0 | " op=%d\n", |
3585 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3586 | 0 | rve->fpos.e_line, rve->fpos.e_col, trv->v.s.len, |
3587 | 0 | trv->v.s.s, rve->op); |
3588 | 0 | ret = 1; |
3589 | 0 | } else if(rve_is_constant(rve->left.rve->left.rve) |
3590 | 0 | && rve_op_is_commutative(rve->op)) { |
3591 | | /* op(op(a, $v), b) => op(op(a, b), $v) */ |
3592 | | /* rv= op(a, b) */ |
3593 | 0 | tmp_rve.op = rve->op; |
3594 | 0 | tmp_rve.left.rve = rve->left.rve->left.rve; |
3595 | 0 | tmp_rve.right.rve = rve->right.rve; |
3596 | | /* no need for the RVE_PLUS_OP hack, all the bad |
3597 | | * cases are caught by rve_op_is_commutative() |
3598 | | * (in this case type will be typeof(a)) => ok only if |
3599 | | * typeof(a) is int) */ |
3600 | 0 | if((rv = rval_expr_eval_new(0, 0, &tmp_rve)) == 0) { |
3601 | 0 | LM_ERR("optimization failure, bad expression\n"); |
3602 | 0 | goto error; |
3603 | 0 | } |
3604 | | /* op(rv, $v) */ |
3605 | 0 | rve_destroy(rve->right.rve); |
3606 | 0 | rve->right.rve = rve->left.rve->right.rve; |
3607 | 0 | rve->left.rve->right.rve = 0; |
3608 | 0 | if(rve_replace_with_ct_rv(rve->left.rve, rv) < 0) |
3609 | 0 | goto error; |
3610 | 0 | rval_destroy(rv); |
3611 | 0 | rv = 0; |
3612 | 0 | trv = &rve->left.rve->left.rval; |
3613 | 0 | if(trv->type == RV_LONG) |
3614 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: " |
3615 | 0 | "op(op(a, $v), b) with op(%d, $v); op=%d\n", |
3616 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3617 | 0 | rve->fpos.e_line, rve->fpos.e_col, |
3618 | 0 | (int)trv->v.l, rve->op); |
3619 | 0 | else if(trv->type == RV_STR) |
3620 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve " |
3621 | 0 | "op(op(a, $v), b) with op(\"%.*s\", $v);" |
3622 | 0 | " op=%d\n", |
3623 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3624 | 0 | rve->fpos.e_line, rve->fpos.e_col, trv->v.s.len, |
3625 | 0 | trv->v.s.s, rve->op); |
3626 | 0 | ret = 1; |
3627 | 0 | } |
3628 | | /* op(op($v, $w),b) => can't optimize */ |
3629 | 0 | } |
3630 | | /* op1(op2(...), b) and op1!=op2 or op is non assoc. |
3631 | | * => can't optimize */ |
3632 | 0 | } else if(rve_is_constant(rve->left.rve)) { |
3633 | | /* op1(a, op2(...)) */ |
3634 | 0 | if((rve->op == rve->right.rve->op) && rve_op_is_assoc(rve->op)) { |
3635 | | /* op(a, op(...)) */ |
3636 | 0 | if(rve_is_constant(rve->right.rve->right.rve) |
3637 | 0 | && rve_op_is_commutative(rve->op)) { |
3638 | | /* op(a, op($v, b)) => op(op(a, b), $v) */ |
3639 | | /* rv= op(a, b) */ |
3640 | 0 | tmp_rve.op = rve->op; |
3641 | 0 | tmp_rve.left.rve = rve->left.rve; |
3642 | 0 | tmp_rve.right.rve = rve->right.rve->right.rve; |
3643 | | /* no need for the RVE_PLUS_OP hack, all the bad |
3644 | | * cases are caught by rve_op_is_commutative() |
3645 | | * (in this case type will be typeof(a)) => ok only if |
3646 | | * typeof(a) is int) */ |
3647 | 0 | if((rv = rval_expr_eval_new(0, 0, &tmp_rve)) == 0) { |
3648 | 0 | LM_ERR("optimization failure, bad expression\n"); |
3649 | 0 | goto error; |
3650 | 0 | } |
3651 | | /* op(rv, $v) */ |
3652 | 0 | if(rve_replace_with_ct_rv(rve->left.rve, rv) < 0) |
3653 | 0 | goto error; |
3654 | 0 | rval_destroy(rv); |
3655 | 0 | rv = 0; |
3656 | 0 | rve_destroy(tmp_rve.right.rve); |
3657 | 0 | rve->right.rve = rve->right.rve->left.rve; |
3658 | 0 | trv = &rve->left.rve->left.rval; |
3659 | 0 | if(trv->type == RV_LONG) |
3660 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: " |
3661 | 0 | "op(a, op($v, b)) with op(%d, $v); op=%d\n", |
3662 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3663 | 0 | rve->fpos.e_line, rve->fpos.e_col, |
3664 | 0 | (int)trv->v.l, rve->op); |
3665 | 0 | else if(trv->type == RV_STR) |
3666 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve " |
3667 | 0 | "op(a, op($v, b)) with op(\"%.*s\", $v);" |
3668 | 0 | " op=%d\n", |
3669 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3670 | 0 | rve->fpos.e_line, rve->fpos.e_col, trv->v.s.len, |
3671 | 0 | trv->v.s.s, rve->op); |
3672 | 0 | ret = 1; |
3673 | 0 | } else if(rve_is_constant(rve->right.rve->left.rve)) { |
3674 | | /* op(a, op(b, $v)) => op(op(a, b), $v) */ |
3675 | | /* rv= op(a, b) */ |
3676 | 0 | tmp_rve.op = rve->op; |
3677 | 0 | tmp_rve.left.rve = rve->left.rve; |
3678 | 0 | tmp_rve.right.rve = rve->right.rve->left.rve; |
3679 | | /* hack for RVE_PLUS_OP which can work on string, ints |
3680 | | * or a combination of them */ |
3681 | 0 | if((rve->op == RVE_PLUS_OP) |
3682 | 0 | && (rve_guess_type(tmp_rve.left.rve) |
3683 | 0 | != rve_guess_type(tmp_rve.right.rve))) { |
3684 | 0 | LM_DBG("RVE optimization failed (%d,%d-%d,%d): cannot " |
3685 | 0 | "optimize +(a, +(b, $v)) when " |
3686 | 0 | "typeof(a)!=typeof(b)\n", |
3687 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3688 | 0 | rve->fpos.e_line, rve->fpos.e_col); |
3689 | 0 | return 0; |
3690 | 0 | } |
3691 | 0 | if((rv = rval_expr_eval_new(0, 0, &tmp_rve)) == 0) { |
3692 | 0 | LM_ERR("optimization failure, bad expression\n"); |
3693 | 0 | goto error; |
3694 | 0 | } |
3695 | | /* op(rv, $v) */ |
3696 | 0 | if(rve_replace_with_ct_rv(rve->left.rve, rv) < 0) |
3697 | 0 | goto error; |
3698 | 0 | rval_destroy(rv); |
3699 | 0 | rv = 0; |
3700 | 0 | rve_destroy(tmp_rve.right.rve); |
3701 | 0 | rve->right.rve = rve->right.rve->right.rve; |
3702 | 0 | trv = &rve->left.rve->left.rval; |
3703 | 0 | if(trv->type == RV_LONG) |
3704 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: " |
3705 | 0 | "op(a, op(b, $v)) with op(%d, $v); op=%d\n", |
3706 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3707 | 0 | rve->fpos.e_line, rve->fpos.e_col, |
3708 | 0 | (int)trv->v.l, rve->op); |
3709 | 0 | else if(trv->type == RV_STR) |
3710 | 0 | LM_DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve " |
3711 | 0 | "op(a, op(b, $v)) with op(\"%.*s\", $v);" |
3712 | 0 | " op=%d\n", |
3713 | 0 | rve->fpos.s_line, rve->fpos.s_col, |
3714 | 0 | rve->fpos.e_line, rve->fpos.e_col, trv->v.s.len, |
3715 | 0 | trv->v.s.s, rve->op); |
3716 | 0 | ret = 1; |
3717 | 0 | } |
3718 | | /* op(a, op($v, $w)) => can't optimize */ |
3719 | 0 | } |
3720 | | /* op1(a, op2(...)) and op1!=op2 or op is non assoc. |
3721 | | * => can't optimize */ |
3722 | 0 | } |
3723 | | /* op(op($v,a), op($w,b)) => no optimizations for now (TODO) */ |
3724 | 0 | } |
3725 | 0 | end: |
3726 | 0 | return ret; |
3727 | 0 | error: |
3728 | 0 | if(rv) |
3729 | 0 | rval_destroy(rv); |
3730 | 0 | return -1; |
3731 | 0 | } |
3732 | | |
3733 | | |
3734 | | /** fix a rval_expr. |
3735 | | * fixes action, bexprs, resolves selects, pvars and |
3736 | | * optimizes simple sub expressions (e.g. 1+2). |
3737 | | * |
3738 | | * @param p - pointer to a rval_expr |
3739 | | * @return 0 on success, <0 on error (modifies also *(struct rval_expr*)p) |
3740 | | */ |
3741 | | int fix_rval_expr(void *p) |
3742 | 0 | { |
3743 | 0 | struct rval_expr *rve; |
3744 | 0 | int ret; |
3745 | |
|
3746 | 0 | rve = (struct rval_expr *)p; |
3747 | |
|
3748 | 0 | switch(rve->op) { |
3749 | 0 | case RVE_NONE_OP: |
3750 | 0 | LM_BUG("empty rval expr\n"); |
3751 | 0 | break; |
3752 | 0 | case RVE_RVAL_OP: |
3753 | 0 | ret = fix_rval(&rve->left.rval, rve); |
3754 | 0 | if(ret < 0) |
3755 | 0 | goto error; |
3756 | 0 | return ret; |
3757 | 0 | case RVE_UMINUS_OP: /* unary operators */ |
3758 | 0 | case RVE_BOOL_OP: |
3759 | 0 | case RVE_LNOT_OP: |
3760 | 0 | case RVE_BNOT_OP: |
3761 | 0 | case RVE_STRLEN_OP: |
3762 | 0 | case RVE_STREMPTY_OP: |
3763 | 0 | case RVE_DEFINED_OP: |
3764 | 0 | case RVE_NOTDEFINED_OP: |
3765 | 0 | case RVE_LONG_OP: |
3766 | 0 | case RVE_STR_OP: |
3767 | 0 | ret = fix_rval_expr((void *)rve->left.rve); |
3768 | 0 | if(ret < 0) |
3769 | 0 | goto error; |
3770 | 0 | break; |
3771 | 0 | case RVE_MUL_OP: |
3772 | 0 | case RVE_DIV_OP: |
3773 | 0 | case RVE_MOD_OP: |
3774 | 0 | case RVE_MINUS_OP: |
3775 | 0 | case RVE_BOR_OP: |
3776 | 0 | case RVE_BAND_OP: |
3777 | 0 | case RVE_BXOR_OP: |
3778 | 0 | case RVE_BLSHIFT_OP: |
3779 | 0 | case RVE_BRSHIFT_OP: |
3780 | 0 | case RVE_LAND_OP: |
3781 | 0 | case RVE_LOR_OP: |
3782 | 0 | case RVE_GT_OP: |
3783 | 0 | case RVE_GTE_OP: |
3784 | 0 | case RVE_LT_OP: |
3785 | 0 | case RVE_LTE_OP: |
3786 | 0 | case RVE_PLUS_OP: |
3787 | 0 | case RVE_IPLUS_OP: |
3788 | 0 | case RVE_EQ_OP: |
3789 | 0 | case RVE_DIFF_OP: |
3790 | 0 | case RVE_IEQ_OP: |
3791 | 0 | case RVE_IDIFF_OP: |
3792 | 0 | case RVE_STREQ_OP: |
3793 | 0 | case RVE_STRDIFF_OP: |
3794 | 0 | case RVE_CONCAT_OP: |
3795 | 0 | case RVE_SELVALEXP_OP: |
3796 | 0 | case RVE_SELVALOPT_OP: |
3797 | 0 | ret = fix_rval_expr((void *)rve->left.rve); |
3798 | 0 | if(ret < 0) |
3799 | 0 | goto error; |
3800 | 0 | ret = fix_rval_expr((void *)rve->right.rve); |
3801 | 0 | if(ret < 0) |
3802 | 0 | goto error; |
3803 | 0 | break; |
3804 | 0 | case RVE_MATCH_OP: |
3805 | 0 | ret = fix_match_rve(rve); |
3806 | 0 | if(ret < 0) |
3807 | 0 | goto error; |
3808 | 0 | break; |
3809 | 0 | default: |
3810 | 0 | LM_BUG("unsupported op type %d (cfg line: %d col: %d)\n", rve->op, |
3811 | 0 | rve->fpos.s_line, rve->fpos.s_col); |
3812 | 0 | } |
3813 | | /* try to optimize */ |
3814 | 0 | rve_optimize(rve); |
3815 | 0 | return 0; |
3816 | | |
3817 | 0 | error: |
3818 | 0 | LM_ERR("failure in cfg at line: %d col: %d\n", rve->fpos.s_line, |
3819 | 0 | rve->fpos.s_col); |
3820 | 0 | return ret; |
3821 | 0 | } |