Imported from ../bash-3.2.tar.gz.
[platform/upstream/bash.git] / parse.y
diff --git a/parse.y b/parse.y
index 1e7bd27..c7dd436 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -1,6 +1,6 @@
 /* Yacc grammar for bash. */
 
-/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2006 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -118,7 +118,6 @@ extern int current_command_number;
 extern int sourcelevel;
 extern int posixly_correct;
 extern int last_command_exit_value;
-extern int interrupt_immediately;
 extern char *shell_name, *current_host_name;
 extern char *dist_version;
 extern int patch_level;
@@ -206,10 +205,6 @@ static void reset_readline_prompt __P((void));
 #endif
 static void print_prompt __P((void));
 
-#if defined (HISTORY)
-char *history_delimiting_chars __P((void));
-#endif
-
 #if defined (HANDLE_MULTIBYTE)
 static void set_line_mbstate __P((void));
 static char *shell_input_line_property = NULL;
@@ -1212,10 +1207,12 @@ yy_readline_get ()
          old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
          interrupt_immediately++;
        }
+      terminate_immediately = 1;
 
       current_readline_line = readline (current_readline_prompt ?
                                          current_readline_prompt : "");
 
+      terminate_immediately = 0;
       if (signal_is_ignored (SIGINT) == 0 && old_sigint)
        {
          interrupt_immediately--;
@@ -1347,10 +1344,16 @@ yy_stream_get ()
   if (bash_input.location.file)
     {
       if (interactive)
-       interrupt_immediately++;
+       {
+         interrupt_immediately++;
+         terminate_immediately++;
+       }
       result = getc_with_restart (bash_input.location.file);
       if (interactive)
-       interrupt_immediately--;
+       {
+         interrupt_immediately--;
+         terminate_immediately--;
+       }
     }
   return (result);
 }
@@ -1869,7 +1872,6 @@ shell_getc (remove_quoted_newline)
   register int i;
   int c;
   unsigned char uc;
-  static int mustpop = 0;
 
   QUIT;
 
@@ -2142,8 +2144,8 @@ discard_until (character)
 }
 
 void
-execute_prompt_command (command)
-     char *command;
+execute_variable_command (command, vname)
+     char *command, *vname;
 {
   char *last_lastarg;
   sh_parser_state_t ps;
@@ -2153,7 +2155,7 @@ execute_prompt_command (command)
   if (last_lastarg)
     last_lastarg = savestring (last_lastarg);
 
-  parse_and_execute (savestring (command), "PROMPT_COMMAND", SEVAL_NONINT|SEVAL_NOHIST);
+  parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST);
 
   restore_parser_state (&ps);
   bind_variable ("_", last_lastarg, 0);
@@ -2556,7 +2558,7 @@ read_token (command)
 #endif /* ALIAS */
 
   /* Read a single word from input.  Start by skipping blanks. */
-  while ((character = shell_getc (1)) != EOF && whitespace (character))
+  while ((character = shell_getc (1)) != EOF && shellblank (character))
     ;
 
   if (character == EOF)
@@ -2716,6 +2718,7 @@ read_token (command)
 #define P_ALLOWESC     0x02
 #define P_DQUOTE       0x04
 #define P_COMMAND      0x08    /* parsing a command, so look for comments */
+#define P_BACKQUOTE    0x10    /* parsing a backquoted command substitution */
 
 static char matched_pair_error;
 static char *
