diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2010-09-15 13:33:02 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-09-15 13:33:02 +0200 |
commit | 063847d6bd23e184c409f37645ba90fa4d039ada (patch) | |
tree | 63e360e3e0a2f46d187ef2e21487753a52697efa | |
parent | 197a6b3c14a8be7101903118516e0e16ec843eb5 (diff) | |
download | busybox-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.c | 11 | ||||
-rw-r--r-- | shell/ash_test/ash-arith/arith.right | 56 | ||||
-rw-r--r-- | shell/hush.c | 40 | ||||
-rw-r--r-- | shell/hush_test/hush-arith/arith.right | 54 | ||||
-rw-r--r-- | shell/math.c | 81 | ||||
-rw-r--r-- | shell/math.h | 2 |
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' | |||
55 | 30 30 | 55 | 30 30 |
56 | 20 20 | 56 | 20 20 |
57 | 30 30 | 57 | 30 30 |
58 | ./arith.tests: line 117: syntax error: 1 ? 20 : x+=2 | 58 | ./arith.tests: line 117: arithmetic syntax error |
59 | 6 6 | 59 | 6 6 |
60 | 6,5,3 6,5,3 | 60 | 6,5,3 6,5,3 |
61 | 263 263 | 61 | 263 263 |
62 | 255 255 | 62 | 255 255 |
63 | 40 40 | 63 | 40 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 |
69 | abc | 69 | abc |
70 | def | 70 | def |
71 | ghi | 71 | ghi |
72 | ./arith.tests: line 191: syntax error: ( 4 + A ) + 4 | 72 | ./arith.tests: line 191: arithmetic syntax error |
73 | 16 16 | 73 | 16 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 |
77 | 9 9 | 77 | 9 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 |
80 | 9 9 | 80 | 9 9 |
81 | 9 9 | 81 | 9 9 |
82 | 9 9 | 82 | 9 9 |
@@ -97,18 +97,18 @@ ghi | |||
97 | 3 3 | 97 | 3 3 |
98 | 4 4 | 98 | 4 4 |
99 | 4 4 | 99 | 4 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 |
105 | 4 4 | 105 | 4 4 |
106 | 7 7 | 106 | 7 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 |
112 | 6 6 | 112 | 6 6 |
113 | 3 3 | 113 | 3 3 |
114 | 7 7 | 114 | 7 7 |
@@ -119,19 +119,19 @@ ghi | |||
119 | 2 2 | 119 | 2 2 |
120 | -2 -2 | 120 | -2 -2 |
121 | 1 1 | 121 | 1 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 |
127 | 5 5 | 127 | 5 5 |
128 | 1 1 | 128 | 1 1 |
129 | 4 4 | 129 | 4 4 |
130 | 0 0 | 130 | 0 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 |
133 | 8 12 | 133 | 8 12 |
134 | ./arith.tests: line 290: syntax error: a b | 134 | ./arith.tests: line 290: arithmetic syntax error |
135 | 42 | 135 | 42 |
136 | 42 | 136 | 42 |
137 | 42 | 137 | 42 |
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 |
4464 | static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p) | 4464 | static 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 | |||
61 | 20 20 | 61 | 20 20 |
62 | 30 30 | 62 | 30 30 |
63 | check precedence of assignment vs. conditional operator | 63 | check precedence of assignment vs. conditional operator |
64 | hush: error in arithmetic | 64 | hush: arithmetic syntax error |
65 | check precedence of assignment vs. conditional operator | 65 | check precedence of assignment vs. conditional operator |
66 | associativity of assignment-operator operator | 66 | associativity of assignment-operator operator |
67 | 6 6 | 67 | 6 6 |
@@ -70,22 +70,22 @@ octal, hex | |||
70 | 263 263 | 70 | 263 263 |
71 | 255 255 | 71 | 255 255 |
72 | 40 40 | 72 | 40 40 |
73 | hush: error in arithmetic | 73 | hush: arithmetic syntax error |
74 | hush: divide by 0 | 74 | hush: divide by zero |
75 | hush: can't execute 'let': No such file or directory | 75 | hush: can't execute 'let': No such file or directory |
76 | hush: error in arithmetic | 76 | hush: arithmetic syntax error |
77 | hush: can't execute 'let': No such file or directory | 77 | hush: can't execute 'let': No such file or directory |
78 | abc | 78 | abc |
79 | def | 79 | def |
80 | ghi | 80 | ghi |
81 | hush: error in arithmetic | 81 | hush: arithmetic syntax error |
82 | 16 16 | 82 | 16 16 |
83 | hush: error in arithmetic | 83 | hush: arithmetic syntax error |
84 | hush: error in arithmetic | 84 | hush: arithmetic syntax error |
85 | hush: error in arithmetic | 85 | hush: arithmetic syntax error |
86 | 9 9 | 86 | 9 9 |
87 | hush: error in arithmetic | 87 | hush: arithmetic syntax error |
88 | hush: error in arithmetic | 88 | hush: arithmetic syntax error |
89 | 9 9 | 89 | 9 9 |
90 | 9 9 | 90 | 9 9 |
91 | 9 9 | 91 | 9 9 |
@@ -106,18 +106,18 @@ hush: error in arithmetic | |||
106 | 3 3 | 106 | 3 3 |
107 | 4 4 | 107 | 4 4 |
108 | 4 4 | 108 | 4 4 |
109 | hush: error in arithmetic | 109 | hush: arithmetic syntax error |
110 | hush: error in arithmetic | 110 | hush: arithmetic syntax error |
111 | hush: error in arithmetic | 111 | hush: arithmetic syntax error |
112 | hush: error in arithmetic | 112 | hush: arithmetic syntax error |
113 | hush: error in arithmetic | 113 | hush: arithmetic syntax error |
114 | 4 4 | 114 | 4 4 |
115 | 7 7 | 115 | 7 7 |
116 | -7 -7 | 116 | -7 -7 |
117 | hush: error in arithmetic | 117 | hush: arithmetic syntax error |
118 | hush: error in arithmetic | 118 | hush: arithmetic syntax error |
119 | hush: error in arithmetic | 119 | hush: arithmetic syntax error |
120 | hush: error in arithmetic | 120 | hush: arithmetic syntax error |
121 | 6 6 | 121 | 6 6 |
122 | 3 3 | 122 | 3 3 |
123 | 7 7 | 123 | 7 7 |
@@ -128,19 +128,19 @@ hush: error in arithmetic | |||
128 | 2 2 | 128 | 2 2 |
129 | -2 -2 | 129 | -2 -2 |
130 | 1 1 | 130 | 1 1 |
131 | hush: error in arithmetic | 131 | hush: arithmetic syntax error |
132 | hush: error in arithmetic | 132 | hush: arithmetic syntax error |
133 | hush: error in arithmetic | 133 | hush: arithmetic syntax error |
134 | hush: error in arithmetic | 134 | hush: arithmetic syntax error |
135 | hush: error in arithmetic | 135 | hush: arithmetic syntax error |
136 | 5 5 | 136 | 5 5 |
137 | 1 1 | 137 | 1 1 |
138 | 4 4 | 138 | 4 4 |
139 | 0 0 | 139 | 0 0 |
140 | hush: error in arithmetic | 140 | hush: arithmetic syntax error |
141 | hush: error in arithmetic | 141 | hush: arithmetic syntax error |
142 | 8 12 | 142 | 8 12 |
143 | hush: error in arithmetic | 143 | hush: arithmetic syntax error |
144 | 42 | 144 | 42 |
145 | 42 | 145 | 42 |
146 | 42 | 146 | 42 |
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 { | |||
250 | static arith_t FAST_FUNC | 247 | static arith_t FAST_FUNC |
251 | evaluate_string(arith_state_t *math_state, const char *expr); | 248 | evaluate_string(arith_state_t *math_state, const char *expr); |
252 | 249 | ||
253 | static int | 250 | static const char* |
254 | arith_lookup_val(arith_state_t *math_state, v_n_t *t) | 251 | arith_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 */ |
295 | static NOINLINE int | 292 | static NOINLINE const char* |
296 | arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **numstackptr) | 293 | arith_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 | |||
498 | evaluate_string(arith_state_t *math_state, const char *expr) | 495 | evaluate_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 | ||
687 | arith_t FAST_FUNC | 685 | arith_t FAST_FUNC |
688 | arith(arith_state_t *math_state, const char *expr) | 686 | arith(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 | ||
97 | typedef struct arith_state_t { | 97 | typedef 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; |