Browse code

script engine: verbose conversion-to-int errors

- more verbose errors (all of them contain now the config file
position for the error).
- integer conversion errors will now by default log a warning
message. Like before they won't cause the expression evaluation
to fail, they'll just evaluate the failed conversion to 0.
The behaviour can be changed using the defines at the top of
rvalue.c. To restore the old behaviour (no int conversion error
message and error ignored), comment out the following defines:
RV_STR2INT_VERBOSE_ERR, RV_STRINT_ERR, EVAL_GET_INT_ERR_WARN,
RVAL_GET_INT_ERR_IGN. For more info see the comments in the
file.

Andrei Pelinescu-Onciul authored on 16/11/2009 18:41:02
Showing 2 changed files
... ...
@@ -377,7 +377,9 @@ int lval_assign(struct run_act_ctx* h, struct sip_msg* msg,
377 377
 	ret=0;
378 378
 	rv=rval_expr_eval(h, msg, rve);
379 379
 	if (unlikely(rv==0)){
380
-		ERR("rval expression evaluation failed\n");
380
+		ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
381
+				rve->fpos.s_line, rve->fpos.s_col,
382
+				rve->fpos.e_line, rve->fpos.e_col);
381 383
 		goto error;
382 384
 	}
383 385
 	switch(lv->type){
... ...
@@ -44,12 +44,43 @@
44 44
  *                          ("" == "")
45 45
  * NOTE: expr == undef, with defined(expr) is always evaluated this way:
46 46
          expr == (type_of(expr))undef
47
+ *  RV_STR2INT_VERBOSE_ERR - if a string conversion to int fails, log (L_WARN)
48
+ *                           the string that caused it (only the string, not
49
+ *                           the expression position).
50
+ *  RV_STR2INT_ERR         - if a string conversion to int fails, don't ignore
51
+ *                           the error (return error).
52
+ *  RVAL_GET_INT_ERR_WARN  - if a conversion to int fails, log a warning with
53
+ *                           the expression position.
54
+ *                           Depends on RV_STR2INT_ERR.
55
+ *  RVAL_GET_INT_ERR_IGN   - if a conversion to int fails, ignore the error
56
+ *                           (the result will be 0). Can be combined with
57
+ *                           RVAL_GET_INT_ERR_WARN.
58
+ *                           Depends on RV_STR2INT_ERR.
47 59
  */
48 60
 
49 61
 #include "rvalue.h"
50 62
 
51 63
 #include <stdlib.h> /* abort() */
52 64
 
65
+/* if defined warn when str2int conversions fail */
66
+#define RV_STR2INT_VERBOSE_ERR
67
+
68
+/* if defined rval_get_int will fail if str2int conversion fail
69
+   (else convert to 0) */
70
+#define RV_STR2INT_ERR
71
+
72
+/* if a rval_get_int fails (conversion to int), warn
73
+   Depends on RV_STR2INT_ERR.
74
+ */
75
+#define RVAL_GET_INT_ERR_WARN
76
+
77
+/* if a rval_get_int fails, ignore it (expression evaluation will not fail,
78
+   the int conversion will result in 0).
79
+   Can be combined with RVAL_GET_INT_ERR_WARN.
80
+   Depends on RV_STR2INT_ERR.
81
+ */
82
+#define RVAL_GET_INT_ERR_IGN
83
+
53 84
 /* minimum size alloc'ed for STR RVs (to accomodate
54 85
  * strops without reallocs) */
55 86
 #define RV_STR_EXTRA 80
... ...
@@ -127,15 +158,19 @@ void rve_destroy(struct rval_expr* rve)
127 158
 				if (rve->left.rval.refcnt==1)
128 159
 					rval_destroy(&rve->left.rval);
129 160
 				else
130
-					BUG("rval expr rval with invalid refcnt: %d\n", 
131
-							rve->left.rval.refcnt);
161
+					BUG("rval expr rval with invalid refcnt: %d (%d,%d-%d,%d)"
162
+							"\n", rve->left.rval.refcnt,
163
+							rve->fpos.s_line, rve->fpos.s_col,
164
+							rve->fpos.e_line, rve->fpos.e_col);
132 165
 			}
