2 * arithmetic code ripped out of ash shell for code sharing
4 * This code is derived from software contributed to Berkeley by
7 * Original BSD copyright notice is retained at the end of this file.
9 * Copyright (c) 1989, 1991, 1993, 1994
10 * The Regents of the University of California. All rights reserved.
12 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
13 * was re-ported from NetBSD and debianized.
15 * rewrite arith.y to micro stack based cryptic algorithm by
16 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
18 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
21 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
22 * used in busybox and size optimizations,
23 * rewrote arith (see notes to this), added locale support,
24 * rewrote dynamic variables.
26 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
28 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
30 * Permission is hereby granted, free of charge, to any person obtaining
31 * a copy of this software and associated documentation files (the
32 * "Software"), to deal in the Software without restriction, including
33 * without limitation the rights to use, copy, modify, merge, publish,
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
36 * the following conditions:
38 * The above copyright notice and this permission notice shall be
39 * included in all copies or substantial portions of the Software.
41 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
42 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
43 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
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,
46 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
47 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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
52 * than a comparable parser written in yacc. The supported operators are
53 * listed in #defines below. Parens, order of operations, and error handling
54 * are supported. This code is thread safe. The exact expression format should
55 * be that which POSIX specifies for shells.
57 * The code uses a simple two-stack algorithm. See
58 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
59 * for a detailed explanation of the infix-to-postfix algorithm on which
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
66 * Aug 24, 2001 Manuel Novoa III
68 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
70 * 1) In arith_apply():
71 * a) Cached values of *numptr and &(numptr[-1]).
72 * b) Removed redundant test for zero denominator.
75 * a) Eliminated redundant code for processing operator tokens by moving
76 * to a table-based implementation. Also folded handling of parens
78 * b) Combined all 3 loops which called arith_apply to reduce generated
79 * code size at the cost of speed.
81 * 3) The following expressions were treated as valid by the original code:
82 * 1() , 0! , 1 ( *3 ) .
83 * These bugs have been fixed by internally enclosing the expression in
84 * parens and then checking that all binary ops and right parens are
85 * preceded by a valid expression (NUM_TOKEN).
87 * Note: It may be desirable to replace Aaron's test for whitespace with
88 * ctype's isspace() if it is used by another busybox applet or if additional
89 * whitespace chars should be considered. Look below the "#include"s for a
93 * Aug 26, 2001 Manuel Novoa III
95 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
97 * Merge in Aaron's comments previously posted to the busybox list,
98 * modified slightly to take account of my changes to the code.
102 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
104 * - allow access to variable,
105 * use recursive value indirection: c="2*2"; a="c"; echo $((a+=2)) produce 6
106 * - implement assign syntax (VAR=expr, +=, *= etc)
107 * - implement exponentiation (** operator)
108 * - implement comma separated - expr, expr
109 * - implement ++expr --expr expr++ expr--
110 * - implement expr ? expr : expr (but second expr is always calculated)
111 * - allow hexadecimal and octal numbers
112 * - restore lost XOR operator
113 * - protect $((num num)) as true zero expr (Manuel's error)
114 * - always use special isspace(), see comment from bash ;-)
119 #define lookupvar (math_state->lookupvar)
120 #define setvar (math_state->setvar )
121 //#define endofname (math_state->endofname)
123 typedef unsigned char operator;
125 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
126 * precedence, and 3 high bits are an ID unique across operators of that
127 * precedence. The ID portion is so that multiple operators can have the
128 * same precedence, ensuring that the leftmost one is evaluated first.
131 #define tok_decl(prec,id) (((id)<<5) | (prec))
132 #define PREC(op) ((op) & 0x1F)
134 #define TOK_LPAREN tok_decl(0,0)
136 #define TOK_COMMA tok_decl(1,0)
138 /* All assignments are right associative and have the same precedence,
139 * but there are 11 of them, which doesn't fit into 3 bits for unique id.
140 * Abusing another precedence level:
142 #define TOK_ASSIGN tok_decl(2,0)
143 #define TOK_AND_ASSIGN tok_decl(2,1)
144 #define TOK_OR_ASSIGN tok_decl(2,2)
145 #define TOK_XOR_ASSIGN tok_decl(2,3)
146 #define TOK_PLUS_ASSIGN tok_decl(2,4)
147 #define TOK_MINUS_ASSIGN tok_decl(2,5)
148 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
149 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
151 #define TOK_MUL_ASSIGN tok_decl(3,0)
152 #define TOK_DIV_ASSIGN tok_decl(3,1)
153 #define TOK_REM_ASSIGN tok_decl(3,2)
155 #define fix_assignment_prec(prec) do { if (prec == 3) prec = 2; } while (0)
157 /* ternary conditional operator is right associative too */
158 #define TOK_CONDITIONAL tok_decl(4,0)
159 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
161 #define TOK_OR tok_decl(5,0)
163 #define TOK_AND tok_decl(6,0)
165 #define TOK_BOR tok_decl(7,0)
167 #define TOK_BXOR tok_decl(8,0)
169 #define TOK_BAND tok_decl(9,0)
171 #define TOK_EQ tok_decl(10,0)
172 #define TOK_NE tok_decl(10,1)
174 #define TOK_LT tok_decl(11,0)
175 #define TOK_GT tok_decl(11,1)
176 #define TOK_GE tok_decl(11,2)
177 #define TOK_LE tok_decl(11,3)
179 #define TOK_LSHIFT tok_decl(12,0)
180 #define TOK_RSHIFT tok_decl(12,1)
182 #define TOK_ADD tok_decl(13,0)
183 #define TOK_SUB tok_decl(13,1)
185 #define TOK_MUL tok_decl(14,0)
186 #define TOK_DIV tok_decl(14,1)
187 #define TOK_REM tok_decl(14,2)
189 /* exponent is right associative */
190 #define TOK_EXPONENT tok_decl(15,1)
192 /* unary operators */
194 #define TOK_BNOT tok_decl(UNARYPREC,0)
195 #define TOK_NOT tok_decl(UNARYPREC,1)
197 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
198 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
200 #define PREC_PRE (UNARYPREC+2)
202 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
203 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
205 #define PREC_POST (UNARYPREC+3)
207 #define TOK_POST_INC tok_decl(PREC_POST, 0)
208 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
210 #define SPEC_PREC (UNARYPREC+4)
212 #define TOK_NUM tok_decl(SPEC_PREC, 0)
213 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
216 tok_have_assign(operator op)
218 operator prec = PREC(op);
220 fix_assignment_prec(prec);
221 return (prec == PREC(TOK_ASSIGN) ||
222 prec == PREC_PRE || prec == PREC_POST);
226 is_right_associative(operator prec)
228 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT)
229 || prec == PREC(TOK_CONDITIONAL));
235 arith_t contidional_second_val;
236 char contidional_second_val_initialized;
237 char *var; /* if NULL then is regular number,
238 else is variable name */
241 typedef struct remembered_name {
242 struct remembered_name *next;
247 static arith_t FAST_FUNC
248 evaluate_string(arith_state_t *math_state, const char *expr);
251 arith_lookup_val(arith_state_t *math_state, v_n_t *t)
254 const char *p = lookupvar(t->var);
256 remembered_name *cur;
257 remembered_name cur_save;
259 /* did we already see this name?
260 * testcase: a=b; b=a; echo $((a))
262 for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) {
263 if (strcmp(cur->var, t->var) == 0) {
265 return "expression recursion loop detected";
269 /* push current var name */
270 cur = math_state->list_of_recursed_names;
271 cur_save.var = t->var;
273 math_state->list_of_recursed_names = &cur_save;
275 /* recursively evaluate p as expression */
276 t->val = evaluate_string(math_state, p);
278 /* pop current var name */
279 math_state->list_of_recursed_names = cur;
281 return math_state->errmsg;
283 /* treat undefined var as 0 */
289 /* "Applying" a token means performing it on the top elements on the integer
290 * stack. For an unary operator it will only change the top element, but a
291 * binary operator will pop two arguments and push the result */
292 static NOINLINE const char*
293 arith_apply(arith_state_t *math_state, operator op, v_n_t *numstack, v_n_t **numstackptr)
295 #define NUMPTR (*numstackptr)
298 arith_t numptr_val, rez;
301 /* There is no operator that can work without arguments */
302 if (NUMPTR == numstack)
304 numptr_m1 = NUMPTR - 1;
306 /* Check operand is var with noninteger value */
307 err = arith_lookup_val(math_state, numptr_m1);
311 rez = numptr_m1->val;
312 if (op == TOK_UMINUS)
314 else if (op == TOK_NOT)
316 else if (op == TOK_BNOT)
318 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
320 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
322 else if (op != TOK_UPLUS) {
323 /* Binary operators */
325 /* check and binary operators need two arguments */
326 if (numptr_m1 == numstack) goto err;
328 /* ... and they pop one */
331 if (op == TOK_CONDITIONAL) {
332 if (!numptr_m1->contidional_second_val_initialized) {
333 /* protect $((expr1 ? expr2)) without ": expr" */
336 rez = numptr_m1->contidional_second_val;
337 } else if (numptr_m1->contidional_second_val_initialized) {
338 /* protect $((expr1 : expr2)) without "expr ? " */
341 numptr_m1 = NUMPTR - 1;
342 if (op != TOK_ASSIGN) {
343 /* check operand is var with noninteger value for not '=' */
344 err = arith_lookup_val(math_state, numptr_m1);
348 if (op == TOK_CONDITIONAL) {
349 numptr_m1->contidional_second_val = rez;
351 rez = numptr_m1->val;
352 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
354 else if (op == TOK_OR)
355 rez = numptr_val || rez;
356 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
358 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
360 else if (op == TOK_AND)
361 rez = rez && numptr_val;
362 else if (op == TOK_EQ)
363 rez = (rez == numptr_val);
364 else if (op == TOK_NE)
365 rez = (rez != numptr_val);
366 else if (op == TOK_GE)
367 rez = (rez >= numptr_val);
368 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
370 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
372 else if (op == TOK_GT)
373 rez = (rez > numptr_val);
374 else if (op == TOK_LT)
375 rez = (rez < numptr_val);
376 else if (op == TOK_LE)
377 rez = (rez <= numptr_val);
378 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
380 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
382 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
384 else if (op == TOK_ASSIGN || op == TOK_COMMA)
386 else if (op == TOK_CONDITIONAL_SEP) {
387 if (numptr_m1 == numstack) {
388 /* protect $((expr : expr)) without "expr ? " */
391 numptr_m1->contidional_second_val_initialized = op;
392 numptr_m1->contidional_second_val = numptr_val;
393 } else if (op == TOK_CONDITIONAL) {
395 numptr_val : numptr_m1->contidional_second_val;
396 } else if (op == TOK_EXPONENT) {
399 return "exponent less than 0";
401 while (--numptr_val >= 0)
404 } else if (numptr_val == 0)
405 return "divide by zero";
406 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
408 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
411 if (tok_have_assign(op)) {
412 char buf[sizeof(arith_t)*3 + 2];
414 if (numptr_m1->var == NULL) {
418 /* save to shell variable */
419 sprintf(buf, arith_t_fmt, rez);
420 setvar(numptr_m1->var, buf);
421 /* after saving, make previous value for v++ or v-- */
422 if (op == TOK_POST_INC)
424 else if (op == TOK_POST_DEC)
427 numptr_m1->val = rez;
428 /* erase var name, it is just a number now */
429 numptr_m1->var = NULL;
432 return "arithmetic syntax error";
436 /* longest must be first */
437 static const char op_tokens[] ALIGN1 = {
438 '<','<','=',0, TOK_LSHIFT_ASSIGN,
439 '>','>','=',0, TOK_RSHIFT_ASSIGN,
440 '<','<', 0, TOK_LSHIFT,
441 '>','>', 0, TOK_RSHIFT,
448 '|','=', 0, TOK_OR_ASSIGN,
449 '&','=', 0, TOK_AND_ASSIGN,
450 '*','=', 0, TOK_MUL_ASSIGN,
451 '/','=', 0, TOK_DIV_ASSIGN,
452 '%','=', 0, TOK_REM_ASSIGN,
453 '+','=', 0, TOK_PLUS_ASSIGN,
454 '-','=', 0, TOK_MINUS_ASSIGN,
455 '-','-', 0, TOK_POST_DEC,
456 '^','=', 0, TOK_XOR_ASSIGN,
457 '+','+', 0, TOK_POST_INC,
458 '*','*', 0, TOK_EXPONENT,
474 '?', 0, TOK_CONDITIONAL,
475 ':', 0, TOK_CONDITIONAL_SEP,
480 #define ptr_to_rparen (&op_tokens[sizeof(op_tokens)-7])
482 const char* FAST_FUNC
483 endofname(const char *name)
488 if (!is_in_name(*name))
494 static arith_t FAST_FUNC
495 evaluate_string(arith_state_t *math_state, const char *expr)
499 const char *start_expr = expr = skip_whitespace(expr);
500 unsigned expr_len = strlen(expr) + 2;
501 /* Stack of integers */
502 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
503 * in any given correct or incorrect expression is left as an exercise to
505 v_n_t *const numstack = alloca((expr_len / 2) * sizeof(numstack[0]));
506 v_n_t *numstackptr = numstack;
507 /* Stack of operator tokens */
508 operator *const stack = alloca(expr_len * sizeof(stack[0]));
509 operator *stackptr = stack;
511 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
520 expr = skip_whitespace(expr);
522 if (arithval == '\0') {
523 if (expr == start_expr) {
524 /* Null expression. */
529 /* This is only reached after all tokens have been extracted from the
530 * input stream. If there are still tokens on the operator stack, they
531 * are to be applied in order. At the end, there should be a final
532 * result on the integer stack */
534 if (expr != ptr_to_rparen + 1) {
535 /* If we haven't done so already,
536 * append a closing right paren
537 * and let the loop process it */
538 expr = ptr_to_rparen;
541 /* At this point, we're done with the expression */
542 if (numstackptr != numstack + 1) {
543 /* ...but if there isn't, it's bad */
547 /* expression is $((var)) only, lookup now */
548 errmsg = arith_lookup_val(math_state, numstack);
556 size_t var_name_size = (p-expr) + 1; /* +1 for NUL */
557 numstackptr->var = alloca(var_name_size);
558 safe_strncpy(numstackptr->var, expr, var_name_size);
561 numstackptr->contidional_second_val_initialized = 0;
567 if (isdigit(arithval)) {
569 numstackptr->var = NULL;
571 numstackptr->val = strto_arith_t(expr, (char**) &expr, 0);
573 numstackptr->val = 0; /* bash compat */
577 /* Should be an operator */
580 const char *e = expr;
581 /* Compare expr to current op_tokens[] element */
582 while (*p && *e == *p)
584 if (*p == '\0') { /* match: operator is found */
588 /* Go to next element of op_tokens[] */
591 p += 2; /* skip NUL and TOK_foo bytes */
592 if (*p == '\0') /* no next element, operator not found */
595 op = p[1]; /* fetch TOK_foo value */
596 /* NB: expr now points past the operator */
598 /* post grammar: a++ reduce to num */
599 if (lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
602 /* Plus and minus are binary (not unary) _only_ if the last
603 * token was a number, or a right paren (which pretends to be
604 * a number, since it evaluates to one). Think about it.
606 if (lasttok != TOK_NUM) {
622 /* We don't want an unary operator to cause recursive descent on the
623 * stack, because there can be many in a row and it could cause an
624 * operator to be evaluated before its argument is pushed onto the
626 * But for binary operators, "apply" everything on the operator
627 * stack until we find an operator with a lesser priority than the
628 * one we have just extracted.
629 * Left paren is given the lowest priority so it will never be
630 * "applied" in this way.
631 * if associativity is right and priority eq, applied also skip
634 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
635 /* not left paren or unary */
636 if (lasttok != TOK_NUM) {
637 /* binary op must be preceded by a num */
640 while (stackptr != stack) {
641 operator prev_op = *--stackptr;
642 if (op == TOK_RPAREN) {
643 /* The algorithm employed here is simple: while we don't
644 * hit an open paren nor the bottom of the stack, pop
645 * tokens and apply them */
646 if (prev_op == TOK_LPAREN) {
647 /* Any operator directly after a
648 * close paren should consider itself binary */
653 operator prev_prec = PREC(prev_op);
654 fix_assignment_prec(prec);
655 fix_assignment_prec(prev_prec);
657 || (prev_prec == prec && is_right_associative(prec))
663 errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr);
667 if (op == TOK_RPAREN) {
672 /* Push this operator to the stack and remember it. */
673 *stackptr++ = lasttok = op;
679 errmsg = "arithmetic syntax error";
681 math_state->errmsg = errmsg;
682 return numstack->val;
686 arith(arith_state_t *math_state, const char *expr)
688 math_state->errmsg = NULL;
689 math_state->list_of_recursed_names = NULL;
690 return evaluate_string(math_state, expr);
694 * Copyright (c) 1989, 1991, 1993, 1994
695 * The Regents of the University of California. All rights reserved.
697 * This code is derived from software contributed to Berkeley by
700 * Redistribution and use in source and binary forms, with or without
701 * modification, are permitted provided that the following conditions
703 * 1. Redistributions of source code must retain the above copyright
704 * notice, this list of conditions and the following disclaimer.
705 * 2. Redistributions in binary form must reproduce the above copyright
706 * notice, this list of conditions and the following disclaimer in the
707 * documentation and/or other materials provided with the distribution.
708 * 3. Neither the name of the University nor the names of its contributors
709 * may be used to endorse or promote products derived from this software
710 * without specific prior written permission.
712 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
713 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
714 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
715 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
716 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
717 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
718 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
719 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
720 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
721 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF