Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/coreutils/expr.c

    r1765 r2725  
    1212 *  - 64 math support
    1313 *
    14  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     14 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1515 */
    1616
     
    2929#include "xregex.h"
    3030
    31 /* The kinds of value we can have.  */
    32 enum valtype {
    33     integer,
    34     string
    35 };
    36 typedef enum valtype TYPE;
    37 
    3831#if ENABLE_EXPR_MATH_SUPPORT_64
    3932typedef int64_t arith_t;
     
    5245/* TODO: use bb_strtol[l]? It's easier to check for errors... */
    5346
     47/* The kinds of value we can have.  */
     48enum {
     49    INTEGER,
     50    STRING
     51};
     52
    5453/* A value is.... */
    5554struct valinfo {
    56     TYPE type;          /* Which kind. */
    57     union {             /* The value itself. */
     55    smallint type;                  /* Which kind. */
     56    union {                         /* The value itself. */
    5857        arith_t i;
    5958        char *s;
     
    6564struct globals {
    6665    char **args;
    67 };
     66} FIX_ALIASING;
    6867#define G (*(struct globals*)&bb_common_bufsiz1)
    6968
     
    7877    VALUE *v;
    7978
    80     v = xmalloc(sizeof(VALUE));
    81     v->type = integer;
     79    v = xzalloc(sizeof(VALUE));
     80    if (INTEGER) /* otherwise xzaaloc did it already */
     81        v->type = INTEGER;
    8282    v->u.i = i;
    8383    return v;
     
    9090    VALUE *v;
    9191
    92     v = xmalloc(sizeof(VALUE));
    93     v->type = string;
     92    v = xzalloc(sizeof(VALUE));
     93    if (STRING) /* otherwise xzaaloc did it already */
     94        v->type = STRING;
    9495    v->u.s = xstrdup(s);
    9596    return v;
     
    9899/* Free VALUE V, including structure components.  */
    99100
    100 static void freev(VALUE * v)
    101 {
    102     if (v->type == string)
     101static void freev(VALUE *v)
     102{
     103    if (v->type == STRING)
    103104        free(v->u.s);
    104105    free(v);
     
    107108/* Return nonzero if V is a null-string or zero-number.  */
    108109
    109 static int null(VALUE * v)
    110 {
    111     if (v->type == integer)
     110static int null(VALUE *v)
     111{
     112    if (v->type == INTEGER)
    112113        return v->u.i == 0;
    113     /* string: */
     114    /* STRING: */
    114115    return v->u.s[0] == '\0' || LONE_CHAR(v->u.s, '0');
    115116}
    116117
    117 /* Coerce V to a string value (can't fail).  */
    118 
    119 static void tostring(VALUE * v)
    120 {
    121     if (v->type == integer) {
     118/* Coerce V to a STRING value (can't fail).  */
     119
     120static void tostring(VALUE *v)
     121{
     122    if (v->type == INTEGER) {
    122123        v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i);
    123         v->type = string;
    124     }
    125 }
    126 
    127 /* Coerce V to an integer value.  Return 1 on success, 0 on failure.  */
    128 
    129 static bool toarith(VALUE * v)
    130 {
    131     if (v->type == string) {
     124        v->type = STRING;
     125    }
     126}
     127
     128/* Coerce V to an INTEGER value.  Return 1 on success, 0 on failure.  */
     129
     130static bool toarith(VALUE *v)
     131{
     132    if (v->type == STRING) {
    132133        arith_t i;
    133134        char *e;
     
    140141        free(v->u.s);
    141142        v->u.i = i;
    142         v->type = integer;
     143        v->type = INTEGER;
    143144    }
    144145    return 1;
    145146}
    146147
    147 /* Return nonzero if the next token matches STR exactly.
     148/* Return str[0]+str[1] if the next token matches STR exactly.
    148149   STR must not be NULL.  */
    149150
    150 static bool nextarg(const char *str)
    151 {
    152     if (*G.args == NULL)
     151static int nextarg(const char *str)
     152{
     153    if (*G.args == NULL || strcmp(*G.args, str) != 0)
    153154        return 0;
    154     return strcmp(*G.args, str) == 0;
     155    return (unsigned char)str[0] + (unsigned char)str[1];
    155156}
    156157
    157158/* The comparison operator handling functions.  */
    158159
    159 static int cmp_common(VALUE * l, VALUE * r, int op)
    160 {
    161     int cmpval;
    162 
    163     if (l->type == string || r->type == string) {
     160static int cmp_common(VALUE *l, VALUE *r, int op)
     161{
     162    arith_t ll, rr;
     163
     164    ll = l->u.i;
     165    rr = r->u.i;
     166    if (l->type == STRING || r->type == STRING) {
    164167        tostring(l);
    165168        tostring(r);
    166         cmpval = strcmp(l->u.s, r->u.s);
    167     } else
    168         cmpval = l->u.i - r->u.i;
     169        ll = strcmp(l->u.s, r->u.s);
     170        rr = 0;
     171    }
     172    /* calculating ll - rr and checking the result is prone to overflows.
     173     * We'll do it differently: */
    169174    if (op == '<')
    170         return cmpval < 0;
    171     if (op == ('L' + 'E'))
    172         return cmpval <= 0;
    173     if (op == '=')
    174         return cmpval == 0;
    175     if (op == '!')
    176         return cmpval != 0;
     175        return ll < rr;
     176    if (op == ('<' + '='))
     177        return ll <= rr;
     178    if (op == '=' || (op == '=' + '='))
     179        return ll == rr;
     180    if (op == '!' + '=')
     181        return ll != rr;
    177182    if (op == '>')
    178         return cmpval > 0;
     183        return ll > rr;
    179184    /* >= */
    180     return cmpval >= 0;
     185    return ll >= rr;
    181186}
    182187
    183188/* The arithmetic operator handling functions.  */
    184189
    185 static arith_t arithmetic_common(VALUE * l, VALUE * r, int op)
     190static arith_t arithmetic_common(VALUE *l, VALUE *r, int op)
    186191{
    187192    arith_t li, ri;
     
    191196    li = l->u.i;
    192197    ri = r->u.i;
    193     if ((op == '/' || op == '%') && ri == 0)
    194         bb_error_msg_and_die("division by zero");
    195198    if (op == '+')
    196199        return li + ri;
    197     else if (op == '-')
     200    if (op == '-')
    198201        return li - ri;
    199     else if (op == '*')
     202    if (op == '*')
    200203        return li * ri;
    201     else if (op == '/')
     204    if (ri == 0)
     205        bb_error_msg_and_die("division by zero");
     206    if (op == '/')
    202207        return li / ri;
    203     else
    204         return li % ri;
     208    return li % ri;
    205209}
    206210
     
    209213   PV is the VALUE for the rhs (the pattern).  */
    210214
    211 static VALUE *docolon(VALUE * sv, VALUE * pv)
    212 {
     215static VALUE *docolon(VALUE *sv, VALUE *pv)
     216{
     217    enum { NMATCH = 2 };
    213218    VALUE *v;
    214219    regex_t re_buffer;
    215     const int NMATCH = 2;
    216220    regmatch_t re_regs[NMATCH];
    217221
     
    220224
    221225    if (pv->u.s[0] == '^') {
    222         bb_error_msg("\
    223 warning: unportable BRE: `%s': using `^' as the first character\n\
    224 of a basic regular expression is not portable; it is being ignored", pv->u.s);
     226        bb_error_msg(
     227"warning: '%s': using '^' as the first character\n"
     228"of a basic regular expression is not portable; it is ignored", pv->u.s);
    225229    }
    226230
    227231    memset(&re_buffer, 0, sizeof(re_buffer));
    228     memset(re_regs, 0, sizeof(*re_regs));
     232    memset(re_regs, 0, sizeof(re_regs));
    229233    xregcomp(&re_buffer, pv->u.s, 0);
    230234
    231235    /* expr uses an anchored pattern match, so check that there was a
    232236     * match and that the match starts at offset 0. */
    233     if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
    234         re_regs[0].rm_so == 0) {
     237    if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH
     238     && re_regs[0].rm_so == 0
     239    ) {
    235240        /* Were \(...\) used? */
    236         if (re_buffer.re_nsub > 0) {
     241        if (re_buffer.re_nsub > 0 && re_regs[1].rm_so >= 0) {
    237242            sv->u.s[re_regs[1].rm_eo] = '\0';
    238243            v = str_value(sv->u.s + re_regs[1].rm_so);
    239         } else
     244        } else {
    240245            v = int_value(re_regs[0].rm_eo);
     246        }
    241247    } else {
    242248        /* Match failed -- return the right kind of null.  */
     
    246252            v = int_value(0);
    247253    }
    248 //FIXME: sounds like here is a bit missing: regfree(&re_buffer);
     254    regfree(&re_buffer);
    249255    return v;
    250256}
     
    328334        else {
    329335            v = xmalloc(sizeof(VALUE));
    330             v->type = string;
     336            v->type = STRING;
    331337            v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
    332338        }
     
    336342    }
    337343    return v;
    338 
    339344}
    340345
     
    368373    l = eval5();
    369374    while (1) {
    370         if (nextarg("*"))
    371             op = '*';
    372         else if (nextarg("/"))
    373             op = '/';
    374         else if (nextarg("%"))
    375             op = '%';
    376         else
    377             return l;
     375        op = nextarg("*");
     376        if (!op) { op = nextarg("/");
     377         if (!op) { op = nextarg("%");
     378          if (!op) return l;
     379        }}
    378380        G.args++;
    379381        r = eval5();
     
    395397    l = eval4();
    396398    while (1) {
    397         if (nextarg("+"))
    398             op = '+';
    399         else if (nextarg("-"))
    400             op = '-';
    401         else
    402             return l;
     399        op = nextarg("+");
     400        if (!op) {
     401            op = nextarg("-");
     402            if (!op) return l;
     403        }
    403404        G.args++;
    404405        r = eval4();
     
    420421    l = eval3();
    421422    while (1) {
    422         if (nextarg("<"))
    423             op = '<';
    424         else if (nextarg("<="))
    425             op = 'L' + 'E';
    426         else if (nextarg("=") || nextarg("=="))
    427             op = '=';
    428         else if (nextarg("!="))
    429             op = '!';
    430         else if (nextarg(">="))
    431             op = 'G' + 'E';
    432         else if (nextarg(">"))
    433             op = '>';
    434         else
    435             return l;
     423        op = nextarg("<");
     424        if (!op) { op = nextarg("<=");
     425         if (!op) { op = nextarg("=");
     426          if (!op) { op = nextarg("==");
     427           if (!op) { op = nextarg("!=");
     428            if (!op) { op = nextarg(">=");
     429             if (!op) { op = nextarg(">");
     430              if (!op) return l;
     431        }}}}}}
    436432        G.args++;
    437433        r = eval3();
     
    484480}
    485481
    486 int expr_main(int argc, char **argv);
    487 int expr_main(int argc, char **argv)
     482int expr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     483int expr_main(int argc UNUSED_PARAM, char **argv)
    488484{
    489485    VALUE *v;
    490486
    491     if (argc == 1) {
     487    xfunc_error_retval = 2; /* coreutils compat */
     488    G.args = argv + 1;
     489    if (*G.args == NULL) {
    492490        bb_error_msg_and_die("too few arguments");
    493491    }
    494 
    495     G.args = argv + 1;
    496 
    497492    v = eval();
    498493    if (*G.args)
    499494        bb_error_msg_and_die("syntax error");
    500 
    501     if (v->type == integer)
     495    if (v->type == INTEGER)
    502496        printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
    503497    else
    504498        puts(v->u.s);
    505 
    506499    fflush_stdout_and_exit(null(v));
    507500}
Note: See TracChangeset for help on using the changeset viewer.