133 166
 			if (rve->right.rval.refcnt){
134 167
 				if (rve->right.rval.refcnt==1)
135 168
 					rval_destroy(&rve->right.rval);
136 169
 				else
137
-					BUG("rval expr rval with invalid refcnt: %d\n", 
138
-							rve->right.rval.refcnt);
170
+					BUG("rval expr rval with invalid refcnt: %d (%d,%d-%d,%d)"
171
+							"\n", rve->right.rval.refcnt,
172
+							rve->fpos.s_line, rve->fpos.s_col,
173
+							rve->fpos.e_line, rve->fpos.e_col);
139 174
 			}
140 175
 		}else{
141 176
 			if (rve->left.rve)
... ...
@@ -802,7 +837,9 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
802 837
 			break;
803 838
 		case RVE_NONE_OP:
804 839
 		default:
805
-			BUG("unexpected rve op %d\n", rve->op);
840
+			BUG("unexpected rve op %d (%d,%d-%d,%d)\n", rve->op,
841
+					rve->fpos.s_line, rve->fpos.s_col,
842
+					rve->fpos.e_line, rve->fpos.e_col);
806 843
 			if (bad_rve) *bad_rve=rve;
807 844
 			if (bad_t) *bad_t=RV_NONE;
808 845
 			if (exp_t) *exp_t=RV_STR;
... ...
@@ -835,11 +872,12 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
835 872
 	pv_value_t pval;
836 873
 	str tmp;
837 874
 	str* s;
838
-	int r;
875
+	int r, ret;
839 876
 	int destroy_pval;
840 877
 	
841 878
 	destroy_pval=0;
842 879
 	s=0;
880
+	ret=0;
843 881
 	switch(rv->type){
844 882
 		case RV_INT:
845 883
 			*i=rv->v.l;
... ...
@@ -931,15 +969,12 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
931 969
 			BUG("rv type %d not handled\n", rv->type);
932 970
 			goto error;
933 971
 	}
934
-	return 0;
972
+	return ret;
935 973
 undef:
936 974
 eval_error: /* same as undefined */
937 975
 	/* handle undefined => result 0, return success */
938 976
 	*i=0;
939 977
 	return 0;
940
-error_cache:
941
-	BUG("invalid cached value:cache type %d, value type %d\n",
942
-			cache?cache->cache_type:0, cache?cache->val_type:0);
943 978
 rv_str:
944 979
 	/* rv is of string type => try to convert it to int */
945 980
 	/* if "" => 0 (most likely case) */
... ...
@@ -947,17 +982,73 @@ rv_str:
947 982
 	else if (unlikely(str2sint(s, i)!=0)){
948 983
 		/* error converting to int => non numeric => 0 */
949 984
 		*i=0;
985
+#ifdef RV_STR2INT_VERBOSE_ERR
986
+		WARN("automatic string to int conversion for \"%.*s\" failed\n",
987
+				s->len, ZSW(s->s));
988
+		/* return an error code */
989
+#endif
990
+#ifdef RV_STR2INT_ERR
991
+		ret=-1;
992
+#endif
950 993
 	}
951 994
 	if (destroy_pval)
952 995
 		pv_value_destroy(&pval);
953
-	return 0;
996
+	return ret;
997
+error_cache:
998
+	BUG("invalid cached value:cache type %d, value type %d\n",
999
+			cache?cache->cache_type:0, cache?cache->val_type:0);
954 1000
 error:
1001
+	if (destroy_pval)
1002
+		pv_value_destroy(&pval);
955 1003
 	*i=0;
956 1004
 	return -1;
957 1005
 }
958 1006
 
959 1007
 
960 1008
 
