• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • Directories
  • File List
  • Globals

rvalue.c

Go to the documentation of this file.
00001 /* 
00002  * Copyright (C) 2008 iptelorg GmbH
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00024 /* 
00025  * History:
00026  * --------
00027  *  2008-12-01  initial version (andrei)
00028  *  2009-04-24  added support for defined, strempty, strlen (andrei)
00029  *  2009-04-28  int and str automatic conversions: (int)undef=0,
00030  *               (str)undef="", (int)""=0, (int)"123"=123, (int)"abc"=0
00031  *              handle undef == expr, in function of the UNDEF_EQ_* defines.
00032  *              (andrei)
00033  *  2009-05-05  casts operator for int & string (andrei)
00034  */
00035 
00036 /* special defines:
00037  *
00038  *  UNDEF_EQ_* - how to behave when undef is on the right side of a generic
00039  *               compare operator
00040  *  UNDEF_EQ_ALWAYS_FALSE:  undef  == something  is always false
00041  *  UNDEF_EQ_UNDEF_TRUE  :  undef == something false except for undef==undef
00042  *                          which is true
00043  *  no UNDEF_EQ* define  :  undef == expr => convert undef to typeof(expr)
00044  *                          and perform normal ==. undef == undef will be
00045  *                          converted to string and it will be true
00046  *                          ("" == "")
00047  * NOTE: expr == undef, with defined(expr) is always evaluated this way:
00048          expr == (type_of(expr))undef
00049  *  RV_STR2INT_VERBOSE_ERR - if a string conversion to int fails, log (L_WARN)
00050  *                           the string that caused it (only the string, not
00051  *                           the expression position).
00052  *  RV_STR2INT_ERR         - if a string conversion to int fails, don't ignore
00053  *                           the error (return error).
00054  *  RVAL_GET_INT_ERR_WARN  - if a conversion to int fails, log a warning with
00055  *                           the expression position.
00056  *                           Depends on RV_STR2INT_ERR.
00057  *  RVAL_GET_INT_ERR_IGN   - if a conversion to int fails, ignore the error
00058  *                           (the result will be 0). Can be combined with
00059  *                           RVAL_GET_INT_ERR_WARN.
00060  *                           Depends on RV_STR2INT_ERR.
00061  */
00062 
00063 
00064 #include "rvalue.h"
00065 
00066 #include <stdlib.h> /* abort() */
00067 
00068 /* if defined warn when str2int conversions fail */
00069 #define RV_STR2INT_VERBOSE_ERR
00070 
00071 /* if defined rval_get_int will fail if str2int conversion fail
00072    (else convert to 0) */
00073 #define RV_STR2INT_ERR
00074 
00075 /* if a rval_get_int fails (conversion to int), warn
00076    Depends on RV_STR2INT_ERR.
00077  */
00078 #define RVAL_GET_INT_ERR_WARN
00079 
00080 /* if a rval_get_int fails, ignore it (expression evaluation will not fail,
00081    the int conversion will result in 0).
00082    Can be combined with RVAL_GET_INT_ERR_WARN.
00083    Depends on RV_STR2INT_ERR.
00084  */
00085 #define RVAL_GET_INT_ERR_IGN
00086 
00087 /* minimum size alloc'ed for STR RVs (to accomodate
00088  * strops without reallocs) */
00089 #define RV_STR_EXTRA 80
00090 
00091 #define rv_ref(rv) ((rv)->refcnt++)
00092 
00094 #define rv_unref(rv) ((--(rv)->refcnt)==0)
00095 
00096 
00097 inline static void rval_force_clean(struct rvalue* rv)
00098 {
00099         if (rv->flags & RV_CNT_ALLOCED_F){
00100                 switch(rv->type){
00101                         case RV_STR:
00102                                 pkg_free(rv->v.s.s);
00103                                 rv->v.s.s=0;
00104                                 rv->v.s.len=0;
00105                                 break;
00106                         default:
00107                                 BUG("RV_CNT_ALLOCED_F not supported for type %d\n", rv->type);
00108                 }
00109                 rv->flags&=~RV_CNT_ALLOCED_F;
00110         }
00111         if (rv->flags & RV_RE_ALLOCED_F){
00112                 if (rv->v.re.regex){
00113                         if (unlikely(rv->type!=RV_STR || !(rv->flags & RV_RE_F))){
00114                                 BUG("RV_RE_ALLOCED_F not supported for type %d or "
00115                                                 "bad flags %x\n", rv->type, rv->flags);
00116                         }
00117                         regfree(rv->v.re.regex);
00118                         pkg_free(rv->v.re.regex);
00119                         rv->v.re.regex=0;
00120                 }
00121                 rv->flags&=~(RV_RE_ALLOCED_F|RV_RE_F);
00122         }
00123 }
00124 
00125 
00126 
00130 void rval_destroy(struct rvalue* rv)
00131 {
00132         if (rv && rv_unref(rv)){
00133                 rval_force_clean(rv);
00134                 /* still an un-regfreed RE ? */
00135                 if ((rv->flags & RV_RE_F) && rv->v.re.regex){
00136                         if (unlikely(rv->type!=RV_STR))
00137                                 BUG("RV_RE_F not supported for type %d\n", rv->type);
00138                         regfree(rv->v.re.regex);
00139                 }
00140                 if (rv->flags & RV_RV_ALLOCED_F){
00141                         pkg_free(rv);
00142                 }
00143         }
00144 }
00145 
00146 
00147 
00148 void rval_clean(struct rvalue* rv)
00149 {
00150         if (rv_unref(rv))
00151                 rval_force_clean(rv);
00152 }
00153 
00154 
00155 
00156 void rve_destroy(struct rval_expr* rve)
00157 {
00158         if (rve){
00159                 if (rve->op==RVE_RVAL_OP){
00160                         if (rve->left.rval.refcnt){
00161                                 if (rve->left.rval.refcnt==1)
00162                                         rval_destroy(&rve->left.rval);
00163                                 else
00164                                         BUG("rval expr rval with invalid refcnt: %d (%d,%d-%d,%d)"
00165                                                         "\n", rve->left.rval.refcnt,
00166                                                         rve->fpos.s_line, rve->fpos.s_col,
00167                                                         rve->fpos.e_line, rve->fpos.e_col);
00168                         }
00169                         if (rve->right.rval.refcnt){
00170                                 if (rve->right.rval.refcnt==1)
00171                                         rval_destroy(&rve->right.rval);
00172                                 else
00173                                         BUG("rval expr rval with invalid refcnt: %d (%d,%d-%d,%d)"
00174                                                         "\n", rve->right.rval.refcnt,
00175                                                         rve->fpos.s_line, rve->fpos.s_col,
00176                                                         rve->fpos.e_line, rve->fpos.e_col);
00177                         }
00178                 }else{
00179                         if (rve->left.rve)
00180                                 rve_destroy(rve->left.rve);
00181                         if (rve->right.rve)
00182                                 rve_destroy(rve->right.rve);
00183                 }
00184                 pkg_free(rve);
00185         }
00186 }
00187 
00188 
00189 
00190 void rval_cache_clean(struct rval_cache* rvc)
00191 {
00192         if ((rvc->cache_type==RV_CACHE_PVAR) && (rvc->val_type!=RV_NONE)){
00193                 pv_value_destroy(&rvc->c.pval);
00194         }
00195         rvc->cache_type=RV_CACHE_EMPTY;
00196         rvc->val_type=RV_NONE;
00197 }
00198 
00199 
00200 #define rv_chg_in_place(rv)  ((rv)->refcnt==1)
00201 
00202 
00203 
00208 void rval_init(struct rvalue* rv, enum rval_type t, union rval_val* v, 
00209                                 int flags)
00210 {
00211         rv->flags=flags;
00212         rv->refcnt=1;
00213         rv->type=t;
00214         if (v){
00215                 rv->v=*v;
00216         }else{
00217                 memset (&rv->v, 0, sizeof(rv->v));
00218         }
00219 }
00220 
00221 
00222 
00230 struct rvalue* rval_new_empty(int extra_size)
00231 {
00232         struct rvalue* rv;
00233         int size; /* extra size at the end */
00234         
00235         size=ROUND_LONG(sizeof(*rv)-sizeof(rv->buf)+extra_size); /* round up */
00236         rv=pkg_malloc(size);
00237         if (likely(rv)){
00238                 rv->bsize=size-sizeof(*rv)-sizeof(rv->buf); /* remaining size->buffer*/
00239                 rv->flags=RV_RV_ALLOCED_F;
00240                 rv->refcnt=1;
00241                 rv->type=RV_NONE;
00242         }
00243         return rv;
00244 }
00245 
00246 
00247 
00256 struct rvalue* rval_new_str(str* s, int extra_size)
00257 {
00258         struct rvalue* rv;
00259         
00260         rv=rval_new_empty(extra_size+s->len+1/* 0 term */);
00261         if (likely(rv)){
00262                 rv->type=RV_STR;
00263                 rv->v.s.s=&rv->buf[0];
00264                 rv->v.s.len=s->len;
00265                 memcpy(rv->v.s.s, s->s, s->len);
00266                 rv->v.s.s[s->len]=0;
00267         }
00268         return rv;
00269 }
00270 
00271 
00272 
00279 struct rvalue* rval_new_re(str* s)
00280 {
00281         struct rvalue* rv;
00282         long offs;
00283         
00284         offs=(long)&((struct rvalue*)0)->buf[0]; /* offset of the buf. member */
00285         /* make sure we reserve enough space so that we can satisfy any regex_t
00286            alignment requirement (pointer) */
00287         rv=rval_new_empty(ROUND_POINTER(offs)-offs+sizeof(*rv->v.re.regex)+
00288                                                 s->len+1/* 0 */);
00289         if (likely(rv)){
00290                 rv->type=RV_STR;
00291                 /* make sure regex points to a properly aligned address
00292                    (use max./pointer alignment to be sure ) */
00293                 rv->v.re.regex=(regex_t*)((char*)&rv->buf[0]+ROUND_POINTER(offs)-offs);
00294                 rv->v.s.s=(char*)rv->v.re.regex+sizeof(*rv->v.re.regex);
00295                 rv->v.s.len=s->len;
00296                 memcpy(rv->v.s.s, s->s, s->len);
00297                 rv->v.s.s[s->len]=0;
00298                 /* compile the regex */
00299                 /* same flags as for expr. =~ (fix_expr()) */
00300                 if (unlikely(regcomp(rv->v.re.regex, s->s,
00301                                                                 REG_EXTENDED|REG_NOSUB|REG_ICASE))){
00302                         /* error */
00303                         pkg_free(rv);
00304                         rv=0;
00305                 }else /* success */
00306                         rv->flags|=RV_RE_F;
00307         }
00308         return rv;
00309 }
00310 
00311 
00312 
00317 char* rval_type_name(enum rval_type type)
00318 {
00319         switch(type){
00320                 case RV_NONE:
00321                         return "none";
00322                 case RV_INT:
00323                         return "int";
00324                 case RV_STR:
00325                         return "str";
00326                 case RV_BEXPR:
00327                         return "bexpr_t";
00328                 case RV_ACTION_ST:
00329                         return "action_t";
00330                 case RV_PVAR:
00331                         return "pvar";
00332                 case RV_AVP:
00333                         return "avp";
00334                         break;
00335                 case RV_SEL:
00336                         return "select";
00337         }
00338         return "error_unknown_type";
00339 }
00340 
00341 
00342 
00351 struct rvalue* rval_new(enum rval_type t, union rval_val* v, int extra_size)
00352 {
00353         struct rvalue* rv;
00354         
00355         if (t==RV_STR && v && v->s.s)
00356                 return rval_new_str(&v->s, extra_size);
00357         rv=rval_new_empty(extra_size);
00358         if (likely(rv)){
00359                 rv->type=t;
00360                 if (likely(v && t!=RV_STR)){
00361                         rv->v=*v;
00362                 }else if (t==RV_STR){
00363                         rv->v.s.s=&rv->buf[0];
00364                         rv->v.s.len=0;
00365                         if (likely(extra_size)) rv->v.s.s[0]=0;
00366                 }else
00367                         memset (&rv->v, 0, sizeof(rv->v));
00368         }
00369         return rv;
00370 }
00371 
00372 
00373 
00389 inline static enum rval_type rval_get_btype(struct run_act_ctx* h,
00390                                                                                         struct sip_msg* msg,
00391                                                                                         struct rvalue* rv,
00392                                                                                         struct rval_cache* val_cache)
00393 {
00394         avp_t* r_avp;
00395         int_str tmp_avp_val;
00396         int_str* avpv;
00397         pv_value_t tmp_pval;
00398         pv_value_t* pv;
00399         enum rval_type tmp;
00400         enum rval_type* ptype;
00401         
00402         switch(rv->type){
00403                 case RV_INT:
00404                 case RV_STR:
00405                         return rv->type;
00406                 case RV_BEXPR:
00407                 case RV_ACTION_ST:
00408                         return RV_INT;
00409                 case RV_PVAR:
00410                         if (likely(val_cache && val_cache->cache_type==RV_CACHE_EMPTY)){
00411                                 pv=&val_cache->c.pval;
00412                                 val_cache->cache_type=RV_CACHE_PVAR;
00413                         }else{
00414                                 val_cache=0;
00415                                 pv=&tmp_pval;
00416                         }
00417                         memset(pv, 0, sizeof(tmp_pval));
00418                         if (likely(pv_get_spec_value(msg, &rv->v.pvs, pv)==0)){
00419                                 if (pv->flags & PV_TYPE_INT){
00420                                         if (likely(val_cache!=0))
00421                                                 val_cache->val_type=RV_INT;
00422                                         else
00423                                                 pv_value_destroy(pv);
00424                                         return RV_INT;
00425                                 }else if (pv->flags & PV_VAL_STR){
00426                                         if (likely(val_cache!=0))
00427                                                 val_cache->val_type=RV_STR;
00428                                         else
00429                                                 pv_value_destroy(pv);
00430                                         return RV_STR;
00431                                 }else{
00432                                         pv_value_destroy(pv);
00433                                         if (likely(val_cache!=0))
00434                                                 val_cache->val_type=RV_NONE; /* undefined */
00435                                         goto error;
00436                                 }
00437                         }else{
00438                                 if (likely(val_cache!=0))
00439                                         val_cache->val_type=RV_NONE; /* undefined */
00440                                 goto error;
00441                         }
00442                         break;
00443                 case RV_AVP:
00444                         if (likely(val_cache && val_cache->cache_type==RV_CACHE_EMPTY)){
00445                                 ptype=&val_cache->val_type;
00446                                 avpv=&val_cache->c.avp_val;
00447                                 val_cache->cache_type=RV_CACHE_AVP;
00448                         }else{
00449                                 ptype=&tmp;
00450                                 avpv=&tmp_avp_val;
00451                         }
00452                         r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
00453                                                                                         avpv, rv->v.avps.index);
00454                         if (likely(r_avp)){
00455                                 if (r_avp->flags & AVP_VAL_STR){
00456                                         *ptype=RV_STR;
00457                                         return RV_STR;
00458                                 }else{
00459                                         *ptype=RV_INT;
00460                                         return RV_INT;
00461                                 }
00462                         }else{
00463                                 *ptype=RV_NONE;
00464                                 goto error;
00465                         }
00466                         break;
00467                 case RV_SEL:
00468                         return RV_STR;
00469                 default:
00470                         BUG("rv type %d not handled\n", rv->type);
00471         }
00472 error:
00473         return RV_NONE;
00474 }
00475 
00476 
00477 
00482 enum rval_type rve_guess_type( struct rval_expr* rve)
00483 {
00484         switch(rve->op){
00485                 case RVE_RVAL_OP:
00486                         switch(rve->left.rval.type){
00487                                 case RV_STR:
00488                                 case RV_SEL:
00489                                         return RV_STR;
00490                                 case RV_INT:
00491                                 case RV_BEXPR:
00492                                 case RV_ACTION_ST:
00493                                         return RV_INT;
00494                                 case RV_PVAR:
00495                                 case RV_AVP:
00496                                 case RV_NONE:
00497                                         return RV_NONE;
00498                         }
00499                         break;
00500                 case RVE_UMINUS_OP:
00501                 case RVE_BOOL_OP:
00502                 case RVE_LNOT_OP:
00503                 case RVE_BNOT_OP:
00504                 case RVE_MINUS_OP:
00505                 case RVE_MUL_OP:
00506                 case RVE_DIV_OP:
00507                 case RVE_MOD_OP:
00508                 case RVE_BOR_OP:
00509                 case RVE_BAND_OP:
00510                 case RVE_BXOR_OP:
00511                 case RVE_BLSHIFT_OP:
00512                 case RVE_BRSHIFT_OP:
00513                 case RVE_LAND_OP:
00514                 case RVE_LOR_OP:
00515                 case RVE_GT_OP:
00516                 case RVE_GTE_OP:
00517                 case RVE_LT_OP:
00518                 case RVE_LTE_OP:
00519                 case RVE_EQ_OP:
00520                 case RVE_DIFF_OP:
00521                 case RVE_IEQ_OP:
00522                 case RVE_IDIFF_OP:
00523                 case RVE_STREQ_OP:
00524                 case RVE_STRDIFF_OP:
00525                 case RVE_MATCH_OP:
00526                 case RVE_IPLUS_OP:
00527                 case RVE_STRLEN_OP:
00528                 case RVE_STREMPTY_OP:
00529                 case RVE_DEFINED_OP:
00530                 case RVE_INT_OP:
00531                         return RV_INT;
00532                 case RVE_PLUS_OP:
00533                         /* '+' evaluates to the type of the left operand */
00534                         return rve_guess_type(rve->left.rve);
00535                 case RVE_CONCAT_OP:
00536                 case RVE_STR_OP:
00537                         return RV_STR;
00538                 case RVE_NONE_OP:
00539                         break;
00540         }
00541         return RV_NONE;
00542 }
00543 
00544 
00545 
00550 int rve_is_constant(struct rval_expr* rve)
00551 {
00552         switch(rve->op){
00553                 case RVE_RVAL_OP:
00554                         switch(rve->left.rval.type){
00555                                 case RV_STR:
00556                                         return 1;
00557                                 case RV_INT:
00558                                         return 1;
00559                                 case RV_SEL:
00560                                 case RV_BEXPR:
00561                                 case RV_ACTION_ST:
00562                                 case RV_PVAR:
00563                                 case RV_AVP:
00564                                 case RV_NONE:
00565                                         return 0;
00566                         }
00567                         break;
00568                 case RVE_UMINUS_OP:
00569                 case RVE_BOOL_OP:
00570                 case RVE_LNOT_OP:
00571                 case RVE_BNOT_OP:
00572                 case RVE_STRLEN_OP:
00573                 case RVE_STREMPTY_OP:
00574                 case RVE_DEFINED_OP:
00575                 case RVE_INT_OP:
00576                 case RVE_STR_OP:
00577                         return rve_is_constant(rve->left.rve);
00578                 case RVE_MINUS_OP:
00579                 case RVE_MUL_OP:
00580                 case RVE_DIV_OP:
00581                 case RVE_MOD_OP:
00582                 case RVE_BOR_OP:
00583                 case RVE_BAND_OP:
00584                 case RVE_BXOR_OP:
00585                 case RVE_BLSHIFT_OP:
00586                 case RVE_BRSHIFT_OP:
00587                 case RVE_LAND_OP:
00588                 case RVE_LOR_OP:
00589                 case RVE_GT_OP:
00590                 case RVE_GTE_OP:
00591                 case RVE_LT_OP:
00592                 case RVE_LTE_OP:
00593                 case RVE_EQ_OP:
00594                 case RVE_DIFF_OP:
00595                 case RVE_IEQ_OP:
00596                 case RVE_IDIFF_OP:
00597                 case RVE_STREQ_OP:
00598                 case RVE_STRDIFF_OP:
00599                 case RVE_MATCH_OP:
00600                 case RVE_PLUS_OP:
00601                 case RVE_IPLUS_OP:
00602                 case RVE_CONCAT_OP:
00603                         return rve_is_constant(rve->left.rve) &&
00604                                         rve_is_constant(rve->right.rve);
00605                 case RVE_NONE_OP:
00606                         break;
00607         }
00608         return 0;
00609 }
00610 
00611 
00612 
00617 int rve_has_side_effects(struct rval_expr* rve)
00618 {
00619         return !rve_is_constant(rve);
00620 }
00621 
00622 
00623 
00627 static int rve_op_unary(enum rval_expr_op op)
00628 {
00629         switch(op){
00630                 case RVE_RVAL_OP: /* not realy an operator */
00631                         return -1;
00632                 case RVE_UMINUS_OP:
00633                 case RVE_BOOL_OP:
00634                 case RVE_LNOT_OP:
00635                 case RVE_BNOT_OP:
00636                 case RVE_STRLEN_OP:
00637                 case RVE_STREMPTY_OP:
00638                 case RVE_DEFINED_OP:
00639                 case RVE_INT_OP:
00640                 case RVE_STR_OP:
00641                         return 1;
00642                 case RVE_MINUS_OP:
00643                 case RVE_MUL_OP:
00644                 case RVE_DIV_OP:
00645                 case RVE_MOD_OP:
00646                 case RVE_BOR_OP:
00647                 case RVE_BAND_OP:
00648                 case RVE_BXOR_OP:
00649                 case RVE_BLSHIFT_OP:
00650                 case RVE_BRSHIFT_OP:
00651                 case RVE_LAND_OP:
00652                 case RVE_LOR_OP:
00653                 case RVE_GT_OP:
00654                 case RVE_GTE_OP:
00655                 case RVE_LT_OP:
00656                 case RVE_LTE_OP:
00657                 case RVE_EQ_OP:
00658                 case RVE_DIFF_OP:
00659                 case RVE_IEQ_OP:
00660                 case RVE_IDIFF_OP:
00661                 case RVE_STREQ_OP:
00662                 case RVE_STRDIFF_OP:
00663                 case RVE_MATCH_OP:
00664                 case RVE_PLUS_OP:
00665                 case RVE_IPLUS_OP:
00666                 case RVE_CONCAT_OP:
00667                         return 0;
00668                 case RVE_NONE_OP:
00669                         return -1;
00670                         break;
00671         }
00672         return 0;
00673 }
00674 
00675 
00676 
00690 int rve_check_type(enum rval_type* type, struct rval_expr* rve,
00691                                         struct rval_expr** bad_rve, 
00692                                         enum rval_type* bad_t,
00693                                         enum rval_type* exp_t)
00694 {
00695         enum rval_type type1, type2;
00696         
00697         switch(rve->op){
00698                 case RVE_RVAL_OP:
00699                         *type=rve_guess_type(rve);
00700                         return 1;
00701                 case RVE_UMINUS_OP:
00702                 case RVE_BOOL_OP:
00703                 case RVE_LNOT_OP:
00704                 case RVE_BNOT_OP:
00705                         *type=RV_INT;
00706                         if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
00707                                 if (type1==RV_STR){
00708                                         if (bad_rve) *bad_rve=rve->left.rve;
00709                                         if (bad_t) *bad_t=type1;
00710                                         if (exp_t) *exp_t=RV_INT;
00711                                         return 0;
00712                                 }
00713                                 return 1;
00714                         }
00715                         return 0;
00716                         break;
00717                 case RVE_MINUS_OP:
00718                 case RVE_MUL_OP:
00719                 case RVE_DIV_OP:
00720                 case RVE_MOD_OP:
00721                 case RVE_BOR_OP:
00722                 case RVE_BAND_OP:
00723                 case RVE_BXOR_OP:
00724                 case RVE_BLSHIFT_OP:
00725                 case RVE_BRSHIFT_OP:
00726                 case RVE_LAND_OP:
00727                 case RVE_LOR_OP:
00728                 case RVE_GT_OP:
00729                 case RVE_GTE_OP:
00730                 case RVE_LT_OP:
00731                 case RVE_LTE_OP:
00732                 case RVE_IEQ_OP:
00733                 case RVE_IDIFF_OP:
00734                 case RVE_IPLUS_OP:
00735                         *type=RV_INT;
00736                         if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
00737                                 if (type1==RV_STR){
00738                                         if (bad_rve) *bad_rve=rve->left.rve;
00739                                         if (bad_t) *bad_t=type1;
00740                                         if (exp_t) *exp_t=RV_INT;
00741                                         return 0;
00742                                 }
00743                                 if (rve_check_type(&type2, rve->right.rve, bad_rve,
00744                                                                         bad_t, exp_t)){
00745                                         if (type2==RV_STR){
00746                                                 if (bad_rve) *bad_rve=rve->right.rve;
00747                                                 if (bad_t) *bad_t=type2;
00748                                                 if (exp_t) *exp_t=RV_INT;
00749                                                 return 0;
00750                                         }
00751                                         return 1;
00752                                 }
00753                         }
00754                         return 0;
00755                 case RVE_EQ_OP:
00756                 case RVE_DIFF_OP:
00757                         *type=RV_INT;
00758                         if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
00759                                 if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
00760                                                                                 exp_t)){
00761                                         if ((type2!=type1) && (type1!=RV_NONE) &&
00762                                                         (type2!=RV_NONE) && 
00763                                                         !(type1==RV_STR && type2==RV_INT)){
00764                                                 if (bad_rve) *bad_rve=rve->right.rve;
00765                                                 if (bad_t) *bad_t=type2;
00766                                                 if (exp_t) *exp_t=type1;
00767                                                 return 0;
00768                                         }
00769                                         return 1;
00770                                 }
00771                         }
00772                         return 0;
00773                 case RVE_PLUS_OP:
00774                         *type=RV_NONE;
00775                         if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
00776                                 if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
00777                                                                         exp_t)){
00778                                         if ((type2!=type1) && (type1!=RV_NONE) &&
00779                                                         (type2!=RV_NONE) && 
00780                                                         !(type1==RV_STR && type2==RV_INT)){
00781                                                 if (bad_rve) *bad_rve=rve->right.rve;
00782                                                 if (bad_t) *bad_t=type2;
00783                                                 if (exp_t) *exp_t=type1;
00784                                                 return 0;
00785                                         }
00786                                         *type=type1;
00787                                         return 1;
00788                                 }
00789                         }
00790                         break;
00791                 case RVE_CONCAT_OP:
00792                         *type=RV_STR;
00793                         if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
00794                                 if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
00795                                                                         exp_t)){
00796                                         if ((type2!=type1) && (type1!=RV_NONE) &&
00797                                                         (type2!=RV_NONE) && 
00798                                                         !(type1==RV_STR && type2==RV_INT)){
00799                                                 if (bad_rve) *bad_rve=rve->right.rve;
00800                                                 if (bad_t) *bad_t=type2;
00801                                                 if (exp_t) *exp_t=type1;
00802                                                 return 0;
00803                                         }
00804                                         if (type1==RV_INT){
00805                                                 if (bad_rve) *bad_rve=rve->left.rve;
00806                                                 if (bad_t) *bad_t=type1;
00807                                                 if (exp_t) *exp_t=RV_STR;
00808                                                 return 0;
00809                                         }
00810                                         return 1;
00811                                 }
00812                         }
00813                         break;
00814                 case RVE_STREQ_OP:
00815                 case RVE_STRDIFF_OP:
00816                 case RVE_MATCH_OP:
00817                         *type=RV_INT;
00818                         if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
00819                                 if (rve_check_type(&type2, rve->right.rve, bad_rve, bad_t,
00820                                                                         exp_t)){
00821                                         if ((type2!=type1) && (type1!=RV_NONE) &&
00822                                                         (type2!=RV_NONE) &&
00823                                                         !(type1==RV_STR && type2==RV_INT)){
00824                                                 if (bad_rve) *bad_rve=rve->right.rve;
00825                                                 if (bad_t) *bad_t=type2;
00826                                                 if (exp_t) *exp_t=type1;
00827                                                 return 0;
00828                                         }
00829                                         if (type1==RV_INT){
00830                                                 if (bad_rve) *bad_rve=rve->left.rve;
00831                                                 if (bad_t) *bad_t=type1;
00832                                                 if (exp_t) *exp_t=RV_STR;
00833                                                 return 0;
00834                                         }
00835                                         return 1;
00836                                 }
00837                         }
00838                         break;
00839                 case RVE_STRLEN_OP:
00840                 case RVE_STREMPTY_OP:
00841                 case RVE_DEFINED_OP:
00842                         *type=RV_INT;
00843                         if (rve_check_type(&type1, rve->left.rve, bad_rve, bad_t, exp_t)){
00844                                 if (type1==RV_INT){
00845                                         if (bad_rve) *bad_rve=rve->left.rve;
00846                                         if (bad_t) *bad_t=type1;
00847                                         if (exp_t) *exp_t=RV_STR;
00848                                         return 0;
00849                                 }
00850                                 return 1;
00851                         }
00852                         break;
00853                 case RVE_INT_OP:
00854                         *type=RV_INT;
00855                         return 1;
00856                         break;
00857                 case RVE_STR_OP:
00858                         *type=RV_STR;
00859                         return 1;
00860                         break;
00861                 case RVE_NONE_OP:
00862                 default:
00863                         BUG("unexpected rve op %d (%d,%d-%d,%d)\n", rve->op,
00864                                         rve->fpos.s_line, rve->fpos.s_col,
00865                                         rve->fpos.e_line, rve->fpos.e_col);
00866                         if (bad_rve) *bad_rve=rve;
00867                         if (bad_t) *bad_t=RV_NONE;
00868                         if (exp_t) *exp_t=RV_STR;
00869                         break;
00870         }
00871         return 0;
00872 }
00873 
00874 
00875 
00889 int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
00890                                                                 int* i, struct rvalue* rv,
00891                                                                 struct rval_cache* cache)
00892 {
00893         avp_t* r_avp;
00894         int_str avp_val;
00895         pv_value_t pval;
00896         str tmp;
00897         str* s;
00898         int r, ret;
00899         int destroy_pval;
00900         
00901         destroy_pval=0;
00902         s=0;
00903         ret=0;
00904         switch(rv->type){
00905                 case RV_INT:
00906                         *i=rv->v.l;
00907                         break;
00908                 case RV_STR:
00909                         s=&rv->v.s;
00910                         goto rv_str;
00911                 case RV_BEXPR:
00912                         *i=eval_expr(h, rv->v.bexpr, msg);
00913                         if (*i==EXPR_DROP){
00914                                 *i=0; /* false */
00915                                 return EXPR_DROP;
00916                         }
00917                         break;
00918                 case RV_ACTION_ST:
00919                         if (rv->v.action) {
00920                                 *i=(run_actions_safe(h, rv->v.action, msg)>0);
00921                                 h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
00922                                                                                                                     break in expr*/
00923                         } else
00924                                 *i=0;
00925                         break;
00926                 case RV_SEL:
00927                         r=run_select(&tmp, &rv->v.sel, msg);
00928                         if (unlikely(r!=0)){
00929                                 if (r<0)
00930                                         goto eval_error;
00931                                 else /* i>0  => undefined */
00932                                         goto undef;
00933                         }
00934                         s=&tmp;
00935                         goto rv_str;
00936                 case RV_AVP:
00937                         if (unlikely(cache && cache->cache_type==RV_CACHE_AVP)){
00938                                 if (likely(cache->val_type==RV_INT)){
00939                                         *i=cache->c.avp_val.n;
00940                                 }else if (cache->val_type==RV_STR){
00941                                         s=&cache->c.avp_val.s;
00942                                         goto rv_str;
00943                                 }else if (cache->val_type==RV_NONE)
00944                                         goto undef;
00945                                 else goto error_cache;
00946                         }else{
00947                                 r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
00948                                                                                         &avp_val, rv->v.avps.index);
00949                                 if (likely(r_avp)){
00950                                         if (unlikely(r_avp->flags & AVP_VAL_STR)){
00951                                                 s=&avp_val.s;
00952                                                 goto rv_str;
00953                                         }else{
00954                                                 *i=avp_val.n;
00955                                         }
00956                                 }else{
00957                                         goto undef;
00958                                 }
00959                         }
00960                         break;
00961                 case RV_PVAR:
00962                         if (unlikely(cache && cache->cache_type==RV_CACHE_PVAR)){
00963                                 if (likely((cache->val_type==RV_INT) ||
00964                                                                 (cache->c.pval.flags & PV_VAL_INT))){
00965                                         *i=cache->c.pval.ri;
00966                                 }else if (cache->val_type==RV_STR){
00967                                         s=&cache->c.pval.rs;
00968                                         goto rv_str;
00969                                 }else if (cache->val_type==RV_NONE)
00970                                         goto undef;
00971                                 else goto error_cache;
00972                         }else{
00973                                 memset(&pval, 0, sizeof(pval));
00974                                 if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
00975                                         if (likely(pval.flags & PV_VAL_INT)){
00976                                                 *i=pval.ri;
00977                                                 pv_value_destroy(&pval);
00978                                         }else if (likely(pval.flags & PV_VAL_STR)){
00979                                                 destroy_pval=1; /* we must pv_value_destroy() later*/
00980                                                 s=&pval.rs;
00981                                                 goto rv_str;
00982                                         }else{
00983                                                 /* no PV_VAL_STR and no PV_VAL_INT => undef
00984                                                    (PV_VAL_NULL) */
00985                                                 pv_value_destroy(&pval);
00986                                                 goto undef;
00987                                         }
00988                                 }else{
00989                                         goto eval_error;
00990                                 }
00991                         }
00992                         break;
00993                 default:
00994                         BUG("rv type %d not handled\n", rv->type);
00995                         goto error;
00996         }
00997         return ret;
00998 undef:
00999 eval_error: /* same as undefined */
01000         /* handle undefined => result 0, return success */
01001         *i=0;
01002         return 0;
01003 rv_str:
01004         /* rv is of string type => try to convert it to int */
01005         /* if "" => 0 (most likely case) */
01006         if (likely(s->len==0)) *i=0;
01007         else if (unlikely(str2sint(s, i)!=0)){
01008                 /* error converting to int => non numeric => 0 */
01009                 *i=0;
01010 #ifdef RV_STR2INT_VERBOSE_ERR
01011                 WARN("automatic string to int conversion for \"%.*s\" failed\n",
01012                                 s->len, ZSW(s->s));
01013                 /* return an error code */
01014 #endif
01015 #ifdef RV_STR2INT_ERR
01016                 ret=-1;
01017 #endif
01018         }
01019         if (destroy_pval)
01020                 pv_value_destroy(&pval);
01021         return ret;
01022 error_cache:
01023         BUG("invalid cached value:cache type %d, value type %d\n",
01024                         cache?cache->cache_type:0, cache?cache->val_type:0);
01025 error:
01026         if (destroy_pval)
01027                 pv_value_destroy(&pval);
01028         *i=0;
01029         return -1;
01030 }
01031 
01032 
01033 
01035 #define RVE_LOG(lev, rve, txt) \
01036         LOG((lev), txt " (%d,%d-%d,%d)\n", \
01037                         (rve)->fpos.s_line, rve->fpos.s_col, \
01038                         (rve)->fpos.e_line, rve->fpos.e_col )
01039 
01040 
01049 #if defined RVAL_GET_INT_ERR_WARN && defined RVAL_GET_INT_ERR_IGN
01050 #define rval_get_int_handle_ret(ret, txt, rve) \
01051         do { \
01052                 if (unlikely((ret)<0)) { \
01053                         RVE_LOG(L_WARN, rve, txt); \
01054                         (ret)=0; \
01055                 } \
01056         }while(0)
01057 #elif defined RVAL_GET_INT_ERR_WARN
01058 #define rval_get_int_handle_ret(ret, txt, rve) \
01059         do { \
01060                 if (unlikely((ret)<0)) \
01061                         RVE_LOG(L_WARN, rve, txt); \
01062         }while(0)
01063 #elif defined RVAL_GET_INT_ERR_IGN
01064 #define rval_get_int_handle_ret(ret, txt, rve) \
01065         do { \
01066                 if (unlikely((ret)<0)) \
01067                                 (ret)=0; \
01068         } while(0)
01069 #else
01070 #define rval_get_int_handle_ret(ret, txt, rve) /* do nothing */
01071 #endif
01072 
01073 
01074 
01075 
01076 
01077 
01102 int rval_get_tmp_str(struct run_act_ctx* h, struct sip_msg* msg,
01103                                                                 str* tmpv, struct rvalue* rv,
01104                                                                 struct rval_cache* cache,
01105                                                                 struct rval_cache* tmp_cache)
01106 {
01107         avp_t* r_avp;
01108         int i;
01109         
01110         switch(rv->type){
01111                 case RV_INT:
01112                         tmpv->s=sint2strbuf(rv->v.l, tmp_cache->i2s,
01113                                                                 sizeof(tmp_cache->i2s), &tmpv->len);
01114                         tmp_cache->cache_type = RV_CACHE_INT2STR;
01115                         break;
01116                 case RV_STR:
01117                         *tmpv=rv->v.s;
01118                         break;
01119                 case RV_ACTION_ST:
01120                         if (rv->v.action) {
01121                                 i=(run_actions_safe(h, rv->v.action, msg)>0);
01122                                 h->run_flags &= ~(RETURN_R_F|BREAK_R_F); /* catch return &
01123                                                                                                                     break in expr*/
01124                         } else
01125                                 i=0;
01126                         tmpv->s=sint2strbuf(i, tmp_cache->i2s,
01127                                                                 sizeof(tmp_cache->i2s), &tmpv->len);
01128                         tmp_cache->cache_type = RV_CACHE_INT2STR;
01129                         break;
01130                 case RV_BEXPR:
01131                         i=eval_expr(h, rv->v.bexpr, msg);
01132                         if (i==EXPR_DROP){
01133                                 i=0; /* false */
01134                                 tmpv->s=sint2strbuf(i, tmp_cache->i2s,
01135                                                 sizeof(tmp_cache->i2s), &tmpv->len);
01136                                 tmp_cache->cache_type = RV_CACHE_INT2STR;
01137                                 return EXPR_DROP;
01138                         }
01139                         tmpv->s=sint2strbuf(i, tmp_cache->i2s, sizeof(tmp_cache->i2s),
01140                                                                 &tmpv->len);
01141                         tmp_cache->cache_type = RV_CACHE_INT2STR;
01142                         break;
01143                 case RV_SEL:
01144                         i=run_select(tmpv, &rv->v.sel, msg);
01145                         if (unlikely(i!=0)){
01146                                 if (i<0){
01147                                         goto eval_error;
01148                                 }else { /* i>0  => undefined */
01149                                         goto undef;
01150                                 }
01151                         }
01152                         break;
01153                 case RV_AVP:
01154                         if (likely(cache && cache->cache_type==RV_CACHE_AVP)){
01155                                 if (likely(cache->val_type==RV_STR)){
01156                                         *tmpv=cache->c.avp_val.s;
01157                                 }else if (cache->val_type==RV_INT){
01158                                         i=cache->c.avp_val.n;
01159                                         tmpv->s=sint2strbuf(i, tmp_cache->i2s,
01160                                                                                 sizeof(tmp_cache->i2s), &tmpv->len);
01161                                         tmp_cache->cache_type = RV_CACHE_INT2STR;
01162                                 }else if (cache->val_type==RV_NONE){
01163                                         goto undef;
01164                                 }else goto error_cache;
01165                         }else{
01166                                 r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
01167                                                                                         &tmp_cache->c.avp_val,
01168                                                                                         rv->v.avps.index);
01169                                 if (likely(r_avp)){
01170                                         if (likely(r_avp->flags & AVP_VAL_STR)){
01171                                                 tmp_cache->cache_type=RV_CACHE_AVP;
01172                                                 tmp_cache->val_type=RV_STR;
01173                                                 *tmpv=tmp_cache->c.avp_val.s;
01174                                         }else{
01175                                                 i=tmp_cache->c.avp_val.n;
01176                                                 tmpv->s=sint2strbuf(i, tmp_cache->i2s,
01177                                                                                 sizeof(tmp_cache->i2s), &tmpv->len);
01178                                                 tmp_cache->cache_type = RV_CACHE_INT2STR;
01179                                         }
01180                                 }else goto undef;
01181                         }
01182                         break;
01183                 case RV_PVAR:
01184                         if (likely(cache && cache->cache_type==RV_CACHE_PVAR)){
01185                                 if (likely(cache->val_type==RV_STR)){
01186                                         *tmpv=cache->c.pval.rs;
01187                                 }else if (cache->val_type==RV_INT){
01188                                         i=cache->c.pval.ri;
01189                                         tmpv->s=sint2strbuf(i, tmp_cache->i2s,
01190                                                                                 sizeof(tmp_cache->i2s), &tmpv->len);
01191                                         tmp_cache->cache_type = RV_CACHE_INT2STR;
01192                                 }else if (cache->val_type==RV_NONE){
01193                                         goto undef;
01194                                 }else goto error_cache;
01195                         }else{
01196                                 memset(&tmp_cache->c.pval, 0, sizeof(tmp_cache->c.pval));
01197                                 if (likely(pv_get_spec_value(msg, &rv->v.pvs,
01198                                                                                                 &tmp_cache->c.pval)==0)){
01199                                         if (likely(tmp_cache->c.pval.flags & PV_VAL_STR)){
01200                                                 /*  the value is not destroyed, but saved instead
01201                                                         in tmp_cache so that it can be destroyed later
01202                                                         when no longer needed */
01203                                                 tmp_cache->cache_type=RV_CACHE_PVAR;
01204                                                 tmp_cache->val_type=RV_STR;
01205                                                 *tmpv=tmp_cache->c.pval.rs;
01206                                         }else if (likely(tmp_cache->c.pval.flags & PV_VAL_INT)){
01207                                                 i=tmp_cache->c.pval.ri;
01208                                                 pv_value_destroy(&tmp_cache->c.pval);
01209                                                 tmpv->s=sint2strbuf(i, tmp_cache->i2s,
01210                                                                                 sizeof(tmp_cache->i2s), &tmpv->len);
01211                                                 tmp_cache->cache_type = RV_CACHE_INT2STR;
01212                                         }else{
01213                                                 /* no PV_VAL_STR and no PV_VAL_INT => undef
01214                                                    (PV_VAL_NULL) */
01215                                                 pv_value_destroy(&tmp_cache->c.pval);
01216                                                 goto undef;
01217                                         }
01218                                 }else{
01219                                         goto eval_error;
01220                                 }
01221                         }
01222                         break;
01223                 default:
01224                         BUG("rv type %d not handled\n", rv->type);
01225                         goto error;
01226         }
01227         return 0;
01228 undef:
01229 eval_error: /* same as undefined */
01230         /* handle undefined => result "", return success */
01231         tmpv->s="";
01232         tmpv->len=0;
01233         return 0;
01234 error_cache:
01235         BUG("invalid cached value:cache type %d, value type %d\n",
01236                         cache?cache->cache_type:0, cache?cache->val_type:0);
01237 error:
01238         tmpv->s="";
01239         tmpv->len=0;
01240         return -1;
01241 }
01242 
01243 
01244 
01250 int rval_get_str(struct run_act_ctx* h, struct sip_msg* msg,
01251                                                                 str* s, struct rvalue* rv,
01252                                                                 struct rval_cache* cache)
01253 {
01254         str tmp;
01255         struct rval_cache tmp_cache;
01256         
01257         rval_cache_init(&tmp_cache);
01258         if (unlikely(rval_get_tmp_str(h, msg, &tmp, rv, cache, &tmp_cache)<0))
01259                 goto error;
01260         s->s=pkg_malloc(tmp.len+1/* 0 term */);
01261         if (unlikely(s->s==0)){
01262                 ERR("memory allocation error\n");
01263                 goto error;
01264         }
01265         s->len=tmp.len;
01266         memcpy(s->s, tmp.s, tmp.len);
01267         s->s[tmp.len]=0; /* 0 term */
01268         rval_cache_clean(&tmp_cache);
01269         return 0;
01270 error:
01271         rval_cache_clean(&tmp_cache);
01272         return -1;
01273 }
01274 
01275 
01276 
01294 struct rvalue* rval_convert(struct run_act_ctx* h, struct sip_msg* msg,
01295                                                         enum rval_type type, struct rvalue* v,
01296                                                         struct rval_cache* c)
01297 {
01298         int i;
01299         struct rval_cache tmp_cache;
01300         str tmp;
01301         struct rvalue* ret;
01302         union rval_val val;
01303         
01304         if (v->type==type){
01305                 rv_ref(v);
01306                 return v;
01307         }
01308         switch(type){
01309                 case RV_INT:
01310                         if (unlikely(rval_get_int(h, msg, &i, v, c) < 0))
01311                                 return 0;
01312                         val.l=i;
01313                         return rval_new(RV_INT, &val, 0);
01314                 case RV_STR:
01315                         rval_cache_init(&tmp_cache);
01316                         if (unlikely(rval_get_tmp_str(h, msg, &tmp, v, c, &tmp_cache) < 0))
01317                         {
01318                                 rval_cache_clean(&tmp_cache);
01319                                 return 0;
01320                         }
01321                         ret=rval_new_str(&tmp, RV_STR_EXTRA);
01322                         rval_cache_clean(&tmp_cache);
01323                         return ret;
01324                 case RV_NONE:
01325                 default:
01326                         BUG("unsupported conversion to type %d\n", type);
01327                         return 0;
01328         }
01329         return 0;
01330 }
01331 
01332 
01333 
01337 inline static int int_intop1(int* res, enum rval_expr_op op, int v)
01338 {
01339         switch(op){
01340                 case RVE_UMINUS_OP:
01341                         *res=-v;
01342                         break;
01343                 case RVE_BOOL_OP:
01344                         *res=!!v;
01345                         break;
01346                 case RVE_LNOT_OP:
01347                         *res=!v;
01348                         break;
01349                 case RVE_BNOT_OP:
01350                         *res=~v;
01351                         break;
01352                 default:
01353                         BUG("rv unsupported intop1 %d\n", op);
01354                         return -1;
01355         }
01356         return 0;
01357 }
01358 
01359 
01360 
01364 inline static int int_intop2(int* res, enum rval_expr_op op, int v1, int v2)
01365 {
01366         switch(op){
01367                 case RVE_PLUS_OP:
01368                 case RVE_IPLUS_OP:
01369                         *res=v1+v2;
01370                         break;
01371                 case RVE_MINUS_OP:
01372                         *res=v1-v2;
01373                         break;
01374                 case RVE_MUL_OP:
01375                         *res=v1*v2;
01376                         break;
01377                 case RVE_DIV_OP:
01378                         if (unlikely(v2==0)){
01379                                 ERR("rv div by 0\n");
01380                                 return -1;
01381                         }
01382                         *res=v1/v2;
01383                         break;
01384                 case RVE_MOD_OP:
01385                         if (unlikely(v2==0)){
01386                                 ERR("rv mod by 0\n");
01387                                 return -1;
01388                         }
01389                         *res=v1%v2;
01390                         break;
01391                 case RVE_BOR_OP:
01392                         *res=v1|v2;
01393                         break;
01394                 case RVE_BAND_OP:
01395                         *res=v1&v2;
01396                         break;
01397                 case RVE_BXOR_OP:
01398                         *res=v1^v2;
01399                         break;
01400                 case RVE_BLSHIFT_OP:
01401                         *res=v1<<v2;
01402                         break;
01403                 case RVE_BRSHIFT_OP:
01404                         *res=v1>>v2;
01405                         break;
01406                 case RVE_LAND_OP:
01407                         *res=v1 && v2;
01408                         break;
01409                 case RVE_LOR_OP:
01410                         *res=v1 || v2;
01411                         break;
01412                 case RVE_GT_OP:
01413                         *res=v1 > v2;
01414                         break;
01415                 case RVE_GTE_OP:
01416                         *res=v1 >= v2;
01417                         break;
01418                 case RVE_LT_OP:
01419                         *res=v1 < v2;
01420                         break;
01421                 case RVE_LTE_OP:
01422                         *res=v1 <= v2;
01423                         break;
01424                 case RVE_EQ_OP:
01425                 case RVE_IEQ_OP:
01426                         *res=v1 == v2;
01427                         break;
01428                 case RVE_DIFF_OP:
01429                 case RVE_IDIFF_OP:
01430                         *res=v1 != v2;
01431                         break;
01432                 case RVE_CONCAT_OP:
01433                         *res=0;
01434                         /* invalid operand for int */
01435                         return -1;
01436                 default:
01437                         BUG("rv unsupported intop %d\n", op);
01438                         return -1;
01439         }
01440         return 0;
01441 }
01442 
01443 
01444 
01449 inline static int bool_rvstrop2( enum rval_expr_op op, int* res,
01450                                                                 struct rvalue* rv1, struct rvalue* rv2)
01451 {
01452         str* s1;
01453         str* s2;
01454         regex_t tmp_re;
01455         
01456         s1=&rv1->v.s;
01457         s2=&rv2->v.s;
01458         switch(op){
01459                 case RVE_EQ_OP:
01460                 case RVE_STREQ_OP:
01461                         *res= (s1->len==s2->len) && (memcmp(s1->s, s2->s, s1->len)==0);
01462                         break;
01463                 case RVE_DIFF_OP:
01464                 case RVE_STRDIFF_OP:
01465                         *res= (s1->len!=s2->len) || (memcmp(s1->s, s2->s, s1->len)!=0);
01466                         break;
01467                 case RVE_MATCH_OP:
01468                         if (likely(rv2->flags & RV_RE_F)){
01469                                 *res=(regexec(rv2->v.re.regex, rv1->v.s.s, 0, 0, 0)==0);
01470                         }else{
01471                                 /* we need to compile the RE on the fly */
01472                                 if (unlikely(regcomp(&tmp_re, s2->s,
01473                                                                                 REG_EXTENDED|REG_NOSUB|REG_ICASE))){
01474                                         /* error */
01475                                         ERR("Bad regular expression \"%s\"\n", s2->s);
01476                                         goto error;
01477                                 }
01478                                 *res=(regexec(&tmp_re, s1->s, 0, 0, 0)==0);
01479                                 regfree(&tmp_re);
01480                         }
01481                         break;
01482                 default:
01483                         BUG("rv unsupported intop %d\n", op);
01484                         goto error;
01485         }
01486         return 0;
01487 error:
01488         *res=0; /* false */
01489         return -1;
01490 }
01491 
01492 
01493 
01497 inline static int int_strop1(int* res, enum rval_expr_op op, str* s1)
01498 {
01499         switch(op){
01500                 case RVE_STRLEN_OP:
01501                         *res=s1->len;
01502                         break;
01503                 case RVE_STREMPTY_OP:
01504                         *res=(s1->len==0);
01505                         break;
01506                 default:
01507                         BUG("rv unsupported int_strop1 %d\n", op);
01508                         *res=0;
01509                         return -1;
01510         }
01511         return 0;
01512 }
01513 
01514 
01515 
01519 inline static struct rvalue* rval_intop1(struct run_act_ctx* h,
01520                                                                                         struct sip_msg* msg,
01521                                                                                         enum rval_expr_op op,
01522                                                                                         struct rvalue* v)
01523 {
01524         struct rvalue* rv2;
01525         struct rvalue* ret;
01526         int i;
01527         
01528         i=0;
01529         rv2=rval_convert(h, msg, RV_INT, v, 0);
01530         if (unlikely(rv2==0)){
01531                 ERR("rval int conversion failed\n");
01532                 goto error;
01533         }
01534         if (unlikely(int_intop1(&i, op, rv2->v.l)<0))
01535                 goto error;
01536         if (rv_chg_in_place(rv2)){
01537                 ret=rv2;
01538                 rv_ref(ret);
01539         }else if (rv_chg_in_place(v)){
01540                 ret=v;
01541                 rv_ref(ret);
01542         }else{
01543                 ret=rval_new(RV_INT, &rv2->v, 0);
01544                 if (unlikely(ret==0)){
01545                         ERR("eval out of memory\n");
01546                         goto error;
01547                 }
01548         }
01549         rval_destroy(rv2);
01550         ret->v.l=i;
01551         return ret;
01552 error:
01553         rval_destroy(rv2);
01554         return 0;
01555 }
01556 
01557 
01558 
01562 inline static struct rvalue* rval_intop2(struct run_act_ctx* h,
01563                                                                                         struct sip_msg* msg,
01564                                                                                         enum rval_expr_op op,
01565                                                                                         struct rvalue* l,
01566                                                                                         struct rvalue* r)
01567 {
01568         struct rvalue* rv1;
01569         struct rvalue* rv2;
01570         struct rvalue* ret;
01571         int i;
01572 
01573         rv2=rv1=0;
01574         ret=0;
01575         if ((rv1=rval_convert(h, msg, RV_INT, l, 0))==0)
01576                 goto error;
01577         if ((rv2=rval_convert(h, msg, RV_INT, r, 0))==0)
01578                 goto error;
01579         if (unlikely(int_intop2(&i, op, rv1->v.l, rv2->v.l)<0))
01580                 goto error;
01581         if (rv_chg_in_place(rv1)){
01582                 /* try reusing rv1 */
01583                 ret=rv1;
01584                 rv_ref(ret);
01585         }else if (rv_chg_in_place(rv2)){
01586                 /* try reusing rv2 */
01587                 ret=rv2;
01588                 rv_ref(ret);
01589         }else if ((l->type==RV_INT) && (rv_chg_in_place(l))){
01590                 ret=l;
01591                 rv_ref(ret);
01592         } else if ((r->type==RV_INT) && (rv_chg_in_place(r))){
01593                 ret=r;
01594                 rv_ref(ret);
01595         }else{
01596                 ret=rval_new(RV_INT, &rv1->v, 0);
01597                 if (unlikely(ret==0)){
01598                         ERR("rv eval out of memory\n");
01599                         goto error;
01600                 }
01601         }
01602         rval_destroy(rv1); 
01603         rval_destroy(rv2); 
01604         ret->v.l=i;
01605         return ret;
01606 error:
01607         rval_destroy(rv1); 
01608         rval_destroy(rv2); 
01609         return 0;
01610 }
01611 
01612 
01613 
01618 inline static struct rvalue* rval_str_add2(struct run_act_ctx* h,
01619                                                                                         struct sip_msg* msg,
01620                                                                                         struct rvalue* l,
01621                                                                                         struct rval_cache* c1,
01622                                                                                         struct rvalue* r,
01623                                                                                         struct rval_cache* c2
01624                                                                                         )
01625 {
01626         struct rvalue* rv1;
01627         struct rvalue* rv2;
01628         struct rvalue* ret;
01629         str* s1;
01630         str* s2;
01631         str tmp;
01632         short flags;
01633         int len;
01634         
01635         rv2=rv1=0;
01636         ret=0;
01637         flags=0;
01638         s1=0;
01639         s2=0;
01640         if ((rv1=rval_convert(h, msg, RV_STR, l, c1))==0)
01641                 goto error;
01642         if ((rv2=rval_convert(h, msg, RV_STR, r, c2))==0)
01643                 goto error;
01644         
01645         len=rv1->v.s.len + rv2->v.s.len + 1 /* 0 */;
01646         
01647         if (rv_chg_in_place(rv1) && (rv1->bsize>=len)){
01648                 /* try reusing rv1 */
01649                 ret=rv1;
01650                 rv_ref(ret);
01651                 s2=&rv2->v.s;
01652                 if (ret->v.s.s == &ret->buf[0]) s1=0;
01653                 else{
01654                         tmp=ret->v.s;
01655                         flags=ret->flags;
01656                         ret->flags &= ~RV_CNT_ALLOCED_F;
01657                         ret->v.s.s=&ret->buf[0];
01658                         ret->v.s.len=0;
01659                         s1=&tmp;
01660                 }
01661         }else if (rv_chg_in_place(rv2) && (rv2->bsize>=len)){
01662                 /* try reusing rv2 */
01663                 ret=rv2;
01664                 rv_ref(ret);
01665                 s1=&rv1->v.s;
01666                 if (ret->v.s.s == &ret->buf[0]) 
01667                         s2=&ret->v.s;
01668                 else{
01669                         tmp=ret->v.s;
01670                         flags=ret->flags;
01671                         ret->flags &= ~RV_CNT_ALLOCED_F;
01672                         ret->v.s.s=&ret->buf[0];
01673                         ret->v.s.len=0;
01674                         s2=&tmp;
01675                 }
01676         }else if ((l->type==RV_STR) && (rv_chg_in_place(l)) && (l->bsize>=len)){
01677                 ret=l;
01678                 rv_ref(ret);
01679                 s2=&rv2->v.s;
01680                 if (ret->v.s.s == &ret->buf[0]) s1=0;
01681                 else{
01682                         tmp=ret->v.s;
01683                         flags=ret->flags;
01684                         ret->flags &= ~RV_CNT_ALLOCED_F;
01685                         ret->v.s.s=&ret->buf[0];
01686                         ret->v.s.len=0;
01687                         s1=&tmp;
01688                 }
01689         } else if ((r->type==RV_STR) && (rv_chg_in_place(r) && (r->bsize>=len))){
01690                 ret=r;
01691                 rv_ref(ret);
01692                 s1=&rv1->v.s;
01693                 if (ret->v.s.s == &ret->buf[0]) 
01694                         s2=&ret->v.s;
01695                 else{
01696                         tmp=ret->v.s;
01697                         flags=ret->flags;
01698                         ret->flags &= ~RV_CNT_ALLOCED_F;
01699                         ret->v.s.s=&ret->buf[0];
01700                         ret->v.s.len=0;
01701                         s2=&tmp;
01702                 }
01703         }else{
01704                 ret=rval_new(RV_STR, &rv1->v, len + RV_STR_EXTRA);
01705                 if (unlikely(ret==0)){
01706                         ERR("rv eval out of memory\n");
01707                         goto error;
01708                 }
01709                 s1=0;
01710                 s2=&rv2->v.s;
01711         }
01712         /* do the actual copy */
01713         memmove(ret->buf+rv1->v.s.len, s2->s, s2->len);
01714         if (s1){
01715                 memcpy(ret->buf, s1->s, s1->len);
01716         }
01717         ret->v.s.len=rv1->v.s.len+s2->len;
01718         ret->v.s.s[ret->v.s.len]=0;
01719         /* cleanup if needed */
01720         if (flags & RV_CNT_ALLOCED_F)
01721                 pkg_free(tmp.s);
01722         rval_destroy(rv1); 
01723         rval_destroy(rv2); 
01724         return ret;
01725 error:
01726         rval_destroy(rv1); 
01727         rval_destroy(rv2); 
01728         return 0;
01729 }
01730 
01731 
01732 
01737 inline static int rval_str_lop2(struct run_act_ctx* h,
01738                                                  struct sip_msg* msg,
01739                                                  int* res,
01740                                                  enum rval_expr_op op,
01741                                                  struct rvalue* l,
01742                                                  struct rval_cache* c1,
01743                                                  struct rvalue* r,
01744                                                  struct rval_cache* c2)
01745 {
01746         struct rvalue* rv1;
01747         struct rvalue* rv2;
01748         int ret;
01749         
01750         rv2=rv1=0;
01751         ret=0;
01752         if ((rv1=rval_convert(h, msg, RV_STR, l, c1))==0)
01753                 goto error;
01754         if ((rv2=rval_convert(h, msg, RV_STR, r, c2))==0)
01755                 goto error;
01756         ret=bool_rvstrop2(op, res, rv1, rv2);
01757         rval_destroy(rv1); 
01758         rval_destroy(rv2); 
01759         return ret;
01760 error:
01761         rval_destroy(rv1); 
01762         rval_destroy(rv2); 
01763         return 0;
01764 }
01765 
01766 
01767 
01781 inline static int rval_int_strop1(struct run_act_ctx* h,
01782                                                  struct sip_msg* msg,
01783                                                  int* res,
01784                                                  enum rval_expr_op op,
01785                                                  struct rvalue* l,
01786                                                  struct rval_cache* c1)
01787 {
01788         struct rvalue* rv1;
01789         int ret;
01790         
01791         rv1=0;
01792         ret=0;
01793         if ((rv1=rval_convert(h, msg, RV_STR, l, c1))==0)
01794                 goto error;
01795         ret=int_strop1(res, op, &rv1->v.s);
01796         rval_destroy(rv1); 
01797         return ret;
01798 error:
01799         *res=0;
01800         rval_destroy(rv1); 
01801         return -1;
01802 }
01803 
01804 
01805 
01819 inline static int rv_defined(struct run_act_ctx* h,
01820                                                  struct sip_msg* msg, int* res,
01821                                                  struct rvalue* rv, struct rval_cache* cache)
01822 {
01823         avp_t* r_avp;
01824         int_str avp_val;
01825         pv_value_t pval;
01826         str tmp;
01827         
01828         *res=1;
01829         switch(rv->type){
01830                 case RV_SEL:
01831                         if (unlikely(cache && cache->cache_type==RV_CACHE_SELECT)){
01832                                 *res=(cache->val_type!=RV_NONE);
01833                         }else
01834                                 /* run select returns 0 on success, -1 on error and >0 on 
01835                                    undefined. error is considered undefined */
01836                                 *res=(run_select(&tmp, &rv->v.sel, msg)==0);
01837                         break;
01838                 case RV_AVP:
01839                         if (unlikely(cache && cache->cache_type==RV_CACHE_AVP)){
01840                                 *res=(cache->val_type!=RV_NONE);
01841                         }else{
01842                                 r_avp = search_avp_by_index(rv->v.avps.type, rv->v.avps.name,
01843                                                                                         &avp_val, rv->v.avps.index);
01844                                 if (unlikely(r_avp==0)){
01845                                         *res=0;
01846                                 }
01847                         }
01848                         break;
01849                 case RV_PVAR:
01850                         /* PV_VAL_NULL or pv_get_spec_value error => undef */
01851                         if (unlikely(cache && cache->cache_type==RV_CACHE_PVAR)){
01852                                 *res=(cache->val_type!=RV_NONE);
01853                         }else{
01854                                 memset(&pval, 0, sizeof(pval));
01855                                 if (likely(pv_get_spec_value(msg, &rv->v.pvs, &pval)==0)){
01856                                         if ((pval.flags & PV_VAL_NULL) &&
01857                                                         ! (pval.flags & (PV_VAL_INT|PV_VAL_STR))){
01858                                                 *res=0;
01859                                         }
01860                                         pv_value_destroy(&pval);
01861                                 }else{
01862                                         *res=0; /* in case of error, consider it undef */
01863                                 }
01864                         }
01865                         break;
01866                 case RV_NONE:
01867                         *res=0;
01868                         break;
01869                 default:
01870                         break;
01871         }
01872         return 0;
01873 }
01874 
01875 
01884 inline static int int_rve_defined(struct run_act_ctx* h,
01885                                                  struct sip_msg* msg, int* res,
01886                                                  struct rval_expr* rve)
01887 {
01888         /* only a rval can be undefined, any expression consisting on more
01889            then one rval => defined */
01890         if (likely(rve->op==RVE_RVAL_OP))
01891                 return rv_defined(h, msg, res, &rve->left.rval, 0);
01892         *res=1;
01893         return 0;
01894 }
01895 
01896 
01897 
01903 int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
01904                                                 int* res, struct rval_expr* rve)
01905 {
01906         int i1, i2, ret;
01907         struct rval_cache c1, c2;
01908         struct rvalue* rv1;
01909         struct rvalue* rv2;
01910         
01911         ret=-1;
01912         switch(rve->op){
01913                 case RVE_RVAL_OP:
01914                         ret=rval_get_int(h, msg, res,  &rve->left.rval, 0);
01915                         rval_get_int_handle_ret(ret, "rval expression conversion to int"
01916                                                                                 " failed", rve);
01917                         break;
01918                 case RVE_UMINUS_OP:
01919                 case RVE_BOOL_OP:
01920                 case RVE_LNOT_OP:
01921                 case RVE_BNOT_OP:
01922                         if (unlikely(
01923                                         (ret=rval_expr_eval_int(h, msg, &i1, rve->left.rve)) <0) )
01924                                 break;
01925                         ret=int_intop1(res, rve->op, i1);
01926                         break;
01927                 case RVE_INT_OP:
01928                         ret=rval_expr_eval_int(h, msg, res, rve->left.rve);
01929                         break;
01930                 case RVE_MUL_OP:
01931                 case RVE_DIV_OP:
01932                 case RVE_MOD_OP:
01933                 case RVE_MINUS_OP:
01934                 case RVE_PLUS_OP:
01935                 case RVE_IPLUS_OP:
01936                 case RVE_BOR_OP:
01937                 case RVE_BAND_OP:
01938                 case RVE_BXOR_OP:
01939                 case RVE_BLSHIFT_OP:
01940                 case RVE_BRSHIFT_OP:
01941                 case RVE_GT_OP:
01942                 case RVE_GTE_OP:
01943                 case RVE_LT_OP:
01944                 case RVE_LTE_OP:
01945                 case RVE_IEQ_OP:
01946                 case RVE_IDIFF_OP:
01947                         if (unlikely(
01948                                         (ret=rval_expr_eval_int(h, msg, &i1, rve->left.rve)) <0) )
01949                                 break;
01950                         if (unlikely(
01951                                         (ret=rval_expr_eval_int(h, msg, &i2, rve->right.rve)) <0) )
01952                                 break;
01953                         ret=int_intop2(res, rve->op, i1, i2);
01954                         break;
01955                 case RVE_LAND_OP:
01956                         if (unlikely(
01957                                         (ret=rval_expr_eval_int(h, msg, &i1, rve->left.rve)) <0) )
01958                                 break;
01959                         if (i1==0){
01960                                 *res=0;
01961                         }else{
01962                                 if (unlikely( (ret=rval_expr_eval_int(h, msg, &i2,
01963                                                                                 rve->right.rve)) <0) )
01964                                         break;
01965                                 *res=i1 && i2;
01966                         }
01967                         ret=0;
01968                         break;
01969                 case RVE_LOR_OP:
01970                         if (unlikely(
01971                                         (ret=rval_expr_eval_int(h, msg, &i1, rve->left.rve)) <0) )
01972                                 break;
01973                         if (i1){
01974                                 *res=1;
01975                         }else{
01976                                 if (unlikely( (ret=rval_expr_eval_int(h, msg, &i2,
01977                                                                                 rve->right.rve)) <0) )
01978                                         break;
01979                                 *res=i1 || i2;
01980                         }
01981                         ret=0;
01982                         break;
01983                 case RVE_EQ_OP:
01984                 case RVE_DIFF_OP:
01985                         /* if left is string, eval left & right as string and
01986                          *   use string diff.
01987                          * if left is int eval as int using int diff
01988                          * if left is undef, look at right and convert to right type
01989                          */
01990                         rval_cache_init(&c1);
01991                         if (unlikely( (ret=rval_expr_eval_rvint(h, msg, &rv1, &i1,
01992                                                                                                         rve->left.rve, &c1))<0)){
01993                                 /* error */
01994                                 rval_cache_clean(&c1);
01995                                 break;
01996                         }
01997                         if (likely(rv1==0)){
01998                                 /* int */
01999                                 rval_cache_clean(&c1);
02000                                 if (unlikely( (ret=rval_expr_eval_int(h, msg, &i2,
02001                                                                                                                 rve->right.rve)) <0) )
02002                                         break;  /* error */
02003                                 ret=int_intop2(res, rve->op, i1, i2);
02004                         }else{
02005                                 /* not int => str or undef */
02006                                 /* check for undefined left operand */
02007                                 if (unlikely( c1.cache_type!=RV_CACHE_EMPTY &&
02008                                                                 c1.val_type==RV_NONE)){
02009 #ifdef UNDEF_EQ_ALWAYS_FALSE
02010                                         /* undef == something  always false
02011                                            undef != something  always true*/
02012                                         ret=(rve->op==RVE_DIFF_OP);
02013 #elif defined UNDEF_EQ_UNDEF_TRUE
02014                                         /* undef == something defined always false
02015                                            undef == undef true */
02016                                         if (int_rve_defined(h, msg, &i2, rve->right.rve)<0){
02017                                                 /* error */
02018                                                 rval_cache_clean(&c1);
02019                                                 rval_destroy(rv1);
02020                                                 break;
02021                                         }
02022                                         ret=(!i2) ^ (rve->op==RVE_DIFF_OP);
02023 #else  /* ! UNDEF_EQ_* */
02024                                         /*  undef == val
02025                                          *  => convert to (type_of(val)) (undef) == val */
02026                                         rval_cache_init(&c2);
02027                                         if (unlikely( (ret=rval_expr_eval_rvint(h, msg, &rv2, &i2,
02028                                                                                                         rve->right.rve, &c2))<0)){
02029                                                 /* error */
02030                                                 rval_cache_clean(&c1);
02031                                                 rval_cache_clean(&c2);
02032                                                 rval_destroy(rv1);
02033                                                 break;
02034                                         }
02035                                         if (rv2==0){
02036                                                 /* int */
02037                                                 ret=int_intop2(res, rve->op, 0 /* undef */, i2);
02038                                         }else{
02039                                                 /* str or undef */
02040                                                 ret=rval_str_lop2(h, msg, res, rve->op, rv1, &c1,
02041                                                                                         rv2, &c2);
02042                                                 rval_cache_clean(&c2);
02043                                                 rval_destroy(rv2);
02044                                         }
02045 #endif /* UNDEF_EQ_* */
02046                                         rval_cache_clean(&c1);
02047                                         rval_destroy(rv1);
02048                                 }else{
02049                                         /* left value == defined and != int => str
02050                                          * => lval == (str) val */
02051                                         if (unlikely((rv2=rval_expr_eval(h, msg,
02052                                                                                                                 rve->right.rve))==0)){
02053                                                 /* error */
02054                                                 rval_destroy(rv1);
02055                                                 rval_cache_clean(&c1);
02056                                                 break;
02057                                         }
02058                                         ret=rval_str_lop2(h, msg, res, rve->op, rv1, &c1, rv2, 0);
02059                                         rval_cache_clean(&c1);
02060                                         rval_destroy(rv1);
02061                                         rval_destroy(rv2);
02062                                 }
02063                         }
02064                         break;
02065                 case RVE_CONCAT_OP:
02066                         /* eval expression => string */
02067                         if (unlikely((rv1=rval_expr_eval(h, msg, rve))==0)){
02068                                 ret=-1;
02069                                 break;
02070                         }
02071                         /* convert to int */
02072                         ret=rval_get_int(h, msg, res, rv1, 0); /* convert to int */
02073                         rval_get_int_handle_ret(ret, "rval expression conversion to int"
02074                                                                                 " failed", rve);
02075                         rval_destroy(rv1);
02076                         break;
02077                 case RVE_STR_OP:
02078                         /* (str)expr => eval expression */
02079                         rval_cache_init(&c1);
02080                         if (unlikely((ret=rval_expr_eval_rvint(h, msg, &rv1, res,
02081                                                                                                         rve->left.rve, &c1))<0)){
02082                                 /* error */
02083                                 rval_cache_clean(&c1);
02084                                 break;
02085                         }
02086                         if (unlikely(rv1)){
02087                                 /* expr evaluated to string => (int)(str)v == (int)v */
02088                                 ret=rval_get_int(h, msg, res, rv1, &c1); /* convert to int */
02089                                 rval_get_int_handle_ret(ret, "rval expression conversion"
02090                                                                                                 " to int failed", rve);
02091                                 rval_destroy(rv1);
02092                                 rval_cache_clean(&c1);
02093                         } /* else (rv1==0)
02094                                  => expr evaluated to int => 
02095                                  return (int)(str)v == (int)v => do nothing */
02096                         break;
02097 
02098 #if 0
02099                         /* same thing as above, but in a not optimized, easier to
02100                            understand way */
02101                         /* 1. (str) expr => eval expr */
02102                         if (unlikely((rv1=rval_expr_eval(h, msg, rve->left.rve))==0)){
02103                                 ret=-1;
02104                                 break;
02105                         }
02106                         /* 2. convert to str and then convert to int
02107                            but since (int)(str)v == (int)v skip over (str)v */
02108                         ret=rval_get_int(h, msg, res, rv1, 0); /* convert to int */
02109                         rval_destroy(rv1);
02110                         break;
02111 #endif
02112                 case RVE_DEFINED_OP:
02113                         ret=int_rve_defined(h, msg, res, rve->left.rve);
02114                         break;
02115                 case RVE_STREQ_OP:
02116                 case RVE_STRDIFF_OP:
02117                 case RVE_MATCH_OP:
02118                         if (unlikely((rv1=rval_expr_eval(h, msg, rve->left.rve))==0)){
02119                                 ret=-1;
02120                                 break;
02121                         }
02122                         if (unlikely((rv2=rval_expr_eval(h, msg, rve->right.rve))==0)){
02123                                 rval_destroy(rv1);
02124                                 ret=-1;
02125                                 break;
02126                         }
02127                         ret=rval_str_lop2(h, msg, res, rve->op, rv1, 0, rv2, 0);
02128                         rval_destroy(rv1);
02129                         rval_destroy(rv2);
02130                         break;
02131                 case RVE_STRLEN_OP:
02132                 case RVE_STREMPTY_OP:
02133                         if (unlikely((rv1=rval_expr_eval(h, msg, rve->left.rve))==0)){
02134                                         ret=-1;
02135                                         break;
02136                         }
02137                         ret=rval_int_strop1(h, msg, res, rve->op, rv1, 0);
02138                         rval_destroy(rv1);
02139                         break;
02140                 case RVE_NONE_OP:
02141                 /*default:*/
02142                         BUG("invalid rval int expression operation %d (%d,%d-%d,%d)\n",
02143                                         rve->op, rve->fpos.s_line, rve->fpos.s_col,
02144                                         rve->fpos.e_line, rve->fpos.e_col);
02145                         ret=-1;
02146         };
02147         return ret;
02148 }
02149 
02150 
02151 
02169 int rval_expr_eval_rvint(                          struct run_act_ctx* h,
02170                                                                            struct sip_msg* msg,
02171                                                                            struct rvalue** res_rv,
02172                                                                            int* res_i,
02173                                                                            struct rval_expr* rve,
02174                                                                            struct rval_cache* cache
02175                                                                            )
02176 {
02177         struct rvalue* rv1;
02178         struct rvalue* rv2;
02179         struct rval_cache c1; /* local cache */
02180         int ret;
02181         int r, i, j;
02182         enum rval_type type;
02183         
02184         rv1=0;
02185         rv2=0;
02186         ret=-1;
02187         switch(rve->op){
02188                 case RVE_RVAL_OP:
02189                         rv1=&rve->left.rval;
02190                         rv_ref(rv1);
02191                         type=rval_get_btype(h, msg, rv1, cache);
02192                         if (type==RV_INT){
02193                                         r=rval_get_int(h, msg, res_i, rv1, cache);
02194                                         rval_get_int_handle_ret(r, "rval expression conversion"
02195                                                                                                 " to int failed", rve);
02196                                         *res_rv=0;
02197                                         ret=r; /* equiv. to if (r<0) goto error */
02198                         }else{
02199                                 /* RV_STR, RV_PVAR, RV_AVP a.s.o => return rv1 and the 
02200                                    cached resolved value in cache*/
02201                                         *res_rv=rv1;
02202                                         rv_ref(rv1);
02203                                         ret=0;
02204                         }
02205                         break;
02206                 case RVE_UMINUS_OP:
02207                 case RVE_BOOL_OP:
02208                 case RVE_LNOT_OP:
02209                 case RVE_BNOT_OP:
02210                 case RVE_MINUS_OP:
02211                 case RVE_MUL_OP:
02212                 case RVE_DIV_OP:
02213                 case RVE_MOD_OP:
02214                 case RVE_BOR_OP:
02215                 case RVE_BAND_OP:
02216                 case RVE_BXOR_OP:
02217                 case RVE_BLSHIFT_OP:
02218                 case RVE_BRSHIFT_OP:
02219                 case RVE_LAND_OP:
02220                 case RVE_LOR_OP:
02221                 case RVE_GT_OP:
02222                 case RVE_GTE_OP:
02223                 case RVE_LT_OP:
02224                 case RVE_LTE_OP:
02225                 case RVE_EQ_OP:
02226                 case RVE_DIFF_OP:
02227                 case RVE_IEQ_OP:
02228                 case RVE_IDIFF_OP:
02229                 case RVE_IPLUS_OP:
02230                 case RVE_STREQ_OP:
02231                 case RVE_STRDIFF_OP:
02232                 case RVE_MATCH_OP:
02233                 case RVE_STRLEN_OP:
02234                 case RVE_STREMPTY_OP:
02235                 case RVE_DEFINED_OP:
02236                 case RVE_INT_OP:
02237                         /* operator forces integer type */
02238                         ret=rval_expr_eval_int(h, msg, res_i, rve);
02239                         *res_rv=0;
02240                         break;
02241                 case RVE_PLUS_OP:
02242                         rval_cache_init(&c1);
02243                         r=rval_expr_eval_rvint(h, msg, &rv1, &i, rve->left.rve, &c1);
02244                         if (unlikely(r<0)){
02245                                 ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
02246                                                 rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
02247                                                 rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col
02248                                         );
02249                                 rval_cache_clean(&c1);
02250                                 goto error;
02251                         }
02252                         if (rv1==0){
02253                                 if (unlikely((r=rval_expr_eval_int(h, msg, &j,
02254                                                                                                                 rve->right.rve))<0)){
02255                                                 ERR("rval expression evaluation failed (%d,%d-%d,%d)"
02256                                                                 "\n", rve->right.rve->fpos.s_line,
02257                                                                 rve->right.rve->fpos.s_col,
02258                                                                 rve->right.rve->fpos.e_line,
02259                                                                 rve->right.rve->fpos.e_col);
02260                                                 rval_cache_clean(&c1);
02261                                                 goto error;
02262                                 }
02263                                 ret=int_intop2(res_i, rve->op, i, j);
02264                                 *res_rv=0;
02265                         }else{
02266                                 rv2=rval_expr_eval(h, msg, rve->right.rve);
02267                                 if (unlikely(rv2==0)){
02268                                         ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
02269                                                                 rve->right.rve->fpos.s_line,
02270                                                                 rve->right.rve->fpos.s_col,
02271                                                                 rve->right.rve->fpos.e_line,
02272                                                                 rve->right.rve->fpos.e_col);
02273                                         rval_cache_clean(&c1);
02274                                         goto error;
02275                                 }
02276                                 *res_rv=rval_str_add2(h, msg, rv1, &c1, rv2, 0);
02277                                 ret=-(*res_rv==0);
02278                         }
02279                         rval_cache_clean(&c1);
02280                         break;
02281                 case RVE_CONCAT_OP:
02282                 case RVE_STR_OP:
02283                         *res_rv=rval_expr_eval(h, msg, rve);
02284                         ret=-(*res_rv==0);
02285                         break;
02286                 case RVE_NONE_OP:
02287                 /*default:*/
02288                         BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
02289                                         rve->op, rve->fpos.s_line, rve->fpos.s_col,
02290                                         rve->fpos.e_line, rve->fpos.e_col);
02291                         goto error;
02292         };
02293         rval_destroy(rv1);
02294         rval_destroy(rv2);
02295         return ret;
02296 error:
02297         rval_destroy(rv1);
02298         rval_destroy(rv2);
02299         return -1;
02300 }
02301 
02302 
02303 
02314 struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
02315                                                                 struct rval_expr* rve)
02316 {
02317         struct rvalue* rv1;
02318         struct rvalue* rv2;
02319         struct rvalue* ret;
02320         struct rval_cache c1;
02321         union rval_val v;
02322         int r, i, j;
02323         enum rval_type type;
02324         
02325         rv1=0;
02326         rv2=0;
02327         ret=0;
02328         switch(rve->op){
02329                 case RVE_RVAL_OP:
02330                         rv_ref(&rve->left.rval);
02331                         return &rve->left.rval;
02332                         break;
02333                 case RVE_UMINUS_OP:
02334                 case RVE_BOOL_OP:
02335                 case RVE_LNOT_OP:
02336                 case RVE_BNOT_OP:
02337                 case RVE_MINUS_OP:
02338                 case RVE_MUL_OP:
02339                 case RVE_DIV_OP:
02340                 case RVE_MOD_OP:
02341                 case RVE_BOR_OP:
02342                 case RVE_BAND_OP:
02343                 case RVE_BXOR_OP:
02344                 case RVE_BLSHIFT_OP:
02345                 case RVE_BRSHIFT_OP:
02346                 case RVE_LAND_OP:
02347                 case RVE_LOR_OP:
02348                 case RVE_GT_OP:
02349                 case RVE_GTE_OP:
02350                 case RVE_LT_OP:
02351                 case RVE_LTE_OP:
02352                 case RVE_EQ_OP:
02353                 case RVE_DIFF_OP:
02354                 case RVE_IEQ_OP:
02355                 case RVE_IDIFF_OP:
02356                 case RVE_IPLUS_OP:
02357                 case RVE_STREQ_OP:
02358                 case RVE_STRDIFF_OP:
02359                 case RVE_MATCH_OP:
02360                 case RVE_STRLEN_OP:
02361                 case RVE_STREMPTY_OP:
02362                 case RVE_DEFINED_OP:
02363                 case RVE_INT_OP:
02364                         /* operator forces integer type */
02365                         r=rval_expr_eval_int(h, msg, &i, rve);
02366                         if (likely(r==0)){
02367                                 v.l=i;
02368                                 ret=rval_new(RV_INT, &v, 0);
02369                                 if (unlikely(ret==0)){
02370                                         ERR("rv eval int expression: out of memory\n");
02371                                         goto error;
02372                                 }
02373                                 return ret;
02374                         }else{
02375                                 ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
02376                                                 rve->fpos.s_line, rve->fpos.s_col,
02377                                                 rve->fpos.e_line, rve->fpos.e_col);
02378                                 goto error;
02379                         }
02380                         break;
02381                 case RVE_PLUS_OP:
02382                         rv1=rval_expr_eval(h, msg, rve->left.rve);
02383                         if (unlikely(rv1==0)){
02384                                 ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
02385                                                 rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
02386                                                 rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
02387                                 goto error;
02388                         }
02389                         rval_cache_init(&c1);
02390                         type=rval_get_btype(h, msg, rv1, &c1);
02391                         switch(type){
02392                                 case RV_INT:
02393                                         r=rval_get_int(h, msg, &i, rv1, &c1);
02394                                         rval_get_int_handle_ret(r, "rval expression left side "
02395                                                                                                 "conversion to int failed",
02396                                                                                         rve);
02397                                         if (unlikely(r<0)){
02398                                                 rval_cache_clean(&c1);
02399                                                 goto error;
02400                                         }
02401                                         if (unlikely((r=rval_expr_eval_int(h, msg, &j,
02402                                                                                                                 rve->right.rve))<0)){
02403                                                 rval_cache_clean(&c1);
02404                                                 ERR("rval expression evaluation failed (%d,%d-%d,%d):"
02405                                                                 " could not evaluate right side to int\n",
02406                                                                 rve->fpos.s_line, rve->fpos.s_col,
02407                                                                 rve->fpos.e_line, rve->fpos.e_col);
02408                                                 goto error;
02409                                         }
02410                                         int_intop2(&r, rve->op, i, j);
02411                                         if (rv_chg_in_place(rv1)){
02412                                                 rv1->v.l=r;
02413                                                 ret=rv1;
02414                                                 rv_ref(ret);
02415                                         }else{
02416                                                 v.l=r;
02417                                                 ret=rval_new(RV_INT, &v, 0);
02418                                                 if (unlikely(ret==0)){
02419                                                         rval_cache_clean(&c1);
02420                                                         ERR("rv eval int expression: out of memory\n");
02421                                                         goto error;
02422                                                 }
02423                                         }
02424                                         break;
02425                                 case RV_STR:
02426                                 case RV_NONE:
02427                                         rv2=rval_expr_eval(h, msg, rve->right.rve);
02428                                         if (unlikely(rv2==0)){
02429                                                 ERR("rval expression evaluation failed (%d,%d-%d,%d)"
02430                                                                 "\n", rve->right.rve->fpos.s_line,
02431                                                                 rve->right.rve->fpos.s_col,
02432                                                                 rve->right.rve->fpos.e_line,
02433                                                                 rve->right.rve->fpos.e_col);
02434                                                 rval_cache_clean(&c1);
02435                                                 goto error;
02436                                         }
02437                                         ret=rval_str_add2(h, msg, rv1, &c1, rv2, 0);
02438                                         break;
02439                                 default:
02440                                         BUG("rv unsupported basic type %d (%d,%d-%d,%d)\n", type,
02441                                                         rve->fpos.s_line, rve->fpos.s_col,
02442                                                         rve->fpos.e_line, rve->fpos.e_col);
02443                         }
02444                         rval_cache_clean(&c1);
02445                         break;
02446                 case RVE_CONCAT_OP:
02447                         rv1=rval_expr_eval(h, msg, rve->left.rve);
02448                         if (unlikely(rv1==0)){
02449                                 ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
02450                                                 rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
02451                                                 rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
02452                                 goto error;
02453                         }
02454                         rv2=rval_expr_eval(h, msg, rve->right.rve);
02455                         if (unlikely(rv2==0)){
02456                                 ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
02457                                                 rve->right.rve->fpos.s_line,
02458                                                 rve->right.rve->fpos.s_col,
02459                                                 rve->right.rve->fpos.e_line,
02460                                                 rve->right.rve->fpos.e_col);
02461                                 goto error;
02462                         }
02463                         ret=rval_str_add2(h, msg, rv1, 0, rv2, 0);
02464                         break;
02465                 case RVE_STR_OP:
02466                         rv1=rval_expr_eval(h, msg, rve->left.rve);
02467                         if (unlikely(rv1==0)){
02468                                 ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
02469                                                 rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
02470                                                 rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
02471                                 goto error;
02472                         }
02473                         ret=rval_convert(h, msg, RV_STR, rv1, 0);
02474                         break;
02475                 case RVE_NONE_OP:
02476                 /*default:*/
02477                         BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
02478                                         rve->op, rve->fpos.s_line, rve->fpos.s_col,
02479                                         rve->fpos.e_line, rve->fpos.e_col);
02480                         goto error;
02481         };
02482         rval_destroy(rv1);
02483         rval_destroy(rv2);
02484         return ret;
02485 error:
02486         rval_destroy(rv1);
02487         rval_destroy(rv2);
02488         return 0;
02489 }
02490 
02491 
02492 
02501 struct rvalue* rval_expr_eval_new(struct run_act_ctx* h, struct sip_msg* msg,
02502                                                                 struct rval_expr* rve)
02503 {
02504         struct rvalue* ret;
02505         struct rvalue* rv;
02506         
02507         ret=rval_expr_eval(h, msg, rve);
02508         if (ret && !rv_chg_in_place(ret)){
02509                 rv=ret;
02510                 /* create a new rv */
02511                 ret=rval_new(rv->type, &rv->v, 0);
02512                 rval_destroy(rv);
02513         }
02514         return ret;
02515 }
02516 
02517 
02518 
02526 struct rval_expr* mk_rval_expr_v(enum rval_type rv_type, void* val, 
02527                                                                         struct cfg_pos* pos)
02528 {
02529         struct rval_expr* rve;
02530         union rval_val v;
02531         str* s;
02532         int flags;
02533         
02534         rve=pkg_malloc(sizeof(*rve));
02535         if (rve==0) 
02536                 return 0;
02537         memset(rve, 0, sizeof(*rve));
02538         flags=0;
02539         switch(rv_type){
02540                 case RV_INT:
02541                         v.l=(long)val;
02542                         break;
02543                 case RV_STR:
02544                         s=(str*)val;
02545                         v.s.s=pkg_malloc(s->len+1 /*0*/);
02546                         if (v.s.s==0){
02547                                 ERR("memory allocation failure\n");
02548                                 return 0;
02549                         }
02550                         v.s.len=s->len;
02551                         memcpy(v.s.s, s->s, s->len);
02552                         v.s.s[s->len]=0;
02553                         flags=RV_CNT_ALLOCED_F;
02554                         break;
02555                 case RV_AVP:
02556                         v.avps=*(avp_spec_t*)val;
02557                         break;
02558                 case RV_PVAR:
02559                         v.pvs=*(pv_spec_t*)val;
02560                         break;
02561                 case RV_SEL:
02562                         v.sel=*(select_t*)val;
02563                         break;
02564                 case RV_BEXPR:
02565                         v.bexpr=(struct expr*)val;
02566                         break;
02567                 case RV_ACTION_ST:
02568                         v.action=(struct action*)val;
02569                         break;
02570                 default:
02571                         BUG("unsupported rv type %d\n", rv_type);
02572                         pkg_free(rve);
02573                         return 0;
02574         }
02575         rval_init(&rve->left.rval, rv_type, &v, flags);
02576         rve->op=RVE_RVAL_OP;
02577         if (pos) rve->fpos=*pos;
02578         return rve;
02579 }
02580 
02581 
02582 
02591 struct rval_expr* mk_rval_expr1(enum rval_expr_op op, struct rval_expr* rve1,
02592                                                                 struct cfg_pos* pos)
02593 {
02594         struct rval_expr* ret;
02595         
02596         switch(op){
02597                 case RVE_UMINUS_OP:
02598                 case RVE_BOOL_OP:
02599                 case RVE_LNOT_OP:
02600                 case RVE_BNOT_OP:
02601                 case RVE_STRLEN_OP:
02602                 case RVE_STREMPTY_OP:
02603                 case RVE_DEFINED_OP:
02604                 case RVE_INT_OP:
02605                 case RVE_STR_OP:
02606                         break;
02607                 default:
02608                         BUG("unsupported unary operator %d\n", op);
02609                         return 0;
02610         }
02611         ret=pkg_malloc(sizeof(*ret));
02612         if (ret==0) 
02613                 return 0;
02614         memset(ret, 0, sizeof(*ret));
02615         ret->op=op;
02616         ret->left.rve=rve1;
02617         if (pos) ret->fpos=*pos;
02618         return ret;
02619 }
02620 
02621 
02622 
02632 struct rval_expr* mk_rval_expr2(enum rval_expr_op op, struct rval_expr* rve1,
02633                                                                                                           struct rval_expr* rve2,
02634                                                                                                           struct cfg_pos* pos)
02635 {
02636         struct rval_expr* ret;
02637         
02638         switch(op){
02639                 case RVE_MUL_OP:
02640                 case RVE_DIV_OP:
02641                 case RVE_MOD_OP:
02642                 case RVE_MINUS_OP:
02643                 case RVE_BOR_OP:
02644                 case RVE_BAND_OP:
02645                 case RVE_BXOR_OP:
02646                 case RVE_BLSHIFT_OP:
02647                 case RVE_BRSHIFT_OP:
02648                 case RVE_LAND_OP:
02649                 case RVE_LOR_OP:
02650                 case RVE_GT_OP:
02651                 case RVE_GTE_OP:
02652                 case RVE_LT_OP:
02653                 case RVE_LTE_OP:
02654                 case RVE_PLUS_OP:
02655                 case RVE_IPLUS_OP:
02656                 case RVE_EQ_OP:
02657                 case RVE_DIFF_OP:
02658                 case RVE_IEQ_OP:
02659                 case RVE_IDIFF_OP:
02660                 case RVE_STREQ_OP:
02661                 case RVE_STRDIFF_OP:
02662                 case RVE_MATCH_OP:
02663                 case RVE_CONCAT_OP:
02664                         break;
02665                 default:
02666                         BUG("unsupported operator %d\n", op);
02667                         return 0;
02668         }
02669         ret=pkg_malloc(sizeof(*ret));
02670         if (ret==0) 
02671                 return 0;
02672         memset(ret, 0, sizeof(*ret));
02673         ret->op=op;
02674         ret->left.rve=rve1;
02675         ret->right.rve=rve2;
02676         if (pos) ret->fpos=*pos;
02677         return ret;
02678 }
02679 
02680 
02681 
02683 static int rve_op_is_assoc(enum rval_expr_op op)
02684 {
02685         switch(op){
02686                 case RVE_NONE_OP:
02687                 case RVE_RVAL_OP:
02688                 case RVE_UMINUS_OP:
02689                 case RVE_BOOL_OP:
02690                 case RVE_LNOT_OP:
02691                 case RVE_BNOT_OP:
02692                 case RVE_STRLEN_OP:
02693                 case RVE_STREMPTY_OP:
02694                 case RVE_DEFINED_OP:
02695                 case RVE_INT_OP:
02696                 case RVE_STR_OP:
02697                         /* one operand expression => cannot be assoc. */
02698                         return 0;
02699                 case RVE_DIV_OP:
02700                 case RVE_MOD_OP:
02701                 case RVE_MINUS_OP:
02702                 case RVE_BLSHIFT_OP:
02703                 case RVE_BRSHIFT_OP:
02704                         return 0;
02705                 case RVE_PLUS_OP:
02706                         /* the generic plus is not assoc, e.g.
02707                            "a" + 1 + "2" => "a12" in one case and "a3" in the other */
02708                         return 0;
02709                 case RVE_IPLUS_OP:
02710                 case RVE_CONCAT_OP:
02711                 case RVE_MUL_OP:
02712                 case RVE_BAND_OP:
02713                 case RVE_BOR_OP:
02714                 case RVE_BXOR_OP:
02715                         return 1;
02716                 case RVE_LAND_OP:
02717                 case RVE_LOR_OP:
02718                         return 1;
02719                 case RVE_GT_OP:
02720                 case RVE_GTE_OP:
02721                 case RVE_LT_OP:
02722                 case RVE_LTE_OP:
02723                 case RVE_EQ_OP:
02724                 case RVE_DIFF_OP:
02725                 case RVE_IEQ_OP:
02726                 case RVE_IDIFF_OP:
02727                 case RVE_STREQ_OP:
02728                 case RVE_STRDIFF_OP:
02729                 case RVE_MATCH_OP:
02730                         return 0;
02731         }
02732         return 0;
02733 }
02734 
02735 
02736 
02738 static int rve_op_is_commutative(enum rval_expr_op op)
02739 {
02740         switch(op){
02741                 case RVE_NONE_OP:
02742                 case RVE_RVAL_OP:
02743                 case RVE_UMINUS_OP:
02744                 case RVE_BOOL_OP:
02745                 case RVE_LNOT_OP:
02746                 case RVE_BNOT_OP:
02747                 case RVE_STRLEN_OP:
02748                 case RVE_STREMPTY_OP:
02749                 case RVE_DEFINED_OP:
02750                 case RVE_INT_OP:
02751                 case RVE_STR_OP:
02752                         /* one operand expression => cannot be commut. */
02753                         return 0;
02754                 case RVE_DIV_OP:
02755                 case RVE_MOD_OP:
02756                 case RVE_MINUS_OP:
02757                 case RVE_BLSHIFT_OP:
02758                 case RVE_BRSHIFT_OP:
02759                         return 0;
02760                 case RVE_PLUS_OP:
02761                         /* non commut. when diff. type 
02762                            (e.g 1 + "2" != "2" + 1 ) => non commut. in general
02763                            (specific same type versions are covered by IPLUS & CONCAT) */
02764                         return 0;
02765                 case RVE_IPLUS_OP:
02766                 case RVE_MUL_OP:
02767                 case RVE_BAND_OP:
02768                 case RVE_BOR_OP:
02769                 case RVE_BXOR_OP:
02770                 case RVE_LAND_OP:
02771                 case RVE_LOR_OP:
02772                 case RVE_IEQ_OP:
02773                 case RVE_IDIFF_OP:
02774                 case RVE_STREQ_OP:
02775                 case RVE_STRDIFF_OP:
02776                         return 1;
02777                 case RVE_GT_OP:
02778                 case RVE_GTE_OP:
02779                 case RVE_LT_OP:
02780                 case RVE_LTE_OP:
02781                 case RVE_CONCAT_OP:
02782                 case RVE_MATCH_OP:
02783                         return 0;
02784                 case RVE_DIFF_OP:
02785                 case RVE_EQ_OP:
02786                         /* non. commut. in general, only for same type e.g.:
02787                            "" == 0  diff. 0 == "" ( "" == "0" and 0 == 0)
02788                            same type versions are covered by IEQ, IDIFF, STREQ, STRDIFF
02789                          */
02790                         return 0 /* asymmetrical undef handling */;
02791         }
02792         return 0;
02793 }
02794 
02795 
02796 #if 0
02797 
02802 static int rve_can_optimize_int(struct rval_expr* rve)
02803 {
02804         if (scr_opt_lev<1)
02805                 return 0;
02806         if (rve->op == RVE_RVAL_OP)
02807                 return 0;
02808         if (rve->left.rve->op != RVE_RVAL_OP)
02809                 return 0;
02810         if (rve->left.rve->left.rval.type!=RV_INT)
02811                 return 0;
02812         if (rve->right.rve){
02813                 if  (rve->right.rve->op != RVE_RVAL_OP)
02814                         return 0;
02815                 if (rve->right.rve->left.rval.type!=RV_INT)
02816                         return 0;
02817         }
02818         DBG("rve_can_optimize_int: left %d, right %d\n", 
02819                         rve->left.rve->op, rve->right.rve?rve->right.rve->op:0);
02820         return 1;
02821 }
02822 
02823 
02824 
02830 static int rve_can_optimize_str(struct rval_expr* rve)
02831 {
02832         if (scr_opt_lev<1)
02833                 return 0;
02834         if (rve->op == RVE_RVAL_OP)
02835                 return 0;
02836         DBG("rve_can_optimize_str: left %d, right %d\n", 
02837                         rve->left.rve->op, rve->right.rve?rve->right.rve->op:0);
02838         if (rve->left.rve->op != RVE_RVAL_OP)
02839                 return 0;
02840         if (rve->left.rve->left.rval.type!=RV_STR)
02841                 return 0;
02842         if (rve->right.rve){
02843                 if  (rve->right.rve->op != RVE_RVAL_OP)
02844                         return 0;
02845                 if ((rve->right.rve->left.rval.type!=RV_STR) && 
02846                                 (rve->right.rve->left.rval.type!=RV_INT))
02847                         return 0;
02848         }
02849         return 1;
02850 }
02851 #endif
02852 
02853 
02854 
02855 static int fix_rval(struct rvalue* rv)
02856 {
02857         DBG("RV fixing type %d\n", rv->type);
02858         switch(rv->type){
02859                 case RV_INT:
02860                         /*nothing to do*/
02861                         DBG("RV is int: %d\n", (int)rv->v.l);
02862                         return 0;
02863                 case RV_STR:
02864                         /*nothing to do*/
02865                         DBG("RV is str: \"%s\"\n", rv->v.s.s);
02866                         return 0;
02867                 case RV_BEXPR:
02868                         return fix_expr(rv->v.bexpr);
02869                 case RV_ACTION_ST:
02870                         return fix_actions(rv->v.action);
02871                 case RV_SEL:
02872                         if (resolve_select(&rv->v.sel)<0){
02873                                 ERR("Unable to resolve select\n");
02874                                 print_select(&rv->v.sel);
02875                         }
02876                         return 0;
02877                 case RV_AVP:
02878                         /* nothing to do, resolved at runtime */
02879                         return 0;
02880                 case RV_PVAR:
02881                         /* nothing to do, resolved at parsing time */
02882                         return 0;
02883                 case RV_NONE:
02884                         BUG("uninitialized rvalue\n");
02885                         return -1;
02886         }
02887         BUG("unknown rvalue type %d\n", rv->type);
02888         return -1;
02889 }
02890 
02891 
02892 
02904 static int rve_replace_with_val(struct rval_expr* rve, enum rval_type type,
02905                                                                 union rval_val* v, int flags)
02906 {
02907         int refcnt;
02908         
02909         refcnt=1; /* replaced-in-place rval refcnt */
02910         if (rve->op!=RVE_RVAL_OP){
02911                 rve_destroy(rve->left.rve);
02912                 if (rve_op_unary(rve->op)==0)
02913                         rve_destroy(rve->right.rve);
02914         }else{
02915                 if (rve->left.rval.refcnt!=1){
02916                         BUG("trying to replace a referenced rval! (refcnt=%d)\n",
02917                                         rve->left.rval.refcnt);
02918                         /* try to recover */
02919                         refcnt=rve->left.rval.refcnt;
02920                         abort(); /* find bugs quicker -- andrei */
02921                 }
02922                 rval_destroy(&rve->left.rval);
02923         }
02924         rval_init(&rve->left.rval, type, v, flags);
02925         rve->left.rval.refcnt=refcnt;
02926         rval_init(&rve->right.rval, RV_NONE, 0, 0);
02927         rve->op=RVE_RVAL_OP;
02928         return 0;
02929 }
02930 
02931 
02932 
02937 static int rve_replace_with_ct_rv(struct rval_expr* rve, struct rvalue* rv)
02938 {
02939         enum rval_type type;
02940         int flags;
02941         int i;
02942         union rval_val v;
02943         
02944         type=rv->type;
02945         flags=0;
02946         if (rv->type==RV_INT){
02947                 if (rval_get_int(0, 0, &i, rv, 0)!=0){
02948                         BUG("unexpected int evaluation failure (%d,%d-%d,%d)\n",
02949                                         rve->fpos.s_line, rve->fpos.s_col,
02950                                         rve->fpos.e_line, rve->fpos.e_col);
02951                         return -1;
02952                 }
02953                 v.l=i;
02954         }else if(rv->type==RV_STR){
02955                 if (rval_get_str(0, 0, &v.s, rv, 0)<0){
02956                         BUG("unexpected str evaluation failure(%d,%d-%d,%d)\n",
02957                                         rve->fpos.s_line, rve->fpos.s_col,
02958                                         rve->fpos.e_line, rve->fpos.e_col);
02959                         return -1;
02960                 }
02961                 flags|=RV_CNT_ALLOCED_F;
02962         }else{
02963                 BUG("unknown constant expression type %d (%d,%d-%d,%d)\n", rv->type,
02964                                 rve->fpos.s_line, rve->fpos.s_col,
02965                                 rve->fpos.e_line, rve->fpos.e_col);
02966                 return -1;
02967         }
02968         return rve_replace_with_val(rve, type, &v, flags);
02969 }
02970 
02971 
02972 
02976 static int fix_match_rve(struct rval_expr* rve)
02977 {
02978         struct rvalue* rv;
02979         regex_t* re;
02980         union rval_val v;
02981         int flags;
02982         int ret;
02983 
02984         rv=0;
02985         v.s.s=0;
02986         v.re.regex=0;
02987         /* normal fix-up for the  left side */
02988         ret=fix_rval_expr((void*)rve->left.rve);
02989         if (ret<0) return ret;
02990         
02991         /* fixup the right side (RE) */
02992         if (rve_is_constant(rve->right.rve)){
02993                 if ((rve_guess_type(rve->right.rve)!=RV_STR)){
02994                         ERR("fixup failure(%d,%d-%d,%d): left side of  =~ is not string"
02995                                         " (%d,%d)\n",   rve->fpos.s_line, rve->fpos.s_col,
02996                                                                         rve->fpos.e_line, rve->fpos.e_col,
02997                                                                         rve->right.rve->fpos.s_line,
02998                                                                         rve->right.rve->fpos.s_col);
02999                         goto error;
03000                 }
03001                 if ((rv=rval_expr_eval(0, 0, rve->right.rve))==0){
03002                         ERR("fixup failure(%d,%d-%d,%d):  bad RE expression\n",
03003                                         rve->right.rve->fpos.s_line, rve->right.rve->fpos.s_col,
03004                                         rve->right.rve->fpos.e_line, rve->right.rve->fpos.e_col);
03005                         goto error;
03006                 }
03007                 if (rval_get_str(0, 0, &v.s, rv, 0)<0){
03008                         BUG("fixup unexpected failure (%d,%d-%d,%d)\n",
03009                                         rve->fpos.s_line, rve->fpos.s_col,
03010                                         rve->fpos.e_line, rve->fpos.e_col);
03011                         goto error;
03012                 }
03013                 /* we have the str, we don't need the rv anymore */
03014                 rval_destroy(rv);
03015                 rv=0;
03016                 re=pkg_malloc(sizeof(*re));
03017                 if (re==0){
03018                         ERR("out of memory\n");
03019                         goto error;
03020                 }
03021                 /* same flags as for expr. =~ (fix_expr()) */
03022                 if (regcomp(re, v.s.s, REG_EXTENDED|REG_NOSUB|REG_ICASE)){
03023                         pkg_free(re);
03024                         ERR("Bad regular expression \"%s\"(%d,%d-%d,%d)\n", v.s.s,
03025                                         rve->right.rve->fpos.s_line, rve->right.rve->fpos.s_col,
03026                                         rve->right.rve->fpos.e_line, rve->right.rve->fpos.e_col);
03027                         goto error;
03028                 }
03029                 v.re.regex=re;
03030                 flags=RV_RE_F|RV_RE_ALLOCED_F|RV_CNT_ALLOCED_F;
03031                 if (rve_replace_with_val(rve->right.rve, RV_STR, &v, flags)<0)
03032                         goto error;
03033         }else{
03034                 /* right side is not constant => normal fixup */
03035                 return fix_rval_expr((void*)rve->right.rve);
03036         }
03037         return 0;
03038 error:
03039         if (rv) rval_destroy(rv);
03040         if (v.s.s) pkg_free(v.s.s);
03041         if (v.re.regex){
03042                 regfree(v.re.regex);
03043                 pkg_free(v.re.regex);
03044         }
03045         return -1;
03046 }
03047 
03048 
03049 
03056 static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
03057 {
03058         struct rvalue* rv;
03059         struct rval_expr* ct_rve;
03060         struct rval_expr* v_rve;
03061         int i;
03062         int ret;
03063         enum rval_expr_op op;
03064         struct cfg_pos pos;
03065         int right; /* debugging msg */
03066         int dbg; /* debugging msg on/off */
03067 
03068 /* helper macro: replace in-place a <ctype> type rve with v (another rve).
03069  * if type_of(v)== <ctype> => rve:=*v (copy v contents into rve and free v)
03070  * else if type_of(v)!=<ctype> => rve:= (ctype) v (casts v to <ctype>)
03071  * Uses pos.
03072  * ctype can be INT or STR
03073  * WARNING: - v might be pkg_free()'d
03074  *          - rve members _are_ _not_ freed or destroyed
03075  */
03076 #define replace_rve_type_cast(e, v, ctype) \
03077         do{\
03078                 if ( rve_guess_type((v)) == RV_##ctype ){\
03079                         /* if type_of($v)==int we don't need to add an \
03080                            int cast operator => replace with v */\
03081                         pos=(e)->fpos; \
03082                         *(e)=*(v); /* replace e with v (in-place) */ \
03083                         (e)->fpos=pos; \
03084                         pkg_free((v)); /* rve_destroy(v_rve) would free everything*/ \
03085                 }else{\
03086                         /* unknown type or str => (int) $v */ \
03087                         (e)->op=RVE_##ctype##_OP; \
03088                         (e)->left.rve=(v); \
03089                         (e)->right.rve=0; \
03090                 }\
03091         }while(0)
03092         
03093 /* helper macro: replace in-place an int type rve with v (another rve).*/
03094 #define replace_int_rve(e, v) replace_rve_type_cast(e, v, INT)
03095 /* helper macro: replace in-place a str type rve with v (another rve).*/
03096 #define replace_str_rve(e, v) replace_rve_type_cast(e, v, STR)
03097         
03098         
03099         rv=0;
03100         ret=0;
03101         right=0;
03102         dbg=1;
03103         
03104         if (rve_is_constant(rve->right.rve)){
03105                 ct_rve=rve->right.rve;
03106                 v_rve=rve->left.rve;
03107                 right=1;
03108         }else if (rve_is_constant(rve->left.rve)){
03109                 ct_rve=rve->left.rve;
03110                 v_rve=rve->right.rve;
03111                 right=0;
03112         }else
03113                 return 0; /* op($v, $w) */
03114         
03115         /* rval_expr_eval_new() instead of rval_expr_eval() to avoid
03116            referencing a ct_rve->left.rval if ct_rve is a rval, which
03117            would prevent rve_destroy(ct_rve) from working */
03118         if ((rv=rval_expr_eval_new(0, 0, ct_rve))==0){
03119                 ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
03120                                 ct_rve->fpos.s_line, ct_rve->fpos.s_col,
03121                                 ct_rve->fpos.e_line, ct_rve->fpos.e_col);
03122                 goto error;
03123         }
03124         op=rve->op;
03125         if (rv->type==RV_INT){
03126                 i=rv->v.l;
03127                 switch(op){
03128                         case RVE_MUL_OP:
03129                                 if (i==0){
03130                                         /* $v *  0 -> 0
03131                                          *  0 * $v -> 0 */
03132                                         if (rve_replace_with_ct_rv(rve, rv)<0)
03133                                                 goto error;
03134                                         ret=1;
03135                                 }else if (i==1){
03136                                         /* $v *  1 -> (int)$v
03137                                          *  1 * $v -> (int)$v */
03138                                         rve_destroy(ct_rve);
03139                                         replace_int_rve(rve, v_rve);
03140                                         ret=1;
03141                                 }
03142                                 break;
03143                         case RVE_DIV_OP:
03144                                 if (i==0){
03145                                         if (ct_rve==rve->left.rve){
03146                                                 /* 0 / $v -> 0 */
03147                                                 if (rve_replace_with_ct_rv(rve, rv)<0)
03148                                                         goto error;
03149                                                 ret=1;
03150                                         }else{
03151                                                 /* $v / 0 */
03152                                                 ERR("RVE divide by 0 at %d,%d\n",
03153                                                                 ct_rve->fpos.s_line, ct_rve->fpos.s_col);
03154                                         }
03155                                 }else if (i==1){
03156                                         if (ct_rve==rve->right.rve){
03157                                                 /* $v / 1 -> (int)$v */
03158                                                 rve_destroy(ct_rve);
03159                                                 replace_int_rve(rve, v_rve);
03160                                                 ret=1;
03161                                         }
03162                                 }
03163                                 break;
03164                         case RVE_MOD_OP:
03165                                 if (i==0){
03166                                         if (ct_rve==rve->left.rve){
03167                                                 /* 0 % $v -> 0 */
03168                                                 if (rve_replace_with_ct_rv(rve, rv)<0)
03169                                                         goto error;
03170                                                 ret=1;
03171                                         }else{
03172                                                 /* $v % 0 */
03173                                                 ERR("RVE modulo by 0 at %d,%d\n",
03174                                                                 ct_rve->fpos.s_line, ct_rve->fpos.s_col);
03175                                         }
03176                                 }
03177                                 /* $v % 1 -> 0 ? */
03178                                 break;
03179                         case RVE_MINUS_OP:
03180                                 if (i==0){
03181                                         if (ct_rve==rve->right.rve){
03182                                                 /* $v - 0 -> $v */
03183                                                 rve_destroy(ct_rve);
03184                                                 replace_int_rve(rve, v_rve);
03185                                                 ret=1;
03186                                         }
03187                                         /* ? 0 - $v -> -($v)  ? */
03188                                 }
03189                                 break;
03190                         case RVE_BAND_OP:
03191                                 if (i==0){
03192                                         /* $v &  0 -> 0
03193                                          *  0 & $v -> 0 */
03194                                         if (rve_replace_with_ct_rv(rve, rv)<0)
03195                                                 goto error;
03196                                         ret=1;
03197                                 }
03198                                 /* no 0xffffff optimization for now (haven't decided on
03199                                    the number of bits ) */
03200                                 break;
03201                         case RVE_BOR_OP:
03202                                 if (i==0){
03203                                         /* $v |  0 -> (int)$v
03204                                          *  0 | $v -> (int)$v */
03205                                         rve_destroy(ct_rve);
03206                                         replace_int_rve(rve, v_rve);
03207                                         ret=1;
03208                                 }
03209                                 break;
03210                         case RVE_LAND_OP:
03211                                 if (i==0){
03212                                         /* $v &&  0 -> 0
03213                                          *  0 && $v -> 0 */
03214                                         if (rve_replace_with_ct_rv(rve, rv)<0)
03215                                                 goto error;
03216                                         ret=1;
03217                                 }else if (i==1){
03218                                         /* $v &&  1 -> (int)$v
03219                                          *  1 && $v -> (int)$v */
03220                                         rve_destroy(ct_rve);
03221                                         replace_int_rve(rve, v_rve);
03222                                         ret=1;
03223                                 }
03224                                 break;
03225                         case RVE_LOR_OP:
03226                                 if (i==1){
03227                                         /* $v ||  1 -> 1
03228                                          *  1 || $v -> 1 */
03229                                         if (rve_replace_with_ct_rv(rve, rv)<0)
03230                                                 goto error;
03231                                         ret=1;
03232                                 }else if (i==0){
03233                                         /* $v ||  0 -> (int)$v
03234                                          *  0 && $v -> (int)$v */
03235                                         rve_destroy(ct_rve);
03236                                         replace_int_rve(rve, v_rve);
03237                                         ret=1;
03238                                 }
03239                                 break;
03240                         case RVE_PLUS_OP:
03241                         case RVE_IPLUS_OP:
03242                                 /* we must make sure that this is an int PLUS
03243                                    (because "foo"+0 is valid => "foo0") =>
03244                                    check if it's an IPLUS or the result is an integer
03245                                    (which generally means unoptimized <int> + <something>).
03246                                  */
03247                                 if ((i==0) && ((op==RVE_IPLUS_OP) || (rve_type==RV_INT))){
03248                                         /* $v +  0 -> (int)$v
03249                                          *  0 + $v -> (int)$v */
03250                                         rve_destroy(ct_rve);
03251                                         replace_int_rve(rve, v_rve);
03252                                         ret=1;
03253                                 }
03254                                 break;
03255                         default:
03256                                 /* do nothing */
03257                                 break;
03258                 }
03259                 /* debugging messages */
03260                 if (ret==1 && dbg){
03261                         if (right){
03262                                 if (rve->op==RVE_RVAL_OP){
03263                                         if (rve->left.rval.type==RV_INT)
03264                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03265                                                                 " op%d($v, %d) -> %d\n", 
03266                                                                 rve->fpos.s_line, rve->fpos.s_col,
03267                                                                 rve->fpos.e_line, rve->fpos.e_col,
03268                                                                 op, i, (int)rve->left.rval.v.l);
03269                                         else
03270                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03271                                                                 " op%d($v, %d) -> $v (rval)\n",
03272                                                                 rve->fpos.s_line, rve->fpos.s_col,
03273                                                                 rve->fpos.e_line, rve->fpos.e_col,
03274                                                                 op, i);
03275                                 }else if (rve->op==RVE_INT_OP){
03276                                         if (rve->left.rve->op==RVE_RVAL_OP &&
03277                                                         rve->left.rve->left.rval.type==RV_INT)
03278                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03279                                                                 " op%d($v, %d) -> (int)%d\n", 
03280                                                                 rve->fpos.s_line, rve->fpos.s_col,
03281                                                                 rve->fpos.e_line, rve->fpos.e_col,
03282                                                                 op, i, (int)rve->left.rve->left.rval.v.l);
03283                                         else
03284                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03285                                                                 " op%d($v, %d) -> (int)$v\n",
03286                                                                 rve->fpos.s_line, rve->fpos.s_col,
03287                                                                 rve->fpos.e_line, rve->fpos.e_col,
03288                                                                 op, i);
03289                                 }else{
03290                                         DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03291                                                         " op%d($v, %d) -> $v\n",
03292                                                         rve->fpos.s_line, rve->fpos.s_col,
03293                                                         rve->fpos.e_line, rve->fpos.e_col,
03294                                                         op, i);
03295                                 }
03296                         }else{
03297                                 if (rve->op==RVE_RVAL_OP){
03298                                         if (rve->left.rval.type==RV_INT)
03299                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03300                                                                 " op%d(%d, $v) -> %d\n", 
03301                                                                 rve->fpos.s_line, rve->fpos.s_col,
03302                                                                 rve->fpos.e_line, rve->fpos.e_col,
03303                                                                 op, i, (int)rve->left.rval.v.l);
03304                                         else
03305                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03306                                                                 " op%d(%d, $v) -> $v (rval)\n",
03307                                                                 rve->fpos.s_line, rve->fpos.s_col,
03308                                                                 rve->fpos.e_line, rve->fpos.e_col,
03309                                                                 op, i);
03310                                 }else if (rve->op==RVE_INT_OP){
03311                                         if (rve->left.rve->op==RVE_RVAL_OP &&
03312                                                         rve->left.rve->left.rval.type==RV_INT)
03313                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03314                                                                 " op%d(%d, $v) -> (int)%d\n", 
03315                                                                 rve->fpos.s_line, rve->fpos.s_col,
03316                                                                 rve->fpos.e_line, rve->fpos.e_col,
03317                                                                 op, i, (int)rve->left.rve->left.rval.v.l);
03318                                         else
03319                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03320                                                                 " op%d(%d, $v) -> (int)$v\n",
03321                                                                 rve->fpos.s_line, rve->fpos.s_col,
03322                                                                 rve->fpos.e_line, rve->fpos.e_col,
03323                                                                 op, i);
03324                                 }else{
03325                                         DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03326                                                         " op%d(%d, $v) -> $v\n",
03327                                                         rve->fpos.s_line, rve->fpos.s_col,
03328                                                         rve->fpos.e_line, rve->fpos.e_col,
03329                                                         op, i);
03330                                 }
03331                         }
03332                 }
03333         }else if (rv->type==RV_STR){
03334                 switch(op){
03335                         case RVE_CONCAT_OP:
03336                                 if (rv->v.s.len==0){
03337                                         /* $v . "" -> (str)$v
03338                                            "" . $v -> (str)$v */
03339                                         rve_destroy(ct_rve);
03340                                         replace_str_rve(rve, v_rve);
03341                                         ret=1;
03342                                 }
03343                                 break;
03344                         case RVE_EQ_OP:
03345                         case RVE_STREQ_OP:
03346                                 if (rv->v.s.len==0){
03347                                         /* $v == "" -> strempty($v) 
03348                                            "" == $v -> strempty ($v) */
03349                                         rve_destroy(ct_rve);
03350                                         /* replace current expr. with strempty(rve) */
03351                                         rve->op=RVE_STREMPTY_OP;
03352                                         rve->left.rve=v_rve;
03353                                         rve->right.rve=0;
03354                                         ret=1;
03355                                         if (dbg)
03356                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03357                                                                 " op%d($v, \"\") -> strempty($v)\n", 
03358                                                                 rve->fpos.s_line, rve->fpos.s_col,
03359                                                                 rve->fpos.e_line, rve->fpos.e_col,
03360                                                                 op);
03361                                         dbg=0;
03362                                 }
03363                                 break;
03364                         default:
03365                                 break;
03366                 }
03367         /* no optimization for generic RVE_PLUS_OP for now, only for RVE_CONCAT_OP
03368            (RVE_PLUS_OP should be converted to RVE_CONCAT_OP if it's supposed
03369             to work on strings. If it's not converted/optimized it means it's type
03370             can be determined only at runtime => we cannot optimize */
03371                 
03372                 /* debugging messages */
03373                 if (ret==1 && dbg){
03374                         if (right){
03375                                 if (rve->op==RVE_RVAL_OP){
03376                                         if (rve->left.rval.type==RV_STR)
03377                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03378                                                                 " op%d($v, <string>) -> \"%s\"\n", 
03379                                                                 rve->fpos.s_line, rve->fpos.s_col,
03380                                                                 rve->fpos.e_line, rve->fpos.e_col,
03381                                                                 op, rve->left.rval.v.s.s);
03382                                         else
03383                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03384                                                                 " op%d($v, <string>) -> $v (rval)\n",
03385                                                                 rve->fpos.s_line, rve->fpos.s_col,
03386                                                                 rve->fpos.e_line, rve->fpos.e_col, op);
03387                                 }else if (rve->op==RVE_STR_OP){
03388                                         if (rve->left.rve->op==RVE_RVAL_OP &&
03389                                                         rve->left.rve->left.rval.type==RV_STR)
03390                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03391                                                                 " op%d($v, <string>) -> (str)\"%s\"\n", 
03392                                                                 rve->fpos.s_line, rve->fpos.s_col,
03393                                                                 rve->fpos.e_line, rve->fpos.e_col,
03394                                                                 op, rve->left.rve->left.rval.v.s.s);
03395                                         else
03396                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03397                                                                 " op%d($v, <string>) -> (str)$v\n",
03398                                                                 rve->fpos.s_line, rve->fpos.s_col,
03399                                                                 rve->fpos.e_line, rve->fpos.e_col, op);
03400                                 }else{
03401                                         DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03402                                                         " op%d($v, <string>) -> $v\n",
03403                                                         rve->fpos.s_line, rve->fpos.s_col,
03404                                                         rve->fpos.e_line, rve->fpos.e_col, op);
03405                                 }
03406                         }else{
03407                                 if (rve->op==RVE_RVAL_OP){
03408                                         if (rve->left.rval.type==RV_STR)
03409                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03410                                                                 " op%d(<string>, $v) -> \"%s\"\n", 
03411                                                                 rve->fpos.s_line, rve->fpos.s_col,
03412                                                                 rve->fpos.e_line, rve->fpos.e_col,
03413                                                                 op, rve->left.rval.v.s.s);
03414                                         else
03415                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03416                                                                 " op%d(<string>, $v) -> $v (rval)\n",
03417                                                                 rve->fpos.s_line, rve->fpos.s_col,
03418                                                                 rve->fpos.e_line, rve->fpos.e_col, op);
03419                                 }else if (rve->op==RVE_STR_OP){
03420                                         if (rve->left.rve->op==RVE_RVAL_OP &&
03421                                                         rve->left.rve->left.rval.type==RV_STR)
03422                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03423                                                                 " op%d(<string>, $v) -> (str)\"%s\"\n", 
03424                                                                 rve->fpos.s_line, rve->fpos.s_col,
03425                                                                 rve->fpos.e_line, rve->fpos.e_col,
03426                                                                 op, rve->left.rve->left.rval.v.s.s);
03427                                         else
03428                                                 DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03429                                                                 " op%d(<string>, $v) -> (str)$v\n",
03430                                                                 rve->fpos.s_line, rve->fpos.s_col,
03431                                                                 rve->fpos.e_line, rve->fpos.e_col, op);
03432                                 }else{
03433                                         DBG("FIXUP RVE: (%d,%d-%d,%d) optimized"
03434                                                         " op%d(<string>, $v) -> $v\n",
03435                                                         rve->fpos.s_line, rve->fpos.s_col,
03436                                                         rve->fpos.e_line, rve->fpos.e_col, op);
03437                                 }
03438                         }
03439                 }
03440         }
03441         if (rv) rval_destroy(rv);
03442         return ret;
03443 error:
03444         if (rv) rval_destroy(rv);
03445         return -1;
03446 }
03447 
03448 
03449 
03451 static int rve_optimize(struct rval_expr* rve)
03452 {
03453         int ret;
03454         struct rvalue* rv;
03455         struct rvalue* trv; /* used only for DBG() */
03456         enum rval_expr_op op;
03457         struct rval_expr tmp_rve;
03458         enum rval_type type, l_type;
03459         struct rval_expr* bad_rve;
03460         enum rval_type bad_type, exp_type;
03461         
03462         ret=0;
03463         rv=0;
03464         if (scr_opt_lev<1)
03465                 return 0;
03466         if (rve->op == RVE_RVAL_OP) /* if rval, nothing to do */
03467                 return 0;
03468         if (rve_is_constant(rve)){
03469                 if ((rv=rval_expr_eval_new(0, 0, rve))==0){
03470                         ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
03471                                         rve->fpos.s_line, rve->fpos.s_col,
03472                                         rve->fpos.e_line, rve->fpos.e_col);
03473                         goto error;
03474                 }
03475                 op=rve->op;
03476                 if (rve_replace_with_ct_rv(rve, rv)<0)
03477                         goto error;
03478                 rval_destroy(rv);
03479                 rv=0;
03480                 trv=&rve->left.rval;
03481                 if (trv->type==RV_INT)
03482                         DBG("FIXUP RVE (%d,%d-%d,%d): optimized constant int rve "
03483                                         "(old op %d) to %d\n",
03484                                         rve->fpos.s_line, rve->fpos.s_col,
03485                                         rve->fpos.e_line, rve->fpos.e_col,
03486                                         op, (int)trv->v.l);
03487                 else if (trv->type==RV_STR)
03488                         DBG("FIXUP RVE (%d,%d-%d,%d): optimized constant str rve "
03489                                         "(old op %d) to \"%.*s\"\n",
03490                                         rve->fpos.s_line, rve->fpos.s_col,
03491                                         rve->fpos.e_line, rve->fpos.e_col,
03492                                         op, trv->v.s.len, trv->v.s.s);
03493                 ret=1;
03494         }else{
03495                 /* expression is not constant */
03496                 /* if unary => nothing to do */
03497                 if (rve_op_unary(rve->op))
03498                         return rve_optimize(rve->left.rve);
03499                 rve_optimize(rve->left.rve);
03500                 rve_optimize(rve->right.rve);
03501                 if (!rve_check_type(&type, rve, &bad_rve, &bad_type, &exp_type)){
03502                         ERR("optimization failure while optimizing %d,%d-%d,%d:"
03503                                         " type mismatch in expression (%d,%d-%d,%d), "
03504                                         "type %s, but expected %s\n",
03505                                         rve->fpos.s_line, rve->fpos.s_col,
03506                                         rve->fpos.e_line, rve->fpos.e_col,
03507                                         bad_rve->fpos.s_line, bad_rve->fpos.s_col,
03508                                         bad_rve->fpos.e_line, bad_rve->fpos.e_col,
03509                                         rval_type_name(bad_type), rval_type_name(exp_type));
03510                         return 0;
03511                 }
03512                 /* $v - a => $v + (-a)  (easier to optimize)*/
03513                 if ((rve->op==RVE_MINUS_OP) && (rve_is_constant(rve->right.rve))){
03514                         if ((rv=rval_expr_eval_new(0, 0, rve->right.rve))==0){
03515                                 ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
03516                                                                 rve->right.rve->fpos.s_line,
03517                                                                 rve->right.rve->fpos.s_col,
03518                                                                 rve->right.rve->fpos.e_line,
03519                                                                 rve->right.rve->fpos.e_col);
03520                                 goto error;
03521                         }
03522                         if (rv->type==RV_INT){
03523                                 rv->v.l=-rv->v.l;
03524                                 if (rve_replace_with_ct_rv(rve->right.rve, rv)<0)
03525                                         goto error;
03526                                 rve->op=RVE_IPLUS_OP;
03527                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized $v - a into "
03528                                                 "$v + (%d)\n",
03529                                                 rve->fpos.s_line, rve->fpos.s_col,
03530                                                 rve->fpos.e_line, rve->fpos.e_col,
03531                                                 (int)rve->right.rve->left.rval.v.l);
03532                         }
03533                         rval_destroy(rv);
03534                         rv=0;
03535                 }
03536                 
03537                 /* e1 PLUS_OP e2 -> change op if we know e1 basic type */
03538                 if (rve->op==RVE_PLUS_OP){
03539                         l_type=rve_guess_type(rve->left.rve);
03540                         if (l_type==RV_INT){
03541                                 rve->op=RVE_IPLUS_OP;
03542                                 DBG("FIXUP RVE (%d,%d-%d,%d): changed + into integer plus\n",
03543                                                 rve->fpos.s_line, rve->fpos.s_col,
03544                                                 rve->fpos.e_line, rve->fpos.e_col);
03545                         }else if (l_type==RV_STR){
03546                                 rve->op=RVE_CONCAT_OP;
03547                                 DBG("FIXUP RVE (%d,%d-%d,%d): changed + into string concat\n",
03548                                                 rve->fpos.s_line, rve->fpos.s_col,
03549                                                 rve->fpos.e_line, rve->fpos.e_col);
03550                         }
03551                 }
03552                 /* e1 EQ_OP e2 -> change op if we know e1 basic type
03553                    e1 DIFF_OP e2 -> change op if we know e2 basic type */
03554                 if (rve->op==RVE_EQ_OP || rve->op==RVE_DIFF_OP){
03555                         l_type=rve_guess_type(rve->left.rve);
03556                         if (l_type==RV_INT){
03557                                 rve->op=(rve->op==RVE_EQ_OP)?RVE_IEQ_OP:RVE_IDIFF_OP;
03558                                 DBG("FIXUP RVE (%d,%d-%d,%d): changed ==/!= into integer"
03559                                                 " ==/!=\n",
03560                                                 rve->fpos.s_line, rve->fpos.s_col,
03561                                                 rve->fpos.e_line, rve->fpos.e_col);
03562                         }else if (l_type==RV_STR){
03563                                 rve->op=(rve->op==RVE_EQ_OP)?RVE_STREQ_OP:RVE_STRDIFF_OP;
03564                                 DBG("FIXUP RVE (%d,%d-%d,%d): changed ==/!= into string"
03565                                                 " ==/!=\n",
03566                                                 rve->fpos.s_line, rve->fpos.s_col,
03567                                                 rve->fpos.e_line, rve->fpos.e_col);
03568                         }
03569                 }
03570                 
03571                 /* $v * 0 => 0; $v * 1 => $v (for *, /, &, |, &&, ||, +, -) */
03572                 if (rve_opt_01(rve, type)==1){
03573                         /* success, rve was changed => return now
03574                           (since this is recursively invoked the "new" rve
03575                            is already optimized) */
03576                         ret=1;
03577                         goto end;
03578                 }
03579                 
03580                 /* op(op($v, a), b) => op($v, op(a,b)) */
03581                 if (rve_is_constant(rve->right.rve)){
03582                         /* op1(op2(...), b) */
03583                         if ((rve->op==rve->left.rve->op) && rve_op_is_assoc(rve->op)){
03584                                 /* op(op(...), b) */
03585                                 if (rve_is_constant(rve->left.rve->right.rve)){
03586                                         /* op(op($v, a), b) => op($v, op(a, b)) */
03587                                         /* rv= op(a, b) */
03588                                         tmp_rve.op=rve->op;
03589                                         tmp_rve.left.rve=rve->left.rve->right.rve;
03590                                         tmp_rve.right.rve=rve->right.rve;
03591                                         /* hack for RVE_PLUS_OP which can work on string, ints
03592                                            or a combination of them */
03593                                         if ((rve->op==RVE_PLUS_OP) &&
03594                                                 (rve_guess_type(tmp_rve.left.rve)!=RV_STR)){
03595                                                 DBG("RVE optimization failed (%d,%d-%d,%d): cannot "
03596                                                         "optimize +(+($v, a), b) when typeof(a)==INT\n",
03597                                                         rve->fpos.s_line, rve->fpos.s_col,
03598                                                         rve->fpos.e_line, rve->fpos.e_col);
03599                                                 return 0;
03600                                         }
03601                                         if ((rv=rval_expr_eval_new(0, 0, &tmp_rve))==0){
03602                                                 ERR("optimization failure, bad expression\n");
03603                                                 goto error;
03604                                         }
03605                                         /* op($v, rv) */
03606                                         if (rve_replace_with_ct_rv(rve->right.rve, rv)<0)
03607                                                 goto error;
03608                                         rval_destroy(rv);
03609                                         rv=0;
03610                                         rve_destroy(tmp_rve.left.rve);
03611                                         rve->left.rve=rve->left.rve->left.rve;
03612                                         trv=&rve->right.rve->left.rval;
03613                                         if (trv->type==RV_INT)
03614                                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
03615                                                                 "op(op($v, a), b) with op($v, %d); op=%d\n",
03616                                                                 rve->fpos.s_line, rve->fpos.s_col,
03617                                                                 rve->fpos.e_line, rve->fpos.e_col,
03618                                                                 (int)trv->v.l, rve->op);
03619                                         else if (trv->type==RV_STR)
03620                                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
03621                                                                 "op(op($v, a), b) with op($v, \"%.*s\");"
03622                                                                 " op=%d\n",
03623                                                                 rve->fpos.s_line, rve->fpos.s_col,
03624                                                                 rve->fpos.e_line, rve->fpos.e_col,
03625                                                                 trv->v.s.len, trv->v.s.s, rve->op);
03626                                         ret=1;
03627                                 }else if (rve_is_constant(rve->left.rve->left.rve) &&
03628                                                         rve_op_is_commutative(rve->op)){
03629                                         /* op(op(a, $v), b) => op(op(a, b), $v) */
03630                                         /* rv= op(a, b) */
03631                                         tmp_rve.op=rve->op;
03632                                         tmp_rve.left.rve=rve->left.rve->left.rve;
03633                                         tmp_rve.right.rve=rve->right.rve;
03634                                         /* no need for the RVE_PLUS_OP hack, all the bad
03635                                            cases are caught by rve_op_is_commutative()
03636                                            (in this case type will be typeof(a)) => ok only if
03637                                            typeof(a) is int) */
03638                                         if ((rv=rval_expr_eval_new(0, 0, &tmp_rve))==0){
03639                                                 ERR("optimization failure, bad expression\n");
03640                                                 goto error;
03641                                         }
03642                                         /* op(rv, $v) */
03643                                         rve_destroy(rve->right.rve);
03644                                         rve->right.rve=rve->left.rve->right.rve;
03645                                         rve->left.rve->right.rve=0;
03646                                         if (rve_replace_with_ct_rv(rve->left.rve, rv)<0)
03647                                                 goto error;
03648                                         rval_destroy(rv);
03649                                         rv=0;
03650                                         trv=&rve->left.rve->left.rval;
03651                                         if (trv->type==RV_INT)
03652                                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
03653                                                                 "op(op(a, $v), b) with op(%d, $v); op=%d\n",
03654                                                                 rve->fpos.s_line, rve->fpos.s_col,
03655                                                                 rve->fpos.e_line, rve->fpos.e_col,
03656                                                                 (int)trv->v.l, rve->op);
03657                                         else if (trv->type==RV_STR)
03658                                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
03659                                                                 "op(op(a, $v), b) with op(\"%.*s\", $v);"
03660                                                                 " op=%d\n",
03661                                                                 rve->fpos.s_line, rve->fpos.s_col,
03662                                                                 rve->fpos.e_line, rve->fpos.e_col,
03663                                                                 trv->v.s.len, trv->v.s.s, rve->op);
03664                                         ret=1;
03665                                 }
03666                                 /* op(op($v, $w),b) => can't optimize */
03667                         }
03668                         /* op1(op2(...), b) and op1!=op2 or op is non assoc.
03669                            => can't optimize */
03670                 }else if (rve_is_constant(rve->left.rve)){
03671                         /* op1(a, op2(...)) */
03672                         if ((rve->op==rve->right.rve->op) && rve_op_is_assoc(rve->op)){
03673                                 /* op(a, op(...)) */
03674                                 if (rve_is_constant(rve->right.rve->right.rve) &&
03675                                                 rve_op_is_commutative(rve->op)){
03676                                         /* op(a, op($v, b)) => op(op(a, b), $v) */
03677                                         /* rv= op(a, b) */
03678                                         tmp_rve.op=rve->op;
03679                                         tmp_rve.left.rve=rve->left.rve;
03680                                         tmp_rve.right.rve=rve->right.rve->right.rve;
03681                                         /* no need for the RVE_PLUS_OP hack, all the bad
03682                                            cases are caught by rve_op_is_commutative()
03683                                            (in this case type will be typeof(a)) => ok only if
03684                                            typeof(a) is int) */
03685                                         if ((rv=rval_expr_eval_new(0, 0, &tmp_rve))==0){
03686                                                 ERR("optimization failure, bad expression\n");
03687                                                 goto error;
03688                                         }
03689                                         /* op(rv, $v) */
03690                                         if (rve_replace_with_ct_rv(rve->left.rve, rv)<0)
03691                                                 goto error;
03692                                         rval_destroy(rv);
03693                                         rv=0;
03694                                         rve_destroy(tmp_rve.right.rve);
03695                                         rve->right.rve=rve->right.rve->left.rve;
03696                                         trv=&rve->left.rve->left.rval;
03697                                         if (trv->type==RV_INT)
03698                                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
03699                                                                 "op(a, op($v, b)) with op(%d, $v); op=%d\n",
03700                                                                 rve->fpos.s_line, rve->fpos.s_col,
03701                                                                 rve->fpos.e_line, rve->fpos.e_col,
03702                                                                 (int)trv->v.l, rve->op);
03703                                         else if (trv->type==RV_STR)
03704                                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
03705                                                                 "op(a, op($v, b)) with op(\"%.*s\", $v);"
03706                                                                 " op=%d\n",
03707                                                                 rve->fpos.s_line, rve->fpos.s_col,
03708                                                                 rve->fpos.e_line, rve->fpos.e_col,
03709                                                                 trv->v.s.len, trv->v.s.s, rve->op);
03710                                         ret=1;
03711                                 }else if (rve_is_constant(rve->right.rve->left.rve)){
03712                                         /* op(a, op(b, $v)) => op(op(a, b), $v) */
03713                                         /* rv= op(a, b) */
03714                                         tmp_rve.op=rve->op;
03715                                         tmp_rve.left.rve=rve->left.rve;
03716                                         tmp_rve.right.rve=rve->right.rve->left.rve;
03717                                         /* hack for RVE_PLUS_OP which can work on string, ints
03718                                            or a combination of them */
03719                                         if ((rve->op==RVE_PLUS_OP) &&
03720                                                 (rve_guess_type(tmp_rve.left.rve) != 
03721                                                         rve_guess_type(tmp_rve.right.rve))){
03722                                                 DBG("RVE optimization failed (%d,%d-%d,%d): cannot "
03723                                                                 "optimize +(a, +(b, $v)) when "
03724                                                                 "typeof(a)!=typeof(b)\n",
03725                                                                 rve->fpos.s_line, rve->fpos.s_col,
03726                                                                 rve->fpos.e_line, rve->fpos.e_col);
03727                                                 return 0;
03728                                         }
03729                                         if ((rv=rval_expr_eval_new(0, 0, &tmp_rve))==0){
03730                                                 ERR("optimization failure, bad expression\n");
03731                                                 goto error;
03732                                         }
03733                                         /* op(rv, $v) */
03734                                         if (rve_replace_with_ct_rv(rve->left.rve, rv)<0)
03735                                                 goto error;
03736                                         rval_destroy(rv);
03737                                         rv=0;
03738                                         rve_destroy(tmp_rve.right.rve);
03739                                         rve->right.rve=rve->right.rve->right.rve;
03740                                         trv=&rve->left.rve->left.rval;
03741                                         if (trv->type==RV_INT)
03742                                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized int rve: "
03743                                                                 "op(a, op(b, $v)) with op(%d, $v); op=%d\n",
03744                                                                 rve->fpos.s_line, rve->fpos.s_col,
03745                                                                 rve->fpos.e_line, rve->fpos.e_col,
03746                                                                 (int)trv->v.l, rve->op);
03747                                         else if (trv->type==RV_STR)
03748                                                 DBG("FIXUP RVE (%d,%d-%d,%d): optimized str rve "
03749                                                                 "op(a, op(b, $v)) with op(\"%.*s\", $v);"
03750                                                                 " op=%d\n",
03751                                                                 rve->fpos.s_line, rve->fpos.s_col,
03752                                                                 rve->fpos.e_line, rve->fpos.e_col,
03753                                                                 trv->v.s.len, trv->v.s.s, rve->op);
03754                                         ret=1;
03755                                 }
03756                                 /* op(a, op($v, $w)) => can't optimize */
03757                         }
03758                         /* op1(a, op2(...)) and op1!=op2 or op is non assoc.
03759                            => can't optimize */
03760                 }
03761                 /* op(op($v,a), op($w,b)) => no optimizations for now (TODO) */
03762         }
03763 end:
03764         return ret;
03765 error:
03766         if (rv) rval_destroy(rv);
03767         return -1;
03768 }
03769 
03770 
03771 
03779 int fix_rval_expr(void* p)
03780 {
03781         struct rval_expr* rve;
03782         int ret;
03783         
03784         rve=(struct rval_expr*)p;
03785         
03786         switch(rve->op){
03787                 case RVE_NONE_OP:
03788                         BUG("empty rval expr\n");
03789                         break;
03790                 case RVE_RVAL_OP:
03791                         return fix_rval(&rve->left.rval);
03792                 case RVE_UMINUS_OP: /* unary operators */
03793                 case RVE_BOOL_OP:
03794                 case RVE_LNOT_OP:
03795                 case RVE_BNOT_OP:
03796                 case RVE_STRLEN_OP:
03797                 case RVE_STREMPTY_OP:
03798                 case RVE_DEFINED_OP:
03799                 case RVE_INT_OP:
03800                 case RVE_STR_OP:
03801                         ret=fix_rval_expr((void*)rve->left.rve);
03802                         if (ret<0) return ret;
03803                         break;
03804                 case RVE_MUL_OP:
03805                 case RVE_DIV_OP:
03806                 case RVE_MOD_OP:
03807                 case RVE_MINUS_OP:
03808                 case RVE_BOR_OP:
03809                 case RVE_BAND_OP:
03810                 case RVE_BXOR_OP:
03811                 case RVE_BLSHIFT_OP:
03812                 case RVE_BRSHIFT_OP:
03813                 case RVE_LAND_OP:
03814                 case RVE_LOR_OP:
03815                 case RVE_GT_OP:
03816                 case RVE_GTE_OP:
03817                 case RVE_LT_OP:
03818                 case RVE_LTE_OP:
03819                 case RVE_PLUS_OP:
03820                 case RVE_IPLUS_OP:
03821                 case RVE_EQ_OP:
03822                 case RVE_DIFF_OP:
03823                 case RVE_IEQ_OP:
03824                 case RVE_IDIFF_OP:
03825                 case RVE_STREQ_OP:
03826                 case RVE_STRDIFF_OP:
03827                 case RVE_CONCAT_OP:
03828                         ret=fix_rval_expr((void*)rve->left.rve);
03829                         if (ret<0) return ret;
03830                         ret=fix_rval_expr((void*)rve->right.rve);
03831                         if (ret<0) return ret;
03832                         break;
03833                 case RVE_MATCH_OP:
03834                         ret=fix_match_rve(rve);
03835                         if (ret<0) return ret;
03836                         break;
03837                 default:
03838                         BUG("unsupported op type %d\n", rve->op);
03839         }
03840         /* try to optimize */
03841         rve_optimize(rve);
03842         return 0;
03843 }

Generated on Tue May 22 2012 13:10:14 for SIP Router by  doxygen 1.7.1