]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20060517 snapshot
authorChet Ramey <chet.ramey@case.edu>
Sun, 4 Dec 2011 03:48:33 +0000 (22:48 -0500)
committerChet Ramey <chet.ramey@case.edu>
Sun, 4 Dec 2011 03:48:33 +0000 (22:48 -0500)
14 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
execute_cmd.c
execute_cmd.c~
lib/readline/history.c
lib/readline/history.c~ [new file with mode: 0644]
lib/readline/rlprivate.h
lib/readline/rlprivate.h~ [new file with mode: 0644]
lib/readline/undo.c
lib/readline/undo.c~ [new file with mode: 0644]
locale.c
locale.c~ [new file with mode: 0644]
shell.c
variables.c~

index 3bf355c2d5c3056edd29985cd8581dea937ea2c9..543128612c6e7be2bb39b1fdd1f43932537616bf 100644 (file)
@@ -13384,3 +13384,38 @@ subst.c
 doc/{bash.1,bashref.texi}
        - clarifed `trap' description to make it clear that trapped signals
          that are not set to SIG_IGN are reset when a subshell is created
+
+                                  5/18
+                                  ----
+locale.c
+       - change reset_locale_vars to call setlocale (LC_ALL, "") if LANG
+         is unset or NULL
+       - if LANG is unset or NULL, reset the export environment before
+         calling setlocale in reset_locale_vars, and trust that it will
+         change the environment setlocale() inspects
+
+                                  5/21
+                                  ----
+lib/readline/history.c
+       - new function, HIST_ENTRY *alloc_history_entry (char *string, char *ts);
+         creates a new history entry with text STRING and timestamp TS (both
+         of which may be NULL)
+       - new function, HIST_ENTRY *copy_history_entry (HIST_ENTRY *hist),
+         which copies the line and timestamp entries to new memory but just
+         copies the data member, since that's an opaque pointer
+       - new function, void replace_history_data (int which, histdata_t *old, histdata_t *new)
+         which replaces the `data' member of specified history entries with
+         NEW, as long as it is OLD.  WHICH says which history entries to
+         modify
+       - add calls to replace_history_data in rl_free_undo_list and
+         rl_do_undo
+
+lib/readline/undo.c
+       - new function, alloc_undo_entry (enum undo_code what, int start, int end, char *text)
+         takes care of allocating and populating a struct for an individual
+         undo list entry
+       - new function: _rl_copy_undo_entry(UNDO_LIST *entry)
+       - new function: _rl_copy_undo_list(UNDO_LIST *head)
+
+lib/readline/rlprivate.h
+       - new extern declarations for _rl_copy_undo_{entry,list}
index d70563dc5ec1bf7c2fb6410c02001ceefe9ccb75..9bb6c1de757016d5e62c660ca7a9cb1b64bf1fcb 100644 (file)
@@ -13372,3 +13372,48 @@ arrayfunc.c
 arrayfunc.h
        - new extern declarations for expand_compound_array_assignment and
          assign_compound_array_list
+
+subst.c
+       - in do_compound_assignment, call expand_compound_array_assignment
+         before creating the local variable so a previous inherited
+         value can be used when expanding the rhs of the compound assignment
+         statement
+
+                                  5/11
+                                  ----
+doc/{bash.1,bashref.texi}
+       - clarifed `trap' description to make it clear that trapped signals
+         that are not set to SIG_IGN are reset when a subshell is created
+
+                                  5/18
+                                  ----
+locale.c
+       - change reset_locale_vars to call setlocale (LC_ALL, "") if LANG
+         is unset or NULL
+       - if LANG is unset or NULL, reset the export environment before
+         calling setlocale in reset_locale_vars, and trust that it will
+         change the environment setlocale() inspects
+
+                                  5/21
+                                  ----
+lib/readline/history.c
+       - new function, HIST_ENTRY *alloc_history_entry (char *string, char *ts);
+         creates a new history entry with text STRING and timestamp TS (both
+         of which may be NULL)
+       - new function, HIST_ENTRY *copy_history_entry (HIST_ENTRY *hist),
+         which copies the line and timestamp entries to new memory but just
+         copies the data member, since that's an opaque pointer
+       - new function, void replace_history_data (int which, histdata_t *old, histdata_t *new)
+         which replaces the `data' member of specified history entries with
+         NEW, as long as it is OLD.  WHICH says which history entries to
+         modify
+       - add calls to replace_history_data in rl_free_undo_list and
+         rl_do_undo
+
+lib/readline/undo.c
+       - new function, alloc_undo_entry (enum undo_code what, int start, int end, char *text)
+         takes care of allocating and populating a struct for an individual
+         undo list entry
+
+
+         
index e52905d549796e711177f0188751d499611bfc80..38833e3bf727716615a3147854291795c01586ce 100644 (file)
@@ -2503,6 +2503,7 @@ execute_cond_node (cond)
     }
   else if (cond->type == COND_BINARY)
     {
+      rmatch = 0;
       patmatch = ((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') &&
                  (cond->op->word[0] == '!' || cond->op->word[0] == '=') ||
                  (cond->op->word[0] == '=' && cond->op->word[1] == '\0'));
@@ -2514,7 +2515,7 @@ execute_cond_node (cond)
       arg1 = cond_expand_word (cond->left->op, 0);
       if (arg1 == 0)
        arg1 = nullstr;
-      arg2 = cond_expand_word (cond->right->op, patmatch);
+      arg2 = cond_expand_word (cond->right->op, patmatch||rmatch);
       if (arg2 == 0)
        arg2 = nullstr;
 
index 57e9d1136ced0da1ec05d9ff6c9544e0088589b3..e52905d549796e711177f0188751d499611bfc80 100644 (file)
@@ -214,6 +214,8 @@ static int special_builtin_failed;
    report the correct line number.  Kind of a hack. */
 static int showing_function_line;
 
+static int line_number_for_err_trap;
+
 /* For catching RETURN in a function. */
 int return_catch_flag;
 int return_catch_value;
@@ -665,7 +667,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
        if (command->flags & CMD_STDIN_REDIR)
          command->value.Simple->flags |= CMD_STDIN_REDIR;
 
-       line_number = command->value.Simple->line;
+       line_number_for_err_trap = line_number = command->value.Simple->line;
        exec_result =
          execute_simple_command (command->value.Simple, pipe_in, pipe_out,
                                  asynchronous, fds_to_close);
index a538f91c0d7b387c088705e785e85c36de62f37e..1ccf4db786c60a544698a8d741258c4d2122cd35 100644 (file)
@@ -209,6 +209,22 @@ history_get (offset)
                : the_history[local_index];
 }
 
+HIST_ENTRY *
+alloc_history_entry (string, ts)
+     char *string;
+     char *ts;
+{
+  HIST_ENTRY *temp;
+
+  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+
+  temp->line = string ? savestring (string) : string;
+  temp->data = (char *)NULL;
+  temp->timestamp = ts;
+
+  return temp;
+}
+
 time_t
 history_get_time (hist)
      HIST_ENTRY *hist;
@@ -290,11 +306,7 @@ add_history (string)
        }
     }
 
-  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
-  temp->line = savestring (string);
-  temp->data = (char *)NULL;
-
-  temp->timestamp = hist_inittime ();
+  temp = alloc_history_entry (string, hist_inittime ());
 
   the_history[history_length] = (HIST_ENTRY *)NULL;
   the_history[history_length - 1] = temp;
@@ -328,6 +340,26 @@ free_history_entry (hist)
   free (hist);
   return (x);
 }
+
+HIST_ENTRY *
+copy_history_entry (hist)
+     HIST_ENTRY *hist;
+{
+  HIST_ENTRY *ret;
+  char *ts;
+
+  if (hist == 0)
+    return hist;
+
+  ret = alloc_history_entry (hist->line, (char *)NULL);
+
+  ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp;
+  ret->timestamp = ts;
+
+  ret->data = hist->data;
+
+  return ret;
+}
   
 /* Make the history entry at WHICH have LINE and DATA.  This returns
    the old entry so you can dispose of the data.  In the case of an
@@ -354,6 +386,51 @@ replace_history_entry (which, line, data)
   return (old_value);
 }
 
+/* Replace the DATA in the specified history entries, replacing OLD with
+   NEW.  WHICH says which one(s) to replace:  WHICH == -1 means to replace
+   all of the history entries where entry->data == OLD; WHICH == -2 means
+   to replace the `newest' history entry where entry->data == OLD; and
+   WHICH >= 0 means to replace that particular history entry's data, as
+   long as it matches OLD. */
+void
+replace_history_data (which,old, new)
+     int which;
+     histdata_t *old, *new;
+{
+  HIST_ENTRY *entry;
+  register int i, last;
+
+  if (which < -2 || which >= history_length || history_length == 0 || the_history == 0)
+    return;
+
+  if (which >= 0)
+    {
+      entry = the_history[which];
+      if (entry && entry->data == old)
+       entry->data = new;
+      return;
+    }
+
+  last = -1;
+  for (i = 0; i < history_length; i++)
+    {
+      entry = the_history[i];
+      if (entry == 0)
+       continue;
+      if (entry->data == old)
+       {
+         last = i;
+         if (which == -1)
+           entry->data = new;
+       }
+    }
+  if (which == -2 && last >= 0)
+    {
+      entry = the_history[last];
+      entry->data = new;       /* XXX - we don't check entry->old */
+    }
+}      
+  
 /* Remove history element WHICH from the history.  The removed
    element is returned to you so you can free the line, data,
    and containing structure. */
diff --git a/lib/readline/history.c~ b/lib/readline/history.c~
new file mode 100644 (file)
index 0000000..e18b410
--- /dev/null
@@ -0,0 +1,486 @@
+/* history.c -- standalone history library */
+
+/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
+
+   This file contains the GNU History Library (the Library), a set of
+   routines for managing the text of previously typed lines.
+
+   The Library is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   The Library is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+/* The goal is to make the implementation transparent, so that you
+   don't have to know what data types are used, just what functions
+   you can call.  I think I have done that. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include "history.h"
+#include "histlib.h"
+
+#include "xmalloc.h"
+
+/* The number of slots to increase the_history by. */
+#define DEFAULT_HISTORY_GROW_SIZE 50
+
+static char *hist_inittime PARAMS((void));
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     History Functions                           */
+/*                                                                 */
+/* **************************************************************** */
+
+/* An array of HIST_ENTRY.  This is where we store the history. */
+static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
+
+/* Non-zero means that we have enforced a limit on the amount of
+   history that we save. */
+static int history_stifled;
+
+/* The current number of slots allocated to the input_history. */
+static int history_size;
+
+/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
+   entries to remember. */
+int history_max_entries;
+int max_input_history; /* backwards compatibility */
+
+/* The current location of the interactive history pointer.  Just makes
+   life easier for outside callers. */
+int history_offset;
+
+/* The number of strings currently stored in the history list. */
+int history_length;
+
+/* The logical `base' of the history array.  It defaults to 1. */
+int history_base = 1;
+
+/* Return the current HISTORY_STATE of the history. */
+HISTORY_STATE *
+history_get_history_state ()
+{
+  HISTORY_STATE *state;
+
+  state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
+  state->entries = the_history;
+  state->offset = history_offset;
+  state->length = history_length;
+  state->size = history_size;
+  state->flags = 0;
+  if (history_stifled)
+    state->flags |= HS_STIFLED;
+
+  return (state);
+}
+
+/* Set the state of the current history array to STATE. */
+void
+history_set_history_state (state)
+     HISTORY_STATE *state;
+{
+  the_history = state->entries;
+  history_offset = state->offset;
+  history_length = state->length;
+  history_size = state->size;
+  if (state->flags & HS_STIFLED)
+    history_stifled = 1;
+}
+
+/* Begin a session in which the history functions might be used.  This
+   initializes interactive variables. */
+void
+using_history ()
+{
+  history_offset = history_length;
+}
+
+/* Return the number of bytes that the primary history entries are using.
+   This just adds up the lengths of the_history->lines and the associated
+   timestamps. */
+int
+history_total_bytes ()
+{
+  register int i, result;
+
+  for (i = result = 0; the_history && the_history[i]; i++)
+    result += HISTENT_BYTES (the_history[i]);
+
+  return (result);
+}
+
+/* Returns the magic number which says what history element we are
+   looking at now.  In this implementation, it returns history_offset. */
+int
+where_history ()
+{
+  return (history_offset);
+}
+
+/* Make the current history item be the one at POS, an absolute index.
+   Returns zero if POS is out of range, else non-zero. */
+int
+history_set_pos (pos)
+     int pos;
+{
+  if (pos > history_length || pos < 0 || !the_history)
+    return (0);
+  history_offset = pos;
+  return (1);
+}
+/* Return the current history array.  The caller has to be carefull, since this
+   is the actual array of data, and could be bashed or made corrupt easily.
+   The array is terminated with a NULL pointer. */
+HIST_ENTRY **
+history_list ()
+{
+  return (the_history);
+}
+
+/* Return the history entry at the current position, as determined by
+   history_offset.  If there is no entry there, return a NULL pointer. */
+HIST_ENTRY *
+current_history ()
+{
+  return ((history_offset == history_length) || the_history == 0)
+               ? (HIST_ENTRY *)NULL
+               : the_history[history_offset];
+}
+
+/* Back up history_offset to the previous history entry, and return
+   a pointer to that entry.  If there is no previous entry then return
+   a NULL pointer. */
+HIST_ENTRY *
+previous_history ()
+{
+  return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
+}
+
+/* Move history_offset forward to the next history entry, and return
+   a pointer to that entry.  If there is no next entry then return a
+   NULL pointer. */
+HIST_ENTRY *
+next_history ()
+{
+  return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
+}
+
+/* Return the history entry which is logically at OFFSET in the history array.
+   OFFSET is relative to history_base. */
+HIST_ENTRY *
+history_get (offset)
+     int offset;
+{
+  int local_index;
+
+  local_index = offset - history_base;
+  return (local_index >= history_length || local_index < 0 || the_history == 0)
+               ? (HIST_ENTRY *)NULL
+               : the_history[local_index];
+}
+
+time_t
+history_get_time (hist)
+     HIST_ENTRY *hist;
+{
+  char *ts;
+  time_t t;
+
+  if (hist == 0 || hist->timestamp == 0)
+    return 0;
+  ts = hist->timestamp;
+  if (ts[0] != history_comment_char)
+    return 0;
+  t = (time_t) atol (ts + 1);          /* XXX - should use strtol() here */
+  return t;
+}
+
+static char *
+hist_inittime ()
+{
+  time_t t;
+  char ts[64], *ret;
+
+  t = (time_t) time ((time_t *)0);
+#if defined (HAVE_VSNPRINTF)           /* assume snprintf if vsnprintf exists */
+  snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
+#else
+  sprintf (ts, "X%lu", (unsigned long) t);
+#endif
+  ret = savestring (ts);
+  ret[0] = history_comment_char;
+
+  return ret;
+}
+
+/* Place STRING at the end of the history list.  The data field
+   is  set to NULL. */
+void
+add_history (string)
+     const char *string;
+{
+  HIST_ENTRY *temp;
+
+  if (history_stifled && (history_length == history_max_entries))
+    {
+      register int i;
+
+      /* If the history is stifled, and history_length is zero,
+        and it equals history_max_entries, we don't save items. */
+      if (history_length == 0)
+       return;
+
+      /* If there is something in the slot, then remove it. */
+      if (the_history[0])
+       (void) free_history_entry (the_history[0]);
+
+      /* Copy the rest of the entries, moving down one slot. */
+      for (i = 0; i < history_length; i++)
+       the_history[i] = the_history[i + 1];
+
+      history_base++;
+    }
+  else
+    {
+      if (history_size == 0)
+       {
+         history_size = DEFAULT_HISTORY_GROW_SIZE;
+         the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
+         history_length = 1;
+       }
+      else
+       {
+         if (history_length == (history_size - 1))
+           {
+             history_size += DEFAULT_HISTORY_GROW_SIZE;
+             the_history = (HIST_ENTRY **)
+               xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
+           }
+         history_length++;
+       }
+    }
+
+  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  temp->line = savestring (string);
+  temp->data = (char *)NULL;
+
+  temp->timestamp = hist_inittime ();
+
+  the_history[history_length] = (HIST_ENTRY *)NULL;
+  the_history[history_length - 1] = temp;
+}
+
+/* Change the time stamp of the most recent history entry to STRING. */
+void
+add_history_time (string)
+     const char *string;
+{
+  HIST_ENTRY *hs;
+
+  hs = the_history[history_length - 1];
+  FREE (hs->timestamp);
+  hs->timestamp = savestring (string);
+}
+
+/* Free HIST and return the data so the calling application can free it
+   if necessary and desired. */
+histdata_t
+free_history_entry (hist)
+     HIST_ENTRY *hist;
+{
+  histdata_t x;
+
+  if (hist == 0)
+    return ((histdata_t) 0);
+  FREE (hist->line);
+  FREE (hist->timestamp);
+  x = hist->data;
+  free (hist);
+  return (x);
+}
+  
+/* Make the history entry at WHICH have LINE and DATA.  This returns
+   the old entry so you can dispose of the data.  In the case of an
+   invalid WHICH, a NULL pointer is returned. */
+HIST_ENTRY *
+replace_history_entry (which, line, data)
+     int which;
+     const char *line;
+     histdata_t data;
+{
+  HIST_ENTRY *temp, *old_value;
+
+  if (which < 0 || which >= history_length)
+    return ((HIST_ENTRY *)NULL);
+
+  temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
+  old_value = the_history[which];
+
+  temp->line = savestring (line);
+  temp->data = data;
+  temp->timestamp = savestring (old_value->timestamp);
+  the_history[which] = temp;
+
+  return (old_value);
+}
+
+/* Replace the DATA in the specified history entries, replacing OLD with
+   NEW.  WHICH says which one(s) to replace:  WHICH == -1 means to replace
+   all of the history entries where entry->data == OLD; WHICH == -2 means
+   to replace the `newest' history entry where entry->data == OLD; and
+   WHICH >= 0 means to replace that particular history entry's data, as
+   long as it matches OLD. */
+void
+replace_history_data (which,old, new)
+     int which;
+     histdata_t *old, *new;
+{
+  HIST_ENTRY *entry;
+  register int i, last;
+
+  if (which < -2 || which >= history_length || history_length == 0 || the_history == 0)
+    return;
+
+  if (which >= 0)
+    {
+      entry = the_history[which];
+      if (entry && entry->data == old)
+       entry->data = new;
+      return;
+    }
+
+  last = -1;
+  for (i = 0; i < history_length; i++)
+    {
+      entry = the_history[i];
+      if (entry == 0)
+       continue;
+      if (entry->data == old)
+       {
+         last = i;
+         if (which == -1)
+           entry->data = new;
+       }
+    }
+  if (which == -2 && last >= 0)
+    {
+      entry = the_history[last];
+      entry->data = new;       /* XXX - we don't check entry->old */
+    }
+}      
+  
+/* Remove history element WHICH from the history.  The removed
+   element is returned to you so you can free the line, data,
+   and containing structure. */
+HIST_ENTRY *
+remove_history (which)
+     int which;
+{
+  HIST_ENTRY *return_value;
+  register int i;
+
+  if (which < 0 || which >= history_length || history_length ==  0 || the_history == 0)
+    return ((HIST_ENTRY *)NULL);
+
+  return_value = the_history[which];
+
+  for (i = which; i < history_length; i++)
+    the_history[i] = the_history[i + 1];
+
+  history_length--;
+
+  return (return_value);
+}
+
+/* Stifle the history list, remembering only MAX number of lines. */
+void
+stifle_history (max)
+     int max;
+{
+  register int i, j;
+
+  if (max < 0)
+    max = 0;
+
+  if (history_length > max)
+    {
+      /* This loses because we cannot free the data. */
+      for (i = 0, j = history_length - max; i < j; i++)
+       free_history_entry (the_history[i]);
+
+      history_base = i;
+      for (j = 0, i = history_length - max; j < max; i++, j++)
+       the_history[j] = the_history[i];
+      the_history[j] = (HIST_ENTRY *)NULL;
+      history_length = j;
+    }
+
+  history_stifled = 1;
+  max_input_history = history_max_entries = max;
+}
+
+/* Stop stifling the history.  This returns the previous maximum
+   number of history entries.  The value is positive if the history
+   was stifled,  negative if it wasn't. */
+int
+unstifle_history ()
+{
+  if (history_stifled)
+    {
+      history_stifled = 0;
+      return (history_max_entries);
+    }
+  else
+    return (-history_max_entries);
+}
+
+int
+history_is_stifled ()
+{
+  return (history_stifled);
+}
+
+void
+clear_history ()
+{
+  register int i;
+
+  /* This loses because we cannot free the data. */
+  for (i = 0; i < history_length; i++)
+    {
+      free_history_entry (the_history[i]);
+      the_history[i] = (HIST_ENTRY *)NULL;
+    }
+
+  history_offset = history_length = 0;
+}
index 1c216ead14f73a4f583acd88080fc200fd09823d..d85fa9f9a62fd090f095c0f7d13ea6d5cb47df85 100644 (file)
@@ -309,6 +309,10 @@ extern int _rl_char_search_internal PARAMS((int, int, int));
 #endif
 extern int _rl_set_mark_at_pos PARAMS((int));
 
+/* undo.c */
+extern UNDO_LIST *_rl_copy_undo_entry PARAMS((UNDO_LIST *));
+extern UNDO_LIST *_rl_copy_undo_list PARAMS((UNDO_LIST *));
+
 /* util.c */
 extern int _rl_abort_internal PARAMS((void));
 extern char *_rl_strindex PARAMS((const char *, const char *));
diff --git a/lib/readline/rlprivate.h~ b/lib/readline/rlprivate.h~
new file mode 100644 (file)
index 0000000..1c216ea
--- /dev/null
@@ -0,0 +1,420 @@
+/* rlprivate.h -- functions and variables global to the readline library,
+                 but not intended for use by applications. */
+
+/* Copyright (C) 1999-2005 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_RL_PRIVATE_H_)
+#define _RL_PRIVATE_H_
+
+#include "rlconf.h"    /* for VISIBLE_STATS */
+#include "rlstdc.h"
+#include "posixjmp.h"  /* defines procenv_t */
+
+/*************************************************************************
+ *                                                                      *
+ * Global structs undocumented in texinfo manual and not in readline.h   *
+ *                                                                      *
+ *************************************************************************/
+/* search types */
+#define RL_SEARCH_ISEARCH      0x01            /* incremental search */
+#define RL_SEARCH_NSEARCH      0x02            /* non-incremental search */
+#define RL_SEARCH_CSEARCH      0x04            /* intra-line char search */
+
+/* search flags */
+#define SF_REVERSE             0x01
+#define SF_FOUND               0x02
+#define SF_FAILED              0x04
+
+typedef struct  __rl_search_context
+{
+  int type;
+  int sflags;
+
+  char *search_string;
+  int search_string_index;
+  int search_string_size;
+
+  char **lines;
+  char *allocated_line;    
+  int hlen;
+  int hindex;
+
+  int save_point;
+  int save_mark;
+  int save_line;
+  int last_found_line;
+  char *prev_line_found;
+
+  UNDO_LIST *save_undo_list;
+
+  int history_pos;
+  int direction;
+
+  int lastc;
+#if defined (HANDLE_MULTIBYTE)
+  char mb[MB_LEN_MAX];
+#endif
+
+  char *sline;
+  int sline_len;
+  int sline_index;
+
+  char  *search_terminators;
+} _rl_search_cxt;
+
+/* Callback data for reading numeric arguments */
+#define NUM_SAWMINUS   0x01
+#define NUM_SAWDIGITS  0x02
+#define NUM_READONE    0x04
+
+typedef int _rl_arg_cxt;
+
+/* A context for reading key sequences longer than a single character when
+   using the callback interface. */
+#define KSEQ_DISPATCHED        0x01
+#define KSEQ_SUBSEQ    0x02
+#define KSEQ_RECURSIVE 0x04
+
+typedef struct __rl_keyseq_context
+{
+  int flags;
+  int subseq_arg;
+  int subseq_retval;           /* XXX */
+  Keymap dmap;
+
+  Keymap oldmap;
+  int okey;
+  struct __rl_keyseq_context *ocxt;
+  int childval;
+} _rl_keyseq_cxt;
+
+  /* fill in more as needed */
+/* `Generic' callback data and functions */
+typedef struct __rl_callback_generic_arg 
+{
+  int count;
+  int i1, i2;
+  /* add here as needed */
+} _rl_callback_generic_arg;
+
+typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *));
+
+/*************************************************************************
+ *                                                                      *
+ * Global functions undocumented in texinfo manual and not in readline.h *
+ *                                                                      *
+ *************************************************************************/
+
+/*************************************************************************
+ *                                                                      *
+ * Global variables undocumented in texinfo manual and not in readline.h *
+ *                                                                      *
+ *************************************************************************/
+
+/* complete.c */
+extern int rl_complete_with_tilde_expansion;
+#if defined (VISIBLE_STATS)
+extern int rl_visible_stats;
+#endif /* VISIBLE_STATS */
+
+/* readline.c */
+extern int rl_line_buffer_len;
+extern int rl_arg_sign;
+extern int rl_visible_prompt_length;
+extern int readline_echoing_p;
+extern int rl_key_sequence_length;
+extern int rl_byte_oriented;
+
+extern _rl_keyseq_cxt *_rl_kscxt;
+
+/* display.c */
+extern int rl_display_fixed;
+
+/* parens.c */
+extern int rl_blink_matching_paren;
+
+/*************************************************************************
+ *                                                                      *
+ * Global functions and variables unsed and undocumented                *
+ *                                                                      *
+ *************************************************************************/
+
+/* kill.c */
+extern int rl_set_retained_kills PARAMS((int));
+
+/* terminal.c */
+extern void _rl_set_screen_size PARAMS((int, int));
+
+/* undo.c */
+extern int _rl_fix_last_undo_of_type PARAMS((int, int, int));
+
+/* util.c */
+extern char *_rl_savestring PARAMS((const char *));
+
+/*************************************************************************
+ *                                                                      *
+ * Functions and variables private to the readline library              *
+ *                                                                      *
+ *************************************************************************/
+
+/* NOTE: Functions and variables prefixed with `_rl_' are
+   pseudo-global: they are global so they can be shared
+   between files in the readline library, but are not intended
+   to be visible to readline callers. */
+
+/*************************************************************************
+ * Undocumented private functions                                       *
+ *************************************************************************/
+
+#if defined(READLINE_CALLBACKS)
+
+/* readline.c */
+extern void readline_internal_setup PARAMS((void));
+extern char *readline_internal_teardown PARAMS((int));
+extern int readline_internal_char PARAMS((void));
+
+extern _rl_keyseq_cxt *_rl_keyseq_cxt_alloc PARAMS((void));
+extern void _rl_keyseq_cxt_dispose PARAMS((_rl_keyseq_cxt *));
+extern void _rl_keyseq_chain_dispose PARAMS((void));
+
+extern int _rl_dispatch_callback PARAMS((_rl_keyseq_cxt *));
+     
+/* callback.c */
+extern _rl_callback_generic_arg *_rl_callback_data_alloc PARAMS((int));
+extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *));
+
+#endif /* READLINE_CALLBACKS */
+
+/* bind.c */
+
+/* complete.c */
+extern char _rl_find_completion_word PARAMS((int *, int *));
+extern void _rl_free_match_list PARAMS((char **));
+
+/* display.c */
+extern char *_rl_strip_prompt PARAMS((char *));
+extern void _rl_move_cursor_relative PARAMS((int, const char *));
+extern void _rl_move_vert PARAMS((int));
+extern void _rl_save_prompt PARAMS((void));
+extern void _rl_restore_prompt PARAMS((void));
+extern char *_rl_make_prompt_for_search PARAMS((int));
+extern void _rl_erase_at_end_of_line PARAMS((int));
+extern void _rl_clear_to_eol PARAMS((int));
+extern void _rl_clear_screen PARAMS((void));
+extern void _rl_update_final PARAMS((void));
+extern void _rl_redisplay_after_sigwinch PARAMS((void));
+extern void _rl_clean_up_for_exit PARAMS((void));
+extern void _rl_erase_entire_line PARAMS((void));
+extern int _rl_current_display_line PARAMS((void));
+
+/* input.c */
+extern int _rl_any_typein PARAMS((void));
+extern int _rl_input_available PARAMS((void));
+extern int _rl_input_queued PARAMS((int));
+extern void _rl_insert_typein PARAMS((int));
+extern int _rl_unget_char PARAMS((int));
+extern int _rl_pushed_input_available PARAMS((void));
+
+/* isearch.c */
+extern _rl_search_cxt *_rl_scxt_alloc PARAMS((int, int));
+extern void _rl_scxt_dispose PARAMS((_rl_search_cxt *, int));
+
+extern int _rl_isearch_dispatch PARAMS((_rl_search_cxt *, int));
+extern int _rl_isearch_callback PARAMS((_rl_search_cxt *));
+
+extern int _rl_search_getchar PARAMS((_rl_search_cxt *));
+
+/* macro.c */
+extern void _rl_with_macro_input PARAMS((char *));
+extern int _rl_next_macro_key PARAMS((void));
+extern void _rl_push_executing_macro PARAMS((void));
+extern void _rl_pop_executing_macro PARAMS((void));
+extern void _rl_add_macro_char PARAMS((int));
+extern void _rl_kill_kbd_macro PARAMS((void));
+
+/* misc.c */
+extern int _rl_arg_overflow PARAMS((void));
+extern void _rl_arg_init PARAMS((void));
+extern int _rl_arg_getchar PARAMS((void));
+extern int _rl_arg_callback PARAMS((_rl_arg_cxt));
+extern void _rl_reset_argument PARAMS((void));
+
+extern void _rl_start_using_history PARAMS((void));
+extern int _rl_free_saved_history_line PARAMS((void));
+extern void _rl_set_insert_mode PARAMS((int, int));
+
+/* nls.c */
+extern int _rl_init_eightbit PARAMS((void));
+
+/* parens.c */
+extern void _rl_enable_paren_matching PARAMS((int));
+
+/* readline.c */
+extern void _rl_init_line_state PARAMS((void));
+extern void _rl_set_the_line PARAMS((void));
+extern int _rl_dispatch PARAMS((int, Keymap));
+extern int _rl_dispatch_subseq PARAMS((int, Keymap, int));
+extern void _rl_internal_char_cleanup PARAMS((void));
+
+/* rltty.c */
+extern int _rl_disable_tty_signals PARAMS((void));
+extern int _rl_restore_tty_signals PARAMS((void));
+
+/* search.c */
+extern int _rl_nsearch_callback PARAMS((_rl_search_cxt *));
+
+/* terminal.c */
+extern void _rl_get_screen_size PARAMS((int, int));
+extern int _rl_init_terminal_io PARAMS((const char *));
+#ifdef _MINIX
+extern void _rl_output_character_function PARAMS((int));
+#else
+extern int _rl_output_character_function PARAMS((int));
+#endif
+extern void _rl_output_some_chars PARAMS((const char *, int));
+extern int _rl_backspace PARAMS((int));
+extern void _rl_enable_meta_key PARAMS((void));
+extern void _rl_control_keypad PARAMS((int));
+extern void _rl_set_cursor PARAMS((int, int));
+
+/* text.c */
+extern void _rl_fix_point PARAMS((int));
+extern int _rl_replace_text PARAMS((const char *, int, int));
+extern int _rl_insert_char PARAMS((int, int));
+extern int _rl_overwrite_char PARAMS((int, int));
+extern int _rl_overwrite_rubout PARAMS((int, int));
+extern int _rl_rubout_char PARAMS((int, int));
+#if defined (HANDLE_MULTIBYTE)
+extern int _rl_char_search_internal PARAMS((int, int, char *, int));
+#else
+extern int _rl_char_search_internal PARAMS((int, int, int));
+#endif
+extern int _rl_set_mark_at_pos PARAMS((int));
+
+/* util.c */
+extern int _rl_abort_internal PARAMS((void));
+extern char *_rl_strindex PARAMS((const char *, const char *));
+extern int _rl_qsort_string_compare PARAMS((char **, char **));
+extern int (_rl_uppercase_p) PARAMS((int));
+extern int (_rl_lowercase_p) PARAMS((int));
+extern int (_rl_pure_alphabetic) PARAMS((int));
+extern int (_rl_digit_p) PARAMS((int));
+extern int (_rl_to_lower) PARAMS((int));
+extern int (_rl_to_upper) PARAMS((int));
+extern int (_rl_digit_value) PARAMS((int));
+
+/* vi_mode.c */
+extern void _rl_vi_initialize_line PARAMS((void));
+extern void _rl_vi_reset_last PARAMS((void));
+extern void _rl_vi_set_last PARAMS((int, int, int));
+extern int _rl_vi_textmod_command PARAMS((int));
+extern void _rl_vi_done_inserting PARAMS((void));
+
+/*************************************************************************
+ * Undocumented private variables                                       *
+ *************************************************************************/
+
+/* bind.c */
+extern const char *_rl_possible_control_prefixes[];
+extern const char *_rl_possible_meta_prefixes[];
+
+/* callback.c */
+extern _rl_callback_func_t *_rl_callback_func;
+extern _rl_callback_generic_arg *_rl_callback_data;
+
+/* complete.c */
+extern int _rl_complete_show_all;
+extern int _rl_complete_show_unmodified;
+extern int _rl_complete_mark_directories;
+extern int _rl_complete_mark_symlink_dirs;
+extern int _rl_print_completions_horizontally;
+extern int _rl_completion_case_fold;
+extern int _rl_match_hidden_files;
+extern int _rl_page_completions;
+
+/* display.c */
+extern int _rl_vis_botlin;
+extern int _rl_last_c_pos;
+extern int _rl_suppress_redisplay;
+extern int _rl_want_redisplay;
+extern char *rl_display_prompt;
+
+/* isearch.c */
+extern char *_rl_isearch_terminators;
+
+extern _rl_search_cxt *_rl_iscxt;
+
+/* macro.c */
+extern char *_rl_executing_macro;
+
+/* misc.c */
+extern int _rl_history_preserve_point;
+extern int _rl_history_saved_point;
+
+extern _rl_arg_cxt _rl_argcxt;
+
+/* readline.c */
+extern int _rl_horizontal_scroll_mode;
+extern int _rl_mark_modified_lines;
+extern int _rl_bell_preference;
+extern int _rl_meta_flag;
+extern int _rl_convert_meta_chars_to_ascii;
+extern int _rl_output_meta_chars;
+extern int _rl_bind_stty_chars;
+extern char *_rl_comment_begin;
+extern unsigned char _rl_parsing_conditionalized_out;
+extern Keymap _rl_keymap;
+extern FILE *_rl_in_stream;
+extern FILE *_rl_out_stream;
+extern int _rl_last_command_was_kill;
+extern int _rl_eof_char;
+extern procenv_t readline_top_level;
+
+/* search.c */
+extern _rl_search_cxt *_rl_nscxt;
+
+/* terminal.c */
+extern int _rl_enable_keypad;
+extern int _rl_enable_meta;
+extern char *_rl_term_clreol;
+extern char *_rl_term_clrpag;
+extern char *_rl_term_im;
+extern char *_rl_term_ic;
+extern char *_rl_term_ei;
+extern char *_rl_term_DC;
+extern char *_rl_term_up;
+extern char *_rl_term_dc;
+extern char *_rl_term_cr;
+extern char *_rl_term_IC;
+extern int _rl_screenheight;
+extern int _rl_screenwidth;
+extern int _rl_screenchars;
+extern int _rl_terminal_can_insert;
+extern int _rl_term_autowrap;
+
+/* undo.c */
+extern int _rl_doing_an_undo;
+extern int _rl_undo_group_level;
+
+/* vi_mode.c */
+extern int _rl_vi_last_command;
+
+#endif /* _RL_PRIVATE_H_ */
index fedfa121fc0d7e68c89da0e5a63ae4ec395c214e..9d9bd25ba8f6b76fdacce6cc554397392fc73d50 100644 (file)
@@ -1,7 +1,7 @@
 /* readline.c -- a general facility for reading lines of input
    with emacs style editing and completion. */
 
-/* Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+/* Copyright (C) 1987, 1989, 1992, 2006 Free Software Foundation, Inc.
 
    This file is part of the GNU Readline Library, a library for
    reading lines of text with interactive input and history editing.
@@ -50,6 +50,8 @@
 #include "rlprivate.h"
 #include "xmalloc.h"
 
+extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
+
 /* Non-zero tells rl_delete_text and rl_insert_text to not add to
    the undo list. */
 int _rl_doing_an_undo = 0;
@@ -66,19 +68,35 @@ UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
 /*                                                                 */
 /* **************************************************************** */
 
-/* Remember how to undo something.  Concatenate some undos if that
-   seems right. */
-void
-rl_add_undo (what, start, end, text)
+static UNDO_LIST *
+alloc_undo_entry (what, start, end, text)
      enum undo_code what;
      int start, end;
      char *text;
 {
-  UNDO_LIST *temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
+  UNDO_LIST *temp;
+
+  temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
   temp->what = what;
   temp->start = start;
   temp->end = end;
   temp->text = text;
+
+  temp->next = (UNDO_LIST *)NULL;
+  return temp;
+}
+
+/* Remember how to undo something.  Concatenate some undos if that
+   seems right. */
+void
+rl_add_undo (what, start, end, text)
+     enum undo_code what;
+     int start, end;
+     char *text;
+{
+  UNDO_LIST *temp;
+
+  temp = alloc_undo_entry (what, start, end, text);
   temp->next = rl_undo_list;
   rl_undo_list = temp;
 }
