Correctly apply IFS to unquoted text in ${x-text}.
Fixes PR/26058 and the 'for i in ${x-a b c}; do ...' and ${x-'a b' c}. I can't find a PR for the latter problem. Regression test goind in shortly.
This commit is contained in:
parent
6d4eb37378
commit
c6cbc16d26
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: eval.c,v 1.77 2004/06/26 14:09:58 dsl Exp $ */
|
||||
/* $NetBSD: eval.c,v 1.78 2004/06/26 22:09:49 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993
|
||||
@ -37,7 +37,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: eval.c,v 1.77 2004/06/26 14:09:58 dsl Exp $");
|
||||
__RCSID("$NetBSD: eval.c,v 1.78 2004/06/26 22:09:49 dsl Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -354,7 +354,7 @@ evalfor(union node *n, int flags)
|
||||
setstackmark(&smark);
|
||||
arglist.lastp = &arglist.list;
|
||||
for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
|
||||
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_IFS_SPLIT);
|
||||
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
|
||||
if (evalskip)
|
||||
goto out;
|
||||
}
|
||||
@ -702,6 +702,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
|
||||
arglist.lastp = &arglist.list;
|
||||
varflag = 1;
|
||||
/* Expand arguments, ignoring the initial 'name=value' ones */
|
||||
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
|
||||
char *p = argp->narg.text;
|
||||
if (varflag && is_name(*p)) {
|
||||
@ -718,6 +719,7 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd)
|
||||
|
||||
expredir(cmd->ncmd.redirect);
|
||||
|
||||
/* Now do the initial 'name=value' ones we skipped above */
|
||||
varlist.lastp = &varlist.list;
|
||||
for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) {
|
||||
char *p = argp->narg.text;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: expand.c,v 1.65 2004/06/26 20:48:44 dsl Exp $ */
|
||||
/* $NetBSD: expand.c,v 1.66 2004/06/26 22:09:49 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: expand.c,v 1.65 2004/06/26 20:48:44 dsl Exp $");
|
||||
__RCSID("$NetBSD: expand.c,v 1.66 2004/06/26 22:09:49 dsl Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -175,9 +175,9 @@ expandarg(union node *arg, struct arglist *arglist, int flag)
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
STATIC void
|
||||
@ -186,6 +186,11 @@ argstr(char *p, int flag)
|
||||
char c;
|
||||
int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
|
||||
int firsteq = 1;
|
||||
const char *ifs;
|
||||
int ifs_split = EXP_IFS_SPLIT;
|
||||
|
||||
if (flag & EXP_IFS_SPLIT)
|
||||
ifs = ifsset() ? ifsval() : " \t\n";
|
||||
|
||||
if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
|
||||
p = exptilde(p, flag);
|
||||
@ -200,6 +205,10 @@ argstr(char *p, int flag)
|
||||
break;
|
||||
if ((flag & EXP_FULL) != 0)
|
||||
STPUTC(c, expdest);
|
||||
ifs_split = 0;
|
||||
break;
|
||||
case CTLQUOTEEND:
|
||||
ifs_split = EXP_IFS_SPLIT;
|
||||
break;
|
||||
case CTLESC:
|
||||
if (quotes)
|
||||
@ -208,7 +217,7 @@ argstr(char *p, int flag)
|
||||
STPUTC(c, expdest);
|
||||
break;
|
||||
case CTLVAR:
|
||||
p = evalvar(p, flag);
|
||||
p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split));
|
||||
break;
|
||||
case CTLBACKQ:
|
||||
case CTLBACKQ|CTLQUOTE:
|
||||
@ -237,6 +246,11 @@ argstr(char *p, int flag)
|
||||
break;
|
||||
default:
|
||||
STPUTC(c, expdest);
|
||||
if (flag & EXP_IFS_SPLIT & ifs_split && strchr(ifs, c) != NULL) {
|
||||
/* We need to get the output split here... */
|
||||
recordregion(expdest - stackblock() - 1,
|
||||
expdest - stackblock(), 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -685,7 +699,7 @@ again: /* jump here after setting a variable with ${var=text} */
|
||||
/* FALLTHROUGH */
|
||||
case VSMINUS:
|
||||
if (!set) {
|
||||
argstr(p, flag);
|
||||
argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0));
|
||||
/*
|
||||
* ${x-a b c} doesn't get split, but removing the
|
||||
* 'apply_ifs = 0' apparantly breaks ${1+"$@"}..
|
||||
@ -907,6 +921,11 @@ recordregion(int start, int end, int inquotes)
|
||||
if (ifslastp == NULL) {
|
||||
ifsp = &ifsfirst;
|
||||
} else {
|
||||
if (ifslastp->endoff == start) {
|
||||
/* extend previous area */
|
||||
ifslastp->endoff = end;
|
||||
return;
|
||||
}
|
||||
ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
|
||||
ifslastp->next = ifsp;
|
||||
}
|
||||
|
100
bin/sh/parser.c
100
bin/sh/parser.c
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: parser.c,v 1.55 2003/08/07 09:05:37 agc Exp $ */
|
||||
/* $NetBSD: parser.c,v 1.56 2004/06/26 22:09:49 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@ -37,7 +37,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: parser.c,v 1.55 2003/08/07 09:05:37 agc Exp $");
|
||||
__RCSID("$NetBSD: parser.c,v 1.56 2004/06/26 22:09:49 dsl Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -961,7 +961,7 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
|
||||
#endif
|
||||
CHECKEND(); /* set c to PEOF if at end of here document */
|
||||
for (;;) { /* until end of line or end of word */
|
||||
CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
|
||||
CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
|
||||
switch(syntax[c]) {
|
||||
case CNL: /* '\n' */
|
||||
if (syntax == BASESYNTAX)
|
||||
@ -987,57 +987,77 @@ readtoken1(int firstc, char const *syntax, char *eofmark, int striptabs)
|
||||
if (c == PEOF) {
|
||||
USTPUTC('\\', out);
|
||||
pungetc();
|
||||
} else if (c == '\n') {
|
||||
break;
|
||||
}
|
||||
if (c == '\n') {
|
||||
if (doprompt)
|
||||
setprompt(2);
|
||||
else
|
||||
setprompt(0);
|
||||
} else {
|
||||
if (ISDBLQUOTE() && c != '\\' &&
|
||||
c != '`' && c != '$' &&
|
||||
(c != '"' || eofmark != NULL))
|
||||
USTPUTC('\\', out);
|
||||
if (SQSYNTAX[c] == CCTL)
|
||||
USTPUTC(CTLESC, out);
|
||||
else if (eofmark == NULL)
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
USTPUTC(c, out);
|
||||
quotef++;
|
||||
break;
|
||||
}
|
||||
quotef = 1;
|
||||
if (ISDBLQUOTE() && c != '\\' &&
|
||||
c != '`' && c != '$' &&
|
||||
(c != '"' || eofmark != NULL))
|
||||
USTPUTC('\\', out);
|
||||
if (SQSYNTAX[c] == CCTL)
|
||||
USTPUTC(CTLESC, out);
|
||||
else if (eofmark == NULL) {
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
USTPUTC(c, out);
|
||||
if (varnest != 0)
|
||||
USTPUTC(CTLQUOTEEND, out);
|
||||
break;
|
||||
}
|
||||
USTPUTC(c, out);
|
||||
break;
|
||||
case CSQUOTE:
|
||||
if (syntax != SQSYNTAX) {
|
||||
if (eofmark == NULL)
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
syntax = SQSYNTAX;
|
||||
break;
|
||||
if (eofmark == NULL)
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
quotef = 1;
|
||||
syntax = SQSYNTAX;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
/* End of single quotes... */
|
||||
if (arinest)
|
||||
syntax = ARISYNTAX;
|
||||
else {
|
||||
syntax = BASESYNTAX;
|
||||
if (varnest != 0)
|
||||
USTPUTC(CTLQUOTEEND, out);
|
||||
}
|
||||
break;
|
||||
case CDQUOTE:
|
||||
if (eofmark != NULL && arinest == 0 &&
|
||||
varnest == 0) {
|
||||
USTPUTC(c, out);
|
||||
} else {
|
||||
if (arinest) {
|
||||
if (c != '"' || ISDBLQUOTE()) {
|
||||
syntax = ARISYNTAX;
|
||||
CLRDBLQUOTE();
|
||||
} else {
|
||||
syntax = DQSYNTAX;
|
||||
SETDBLQUOTE();
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
}
|
||||
} else if (eofmark == NULL) {
|
||||
if (c != '"' || ISDBLQUOTE()) {
|
||||
syntax = BASESYNTAX;
|
||||
CLRDBLQUOTE();
|
||||
} else {
|
||||
syntax = DQSYNTAX;
|
||||
SETDBLQUOTE();
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
}
|
||||
break;
|
||||
}
|
||||
quotef = 1;
|
||||
if (arinest) {
|
||||
if (ISDBLQUOTE()) {
|
||||
syntax = ARISYNTAX;
|
||||
CLRDBLQUOTE();
|
||||
} else {
|
||||
syntax = DQSYNTAX;
|
||||
SETDBLQUOTE();
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
}
|
||||
quotef++;
|
||||
break;
|
||||
}
|
||||
if (eofmark != NULL)
|
||||
break;
|
||||
if (ISDBLQUOTE()) {
|
||||
if (varnest != 0)
|
||||
USTPUTC(CTLQUOTEEND, out);
|
||||
syntax = BASESYNTAX;
|
||||
CLRDBLQUOTE();
|
||||
} else {
|
||||
syntax = DQSYNTAX;
|
||||
SETDBLQUOTE();
|
||||
USTPUTC(CTLQUOTEMARK, out);
|
||||
}
|
||||
break;
|
||||
case CVAR: /* '$' */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: parser.h,v 1.16 2003/08/07 09:05:37 agc Exp $ */
|
||||
/* $NetBSD: parser.h,v 1.17 2004/06/26 22:09:49 dsl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1991, 1993
|
||||
@ -45,7 +45,8 @@
|
||||
#define CTLARI '\206' /* arithmetic expression */
|
||||
#define CTLENDARI '\207'
|
||||
#define CTLQUOTEMARK '\210'
|
||||
#define CTL_LAST '\210' /* last 'special' character */
|
||||
#define CTLQUOTEEND '\211' /* only inside ${...} */
|
||||
#define CTL_LAST '\211' /* last 'special' character */
|
||||
|
||||
/* variable substitution byte (follows CTLVAR) */
|
||||
#define VSTYPE 0x0f /* type of variable substitution */
|
||||
|
Loading…
Reference in New Issue
Block a user