From b8c0bc18f0cc31e3a2f41dd2c0b30426e4a77fc5 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Jul 2017 23:03:21 +0200 Subject: [PATCH] ash: revert previous implementation of "A=1 A=2 B=$A cmd" code 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 --- shell/ash.c | 62 +++++++++++++---------------------------------------- 1 file changed, 15 insertions(+), 47 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 5bb59355c..faa42e28c 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -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, "ed); + varlen = varvalue(var, varflags, flag, "ed); 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); -- 2.25.1