]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fix recogniation of IN token in for command nested within case command
authorChet Ramey <chet.ramey@case.edu>
Mon, 15 Apr 2024 14:11:38 +0000 (10:11 -0400)
committerChet Ramey <chet.ramey@case.edu>
Mon, 15 Apr 2024 14:11:38 +0000 (10:11 -0400)
CWRU/CWRU.chlog
examples/loadables/getconf.c
parse.y
parser.h
shell.h
tests/parser.right
tests/posix2syntax.sub

index 145db0a2d79a43d50aedfc23b4ef692061fa1314..40012ac6e1bc76bfb8c9ecdfa9dd171b576e1a68 100644 (file)
@@ -9155,4 +9155,25 @@ redir.c
          get expanded again.
          Fixes bug reported by squeaky <q7d9y9muja@liamekaens.com>
 
-         
+                                  4/12
+                                  ----
+parse.y
+       - expecting_in_command: new variable, set to FOR or CASE depending on
+         which command is expecting the IN token to follow it
+       - {save,restore}_parser_state: save and restore expecting_in_command
+         in `incmd' member
+       - special_case_tokens: for POSIX rule 6, check expecting_in_token
+         instead of last_read_token/token_before_that for case/for command
+         and whether we should return IN and maybe set PST_CASEPAT
+       - special_case_tokens: reset expecting_in_command before returning DO
+       - read_token_word: set expecting_in_command if last_read_token was
+         CASE or FOR and we are returning a WORD
+       - reset_parser: reset expecting_in_command
+       - parse_comsub,parse_compound_assignment: reset expecting_in_command
+         Fixes bug reported by nbowler@draconx.ca
+
+parser.h
+       - incmd: new member of parser_state, saves and restores the value of
+         expecting_in_command
+       - PST_FORCMD: new parser state, used to say if we're parsing a `for'
+         command and waiting for an IN token (not used yet)
index 56ef257aa349e18995490bcb0d188f389663b35b..c79156e19f355193c4417f9d89e18b9740f65df6 100644 (file)
@@ -1042,12 +1042,12 @@ getconf_all (WORD_LIST *list)
   int r;
 
   r = EXECUTION_SUCCESS;
-  path = list ? list->word->word : 0;
+  path = list ? list->word->word : "/";
   for (c = vars; c->name != NULL; ++c)
     {
+#if 0
       if (c->call == PATHCONF && path == 0)
        continue;       /* Don't print pathconf vars if no path supplied */
-#if 0
       if (c->call != PATHCONF && path)
        continue;       /* Only print pathconf vars if path supplied */
 #endif
diff --git a/parse.y b/parse.y
index d129dd284d4a30df7bf45208b824dc4e530ab884..57a5e98462fd219aee1fba84002f2e85cdcda6c7 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -3035,6 +3035,7 @@ static int esacs_needed_count;
 /* When non-zero, we can read IN as an acceptable token, regardless of how
    many newlines we read. */
 static int expecting_in_token;
+static int expecting_in_command;       /* XXX - maybe save previous? */
 
 static void
 push_heredoc (REDIRECT *r)
@@ -3119,12 +3120,15 @@ static int open_brace_count;
              if (word_token_alist[i].token == ESAC) { \
                parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \
                esacs_needed_count--; \
-             } else if (word_token_alist[i].token == CASE) \
+             } else if (word_token_alist[i].token == CASE) \
                parser_state |= PST_CASESTMT; \
-             else if (word_token_alist[i].token == COND_END) \
+               expecting_in_command = CASE; \
+             } else if (word_token_alist[i].token == COND_END) \
                parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \
              else if (word_token_alist[i].token == COND_START) \
                parser_state |= PST_CONDCMD; \
+             else if (word_token_alist[i].token == FOR)  \
+               expecting_in_command = FOR; \
              else if (word_token_alist[i].token == '{') \
                open_brace_count++; \
              else if (word_token_alist[i].token == '}' && open_brace_count) \
