summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/ksh/lex.c19
-rw-r--r--bin/ksh/lex.h3
-rw-r--r--bin/ksh/tests/unclass2.t110
3 files changed, 128 insertions, 4 deletions
diff --git a/bin/ksh/lex.c b/bin/ksh/lex.c
index 73e5610eeb3..01aa6863c3b 100644
--- a/bin/ksh/lex.c
+++ b/bin/ksh/lex.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lex.c,v 1.46 2013/01/20 14:47:46 stsp Exp $ */
+/* $OpenBSD: lex.c,v 1.47 2013/03/03 19:11:34 guenther Exp $ */
/*
* lexical analysis and source input
@@ -113,7 +113,7 @@ yylex(int cf)
Again:
states[0].ls_state = -1;
- states[0].ls_info.base = (Lex_state *) 0;
+ states[0].ls_info.base = NULL;
statep = &states[1];
state_info.base = states;
state_info.end = &states[STATE_BSIZE];
@@ -270,6 +270,10 @@ yylex(int cf)
*wp++ = QCHAR, *wp++ = c;
break;
case '\'':
+ if ((cf & HEREDOC) || state == SBRACEQ) {
+ *wp++ = CHAR, *wp++ = c;
+ break;
+ }
*wp++ = OQUOTE;
ignore_backslash_newline++;
PUSH_STATE(SSQUOTE);
@@ -346,7 +350,11 @@ yylex(int cf)
PUSH_STATE(STBRACE);
} else {
ungetsc(c);
- PUSH_STATE(SBRACE);
+ if (state == SDQUOTE ||
+ state == SBRACEQ)
+ PUSH_STATE(SBRACEQ);
+ else
+ PUSH_STATE(SBRACE);
}
} else if (ctype(c, C_ALPHA)) {
*wp++ = OSUBST;
@@ -423,6 +431,10 @@ yylex(int cf)
case SSQUOTE:
if (c == '\'') {
POP_STATE();
+ if (state == SBRACEQ) {
+ *wp++ = CHAR, *wp++ = c;
+ break;
+ }
*wp++ = CQUOTE;
ignore_backslash_newline--;
} else
@@ -529,6 +541,7 @@ yylex(int cf)
*wp++ = c;
break;
+ case SBRACEQ:
case SBRACE:
/*{*/
if (c == '}') {
diff --git a/bin/ksh/lex.h b/bin/ksh/lex.h
index 0b2f2a2cae3..12d76769e46 100644
--- a/bin/ksh/lex.h
+++ b/bin/ksh/lex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lex.h,v 1.12 2013/01/20 14:47:46 stsp Exp $ */
+/* $OpenBSD: lex.h,v 1.13 2013/03/03 19:11:34 guenther Exp $ */
/*
* Source input, lexer and parser
@@ -64,6 +64,7 @@ struct source {
#define SHEREDQUOTE 10 /* parsing " in <<,<<- delimiter */
#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */
#define STBRACE 12 /* parsing ${..[#%]..} */
+#define SBRACEQ 13 /* inside "${}" */
typedef union {
int i;
diff --git a/bin/ksh/tests/unclass2.t b/bin/ksh/tests/unclass2.t
index 56be75156b9..bdd8c362cfd 100644
--- a/bin/ksh/tests/unclass2.t
+++ b/bin/ksh/tests/unclass2.t
@@ -161,3 +161,113 @@ expected-stderr: !
XX
---
+name: single-quotes-in-braces
+description:
+ Check that single quotes inside unquoted {} are treated as quotes
+stdin:
+ foo=1
+ echo ${foo:+'blah $foo'}
+expected-stdout:
+ blah $foo
+---
+
+name: single-quotes-in-quoted-braces
+description:
+ Check that single quotes inside quoted {} are treated as
+ normal char
+stdin:
+ foo=1
+ echo "${foo:+'blah $foo'}"
+expected-stdout:
+ 'blah 1'
+---
+
+name: single-quotes-in-braces-nested
+description:
+ Check that single quotes inside unquoted {} are treated as quotes,
+ even if that's inside a double-quoted command expansion
+stdin:
+ foo=1
+ echo "$( echo ${foo:+'blah $foo'})"
+expected-stdout:
+ blah $foo
+---
+
+name: single-quotes-in-brace-pattern
+description:
+ Check that single quotes inside {} pattern are treated as quotes
+stdin:
+ foo=1234
+ echo ${foo%'2'*} "${foo%'2'*}" ${foo%2'*'} "${foo%2'*'}"
+expected-stdout:
+ 1 1 1234 1234
+---
+
+name: single-quotes-in-heredoc-braces
+description:
+ Check that single quotes inside {} in heredoc are treated
+ as normal char
+stdin:
+ foo=1
+ cat <<EOM
+ ${foo:+'blah $foo'}
+ EOM
+expected-stdout:
+ 'blah 1'
+---
+
+name: single-quotes-in-nested-braces
+description:
+ Check that single quotes inside nested unquoted {} are
+ treated as quotes
+stdin:
+ foo=1
+ echo ${foo:+${foo:+'blah $foo'}}
+expected-stdout:
+ blah $foo
+---
+
+name: single-quotes-in-nested-quoted-braces
+description:
+ Check that single quotes inside nested quoted {} are treated
+ as normal char
+stdin:
+ foo=1
+ echo "${foo:+${foo:+'blah $foo'}}"
+expected-stdout:
+ 'blah 1'
+---
+
+name: single-quotes-in-nested-braces-nested
+description:
+ Check that single quotes inside nested unquoted {} are treated
+ as quotes, even if that's inside a double-quoted command expansion
+stdin:
+ foo=1
+ echo "$( echo ${foo:+${foo:+'blah $foo'}})"
+expected-stdout:
+ blah $foo
+---
+
+name: single-quotes-in-nested-brace-pattern
+description:
+ Check that single quotes inside nested {} pattern are treated as quotes
+stdin:
+ foo=1234
+ echo ${foo:+${foo%'2'*}} "${foo:+${foo%'2'*}}" ${foo:+${foo%2'*'}} "${foo:+${foo%2'*'}}"
+expected-stdout:
+ 1 1 1234 1234
+---
+
+name: single-quotes-in-heredoc-nested-braces
+description:
+ Check that single quotes inside nested {} in heredoc are treated
+ as normal char
+stdin:
+ foo=1
+ cat <<EOM
+ ${foo:+${foo:+'blah $foo'}}
+ EOM
+expected-stdout:
+ 'blah 1'
+---