aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-09-15 13:33:02 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-09-15 13:33:02 +0200
commit063847d6bd23e184c409f37645ba90fa4d039ada (patch)
tree63e360e3e0a2f46d187ef2e21487753a52697efa
parent197a6b3c14a8be7101903118516e0e16ec843eb5 (diff)
downloadbusybox-w32-063847d6bd23e184c409f37645ba90fa4d039ada.tar.gz
busybox-w32-063847d6bd23e184c409f37645ba90fa4d039ada.tar.bz2
busybox-w32-063847d6bd23e184c409f37645ba90fa4d039ada.zip
shell/math: return string error indicator, not integer
function old new delta expand_and_evaluate_arith 87 106 +19 expand_one_var 1563 1570 +7 arith 12 18 +6 evaluate_string 678 680 +2 arith_apply 1269 1271 +2 builtin_umask 133 132 -1 ash_arith 118 75 -43 expand_vars_to_list 1094 1038 -56 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/3 up/down: 36/-100) Total: -64 bytes Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r--shell/ash.c11
-rw-r--r--shell/ash_test/ash-arith/arith.right56
-rw-r--r--shell/hush.c40
-rw-r--r--shell/hush_test/hush-arith/arith.right54
-rw-r--r--shell/math.c81
-rw-r--r--shell/math.h2
6 files changed, 113 insertions, 131 deletions
diff --git a/shell/ash.c b/shell/ash.c
index c27ab7de2..ec887e088 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -5451,15 +5451,8 @@ ash_arith(const char *s)
5451 5451
5452 INT_OFF; 5452 INT_OFF;
5453 result = arith(&math_state, s); 5453 result = arith(&math_state, s);
5454 if (math_state.errcode < 0) { 5454 if (math_state.errmsg)
5455 if (math_state.errcode == -3) 5455 ash_msg_and_raise_error(math_state.errmsg);
5456 ash_msg_and_raise_error("exponent less than 0");
5457 if (math_state.errcode == -2)
5458 ash_msg_and_raise_error("divide by zero");
5459 if (math_state.errcode == -5)
5460 ash_msg_and_raise_error("expression recursion loop detected");
5461 raise_error_syntax(s);
5462 }
5463 INT_ON; 5456 INT_ON;
5464 5457
5465 return result; 5458 return result;
diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right
index 3ea7ce680..7257cc566 100644
--- a/shell/ash_test/ash-arith/arith.right
+++ b/shell/ash_test/ash-arith/arith.right
@@ -55,28 +55,28 @@ Format: 'expected actual'
5530 30 5530 30
5620 20 5620 20
5730 30 5730 30
58./arith.tests: line 117: syntax error: 1 ? 20 : x+=2 58./arith.tests: line 117: arithmetic syntax error
596 6 596 6
606,5,3 6,5,3 606,5,3 6,5,3
61263 263 61263 263
62255 255 62255 255
6340 40 6340 40
64./arith.tests: line 163: syntax error: 7 = 43 64./arith.tests: line 163: arithmetic syntax error
65./arith.tests: line 165: divide by zero 65./arith.tests: line 165: divide by zero
66./arith.tests: let: line 166: syntax error: jv += $iv 66./arith.tests: let: line 166: arithmetic syntax error
67./arith.tests: line 167: syntax error: jv += $iv 67./arith.tests: line 167: arithmetic syntax error
68./arith.tests: let: line 168: syntax error: rv = 7 + (43 * 6 68./arith.tests: let: line 168: arithmetic syntax error
69abc 69abc
70def 70def
71ghi 71ghi
72./arith.tests: line 191: syntax error: ( 4 + A ) + 4 72./arith.tests: line 191: arithmetic syntax error
7316 16 7316 16
74./arith.tests: line 196: syntax error: 4 ? : 3 + 5 74./arith.tests: line 196: arithmetic syntax error
75./arith.tests: line 197: syntax error: 1 ? 20 75./arith.tests: line 197: arithmetic syntax error
76./arith.tests: line 198: syntax error: 4 ? 20 : 76./arith.tests: line 198: arithmetic syntax error
779 9 779 9
78./arith.tests: line 205: syntax error: 0 && B=42 78./arith.tests: line 205: arithmetic syntax error
79./arith.tests: line 208: syntax error: 1 || B=88 79./arith.tests: line 208: arithmetic syntax error
809 9 809 9
819 9 819 9
829 9 829 9
@@ -97,18 +97,18 @@ ghi
973 3 973 3
984 4 984 4
994 4 994 4
100./arith.tests: line 257: syntax error: 7-- 100./arith.tests: line 257: arithmetic syntax error
101./arith.tests: line 259: syntax error: --x=7 101./arith.tests: line 259: arithmetic syntax error
102./arith.tests: line 260: syntax error: ++x=7 102./arith.tests: line 260: arithmetic syntax error
103./arith.tests: line 262: syntax error: x++=7 103./arith.tests: line 262: arithmetic syntax error
104./arith.tests: line 263: syntax error: x--=7 104./arith.tests: line 263: arithmetic syntax error
1054 4 1054 4
1067 7 1067 7
107-7 -7 107-7 -7
108./arith1.sub: line 2: syntax error: 4-- 108./arith1.sub: line 2: arithmetic syntax error
109./arith1.sub: line 3: syntax error: 4++ 109./arith1.sub: line 3: arithmetic syntax error
110./arith1.sub: line 4: syntax error: 4 -- 110./arith1.sub: line 4: arithmetic syntax error
111./arith1.sub: line 5: syntax error: 4 ++ 111./arith1.sub: line 5: arithmetic syntax error
1126 6 1126 6
1133 3 1133 3
1147 7 1147 7
@@ -119,19 +119,19 @@ ghi
1192 2 1192 2
120-2 -2 120-2 -2
1211 1 1211 1
122./arith1.sub: line 37: syntax error: +++7 122./arith1.sub: line 37: arithmetic syntax error
123./arith2.sub: line 2: syntax error: --7 123./arith2.sub: line 2: arithmetic syntax error
124./arith2.sub: line 3: syntax error: ++7 124./arith2.sub: line 3: arithmetic syntax error
125./arith2.sub: line 4: syntax error: -- 7 125./arith2.sub: line 4: arithmetic syntax error
126./arith2.sub: line 5: syntax error: ++ 7 126./arith2.sub: line 5: arithmetic syntax error
1275 5 1275 5
1281 1 1281 1
1294 4 1294 4
1300 0 1300 0
131./arith2.sub: line 42: syntax error: -- - 7 131./arith2.sub: line 42: arithmetic syntax error
132./arith2.sub: line 47: syntax error: ++ + 7 132./arith2.sub: line 47: arithmetic syntax error
1338 12 1338 12
134./arith.tests: line 290: syntax error: a b 134./arith.tests: line 290: arithmetic syntax error
13542 13542
13642 13642
13742 13742
diff --git a/shell/hush.c b/shell/hush.c
index 4ca5403de..ad30ac1ea 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -4461,7 +4461,7 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int
4461} 4461}
4462 4462
4463#if ENABLE_SH_MATH_SUPPORT 4463#if ENABLE_SH_MATH_SUPPORT
4464static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p) 4464static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
4465{ 4465{
4466 arith_state_t math_state; 4466 arith_state_t math_state;
4467 arith_t res; 4467 arith_t res;
@@ -4472,8 +4472,11 @@ static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p)
4472 //math_state.endofname = endofname; 4472 //math_state.endofname = endofname;
4473 exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); 4473 exp_str = encode_then_expand_string(arg, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
4474 res = arith(&math_state, exp_str ? exp_str : arg); 4474 res = arith(&math_state, exp_str ? exp_str : arg);
4475 *errcode_p = math_state.errcode;
4476 free(exp_str); 4475 free(exp_str);
4476 if (errmsg_p)
4477 *errmsg_p = math_state.errmsg;
4478 if (math_state.errmsg)
4479 die_if_script(math_state.errmsg);
4477 return res; 4480 return res;
4478} 4481}
4479#endif 4482#endif
@@ -4714,22 +4717,26 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
4714 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL> 4717 * var:N<SPECIAL_VAR_SYMBOL>M<SPECIAL_VAR_SYMBOL>
4715 */ 4718 */
4716 arith_t beg, len; 4719 arith_t beg, len;
4717 int errcode = 0; 4720 const char *errmsg;
4718 4721
4719 beg = expand_and_evaluate_arith(exp_word, &errcode); 4722 beg = expand_and_evaluate_arith(exp_word, &errmsg);
4723 if (errmsg)
4724 goto arith_err;
4720 debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg); 4725 debug_printf_varexp("beg:'%s'=%lld\n", exp_word, (long long)beg);
4721 *p++ = SPECIAL_VAR_SYMBOL; 4726 *p++ = SPECIAL_VAR_SYMBOL;
4722 exp_word = p; 4727 exp_word = p;
4723 p = strchr(p, SPECIAL_VAR_SYMBOL); 4728 p = strchr(p, SPECIAL_VAR_SYMBOL);
4724 *p = '\0'; 4729 *p = '\0';
4725 len = expand_and_evaluate_arith(exp_word, &errcode); 4730 len = expand_and_evaluate_arith(exp_word, &errmsg);
4731 if (errmsg)
4732 goto arith_err;
4726 debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len); 4733 debug_printf_varexp("len:'%s'=%lld\n", exp_word, (long long)len);
4727 4734 if (len >= 0) { /* bash compat: len < 0 is illegal */
4728 if (errcode >= 0 && len >= 0) { /* bash compat: len < 0 is illegal */
4729 if (beg < 0) /* bash compat */ 4735 if (beg < 0) /* bash compat */
4730 beg = 0; 4736 beg = 0;
4731 debug_printf_varexp("from val:'%s'\n", val); 4737 debug_printf_varexp("from val:'%s'\n", val);
4732 if (len == 0 || !val || beg >= strlen(val)) { 4738 if (len == 0 || !val || beg >= strlen(val)) {
4739 arith_err:
4733 val = NULL; 4740 val = NULL;
4734 } else { 4741 } else {
4735 /* Paranoia. What if user entered 9999999999999 4742 /* Paranoia. What if user entered 9999999999999
@@ -4926,28 +4933,11 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
4926#if ENABLE_SH_MATH_SUPPORT 4933#if ENABLE_SH_MATH_SUPPORT
4927 case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */ 4934 case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */
4928 arith_t res; 4935 arith_t res;
4929 int errcode;
4930 4936
4931 arg++; /* skip '+' */ 4937 arg++; /* skip '+' */
4932 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */ 4938 *p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
4933 debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch); 4939 debug_printf_subst("ARITH '%s' first_ch %x\n", arg, first_ch);
4934 res = expand_and_evaluate_arith(arg, &errcode); 4940 res = expand_and_evaluate_arith(arg, NULL);
4935
4936 if (errcode < 0) {
4937 const char *msg = "error in arithmetic";
4938 switch (errcode) {
4939 case -3:
4940 msg = "exponent less than 0";
4941 break;
4942 case -2:
4943 msg = "divide by 0";
4944 break;
4945 case -5:
4946 msg = "expression recursion loop detected";
4947 break;
4948 }
4949 die_if_script(msg);
4950 }
4951 debug_printf_subst("ARITH RES '"arith_t_fmt"'\n", res); 4941 debug_printf_subst("ARITH RES '"arith_t_fmt"'\n", res);
4952 sprintf(arith_buf, arith_t_fmt, res); 4942 sprintf(arith_buf, arith_t_fmt, res);
4953 val = arith_buf; 4943 val = arith_buf;
diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right
index 718c26ad0..fd4ea8e01 100644
--- a/shell/hush_test/hush-arith/arith.right
+++ b/shell/hush_test/hush-arith/arith.right
@@ -61,7 +61,7 @@ check that the unevaluated part of the ternary operator does not do evaluation o
6120 20 6120 20
6230 30 6230 30
63check precedence of assignment vs. conditional operator 63check precedence of assignment vs. conditional operator
64hush: error in arithmetic 64hush: arithmetic syntax error
65check precedence of assignment vs. conditional operator 65check precedence of assignment vs. conditional operator
66associativity of assignment-operator operator 66associativity of assignment-operator operator
676 6 676 6
@@ -70,22 +70,22 @@ octal, hex
70263 263 70263 263
71255 255 71255 255
7240 40 7240 40
73hush: error in arithmetic 73hush: arithmetic syntax error
74hush: divide by 0 74hush: divide by zero
75hush: can't execute 'let': No such file or directory 75hush: can't execute 'let': No such file or directory
76hush: error in arithmetic 76hush: arithmetic syntax error
77hush: can't execute 'let': No such file or directory 77hush: can't execute 'let': No such file or directory
78abc 78abc
79def 79def
80ghi 80ghi
81hush: error in arithmetic 81hush: arithmetic syntax error
8216 16 8216 16
83hush: error in arithmetic 83hush: arithmetic syntax error
84hush: error in arithmetic 84hush: arithmetic syntax error
85hush: error in arithmetic 85hush: arithmetic syntax error
869 9 869 9
87hush: error in arithmetic 87hush: arithmetic syntax error
88hush: error in arithmetic 88hush: arithmetic syntax error
899 9 899 9
909 9 909 9
919 9 919 9
@@ -106,18 +106,18 @@ hush: error in arithmetic
1063 3 1063 3
1074 4 1074 4
1084 4 1084 4
109hush: error in arithmetic 109hush: arithmetic syntax error
110hush: error in arithmetic 110hush: arithmetic syntax error
111hush: error in arithmetic 111hush: arithmetic syntax error
112hush: error in arithmetic 112hush: arithmetic syntax error
113hush: error in arithmetic 113hush: arithmetic syntax error
1144 4 1144 4
1157 7 1157 7
116-7 -7 116-7 -7
117hush: error in arithmetic 117hush: arithmetic syntax error
118hush: error in arithmetic 118hush: arithmetic syntax error
119hush: error in arithmetic 119hush: arithmetic syntax error
120hush: error in arithmetic 120hush: arithmetic syntax error
1216 6 1216 6
1223 3 1223 3
1237 7 1237 7
@@ -128,19 +128,19 @@ hush: error in arithmetic
1282 2 1282 2
129-2 -2 129-2 -2
1301 1 1301 1
131hush: error in arithmetic 131hush: arithmetic syntax error
132hush: error in arithmetic 132hush: arithmetic syntax error
133hush: error in arithmetic 133hush: arithmetic syntax error
134hush: error in arithmetic 134hush: arithmetic syntax error
135hush: error in arithmetic 135hush: arithmetic syntax error
1365 5 1365 5
1371 1 1371 1
1384 4 1384 4
1390 0 1390 0
140hush: error in arithmetic 140hush: arithmetic syntax error
141hush: error in arithmetic 141hush: arithmetic syntax error
1428 12 1428 12
143hush: error in arithmetic 143hush: arithmetic syntax error
14442 14442
14542 14542
14642 14642
diff --git a/shell/math.c b/shell/math.c
index 839715776..871c06c3e 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -26,26 +26,26 @@
26 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 26 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
27 */ 27 */
28/* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com> 28/* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
29 29 *
30 Permission is hereby granted, free of charge, to any person obtaining 30 * Permission is hereby granted, free of charge, to any person obtaining
31 a copy of this software and associated documentation files (the 31 * a copy of this software and associated documentation files (the
32 "Software"), to deal in the Software without restriction, including 32 * "Software"), to deal in the Software without restriction, including
33 without limitation the rights to use, copy, modify, merge, publish, 33 * without limitation the rights to use, copy, modify, merge, publish,
34 distribute, sublicense, and/or sell copies of the Software, and to 34 * distribute, sublicense, and/or sell copies of the Software, and to
35 permit persons to whom the Software is furnished to do so, subject to 35 * permit persons to whom the Software is furnished to do so, subject to
36 the following conditions: 36 * the following conditions:
37 37 *
38 The above copyright notice and this permission notice shall be 38 * The above copyright notice and this permission notice shall be
39 included in all copies or substantial portions of the Software. 39 * included in all copies or substantial portions of the Software.
40 40 *
41 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
42 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 42 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
43 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 43 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
44 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 44 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
45 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 45 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
46 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 46 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
47 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 47 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48*/ 48 */
49 49
50/* This is my infix parser/evaluator. It is optimized for size, intended 50/* This is my infix parser/evaluator. It is optimized for size, intended
51 * as a replacement for yacc-based parsers. However, it may well be faster 51 * as a replacement for yacc-based parsers. However, it may well be faster
@@ -60,9 +60,6 @@
60 * this is based (this code differs in that it applies operators immediately 60 * this is based (this code differs in that it applies operators immediately
61 * to the stack instead of adding them to a queue to end up with an 61 * to the stack instead of adding them to a queue to end up with an
62 * expression). 62 * expression).
63 *
64 * To use the routine, call it with an expression string and error return
65 * pointer
66 */ 63 */
67 64
68/* 65/*
@@ -250,7 +247,7 @@ typedef struct remembered_name {
250static arith_t FAST_FUNC 247static arith_t FAST_FUNC
251evaluate_string(arith_state_t *math_state, const char *expr); 248evaluate_string(arith_state_t *math_state, const char *expr);
252 249
253static int 250static const char*
254arith_lookup_val(arith_state_t *math_state, v_n_t *t) 251arith_lookup_val(arith_state_t *math_state, v_n_t *t)
255{ 252{
256 if (t->var) { 253 if (t->var) {
@@ -264,8 +261,8 @@ arith_lookup_val(arith_state_t *math_state, v_n_t *t)
264 */ 261 */
265 for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) { 262 for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) {
266 if (strcmp(cur->var, t->var) == 0) { 263 if (strcmp(cur->var, t->var) == 0) {
267 /* Yes. Expression recursion loop detected */ 264 /* Yes */
268 return -5; 265 return "expression recursion loop detected";
269 } 266 }
270 } 267 }
271 268
@@ -281,7 +278,7 @@ arith_lookup_val(arith_state_t *math_state, v_n_t *t)
281 /* pop current var name */ 278 /* pop current var name */
282 math_state->list_of_recursed_names = cur; 279 math_state->list_of_recursed_names = cur;
283 280
284 return math_state->errcode; 281 return math_state->errmsg;
285 } 282 }
286 /* treat undefined var as 0 */ 283 /* treat undefined var as 0 */
287 t->val = 0; 284 t->val = 0;
@@ -292,14 +289,14 @@ arith_lookup_val(arith_state_t *math_state, v_n_t *t)
292/* "Applying" a token means performing it on the top elements on the integer 289/* "Applying" a token means performing it on the top elements on the integer
293 * stack. For an unary operator it will only change the top element, but a 290 * stack. For an unary operator it will only change the top element, but a
294 * binary operator will pop two arguments and push the result */ 291 * binary operator will pop two arguments and push the result */
295static NOINLINE int 292static NOINLINE const char*
296arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **numstackptr) 293arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **numstackptr)
297{ 294{
298#define NUMPTR (*numstackptr) 295#define NUMPTR (*numstackptr)
299 296
300 v_n_t *numptr_m1; 297 v_n_t *numptr_m1;
301 arith_t numptr_val, rez; 298 arith_t numptr_val, rez;
302 int err; 299 const char *err;
303 300
304 /* There is no operator that can work without arguments */ 301 /* There is no operator that can work without arguments */
305 if (NUMPTR == numstack) 302 if (NUMPTR == numstack)
@@ -399,13 +396,13 @@ arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **num
399 } else if (op == TOK_EXPONENT) { 396 } else if (op == TOK_EXPONENT) {
400 arith_t c; 397 arith_t c;
401 if (numptr_val < 0) 398 if (numptr_val < 0)
402 return -3; /* exponent less than 0 */ 399 return "exponent less than 0";
403 c = 1; 400 c = 1;
404 while (--numptr_val >= 0) 401 while (--numptr_val >= 0)
405 c *= rez; 402 c *= rez;
406 rez = c; 403 rez = c;
407 } else if (numptr_val==0) /* zero divisor check */ 404 } else if (numptr_val == 0)
408 return -2; 405 return "divide by zero";
409 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN) 406 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
410 rez /= numptr_val; 407 rez /= numptr_val;
411 else if (op == TOK_REM || op == TOK_REM_ASSIGN) 408 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
@@ -430,9 +427,9 @@ arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **num
430 numptr_m1->val = rez; 427 numptr_m1->val = rez;
431 /* erase var name, it is just a number now */ 428 /* erase var name, it is just a number now */
432 numptr_m1->var = NULL; 429 numptr_m1->var = NULL;
433 return 0; 430 return NULL;
434 err: 431 err:
435 return -1; 432 return "arithmetic syntax error";
436#undef NUMPTR 433#undef NUMPTR
437} 434}
438 435
@@ -498,7 +495,7 @@ static arith_t FAST_FUNC
498evaluate_string(arith_state_t *math_state, const char *expr) 495evaluate_string(arith_state_t *math_state, const char *expr)
499{ 496{
500 operator lasttok; 497 operator lasttok;
501 int errcode; 498 const char *errmsg;
502 const char *start_expr = expr = skip_whitespace(expr); 499 const char *start_expr = expr = skip_whitespace(expr);
503 unsigned expr_len = strlen(expr) + 2; 500 unsigned expr_len = strlen(expr) + 2;
504 /* Stack of integers */ 501 /* Stack of integers */
@@ -512,7 +509,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
512 operator *stackptr = stack; 509 operator *stackptr = stack;
513 510
514 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */ 511 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
515 errcode = 0; 512 errmsg = NULL;
516 513
517 while (1) { 514 while (1) {
518 const char *p; 515 const char *p;
@@ -548,7 +545,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
548 } 545 }
549 if (numstack->var) { 546 if (numstack->var) {
550 /* expression is $((var)) only, lookup now */ 547 /* expression is $((var)) only, lookup now */
551 errcode = arith_lookup_val(math_state, numstack); 548 errmsg = arith_lookup_val(math_state, numstack);
552 } 549 }
553 goto ret; 550 goto ret;
554 } 551 }
@@ -663,8 +660,8 @@ evaluate_string(arith_state_t *math_state, const char *expr)
663 break; 660 break;
664 } 661 }
665 } 662 }
666 errcode = arith_apply(math_state, prev_op, numstack, &numstackptr); 663 errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr);
667 if (errcode) 664 if (errmsg)
668 goto ret; 665 goto ret;
669 } 666 }
670 if (op == TOK_RPAREN) { 667 if (op == TOK_RPAREN) {
@@ -678,15 +675,17 @@ evaluate_string(arith_state_t *math_state, const char *expr)
678 } /* while (1) */ 675 } /* while (1) */
679 676
680 err: 677 err:
681 numstack->val = errcode = -1; 678 numstack->val = -1;
679 errmsg = "arithmetic syntax error";
682 ret: 680 ret:
683 math_state->errcode = errcode; 681 math_state->errmsg = errmsg;
684 return numstack->val; 682 return numstack->val;
685} 683}
686 684
687arith_t FAST_FUNC 685arith_t FAST_FUNC
688arith(arith_state_t *math_state, const char *expr) 686arith(arith_state_t *math_state, const char *expr)
689{ 687{
688 math_state->errmsg = NULL;
690 math_state->list_of_recursed_names = NULL; 689 math_state->list_of_recursed_names = NULL;
691 return evaluate_string(math_state, expr); 690 return evaluate_string(math_state, expr);
692} 691}
diff --git a/shell/math.h b/shell/math.h
index e34b65d5d..2dcab130d 100644
--- a/shell/math.h
+++ b/shell/math.h
@@ -95,7 +95,7 @@ typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *v
95//typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name); 95//typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name);
96 96
97typedef struct arith_state_t { 97typedef struct arith_state_t {
98 int errcode; 98 const char *errmsg;
99 arith_var_lookup_t lookupvar; 99 arith_var_lookup_t lookupvar;
100 arith_var_set_t setvar; 100 arith_var_set_t setvar;
101// arith_var_endofname_t endofname; 101// arith_var_endofname_t endofname;