@@ -2725,12 +2728,13 @@ parse_matched_pair (qc, open, close, lenp, flags)
      int *lenp, flags;
 {
   int count, ch, was_dollar, in_comment, check_comment;
-  int pass_next_character, nestlen, ttranslen, start_lineno;
+  int pass_next_character, backq_backslash, nestlen, ttranslen, start_lineno;
   char *ret, *nestret, *ttrans;
   int retind, retsize, rflags;
 
+/* itrace("parse_matched_pair: open = %c close = %c", open, close); */
   count = 1;
-  pass_next_character = was_dollar = in_comment = 0;
+  pass_next_character = backq_backslash = was_dollar = in_comment = 0;
   check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
 
   /* RFLAGS is the set of flags we want to pass to recursive calls. */
@@ -2742,11 +2746,8 @@ parse_matched_pair (qc, open, close, lenp, flags)
   start_lineno = line_number;
   while (count)
     {
-#if 0
-      ch = shell_getc ((qc != '\'' || (flags & P_ALLOWESC)) && pass_next_character == 0);
-#else
-      ch = shell_getc (qc != '\'' && pass_next_character == 0);
-#endif
+      ch = shell_getc (qc != '\'' && pass_next_character == 0 && backq_backslash == 0);
+
       if (ch == EOF)
        {
          free (ret);
@@ -2770,10 +2771,19 @@ parse_matched_pair (qc, open, close, lenp, flags)
 
          continue;
        }
-      /* Not exactly right yet */
-      else if (check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind -1])))
+      /* Not exactly right yet, should handle shell metacharacters, too.  If
+        any changes are made to this test, make analogous changes to subst.c:
+        extract_delimited_string(). */
+      else if MBTEST(check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind - 1])))
        in_comment = 1;
 
+      /* last char was backslash inside backquoted command substitution */
+      if (backq_backslash)
+       {
+         backq_backslash = 0;
+         /* Placeholder for adding special characters */
+       }
+
       if (pass_next_character)         /* last char was backslash */
        {
          pass_next_character = 0;
@@ -2798,11 +2808,9 @@ parse_matched_pair (qc, open, close, lenp, flags)
        }
       else if MBTEST(ch == close)              /* ending delimiter */
        count--;
-#if 1
       /* handle nested ${...} specially. */
       else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
        count++;
-#endif
       else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open)      /* nested begin */
        count++;
 
@@ -2814,6 +2822,10 @@ parse_matched_pair (qc, open, close, lenp, flags)
        {
          if MBTEST((flags & P_ALLOWESC) && ch == '\\')
            pass_next_character++;
+#if 0
+         else if MBTEST((flags & P_BACKQUOTE) && ch == '\\')
+           backq_backslash++;
+#endif
          continue;
        }
 
@@ -2896,18 +2908,24 @@ add_nestret:
            }
          FREE (nestret);
        }
+#if 0
       else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
        {
-         nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags);
+         /* Add P_BACKQUOTE so backslash quotes the next character and
+            shell_getc does the right thing with \<newline>.  We do this for
+            a measure  of backwards compatibility -- it's not strictly the
+            right POSIX thing. */
+         nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags|P_BACKQUOTE);
          goto add_nestret;
        }
-      else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '['))      /* ) } ] */
+#endif
+      else if MBTEST(open != '`' && was_dollar && (ch == '(' || ch == '{' || ch == '['))       /* ) } ] */
        /* check for $(), $[], or ${} inside quoted string. */
        {
          if (open == ch)       /* undo previous increment */
            count--;
          if (ch == '(')                /* ) */
-           nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags);
+           nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE);
          else if (ch == '{')           /* } */
            nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
          else if (ch == '[')           /* ] */