1009
+/** log a message, appending rve position and a '\n'.*/
1010
+#define RVE_LOG(lev, rve, txt) \
1011
+	LOG((lev), txt " (%d,%d-%d,%d)\n", \
1012
+			(rve)->fpos.s_line, rve->fpos.s_col, \
1013
+			(rve)->fpos.e_line, rve->fpos.e_col )
1014
+
1015
+
1016
+/** macro for checking and handling rval_get_int() retcode.
1017
+ * check if the return code is an rval_get_int error and if so
1018
+ * handle the error (e.g. print a log message, ignore the error by
1019
+ * setting ret to 0 a.s.o.)
1020
+ * @param ret - retcode as returned by rval_get_int() (might be changed)
1021
+ * @param txt - warning message txt (no pointer allowed)
1022
+ * @param rve - rval_expr, used to access the config. pos
1023
+ */
1024
+#if defined RVAL_GET_INT_ERR_WARN && defined RVAL_GET_INT_ERR_IGN
1025
+#define rval_get_int_handle_ret(ret, txt, rve) \
1026
+	do { \
1027
+		if (unlikely((ret)<0)) { \
1028
+			RVE_LOG(L_WARN, rve, txt); \
1029
+			(ret)=0; \
1030
+		} \
1031
+	}while(0)
1032
+#elif defined RVAL_GET_INT_ERR_WARN
1033
+#define rval_get_int_handle_ret(ret, txt, rve) \
1034
+	do { \
1035
+		if (unlikely((ret)<0)) \
1036
+			RVE_LOG(L_WARN, rve, txt); \
1037
+	}while(0)
1038
+#elif define RVAL_GET_INT_ERR_IGN \
1039
+	do { \
1040
+		if (unlikely((ret)<0)) \
1041
+				(ret)=0; \
1042
+	} while(0)
1043
+#else
1044
+#define rval_get_int_handle_ret(ret, txt, rve) /* do nothing */
1045
+#endif
1046
+
1047
+
1048
+
1049
+
1050
+
1051
+
961 1052
 /** get the string value of an rv in a tmp variable
962 1053
   * *s=(str)rv
963 1054
   * if rv == undefined select, avp or pvar, return "".
... ...
@@ -1743,6 +1834,8 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1743 1834
 	switch(rve->op){
1744 1835
 		case RVE_RVAL_OP:
1745 1836
 			ret=rval_get_int(h, msg, res,  &rve->left.rval, 0);
1837
+			rval_get_int_handle_ret(ret, "rval expression conversion to int"
1838
+										" failed", rve);
1746 1839
 			break;
1747 1840
 		case RVE_UMINUS_OP:
1748 1841
 		case RVE_BOOL_OP:
... ...
@@ -1870,7 +1963,7 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1870 1963
 #endif /* UNDEF_EQ_* */
1871 1964
 					rval_cache_clean(&c1);
1872 1965
 					rval_destroy(rv1);
