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>
This commit is contained in:
parent
d04fc712e3
commit
b8c0bc18f0
62
shell/ash.c
62
shell/ash.c
@ -6304,19 +6304,15 @@ expari(int flag)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* argstr needs it */
|
/* 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
|
* Perform variable and command substitution. If EXP_FULL is set, output CTLESC
|
||||||
* characters to allow for further processing. Otherwise treat
|
* characters to allow for further processing. Otherwise treat
|
||||||
* $@ like $* since no splitting will be performed.
|
* $@ 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
|
static void
|
||||||
argstr(char *p, int flags, struct strlist *var_str_list)
|
argstr(char *p, int flags)
|
||||||
{
|
{
|
||||||
static const char spclchars[] ALIGN1 = {
|
static const char spclchars[] ALIGN1 = {
|
||||||
'=',
|
'=',
|
||||||
@ -6409,7 +6405,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
|
|||||||
inquotes ^= EXP_QUOTED;
|
inquotes ^= EXP_QUOTED;
|
||||||
/* "$@" syntax adherence hack */
|
/* "$@" syntax adherence hack */
|
||||||
if (inquotes && !memcmp(p, dolatstr + 1, DOLATSTRLEN - 1)) {
|
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;
|
goto start;
|
||||||
}
|
}
|
||||||
addquote:
|
addquote:
|
||||||
@ -6435,7 +6431,7 @@ argstr(char *p, int flags, struct strlist *var_str_list)
|
|||||||
goto addquote;
|
goto addquote;
|
||||||
case CTLVAR:
|
case CTLVAR:
|
||||||
TRACE(("argstr: evalvar('%s')\n", p));
|
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()));
|
TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
|
||||||
goto start;
|
goto start;
|
||||||
case CTLBACKQ:
|
case CTLBACKQ:
|
||||||
@ -6577,7 +6573,7 @@ varunset(const char *end, const char *var, const char *umsg, int varflags)
|
|||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
subevalvar(char *p, char *varname, int strloc, int subtype,
|
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;
|
struct nodelist *saveargbackq = argbackq;
|
||||||
int quotes = flag & QUOTES_ESC;
|
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);
|
// p, varname, strloc, subtype, startloc, varflags, quotes);
|
||||||
|
|
||||||
argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
|
argstr(p, EXP_TILDE | (subtype != VSASSIGN && subtype != VSQUESTION ?
|
||||||
(flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0),
|
(flag & (EXP_QUOTED | EXP_QPAT) ? EXP_QPAT : EXP_CASE) : 0)
|
||||||
var_str_list);
|
);
|
||||||
STPUTC('\0', expdest);
|
STPUTC('\0', expdest);
|
||||||
argbackq = saveargbackq;
|
argbackq = saveargbackq;
|
||||||
startp = (char *)stackblock() + startloc;
|
startp = (char *)stackblock() + startloc;
|
||||||
@ -6873,7 +6869,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
|
|||||||
* ash -c 'echo ${#1#}' name:'1=#'
|
* ash -c 'echo ${#1#}' name:'1=#'
|
||||||
*/
|
*/
|
||||||
static NOINLINE ssize_t
|
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;
|
const char *p;
|
||||||
int num;
|
int num;
|
||||||
@ -6965,31 +6961,6 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int
|
|||||||
goto value;
|
goto value;
|
||||||
default:
|
default:
|
||||||
/* NB: name has form "VAR=..." */
|
/* 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);
|
p = lookupvar(name);
|
||||||
value:
|
value:
|
||||||
if (!p)
|
if (!p)
|
||||||
@ -7019,7 +6990,7 @@ varvalue(char *name, int varflags, int flags, struct strlist *var_str_list, int
|
|||||||
* input string.
|
* input string.
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
evalvar(char *p, int flag, struct strlist *var_str_list)
|
evalvar(char *p, int flag)
|
||||||
{
|
{
|
||||||
char varflags;
|
char varflags;
|
||||||
char subtype;
|
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)?
|
p = strchr(p, '=') + 1; //TODO: use var_end(p)?
|
||||||
|
|
||||||
again:
|
again:
|
||||||
varlen = varvalue(var, varflags, flag, var_str_list, "ed);
|
varlen = varvalue(var, varflags, flag, "ed);
|
||||||
if (varflags & VSNUL)
|
if (varflags & VSNUL)
|
||||||
varlen--;
|
varlen--;
|
||||||
|
|
||||||
@ -7057,8 +7028,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
|
|||||||
if (varlen < 0) {
|
if (varlen < 0) {
|
||||||
argstr(
|
argstr(
|
||||||
p,
|
p,
|
||||||
flag | EXP_TILDE | EXP_WORD,
|
flag | EXP_TILDE | EXP_WORD
|
||||||
var_str_list
|
|
||||||
);
|
);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -7070,7 +7040,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
|
|||||||
goto record;
|
goto record;
|
||||||
|
|
||||||
subevalvar(p, var, 0, subtype, startloc, varflags,
|
subevalvar(p, var, 0, subtype, startloc, varflags,
|
||||||
flag & ~QUOTES_ESC, var_str_list);
|
flag & ~QUOTES_ESC);
|
||||||
varflags &= ~VSNUL;
|
varflags &= ~VSNUL;
|
||||||
/*
|
/*
|
||||||
* Remove any recorded regions beyond
|
* Remove any recorded regions beyond
|
||||||
@ -7123,7 +7093,7 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
|
|||||||
STPUTC('\0', expdest);
|
STPUTC('\0', expdest);
|
||||||
patloc = expdest - (char *)stackblock();
|
patloc = expdest - (char *)stackblock();
|
||||||
if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
|
if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
|
||||||
startloc, varflags, flag, var_str_list)) {
|
startloc, varflags, flag)) {
|
||||||
int amount = expdest - (
|
int amount = expdest - (
|
||||||
(char *)stackblock() + patloc - 1
|
(char *)stackblock() + patloc - 1
|
||||||
);
|
);
|
||||||
@ -7547,8 +7517,7 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
|
|||||||
argbackq = arg->narg.backquote;
|
argbackq = arg->narg.backquote;
|
||||||
STARTSTACKSTR(expdest);
|
STARTSTACKSTR(expdest);
|
||||||
TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
|
TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
|
||||||
argstr(arg->narg.text, flag,
|
argstr(arg->narg.text, flag);
|
||||||
/* var_str_list: */ arglist ? arglist->list : NULL);
|
|
||||||
p = _STPUTC('\0', expdest);
|
p = _STPUTC('\0', expdest);
|
||||||
expdest = p - 1;
|
expdest = p - 1;
|
||||||
if (arglist == NULL) {
|
if (arglist == NULL) {
|
||||||
@ -7615,8 +7584,7 @@ casematch(union node *pattern, char *val)
|
|||||||
setstackmark(&smark);
|
setstackmark(&smark);
|
||||||
argbackq = pattern->narg.backquote;
|
argbackq = pattern->narg.backquote;
|
||||||
STARTSTACKSTR(expdest);
|
STARTSTACKSTR(expdest);
|
||||||
argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
|
argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
|
||||||
/* var_str_list: */ NULL);
|
|
||||||
STACKSTRNUL(expdest);
|
STACKSTRNUL(expdest);
|
||||||
ifsfree();
|
ifsfree();
|
||||||
result = patmatch(stackblock(), val);
|
result = patmatch(stackblock(), val);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user