@@ -2933,8 +2951,8 @@ static int
 parse_dparen (c)
      int c;
 {
-  int cmdtyp, len, sline;
-  char *wval, *wv2;
+  int cmdtyp, sline;
+  char *wval;
   WORD_DESC *wd;
 
 #if defined (ARITH_FOR_COMMAND)
@@ -2946,7 +2964,6 @@ parse_dparen (c)
        {
          wd = alloc_word_desc ();
          wd->word = wval;
-         wd = make_word (wval);
          yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
          return (ARITH_FOR_EXPRS);
        }
@@ -3496,7 +3513,7 @@ read_token_word (character)
                }
              else
                {
-                 /* Try to locale)-expand the converted string. */
+                 /* Try to locale-expand the converted string. */
                  ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
                  free (ttok);
 
@@ -3578,7 +3595,7 @@ read_token_word (character)
              FREE (ttok);
              all_digit_token = 0;
              compound_assignment = 1;
-#if 0
+#if 1
              goto next_character;
 #else
              goto got_token;           /* ksh93 seems to do this */
@@ -3676,8 +3693,8 @@ got_token:
   if (dollar_present)
     the_word->flags |= W_HASDOLLAR;
   if (quoted)
-    the_word->flags |= W_QUOTED;
-  if (compound_assignment)
+    the_word->flags |= W_QUOTED;               /*(*/
+  if (compound_assignment && token[token_index-1] == ')')
     the_word->flags |= W_COMPASSIGN;
   /* A word is an assignment if it appears at the beginning of a
      simple command, or after another assignment word.  This is
@@ -3695,7 +3712,9 @@ got_token:
       struct builtin *b;
       b = builtin_address_internal (token, 0);
       if (b && (b->flags & ASSIGNMENT_BUILTIN))
-        parser_state |= PST_ASSIGNOK;
+       parser_state |= PST_ASSIGNOK;
+      else if (STREQ (token, "eval") || STREQ (token, "let"))
+       parser_state |= PST_ASSIGNOK;
     }
 
   yylval.word = the_word;
@@ -3974,7 +3993,7 @@ decode_prompt_string (string)
   int last_exit_value;
 #if defined (PROMPT_STRING_DECODE)
   int result_size, result_index;
-  int c, n;
+  int c, n, i;
   char *temp, octal_string[4];
   struct tm *tm;  
   time_t the_time;
@@ -4136,7 +4155,7 @@ decode_prompt_string (string)
            case 'W':
              {
                /* Use the value of PWD because it is much more efficient. */
-               char t_string[PATH_MAX], *t;
+               char t_string[PATH_MAX];
                int tlen;
 
                temp = get_string_value ("PWD");
@@ -4246,9 +4265,12 @@ decode_prompt_string (string)
                  break;
                }
              temp = (char *)xmalloc (3);
-             temp[0] = '\001';
-             temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
-             temp[2] = '\0';
+             n = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
+             i = 0;
+             if (n == CTLESC || n == CTLNUL)
+               temp[i++] = CTLESC;
+             temp[i++] = n;
+             temp[i] = '\0';
              goto add_string;
 #endif /* READLINE */
 
@@ -4344,15 +4366,15 @@ yyerror (msg)
 }
 
 static char *
-error_token_from_token (token)
-     int token;
+error_token_from_token (tok)
+     int tok;
 {
   char *t;
 
-  if (t = find_token_in_alist (token, word_token_alist, 0))
+  if (t = find_token_in_alist (tok, word_token_alist, 0))
     return t;
 
-  if (t = find_token_in_alist (token, other_token_alist, 0))
+  if (t = find_token_in_alist (tok, other_token_alist, 0))
     return t;
 
   t = (char *)NULL;
@@ -4686,18 +4708,21 @@ parse_compound_assignment (retlenp)
      int *retlenp;
 {
   WORD_LIST *wl, *rl;
-  int tok, orig_line_number, orig_token_size;
+  int tok, orig_line_number, orig_token_size, orig_last_token, assignok;
   char *saved_token, *ret;
 
   saved_token = token;
   orig_token_size = token_buffer_size;
   orig_line_number = line_number;
+  orig_last_token = last_read_token;
 
   last_read_token = WORD;      /* WORD to allow reserved words here */
 
   token = (char *)NULL;
   token_buffer_size = 0;
 
+  assignok = parser_state&PST_ASSIGNOK;                /* XXX */
+
   wl = (WORD_LIST *)NULL;      /* ( */
   parser_state |= PST_COMPASSIGN;
 
@@ -4740,7 +4765,8 @@ parse_compound_assignment (retlenp)
        jump_to_top_level (DISCARD);
     }
 
-  last_read_token = WORD;
+  last_read_token = orig_last_token;           /* XXX - was WORD? */
+
   if (wl)
     {
       rl = REVERSE_LIST (wl, WORD_LIST *);
@@ -4752,6 +4778,10 @@ parse_compound_assignment (retlenp)
 
   if (retlenp)
     *retlenp = (ret && *ret) ? strlen (ret) : 0;
+
+  if (assignok)
+    parser_state |= PST_ASSIGNOK;
+
   return ret;
 }