diff options
-rw-r--r-- | bin/ksh/lex.c | 19 | ||||
-rw-r--r-- | bin/ksh/lex.h | 3 | ||||
-rw-r--r-- | bin/ksh/tests/unclass2.t | 110 |
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' +--- |