1873
-				}else{ 
1966
+				}else{
1874 1967
 					/* left value == defined and != int => str
1875 1968
 					 * => lval == (str) val */
1876 1969
 					if (unlikely((rv2=rval_expr_eval(h, msg,
... ...
@@ -1893,8 +1986,10 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1893 1986
 				ret=-1;
1894 1987
 				break;
1895 1988
 			}
1896
-			/* conver to int */
1989
+			/* convert to int */
1897 1990
 			ret=rval_get_int(h, msg, res, rv1, 0); /* convert to int */
1991
+			rval_get_int_handle_ret(ret, "rval expression conversion to int"
1992
+										" failed", rve);
1898 1993
 			rval_destroy(rv1);
1899 1994
 			break;
1900 1995
 		case RVE_STR_OP:
... ...
@@ -1909,6 +2004,8 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1909 2004
 			if (unlikely(rv1)){
1910 2005
 				/* expr evaluated to string => (int)(str)v == (int)v */
1911 2006
 				ret=rval_get_int(h, msg, res, rv1, &c1); /* convert to int */
2007
+				rval_get_int_handle_ret(ret, "rval expression conversion"
2008
+												" to int failed", rve);
1912 2009
 				rval_destroy(rv1);
1913 2010
 				rval_cache_clean(&c1);
1914 2011
 			} /* else (rv1==0)
... ...
@@ -1960,7 +2057,9 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1960 2057
 			break;
1961 2058
 		case RVE_NONE_OP:
1962 2059
 		/*default:*/
1963
-			BUG("invalid rval int expression operation %d\n", rve->op);
2060
+			BUG("invalid rval int expression operation %d (%d,%d-%d,%d)\n",
2061
+					rve->op, rve->fpos.s_line, rve->fpos.s_col,
2062
+					rve->fpos.e_line, rve->fpos.e_col);
1964 2063
 			ret=-1;
1965 2064
 	};
1966 2065
 	return ret;
... ...
@@ -2010,12 +2109,10 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
2010 2109
 			type=rval_get_btype(h, msg, rv1, cache);
2011 2110
 			if (type==RV_INT){
2012 2111
 					r=rval_get_int(h, msg, res_i, rv1, cache);
2013
-					if (unlikely(r<0)){
2014
-						ERR("rval expression evaluation failed\n");
2015
-						goto error;
2016
-					}
2112
+					rval_get_int_handle_ret(r, "rval expression conversion"
2113
+												" to int failed", rve);
2017 2114
 					*res_rv=0;
2018
-					ret=0;
2115
+					ret=r; /* equiv. to if (r<0) goto error */
2019 2116
 			}else{
2020 2117
 				/* RV_STR, RV_PVAR, RV_AVP a.s.o => return rv1 and the 
2021 2118
 				   cached resolved value in cache*/
... ...
@@ -2059,14 +2156,21 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
2059 2156
 			rval_cache_init(&c1);
2060 2157
 			r=rval_expr_eval_rvint(h, msg, &rv1, &i, rve->left.rve, &c1);
2061 2158
 			if (unlikely(r<0)){
2062
-				ERR("rval expression evaluation failed\n");
2159
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2160
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2161
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col
2162
+					);
2063 2163
 				rval_cache_clean(&c1);
2064 2164
 				goto error;
2065 2165
 			}
2066 2166
 			if (rv1==0){
2067 2167
 				if (unlikely((r=rval_expr_eval_int(h, msg, &j,
2068 2168
 														rve->right.rve))<0)){
2069
-						ERR("rval expression evaluation failed\n");
2169
+						ERR("rval expression evaluation failed (%d,%d-%d,%d)"
2170
+								"\n", rve->right.rve->fpos.s_line,
2171
+								rve->right.rve->fpos.s_col,
2172
+								rve->right.rve->fpos.e_line,
2173
+								rve->right.rve->fpos.e_col);
2070 2174
 						rval_cache_clean(&c1);
2071 2175
 						goto error;
2072 2176
 				}
... ...
@@ -2075,7 +2179,11 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
2075 2179
 			}else{
2076 2180
 				rv2=rval_expr_eval(h, msg, rve->right.rve);
2077 2181
 				if (unlikely(rv2==0)){
2078
-					ERR("rval expression evaluation failed\n");
2182
+					ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2183
+								rve->right.rve->fpos.s_line,
2184
+								rve->right.rve->fpos.s_col,
2185
+								rve->right.rve->fpos.e_line,
2186
+								rve->right.rve->fpos.e_col);
2079 2187
 					rval_cache_clean(&c1);
2080 2188
 					goto error;
2081 2189
 				}
... ...
@@ -2091,7 +2199,9 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
2091 2199
 			break;
2092 2200
 		case RVE_NONE_OP:
2093 2201
 		/*default:*/
2094
-			BUG("invalid rval expression operation %d\n", rve->op);
2202
+			BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
2203
+					rve->op, rve->fpos.s_line, rve->fpos.s_col,
2204
+					rve->fpos.e_line, rve->fpos.e_col);
2095 2205
 			goto error;
2096 2206
 	};
2097 2207
 	rval_destroy(rv1);
... ...
@@ -2168,29 +2278,39 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
2168 2278
 				}
2169 2279
 				return ret;
2170 2280
 			}else{
2171
-				ERR("rval expression evaluation failed\n");
2281
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2282
+						rve->fpos.s_line, rve->fpos.s_col,
2283
+						rve->fpos.e_line, rve->fpos.e_col);
2172 2284
 				goto error;
2173 2285
 			}
2174 2286
 			break;
2175 2287
 		case RVE_PLUS_OP:
2176 2288
 			rv1=rval_expr_eval(h, msg, rve->left.rve);
2177 2289
 			if (unlikely(rv1==0)){
2178
-				ERR("rval expression evaluation failed\n");
2290
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2291
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2292
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
2179 2293
 				goto error;
2180 2294
 			}
2181 2295
 			rval_cache_init(&c1);
2182 2296
 			type=rval_get_btype(h, msg, rv1, &c1);
