X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=coreutils%2Fexpr.c;h=cbbd4cd0399649e12cb89889bebd6d34ab1b1d26;hb=37ba6bfb6d7ff7287ecda14bb4906fa6de1e78c9;hp=71bd22417bd215d5406608ccebde304519455957;hpb=ed3ef50c233ffb1b50ea0e7382a8e60b86491009;p=oweals%2Fbusybox.git diff --git a/coreutils/expr.c b/coreutils/expr.c index 71bd22417..cbbd4cd03 100644 --- a/coreutils/expr.c +++ b/coreutils/expr.c @@ -5,27 +5,28 @@ * based on GNU expr Mike Parker. * Copyright (C) 86, 1991-1997, 1999 Free Software Foundation, Inc. * - * Busybox modifications + * Busybox modifications * Copyright (c) 2000 Edward Betts . + * Aug 2003 Vladimir Oleynik - reduced 464 bytes. * - * this program is free software; you can redistribute it and/or modify - * it under the terms of the gnu general public license as published by - * the free software foundation; either version 2 of the license, or + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * this program is distributed in the hope that it will be useful, - * but without any warranty; without even the implied warranty of - * merchantability or fitness for a particular purpose. see the gnu - * general public license for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. * - * you should have received a copy of the gnu general public license - * along with this program; if not, write to the free software - * foundation, inc., 59 temple place, suite 330, boston, ma 02111-1307 usa + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ /* This program evaluates expressions. Each token (operator, operand, - * parenthesis) of the expression must be a seperate argument. The + * parenthesis) of the expression must be a separate argument. The * parser used is a reasonably general one, though any incarnation of * it is language-specific. It is especially nice for expressions. * @@ -33,12 +34,15 @@ * One function can handle multiple operators all of equal precedence, * provided they all associate ((x op x) op x). */ -#include "busybox.h" +/* no getopt needed */ + #include #include #include #include #include +#include +#include "busybox.h" /* The kinds of value we can have. */ @@ -76,19 +80,19 @@ int expr_main (int argc, char **argv) VALUE *v; if (argc == 1) { - error_msg_and_die("too few arguments\n"); + bb_error_msg_and_die("too few arguments"); } args = argv + 1; v = eval (); if (*args) - error_msg_and_die ("syntax error\n"); + bb_error_msg_and_die ("syntax error"); if (v->type == integer) printf ("%d\n", v->u.i); - else - printf ("%s\n", v->u.s); + else + puts (v->u.s); exit (null (v)); } @@ -113,7 +117,7 @@ static VALUE *str_value (char *s) v = xmalloc (sizeof(VALUE)); v->type = string; - v->u.s = strdup (s); + v->u.s = bb_xstrdup (s); return v; } @@ -133,10 +137,8 @@ static int null (VALUE *v) switch (v->type) { case integer: return v->u.i == 0; - case string: + default: /* string: */ return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0; - default: - abort (); } } @@ -144,12 +146,8 @@ static int null (VALUE *v) static void tostring (VALUE *v) { - char *temp; - if (v->type == integer) { - temp = xmalloc (4 * (sizeof (int) / sizeof (char))); - sprintf (temp, "%d", v->u.i); - v->u.s = temp; + bb_xasprintf (&(v->u.s), "%d", v->u.i); v->type = string; } } @@ -158,24 +156,20 @@ static void tostring (VALUE *v) static int toarith (VALUE *v) { - int i; + if(v->type == string) { + int i; + char *e; - switch (v->type) { - case integer: - return 1; - case string: - i = 0; - /* Don't interpret the empty string as an integer. */ - if (v->u.s == 0) - return 0; - i = atoi(v->u.s); - free (v->u.s); - v->u.i = i; - v->type = integer; - return 1; - default: - abort (); + /* Don't interpret the empty string as an integer. */ + /* Currently does not worry about overflow or int/long differences. */ + i = (int) strtol(v->u.s, &e, 10); + if ((v->u.s == e) || *e) + return 0; + free (v->u.s); + v->u.i = i; + v->type = integer; } + return 1; } /* Return nonzero if the next token matches STR exactly. @@ -191,56 +185,59 @@ nextarg (char *str) /* The comparison operator handling functions. */ -#define cmpf(name, rel) \ -static int name (l, r) VALUE *l; VALUE *r; \ -{ \ - if (l->type == string || r->type == string) { \ - tostring (l); \ - tostring (r); \ - return strcmp (l->u.s, r->u.s) rel 0; \ - } \ - else \ - return l->u.i rel r->u.i; \ -} - cmpf (less_than, <) - cmpf (less_equal, <=) - cmpf (equal, ==) - cmpf (not_equal, !=) - cmpf (greater_equal, >=) - cmpf (greater_than, >) +static int cmp_common (VALUE *l, VALUE *r, int op) +{ + int cmpval; -#undef cmpf + if (l->type == string || r->type == string) { + tostring (l); + tostring (r); + cmpval = strcmp (l->u.s, r->u.s); + } + else + cmpval = l->u.i - r->u.i; + switch(op) { + case '<': + return cmpval < 0; + case ('L'+'E'): + return cmpval <= 0; + case '=': + return cmpval == 0; + case '!': + return cmpval != 0; + case '>': + return cmpval > 0; + default: /* >= */ + return cmpval >= 0; + } +} /* The arithmetic operator handling functions. */ -#define arithf(name, op) \ -static \ -int name (l, r) VALUE *l; VALUE *r; \ -{ \ - if (!toarith (l) || !toarith (r)) \ - error_msg_and_die ("non-numeric argument\n"); \ - return l->u.i op r->u.i; \ -} - -#define arithdivf(name, op) \ -int name (l, r) VALUE *l; VALUE *r; \ -{ \ - if (!toarith (l) || !toarith (r)) \ - error_msg_and_die ( "non-numeric argument\n"); \ - if (r->u.i == 0) \ - error_msg_and_die ( "division by zero\n"); \ - return l->u.i op r->u.i; \ +static int arithmetic_common (VALUE *l, VALUE *r, int op) +{ + int li, ri; + + if (!toarith (l) || !toarith (r)) + bb_error_msg_and_die ("non-numeric argument"); + li = l->u.i; + ri = r->u.i; + if((op == '/' || op == '%') && ri == 0) + bb_error_msg_and_die ( "division by zero"); + switch(op) { + case '+': + return li + ri; + case '-': + return li - ri; + case '*': + return li * ri; + case '/': + return li / ri; + default: + return li % ri; + } } - arithf (plus, +) - arithf (minus, -) - arithf (multiply, *) - arithdivf (divide, /) - arithdivf (mod, %) - -#undef arithf -#undef arithdivf - /* Do the : operator. SV is the VALUE for the lhs (the string), PV is the VALUE for the rhs (the pattern). */ @@ -272,7 +269,7 @@ of a basic regular expression is not portable; it is being ignored", re_syntax_options = RE_SYNTAX_POSIX_BASIC; errmsg = re_compile_pattern (pv->u.s, len, &re_buffer); if (errmsg) { - error_msg_and_die("%s\n", errmsg); + bb_error_msg_and_die("%s", errmsg); } len = re_match (&re_buffer, sv->u.s, strlen (sv->u.s), 0, &re_regs); @@ -303,19 +300,19 @@ static VALUE *eval7 (void) VALUE *v; if (!*args) - error_msg_and_die ( "syntax error\n"); + bb_error_msg_and_die ( "syntax error"); if (nextarg ("(")) { args++; v = eval (); if (!nextarg (")")) - error_msg_and_die ( "syntax error\n"); + bb_error_msg_and_die ( "syntax error"); args++; return v; } if (nextarg (")")) - error_msg_and_die ( "syntax error\n"); + bb_error_msg_and_die ( "syntax error"); return str_value (*args++); } @@ -329,7 +326,7 @@ static VALUE *eval6 (void) if (nextarg ("quote")) { args++; if (!*args) - error_msg_and_die ( "syntax error\n"); + bb_error_msg_and_die ( "syntax error"); return str_value (*args++); } else if (nextarg ("length")) { @@ -375,9 +372,7 @@ static VALUE *eval6 (void) else { v = xmalloc (sizeof(VALUE)); v->type = string; - v->u.s = strncpy ((char *) xmalloc (i2->u.i + 1), - l->u.s + i1->u.i - 1, i2->u.i); - v->u.s[i2->u.i] = 0; + v->u.s = bb_xstrndup(l->u.s + i1->u.i - 1, i2->u.i); } freev (l); freev (i1); @@ -412,21 +407,21 @@ static VALUE *eval5 (void) static VALUE *eval4 (void) { VALUE *l, *r; - int (*fxn) (), val; + int op, val; l = eval5 (); while (1) { if (nextarg ("*")) - fxn = multiply; + op = '*'; else if (nextarg ("/")) - fxn = divide; + op = '/'; else if (nextarg ("%")) - fxn = mod; + op = '%'; else return l; args++; r = eval5 (); - val = (*fxn) (l, r); + val = arithmetic_common (l, r, op); freev (l); freev (r); l = int_value (val); @@ -438,19 +433,19 @@ static VALUE *eval4 (void) static VALUE *eval3 (void) { VALUE *l, *r; - int (*fxn) (), val; + int op, val; l = eval4 (); while (1) { if (nextarg ("+")) - fxn = plus; + op = '+'; else if (nextarg ("-")) - fxn = minus; + op = '-'; else return l; args++; r = eval4 (); - val = (*fxn) (l, r); + val = arithmetic_common (l, r, op); freev (l); freev (r); l = int_value (val); @@ -462,29 +457,29 @@ static VALUE *eval3 (void) static VALUE *eval2 (void) { VALUE *l, *r; - int (*fxn) (), val; + int op, val; l = eval3 (); while (1) { if (nextarg ("<")) - fxn = less_than; + op = '<'; else if (nextarg ("<=")) - fxn = less_equal; + op = 'L'+'E'; else if (nextarg ("=") || nextarg ("==")) - fxn = equal; + op = '='; else if (nextarg ("!=")) - fxn = not_equal; + op = '!'; else if (nextarg (">=")) - fxn = greater_equal; + op = 'G'+'E'; else if (nextarg (">")) - fxn = greater_than; + op = '>'; else return l; args++; r = eval3 (); toarith (l); toarith (r); - val = (*fxn) (l, r); + val = cmp_common (l, r, op); freev (l); freev (r); l = int_value (val);