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 127
 				if (rve->left.rval.refcnt==1)
128 128
 					rval_destroy(&rve->left.rval);
129 129
 				else
130
-					BUG("rval expr rval with invalid refcnt: %d\n", 
131
-							rve->left.rval.refcnt);
130
+					BUG("rval expr rval with invalid refcnt: %d (%d,%d-%d,%d)"
131
+							"\n", rve->left.rval.refcnt,
132
+							rve->fpos.s_line, rve->fpos.s_col,
133
+							rve->fpos.e_line, rve->fpos.e_col);
132 134
 			}
133 135
 			if (rve->right.rval.refcnt){
134 136
 				if (rve->right.rval.refcnt==1)
135 137
 					rval_destroy(&rve->right.rval);
136 138
 				else
137
-					BUG("rval expr rval with invalid refcnt: %d\n", 
138
-							rve->right.rval.refcnt);
139
+					BUG("rval expr rval with invalid refcnt: %d (%d,%d-%d,%d)"
140
+							"\n", rve->right.rval.refcnt,
141
+							rve->fpos.s_line, rve->fpos.s_col,
142
+							rve->fpos.e_line, rve->fpos.e_col);
139 143
 			}
140 144
 		}else{
141 145
 			if (rve->left.rve)
... ...
@@ -802,7 +837,9 @@ int rve_check_type(enum rval_type* type, struct rval_expr* rve,
802 802
 			break;
803 803
 		case RVE_NONE_OP:
804 804
 		default:
805
-			BUG("unexpected rve op %d\n", rve->op);
805
+			BUG("unexpected rve op %d (%d,%d-%d,%d)\n", rve->op,
806
+					rve->fpos.s_line, rve->fpos.s_col,
807
+					rve->fpos.e_line, rve->fpos.e_col);
806 808
 			if (bad_rve) *bad_rve=rve;
807 809
 			if (bad_t) *bad_t=RV_NONE;
808 810
 			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 835
 	pv_value_t pval;
836 836
 	str tmp;
837 837
 	str* s;
838
-	int r;
838
+	int r, ret;
839 839
 	int destroy_pval;
840 840
 	
841 841
 	destroy_pval=0;
842 842
 	s=0;
843
+	ret=0;
843 844
 	switch(rv->type){
844 845
 		case RV_INT:
845 846
 			*i=rv->v.l;
... ...
@@ -931,15 +969,12 @@ int rval_get_int(struct run_act_ctx* h, struct sip_msg* msg,
931 931
 			BUG("rv type %d not handled\n", rv->type);
932 932
 			goto error;
933 933
 	}
934
-	return 0;
934
+	return ret;
935 935
 undef:
936 936
 eval_error: /* same as undefined */
937 937
 	/* handle undefined => result 0, return success */
938 938
 	*i=0;
939 939
 	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 940
 rv_str:
944 941
 	/* rv is of string type => try to convert it to int */
945 942
 	/* if "" => 0 (most likely case) */
... ...
@@ -947,17 +982,73 @@ rv_str:
947 947
 	else if (unlikely(str2sint(s, i)!=0)){
948 948
 		/* error converting to int => non numeric => 0 */
949 949
 		*i=0;
950
+#ifdef RV_STR2INT_VERBOSE_ERR
951
+		WARN("automatic string to int conversion for \"%.*s\" failed\n",
952
+				s->len, ZSW(s->s));
953
+		/* return an error code */
954
+#endif
955
+#ifdef RV_STR2INT_ERR
956
+		ret=-1;
957
+#endif
950 958
 	}
951 959
 	if (destroy_pval)
952 960
 		pv_value_destroy(&pval);
953
-	return 0;
961
+	return ret;
962
+error_cache:
963
+	BUG("invalid cached value:cache type %d, value type %d\n",
964
+			cache?cache->cache_type:0, cache?cache->val_type:0);
954 965
 error:
966
+	if (destroy_pval)
967
+		pv_value_destroy(&pval);
955 968
 	*i=0;
956 969
 	return -1;
957 970
 }
958 971
 
959 972
 
960 973
 
974
+/** log a message, appending rve position and a '\n'.*/
975
+#define RVE_LOG(lev, rve, txt) \
976
+	LOG((lev), txt " (%d,%d-%d,%d)\n", \
977
+			(rve)->fpos.s_line, rve->fpos.s_col, \
978
+			(rve)->fpos.e_line, rve->fpos.e_col )
979
+
980
+
981
+/** macro for checking and handling rval_get_int() retcode.
982
+ * check if the return code is an rval_get_int error and if so
983
+ * handle the error (e.g. print a log message, ignore the error by
984
+ * setting ret to 0 a.s.o.)
985
+ * @param ret - retcode as returned by rval_get_int() (might be changed)
986
+ * @param txt - warning message txt (no pointer allowed)
987
+ * @param rve - rval_expr, used to access the config. pos
988
+ */
989
+#if defined RVAL_GET_INT_ERR_WARN && defined RVAL_GET_INT_ERR_IGN
990
+#define rval_get_int_handle_ret(ret, txt, rve) \
991
+	do { \
992
+		if (unlikely((ret)<0)) { \
993
+			RVE_LOG(L_WARN, rve, txt); \
994
+			(ret)=0; \
995
+		} \
996
+	}while(0)
997
+#elif defined RVAL_GET_INT_ERR_WARN
998
+#define rval_get_int_handle_ret(ret, txt, rve) \
999
+	do { \
1000
+		if (unlikely((ret)<0)) \
1001
+			RVE_LOG(L_WARN, rve, txt); \
1002
+	}while(0)
1003
+#elif define RVAL_GET_INT_ERR_IGN \
1004
+	do { \
1005
+		if (unlikely((ret)<0)) \
1006
+				(ret)=0; \
1007
+	} while(0)
1008
+#else
1009
+#define rval_get_int_handle_ret(ret, txt, rve) /* do nothing */
1010
+#endif
1011
+
1012
+
1013
+
1014
+
1015
+
1016
+
961 1017
 /** get the string value of an rv in a tmp variable
962 1018
   * *s=(str)rv
963 1019
   * 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 1743
 	switch(rve->op){
1744 1744
 		case RVE_RVAL_OP:
1745 1745
 			ret=rval_get_int(h, msg, res,  &rve->left.rval, 0);
1746
+			rval_get_int_handle_ret(ret, "rval expression conversion to int"
1747
+										" failed", rve);
1746 1748
 			break;
1747 1749
 		case RVE_UMINUS_OP:
1748 1750
 		case RVE_BOOL_OP:
... ...
@@ -1870,7 +1963,7 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1870 1870
 #endif /* UNDEF_EQ_* */
1871 1871
 					rval_cache_clean(&c1);
1872 1872
 					rval_destroy(rv1);
1873
-				}else{ 
1873
+				}else{
1874 1874
 					/* left value == defined and != int => str
1875 1875
 					 * => lval == (str) val */
1876 1876
 					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 1893
 				ret=-1;
1894 1894
 				break;
1895 1895
 			}
1896
-			/* conver to int */
1896
+			/* convert to int */
1897 1897
 			ret=rval_get_int(h, msg, res, rv1, 0); /* convert to int */
1898
+			rval_get_int_handle_ret(ret, "rval expression conversion to int"
1899
+										" failed", rve);
1898 1900
 			rval_destroy(rv1);
1899 1901
 			break;
1900 1902
 		case RVE_STR_OP:
... ...
@@ -1909,6 +2004,8 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1909 1909
 			if (unlikely(rv1)){
1910 1910
 				/* expr evaluated to string => (int)(str)v == (int)v */
1911 1911
 				ret=rval_get_int(h, msg, res, rv1, &c1); /* convert to int */
1912
+				rval_get_int_handle_ret(ret, "rval expression conversion"
1913
+												" to int failed", rve);
1912 1914
 				rval_destroy(rv1);
1913 1915
 				rval_cache_clean(&c1);
1914 1916
 			} /* else (rv1==0)
... ...
@@ -1960,7 +2057,9 @@ int rval_expr_eval_int( struct run_act_ctx* h, struct sip_msg* msg,
1960 1960
 			break;
1961 1961
 		case RVE_NONE_OP:
1962 1962
 		/*default:*/
1963
-			BUG("invalid rval int expression operation %d\n", rve->op);
1963
+			BUG("invalid rval int expression operation %d (%d,%d-%d,%d)\n",
1964
+					rve->op, rve->fpos.s_line, rve->fpos.s_col,
1965
+					rve->fpos.e_line, rve->fpos.e_col);
1964 1966
 			ret=-1;
1965 1967
 	};