@@ -87,9 +105,12 @@ rl_add_undo (what, start, end, text)
 void
 rl_free_undo_list ()
 {
+  UNDO_LIST *release, *orig_list;
+
+  orig_list = rl_undo_list;
   while (rl_undo_list)
     {
-      UNDO_LIST *release = rl_undo_list;
+      release = rl_undo_list;
       rl_undo_list = rl_undo_list->next;
 
       if (release->what == UNDO_DELETE)
@@ -98,6 +119,43 @@ rl_free_undo_list ()
       free (release);
     }
   rl_undo_list = (UNDO_LIST *)NULL;
+  replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
+}
+
+UNDO_LIST *
+_rl_copy_undo_entry (entry)
+     UNDO_LIST *entry;
+{
+  UNDO_LIST *new;
+
+  new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
+  new->text = entry->text ? savestring (entry->text) : 0;
+  return new;
+}
+
+UNDO_LIST *
+_rl_copy_undo_list (head)
+     UNDO_LIST *head;
+{
+  UNDO_LIST *list, *new, *roving, *c;
+
+  list = head;
+  new = 0;
+  while (list)
+    {
+      c = _rl_copy_undo_entry (list);
+      if (new == 0)
+       roving = new = c;
+      else
+       {
+         roving->next = c;
+         roving = roving->next;
+       }
+      list = list->next;
+    }
+
+  roving->next = 0;
+  return new;
 }
 
 /* Undo the next thing in the list.  Return 0 if there
@@ -161,6 +219,8 @@ rl_do_undo ()
 
       release = rl_undo_list;
       rl_undo_list = rl_undo_list->next;
+      replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
+
       free (release);
     }
   while (waiting_for_begin);
diff --git a/lib/readline/undo.c~ b/lib/readline/undo.c~
new file mode 100644 (file)
index 0000000..a27089a
--- /dev/null
@@ -0,0 +1,292 @@
+/* readline.c -- a general facility for reading lines of input
+   with emacs style editing and completion. */
+
+/* Copyright (C) 1987, 1989, 1992, 2006 Free Software Foundation, Inc.
+
+   This file is part of the GNU Readline Library, a library for
+   reading lines of text with interactive input and history editing.
+
+   The GNU Readline Library is free software; you can redistribute it
+   and/or modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2, or
+   (at your option) any later version.
+
+   The GNU Readline Library is distributed in the hope that it will be
+   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   The GNU General Public License is often shipped with GNU software, and
+   is generally kept in a file called COPYING or LICENSE.  If you do not
+   have a copy of the license, write to the Free Software Foundation,
+   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>           /* for _POSIX_VERSION */
+#endif /* HAVE_UNISTD_H */
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#include <stdio.h>
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
+
+/* Non-zero tells rl_delete_text and rl_insert_text to not add to
+   the undo list. */
+int _rl_doing_an_undo = 0;
+
+/* How many unclosed undo groups we currently have. */
+int _rl_undo_group_level = 0;
+
+/* The current undo list for THE_LINE. */
+UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
+
+/* **************************************************************** */
+/*                                                                 */
+/*                     Undo, and Undoing                           */
+/*                                                                 */
+/* **************************************************************** */
+
+static UNDO_LIST *
+alloc_undo_entry (what, start, end, text)
+     enum undo_code what;
+     int start, end;
+     char *text;
+{
+  UNDO_LIST *temp;
+
+  temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
+  temp->what = what;
+  temp->start = start;
+  temp->end = end;
+  temp->text = text;
+
+  temp->next = (UNDO_LIST *)NULL;
+  return temp;
+}
+
+/* Remember how to undo something.  Concatenate some undos if that
+   seems right. */
+void
+rl_add_undo (what, start, end, text)
+     enum undo_code what;
+     int start, end;
+     char *text;
+{
+  UNDO_LIST *temp;
+
+  temp = alloc_undo_entry (what, start, end, text);
+  temp->next = rl_undo_list;
+  rl_undo_list = temp;
+}
+
+/* Free the existing undo list. */
+void
+rl_free_undo_list ()
+{
+  UNDO_LIST *release, *orig_list;
+
+  orig_list = rl_undo_list;
+  while (rl_undo_list)
+    {
+      release = rl_undo_list;
+      rl_undo_list = rl_undo_list->next;
+
+      if (release->what == UNDO_DELETE)
+       free (release->text);
+
+      free (release);
+    }
+  rl_undo_list = (UNDO_LIST *)NULL;
+  replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
+}
+
+/* Undo the next thing in the list.  Return 0 if there
+   is nothing to undo, or non-zero if there was. */
+int
+rl_do_undo ()
+{
+  UNDO_LIST *release;
+  int waiting_for_begin, start, end;
+
+#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
+
+  start = end = waiting_for_begin = 0;
+  do
+    {
+      if (!rl_undo_list)
+       return (0);
+
+      _rl_doing_an_undo = 1;
+      RL_SETSTATE(RL_STATE_UNDOING);
+
+      /* To better support vi-mode, a start or end value of -1 means
+        rl_point, and a value of -2 means rl_end. */
+      if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
+       {
+         start = TRANS (rl_undo_list->start);
+         end = TRANS (rl_undo_list->end);
+       }
+
+      switch (rl_undo_list->what)
+       {
+       /* Undoing deletes means inserting some text. */
+       case UNDO_DELETE:
+         rl_point = start;
+         rl_insert_text (rl_undo_list->text);
+         free (rl_undo_list->text);
+         break;
+
+       /* Undoing inserts means deleting some text. */
+       case UNDO_INSERT:
+         rl_delete_text (start, end);
+         rl_point = start;
+         break;
+
+       /* Undoing an END means undoing everything 'til we get to a BEGIN. */
+       case UNDO_END:
+         waiting_for_begin++;
+         break;
+
+       /* Undoing a BEGIN means that we are done with this group. */
+       case UNDO_BEGIN:
+         if (waiting_for_begin)
+           waiting_for_begin--;
+         else
+           rl_ding ();
+         break;
+       }
+
+      _rl_doing_an_undo = 0;
+      RL_UNSETSTATE(RL_STATE_UNDOING);
+
+      release = rl_undo_list;
+      rl_undo_list = rl_undo_list->next;
+      replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
+
+      free (release);
+    }
+  while (waiting_for_begin);
+
+  return (1);
+}
+#undef TRANS
+
+int
+_rl_fix_last_undo_of_type (type, start, end)
+     int type, start, end;
+{
+  UNDO_LIST *rl;
+
+  for (rl = rl_undo_list; rl; rl = rl->next)
+    {
+      if (rl->what == type)
+       {
+         rl->start = start;
+         rl->end = end;
+         return 0;
+       }
+    }
+  return 1;
+}
+
+/* Begin a group.  Subsequent undos are undone as an atomic operation. */
+int
+rl_begin_undo_group ()
+{
+  rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+  _rl_undo_group_level++;
+  return 0;
+}
+
+/* End an undo group started with rl_begin_undo_group (). */
+int
+rl_end_undo_group ()
+{
+  rl_add_undo (UNDO_END, 0, 0, 0);
+  _rl_undo_group_level--;
+  return 0;
+}
+
+/* Save an undo entry for the text from START to END. */
+int
+rl_modifying (start, end)
+     int start, end;
+{
+  if (start > end)
+    {
+      SWAP (start, end);
+    }
+
+  if (start != end)
+    {
+      char *temp = rl_copy_text (start, end);
+      rl_begin_undo_group ();
+      rl_add_undo (UNDO_DELETE, start, end, temp);
+      rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
+      rl_end_undo_group ();
+    }
+  return 0;
+}
+
+/* Revert the current line to its previous state. */
+int
+rl_revert_line (count, key)
+     int count, key;
+{
+  if (!rl_undo_list)
+    rl_ding ();
+  else
+    {
+      while (rl_undo_list)
+       rl_do_undo ();
+#if defined (VI_MODE)
+      if (rl_editing_mode == vi_mode)
+       rl_point = rl_mark = 0;         /* rl_end should be set correctly */
+#endif
+    }
+    
+  return 0;
+}
+
+/* Do some undoing of things that were done. */
+int
+rl_undo_command (count, key)
+     int count, key;
+{
+  if (count < 0)
+    return 0;  /* Nothing to do. */
+
+  while (count)
+    {
+      if (rl_do_undo ())
+       count--;
+      else
+       {
+         rl_ding ();
+         break;
+       }
+    }
+  return 0;
+}
index 48e44ec4865efb93c93856f20f89365955f80639..3d0061768ea2e8c4e24f6ab2835d2dc5f0018921 100644 (file)
--- a/locale.c
+++ b/locale.c
@@ -251,6 +251,20 @@ set_lang (var, value)
   return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
 }
 
