* 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;

Reply via email to