1966 1968
 	return ret;
... ...
@@ -2010,12 +2109,10 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
2010 2010
 			type=rval_get_btype(h, msg, rv1, cache);
2011 2011
 			if (type==RV_INT){
2012 2012
 					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
-					}
2013
+					rval_get_int_handle_ret(r, "rval expression conversion"
2014
+												" to int failed", rve);
2017 2015
 					*res_rv=0;
2018
-					ret=0;
2016
+					ret=r; /* equiv. to if (r<0) goto error */
2019 2017
 			}else{
2020 2018
 				/* RV_STR, RV_PVAR, RV_AVP a.s.o => return rv1 and the 
2021 2019
 				   cached resolved value in cache*/
... ...
@@ -2059,14 +2156,21 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
2059 2059
 			rval_cache_init(&c1);
2060 2060
 			r=rval_expr_eval_rvint(h, msg, &rv1, &i, rve->left.rve, &c1);
2061 2061
 			if (unlikely(r<0)){
2062
-				ERR("rval expression evaluation failed\n");
2062
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2063
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2064
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col
2065
+					);
2063 2066
 				rval_cache_clean(&c1);
2064 2067
 				goto error;
2065 2068
 			}
2066 2069
 			if (rv1==0){
2067 2070
 				if (unlikely((r=rval_expr_eval_int(h, msg, &j,
2068 2071
 														rve->right.rve))<0)){
2069
-						ERR("rval expression evaluation failed\n");
2072
+						ERR("rval expression evaluation failed (%d,%d-%d,%d)"
2073
+								"\n", rve->right.rve->fpos.s_line,
2074
+								rve->right.rve->fpos.s_col,
2075
+								rve->right.rve->fpos.e_line,
2076
+								rve->right.rve->fpos.e_col);
2070 2077
 						rval_cache_clean(&c1);
2071 2078
 						goto error;
2072 2079
 				}
... ...
@@ -2075,7 +2179,11 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
2075 2075
 			}else{
2076 2076
 				rv2=rval_expr_eval(h, msg, rve->right.rve);
2077 2077
 				if (unlikely(rv2==0)){
2078
-					ERR("rval expression evaluation failed\n");
2078
+					ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2079
+								rve->right.rve->fpos.s_line,
2080
+								rve->right.rve->fpos.s_col,
2081
+								rve->right.rve->fpos.e_line,
2082
+								rve->right.rve->fpos.e_col);
2079 2083
 					rval_cache_clean(&c1);
2080 2084
 					goto error;
2081 2085
 				}