@@ -3300,19 +3304,20 @@ special_case_tokens (const char *tokstr)
   /* Posix grammar rule 6 */
   if ((last_read_token == WORD) &&
 #if defined (SELECT_COMMAND)
-      ((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
+      (token_before_that == FOR || token_before_that == CASE || token_before_that == SELECT) &&
 #else
-      ((token_before_that == FOR) || (token_before_that == CASE)) &&
+      (token_before_that == FOR || token_before_that == CASE) &&
 #endif
       (tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
     {
-      if (token_before_that == CASE)
+      if (expecting_in_command == CASE)
        {
          parser_state |= PST_CASEPAT;
          esacs_needed_count++;
        }
       if (expecting_in_token)
        expecting_in_token--;
+      expecting_in_command = 0;
       return (IN);
     }
 
@@ -3322,12 +3327,13 @@ special_case_tokens (const char *tokstr)
   if (expecting_in_token && (last_read_token == WORD || last_read_token == '\n') &&
       (tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
     {
-      if (parser_state & PST_CASESTMT)
+      if (expecting_in_command == CASE && (parser_state & PST_CASESTMT))
        {
          parser_state |= PST_CASEPAT;
          esacs_needed_count++;
        }
       expecting_in_token--;
+      expecting_in_command = 0;
       return (IN);
     }
   /* Posix grammar rule 6, third word in FOR: for i; do command-list; done */
@@ -3335,6 +3341,7 @@ special_case_tokens (const char *tokstr)
     (tokstr[0] == 'd' && tokstr[1] == 'o' && tokstr[2] == '\0'))
     {
       expecting_in_token--;
+      expecting_in_command = 0;
       return (DO);
     }
 
@@ -3349,6 +3356,7 @@ special_case_tokens (const char *tokstr)
     {
       if (expecting_in_token)
        expecting_in_token--;
+      expecting_in_command = 0;
       return (DO);
     }
 
@@ -3457,6 +3465,7 @@ reset_parser (void)
   need_here_doc = 0;
   redir_stack[0] = 0;
   esacs_needed_count = expecting_in_token = 0;
+  expecting_in_command = 0;
 
   simplecmd_lineno = line_number;
 
@@ -4422,8 +4431,9 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
 
   /* State flags we don't want to persist into command substitutions. */
   parser_state &= ~(PST_REGEXP|PST_EXTPAT|PST_CONDCMD|PST_CONDEXPR|PST_COMPASSIGN);
-  /* Could do PST_CASESTMT too, but that also affects history. Setting
-     expecting_in_token below should take care of the parsing requirements.
+  /* Could do PST_CASESTMT too, but that also affects history. Ditto for
+     PST_FORCMD. Setting expecting_in_token and expecting_in_command below
+     should take care of the parsing requirements.
      Unsetting PST_REDIRLIST isn't strictly necessary because of how we set
      token_to_read below, but we do it anyway. */
   parser_state &= ~(PST_CASEPAT|PST_ALEXPNEXT|PST_SUBSHELL|PST_REDIRLIST);
@@ -4442,6 +4452,7 @@ parse_comsub (int qc, int open, int close, size_t *lenp, int flags)
   /* These are reset by reset_parser() */
   need_here_doc = 0;
   esacs_needed_count = expecting_in_token = 0;
+  expecting_in_command = 0;
 
   /* We want to expand aliases on this pass if we're in posix mode, since the
      standard says you have to take aliases into account when looking for the
@@ -5763,8 +5774,9 @@ got_token:
       function_dstart = line_number;
       break;
     case CASE:
-    case SELECT:
     case FOR:
+      expecting_in_command = last_read_token;
+    case SELECT:
       expecting_in_token++;
       break;
     }
@@ -6996,6 +7008,7 @@ parse_compound_assignment (size_t *retlenp)
   parser_state |= PST_COMPASSIGN;
 
   esacs_needed_count = expecting_in_token = 0;
+  expecting_in_command = 0;
 
   /* We're not pushing any new input here, we're reading from the current input
      source. If that's an alias, we have to be prepared for the alias to get
@@ -7126,6 +7139,7 @@ save_parser_state (sh_parser_state_t *ps)
 
   ps->esacs_needed = esacs_needed_count;
   ps->expecting_in = expecting_in_token;
+  ps->incmd = expecting_in_command;
 
   if (need_here_doc == 0)
     ps->redir_stack[0] = 0;
@@ -7190,6 +7204,7 @@ restore_parser_state (sh_parser_state_t *ps)
 
   esacs_needed_count = ps->esacs_needed;
   expecting_in_token = ps->expecting_in;
+  expecting_in_command = ps->incmd;
 
 #if 0
   for (i = 0; i < HEREDOC_MAX; i++)
index bef71707fbdca041ce3c5fad67ead9a49e5169c1..ccfc8e16bcad363c4a42ff6dbe248a3712925645 100644 (file)
--- a/parser.h
+++ b/parser.h
@@ -53,6 +53,7 @@
 #define PST_STRING     0x1000000       /* parsing a string to a command or word list */
 #define PST_CMDBLTIN   0x2000000       /* last token was the `command' builtin */
 #define PST_FUNSUBST   0x4000000       /* parsing a foreground command substitution */
+#define PST_FORCMD     0x8000000       /* parsing for command -- not used yet */
 
 /* Definition of the delimiter stack.  Needed by parse.y and bashhist.c. */
 struct dstack {
diff --git a/shell.h b/shell.h
index b9d259a515e9216953e4f7c42194ccbabdac7370..d81db2175540178fb11d0862a268ff6bd45ac7db 100644 (file)
--- a/shell.h
+++ b/shell.h
@@ -215,6 +215,7 @@ typedef struct _sh_parser_state_t
 
   int esacs_needed;
   int expecting_in;
+  int incmd;
 
   /* structures affecting the parser */
   void *pushed_strings;
index e0cdfac7a799f324031c2679ddd5baa009ab560a..6424dba60ffc0210f540274b94394e4eacc3372c 100644 (file)
@@ -15,3 +15,6 @@ bash5: -c: line 1: `for()'
 in
 done
 ok 1
+x
+x
+x
index 39af9a55febd02928ab255dd4cb7fc9c27592064..e2c2368f04a5700d037a5e5eaeb93e39d31cb3a9 100644 (file)
@@ -63,4 +63,39 @@ in
        foo) echo "ok 1";;
 esac' $bashname
 
+# POSIX grammar rule 6 with <linebreak> consisting of multiple newlines and
+# nested case and for commands
+
+case x in x)
+for x
+in x
+do
+echo $x
+done
+esac
+
+# need to recognize IN here
+case x in x)
+for x
+
+
+in x
+do
+echo $x
+done
+esac
+
+# recognize both IN and DO
+case x in x)
+for x
+
+
+in x
+
+
+
+do
+echo $x
+done
+esac