diff options
Diffstat (limited to 'libbb/arith.c')
-rw-r--r-- | libbb/arith.c | 141 |
1 files changed, 57 insertions, 84 deletions
diff --git a/libbb/arith.c b/libbb/arith.c index d79501c..3e10712 100644 --- a/libbb/arith.c +++ b/libbb/arith.c @@ -140,8 +140,7 @@ typedef char operator; #define TOK_REM tok_decl(10,2) /* For now all unary operators have the same precedence, and that's used to - * identify them as unary operators - */ + * identify them as unary operators */ #define UNARYPREC 14 #define TOK_BNOT tok_decl(UNARYPREC,0) #define TOK_NOT tok_decl(UNARYPREC,1) @@ -157,82 +156,68 @@ typedef char operator; /* "applying" a token means performing it on the top elements on the integer * stack. For a unary operator it will only change the top element, but a - * binary operator will pop two arguments and push a result - */ + * binary operator will pop two arguments and push a result */ static short arith_apply(operator op, long *numstack, long **numstackptr) { long numptr_val; long *NUMPTR_M1; - /* There is no operator that can work without arguments */ - if (NUMPTR == numstack) { - goto err; - } - + if (NUMPTR == numstack) goto err; /* There is no operator that can work + without arguments */ NUMPTR_M1 = NUMPTR - 1; - if (op == TOK_UMINUS) { + if (op == TOK_UMINUS) *NUMPTR_M1 *= -1; - } else if (op == TOK_NOT) { + else if (op == TOK_NOT) *NUMPTR_M1 = !(*NUMPTR_M1); - } else if (op == TOK_BNOT) { + else if (op == TOK_BNOT) *NUMPTR_M1 = ~(*NUMPTR_M1); - } else if (op != TOK_UPLUS) { + else if (op != TOK_UPLUS) { /* Binary operators */ - - /* ... and binary operators need two arguments */ - if (NUMPTR_M1 == numstack) { - goto err; - } - /* ... and they pop one */ - numptr_val = *--NUMPTR; - + if (NUMPTR_M1 == numstack) goto err; /* ... and binary operators need two + arguments */ + numptr_val = *--NUMPTR; /* ... and they pop one */ NUMPTR_M1 = NUMPTR - 1; - - if (op == TOK_BOR) { + if (op == TOK_BOR) *NUMPTR_M1 |= numptr_val; - } else if (op == TOK_OR) { + else if (op == TOK_OR) *NUMPTR_M1 = numptr_val || *NUMPTR_M1; - } else if (op == TOK_BAND) { + else if (op == TOK_BAND) *NUMPTR_M1 &= numptr_val; - } else if (op == TOK_AND) { + else if (op == TOK_AND) *NUMPTR_M1 = *NUMPTR_M1 && numptr_val; - } else if (op == TOK_EQ) { + else if (op == TOK_EQ) *NUMPTR_M1 = (*NUMPTR_M1 == numptr_val); - } else if (op == TOK_NE) { + else if (op == TOK_NE) *NUMPTR_M1 = (*NUMPTR_M1 != numptr_val); - } else if (op == TOK_GE) { + else if (op == TOK_GE) *NUMPTR_M1 = (*NUMPTR_M1 >= numptr_val); - } else if (op == TOK_RSHIFT) { + else if (op == TOK_RSHIFT) *NUMPTR_M1 >>= numptr_val; - } else if (op == TOK_LSHIFT) { + else if (op == TOK_LSHIFT) *NUMPTR_M1 <<= numptr_val; - } else if (op == TOK_GT) { + else if (op == TOK_GT) *NUMPTR_M1 = (*NUMPTR_M1 > numptr_val); - } else if (op == TOK_LT) { + else if (op == TOK_LT) *NUMPTR_M1 = (*NUMPTR_M1 < numptr_val); - } else if (op == TOK_LE) { + else if (op == TOK_LE) *NUMPTR_M1 = (*NUMPTR_M1 <= numptr_val); - } else if (op == TOK_MUL) { + else if (op == TOK_MUL) *NUMPTR_M1 *= numptr_val; - } else if (op == TOK_ADD) { + else if (op == TOK_ADD) *NUMPTR_M1 += numptr_val; - } else if (op == TOK_SUB) { + else if (op == TOK_SUB) *NUMPTR_M1 -= numptr_val; - } - /* zero divisor check */ - else if (numptr_val == 0) { + else if(numptr_val==0) /* zero divisor check */ return -2; - } else if (op == TOK_DIV) { + else if (op == TOK_DIV) *NUMPTR_M1 /= numptr_val; - } else if (op == TOK_REM) { + else if (op == TOK_REM) *NUMPTR_M1 %= numptr_val; - } /* WARNING!!! WARNING!!! WARNING!!! */ /* Any new operators should be added BEFORE the zero divisor check! */ } return 0; - err: - return (-1); +err: return(-1); } static const char endexpression[] = ")"; @@ -242,7 +227,7 @@ static const char op_char[] = "!<>=|&*/%~()+-"; static const char op_token[] = { /* paired with equal */ TOK_NE, TOK_LE, TOK_GE, - /* paired with self -- note: ! is special-cased below */ + /* paired with self -- note: ! is special-cased below*/ TOK_ERROR, TOK_LSHIFT, TOK_RSHIFT, TOK_EQ, TOK_OR, TOK_AND, /* singles */ TOK_NOT, TOK_LT, TOK_GT, TOK_ERROR, TOK_BOR, TOK_BAND, @@ -253,33 +238,34 @@ static const char op_token[] = { #define NUM_PAIR_EQUAL 3 #define NUM_PAIR_SAME 6 -extern long arith(const char *expr, int *errcode) +extern long arith (const char *expr, int *errcode) { register char arithval; /* Current character under analysis */ operator lasttok, op; unsigned char prec; + const char *p = endexpression; - size_t datasizes = strlen(expr); + + size_t datasizes = strlen(expr) + 2; /* Stack of integers */ /* The proof that there can be no more than strlen(startbuf)/2+1 integers * in any given correct or incorrect expression is left as an excersize to * the reader. */ - long *numstack = alloca(((datasizes + 1) / 2) * sizeof(long)); - long *numstackptr = numstack; - + long *numstack = alloca(((datasizes)/2)*sizeof(long)), + *numstackptr = numstack; /* Stack of operator tokens */ - operator * stack = alloca((datasizes + 1) * sizeof(operator)); - operator * stackptr = stack; + operator *stack = alloca((datasizes) * sizeof(operator)), + *stackptr = stack; - /* start off with a left paren */ - *stackptr++ = lasttok = TOK_LPAREN; + *numstack = 0; + *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */ loop: if ((arithval = *expr) == 0) { - /* Null expression. */ - if (p == endexpression) { - return (*errcode = 0); + if (p == endexpression) { /* Null expression. */ + *errcode = 0; + return *numstack; } /* This is only reached after all tokens have been extracted from the @@ -292,7 +278,7 @@ extern long arith(const char *expr, int *errcode) goto loop; /* and let the loop process it. */ } /* At this point, we're done with the expression. */ - if (numstackptr != numstack + 1) { /* ... but if there isn't, it's bad */ + if (numstackptr != numstack+1) {/* ... but if there isn't, it's bad */ err: return (*errcode = -1); /* NOTREACHED */ @@ -300,12 +286,10 @@ extern long arith(const char *expr, int *errcode) return *numstack; } else { /* Continue processing the expression. */ - /* Skip whitespace */ if (isspace(arithval)) { - goto prologue; + goto prologue; /* Skip whitespace */ } - /* isdigit ? */ - if ((unsigned) arithval - '0' <= 9) { + if ((unsigned)arithval-'0' <= 9) /* isdigit */ { *numstackptr++ = strtol(expr, (char **) &expr, 10); lasttok = TOK_NUM; goto loop; @@ -315,21 +299,20 @@ extern long arith(const char *expr, int *errcode) goto err; } #else - for (p = op_char; *p != arithval; p++) { + for ( p=op_char ; *p != arithval ; p++ ) { if (!*p) { goto err; } } #endif - p = op_token + (int) (p - op_char); + p = op_token + (int)(p - op_char); ++expr; if ((p >= op_token + NUM_PAIR_EQUAL) || (*expr != '=')) { p += NUM_PAIR_EQUAL; if ((p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL) || (*expr != arithval) || (arithval == '!')) { --expr; - /* single = */ - if (arithval == '=') { + if (arithval == '=') { /* single = */ goto err; } p += NUM_PAIR_SAME; @@ -338,11 +321,9 @@ extern long arith(const char *expr, int *errcode) * a number, since it evaluates to one). Think about it. * It makes sense. */ if ((lasttok != TOK_NUM) - && (p >= - (op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL + - sizeof(op_char) - 2))) { - /* Unary plus or minus */ - p += 2; + && (p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL + + sizeof(op_char) - 2)) { + p += 2; /* Unary plus or minus */ } } } @@ -358,11 +339,8 @@ extern long arith(const char *expr, int *errcode) /* Left paren is given the lowest priority so it will never be * "applied" in this way */ prec = PREC(op); - - /* not left paren or unary */ - if ((prec > 0) && (prec != UNARYPREC)) { - /* binary op must be preceded by a num */ - if (lasttok != TOK_NUM) { + if ((prec > 0) && (prec != UNARYPREC)) { /* not left paren or unary */ + if (lasttok != TOK_NUM) { /* binary op must be preceded by a num */ goto err; } while (stackptr != stack) { @@ -372,10 +350,7 @@ extern long arith(const char *expr, int *errcode) * tokens and apply them */ if (stackptr[-1] == TOK_LPAREN) { --stackptr; - - /* Any operator directly after a */ - lasttok = TOK_NUM; - + lasttok = TOK_NUM; /* Any operator directly after a */ /* close paren should consider itself binary */ goto prologue; } @@ -383,9 +358,7 @@ extern long arith(const char *expr, int *errcode) break; } *errcode = ARITH_APPLY(*--stackptr); - if (*errcode) { - return *errcode; - } + if(*errcode) return *errcode; } if (op == TOK_RPAREN) { goto err; |