... ...
@@ -2091,7 +2199,9 @@ int rval_expr_eval_rvint(			   struct run_act_ctx* h,
2091 2091
 			break;
2092 2092
 		case RVE_NONE_OP:
2093 2093
 		/*default:*/
2094
-			BUG("invalid rval expression operation %d\n", rve->op);
2094
+			BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
2095
+					rve->op, rve->fpos.s_line, rve->fpos.s_col,
2096
+					rve->fpos.e_line, rve->fpos.e_col);
2095 2097
 			goto error;
2096 2098
 	};
2097 2099
 	rval_destroy(rv1);
... ...
@@ -2168,29 +2278,39 @@ struct rvalue* rval_expr_eval(struct run_act_ctx* h, struct sip_msg* msg,
2168 2168
 				}
2169 2169
 				return ret;
2170 2170
 			}else{
2171
-				ERR("rval expression evaluation failed\n");
2171
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2172
+						rve->fpos.s_line, rve->fpos.s_col,
2173
+						rve->fpos.e_line, rve->fpos.e_col);
2172 2174
 				goto error;
2173 2175
 			}
2174 2176
 			break;
2175 2177
 		case RVE_PLUS_OP:
2176 2178
 			rv1=rval_expr_eval(h, msg, rve->left.rve);
2177 2179
 			if (unlikely(rv1==0)){
2178
-				ERR("rval expression evaluation failed\n");
2180
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2181
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2182
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
2179 2183
 				goto error;
2180 2184
 			}
2181 2185
 			rval_cache_init(&c1);
