* Philip Guenther <guent...@gmail.com> [120812 18:50]: > On Sun, 12 Aug 2012, Alexander Polakov wrote: > Below is an expansion of your diff for tests/unclass2.t to cover the cases > discussed in this thread plus a couple others. > > > As for how to get the fix to cover all those cases: the heredoc case can > be handled by changing the added test to > if ((cf & HEREDOC) || state == SBRACE) > > ...but it needs to be something like > if ((cf & HEREDOC) || (state == SBRACE && is_in_double_quotes)) > > with "is_in_double_quotes" some magic to differentiate between the > "${foo+'bar'}" and ${foo+'bar'} cases. That presumably involves walking > up the statep list, but that has to stop when it hits a wrapping > command-expansion. For example, the third new test in the diff below: > echo "$( echo ${foo:+'blah $foo'})" > that should output > blah $foo
Ok, second attempt Index: lex.c =================================================================== RCS file: /cvs/src/bin/ksh/lex.c,v retrieving revision 1.45 diff -u -r1.45 lex.c --- lex.c 9 Mar 2011 09:30:39 -0000 1.45 +++ lex.c 12 Aug 2012 19:13:12 -0000 @@ -113,7 +113,7 @@ Again: states[0].ls_state = -1; - states[0].ls_info.base = (Lex_state *) 0; + states[0].ls_info.base = (Lex_state *) NULL; statep = &states[1]; state_info.base = states; state_info.end = &states[STATE_BSIZE]; @@ -270,6 +270,10 @@ *wp++ = QCHAR, *wp++ = c; break; case '\'': + if ((cf & HEREDOC) || state == SBRACEQ) { + *wp++ = CHAR, *wp++ = c; + break; + } *wp++ = OQUOTE; ignore_backslash_newline++; PUSH_STATE(SSQUOTE); @@ -342,7 +346,10 @@ PUSH_STATE(STBRACE); } else { ungetsc(c); - PUSH_STATE(SBRACE); + if (state == SDQUOTE) + PUSH_STATE(SBRACEQ); + else + PUSH_STATE(SBRACE); } } else if (ctype(c, C_ALPHA)) { *wp++ = OSUBST; @@ -419,6 +426,10 @@ case SSQUOTE: if (c == '\'') { POP_STATE(); + if (state == SBRACEQ) { + *wp++ = CHAR, *wp++ = c; + break; + } *wp++ = CQUOTE; ignore_backslash_newline--; } else @@ -525,6 +536,7 @@ *wp++ = c; break; + case SBRACEQ: case SBRACE: /*{*/ if (c == '}') { Index: lex.h =================================================================== RCS file: /cvs/src/bin/ksh/lex.h,v retrieving revision 1.11 diff -u -r1.11 lex.h --- lex.h 29 May 2006 18:22:24 -0000 1.11 +++ lex.h 12 Aug 2012 19:13:12 -0000 @@ -51,19 +51,20 @@ /* * states while lexing word */ -#define SBASE 0 /* outside any lexical constructs */ -#define SWORD 1 /* implicit quoting for substitute() */ -#define SLETPAREN 2 /* inside (( )), implicit quoting */ -#define SSQUOTE 3 /* inside '' */ -#define SDQUOTE 4 /* inside "" */ -#define SBRACE 5 /* inside ${} */ -#define SCSPAREN 6 /* inside $() */ -#define SBQUOTE 7 /* inside `` */ -#define SASPAREN 8 /* inside $(( )) */ -#define SHEREDELIM 9 /* parsing <<,<<- delimiter */ -#define SHEREDQUOTE 10 /* parsing " in <<,<<- delimiter */ -#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */ -#define STBRACE 12 /* parsing ${..[#%]..} */ +#define SBASE 0 /* outside any lexical constructs */ +#define SWORD 1 /* implicit quoting for substitute() */ +#define SLETPAREN 2 /* inside (( )), implicit quoting */ +#define SSQUOTE 3 /* inside '' */ +#define SDQUOTE 4 /* inside "" */ +#define SBRACE 5 /* inside ${} */ +#define SBRACEQ 6 /* inside "${}" */ +#define SCSPAREN 7 /* inside $() */ +#define SBQUOTE 8 /* inside `` */ +#define SASPAREN 9 /* inside $(( )) */ +#define SHEREDELIM 10 /* parsing <<,<<- delimiter */ +#define SHEREDQUOTE 11 /* parsing " in <<,<<- delimiter */ +#define SPATTERN 12 /* parsing *(...|...) pattern (*+?@!) */ +#define STBRACE 13 /* parsing ${..[#%]..} */ typedef union { int i;