summaryrefslogtreecommitdiffstats
path: root/bin/sh
diff options
context:
space:
mode:
authorjilles <jilles@FreeBSD.org>2011-03-13 20:02:39 +0000
committerjilles <jilles@FreeBSD.org>2011-03-13 20:02:39 +0000
commit161663c247c528c78fb3d3ec62b4d826259dd707 (patch)
treef8703bdb3bbcc10652390ec6b284f73b32c8f503 /bin/sh
parenteed23027f077c062772ce762806a18153a55cb4b (diff)
downloadFreeBSD-src-161663c247c528c78fb3d3ec62b4d826259dd707.zip
FreeBSD-src-161663c247c528c78fb3d3ec62b4d826259dd707.tar.gz
sh: Fix some parameter expansion variants ${#...}.
These already worked: $# ${#} ${##} ${#-} ${#?} These now work as well: ${#+word} ${#-word} ${##word} ${#%word} There is an ambiguity in the standard with ${#?}: it could be the length of $? or it could be $# giving an error in the (impossible) case that it is not set. We continue to use the former interpretation as it seems more useful.
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/parser.c49
1 files changed, 30 insertions, 19 deletions
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index f883dff..075c04d 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -1447,6 +1447,7 @@ parsesub: {
int bracketed_name = 0; /* used to handle ${[0-9]*} variables */
int linno;
int length;
+ int c1;
c = pgetc();
if (c != '(' && c != '{' && (is_eof(c) || !is_name(c)) &&
@@ -1473,15 +1474,9 @@ parsesub: {
if (c == '{') {
bracketed_name = 1;
c = pgetc();
- if (c == '#') {
- if ((c = pgetc()) == '}')
- c = '#';
- else
- subtype = VSLENGTH;
- }
- else
- subtype = 0;
+ subtype = 0;
}
+varname:
if (!is_eof(c) && is_name(c)) {
length = 0;
do {
@@ -1511,19 +1506,35 @@ parsesub: {
STPUTC(c, out);
c = pgetc();
}
- } else {
- if (! is_special(c)) {
- subtype = VSERROR;
- if (c == '}')
- pungetc();
- else if (c == '\n' || c == PEOF)
- synerror("Unexpected end of line in substitution");
- else
- USTPUTC(c, out);
- } else {
- USTPUTC(c, out);
+ } else if (is_special(c)) {
+ c1 = c;
+ c = pgetc();
+ if (subtype == 0 && c1 == '#') {
+ subtype = VSLENGTH;
+ if (strchr(types, c) == NULL && c != ':' &&
+ c != '#' && c != '%')
+ goto varname;
+ c1 = c;
c = pgetc();
+ if (c1 != '}' && c == '}') {
+ pungetc();
+ c = c1;
+ goto varname;
+ }
+ pungetc();
+ c = c1;
+ c1 = '#';
+ subtype = 0;
}
+ USTPUTC(c1, out);
+ } else {
+ subtype = VSERROR;
+ if (c == '}')
+ pungetc();
+ else if (c == '\n' || c == PEOF)
+ synerror("Unexpected end of line in substitution");
+ else
+ USTPUTC(c, out);
}
if (subtype == 0) {
switch (c) {
OpenPOWER on IntegriCloud