ash: revert previous implementation of "A=1 A=2 B=$A cmd" code
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 26 Jul 2017 21:03:21 +0000 (23:03 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 26 Jul 2017 21:03:21 +0000 (23:03 +0200)
Reverts this:

    commit 0e6f661e23d358cca104c24f8438d0ec64df32f1
    Date:   Fri Feb 15 15:02:15 2008 +0000
    ash: handle "A=1 A=2 B=$A; echo $B". closes bug 947.

A different fix from upstream has been imported by previous six commits.

Last seven commits, cumulative:

function                                             old     new   delta
poplocalvars                                           -     314    +314
mklocal                                                -     288    +288
pushlocalvars                                          -      48     +48
evalcommand                                         1372    1408     +36
unwindlocalvars                                        -      22     +22
ash_main                                            1022    1029      +7
setvar                                               167     172      +5
localvar_stack                                         -       4      +4
setvareq                                             303     302      -1
evalcase                                             271     269      -2
subevalvar                                          1202    1198      -4
localvars                                              4       -      -4
cmdenviron                                             4       -      -4
expandarg                                            984     973     -11
evalvar                                              589     574     -15
argstr                                              1164    1141     -23
dotcmd                                               335     303     -32
bltinlookup                                           51       5     -46
varvalue                                             709     596    -113
evalfun                                              456     270    -186
localcmd                                             364      44    -320
------------------------------------------------------------------------------
(add/remove: 5/2 grow/shrink: 3/11 up/down: 724/-761)         Total: -37 bytes
   text    data     bss     dec     hex filename
 915353     485    6888  922726   e1466 busybox_old
 915320     485    6880  922685   e143d busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c

index 5bb59355c6bbb4210005b8a8b58b5ebcc0b127c3..faa42e28ce473eb7aac0c397421f3ef87e554d94 100644 (file)
@@ -6304,19 +6304,15 @@ expari(int flag)
 #endif
 
 /* argstr needs it */
-static char *evalvar(char *p, int flags, struct strlist *var_str_list);
+static char *evalvar(char *p, int flags);
 
 /*
  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
  * characters to allow for further processing.  Otherwise treat
  * $@ like $* since no splitting will be performed.
- *
- * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
- * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it
- * for correct expansion of "B=$A" word.
  */
 static void
-argstr(char *p, int flags, struct strlist *var_str_list)
+argstr(char *p, int flags)
 {
        static const char spclchars[] ALIGN1 = {
                '=',
@@ -6409,7 +6405,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
                        inquotes ^= EXP_QUOTED;
                        /* "$@" syntax adherence hack */
                        if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
-                               p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1;
+                               p = evalvar(p + 1, flags | inquotes) + 1;
                                goto start;
                        }
  addquote:
@@ -6435,7 +6431,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
                        goto addquote;
                case CTLVAR:
                        TRACE(("argstr: evalvar('%s')\n", p));
-                       p = evalvar(p, flags | inquotes, var_str_list);
+                       p = evalvar(p, flags | inquotes);
                        TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
                        goto start;
                case CTLBACKQ:
@@ -6577,7 +6573,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags)
 
 static const char *
 subevalvar(char *p, char *varname, int strloc, int subtype,
-               int startloc, int varflags, int flag, struct strlist *var_str_list)
+               int startloc, int varflags, int flag)
 {
        struct nodelist *saveargbackq = argbackq;
        int quotes = flag & QUOTES_ESC;
@@ -6595,8 +6591,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
        //              p, varname, strloc, subtype, startloc, varflags, quotes);
 
        argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
-                       (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
-                       var_str_list);
+                       (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
+       );
        STPUTC('\0', expdest);
        argbackq = saveargbackq;
        startp = (char *)stackblock() + startloc;
@@ -6873,7 +6869,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
  * ash -c 'echo ${#1#}'  name:'1=#'
  */
 static NOINLINE ssize_t
-varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp)
+varvalue(char *name, int varflags, int flags, int *quotedp)
 {
        const char *p;
        int num;
@@ -6965,31 +6961,6 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int
                goto value;
        default:
                /* NB: name has form "VAR=..." */
-
-               /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
-                * which should be considered before we check variables. */
-               if (var_str_list) {
-                       unsigned name_len = (strchrnul(name, '=') - name) + 1;
-                       p = NULL;
-                       do {
-                               char *str, *eq;
-                               str = var_str_list->text;
-                               eq = strchr(str, '=');
-                               if (!eq) /* stop at first non-assignment */
-                                       break;
-                               eq++;
-                               if (name_len == (unsigned)(eq - str)
-                                && strncmp(str, name, name_len) == 0
-                               ) {
-                                       p = eq;
-                                       /* goto value; - WRONG! */
-                                       /* think "A=1 A=2 B=$A" */
-                               }
-                               var_str_list = var_str_list->next;
-                       } while (var_str_list);
-                       if (p)
-                               goto value;
-               }
                p = lookupvar(name);
  value:
                if (!p)
@@ -7019,7 +6990,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int
  * input string.
  */
 static char *
-evalvar(char *p, int flag, struct strlist *var_str_list)
+evalvar(char *p, int flag)
 {
        char varflags;
        char subtype;
@@ -7043,7 +7014,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
        p = strchr(p, '=') + 1; //TODO: use var_end(p)?
 
  again:
-       varlen = varvalue(var, varflags, flag, var_str_list, &quoted);
+       varlen = varvalue(var, varflags, flag, &quoted);
        if (varflags & VSNUL)
                varlen--;
 
@@ -7057,8 +7028,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
                if (varlen < 0) {
                        argstr(
                                p,
-                               flag | EXP_TILDE | EXP_WORD,
-                               var_str_list
+                               flag | EXP_TILDE | EXP_WORD
                        );
                        goto end;
                }
@@ -7070,7 +7040,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
                        goto record;
 
                subevalvar(p, var, 0, subtype, startloc, varflags,
-                          flag & ~QUOTES_ESC, var_str_list);
+                          flag & ~QUOTES_ESC);
                varflags &= ~VSNUL;
                /*
                 * Remove any recorded regions beyond
@@ -7123,7 +7093,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
                STPUTC('\0', expdest);
                patloc = expdest - (char *)stackblock();
                if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
-                               startloc, varflags, flag, var_str_list)) {
+                               startloc, varflags, flag)) {
                        int amount = expdest - (
                                (char *)stackblock() + patloc - 1
                        );
@@ -7547,8 +7517,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
        argbackq = arg->narg.backquote;
        STARTSTACKSTR(expdest);
        TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
-       argstr(arg->narg.text, flag,
-                       /* var_str_list: */ arglist ? arglist->list : NULL);
+       argstr(arg->narg.text, flag);
        p = _STPUTC('\0', expdest);
        expdest = p - 1;
        if (arglist == NULL) {
@@ -7615,8 +7584,7 @@ casematch(union node *pattern, char *val)
        setstackmark(&smark);
        argbackq = pattern->narg.backquote;
        STARTSTACKSTR(expdest);
-       argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
-                       /* var_str_list: */ NULL);
+       argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
        STACKSTRNUL(expdest);
        ifsfree();
        result = patmatch(stackblock(), val);