Imported from ../bash-2.05b.tar.gz.
[platform/upstream/bash.git] / bashhist.c
index b89758a..8090266 100644 (file)
@@ -57,6 +57,8 @@ extern int errno;
 #endif
 
 static int histignore_item_func __P((struct ign *));
+static int check_history_control __P((char *));
+static void really_add_history __P((char *));
 
 static struct ignorevar histignore =
 {
@@ -87,8 +89,8 @@ int history_lines_in_file;
 int history_expansion_inhibited;
 #endif
 
-/* By default, every line is saved in the history individually.  I.e.,
-   if the user enters:
+/* With the old default, every line was saved in the history individually.
+   I.e., if the user enters:
        bash$ for i in a b c
        > do
        > echo $i
@@ -114,9 +116,16 @@ int history_expansion_inhibited;
        11  history
    The user can then recall the whole command all at once instead
    of just being able to recall one line at a time.
+
+   This is now enabled by default.
    */
 int command_oriented_history = 1;
 
+/* Set to 1 if the first line of a possibly-multi-line command was saved
+   in the history list.  Managed by maybe_add_history(), but global so
+   the history-manipluating builtins can see it. */
+int current_command_first_line_saved = 0;
+
 /* Non-zero means to store newlines in the history list when using
    command_oriented_history rather than trying to use semicolons. */
 int literal_history;
@@ -493,26 +502,61 @@ filter_comments (line)
 }
 #endif
 
-/* Add LINE to the history list depending on the value of HISTORY_CONTROL. */
-void
-maybe_add_history (line)
+/* Check LINE against what HISTCONTROL says to do.  Returns 1 if the line
+   should be saved; 0 if it should be discarded. */
+static int
+check_history_control (line)
      char *line;
 {
-  static int first_line_saved = 0;
   HIST_ENTRY *temp;
+  int r;
 
+  switch (history_control)
+    {
+    case 0:                    /* nothing */
+      return 1;
+    case 1:                    /* ignorespace */
+      return (*line != ' ');
+    case 3:                    /* ignoreboth */
+      if (*line == ' ')
+       return 0;
+      /* FALLTHROUGH if case == 3 (`ignoreboth') */
+    case 2:                    /* ignoredups */
+      using_history ();
+      temp = previous_history ();
+
+      r = (temp == 0 || STREQ (temp->line, line) == 0);
+
+      using_history ();
+      return r;
+    }
+
+  return 0;
+}
+
+/* Add LINE to the history list, handling possibly multi-line compound
+   commands.  We note whether or not we save the first line of each command
+   (which is usually the entire command and history entry), and don't add
+   the second and subsequent lines of a multi-line compound command if we
+   didn't save the first line.  We don't usually save shell comment lines in
+   compound commands in the history, because they could have the effect of
+   commenting out the rest of the command when the entire command is saved as
+   a single history entry (when COMMAND_ORIENTED_HISTORY is enabled).  If
+   LITERAL_HISTORY is set, we're saving lines in the history with embedded
+   newlines, so it's OK to save comment lines.  We also make sure to save
+   multiple-line quoted strings or other constructs. */
+void
+maybe_add_history (line)
+     char *line;
+{
   hist_last_line_added = 0;
 
   /* Don't use the value of history_control to affect the second
      and subsequent lines of a multi-line command (old code did
      this only when command_oriented_history is enabled). */
-#if 0
-  if (command_oriented_history && current_command_line_count > 1)
-#else
   if (current_command_line_count > 1)
-#endif
     {
-      if (first_line_saved &&
+      if (current_command_first_line_saved &&
          (literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
        bash_add_history (line);
       return;
@@ -520,36 +564,29 @@ maybe_add_history (line)
 
   /* This is the first line of a (possible multi-line) command.  Note whether
      or not we should save the first line and remember it. */
-  first_line_saved = 0;
+  current_command_first_line_saved = check_add_history (line, 0);
+}
 
-  switch (history_control)
+/* Just check LINE against HISTCONTROL and HISTIGNORE and add it to the
+   history if it's OK.  Used by `history -s' as well as maybe_add_history().
+   Returns 1 if the line was saved in the history, 0 otherwise. */
+int
+check_add_history (line, force)
+     char *line;
+     int force;
+{
+  if (check_history_control (line) && history_should_ignore (line) == 0)
     {
-    case 0:
-      first_line_saved = 1;
-      break;
-    case 1:
-      if (*line != ' ')
-       first_line_saved = 1;
-      break;
-    case 3:
-      if (*line == ' ')
-       break;
-      /* FALLTHROUGH if case == 3 (`ignoreboth') */
-    case 2:
-      using_history ();
-      temp = previous_history ();
-
-      if (temp == 0 || STREQ (temp->line, line) == 0)
-       first_line_saved = 1;
-
-      using_history ();
-      break;
+      if (force)
+       {
+         really_add_history (line);
+         using_history ();
+       }
+      else
+       bash_add_history (line);
+      return 1;
     }
-
-  if (first_line_saved && history_should_ignore (line) == 0)
-    bash_add_history (line);
-  else
-    first_line_saved = 0;
+  return 0;
 }
 
 /* Add a line to the history list.
@@ -607,14 +644,20 @@ bash_add_history (line)
     }
 
   if (add_it)
-    {
-      hist_last_line_added = 1;
-      add_history (line);
-      history_lines_this_session++;
-    }
+    really_add_history (line);
+
   using_history ();
 }
 
+static void
+really_add_history (line)
+     char *line;
+{
+  hist_last_line_added = 1;
+  add_history (line);
+  history_lines_this_session++;
+}
+
 int
 history_number ()
 {