2182 2186
 			type=rval_get_btype(h, msg, rv1, &c1);
2183 2187
 			switch(type){
2184 2188
 				case RV_INT:
2185
-					if (unlikely((r=rval_get_int(h, msg, &i, rv1, &c1))<0)){
2189
+					r=rval_get_int(h, msg, &i, rv1, &c1);
2190
+					rval_get_int_handle_ret(r, "rval expression left side "
2191
+												"conversion to int failed",
2192
+											rve);
2193
+					if (unlikely(r<0)){
2186 2194
 						rval_cache_clean(&c1);
2187
-						ERR("rval expression evaluation failed\n");
2188 2195
 						goto error;
2189 2196
 					}
2190 2197
 					if (unlikely((r=rval_expr_eval_int(h, msg, &j,
2191 2198
 														rve->right.rve))<0)){
2192 2199
 						rval_cache_clean(&c1);
2193
-						ERR("rval expression evaluation failed\n");
2200
+						ERR("rval expression evaluation failed (%d,%d-%d,%d):"
2201
+								" could not evaluate right side to int\n",
2202
+								rve->fpos.s_line, rve->fpos.s_col,
2203
+								rve->fpos.e_line, rve->fpos.e_col);
2194 2204
 						goto error;
2195 2205
 					}
2196 2206
 					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 2212
 				case RV_NONE:
2213 2213
 					rv2=rval_expr_eval(h, msg, rve->right.rve);
2214 2214
 					if (unlikely(rv2==0)){
2215
-						ERR("rval expression evaluation failed\n");
2215
+						ERR("rval expression evaluation failed (%d,%d-%d,%d)"
2216
+								"\n", rve->right.rve->fpos.s_line,
2217
+								rve->right.rve->fpos.s_col,
2218
+								rve->right.rve->fpos.e_line,
2219
+								rve->right.rve->fpos.e_col);
2216 2220
 						rval_cache_clean(&c1);
2217 2221
 						goto error;
2218 2222
 					}
2219 2223
 					ret=rval_str_add2(h, msg, rv1, &c1, rv2, 0);
2220 2224
 					break;
2221 2225
 				default:
2222
-					BUG("rv unsupported basic type %d\n", type);
2226
+					BUG("rv unsupported basic type %d (%d,%d-%d,%d)\n", type,
2227
+							rve->fpos.s_line, rve->fpos.s_col,
2228
+							rve->fpos.e_line, rve->fpos.e_col);
2223 2229
 			}
2224 2230
 			rval_cache_clean(&c1);
2225 2231
 			break;
2226 2232
 		case RVE_CONCAT_OP:
2227 2233
 			rv1=rval_expr_eval(h, msg, rve->left.rve);
2228 2234
 			if (unlikely(rv1==0)){
2229
-				ERR("rval expression evaluation failed\n");
2235
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2236
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2237
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
2230 2238
 				goto error;
2231 2239
 			}
2232 2240
 			rv2=rval_expr_eval(h, msg, rve->right.rve);
2233 2241
 			if (unlikely(rv2==0)){
2234
-				ERR("rval expression evaluation failed\n");
2242
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2243
+						rve->right.rve->fpos.s_line,
2244
+						rve->right.rve->fpos.s_col,
2245
+						rve->right.rve->fpos.e_line,
2246
+						rve->right.rve->fpos.e_col);
2235 2247
 				goto error;
2236 2248
 			}
2237 2249
 			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 2239
 		case RVE_STR_OP:
2240 2240
 			rv1=rval_expr_eval(h, msg, rve->left.rve);
2241 2241
 			if (unlikely(rv1==0)){
2242
-				ERR("rval expression evaluation failed\n");
2242
+				ERR("rval expression evaluation failed (%d,%d-%d,%d)\n",
2243
+						rve->left.rve->fpos.s_line, rve->left.rve->fpos.s_col,
2244
+						rve->left.rve->fpos.e_line, rve->left.rve->fpos.e_col);
2243 2245
 				goto error;
2244 2246
 			}
2245 2247
 			ret=rval_convert(h, msg, RV_STR, rv1, 0);
2246 2248
 			break;
2247 2249
 		case RVE_NONE_OP:
2248 2250
 		/*default:*/
