diff options
author | jilles <jilles@FreeBSD.org> | 2010-10-29 13:42:18 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2010-10-29 13:42:18 +0000 |
commit | 28ad180ab428c06679f4d2e8422bfb77ae2a926c (patch) | |
tree | a904801ee278e1d897c3118d8e675fd52f1a7856 /bin/sh/parser.c | |
parent | b6cd17990d125d91ed9a1a32e708c186c2fd3945 (diff) | |
download | FreeBSD-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.c | 16 |
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++; } |