summaryrefslogtreecommitdiff
path: root/shell/math.c
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 /shell/math.c
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>
Diffstat (limited to 'shell/math.c')
-rw-r--r--shell/math.c81
1 files changed, 40 insertions, 41 deletions
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}