2183 2297
 			switch(type){
2184 2298
 				case RV_INT:
2185
-					if (unlikely((r=rval_get_int(h, msg, &i, rv1, &c1))<0)){
2299
+					r=rval_get_int(h, msg, &i, rv1, &c1);
2300
+					rval_get_int_handle_ret(r, "rval expression left side "
2301
+												"conversion to int failed",
2302
+											rve);
2303
+					if (unlikely(r<0)){
2186 2304
 						rval_cache_clean(&c1);
2187
-						ERR("rval expression evaluation failed\n");
2188 2305
 						goto error;
2189 2306
 					}
2190 2307
 					if (unlikely((r=rval_expr_eval_int(h, msg, &j,
2191 2308
 														rve->right.rve))<0)){
2192 2309
 						rval_cache_clean(&c1);
2193
-						ERR("rval expression evaluation failed\n");
2310
+						ERR("rval expression evaluation failed (%d,%d-%d,%d):"
2311
+								" could not evaluate right side to int\n",
2312
+								rve->fpos.s_line, rve->fpos.s_col,
2313
+								rve->fpos.e_line, rve->fpos.e_col);
2194 2314
 						goto error;
2195 2315
 					}
2196 2316
 					int_intop2(&r, rve->op, i, j);
... ...
@@ -2212,26 +2332,38 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
2212 2332
 				case RV_NONE:
2213 2333
 					rv2=rval_expr_eval(h, msg, rve->right.rve);
2214 2334
 					if (unlikely(rv2==0)){
2215
-						ERR("rval expression evaluation failed\n");
2335
+						ERR("rval expression evaluation failed (%d,%d-%d,%d)"
2336
+								"\n", rve->right.rve->fpos.s_line,
2337
+								rve->right.rve->fpos.s_col,
2338
+								rve->right.rve->fpos.e_line,
2339
+								rve->right.rve->fpos.e_col);
2216 2340
 						rval_cache_clean(&c1);
2217 2341
 						goto error;
2218 2342
 					}
2219 2343
 					ret=rval_str_add2(h, msg, rv1, &c1, rv2, 0);
2220 2344
 					break;
2221 2345
 				default:
2222
-					BUG("rv unsupported basic type %d\n", type);
2346
+					BUG("rv unsupported basic type %d (%d,%d-%d,%d)\n", type,
2347
+							rve->fpos.s_line, rve->fpos.s_col,
2348
+							rve->fpos.e_line, rve->fpos.e_col);
2223 2349
 			}
2224 2350
 			rval_cache_clean(&c1);
2225 2351
 			break;
2226 2352
 		case RVE_CONCAT_OP:
2227 2353
 			rv1=rval_expr_eval(h, msg, rve->left.rve);
2228 2354
 			if (unlikely(rv1==0)){
2229
-				ERR("rval expression evaluation failed\n");
2355
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2356
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2357
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
2230 2358
 				goto error;
2231 2359
 			}
2232 2360
 			rv2=rval_expr_eval(h, msg, rve->right.rve);
2233 2361
 			if (unlikely(rv2==0)){
2234
-				ERR("rval expression evaluation failed\n");
2362
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2363
+						rve->right.rve->fpos.s_line,
2364
+						rve->right.rve->fpos.s_col,
2365
+						rve->right.rve->fpos.e_line,
2366
+						rve->right.rve->fpos.e_col);
2235 2367
 				goto error;
2236 2368
 			}
2237 2369
 			ret=rval_str_add2(h, msg, rv1, 0, rv2, 0);
... ...
@@ -2239,14 +2371,18 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
2239 2371
 		case RVE_STR_OP:
2240 2372
 			rv1=rval_expr_eval(h, msg, rve->left.rve);
2241 2373
 			if (unlikely(rv1==0)){
2242
-				ERR("rval expression evaluation failed\n");
2374
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2375
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2376
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
2243 2377
 				goto error;
2244 2378
 			}
2245 2379
 			ret=rval_convert(h, msg, RV_STR, rv1, 0);
2246 2380
 			break;
2247 2381
 		case RVE_NONE_OP:
2248 2382
 		/*default:*/