2249
-			BUG("invalid rval expression operation %d\n", rve->op);
2251
+			BUG("invalid rval expression operation %d (%d,%d-%d,%d)\n",
2252
+					rve->op, rve->fpos.s_line, rve->fpos.s_col,
2253
+					rve->fpos.e_line, rve->fpos.e_col);
2250 2254
 			goto error;
2251 2255
 	};
2252 2256
 	rval_destroy(rv1);
... ...
@@ -2697,18 +2833,24 @@ static int rve_replace_with_ct_rv(struct rval_expr* rve, struct rvalue* rv)
2697 2697
 	flags=0;
2698 2698
 	if (rv->type==RV_INT){
2699 2699
 		if (rval_get_int(0, 0, &i, rv, 0)!=0){
2700
-			BUG("unexpected int evaluation failure\n");
2700
+			BUG("unexpected int evaluation failure (%d,%d-%d,%d)\n",
2701
+					rve->fpos.s_line, rve->fpos.s_col,
2702
+					rve->fpos.e_line, rve->fpos.e_col);
2701 2703
 			return -1;
2702 2704
 		}
2703 2705
 		v.l=i;
2704 2706
 	}else if(rv->type==RV_STR){
2705 2707
 		if (rval_get_str(0, 0, &v.s, rv, 0)<0){
2706
-			BUG("unexpected str evaluation failure\n");
2708
+			BUG("unexpected str evaluation failure(%d,%d-%d,%d)\n",
2709
+					rve->fpos.s_line, rve->fpos.s_col,
2710
+					rve->fpos.e_line, rve->fpos.e_col);
2707 2711
 			return -1;
2708 2712
 		}
2709 2713
 		flags|=RV_CNT_ALLOCED_F;
2710 2714
 	}else{
2711
-		BUG("unknown constant expression type %d\n", rv->type);
2715
+		BUG("unknown constant expression type %d (%d,%d-%d,%d)\n", rv->type,
2716
+				rve->fpos.s_line, rve->fpos.s_col,
2717
+				rve->fpos.e_line, rve->fpos.e_col);
2712 2718
 		return -1;
2713 2719
 	}
2714 2720
 	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 2862
 	   referencing a ct_rve->left.rval if ct_rve is a rval, which
2863 2863
 	   would prevent rve_destroy(ct_rve) from working */
2864 2864
 	if ((rv=rval_expr_eval_new(0, 0, ct_rve))==0){
2865
-		ERR("optimization failure, bad expression\n");
2865
+		ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
2866
+				ct_rve->fpos.s_line, ct_rve->fpos.s_col,
2867
+				ct_rve->fpos.e_line, ct_rve->fpos.e_col);
2866 2868
 		goto error;
2867 2869
 	}
2868 2870
 	op=rve->op;
... ...
@@ -3213,7 +3357,9 @@ static int rve_optimize(struct rval_expr* rve)
3213 3213
 		return 0;
3214 3214
 	if (rve_is_constant(rve)){
3215 3215
 		if ((rv=rval_expr_eval_new(0, 0, rve))==0){
3216
-			ERR("optimization failure, bad expression\n");
3216
+			ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
3217
+					rve->fpos.s_line, rve->fpos.s_col,
3218
+					rve->fpos.e_line, rve->fpos.e_col);
3217 3219
 			goto error;
3218 3220
 		}
3219 3221
 		op=rve->op;
... ...
@@ -3256,7 +3402,11 @@ static int rve_optimize(struct rval_expr* rve)
3256 3256
 		/* $v - a => $v + (-a)  (easier to optimize)*/
3257 3257
 		if ((rve->op==RVE_MINUS_OP) && (rve_is_constant(rve->right.rve))){
3258 3258
 			if ((rv=rval_expr_eval_new(0, 0, rve->right.rve))==0){
3259
-				ERR("optimization failure, bad expression\n");
3259
+				ERR("optimization failure, bad expression (%d,%d-%d,%d)\n",
3260
+								rve->right.rve->fpos.s_line,
3261
+								rve->right.rve->fpos.s_col,
3262
+								rve->right.rve->fpos.e_line,
3263
+								rve->right.rve->fpos.e_col);
3260 3264
 				goto error;
3261 3265
 			}
3262 3266
 			if (rv->type==RV_INT){