Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

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

    r821 r1765  
    1212 *  - 64 math support
    1313 *
    14  * This program is free software; you can redistribute it and/or modify
    15  * it under the terms of the GNU General Public License as published by
    16  * the Free Software Foundation; either version 2 of the License, or
    17  * (at your option) any later version.
    18  *
    19  * This program is distributed in the hope that it will be useful,
    20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    22  * General Public License for more details.
    23  *
    24  * You should have received a copy of the GNU General Public License
    25  * along with this program; if not, write to the Free Software
    26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    27  *
     14 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    2815 */
    2916
     
    3926/* no getopt needed */
    4027
    41 #include <stdio.h>
    42 #include <string.h>
    43 #include <stdlib.h>
    44 #include <regex.h>
    45 #include <sys/types.h>
    46 #include <errno.h>
    47 #include "busybox.h"
    48 
     28#include "libbb.h"
     29#include "xregex.h"
    4930
    5031/* The kinds of value we can have.  */
     
    5738#if ENABLE_EXPR_MATH_SUPPORT_64
    5839typedef int64_t arith_t;
     40
    5941#define PF_REZ      "ll"
    6042#define PF_REZ_TYPE (long long)
     
    6244#else
    6345typedef long arith_t;
     46
    6447#define PF_REZ      "l"
    6548#define PF_REZ_TYPE (long)
     
    6750#endif
    6851
     52/* TODO: use bb_strtol[l]? It's easier to check for errors... */
     53
    6954/* A value is.... */
    7055struct valinfo {
    71     TYPE type;                      /* Which kind. */
    72     union {                         /* The value itself. */
     56    TYPE type;          /* Which kind. */
     57    union {             /* The value itself. */
    7358        arith_t i;
    7459        char *s;
     
    7863
    7964/* The arguments given to the program, minus the program name.  */
    80 static char **args;
    81 
    82 static VALUE *docolon (VALUE *sv, VALUE *pv);
    83 static VALUE *eval (void);
    84 static VALUE *int_value (arith_t i);
    85 static VALUE *str_value (char *s);
    86 static int nextarg (char *str);
    87 static int null (VALUE *v);
    88 static int toarith (VALUE *v);
    89 static void freev (VALUE *v);
    90 static void tostring (VALUE *v);
    91 
    92 int expr_main (int argc, char **argv)
     65struct globals {
     66    char **args;
     67};
     68#define G (*(struct globals*)&bb_common_bufsiz1)
     69
     70/* forward declarations */
     71static VALUE *eval(void);
     72
     73
     74/* Return a VALUE for I.  */
     75
     76static VALUE *int_value(arith_t i)
    9377{
    9478    VALUE *v;
    9579
    96     if (argc == 1) {
    97         bb_error_msg_and_die("too few arguments");
    98     }
    99 
    100     args = argv + 1;
    101 
    102     v = eval ();
    103     if (*args)
    104         bb_error_msg_and_die ("syntax error");
    105 
    106     if (v->type == integer)
    107         printf ("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
    108     else
    109         puts (v->u.s);
    110 
    111     exit (null (v));
    112 }
    113 
    114 /* Return a VALUE for I.  */
    115 
    116 static VALUE *int_value (arith_t i)
    117 {
    118     VALUE *v;
    119 
    120     v = xmalloc (sizeof(VALUE));
     80    v = xmalloc(sizeof(VALUE));
    12181    v->type = integer;
    12282    v->u.i = i;
     
    12686/* Return a VALUE for S.  */
    12787
    128 static VALUE *str_value (char *s)
     88static VALUE *str_value(const char *s)
    12989{
    13090    VALUE *v;
    13191
    132     v = xmalloc (sizeof(VALUE));
     92    v = xmalloc(sizeof(VALUE));
    13393    v->type = string;
    134     v->u.s = bb_xstrdup (s);
     94    v->u.s = xstrdup(s);
    13595    return v;
    13696}
     
    13898/* Free VALUE V, including structure components.  */
    13999
    140 static void freev (VALUE *v)
     100static void freev(VALUE * v)
    141101{
    142102    if (v->type == string)
    143         free (v->u.s);
    144     free (v);
     103        free(v->u.s);
     104    free(v);
    145105}
    146106
    147107/* Return nonzero if V is a null-string or zero-number.  */
    148108
    149 static int null (VALUE *v)
    150 {
    151     switch (v->type) {
    152         case integer:
    153             return v->u.i == 0;
    154         default: /* string: */
    155             return v->u.s[0] == '\0' || strcmp (v->u.s, "0") == 0;
    156     }
     109static int null(VALUE * v)
     110{
     111    if (v->type == integer)
     112        return v->u.i == 0;
     113    /* string: */
     114    return v->u.s[0] == '\0' || LONE_CHAR(v->u.s, '0');
    157115}
    158116
    159117/* Coerce V to a string value (can't fail).  */
    160118
    161 static void tostring (VALUE *v)
     119static void tostring(VALUE * v)
    162120{
    163121    if (v->type == integer) {
    164         v->u.s = bb_xasprintf ("%" PF_REZ "d", PF_REZ_TYPE v->u.i);
     122        v->u.s = xasprintf("%" PF_REZ "d", PF_REZ_TYPE v->u.i);
    165123        v->type = string;
    166124    }
     
    169127/* Coerce V to an integer value.  Return 1 on success, 0 on failure.  */
    170128
    171 static int toarith (VALUE *v)
    172 {
    173     if(v->type == string) {
     129static bool toarith(VALUE * v)
     130{
     131    if (v->type == string) {
    174132        arith_t i;
    175133        char *e;
     
    180138        if ((v->u.s == e) || *e)
    181139            return 0;
    182         free (v->u.s);
     140        free(v->u.s);
    183141        v->u.i = i;
    184142        v->type = integer;
     
    190148   STR must not be NULL.  */
    191149
    192 static int
    193 nextarg (char *str)
    194 {
    195     if (*args == NULL)
     150static bool nextarg(const char *str)
     151{
     152    if (*G.args == NULL)
    196153        return 0;
    197     return strcmp (*args, str) == 0;
     154    return strcmp(*G.args, str) == 0;
    198155}
    199156
    200157/* The comparison operator handling functions.  */
    201158
    202 static int cmp_common (VALUE *l, VALUE *r, int op)
     159static int cmp_common(VALUE * l, VALUE * r, int op)
    203160{
    204161    int cmpval;
    205162
    206163    if (l->type == string || r->type == string) {
    207         tostring (l);
    208         tostring (r);
    209         cmpval = strcmp (l->u.s, r->u.s);
    210     }
     164        tostring(l);
     165        tostring(r);
     166        cmpval = strcmp(l->u.s, r->u.s);
     167    } else
     168        cmpval = l->u.i - r->u.i;
     169    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;
     177    if (op == '>')
     178        return cmpval > 0;
     179    /* >= */
     180    return cmpval >= 0;
     181}
     182
     183/* The arithmetic operator handling functions.  */
     184
     185static arith_t arithmetic_common(VALUE * l, VALUE * r, int op)
     186{
     187    arith_t li, ri;
     188
     189    if (!toarith(l) || !toarith(r))
     190        bb_error_msg_and_die("non-numeric argument");
     191    li = l->u.i;
     192    ri = r->u.i;
     193    if ((op == '/' || op == '%') && ri == 0)
     194        bb_error_msg_and_die("division by zero");
     195    if (op == '+')
     196        return li + ri;
     197    else if (op == '-')
     198        return li - ri;
     199    else if (op == '*')
     200        return li * ri;
     201    else if (op == '/')
     202        return li / ri;
    211203    else
    212         cmpval = l->u.i - r->u.i;
    213     switch(op) {
    214         case '<':
    215             return cmpval < 0;
    216         case ('L'+'E'):
    217             return cmpval <= 0;
    218         case '=':
    219             return cmpval == 0;
    220         case '!':
    221             return cmpval != 0;
    222         case '>':
    223             return cmpval > 0;
    224         default: /* >= */
    225             return cmpval >= 0;
    226     }
    227 }
    228 
    229 /* The arithmetic operator handling functions.  */
    230 
    231 static arith_t arithmetic_common (VALUE *l, VALUE *r, int op)
    232 {
    233   arith_t li, ri;
    234 
    235   if (!toarith (l) || !toarith (r))
    236     bb_error_msg_and_die ("non-numeric argument");
    237   li = l->u.i;
    238   ri = r->u.i;
    239   if((op == '/' || op == '%') && ri == 0)
    240     bb_error_msg_and_die ( "division by zero");
    241   switch(op) {
    242     case '+':
    243         return li + ri;
    244     case '-':
    245         return li - ri;
    246     case '*':
    247         return li * ri;
    248     case '/':
    249         return li / ri;
    250     default:
    251204        return li % ri;
    252   }
    253205}
    254206
     
    257209   PV is the VALUE for the rhs (the pattern).  */
    258210
    259 static VALUE *docolon (VALUE *sv, VALUE *pv)
     211static VALUE *docolon(VALUE * sv, VALUE * pv)
    260212{
    261213    VALUE *v;
     
    264216    regmatch_t re_regs[NMATCH];
    265217
    266     tostring (sv);
    267     tostring (pv);
     218    tostring(sv);
     219    tostring(pv);
    268220
    269221    if (pv->u.s[0] == '^') {
    270         fprintf (stderr, "\
     222        bb_error_msg("\
    271223warning: unportable BRE: `%s': using `^' as the first character\n\
    272 of a basic regular expression is not portable; it is being ignored",
    273         pv->u.s);
    274     }
    275 
    276     memset (&re_buffer, 0, sizeof (re_buffer));
    277     memset (re_regs, 0, sizeof (*re_regs));
    278     if( regcomp (&re_buffer, pv->u.s, 0) != 0 )
    279         bb_error_msg_and_die("Invalid regular expression");
     224of a basic regular expression is not portable; it is being ignored", pv->u.s);
     225    }
     226
     227    memset(&re_buffer, 0, sizeof(re_buffer));
     228    memset(re_regs, 0, sizeof(*re_regs));
     229    xregcomp(&re_buffer, pv->u.s, 0);
    280230
    281231    /* expr uses an anchored pattern match, so check that there was a
    282232     * match and that the match starts at offset 0. */
    283     if (regexec (&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
    284             re_regs[0].rm_so == 0) {
     233    if (regexec(&re_buffer, sv->u.s, NMATCH, re_regs, 0) != REG_NOMATCH &&
     234        re_regs[0].rm_so == 0) {
    285235        /* Were \(...\) used? */
    286236        if (re_buffer.re_nsub > 0) {
    287237            sv->u.s[re_regs[1].rm_eo] = '\0';
    288             v = str_value (sv->u.s + re_regs[1].rm_so);
    289         }
    290         else
    291             v = int_value (re_regs[0].rm_eo);
    292     }
    293     else {
     238            v = str_value(sv->u.s + re_regs[1].rm_so);
     239        } else
     240            v = int_value(re_regs[0].rm_eo);
     241    } else {
    294242        /* Match failed -- return the right kind of null.  */
    295243        if (re_buffer.re_nsub > 0)
    296             v = str_value ("");
     244            v = str_value("");
    297245        else
    298             v = int_value (0);
    299     }
     246            v = int_value(0);
     247    }
     248//FIXME: sounds like here is a bit missing: regfree(&re_buffer);
    300249    return v;
    301250}
     
    303252/* Handle bare operands and ( expr ) syntax.  */
    304253
    305 static VALUE *eval7 (void)
     254static VALUE *eval7(void)
    306255{
    307256    VALUE *v;
    308257
    309     if (!*args)
    310         bb_error_msg_and_die ( "syntax error");
    311 
    312     if (nextarg ("(")) {
    313         args++;
    314         v = eval ();
    315         if (!nextarg (")"))
    316             bb_error_msg_and_die ( "syntax error");
    317             args++;
    318             return v;
     258    if (!*G.args)
     259        bb_error_msg_and_die("syntax error");
     260
     261    if (nextarg("(")) {
     262        G.args++;
     263        v = eval();
     264        if (!nextarg(")"))
     265            bb_error_msg_and_die("syntax error");
     266        G.args++;
     267        return v;
     268    }
     269
     270    if (nextarg(")"))
     271        bb_error_msg_and_die("syntax error");
     272
     273    return str_value(*G.args++);
     274}
     275
     276/* Handle match, substr, index, length, and quote keywords.  */
     277
     278static VALUE *eval6(void)
     279{
     280    static const char keywords[] ALIGN1 =
     281        "quote\0""length\0""match\0""index\0""substr\0";
     282
     283    VALUE *r, *i1, *i2;
     284    VALUE *l = l; /* silence gcc */
     285    VALUE *v = v; /* silence gcc */
     286    int key = *G.args ? index_in_strings(keywords, *G.args) + 1 : 0;
     287
     288    if (key == 0) /* not a keyword */
     289        return eval7();
     290    G.args++; /* We have a valid token, so get the next argument.  */
     291    if (key == 1) { /* quote */
     292        if (!*G.args)
     293            bb_error_msg_and_die("syntax error");
     294        return str_value(*G.args++);
     295    }
     296    if (key == 2) { /* length */
     297        r = eval6();
     298        tostring(r);
     299        v = int_value(strlen(r->u.s));
     300        freev(r);
     301    } else
     302        l = eval6();
     303
     304    if (key == 3) { /* match */
     305        r = eval6();
     306        v = docolon(l, r);
     307        freev(l);
     308        freev(r);
     309    }
     310    if (key == 4) { /* index */
     311        r = eval6();
     312        tostring(l);
     313        tostring(r);
     314        v = int_value(strcspn(l->u.s, r->u.s) + 1);
     315        if (v->u.i == (arith_t) strlen(l->u.s) + 1)
     316            v->u.i = 0;
     317        freev(l);
     318        freev(r);
     319    }
     320    if (key == 5) { /* substr */
     321        i1 = eval6();
     322        i2 = eval6();
     323        tostring(l);
     324        if (!toarith(i1) || !toarith(i2)
     325         || i1->u.i > (arith_t) strlen(l->u.s)
     326         || i1->u.i <= 0 || i2->u.i <= 0)
     327            v = str_value("");
     328        else {
     329            v = xmalloc(sizeof(VALUE));
     330            v->type = string;
     331            v->u.s = xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
    319332        }
    320 
    321     if (nextarg (")"))
    322         bb_error_msg_and_die ( "syntax error");
    323 
    324     return str_value (*args++);
    325 }
    326 
    327 /* Handle match, substr, index, length, and quote keywords.  */
    328 
    329 static VALUE *eval6 (void)
    330 {
    331     VALUE *l, *r, *v, *i1, *i2;
    332 
    333     if (nextarg ("quote")) {
    334         args++;
    335         if (!*args)
    336             bb_error_msg_and_die ( "syntax error");
    337         return str_value (*args++);
    338     }
    339     else if (nextarg ("length")) {
    340         args++;
    341         r = eval6 ();
    342         tostring (r);
    343         v = int_value (strlen (r->u.s));
    344         freev (r);
    345         return v;
    346     }
    347     else if (nextarg ("match")) {
    348         args++;
    349         l = eval6 ();
    350         r = eval6 ();
    351         v = docolon (l, r);
    352         freev (l);
    353         freev (r);
    354         return v;
    355     }
    356     else if (nextarg ("index")) {
    357         args++;
    358         l = eval6 ();
    359         r = eval6 ();
    360         tostring (l);
    361         tostring (r);
    362         v = int_value (strcspn (l->u.s, r->u.s) + 1);
    363         if (v->u.i == (arith_t) strlen (l->u.s) + 1)
    364             v->u.i = 0;
    365         freev (l);
    366         freev (r);
    367         return v;
    368     }
    369     else if (nextarg ("substr")) {
    370         args++;
    371         l = eval6 ();
    372         i1 = eval6 ();
    373         i2 = eval6 ();
    374         tostring (l);
    375         if (!toarith (i1) || !toarith (i2)
    376             || i1->u.i > (arith_t) strlen (l->u.s)
    377             || i1->u.i <= 0 || i2->u.i <= 0)
    378         v = str_value ("");
    379         else {
    380             v = xmalloc (sizeof(VALUE));
    381             v->type = string;
    382             v->u.s = bb_xstrndup(l->u.s + i1->u.i - 1, i2->u.i);
    383         }
    384         freev (l);
    385         freev (i1);
    386         freev (i2);
    387         return v;
    388     }
    389     else
    390         return eval7 ();
     333        freev(l);
     334        freev(i1);
     335        freev(i2);
     336    }
     337    return v;
     338
    391339}
    392340
     
    394342   Calls docolon to do the real work.  */
    395343
    396 static VALUE *eval5 (void)
     344static VALUE *eval5(void)
    397345{
    398346    VALUE *l, *r, *v;
    399347
    400     l = eval6 ();
    401     while (nextarg (":")) {
    402         args++;
    403         r = eval6 ();
    404         v = docolon (l, r);
    405         freev (l);
    406         freev (r);
     348    l = eval6();
     349    while (nextarg(":")) {
     350        G.args++;
     351        r = eval6();
     352        v = docolon(l, r);
     353        freev(l);
     354        freev(r);
    407355        l = v;
    408356    }
     
    412360/* Handle *, /, % operators.  */
    413361
    414 static VALUE *eval4 (void)
     362static VALUE *eval4(void)
    415363{
    416364    VALUE *l, *r;
     
    418366    arith_t val;
    419367
    420     l = eval5 ();
     368    l = eval5();
    421369    while (1) {
    422         if (nextarg ("*"))
     370        if (nextarg("*"))
    423371            op = '*';
    424         else if (nextarg ("/"))
     372        else if (nextarg("/"))
    425373            op = '/';
    426         else if (nextarg ("%"))
     374        else if (nextarg("%"))
    427375            op = '%';
    428376        else
    429377            return l;
    430         args++;
    431         r = eval5 ();
    432         val = arithmetic_common (l, r, op);
    433         freev (l);
    434         freev (r);
    435         l = int_value (val);
     378        G.args++;
     379        r = eval5();
     380        val = arithmetic_common(l, r, op);
     381        freev(l);
     382        freev(r);
     383        l = int_value(val);
    436384    }
    437385}
     
    439387/* Handle +, - operators.  */
    440388
    441 static VALUE *eval3 (void)
     389static VALUE *eval3(void)
    442390{
    443391    VALUE *l, *r;
     
    445393    arith_t val;
    446394
    447     l = eval4 ();
     395    l = eval4();
    448396    while (1) {
    449         if (nextarg ("+"))
     397        if (nextarg("+"))
    450398            op = '+';
    451         else if (nextarg ("-"))
     399        else if (nextarg("-"))
    452400            op = '-';
    453401        else
    454402            return l;
    455         args++;
    456         r = eval4 ();
    457         val = arithmetic_common (l, r, op);
    458         freev (l);
    459         freev (r);
    460         l = int_value (val);
     403        G.args++;
     404        r = eval4();
     405        val = arithmetic_common(l, r, op);
     406        freev(l);
     407        freev(r);
     408        l = int_value(val);
    461409    }
    462410}
     
    464412/* Handle comparisons.  */
    465413
    466 static VALUE *eval2 (void)
     414static VALUE *eval2(void)
    467415{
    468416    VALUE *l, *r;
     
    470418    arith_t val;
    471419
    472     l = eval3 ();
     420    l = eval3();
    473421    while (1) {
    474         if (nextarg ("<"))
     422        if (nextarg("<"))
    475423            op = '<';
    476         else if (nextarg ("<="))
    477             op = 'L'+'E';
    478         else if (nextarg ("=") || nextarg ("=="))
     424        else if (nextarg("<="))
     425            op = 'L' + 'E';
     426        else if (nextarg("=") || nextarg("=="))
    479427            op = '=';
    480         else if (nextarg ("!="))
     428        else if (nextarg("!="))
    481429            op = '!';
    482         else if (nextarg (">="))
    483             op = 'G'+'E';
    484         else if (nextarg (">"))
     430        else if (nextarg(">="))
     431            op = 'G' + 'E';
     432        else if (nextarg(">"))
    485433            op = '>';
    486434        else
    487435            return l;
    488         args++;
    489         r = eval3 ();
    490         toarith (l);
    491         toarith (r);
    492         val = cmp_common (l, r, op);
    493         freev (l);
    494         freev (r);
    495         l = int_value (val);
     436        G.args++;
     437        r = eval3();
     438        toarith(l);
     439        toarith(r);
     440        val = cmp_common(l, r, op);
     441        freev(l);
     442        freev(r);
     443        l = int_value(val);
    496444    }
    497445}
     
    499447/* Handle &.  */
    500448
    501 static VALUE *eval1 (void)
     449static VALUE *eval1(void)
    502450{
    503451    VALUE *l, *r;
    504452
    505     l = eval2 ();
    506     while (nextarg ("&")) {
    507         args++;
    508         r = eval2 ();
    509         if (null (l) || null (r)) {
    510             freev (l);
    511             freev (r);
    512             l = int_value (0);
    513         }
    514         else
    515             freev (r);
     453    l = eval2();
     454    while (nextarg("&")) {
     455        G.args++;
     456        r = eval2();
     457        if (null(l) || null(r)) {
     458            freev(l);
     459            freev(r);
     460            l = int_value(0);
     461        } else
     462            freev(r);
    516463    }
    517464    return l;
     
    520467/* Handle |.  */
    521468
    522 static VALUE *eval (void)
     469static VALUE *eval(void)
    523470{
    524471    VALUE *l, *r;
    525472
    526     l = eval1 ();
    527     while (nextarg ("|")) {
    528         args++;
    529         r = eval1 ();
    530         if (null (l)) {
    531             freev (l);
     473    l = eval1();
     474    while (nextarg("|")) {
     475        G.args++;
     476        r = eval1();
     477        if (null(l)) {
     478            freev(l);
    532479            l = r;
    533         }
    534         else
    535             freev (r);
     480        } else
     481            freev(r);
    536482    }
    537483    return l;
    538484}
     485
     486int expr_main(int argc, char **argv);
     487int expr_main(int argc, char **argv)
     488{
     489    VALUE *v;
     490
     491    if (argc == 1) {
     492        bb_error_msg_and_die("too few arguments");
     493    }
     494
     495    G.args = argv + 1;
     496
     497    v = eval();
     498    if (*G.args)
     499        bb_error_msg_and_die("syntax error");
     500
     501    if (v->type == integer)
     502        printf("%" PF_REZ "d\n", PF_REZ_TYPE v->u.i);
     503    else
     504        puts(v->u.s);
     505
     506    fflush_stdout_and_exit(null(v));
     507}
Note: See TracChangeset for help on using the changeset viewer.