2249
-			BUG("invalid rval expression operation %d\n", rve->op);
2383
+			BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
2384
+					rve->op, rve->fpos.s_line, rve->fpos.s_col,
2385
+					rve->fpos.e_line, rve->fpos.e_col);
2250 2386
 			goto error;
2251 2387
 	};
2252 2388
 	rval_destroy(rv1);
... ...
@@ -2697,18 +2833,24 @@ static int rve_replace_with_ct_rv(struct rval_expr* rve, struct rvalue* rv)
2697 2833
 	flags=0;
2698 2834
 	if (rv->type==RV_INT){
2699 2835
 		if (rval_get_int(0, 0, &i, rv, 0)!=0){
2700
-			BUG("unexpected int evaluation failure\n");
2836
+			BUG("unexpected int evaluation failure (%d,%d-%d,%d)\n",
2837
+					rve->fpos.s_line, rve->fpos.s_col,
2838
+					rve->fpos.e_line, rve->fpos.e_col);
2701 2839
 			return -1;
2702 2840
 		}
2703 2841
 		v.l=i;
2704 2842
 	}else if(rv->type==RV_STR){
2705 2843
 		if (rval_get_str(0, 0, &v.s, rv, 0)<0){
2706
-			BUG("unexpected str evaluation failure\n");
2844
+			BUG("unexpected str evaluation failure(%d,%d-%d,%d)\n",
2845
+					rve->fpos.s_line, rve->fpos.s_col,
2846
+					rve->fpos.e_line, rve->fpos.e_col);
2707 2847
 			return -1;
2708 2848
 		}
2709 2849
 		flags|=RV_CNT_ALLOCED_F;
2710 2850
 	}else{
2711
-		BUG("unknown constant expression type %d\n", rv->type);
2851
+		BUG("unknown constant expression type %d (%d,%d-%d,%d)\n", rv->type,
2852
+				rve->fpos.s_line, rve->fpos.s_col,
2853
+				rve->fpos.e_line, rve->fpos.e_col);
2712 2854
 		return -1;
2713 2855
 	}
2714 2856
 	return rve_replace_with_val(rve, type, &v, flags);
... ...
@@ -2862,7 +3004,9 @@ static int rve_opt_01(struct rval_expr* rve, enum rval_type rve_type)
2862 3004
 	   referencing a ct_rve->left.rval if ct_rve is a rval, which
2863 3005
 	   would prevent rve_destroy(ct_rve) from working */
2864 3006
 	if ((rv=rval_expr_eval_new(0, 0, ct_rve))==0){
2865
-		ERR("optimization failure, bad expression\n");
3007
+		ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
3008
+				ct_rve->fpos.s_line, ct_rve->fpos.s_col,
3009
+				ct_rve->fpos.e_line, ct_rve->fpos.e_col);
2866 3010
 		goto error;
2867 3011
 	}
2868 3012
 	op=rve->op;
... ...
@@ -3213,7 +3357,9 @@ static int rve_optimize(struct rval_expr* rve)
3213 3357
 		return 0;
3214 3358
 	if (rve_is_constant(rve)){
3215 3359
 		if ((rv=rval_expr_eval_new(0, 0, rve))==0){
3216
-			ERR("optimization failure, bad expression\n");
3360
+			ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
3361
+					rve->fpos.s_line, rve->fpos.s_col,
3362
+					rve->fpos.e_line, rve->fpos.e_col);
3217 3363
 			goto error;
3218 3364
 		}
3219 3365
 		op=rve->op;
... ...
@@ -3256,7 +3402,11 @@ static int rve_optimize(struct rval_expr* rve)
3256 3402
 		/* $v - a => $v + (-a)  (easier to optimize)*/
3257 3403
 		if ((rve->op==RVE_MINUS_OP) && (rve_is_constant(rve->right.rve))){
3258 3404
 			if ((rv=rval_expr_eval_new(0, 0, rve->right.rve))==0){
3259
-				ERR("optimization failure, bad expression\n");
3405
+				ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
3406
+								rve->right.rve->fpos.s_line,
3407
+								rve->right.rve->fpos.s_col,
3408
+								rve->right.rve->fpos.e_line,
3409
+								rve->right.rve->fpos.e_col);
3260 3410
 				goto error;
3261 3411
 			}
3262 3412
 			if (rv->type==RV_INT){