summaryrefslogtreecommitdiffstats
path: root/bin/sh/parser.c
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2010-10-29 13:42:18 +0000
committerjilles <jilles@FreeBSD.org>2010-10-29 13:42:18 +0000
commit28ad180ab428c06679f4d2e8422bfb77ae2a926c (patch)
treea904801ee278e1d897c3118d8e675fd52f1a7856 /bin/sh/parser.c
parentb6cd17990d125d91ed9a1a32e708c186c2fd3945 (diff)
downloadFreeBSD-src-28ad180ab428c06679f4d2e8422bfb77ae2a926c.zip
FreeBSD-src-28ad180ab428c06679f4d2e8422bfb77ae2a926c.tar.gz
sh: Do IFS splitting on word in ${v+word} and ${v-word}.
The code is inspired by NetBSD sh somewhat, but different because we preserve the old Almquist/Bourne/Korn ability to have an unquoted part in a quoted ${v+word}. For example, "${v-"*"}" expands to $v as a single field if v is set, but generates filenames otherwise. Note that this is the only place where we split text literally from the script (the similar ${v=word} assigns to v and then expands $v). The parser must now add additional markers to allow the expansion code to know whether arbitrary characters in substitutions are quoted. Example: for i in ${$+a b c}; do echo $i; done Exp-run done by: pav (with some other sh(1) changes)
Diffstat (limited to 'bin/sh/parser.c')
-rw-r--r--bin/sh/parser.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index 07e6e72..64dcb40 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -1161,7 +1161,7 @@ readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
loop: { /* for each line, until end of word */
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 */
synentry = state[level].syntax[c];
@@ -1203,12 +1203,18 @@ readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
newvarnest == 0)) &&
(c != '}' || state[level].category != TSTATE_VAR_OLD))
USTPUTC('\\', out);
+ if ((eofmark == NULL ||
+ newvarnest > 0) &&
+ state[level].syntax == BASESYNTAX)
+ USTPUTC(CTLQUOTEMARK, out);
if (SQSYNTAX[c] == CCTL)
USTPUTC(CTLESC, out);
- else if (eofmark == NULL ||
- newvarnest > 0)
- USTPUTC(CTLQUOTEMARK, out);
USTPUTC(c, out);
+ if ((eofmark == NULL ||
+ newvarnest > 0) &&
+ state[level].syntax == BASESYNTAX &&
+ state[level].category == TSTATE_VAR_OLD)
+ USTPUTC(CTLQUOTEEND, out);
quotef++;
}
break;
@@ -1224,6 +1230,8 @@ readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
if (eofmark != NULL && newvarnest == 0)
USTPUTC(c, out);
else {
+ if (state[level].category == TSTATE_VAR_OLD)
+ USTPUTC(CTLQUOTEEND, out);
state[level].syntax = BASESYNTAX;
quotef++;
}
OpenPOWER on IntegriCloud