diff options
author | jilles <jilles@FreeBSD.org> | 2011-03-13 20:02:39 +0000 |
---|---|---|
committer | jilles <jilles@FreeBSD.org> | 2011-03-13 20:02:39 +0000 |
commit | 161663c247c528c78fb3d3ec62b4d826259dd707 (patch) | |
tree | f8703bdb3bbcc10652390ec6b284f73b32c8f503 /bin | |
parent | eed23027f077c062772ce762806a18153a55cb4b (diff) | |
download | FreeBSD-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')
-rw-r--r-- | bin/sh/parser.c | 49 |
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) { |