diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-26 23:03:21 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-07-26 23:03:21 +0200 |
commit | b8c0bc18f0cc31e3a2f41dd2c0b30426e4a77fc5 (patch) | |
tree | 593a170b42f42ef1aa8ca8e642a86cfaa40e41b1 | |
parent | d04fc712e30b681117afaad490fec2a747b390c6 (diff) | |
download | busybox-w32-b8c0bc18f0cc31e3a2f41dd2c0b30426e4a77fc5.tar.gz busybox-w32-b8c0bc18f0cc31e3a2f41dd2c0b30426e4a77fc5.tar.bz2 busybox-w32-b8c0bc18f0cc31e3a2f41dd2c0b30426e4a77fc5.zip |
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 <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash.c | 62 |
1 files 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) | |||
6304 | #endif | 6304 | #endif |
6305 | 6305 | ||
6306 | /* argstr needs it */ | 6306 | /* argstr needs it */ |
6307 | static char *evalvar(char *p, int flags, struct strlist *var_str_list); | 6307 | static char *evalvar(char *p, int flags); |
6308 | 6308 | ||
6309 | /* | 6309 | /* |
6310 | * Perform variable and command substitution. If EXP_FULL is set, output CTLESC | 6310 | * Perform variable and command substitution. If EXP_FULL is set, output CTLESC |
6311 | * characters to allow for further processing. Otherwise treat | 6311 | * characters to allow for further processing. Otherwise treat |
6312 | * $@ like $* since no splitting will be performed. | 6312 | * $@ like $* since no splitting will be performed. |
6313 | * | ||
6314 | * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence | ||
6315 | * over shell variables. Needed for "A=a B=$A; echo $B" case - we use it | ||
6316 | * for correct expansion of "B=$A" word. | ||
6317 | */ | 6313 | */ |
6318 | static void | 6314 | static void |
6319 | argstr(char *p, int flags, struct strlist *var_str_list) | 6315 | argstr(char *p, int flags) |
6320 | { | 6316 | { |
6321 | static const char spclchars[] ALIGN1 = { | 6317 | static const char spclchars[] ALIGN1 = { |
6322 | '=', | 6318 | '=', |
@@ -6409,7 +6405,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
6409 | inquotes ^= EXP_QUOTED; | 6405 | inquotes ^= EXP_QUOTED; |
6410 | /* "$@" syntax adherence hack */ | 6406 | /* "$@" syntax adherence hack */ |
6411 | if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) { | 6407 | if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) { |
6412 | p = evalvar(p + 1, flags | inquotes, /* var_str_list: */ NULL) + 1; | 6408 | p = evalvar(p + 1, flags | inquotes) + 1; |
6413 | goto start; | 6409 | goto start; |
6414 | } | 6410 | } |
6415 | addquote: | 6411 | addquote: |
@@ -6435,7 +6431,7 @@ argstr(char *p, int flags, struct strlist *var_str_list) | |||
6435 | goto addquote; | 6431 | goto addquote; |
6436 | case CTLVAR: | 6432 | case CTLVAR: |
6437 | TRACE(("argstr: evalvar('%s')\n", p)); | 6433 | TRACE(("argstr: evalvar('%s')\n", p)); |
6438 | p = evalvar(p, flags | inquotes, var_str_list); | 6434 | p = evalvar(p, flags | inquotes); |
6439 | TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock())); | 6435 | TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock())); |
6440 | goto start; | 6436 | goto start; |
6441 | case CTLBACKQ: | 6437 | case CTLBACKQ: |
@@ -6577,7 +6573,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags) | |||
6577 | 6573 | ||
6578 | static const char * | 6574 | static const char * |
6579 | subevalvar(char *p, char *varname, int strloc, int subtype, | 6575 | subevalvar(char *p, char *varname, int strloc, int subtype, |
6580 | int startloc, int varflags, int flag, struct strlist *var_str_list) | 6576 | int startloc, int varflags, int flag) |
6581 | { | 6577 | { |
6582 | struct nodelist *saveargbackq = argbackq; | 6578 | struct nodelist *saveargbackq = argbackq; |
6583 | int quotes = flag & QUOTES_ESC; | 6579 | int quotes = flag & QUOTES_ESC; |
@@ -6595,8 +6591,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6595 | // p, varname, strloc, subtype, startloc, varflags, quotes); | 6591 | // p, varname, strloc, subtype, startloc, varflags, quotes); |
6596 | 6592 | ||
6597 | argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? | 6593 | argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ? |
6598 | (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0), | 6594 | (flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0) |
6599 | var_str_list); | 6595 | ); |
6600 | STPUTC('\0', expdest); | 6596 | STPUTC('\0', expdest); |
6601 | argbackq = saveargbackq; | 6597 | argbackq = saveargbackq; |
6602 | startp = (char *)stackblock() + startloc; | 6598 | startp = (char *)stackblock() + startloc; |
@@ -6873,7 +6869,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6873 | * ash -c 'echo ${#1#}' name:'1=#' | 6869 | * ash -c 'echo ${#1#}' name:'1=#' |
6874 | */ | 6870 | */ |
6875 | static NOINLINE ssize_t | 6871 | static NOINLINE ssize_t |
6876 | varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int *quotedp) | 6872 | varvalue(char *name, int varflags, int flags, int *quotedp) |
6877 | { | 6873 | { |
6878 | const char *p; | 6874 | const char *p; |
6879 | int num; | 6875 | int num; |
@@ -6965,31 +6961,6 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int | |||
6965 | goto value; | 6961 | goto value; |
6966 | default: | 6962 | default: |
6967 | /* NB: name has form "VAR=..." */ | 6963 | /* NB: name has form "VAR=..." */ |
6968 | |||
6969 | /* "A=a B=$A" case: var_str_list is a list of "A=a" strings | ||
6970 | * which should be considered before we check variables. */ | ||
6971 | if (var_str_list) { | ||
6972 | unsigned name_len = (strchrnul(name, '=') - name) + 1; | ||
6973 | p = NULL; | ||
6974 | do { | ||
6975 | char *str, *eq; | ||
6976 | str = var_str_list->text; | ||
6977 | eq = strchr(str, '='); | ||
6978 | if (!eq) /* stop at first non-assignment */ | ||
6979 | break; | ||
6980 | eq++; | ||
6981 | if (name_len == (unsigned)(eq - str) | ||
6982 | && strncmp(str, name, name_len) == 0 | ||
6983 | ) { | ||
6984 | p = eq; | ||
6985 | /* goto value; - WRONG! */ | ||
6986 | /* think "A=1 A=2 B=$A" */ | ||
6987 | } | ||
6988 | var_str_list = var_str_list->next; | ||
6989 | } while (var_str_list); | ||
6990 | if (p) | ||
6991 | goto value; | ||
6992 | } | ||
6993 | p = lookupvar(name); | 6964 | p = lookupvar(name); |
6994 | value: | 6965 | value: |
6995 | if (!p) | 6966 | if (!p) |
@@ -7019,7 +6990,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int | |||
7019 | * input string. | 6990 | * input string. |
7020 | */ | 6991 | */ |
7021 | static char * | 6992 | static char * |
7022 | evalvar(char *p, int flag, struct strlist *var_str_list) | 6993 | evalvar(char *p, int flag) |
7023 | { | 6994 | { |
7024 | char varflags; | 6995 | char varflags; |
7025 | char subtype; | 6996 | char subtype; |
@@ -7043,7 +7014,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list) | |||
7043 | p = strchr(p, '=') + 1; //TODO: use var_end(p)? | 7014 | p = strchr(p, '=') + 1; //TODO: use var_end(p)? |
7044 | 7015 | ||
7045 | again: | 7016 | again: |
7046 | varlen = varvalue(var, varflags, flag, var_str_list, "ed); | 7017 | varlen = varvalue(var, varflags, flag, "ed); |
7047 | if (varflags & VSNUL) | 7018 | if (varflags & VSNUL) |
7048 | varlen--; | 7019 | varlen--; |
7049 | 7020 | ||
@@ -7057,8 +7028,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list) | |||
7057 | if (varlen < 0) { | 7028 | if (varlen < 0) { |
7058 | argstr( | 7029 | argstr( |
7059 | p, | 7030 | p, |
7060 | flag | EXP_TILDE | EXP_WORD, | 7031 | flag | EXP_TILDE | EXP_WORD |
7061 | var_str_list | ||
7062 | ); | 7032 | ); |
7063 | goto end; | 7033 | goto end; |
7064 | } | 7034 | } |
@@ -7070,7 +7040,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list) | |||
7070 | goto record; | 7040 | goto record; |
7071 | 7041 | ||
7072 | subevalvar(p, var, 0, subtype, startloc, varflags, | 7042 | subevalvar(p, var, 0, subtype, startloc, varflags, |
7073 | flag & ~QUOTES_ESC, var_str_list); | 7043 | flag & ~QUOTES_ESC); |
7074 | varflags &= ~VSNUL; | 7044 | varflags &= ~VSNUL; |
7075 | /* | 7045 | /* |
7076 | * Remove any recorded regions beyond | 7046 | * Remove any recorded regions beyond |
@@ -7123,7 +7093,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list) | |||
7123 | STPUTC('\0', expdest); | 7093 | STPUTC('\0', expdest); |
7124 | patloc = expdest - (char *)stackblock(); | 7094 | patloc = expdest - (char *)stackblock(); |
7125 | if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, | 7095 | if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype, |
7126 | startloc, varflags, flag, var_str_list)) { | 7096 | startloc, varflags, flag)) { |
7127 | int amount = expdest - ( | 7097 | int amount = expdest - ( |
7128 | (char *)stackblock() + patloc - 1 | 7098 | (char *)stackblock() + patloc - 1 |
7129 | ); | 7099 | ); |
@@ -7547,8 +7517,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag) | |||
7547 | argbackq = arg->narg.backquote; | 7517 | argbackq = arg->narg.backquote; |
7548 | STARTSTACKSTR(expdest); | 7518 | STARTSTACKSTR(expdest); |
7549 | TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag)); | 7519 | TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag)); |
7550 | argstr(arg->narg.text, flag, | 7520 | argstr(arg->narg.text, flag); |
7551 | /* var_str_list: */ arglist ? arglist->list : NULL); | ||
7552 | p = _STPUTC('\0', expdest); | 7521 | p = _STPUTC('\0', expdest); |
7553 | expdest = p - 1; | 7522 | expdest = p - 1; |
7554 | if (arglist == NULL) { | 7523 | if (arglist == NULL) { |
@@ -7615,8 +7584,7 @@ casematch(union node *pattern, char *val) | |||
7615 | setstackmark(&smark); | 7584 | setstackmark(&smark); |
7616 | argbackq = pattern->narg.backquote; | 7585 | argbackq = pattern->narg.backquote; |
7617 | STARTSTACKSTR(expdest); | 7586 | STARTSTACKSTR(expdest); |
7618 | argstr(pattern->narg.text, EXP_TILDE | EXP_CASE, | 7587 | argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); |
7619 | /* var_str_list: */ NULL); | ||
7620 | STACKSTRNUL(expdest); | 7588 | STACKSTRNUL(expdest); |
7621 | ifsfree(); | 7589 | ifsfree(); |
7622 | result = patmatch(stackblock(), val); | 7590 | result = patmatch(stackblock(), val); |