mod_fix.c
51d17660
 /* 
  * $Id$
  * 
  * Copyright (C) 2008 iptelorg GmbH
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
  *
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 /**
  * @file mod_fix.c
  * @brief kamailio compatible fixups
  */
 /* 
  * History:
  * --------
  *  2008-11-25  initial version (andrei)
  */
 
 #include "mod_fix.h"
 #include "mem/mem.h"
 
 
 
 #if 0
 /* TODO: */
 int fixup_regexpNL_null(void** param, int param_no); /* not used */
 int fixup_regexpNL_none(void** param, int param_no); /* textops */
 #endif
 
 
 
 #define FREE_FIXUP_FP(suffix, minp, maxp) \
 	int fixup_free_##suffix(void** param, int param_no) \
 	{ \
 		if ((param_no > (maxp)) || (param_no < (minp))) \
 			return E_UNSPEC; \
 		if (*param){ \
 			fparam_free_contents((fparam_t*)*param); \
 			pkg_free(*param); \
 			*param=0; \
 		} \
 		return 0; \
 	}
 
 
 /** macro for declaring a fixup and the corresponding free_fixup
   * for a function which fixes to fparam_t and expects 2 different types.
   *
   * The result (in *param) will be a fparam_t.
   *
   * @param suffix - function suffix (fixup_ will be pre-pended to it 
   * @param minp - minimum parameter number acceptable
   * @param maxp - maximum parameter number
   * @param no1 -  number of parameters of type1
   * @param type1 - fix_param type for the 1st param
   * @paran type2 - fix_param type for all the other params
   */
 #define FIXUP_F2FP(suffix, minp, maxp, no1, type1, type2) \
 	int fixup_##suffix (void** param, int param_no) \
 	{ \
 		if ((param_no > (maxp)) || (param_no <(minp))) \
 			return E_UNSPEC; \
 		if (param_no <= (no1)){ \
 			if (fix_param_types((type1), param)!=0) {\
 				ERR("Cannot convert function parameter %d to" #type1 "\n", \
 						param_no);\
 				return E_UNSPEC; \
 			} \
 		}else{ \
 			if (fix_param_types((type2), param)!=0) {\
 				ERR("Cannot convert function parameter %d to" #type2 "\n", \
 						param_no); \
 				return E_UNSPEC; \
 			} \
 		}\
 		return 0; \
 	} \
 	FREE_FIXUP_FP(suffix, minp, maxp)
 
 
 /** macro for declaring a fixup and the corresponding free_fixup
   * for a function which fixes directly to the requested type.
   *
   * @see FIXUP_F2FP for the parameters
   * Side effect: declares also some _fp_helper functions
   */
 #define FIXUP_F2T(suffix, minp, maxp, no1, type1, type2) \
 	FIXUP_F2FP(fp_##suffix, minp, maxp, no1, type1, type2) \
 	int fixup_##suffix (void** param, int param_no) \
 	{ \
 		int ret; \
 		if ((ret=fixup_fp_##suffix (param, param_no))!=0) \
 			return ret; \
 		*param=&((fparam_t*)*param)->v; \
 		return 0; \
 	} \
 	int fixup_free_##suffix (void** param, int param_no) \
 	{ \
 		void* p; \
 		int ret; \
 		if (param && *param){ \
 			p=*param - (long)&((fparam_t*)0)->v; \
 			if ((ret=fixup_free_fp_##suffix(&p, param_no))==0) *param=p; \
 			return ret; \
 		} \
 		return 0; \
 	}
 
 
 /** macro for declaring a fixup and the corresponding free_fixup
   * for a function expecting first no1 params as fparamt_t and the
   * rest as direct type.
   *
   * @see FIXUP_F2FP for the parameters with the exception
   * that only the first no1 parameters are converted to 
   * fparamt_t and the rest directly to the correponding type
   *
   * Side effect: declares also some _fpt_helper functions
   */
 #define FIXUP_F2FP_T(suffix, minp, maxp, no1, type1, type2) \
 	FIXUP_F2FP(fpt_##suffix, minp, maxp, no1, type1, type2) \
 	int fixup_##suffix (void** param, int param_no) \
 	{ \
 		int ret; \
 		if ((ret=fixup_fpt_##suffix(param, param_no))!=0) \
 			return ret; \
 		if (param_no>(no1)) *param=&((fparam_t*)*param)->v; \
 		return 0; \
 	} \
 	int fixup_free_##suffix (void** param, int param_no) \
 	{ \
 		void* p; \
 		int ret; \
 		if (param && *param){ \
 			p=(param_no>(no1))? *param - (long)&((fparam_t*)0)->v : *param;\
 			if ((ret=fixup_free_fpt_##suffix(&p, param_no))==0) *param=0; \
 			return ret; \
 		} \
 		return 0; \
 	}
 
 
 /** macro for declaring a fixup which fixes all the paremeters to the same
   * type.
   *
   * @see FIXUP_F2T.
   */
 #define FIXUP_F1T(suffix, minp, maxp, type) \
 	FIXUP_F2T(suffix, minp, maxp, maxp, type, 0)
 
 
 
 FIXUP_F1T(str_null, 1, 1, FPARAM_STR)
 FIXUP_F1T(str_str, 1, 2,  FPARAM_STR)
 
 /* TODO: int can be converted in place, no need for pkg_malloc'ed fparam_t*/
 FIXUP_F1T(uint_null, 1, 1, FPARAM_INT)
 FIXUP_F1T(uint_uint, 1, 2, FPARAM_INT)
 
 FIXUP_F1T(regexp_null, 1, 1, FPARAM_REGEX)
 
 FIXUP_F1T(pvar_null, 1, 1, FPARAM_PVS)
 FIXUP_F1T(pvar_pvar, 1, 2, FPARAM_PVS)
 
 FIXUP_F2T(pvar_str, 1, 2, 1, FPARAM_PVS, FPARAM_STR)
 FIXUP_F2T(pvar_str_str, 1, 3, 1, FPARAM_PVS, FPARAM_STR)
 
 FIXUP_F2FP(igp_null, 1, 1, 1, FPARAM_INT|FPARAM_PVS, 0)
 FIXUP_F2FP(igp_igp, 1, 2, 2,  FPARAM_INT|FPARAM_PVS, 0)
 
 FIXUP_F2FP_T(igp_pvar_pvar, 1, 3, 1, FPARAM_INT|FPARAM_PVS, FPARAM_PVS)
 
 /** macro for declaring a spve fixup and the corresponding free_fixup
   * for a function expecting first no1 params as fparam converted spve 
   * and the * rest as direct type.
   *
   * @see FIXUP_F2FP for the parameters with the exception
   * that the first no1 parameters are converted to fparam_t from spve
   * and the rest directly to the corresponding type
   *
   * Side effect: declares also some _spvet_helper functions
   */
 #define FIXUP_F_SPVE_T(suffix, minp, maxp, no1, type2) \
 	FIXUP_F1T(spvet_##suffix, minp, maxp, type2) \
 	int fixup_##suffix (void** param, int param_no) \
 	{ \
 		int ret; \
 		char * bkp; \
 		fparam_t* fp; \
 		bkp=*param; \
 		if (param_no<=(no1)){ \
 			if ((ret=fix_param_types(FPARAM_PVE, param))<0){ \
 				ERR("Cannot convert function parameter %d to" #type2 "\n", \
 						param_no);\
 				return E_UNSPEC; \
 			} else{ \
 				fp=(fparam_t*)*param; \
 				if ((ret==0) && (fp->v.pve->spec.getf==0)){ \
 					fparam_free_contents(fp); \
 					pkg_free(fp); \
 					*param=bkp; \
 					return fix_param_types(FPARAM_STR, param); \
 				} else if (ret==1) \
 					return fix_param_types(FPARAM_STR, param); \
 				return ret; \
 			} \
 		} else return fixup_spvet_##suffix(param, param_no); \
 		return 0; \
 	} \
 	int fixup_free_##suffix (void** param, int param_no) \
 	{ \
 		if (param && *param){ \
 			if (param_no<=(no1)){ \
 				fparam_free_contents((fparam_t*)*param); \
 				pkg_free(*param); \
 				*param=0; \
 			} else \
 				return fixup_free_spvet_##suffix(param, param_no); \
 		} \
 		return 0; \
 	}
 
 
 FIXUP_F_SPVE_T(spve_spve, 1, 2, 2, 0)
 FIXUP_F_SPVE_T(spve_uint, 1, 2, 2, FPARAM_INT)
 FIXUP_F_SPVE_T(spve_str, 1, 2, 2, FPARAM_STR)