+/* Set default values for LANG and LC_ALL.  Default values for all other
+   locale-related variables depend on these. */
+void
+set_default_lang ()
+{
+  char *v;
+
+  v = get_string_value ("LC_ALL");
+  set_locale_var ("LC_ALL", v);
+
+  v = get_string_value ("LANG");
+  set_lang ("LANG", v);
+}
+
 /* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
    The precedence is as POSIX.2 specifies:  LC_ALL has precedence over
    the specific locale variables, and LANG, if set, is used as the default. */
@@ -267,7 +281,7 @@ get_locale_var (var)
   if (locale == 0 || *locale == 0)
     locale = lang;
   if (locale == 0 || *locale == 0)
-    locale = default_locale;   /* system-dependent; not really portable */
+    locale = default_locale;   /* system-dependent; not really portable.  should it be "C"? */
 
   return (locale);
 }
@@ -279,12 +293,9 @@ static int
 reset_locale_vars ()
 {
 #if defined (HAVE_SETLOCALE)
-  char *locale;
-
-  locale = lang;
-  if (locale == 0 || *locale == '\0')
-    locale = default_locale;
-  if (setlocale (LC_ALL, locale) == 0)
+  if (lang == 0 || *lang == '\0')
+    maybe_make_export_env ();          /* trust that this will change environment for setlocale */
+  if (setlocale (LC_ALL, lang ? lang : "") == 0)
     return 0;
 
 #  if defined (LC_CTYPE)
diff --git a/locale.c~ b/locale.c~
new file mode 100644 (file)
index 0000000..bce1017
--- /dev/null
+++ b/locale.c~
@@ -0,0 +1,514 @@
+/* locale.c - Miscellaneous internationalization functions. */
+
+/* Copyright (C) 1996-2004 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#include "config.h"
+
+#include "bashtypes.h"
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "bashintl.h"
+#include "bashansi.h"
+#include <stdio.h>
+#include "chartypes.h"
+
+#include "shell.h"
+#include "input.h"     /* For bash_input */
+
+extern int dump_translatable_strings, dump_po_strings;
+
+/* The current locale when the program begins */
+static char *default_locale;
+
+/* The current domain for textdomain(3). */
+static char *default_domain;
+static char *default_dir;
+
+/* tracks the value of LC_ALL; used to override values for other locale
+   categories */
+static char *lc_all;
+
+/* tracks the value of LC_ALL; used to provide defaults for locale
+   categories */
+static char *lang;
+
+/* Called to reset all of the locale variables to their appropriate values
+   if (and only if) LC_ALL has not been assigned a value. */
+static int reset_locale_vars __P((void));
+
+static void locale_setblanks __P((void));
+
+/* Set the value of default_locale and make the current locale the
+   system default locale.  This should be called very early in main(). */
+void
+set_default_locale ()
+{
+#if defined (HAVE_SETLOCALE)
+  default_locale = setlocale (LC_ALL, "");
+  if (default_locale)
+    default_locale = savestring (default_locale);
+itrace("default locale = %s", default_locale ? default_locale : "NULL");
+#endif /* HAVE_SETLOCALE */
+  bindtextdomain (PACKAGE, LOCALEDIR);
+  textdomain (PACKAGE);
+}
+
+/* Set default values for LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_NUMERIC and
+   LC_TIME if they are not specified in the environment, but LC_ALL is.  This
+   should be called from main() after parsing the environment. */
+void
+set_default_locale_vars ()
+{
+  char *val;
+  int r;
+
+#if defined (HAVE_SETLOCALE)
+
+#  if defined (LC_CTYPE)
+  val = get_string_value ("LC_CTYPE");
+  if (val == 0 && lc_all && *lc_all)
+    {
+      setlocale (LC_CTYPE, lc_all);
+      locale_setblanks ();
+    }
+#  endif
+
+#  if defined (LC_COLLATE)
+  val = get_string_value ("LC_COLLATE");
+  if (val == 0 && lc_all && *lc_all)
+    setlocale (LC_COLLATE, lc_all);
+#  endif /* LC_COLLATE */
+
+#  if defined (LC_MESSAGES)
+  val = get_string_value ("LC_MESSAGES");
+  if (val == 0 && lc_all && *lc_all)
+    setlocale (LC_MESSAGES, lc_all);
+#  endif /* LC_MESSAGES */
+
+#  if defined (LC_NUMERIC)
+  val = get_string_value ("LC_NUMERIC");
+  if (val == 0 && lc_all && *lc_all)
+    setlocale (LC_NUMERIC, lc_all);
+#  endif /* LC_NUMERIC */
+
+#  if defined (LC_TIME)
+  val = get_string_value ("LC_TIME");
+  if (val == 0 && lc_all && *lc_all)
+    setlocale (LC_TIME, lc_all);
+#  endif /* LC_TIME */
+
+#endif /* HAVE_SETLOCALE */
+
+  val = get_string_value ("TEXTDOMAIN");
+  if (val && *val)
+    {
+      FREE (default_domain);
+      default_domain = savestring (val);
+#if 0
+      /* Don't want to override the shell's textdomain as the default */
+      textdomain (default_domain);
+#endif
+    }
+
+  val = get_string_value ("TEXTDOMAINDIR");
+  if (val && *val)
+    {
+      FREE (default_dir);
+      default_dir = savestring (val);
+      if (default_domain && *default_domain)
+       bindtextdomain (default_domain, default_dir);
+    }
+}
+
+/* Set one of the locale categories (specified by VAR) to VALUE.  Returns 1
+  if successful, 0 otherwise. */
+int
+set_locale_var (var, value)
+     char *var, *value;
+{
+  int r;
+
+  if (var[0] == 'T' && var[10] == 0)           /* TEXTDOMAIN */
+    {
+      FREE (default_domain);
+      default_domain = value ? savestring (value) : (char *)NULL;
+#if 0
+      /* Don't want to override the shell's textdomain as the default */
+      textdomain (default_domain);
+#endif
+      return (1);
+    }
+  else if (var[0] == 'T')                      /* TEXTDOMAINDIR */
+    {
+      FREE (default_dir);
+      default_dir = value ? savestring (value) : (char *)NULL;
+      if (default_domain && *default_domain)
+       bindtextdomain (default_domain, default_dir);
+      return (1);
+    }
+
+  /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
+
+  else if (var[3] == 'A')                      /* LC_ALL */
+    {
+      FREE (lc_all);
+      if (value)
+       lc_all = savestring (value);
+      else
+       {
+         lc_all = (char *)xmalloc (1);
+         lc_all[0] = '\0';
+       }
+#if defined (HAVE_SETLOCALE)
+      r = *lc_all ? (setlocale (LC_ALL, lc_all) != 0) : reset_locale_vars ();
+      locale_setblanks ();
+      return r;
+#else
+      return (1);
+#endif
+    }
+
+#if defined (HAVE_SETLOCALE)
+  else if (var[3] == 'C' && var[4] == 'T')     /* LC_CTYPE */
+    {
+#  if defined (LC_CTYPE)
+      if (lc_all == 0 || *lc_all == '\0')
+       {
+         r = (setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")) != 0);
+         locale_setblanks ();
+         return r;
+       }
+#  endif
+    }
+  else if (var[3] == 'C' && var[4] == 'O')     /* LC_COLLATE */
+    {
+#  if defined (LC_COLLATE)
+      if (lc_all == 0 || *lc_all == '\0')
+       return (setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")) != 0);
+#  endif /* LC_COLLATE */
+    }
+  else if (var[3] == 'M' && var[4] == 'E')     /* LC_MESSAGES */
+    {
+#  if defined (LC_MESSAGES)
+      if (lc_all == 0 || *lc_all == '\0')
+       return (setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")) != 0);
+#  endif /* LC_MESSAGES */
+    }
+  else if (var[3] == 'N' && var[4] == 'U')     /* LC_NUMERIC */
+    {
+#  if defined (LC_NUMERIC)
+      if (lc_all == 0 || *lc_all == '\0')
+       return (setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")) != 0);
+#  endif /* LC_NUMERIC */
+    }
+  else if (var[3] == 'T' && var[4] == 'I')     /* LC_TIME */
+    {
+#  if defined (LC_TIME)
+      if (lc_all == 0 || *lc_all == '\0')
+       return (setlocale (LC_TIME, get_locale_var ("LC_TIME")) != 0);
+#  endif /* LC_TIME */
+    }
+#endif /* HAVE_SETLOCALE */
+  
+
+  return (0);
+}
+
+/* Called when LANG is assigned a value.  Tracks value in `lang'.  Calls
+   reset_locale_vars() to reset any default values if LC_ALL is unset or
+   null. */
+int
+set_lang (var, value)
+     char *var, *value;
+{
+  FREE (lang);
+  if (value)
+    lang = savestring (value);
+  else
+    {
+      lang = (char *)xmalloc (1);
+      lang[0] = '\0';
+    }
+    
+  return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
+}
+
+/* Set default values for LANG and LC_ALL.  Default values for all other
+   locale-related variables depend on these. */
+void
+set_default_lang ()
+{
+  char *v;
+
+  v = get_string_value ("LC_ALL");
+  set_locale_var ("LC_ALL", v);
+
+  v = get_string_value ("LANG");
+  set_lang ("LANG", v);
+}
+
+/* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
+   The precedence is as POSIX.2 specifies:  LC_ALL has precedence over
+   the specific locale variables, and LANG, if set, is used as the default. */
+char *
+get_locale_var (var)
+     char *var;
+{
+  char *locale;
+
+  locale = lc_all;
+
+  if (locale == 0 || *locale == 0)
+    locale = get_string_value (var);
+  if (locale == 0 || *locale == 0)
+    locale = lang;
+  if (locale == 0 || *locale == 0)
+    locale = default_locale;   /* system-dependent; not really portable.  should it be "C"? */
+
+  return (locale);
+}
+
+/* Called to reset all of the locale variables to their appropriate values
+   if (and only if) LC_ALL has not been assigned a value.  DO NOT CALL THIS
+   IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
+static int
+reset_locale_vars ()
+{
+#if defined (HAVE_SETLOCALE)
+  char *locale;
+
+  if (lang == 0 || *lang == '\0')
+    maybe_make_export_env ();          /* trust that this will change environment for setlocale */
+  if (setlocale (LC_ALL, lang ? lang : "") == 0)
+    return 0;
+
+itrace("setlocale(LC_ALL, \"%s\")", lang ? lang : "");
+locale = setlocale(LC_ALL, (char *)NULL);
+itrace("current locale = %s", locale ? locale : "NULL");
+
+#  if defined (LC_CTYPE)
+  setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
+#  endif
+#  if defined (LC_COLLATE)
+  setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
+#  endif
+#  if defined (LC_MESSAGES)
+  setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
+#  endif
+#  if defined (LC_NUMERIC)
+  setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
+#  endif
+#  if defined (LC_TIME)
+  setlocale (LC_TIME, get_locale_var ("LC_TIME"));
+#  endif
+
+  locale_setblanks ();  
+
+#endif
+  return 1;
+}
+
+/* Translate the contents of STRING, a $"..." quoted string, according
+   to the current locale.  In the `C' or `POSIX' locale, or if gettext()
+   is not available, the passed string is returned unchanged.  The
+   length of the translated string is returned in LENP, if non-null. */
+char *
+localetrans (string, len, lenp)
+     char *string;
+     int len, *lenp;
+{
+  char *locale, *t;
+  char *translated;
+  int tlen;
+
+  /* Don't try to translate null strings. */
+  if (string == 0 || *string == 0)
+    {
+      if (lenp)
+       *lenp = 0;
+      return ((char *)NULL);
+    }
+
+  locale = get_locale_var ("LC_MESSAGES");
+
+  /* If we don't have setlocale() or the current locale is `C' or `POSIX',
+     just return the string.  If we don't have gettext(), there's no use
+     doing anything else. */
+  if (locale == 0 || locale[0] == '\0' ||
+      (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
+    {
+      t = (char *)xmalloc (len + 1);
+      strcpy (t, string);
+      if (lenp)
+       *lenp = len;
+      return (t);
+    }
+
+  /* Now try to translate it. */
+  if (default_domain && *default_domain)
+    translated = dgettext (default_domain, string);
+  else
+    translated = string;
+
+  if (translated == string)    /* gettext returns its argument if untranslatable */
+    {
+      t = (char *)xmalloc (len + 1);
+      strcpy (t, string);
+      if (lenp)
+       *lenp = len;
+    }
+  else
+    {
+      tlen = strlen (translated);
+      t = (char *)xmalloc (tlen + 1);
+      strcpy (t, translated);
+      if (lenp)
+       *lenp = tlen;
+    }
+  return (t);
+}
+
+/* Change a bash string into a string suitable for inclusion in a `po' file.
+   This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
+char *
+mk_msgstr (string, foundnlp)
+     char *string;
+     int *foundnlp;
+{
+  register int c, len;
+  char *result, *r, *s;
+
+  for (len = 0, s = string; s && *s; s++)
+    {
+      len++;
+      if (*s == '"' || *s == '\\')
+       len++;
+      else if (*s == '\n')
+       len += 5;
+    }
+  
+  r = result = (char *)xmalloc (len + 3);
+  *r++ = '"';
+
+  for (s = string; s && (c = *s); s++)
+    {
+      if (c == '\n')   /* <NL> -> \n"<NL>" */
+       {
+         *r++ = '\\';
+         *r++ = 'n';
+         *r++ = '"';
+         *r++ = '\n';
+         *r++ = '"';
+         if (foundnlp)
+           *foundnlp = 1;
+         continue;
+       }
+      if (c == '"' || c == '\\')
+       *r++ = '\\';
+      *r++ = c;
+    }
+
+  *r++ = '"';
+  *r++ = '\0';
+
+  return result;
+}
+
+/* $"..." -- Translate the portion of STRING between START and END
+   according to current locale using gettext (if available) and return
+   the result.  The caller will take care of leaving the quotes intact.
+   The string will be left without the leading `$' by the caller.
+   If translation is performed, the translated string will be double-quoted
+   by the caller.  The length of the translated string is returned in LENP,
+   if non-null. */
+char *
+localeexpand (string, start, end, lineno, lenp)
+     char *string;
+     int start, end, lineno, *lenp;
+{
+  int len, tlen, foundnl;
+  char *temp, *t, *t2;
+
+  temp = (char *)xmalloc (end - start + 1);
+  for (tlen = 0, len = start; len < end; )
+    temp[tlen++] = string[len++];
+  temp[tlen] = '\0';
+
+  /* If we're just dumping translatable strings, don't do anything with the
+     string itself, but if we're dumping in `po' file format, convert it into
+     a form more palatable to gettext(3) and friends by quoting `"' and `\'
+     with backslashes and converting <NL> into `\n"<NL>"'.  If we find a
+     newline in TEMP, we first output a `msgid ""' line and then the
+     translated string; otherwise we output the `msgid' and translated
+     string all on one line. */
+  if (dump_translatable_strings)
+    {
+      if (dump_po_strings)
+       {
+         foundnl = 0;
+         t = mk_msgstr (temp, &foundnl);
+         t2 = foundnl ? "\"\"\n" : "";
+
+         printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
+                       yy_input_name (), lineno, t2, t);
+         free (t);
+       }
+      else
+       printf ("\"%s\"\n", temp);
+
+      if (lenp)
+       *lenp = tlen;
+      return (temp);
+    }
+  else if (*temp)
+    {
+      t = localetrans (temp, tlen, &len);
+      free (temp);
+      if (lenp)
+       *lenp = len;
+      return (t);
+    }
+  else
+    {
+      if (lenp)
+       *lenp = 0;
+      return (temp);
+    }
+}
+
+/* Set every character in the <blank> character class to be a shell break
+   character for the lexical analyzer when the locale changes. */
+static void
+locale_setblanks ()
+{
+  int x;
+
+  for (x = 0; x < sh_syntabsiz; x++)
+    {
+      if (isblank (x))
+       sh_syntaxtab[x] |= CSHBRK;
+      else if (member (x, shell_break_chars))
+       sh_syntaxtab[x] |= CSHBRK;
+      else
+       sh_syntaxtab[x] &= ~CSHBRK;
+    }
+}
diff --git a/shell.c b/shell.c
index a28442c95f1af34cfddf8f65ec69b7f77219a759..6693f852efbb2013bfb1c56ab3c4dc55d78ca989 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -532,6 +532,7 @@ main (argc, argv, env)
      Variables from the environment are expected to be set, etc. */
   shell_initialize ();
 
+  set_default_lang ();
   set_default_locale_vars ();
 
   if (interactive_shell)
index d54f10a21b1aa67ec81e1d19a0518e54c3e130b6..449975e060b92e07f5a8561707e261163f4b526e 100644 (file)
@@ -346,6 +346,8 @@ initialize_shell_variables (env, privmode)
       else
        {
          temp_var = bind_variable (name, string, 0);
+if (strcmp(name,"LANG") == 0)
+  itrace("bound LANG to %s", string);
          VSETATTR (temp_var, (att_exported | att_imported));
          array_needs_making = 1;
        }
@@ -440,7 +442,7 @@ initialize_shell_variables (env, privmode)
   bind_variable ("OPTERR", "1", 0);
   sh_opterr = 1;
 
-  if (login_shell == 1)
+  if (login_shell == 1 && posixly_correct == 0)
     set_home_var ();
 
   /* Get the full pathname to THIS shell, and set the BASH variable
@@ -1359,7 +1361,7 @@ get_dirstack (self)
   ARRAY *a;
   WORD_LIST *l;
 
-  l = get_directory_stack ();
+  l = get_directory_stack (0);
   a = array_from_word_list (l);
   array_dispose (array_cell (self));
   dispose_words (l);