commit bash-20050825 snapshot
authorChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 18:50:17 +0000 (13:50 -0500)
committerChet Ramey <chet.ramey@case.edu>
Sat, 3 Dec 2011 18:50:17 +0000 (13:50 -0500)
42 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
bashline.c
bashline.c~
builtins/cd.def
builtins/fc.def
builtins/fc.def~
builtins/fg_bg.def
builtins/history.def
builtins/kill.def
builtins/type.def
doc/bash.1
doc/bash.1~
doc/bashref.texi
doc/bashref.texi~
doc/version.texi
doc/version.texi~
execute_cmd.c
general.c
general.c~
general.h
general.h~
jobs.c
jobs.h
lib/readline/bind.c
lib/readline/bind.c~
lib/readline/doc/readline.3
lib/readline/doc/readline.3~
lib/readline/doc/rluser.texi
lib/readline/doc/rluser.texi~
lib/readline/doc/version.texi
lib/readline/doc/version.texi~
lib/readline/history.c
lib/readline/isearch.c
lib/readline/isearch.c~ [new file with mode: 0644]
lib/readline/rlprivate.h
lib/readline/rlprivate.h~ [new file with mode: 0644]
lib/readline/search.c
lib/readline/search.c~ [new file with mode: 0644]
lib/sh/pathphys.c
lib/sh/pathphys.c~ [new file with mode: 0644]
nojobs.c

index bb67b2f..257da55 100644 (file)
@@ -11949,3 +11949,98 @@ builtins/read.def
          `read', call sync_buffered_stream to seek backward in the input
          stream if necessary (XXX - should we do this for all shell builtins?)
 
+                                  8/23
+                                  ----
+builtins/cd.def
+       - in posix mode, if canonicalization of the absolute pathname fails
+         because the path length exceeds PATH_MAX, but the length of the passed
+         (non-absolute) pathname does not, attempt the chdir, just as when
+         not in posix mode
+
+builtins/type.def
+       - don't have describe_command call sh_makepath if the full path found
+         is already an absolute pathname (sh_makepath will stick $PWD onto the
+         front of it)
+
+                                  8/24
+                                  ----
+
+jobs.c
+       - in posix mode, don't have start_job print out and indication of
+         whether the job started by `bg' is the current or previous job
+       - change start_job to return success if a job to be resumed in the
+         background is already running.  This means that bg won't fail when
+         asked to bg a background job, as SUSv3/XPG6 requires
+       - new function, init_job_stats, to zero out the global jobstats struct
+
+{jobs,nojobs}.c
+       - change kill_pid to handle pids < -1 by killing process groups
+
+jobs.h
+       - extern declaration for init_job_stats
+
+lib/readline/history.c
+       - check whether or not the history list is null in remove_history
+
+builtins/history.def
+       - delete_last_history is no longer static so fc builtin can use it
+
+builtins/fc.def
+       - use free_history_entry in fc_replhist instead of freeing struct
+         members individually
+       - call delete_last_history from fc_replhist instead of using inline
+         code
+       - if editing (-l not specified), make sure the fc command that caused
+         the editing is removed from the history list, as POSIX specifies
+
+builtins/kill.def
+       - just call kill_pid with any pid argument and let it handle pids < -1
+         This is the only way to let kill_pid know whether a negative pid or
+         a job spec was supplied as an argument to kill
+
+builtins/fg_bg.def
+       - force fg_bg to return EXECUTION_SUCCESS explicitly if called by bg
+         and start_job returns successfully
+       - bg now returns success only if all the specified jobs were resumed
+         successfully
+
+execute_cmd.c
+       - call init_job_stats from initialize_subshell to zero out the global
+         job stats structure
+
+                                  8/25
+                                  ----
+bashline.c
+       - change vi_edit_and_execute_command to just call vi when in posix
+         mode, instead of checking $FCEDIT and $EDITOR
+
+lib/readline/search.c
+       - if in vi_mode, call rl_free_undo_list in make_history_line_current
+         to dispose of undo list accumulated while reading the search string
+         (if this isn't done, since vi mode leaves the current history
+         position at the entry which matched the search, the call to
+         rl_revert_line in rl_internal_teardown will mangle the matched
+         history entry using a bogus rl_undo_list)
+       - call rl_free_undo_list after reading a non-incremental search string
+         into rl_line_buffer -- that undo list should be discarded
+
+lib/readline/rlprivate.h
+       - add UNDO_LIST * member to search context struct
+
+lib/readline/isearch.c
+       - initialize UNDO_LIST *save_undo_list member of search context struct
+
+                                  8/27
+                                  ----
+lib/readline/bind.c
+       - change rl_parse_and_bind to strip whitespace from the end of a
+         variable value assignment before calling rl_variable_bind
+
+doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
+       - clarified the language concerning parsing values for boolean
+         variables in assignment statements
+
+                                  8/28
+                                  ----
+lib/sh/pathphys.c
+       - fix small memory leak in sh_realpath reported by Eric Blake
index 1fb4487..baa76bd 100644 (file)
@@ -11944,3 +11944,98 @@ builtins/cd.def
        - in posix mode, pwd needs to check that the value it prints and `.'
          are the same file
 
+builtins/read.def
+       - if reading input from stdin in a non-interactive shell and calling
+         `read', call sync_buffered_stream to seek backward in the input
+         stream if necessary (XXX - should we do this for all shell builtins?)
+
+                                  8/23
+                                  ----
+builtins/cd.def
+       - in posix mode, if canonicalization of the absolute pathname fails
+         because the path length exceeds PATH_MAX, but the length of the passed
+         (non-absolute) pathname does not, attempt the chdir, just as when
+         not in posix mode
+
+builtins/type.def
+       - don't have describe_command call sh_makepath if the full path found
+         is already an absolute pathname (sh_makepath will stick $PWD onto the
+         front of it)
+
+                                  8/24
+                                  ----
+
+jobs.c
+       - in posix mode, don't have start_job print out and indication of
+         whether the job started by `bg' is the current or previous job
+       - change start_job to return success if a job to be resumed in the
+         background is already running.  This means that bg won't fail when
+         asked to bg a background job, as SUSv3/XPG6 requires
+       - new function, init_job_stats, to zero out the global jobstats struct
+
+{jobs,nojobs}.c
+       - change kill_pid to handle pids < -1 by killing process groups
+
+jobs.h
+       - extern declaration for init_job_stats
+
+lib/readline/history.c
+       - check whether or not the history list is null in remove_history
+
+builtins/history.def
+       - delete_last_history is no longer static so fc builtin can use it
+
+builtins/fc.def
+       - use free_history_entry in fc_replhist instead of freeing struct
+         members individually
+       - call delete_last_history from fc_replhist instead of using inline
+         code
+       - if editing (-l not specified), make sure the fc command that caused
+         the editing is removed from the history list, as POSIX specifies
+
+builtins/kill.def
+       - just call kill_pid with any pid argument and let it handle pids < -1
+         This is the only way to let kill_pid know whether a negative pid or
+         a job spec was supplied as an argument to kill
+
+builtins/fg_bg.def
+       - force fg_bg to return EXECUTION_SUCCESS explicitly if called by bg
+         and start_job returns successfully
+       - bg now returns success only if all the specified jobs were resumed
+         successfully
+
+execute_cmd.c
+       - call init_job_stats from initialize_subshell to zero out the global
+         job stats structure
+
+                                  8/25
+                                  ----
+bashline.c
+       - change vi_edit_and_execute_command to just call vi when in posix
+         mode, instead of checking $FCEDIT and $EDITOR
+
+lib/readline/search.c
+       - if in vi_mode, call rl_free_undo_list in make_history_line_current
+         to dispose of undo list accumulated while reading the search string
+         (if this isn't done, since vi mode leaves the current history
+         position at the entry which matched the search, the call to
+         rl_revert_line in rl_internal_teardown will mangle the matched
+         history entry using a bogus rl_undo_list)
+       - call rl_free_undo_list after reading a non-incremental search string
+         into rl_line_buffer -- that undo list should be discarded
+
+lib/readline/rlprivate.h
+       - add UNDO_LIST * member to search context struct
+
+lib/readline/isearch.c
+       - initialize UNDO_LIST *save_undo_list member of search context struct
+
+                                  8/27
+                                  ----
+lib/readline/bind.c
+       - change rl_parse_and_bind to strip whitespace from the end of a
+         variable value assignment before calling rl_variable_bind
+
+doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
+       - clarified the language concerning parsing values for boolean
+         variables in assignment statements
index ed33b53..3fdee66 100644 (file)
@@ -798,6 +798,7 @@ operate_and_get_next (count, c)
 
 #define VI_EDIT_COMMAND                "fc -e \"${VISUAL:-${EDITOR:-vi}}\""
 #define EMACS_EDIT_COMMAND     "fc -e \"${VISUAL:-${EDITOR:-emacs}}\""
+#define POSIX_VI_EDIT_COMMAND  "fc -e vi"
 
 static int
 edit_and_execute_command (count, c, editing_mode, edit_command)
@@ -857,7 +858,10 @@ static int
 vi_edit_and_execute_command (count, c)
      int count, c;
 {
-  return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND));
+  if (posixly_correct)
+    return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND));
+  else
+    return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND));
 }
 #endif /* VI_MODE */
 
index 76d0f18..ed33b53 100644 (file)
@@ -1522,6 +1522,8 @@ command_subst_completion_function (text, state)
         put the lcd in matches[0].  Skip over it. */
       cmd_index = matches && matches[0] && matches[1];
 
+      /* If there's a single match and it's a directory, set the append char
+        to the expected `/'.  Otherwise, don't append anything. */
       if (matches && matches[0] && matches[1] == 0 && test_for_directory (matches[0]))
        rl_completion_append_character = '/';
       else
index e9be35a..dad6251 100644 (file)
@@ -400,7 +400,7 @@ change_to_directory (newdir, nolinks)
      int nolinks;
 {
   char *t, *tdir;
-  int err, canon_failed, r;
+  int err, canon_failed, r, ndlen, dlen;
 
   tdir = (char *)NULL;
 
@@ -418,6 +418,9 @@ change_to_directory (newdir, nolinks)
   tdir = nolinks ? sh_physpath (t, 0)
                 : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
 
+  ndlen = strlen (newdir);
+  dlen = strlen (t);
+
   /* Use the canonicalized version of NEWDIR, or, if canonicalization
      failed, use the non-canonical form. */
   canon_failed = 0;
@@ -433,7 +436,7 @@ change_to_directory (newdir, nolinks)
   /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
      returns NULL (because it checks the path, it will return NULL if the
      resolved path doesn't exist), fail immediately. */
-  if (posixly_correct && nolinks == 0 && canon_failed)
+  if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
     {
 #if defined ENAMETOOLONG
       if (errno != ENOENT && errno != ENAMETOOLONG)
index a2bf881..6645d8b 100644 (file)
@@ -1,7 +1,7 @@
 This file is fc.def, from which is created fc.c.
 It implements the builtin "fc" in Bash.
 
-Copyright (C) 1987-2003 Free Software Foundation, Inc.
+Copyright (C) 1987-2005 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -89,6 +89,7 @@ extern int posixly_correct;
 extern int unlink __P((const char *));
 
 extern FILE *sh_mktmpfp __P((char *, int, char **));
+extern int delete_last_history __P((void));
 
 /* **************************************************************** */
 /*                                                                 */
@@ -286,6 +287,11 @@ fc_builtin (list)
      line was actually added (HISTIGNORE may have caused it to not be),
      so we check hist_last_line_added. */
 
+  /* "When not  listing, he fc command that caused the editing shall not be
+     entered into the history list." */
+  if (listing == 0 && hist_last_line_added)
+    delete_last_history ();
+
   last_hist = i - 1 - hist_last_line_added;
 
   if (list)
@@ -497,7 +503,7 @@ fc_gethist (command, hlist)
 {
   int i;
 
-  if (!hlist)
+  if (hlist == 0)
     return ((char *)NULL);
 
   i = fc_gethnum (command, hlist);
@@ -581,41 +587,18 @@ static void
 fc_replhist (command)
      char *command;
 {
-  register int i;
-  HIST_ENTRY **hlist, *histent, *discard;
   int n;
 
   if (command == 0 || *command == '\0')
     return;
 
-  hlist = history_list ();
-
-  if (hlist == NULL)
-    return;
-
-  for (i = 0; hlist[i]; i++);
-  i--;
-
-  /* History_get () takes a parameter that should be
-     offset by history_base. */
-
-  histent = history_get (history_base + i);    /* Don't free this */
-  if (histent == NULL)
-    return;
-
   n = strlen (command);
-
   if (command[n - 1] == '\n')
     command[n - 1] = '\0';
 
   if (command && *command)
     {
-      discard = remove_history (i);
-      if (discard)
-       {
-         FREE (discard->line);
-         free ((char *) discard);
-       }
+      delete_last_history ();
       maybe_add_history (command);     /* Obeys HISTCONTROL setting. */
     }
 }
@@ -628,13 +611,16 @@ fc_addhist (line)
 {
   register int n;
 
+  if (line == 0 || *line == 0)
+    return;
+
   n = strlen (line);
 
   if (line[n - 1] == '\n')
     line[n - 1] = '\0';
 
   if (line && *line)
-    maybe_add_history (line);
+    maybe_add_history (line);          /* Obeys HISTCONTROL setting. */
 }
 #endif
 
index 93c7ae3..57b5384 100644 (file)
@@ -84,10 +84,12 @@ extern int errno;
 extern int echo_input_at_read;
 extern int current_command_line_count;
 extern int literal_history;
+extern int posixly_correct;
 
 extern int unlink __P((const char *));
 
 extern FILE *sh_mktmpfp __P((char *, int, char **));
+extern int delete_last_history __P((void));
 
 /* **************************************************************** */
 /*                                                                 */
@@ -155,6 +157,7 @@ static void fc_addhist __P((char *));
 
 /* String to execute on a file that we want to edit. */
 #define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
+#define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
 
 int
 fc_builtin (list)
@@ -166,7 +169,7 @@ fc_builtin (list)
   int histbeg, histend, last_hist, retval, opt;
   FILE *stream;
   REPL *rlist, *rl;
-  char *ename, *command, *newcom;
+  char *ename, *command, *newcom, *fcedit;
   HIST_ENTRY **hlist;
   char *fn;
 
@@ -284,6 +287,11 @@ fc_builtin (list)
      line was actually added (HISTIGNORE may have caused it to not be),
      so we check hist_last_line_added. */
 
+  /* "When not  listing, he fc command that caused the editing shall not be
+     entered into the history list." */
+  if (listing == 0 && hist_last_line_added)
+    delete_last_history ();
+
   last_hist = i - 1 - hist_last_line_added;
 
   if (list)
@@ -302,7 +310,7 @@ fc_builtin (list)
       if (listing)
        {
          histend = last_hist;
-         histbeg = histend - 16;
+         histbeg = histend - 16 + 1;   /* +1 because loop below uses >= */
          if (histbeg < 0)
            histbeg = 0;
        }
@@ -347,7 +355,12 @@ fc_builtin (list)
       if (numbering)
        fprintf (stream, "%d", i + history_base);
       if (listing)
-       fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
+       {
+         if (posixly_correct)
+           fputs ("\t", stream);
+         else
+           fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
+       }
       fprintf (stream, "%s\n", histline (i));
     }
 
@@ -364,7 +377,8 @@ fc_builtin (list)
     }
   else
     {
-      command = (char *)xmalloc (3 + strlen (FC_EDIT_COMMAND) + strlen (fn));
+      fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
+      command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
       sprintf (command, "%s %s", FC_EDIT_COMMAND, fn);
     }
   retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
@@ -489,7 +503,7 @@ fc_gethist (command, hlist)
 {
   int i;
 
-  if (!hlist)
+  if (hlist == 0)
     return ((char *)NULL);
 
   i = fc_gethnum (command, hlist);
@@ -573,41 +587,18 @@ static void
 fc_replhist (command)
      char *command;
 {
-  register int i;
-  HIST_ENTRY **hlist, *histent, *discard;
   int n;
 
   if (command == 0 || *command == '\0')
     return;
 
-  hlist = history_list ();
-
-  if (hlist == NULL)
-    return;
-
-  for (i = 0; hlist[i]; i++);
-  i--;
-
-  /* History_get () takes a parameter that should be
-     offset by history_base. */
-
-  histent = history_get (history_base + i);    /* Don't free this */
-  if (histent == NULL)
-    return;
-
   n = strlen (command);
-
   if (command[n - 1] == '\n')
     command[n - 1] = '\0';
 
   if (command && *command)
     {
-      discard = remove_history (i);
-      if (discard)
-       {
-         FREE (discard->line);
-         free ((char *) discard);
-       }
+      delete_last_history ();
       maybe_add_history (command);     /* Obeys HISTCONTROL setting. */
     }
 }
@@ -620,13 +611,16 @@ fc_addhist (line)
 {
   register int n;
 
+  if (line == 0 || *line == 0)
+    return;
+
   n = strlen (line);
 
   if (line[n - 1] == '\n')
     line[n - 1] = '\0';
 
   if (line && *line)
-    maybe_add_history (line);
+    maybe_add_history (line);          /* Obeys HISTCONTROL setting. */
 }
 #endif
 
index c5e2e47..c14381b 100644 (file)
@@ -82,8 +82,8 @@ fg_builtin (list)
 $BUILTIN bg
 $FUNCTION bg_builtin
 $DEPENDS_ON JOB_CONTROL
-$SHORT_DOC bg [job_spec]
-Place JOB_SPEC in the background, as if it had been started with
+$SHORT_DOC bg [job_spec ...]
+Place each JOB_SPEC in the background, as if it had been started with
 `&'.  If JOB_SPEC is not present, the shell's notion of the current
 job is used.
 $END
@@ -108,9 +108,11 @@ bg_builtin (list)
 
   /* This relies on the fact that fg_bg() takes a WORD_LIST *, but only acts
      on the first member (if any) of that list. */
+  r = EXECUTION_SUCCESS;
   do
     {
-      r = fg_bg (list, 0);
+      if (fg_bg (list, 0) == EXECUTION_FAILURE)
+       r = EXECUTION_FAILURE;
       if (list)
        list = list->next;
     }
@@ -160,7 +162,7 @@ fg_bg (list, foreground)
     {
     /* win: */
       UNBLOCK_CHILD (oset);
-      return (status);
+      return (foreground ? status : EXECUTION_SUCCESS);
     }
   else
     {
index 40708da..0086b0b 100644 (file)
@@ -78,10 +78,11 @@ extern int errno;
 
 extern int current_command_line_count;
 
+int delete_last_history __P((void));
+
 static char *histtime __P((HIST_ENTRY *, const char *));
 static void display_history __P((WORD_LIST *));
 static int delete_histent __P((int));
-static int delete_last_history __P((void));
 static void push_history __P((WORD_LIST *));
 static int expand_and_print_history __P((WORD_LIST *));
 
@@ -310,7 +311,7 @@ delete_histent (i)
   return 1;
 }
 
-static int
+int
 delete_last_history ()
 {
   register int i;
@@ -346,8 +347,6 @@ push_history (list)
 {
   char *s;
 
-if (current_command_line_count == 0)
-  itrace("push_history: current_command_line_count == 0");
   /* Delete the last history entry if it was a single entry added to the
      history list (generally the `history -s' itself), or if `history -s'
      is being used in a compound command and the compound command was
index 6bcfad1..bedbb1a 100644 (file)
@@ -170,7 +170,7 @@ kill_builtin (list)
        {
          pid = (pid_t) pid_value;
 
-         if ((pid < -1 ? kill_pid (-pid, sig, 1) : kill_pid (pid, sig, 0)) < 0)
+         if (kill_pid (pid, sig, pid < -1) < 0)
            {
              if (errno == EINVAL)
                sh_invalidsig (sigspec);
index 4d91cd8..d03ccb2 100644 (file)
@@ -372,6 +372,8 @@ describe_command (command, dflags)
              if (all == 0)
                break;
            }
+         else if (ABSPATH (full_path))
+           ;   /* placeholder; don't need to do anything yet */
          else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC))
            {
              f = MP_DOCWD | ((dflags & CDESC_ABSPATH) ? MP_RMDOT : 0);
index 4b7843d..3a5fa59 100644 (file)
@@ -6,12 +6,12 @@
 .\"    Case Western Reserve University
 .\"    chet@po.CWRU.Edu
 .\"
-.\"    Last Change: Fri Jul 15 23:15:01 EDT 2005
+.\"    Last Change: Sat Aug 27 13:28:44 EDT 2005
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2005 Jul 15" "GNU Bash-3.1-devel"
+.TH BASH 1 "2005 Aug 27" "GNU Bash-3.1-alpha1"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -4565,7 +4565,12 @@ file with a statement of the form
 Except where noted, readline variables can take the values
 .B On
 or
-.BR Off .
+.B Off
+(without regard to case).
+Unrecognized variable names are ignored.
+When a variable value is read, empty or null values, "on" (case-insensitive),
+and "1" are equivalent to \fBOn\fP.  All other values are equivalent to
+\fBOff\fP.
 The variables and their default values are:
 .PP
 .PD 0
@@ -5968,8 +5973,8 @@ If \fIjobspec\fP is not present, the shell's notion of the
 .B bg
 .I jobspec
 returns 0 unless run when job control is disabled or, when run with
-job control enabled, if the last \fIjobspec\fP was not found or was
-started without job control.
+job control enabled, any specified \fIjobspec\fP was not found
+or was started without job control.
 .TP
 \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP]
 .PD 0
index fc1318b..ffe92b6 100644 (file)
@@ -6,12 +6,12 @@
 .\"    Case Western Reserve University
 .\"    chet@po.CWRU.Edu
 .\"
-.\"    Last Change: Fri Jul 15 23:15:01 EDT 2005
+.\"    Last Change: Wed Aug 24 17:20:03 EDT 2005
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2005 Jul 15" "GNU Bash-3.1-devel"
+.TH BASH 1 "2005 Aug 24" "GNU Bash-3.1-alpha1"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -4634,7 +4634,7 @@ arrow keys.
 If set to \fBon\fP, tilde expansion is performed when readline
 attempts word completion.
 .TP
-.B history-preserve-point
+.B history\-preserve\-point (Off)
 If set to \fBon\fP, the history code attempts to place point at the
 same location on each history line retrieved with \fBprevious-history\fP
 or \fBnext-history\fP.
@@ -5968,8 +5968,8 @@ If \fIjobspec\fP is not present, the shell's notion of the
 .B bg
 .I jobspec
 returns 0 unless run when job control is disabled or, when run with
-job control enabled, if the last \fIjobspec\fP was not found or was
-started without job control.
+job control enabled, any specified \fIjobspec\fP was not found
+or was started without job control.
 .TP
 \fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP]
 .PD 0
index a0870b6..8abe4fe 100644 (file)
@@ -6090,6 +6090,11 @@ but without a leading @samp{#!}, Bash sets @code{$0} to the full pathname of
 the script as found by searching @code{$PATH}, rather than the command as
 typed by the user.
 
+@item
+The @code{fc} builtin checks @code{$EDITOR} as a program to edit history lines 
+if @code{FCEDIT} is unset, rather than defaulting directly to @code{ed}.
+@code{fc} uses @code{ed} if @code{EDITOR} is unset.
+
 @end enumerate
 
 @node Job Control
@@ -6219,8 +6224,8 @@ Resume each suspended job @var{jobspec} in the background, as if it
 had been started with @samp{&}.
 If @var{jobspec} is not supplied, the current job is used.
 The return status is zero unless it is run when job control is not
-enabled, or, when run with job control enabled, if the last
-@var{jobspec} was not found or the last @var{jobspec} specifies a job
+enabled, or, when run with job control enabled, any
+@var{jobspec} was not found or specifies a job
 that was started without job control.
 
 @item fg
index 401bc66..224ccc6 100644 (file)
@@ -4784,6 +4784,10 @@ prompt when the shell is interactive.
 Bash terminates after that number of seconds if input does
 not arrive.
 
+@item TMPDIR
+If set, Bash uses its value as the name of a directory in which
+Bash creates temporary files for the shell's use.
+
 @item UID
 The numeric real user id of the current user.  This variable is readonly.
 
@@ -6086,11 +6090,6 @@ but without a leading @samp{#!}, Bash sets @code{$0} to the full pathname of
 the script as found by searching @code{$PATH}, rather than the command as
 typed by the user.
 
-@item
-When using @samp{.} to source a shell script found in @code{$PATH}, bash
-checks execute permission bits rather than read permission bits, just as
-if it were searching for a command.
-
 @end enumerate
 
 @node Job Control
@@ -6220,8 +6219,8 @@ Resume each suspended job @var{jobspec} in the background, as if it
 had been started with @samp{&}.
 If @var{jobspec} is not supplied, the current job is used.
 The return status is zero unless it is run when job control is not
-enabled, or, when run with job control enabled, if the last
-@var{jobspec} was not found or the last @var{jobspec} specifies a job
+enabled, or, when run with job control enabled, any
+@var{jobspec} was not found or specifies a job
 that was started without job control.
 
 @item fg
index 638db25..52d2c4b 100644 (file)
@@ -2,9 +2,9 @@
 Copyright (C) 1988-2005 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Fri Jul 15 23:14:38 EDT 2005
+@set LASTCHANGE Sat Aug 27 13:54:54 EDT 2005
 
-@set EDITION 3.1-devel
-@set VERSION 3.1-devel
-@set UPDATED 15 July 2005
-@set UPDATED-MONTH July 2005
+@set EDITION 3.1-alpha1
+@set VERSION 3.1-alpha1
+@set UPDATED 27 August 2005
+@set UPDATED-MONTH August 2005
index 292eee5..f53d193 100644 (file)
@@ -2,9 +2,9 @@
 Copyright (C) 1988-2005 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Thu Jun 23 09:48:04 EDT 2005
+@set LASTCHANGE Wed Aug 24 17:22:10 EDT 2005
 
-@set EDITION 3.1-devel
-@set VERSION 3.1-devel
-@set UPDATED 30 April 2005
-@set UPDATED-MONTH April 2005
+@set EDITION 3.1-alpha1
+@set VERSION 3.1-alpha1
+@set UPDATED 24 August 2005
+@set UPDATED-MONTH August 2005
index 63da5a9..d05981b 100644 (file)
@@ -3780,6 +3780,7 @@ initialize_subshell ()
   /* Forget about the way job control was working. We are in a subshell. */
   without_job_control ();
   set_sigchld_handler ();
+  init_job_stats ();
 #endif /* JOB_CONTROL */
 
   /* Reset the values of the shell flags and options. */
index d399f06..3384e84 100644 (file)
--- a/general.c
+++ b/general.c
@@ -506,6 +506,36 @@ file_iswdir (fn)
   return (file_isdir (fn) && test_eaccess (fn, W_OK) == 0);
 }
 
+/* Return 1 if STRING contains an absolute pathname, else 0.  Used by `cd'
+   to decide whether or not to look up a directory name in $CDPATH. */
+int
+absolute_pathname (string)
+     const char *string;
+{
+  if (string == 0 || *string == '\0')
+    return (0);
+
+  if (ABSPATH(string))
+    return (1);
+
+  if (string[0] == '.' && PATHSEP(string[1]))  /* . and ./ */
+    return (1);
+
+  if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2]))      /* .. and ../ */
+    return (1);
+
+  return (0);
+}
+
+/* Return 1 if STRING is an absolute program name; it is absolute if it
+   contains any slashes.  This is used to decide whether or not to look
+   up through $PATH. */
+int
+absolute_program (string)
+     const char *string;
+{
+  return ((char *)xstrchr (string, '/') != (char *)NULL);
+}
 
 /* **************************************************************** */
 /*                                                                 */
@@ -540,37 +570,6 @@ make_absolute (string, dot_path)
   return (result);
 }
 
-/* Return 1 if STRING contains an absolute pathname, else 0.  Used by `cd'
-   to decide whether or not to look up a directory name in $CDPATH. */
-int
-absolute_pathname (string)
-     const char *string;
-{
-  if (string == 0 || *string == '\0')
-    return (0);
-
-  if (ABSPATH(string))
-    return (1);
-
-  if (string[0] == '.' && PATHSEP(string[1]))  /* . and ./ */
-    return (1);
-
-  if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2]))      /* .. and ../ */
-    return (1);
-
-  return (0);
-}
-
-/* Return 1 if STRING is an absolute program name; it is absolute if it
-   contains any slashes.  This is used to decide whether or not to look
-   up through $PATH. */
-int
-absolute_program (string)
-     const char *string;
-{
-  return ((char *)xstrchr (string, '/') != (char *)NULL);
-}
-
 /* Return the `basename' of the pathname in STRING (the stuff after the
    last '/').  If STRING is `/', just return it. */
 char *
index 7b97ea9..d399f06 100644 (file)
@@ -289,7 +289,7 @@ assignment (string, flags)
          if (string[newi++] != ']')
            return (0);
          if (string[newi] == '+' && string[newi+1] == '=')
-           return (flags ? 0 : (newi + 1));
+           return (newi + 1);
          return ((string[newi] == '=') ? newi : 0);
        }
 #endif /* ARRAY_VARS */
index 9e73e62..e1d01f5 100644 (file)
--- a/general.h
+++ b/general.h
@@ -299,10 +299,10 @@ extern int same_file __P((char *, char *, struct stat *, struct stat *));
 
 extern int file_isdir __P((char  *));
 extern int file_iswdir __P((char  *));
-
-extern char *make_absolute __P((char *, char *));
 extern int absolute_pathname __P((const char *));
 extern int absolute_program __P((const char *));
+
+extern char *make_absolute __P((char *, char *));
 extern char *base_pathname __P((char *));
 extern char *full_pathname __P((char *));
 extern char *polite_directory_format __P((char *));
index 97e4293..9e73e62 100644 (file)
@@ -24,6 +24,7 @@
 #include "stdc.h"
 
 #include "bashtypes.h"
+#include "chartypes.h"
 
 #if defined (HAVE_SYS_RESOURCE_H) && defined (RLIMTYPE)
 #  if defined (HAVE_SYS_TIME_H)
@@ -231,6 +232,7 @@ typedef int sh_builtin_func_t __P((WORD_LIST *)); /* sh_wlist_func_t */
 #define FS_EXEC_ONLY     0x8
 #define FS_DIRECTORY     0x10
 #define FS_NODIRS        0x20
+#define FS_READABLE      0x40
 
 /* Default maximum for move_to_high_fd */
 #define HIGH_FD_MAX    256
@@ -249,14 +251,18 @@ typedef int QSFUNC ();
 #  define ABSPATH(x)   ((x)[0] == '/')
 #  define RELPATH(x)   ((x)[0] != '/')
 #else /* __CYGWIN__ */
-#  define ABSPATH(x)   (((x)[0] && ISALPHA((unsigned char)(x)[0]) && (x)[1] == ':' && (x)[2] == '/') || (x)[0] == '/')
-#  define RELPATH(x)   (!(x)[0] || ((x)[1] != ':' && (x)[0] != '/'))
+#  define ABSPATH(x)   (((x)[0] && ISALPHA((unsigned char)(x)[0]) && (x)[1] == ':') || ISDIRSEP((x)[0]))
+#  define RELPATH(x)   (ABSPATH(x) == 0)
 #endif /* __CYGWIN__ */
 
 #define ROOTEDPATH(x)  (ABSPATH(x))
 
 #define DIRSEP '/'
-#define ISDIRSEP(c)    ((c) == '/')
+#if !defined (__CYGWIN__)
+#  define ISDIRSEP(c)  ((c) == '/')
+#else
+#  define ISDIRSEP(c)  ((c) == '/' || (c) == '\\')
+#endif /* __CYGWIN__ */
 #define PATHSEP(c)     (ISDIRSEP(c) || (c) == 0)
 
 #if 0
diff --git a/jobs.c b/jobs.c
index 5e8b53d..5a70b5f 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -160,6 +160,7 @@ extern procenv_t wait_intr_buf;
 extern int wait_signal_received;
 extern WORD_LIST *subst_assign_varlist;
 
+static struct jobstats zerojs = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
 struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
 
 struct bgpids bgpids = { 0, 0, 0 };
@@ -349,6 +350,13 @@ tcgetpgrp (fd)
 
 #endif /* !_POSIX_VERSION */
 
+/* Initialize the global job stats structure. */
+void
+init_job_stats ()
+{
+  js = zerojs;
+}
+
 /* Return the working directory for the current process.  Unlike
    job_working_directory, this does not call malloc (), nor do any
    of the functions it calls.  This is so that it can safely be called
@@ -2639,7 +2647,7 @@ start_job (job, foreground)
   register PROCESS *p;
   int already_running;
   sigset_t set, oset;
-  char *wd;
+  char *wd, *s;
   static TTYSTRUCT save_stty;
 
   BLOCK_CHILD (set, oset);
@@ -2657,7 +2665,7 @@ start_job (job, foreground)
     {
       internal_error (_("%s: job %d already in background"), this_command_name, job + 1);
       UNBLOCK_CHILD (oset);
-      return (-1);
+      return (0);              /* XPG6/SUSv3 says this is not an error */
     }
 
   wd = current_working_directory ();
@@ -2675,8 +2683,15 @@ start_job (job, foreground)
   p = jobs[job]->pipe;
 
   if (foreground == 0)
-    printf ("[%d]%c ", job + 1,
-          (job == js.j_current) ? '+': ((job == js.j_previous) ? '-' : ' '));
+    {
+      /* POSIX.2 says `bg' doesn't give any indication about current or
+        previous job. */
+      if (posixly_correct == 0)
+       s = (job == js.j_current) ? "+ ": ((job == js.j_previous) ? "- " : " ");       
+      else
+       s = " ";
+      printf ("[%d]%s", job + 1, s);
+    }
 
   do
     {
@@ -2748,9 +2763,17 @@ kill_pid (pid, sig, group)
      int sig, group;
 {
   register PROCESS *p;
-  int job, result;
+  int job, result, negative;
   sigset_t set, oset;
 
+  if (pid < -1)
+    {
+      pid = -pid;
+      group = negative = 1;
+    }
+  else
+    negative = 0;
+
   result = EXECUTION_SUCCESS;
   if (group)
     {
@@ -2762,8 +2785,26 @@ kill_pid (pid, sig, group)
          jobs[job]->flags &= ~J_NOTIFIED;
 
          /* Kill process in backquotes or one started without job control? */
-         if (jobs[job]->pgrp == shell_pgrp)
+
+         /* If we're passed a pid < -1, just call killpg and see what happens  */
+         if (negative && jobs[job]->pgrp == shell_pgrp)
            result = killpg (pid, sig);
+         /* If we're killing using job control notification, for example,
+            without job control active, we have to do things ourselves. */
+         else if (jobs[job]->pgrp == shell_pgrp)
+           {
+             p = jobs[job]->pipe;
+             do
+               {
+                 if (PALIVE (p) == 0)
+                   continue;           /* avoid pid recycling problem */
+                 kill (p->pid, sig);
+                 if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
+                   kill (p->pid, SIGCONT);
+                 p = p->next;
+               }
+             while  (p != jobs[job]->pipe);
+           }
          else
            {
              result = killpg (jobs[job]->pgrp, sig);
diff --git a/jobs.h b/jobs.h
index ee1bd38..72ae227 100644 (file)
--- a/jobs.h
+++ b/jobs.h
@@ -230,6 +230,8 @@ extern void set_sigchld_handler __P((void));
 extern void ignore_tty_job_signals __P((void));
 extern void default_tty_job_signals __P((void));
 
+extern void init_job_stats __P((void));
+
 #if defined (JOB_CONTROL)
 extern int job_control;
 #endif
index e752753..8db8209 100644 (file)
@@ -1192,9 +1192,9 @@ rl_parse_and_bind (string)
   /* If this is a command to set a variable, then do that. */
   if (_rl_stricmp (string, "set") == 0)
     {
-      char *var = string + i;
-      char *value;
+      char *var, *value, *e;
 
+      var = string + i;
       /* Make VAR point to start of variable name. */
       while (*var && whitespace (*var)) var++;
 
@@ -1205,6 +1205,14 @@ rl_parse_and_bind (string)
        *value++ = '\0';
       while (*value && whitespace (*value)) value++;
 
+      /* remove trailing whitespace */
+      e = value + strlen (value) - 1;
+      while (e >= value && whitespace (*e))
+        e--;
+      e++;             /* skip back to whitespace or EOS */
+      if (*e && e >= value)
+        *e = '\0';
+
       rl_variable_bind (var, value);
       return 0;
     }
@@ -1225,8 +1233,9 @@ rl_parse_and_bind (string)
      the quoted string delimiter, like the shell. */
   if (*funname == '\'' || *funname == '"')
     {
-      int delimiter = string[i++], passc;
+      int delimiter, passc;
 
+      delimiter = string[i++];
       for (passc = 0; c = string[i]; i++)
        {
          if (passc)
index 8c88240..b57be1f 100644 (file)
@@ -369,7 +369,7 @@ rl_generic_bind (type, keyseq, data, map)
       if (ic < 0 || ic >= KEYMAP_SIZE)
        return -1;
 
-      if (_rl_convert_meta_chars_to_ascii && META_CHAR (ic))
+      if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
        {
          ic = UNMETA (ic);
          if (map[ESC].type == ISKMAP)
@@ -460,7 +460,14 @@ rl_translate_keyseq (seq, array, len)
              else if (c == 'M')
                {
                  i++;
-                 array[l++] = ESC;     /* ESC is meta-prefix */
+                 /* XXX - should obey convert-meta setting? */
+                 if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP)
+                   array[l++] = ESC;   /* ESC is meta-prefix */
+                 else
+                   {
+                     i++;
+                     array[l++] = META (seq[i]);
+                   }
                }
              else if (c == 'C')
                {
@@ -1185,9 +1192,9 @@ rl_parse_and_bind (string)
   /* If this is a command to set a variable, then do that. */
   if (_rl_stricmp (string, "set") == 0)
     {
-      char *var = string + i;
-      char *value;
+      char *var, *value, *e;
 
+      var = string + i;
       /* Make VAR point to start of variable name. */
       while (*var && whitespace (*var)) var++;
 
@@ -1198,6 +1205,13 @@ rl_parse_and_bind (string)
        *value++ = '\0';
       while (*value && whitespace (*value)) value++;
 
+      /* remove trailing whitespace */
+      e = value + strlen (value) - 1;
+      while (e >= value && whitespace (*e))
+        e--;
+      if (*e && e >= value)
+        *e = '\0';
+
       rl_variable_bind (var, value);
       return 0;
     }
@@ -1218,8 +1232,9 @@ rl_parse_and_bind (string)
      the quoted string delimiter, like the shell. */
   if (*funname == '\'' || *funname == '"')
     {
-      int delimiter = string[i++], passc;
+      int delimiter, passc;
 
+      delimiter = string[i++];
       for (passc = 0; c = string[i]; i++)
        {
          if (passc)
@@ -1469,7 +1484,7 @@ find_string_var (name)
    values result in 0 (false). */
 static int
 bool_to_int (value)
-     char *value;
+     const char *value;
 {
   return (value == 0 || *value == '\0' ||
                (_rl_stricmp (value, "on") == 0) ||
index e86922d..a719b2a 100644 (file)
@@ -6,9 +6,9 @@
 .\"    Case Western Reserve University
 .\"    chet@ins.CWRU.Edu
 .\"
-.\"    Last Change: Mon Nov 22 11:10:14 EST 2004
+.\"    Last Change: Sat Aug 27 13:29:08 EDT 2005
 .\"
-.TH READLINE 3 "2004 Nov 22" "GNU Readline 5.1-devel"
+.TH READLINE 3 "2005 Aug 27" "GNU Readline 5.1-alpha1"
 .\"
 .\" File Name macro.  This used to be `.PN', for Path Name,
 .\" but Sun doesn't seem to like that very much.
@@ -328,6 +328,10 @@ Except where noted, readline variables can take the values
 or
 .B Off
 (without regard to case).
+Unrecognized variable names are ignored.
+When a variable value is read, empty or null values, "on" (case-insensitive),
+and "1" are equivalent to \fBOn\fP.  All other values are equivalent to
+\fBOff\fP.
 The variables and their default values are:
 .PP
 .PD 0
index 3bdf6e1..e86922d 100644 (file)
@@ -396,9 +396,9 @@ arrow keys.
 If set to \fBon\fP, tilde expansion is performed when readline
 attempts word completion.
 .TP
-.B history-preserve-point     
+.B history\-preserve\-point (Off)
 If set to \fBon\fP, the history code attempts to place point at the 
-same location on each history line retrived with \fBprevious-history\fP 
+same location on each history line retrieved with \fBprevious-history\fP 
 or \fBnext-history\fP.
 .TP
 .B horizontal\-scroll\-mode (Off)
index 8f0459b..1444f85 100644 (file)
@@ -383,7 +383,11 @@ set editing-mode vi
 @end example
 
 Variable names and values, where appropriate, are recognized without regard
-to case. 
+to case.  Unrecognized variable names are ignored.
+
+Boolean variables (those that can be set to on or off) are set to on if
+the value is null or empty, @var{on} (case-insensitive), or 1.  Any other
+value results in the variable being set to off.
 
 @ifset BashFeatures
 The @w{@code{bind -V}} command lists the current Readline variable names
index bffb0c8..8f0459b 100644 (file)
@@ -10,7 +10,7 @@ use these features.  There is a document entitled "readline.texinfo"
 which contains both end-user and programmer documentation for the
 GNU Readline Library.
 
-Copyright (C) 1988-2004 Free Software Foundation, Inc.
+Copyright (C) 1988-2005 Free Software Foundation, Inc.
 
 Authored by Brian Fox and Chet Ramey.
 
index cd41234..7afafd7 100644 (file)
@@ -4,7 +4,7 @@ Copyright (C) 1988-2005 Free Software Foundation, Inc.
 
 @set EDITION 5.1-devel
 @set VERSION 5.1-devel
-@set UPDATED 4 January 2005
-@set UPDATED-MONTH January 2005
+@set UPDATED 27 August 2005
+@set UPDATED-MONTH August 2005
 
-@set LASTCHANGE Tue Jan  4 17:26:58 EST 2005
+@set LASTCHANGE Sat Aug 27 13:28:14 EDT 2005
index 69ff2ae..cd41234 100644 (file)
@@ -1,10 +1,10 @@
 @ignore
-Copyright (C) 1988-2004 Free Software Foundation, Inc. 
+Copyright (C) 1988-2005 Free Software Foundation, Inc. 
 @end ignore
 
 @set EDITION 5.1-devel
 @set VERSION 5.1-devel
-@set UPDATED 15 October 2004
-@set UPDATED-MONTH October 2004
+@set UPDATED 4 January 2005
+@set UPDATED-MONTH January 2005
 
-@set LASTCHANGE Fri Oct 15 14:52:31 EDT 2004
+@set LASTCHANGE Tue Jan  4 17:26:58 EST 2005
index 3da5748..a538f91 100644 (file)
@@ -204,7 +204,7 @@ history_get (offset)
   int local_index;
 
   local_index = offset - history_base;
-  return (local_index >= history_length || local_index < 0 || !the_history)
+  return (local_index >= history_length || local_index < 0 || the_history == 0)
                ? (HIST_ENTRY *)NULL
                : the_history[local_index];
 }
@@ -364,7 +364,7 @@ remove_history (which)
   HIST_ENTRY *return_value;
   register int i;
 
-  if (which < 0 || which >= history_length || history_length ==  0)
+  if (which < 0 || which >= history_length || history_length ==  0 || the_history == 0)
     return ((HIST_ENTRY *)NULL);
 
   return_value = the_history[which];
index 88b3985..31aa0a4 100644 (file)
@@ -101,6 +101,8 @@ _rl_scxt_alloc (type, flags)
   cxt->last_found_line = cxt->save_line;
   cxt->prev_line_found = 0;
 
+  cxt->save_undo_list = 0;
+
   cxt->history_pos = 0;
   cxt->direction = 0;
 
diff --git a/lib/readline/isearch.c~ b/lib/readline/isearch.c~
new file mode 100644 (file)
index 0000000..88b3985
--- /dev/null
@@ -0,0 +1,656 @@
+/* **************************************************************** */
+/*                                                                 */
+/*                     I-Search and Searching                      */
+/*                                                                 */
+/* **************************************************************** */
+
+/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
+
+   This file contains the Readline Library (the Library), a set of
+   routines for providing Emacs style line input to programs that ask
+   for it.
+
+   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. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif
+
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+/* Variables exported to other files in the readline library. */
+char *_rl_isearch_terminators = (char *)NULL;
+
+_rl_search_cxt *_rl_iscxt = 0;
+
+/* Variables imported from other files in the readline library. */
+extern HIST_ENTRY *_rl_saved_line_for_history;
+
+static int rl_search_history PARAMS((int, int));
+
+static _rl_search_cxt *_rl_isearch_init PARAMS((int));
+static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
+static int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int));
+
+/* Last line found by the current incremental search, so we don't `find'
+   identical lines many times in a row. */
+static char *prev_line_found;
+
+/* Last search string and its length. */
+static char *last_isearch_string;
+static int last_isearch_string_len;
+
+static char *default_isearch_terminators = "\033\012";
+
+_rl_search_cxt *
+_rl_scxt_alloc (type, flags)
+     int type, flags;
+{
+  _rl_search_cxt *cxt;
+
+  cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt));
+
+  cxt->type = type;
+  cxt->sflags = flags;
+
+  cxt->search_string = 0;
+  cxt->search_string_size = cxt->search_string_index = 0;
+
+  cxt->lines = 0;
+  cxt->allocated_line = 0;
+  cxt->hlen = cxt->hindex = 0;
+
+  cxt->save_point = rl_point;
+  cxt->save_mark = rl_mark;
+  cxt->save_line = where_history ();
+  cxt->last_found_line = cxt->save_line;
+  cxt->prev_line_found = 0;
+
+  cxt->history_pos = 0;
+  cxt->direction = 0;
+
+  cxt->lastc = 0;
+
+  cxt->sline = 0;
+  cxt->sline_len = cxt->sline_index = 0;
+
+  cxt->search_terminators = 0;
+
+  return cxt;
+}
+
+void
+_rl_scxt_dispose (cxt, flags)
+     _rl_search_cxt *cxt;
+     int flags;
+{
+  FREE (cxt->search_string);
+  FREE (cxt->allocated_line);
+  FREE (cxt->lines);
+
+  free (cxt);
+}
+
+/* Search backwards through the history looking for a string which is typed
+   interactively.  Start with the current line. */
+int
+rl_reverse_search_history (sign, key)
+     int sign, key;
+{
+  return (rl_search_history (-sign, key));
+}
+
+/* Search forwards through the history looking for a string which is typed
+   interactively.  Start with the current line. */
+int
+rl_forward_search_history (sign, key)
+     int sign, key;
+{
+  return (rl_search_history (sign, key));
+}
+
+/* Display the current state of the search in the echo-area.
+   SEARCH_STRING contains the string that is being searched for,
+   DIRECTION is zero for forward, or 1 for reverse,
+   WHERE is the history list number of the current line.  If it is
+   -1, then this line is the starting one. */
+static void
+rl_display_search (search_string, reverse_p, where)
+     char *search_string;
+     int reverse_p, where;
+{
+  char *message;
+  int msglen, searchlen;
+
+  searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
+
+  message = (char *)xmalloc (searchlen + 33);
+  msglen = 0;
+
+#if defined (NOTDEF)
+  if (where != -1)
+    {
+      sprintf (message, "[%d]", where + history_base);
+      msglen = strlen (message);
+    }
+#endif /* NOTDEF */
+
+  message[msglen++] = '(';
+
+  if (reverse_p)
+    {
+      strcpy (message + msglen, "reverse-");
+      msglen += 8;
+    }
+
+  strcpy (message + msglen, "i-search)`");
+  msglen += 10;
+
+  if (search_string)
+    {
+      strcpy (message + msglen, search_string);
+      msglen += searchlen;
+    }
+
+  strcpy (message + msglen, "': ");
+
+  rl_message ("%s", message);
+  free (message);
+  (*rl_redisplay_function) ();
+}
+
+static _rl_search_cxt *
+_rl_isearch_init (direction)
+     int direction;
+{
+  _rl_search_cxt *cxt;
+  register int i;
+  HIST_ENTRY **hlist;
+
+  cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
+  if (direction < 0)
+    cxt->sflags |= SF_REVERSE;
+
+  cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
+                                               : default_isearch_terminators;
+
+  /* Create an arrary of pointers to the lines that we want to search. */
+  hlist = history_list ();
+  rl_maybe_replace_line ();
+  i = 0;
+  if (hlist)
+    for (i = 0; hlist[i]; i++);
+
+  /* Allocate space for this many lines, +1 for the current input line,
+     and remember those lines. */
+  cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *));
+  for (i = 0; i < cxt->hlen; i++)
+    cxt->lines[i] = hlist[i]->line;
+
+  if (_rl_saved_line_for_history)
+    cxt->lines[i] = _rl_saved_line_for_history->line;
+  else
+    {
+      /* Keep track of this so we can free it. */
+      cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
+      strcpy (cxt->allocated_line, &rl_line_buffer[0]);
+      cxt->lines[i] = cxt->allocated_line;
+    }
+
+  cxt->hlen++;
+
+  /* The line where we start the search. */
+  cxt->history_pos = cxt->save_line;
+
+  rl_save_prompt ();
+
+  /* Initialize search parameters. */
+  cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
+  cxt->search_string[cxt->search_string_index = 0] = '\0';
+
+  /* Normalize DIRECTION into 1 or -1. */
+  cxt->direction = (direction >= 0) ? 1 : -1;
+
+  cxt->sline = rl_line_buffer;
+  cxt->sline_len = strlen (cxt->sline);
+  cxt->sline_index = rl_point;
+
+  _rl_iscxt = cxt;             /* save globally */
+
+  return cxt;
+}
+
+static void
+_rl_isearch_fini (cxt)
+     _rl_search_cxt *cxt;
+{
+  /* First put back the original state. */
+  strcpy (rl_line_buffer, cxt->lines[cxt->save_line]);
+
+  rl_restore_prompt ();
+
+  /* Save the search string for possible later use. */
+  FREE (last_isearch_string);
+  last_isearch_string = cxt->search_string;
+  last_isearch_string_len = cxt->search_string_index;
+  cxt->search_string = 0;
+
+  if (cxt->last_found_line < cxt->save_line)
+    rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
+  else
+    rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
+
+  /* If the string was not found, put point at the end of the last matching
+     line.  If last_found_line == orig_line, we didn't find any matching
+     history lines at all, so put point back in its original position. */
+  if (cxt->sline_index < 0)
+    {
+      if (cxt->last_found_line == cxt->save_line)
+       cxt->sline_index = cxt->save_point;
+      else
+       cxt->sline_index = strlen (rl_line_buffer);
+      rl_mark = cxt->save_mark;
+    }
+
+  rl_point = cxt->sline_index;
+  /* Don't worry about where to put the mark here; rl_get_previous_history
+     and rl_get_next_history take care of it. */
+
+  rl_clear_message ();
+}
+
+int
+_rl_search_getchar (cxt)
+     _rl_search_cxt *cxt;
+{
+  int c;
+
+  /* Read a key and decide how to proceed. */
+  RL_SETSTATE(RL_STATE_MOREINPUT);
+  c = cxt->lastc = rl_read_key ();
+  RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
+#endif
+
+  return c;
+}
+
+/* Process just-read character C according to isearch context CXT.  Return
+   -1 if the caller should just free the context and return, 0 if we should
+   break out of the loop, and 1 if we should continue to read characters. */
+int
+_rl_isearch_dispatch (cxt, c)
+     _rl_search_cxt *cxt;
+     int c;
+{
+  int n, wstart, wlen, limit;
+  rl_command_func_t *f;
+
+  f = (rl_command_func_t *)NULL;
+ /* Translate the keys we do something with to opcodes. */
+  if (c >= 0 && _rl_keymap[c].type == ISFUNC)
+    {
+      f = _rl_keymap[c].function;
+
+      if (f == rl_reverse_search_history)
+       cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
+      else if (f == rl_forward_search_history)
+       cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
+      else if (f == rl_rubout)
+       cxt->lastc = -3;
+      else if (c == CTRL ('G'))
+       cxt->lastc = -4;
+      else if (c == CTRL ('W'))        /* XXX */
+       cxt->lastc = -5;
+      else if (c == CTRL ('Y'))        /* XXX */
+       cxt->lastc = -6;
+    }
+
+  /* The characters in isearch_terminators (set from the user-settable
+     variable isearch-terminators) are used to terminate the search but
+     not subsequently execute the character as a command.  The default
+     value is "\033\012" (ESC and C-J). */
+  if (strchr (cxt->search_terminators, cxt->lastc))
+    {
+      /* ESC still terminates the search, but if there is pending
+        input or if input arrives within 0.1 seconds (on systems
+        with select(2)) it is used as a prefix character
+        with rl_execute_next.  WATCH OUT FOR THIS!  This is intended
+        to allow the arrow keys to be used like ^F and ^B are used
+        to terminate the search and execute the movement command.
+        XXX - since _rl_input_available depends on the application-
+        settable keyboard timeout value, this could alternatively
+        use _rl_input_queued(100000) */
+      if (cxt->lastc == ESC && _rl_input_available ())
+       rl_execute_next (ESC);
+      return (0);
+    }
+
+#define ENDSRCH_CHAR(c) \
+  ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
+
+#if defined (HANDLE_MULTIBYTE)
+  if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+    {
+      if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
+       {
+         /* This sets rl_pending_input to c; it will be picked up the next
+            time rl_read_key is called. */
+         rl_execute_next (cxt->lastc);
+         return (0);
+       }
+    }
+  else
+#endif
+    if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
+      {
+       /* This sets rl_pending_input to LASTC; it will be picked up the next
+          time rl_read_key is called. */
+       rl_execute_next (cxt->lastc);
+       return (0);
+      }
+
+  /* Now dispatch on the character.  `Opcodes' affect the search string or
+     state.  Other characters are added to the string.  */
+  switch (cxt->lastc)
+    {
+    /* search again */
+    case -1:
+      if (cxt->search_string_index == 0)
+       {
+         if (last_isearch_string)
+           {
+             cxt->search_string_size = 64 + last_isearch_string_len;
+             cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
+             strcpy (cxt->search_string, last_isearch_string);
+             cxt->search_string_index = last_isearch_string_len;
+             rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
+             break;
+           }
+         return (1);
+       }
+      else if (cxt->sflags & SF_REVERSE)
+       cxt->sline_index--;
+      else if (cxt->sline_index != cxt->sline_len)
+       cxt->sline_index++;
+      else
+       rl_ding ();
+      break;
+
+    /* switch directions */
+    case -2:
+      cxt->direction = -cxt->direction;
+      if (cxt->direction < 0)
+       cxt->sflags |= SF_REVERSE;
+      break;
+
+    /* delete character from search string. */
+    case -3:   /* C-H, DEL */
+      /* This is tricky.  To do this right, we need to keep a
+        stack of search positions for the current search, with
+        sentinels marking the beginning and end.  But this will
+        do until we have a real isearch-undo. */
+      if (cxt->search_string_index == 0)
+       rl_ding ();
+      else
+       cxt->search_string[--cxt->search_string_index] = '\0';
+      break;
+
+    case -4:   /* C-G, abort */
+      rl_replace_line (cxt->lines[cxt->save_line], 0);
+      rl_point = cxt->save_point;
+      rl_mark = cxt->save_mark;
+      rl_restore_prompt();
+      rl_clear_message ();
+
+      return -1;
+
+    case -5:   /* C-W */
+      /* skip over portion of line we already matched and yank word */
+      wstart = rl_point + cxt->search_string_index;
+      if (wstart >= rl_end)
+       {
+         rl_ding ();
+         break;
+       }
+
+      /* if not in a word, move to one. */
+      if (rl_alphabetic(rl_line_buffer[wstart]) == 0)
+       {
+         rl_ding ();
+         break;
+       }
+      n = wstart;
+      while (n < rl_end && rl_alphabetic(rl_line_buffer[n]))
+       n++;
+      wlen = n - wstart + 1;
+      if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
+       {
+         cxt->search_string_size += wlen + 1;
+         cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
+       }
+      for (; wstart < n; wstart++)
+       cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart];
+      cxt->search_string[cxt->search_string_index] = '\0';
+      break;
+
+    case -6:   /* C-Y */
+      /* skip over portion of line we already matched and yank rest */
+      wstart = rl_point + cxt->search_string_index;
+      if (wstart >= rl_end)
+       {
+         rl_ding ();
+         break;
+       }
+      n = rl_end - wstart + 1;
+      if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
+       {
+         cxt->search_string_size += n + 1;
+         cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
+       }
+      for (n = wstart; n < rl_end; n++)
+       cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n];
+      cxt->search_string[cxt->search_string_index] = '\0';
+      break;
+
+    /* Add character to search string and continue search. */
+    default:
+      if (cxt->search_string_index + 2 >= cxt->search_string_size)
+       {
+         cxt->search_string_size += 128;
+         cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
+       }
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       {
+         int j, l;
+         for (j = 0, l = strlen (cxt->mb); j < l; )
+           cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
+       }
+      else
+#endif
+       cxt->search_string[cxt->search_string_index++] = c;
+      cxt->search_string[cxt->search_string_index] = '\0';
+      break;
+    }
+
+  for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
+    {
+      limit = cxt->sline_len - cxt->search_string_index + 1;
+
+      /* Search the current line. */
+      while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
+       {
+         if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
+           {
+             cxt->sflags |= SF_FOUND;
+             break;
+           }
+         else
+           cxt->sline_index += cxt->direction;
+       }
+      if (cxt->sflags & SF_FOUND)
+       break;
+
+      /* Move to the next line, but skip new copies of the line
+        we just found and lines shorter than the string we're
+        searching for. */
+      do
+       {
+         /* Move to the next line. */
+         cxt->history_pos += cxt->direction;
+
+         /* At limit for direction? */
+         if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
+           {
+             cxt->sflags |= SF_FAILED;
+             break;
+           }
+
+         /* We will need these later. */
+         cxt->sline = cxt->lines[cxt->history_pos];
+         cxt->sline_len = strlen (cxt->sline);
+       }
+      while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
+            (cxt->search_string_index > cxt->sline_len));
+
+      if (cxt->sflags & SF_FAILED)
+       break;
+
+      /* Now set up the line for searching... */
+      cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
+    }
+
+  if (cxt->sflags & SF_FAILED)
+    {
+      /* We cannot find the search string.  Ding the bell. */
+      rl_ding ();
+      cxt->history_pos = cxt->last_found_line;
+      return 1;
+    }
+
+  /* We have found the search string.  Just display it.  But don't
+     actually move there in the history list until the user accepts
+     the location. */
+  if (cxt->sflags & SF_FOUND)
+    {
+      cxt->prev_line_found = cxt->lines[cxt->history_pos];
+      rl_replace_line (cxt->lines[cxt->history_pos], 0);
+      rl_point = cxt->sline_index;
+      cxt->last_found_line = cxt->history_pos;
+      rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
+    }
+
+  return 1;
+}
+
+static int
+_rl_isearch_cleanup (cxt, r)
+     _rl_search_cxt *cxt;
+     int r;
+{
+  if (r >= 0)
+    _rl_isearch_fini (cxt);
+  _rl_scxt_dispose (cxt, 0);
+  _rl_iscxt = 0;
+
+  RL_UNSETSTATE(RL_STATE_ISEARCH);
+
+  return (r != 0);
+}
+
+/* Search through the history looking for an interactively typed string.
+   This is analogous to i-search.  We start the search in the current line.
+   DIRECTION is which direction to search; >= 0 means forward, < 0 means
+   backwards. */
+static int
+rl_search_history (direction, invoking_key)
+     int direction, invoking_key;
+{
+  _rl_search_cxt *cxt;         /* local for now, but saved globally */
+  int c, r;
+
+  RL_SETSTATE(RL_STATE_ISEARCH);
+  cxt = _rl_isearch_init (direction);
+
+  rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
+
+  /* If we are using the callback interface, all we do is set up here and
+      return.  The key is that we leave RL_STATE_ISEARCH set. */
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    return (0);
+
+  r = -1;
+  for (;;)
+    {
+      c = _rl_search_getchar (cxt);
+      /* We might want to handle EOF here (c == 0) */
+      r = _rl_isearch_dispatch (cxt, cxt->lastc);
+      if (r <= 0)
+        break;
+    }
+
+  /* The searching is over.  The user may have found the string that she
+     was looking for, or else she may have exited a failing search.  If
+     LINE_INDEX is -1, then that shows that the string searched for was
+     not found.  We use this to determine where to place rl_point. */
+  return (_rl_isearch_cleanup (cxt, r));
+}
+
+#if defined (READLINE_CALLBACKS)
+/* Called from the callback functions when we are ready to read a key.  The
+   callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
+   If _rl_isearch_dispatch finishes searching, this function is responsible
+   for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
+int
+_rl_isearch_callback (cxt)
+     _rl_search_cxt *cxt;
+{
+  int c, r;
+
+  c = _rl_search_getchar (cxt);
+  /* We might want to handle EOF here */
+  r = _rl_isearch_dispatch (cxt, cxt->lastc);
+
+  return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;
+}
+#endif
index efc954c..1c216ea 100644 (file)
@@ -63,6 +63,8 @@ typedef struct  __rl_search_context
   int last_found_line;
   char *prev_line_found;
 
+  UNDO_LIST *save_undo_list;
+
   int history_pos;
   int direction;
 
diff --git a/lib/readline/rlprivate.h~ b/lib/readline/rlprivate.h~
new file mode 100644 (file)
index 0000000..efc954c
--- /dev/null
@@ -0,0 +1,418 @@
+/* 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;
+
+  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 b4c174d..8013916 100644 (file)
@@ -70,6 +70,7 @@ static int rl_history_search_pos;
 static char *history_search_string;
 static int history_string_size;
 
+static UNDO_LIST *noninc_saved_undo_list;
 static void make_history_line_current PARAMS((HIST_ENTRY *));
 static int noninc_search_from_pos PARAMS((char *, int, int));
 static int noninc_dosearch PARAMS((char *, int));
@@ -89,12 +90,15 @@ static void
 make_history_line_current (entry)
      HIST_ENTRY *entry;
 {
-#if 0
-  rl_replace_line (entry->line, 1);
-  rl_undo_list = (UNDO_LIST *)entry->data;
-#else
   _rl_replace_text (entry->line, 0, rl_end);
   _rl_fix_point (1);
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    /* POSIX.2 says that the `U' command doesn't affect the copy of any
+       command lines to the edit line.  We're going to implement that by
+       making the undo list start after the matching line is copied to the
+       current editing buffer. */
+    rl_free_undo_list ();
 #endif
 
   if (_rl_saved_line_for_history)
@@ -325,6 +329,13 @@ _rl_nsearch_dosearch (cxt)
       noninc_history_pos = cxt->save_line;
       FREE (noninc_search_string);
       noninc_search_string = savestring (rl_line_buffer);
+
+      /* If we don't want the subsequent undo list generated by the search
+        matching a history line to include the contents of the search string,
+        we need to clear rl_line_buffer here.  For now, we just clear the
+        undo list generated by reading the search string.  (If the search
+        fails, the old undo list will be restored by rl_maybe_unsave_line.) */
+      rl_free_undo_list ();
     }
 
   rl_restore_prompt ();
diff --git a/lib/readline/search.c~ b/lib/readline/search.c~
new file mode 100644 (file)
index 0000000..764c33a
--- /dev/null
@@ -0,0 +1,572 @@
+/* search.c - code for non-incremental searching in emacs and vi modes. */
+
+/* Copyright (C) 1992-2005 Free Software Foundation, Inc.
+
+   This file is part of the Readline Library (the Library), a set of
+   routines for providing Emacs style line input to programs that ask
+   for it.
+
+   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. */
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#if defined (HAVE_STDLIB_H)
+#  include <stdlib.h>
+#else
+#  include "ansi_stdlib.h"
+#endif
+
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+#ifdef abs
+#  undef abs
+#endif
+#define abs(x)         (((x) >= 0) ? (x) : -(x))
+
+_rl_search_cxt *_rl_nscxt = 0;
+
+extern HIST_ENTRY *_rl_saved_line_for_history;
+
+/* Functions imported from the rest of the library. */
+extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
+
+static char *noninc_search_string = (char *) NULL;
+static int noninc_history_pos;
+
+static char *prev_line_found = (char *) NULL;
+
+static int rl_history_search_len;
+static int rl_history_search_pos;
+static char *history_search_string;
+static int history_string_size;
+
+static UNDO_LIST *noninc_saved_undo_list;
+static void make_history_line_current PARAMS((HIST_ENTRY *));
+static int noninc_search_from_pos PARAMS((char *, int, int));
+static int noninc_dosearch PARAMS((char *, int));
+static int noninc_search PARAMS((int, int));
+static int rl_history_search_internal PARAMS((int, int));
+static void rl_history_search_reinit PARAMS((void));
+
+static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
+static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
+static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
+static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
+
+/* Make the data from the history entry ENTRY be the contents of the
+   current line.  This doesn't do anything with rl_point; the caller
+   must set it. */
+static void
+make_history_line_current (entry)
+     HIST_ENTRY *entry;
+{
+  _rl_replace_text (entry->line, 0, rl_end);
+  _rl_fix_point (1);
+#if defined (VI_MODE)
+  if (rl_editing_mode == vi_mode)
+    /* POSIX.2 says that the `U' command doesn't affect command lines copied
+       to the edit line.  That's ambiguous, but we're going to interpret it
+       to mean that the undo list starts after the matching line is copied to
+       the current editing buffer. */
+    rl_free_undo_list ();
+#endif
+
+  if (_rl_saved_line_for_history)
+    _rl_free_history_entry (_rl_saved_line_for_history);
+  _rl_saved_line_for_history = (HIST_ENTRY *)NULL;
+}
+
+/* Search the history list for STRING starting at absolute history position
+   POS.  If STRING begins with `^', the search must match STRING at the
+   beginning of a history line, otherwise a full substring match is performed
+   for STRING.  DIR < 0 means to search backwards through the history list,
+   DIR >= 0 means to search forward. */
+static int
+noninc_search_from_pos (string, pos, dir)
+     char *string;
+     int pos, dir;
+{
+  int ret, old;
+
+  if (pos < 0)
+    return -1;
+
+  old = where_history ();
+  if (history_set_pos (pos) == 0)
+    return -1;
+
+  RL_SETSTATE(RL_STATE_SEARCH);
+  if (*string == '^')
+    ret = history_search_prefix (string + 1, dir);
+  else
+    ret = history_search (string, dir);
+  RL_UNSETSTATE(RL_STATE_SEARCH);
+
+  if (ret != -1)
+    ret = where_history ();
+
+  history_set_pos (old);
+  return (ret);
+}
+
+/* Search for a line in the history containing STRING.  If DIR is < 0, the
+   search is backwards through previous entries, else through subsequent
+   entries.  Returns 1 if the search was successful, 0 otherwise. */
+static int
+noninc_dosearch (string, dir)
+     char *string;
+     int dir;
+{
+  int oldpos, pos;
+  HIST_ENTRY *entry;
+
+  if (string == 0 || *string == '\0' || noninc_history_pos < 0)
+    {
+      rl_ding ();
+      return 0;
+    }
+
+  pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
+  if (pos == -1)
+    {
+      /* Search failed, current history position unchanged. */
+      rl_maybe_unsave_line ();
+      rl_clear_message ();
+      rl_point = 0;
+      rl_ding ();
+      return 0;
+    }
+
+  noninc_history_pos = pos;
+
+  oldpos = where_history ();
+  history_set_pos (noninc_history_pos);
+  entry = current_history ();
+#if defined (VI_MODE)
+  if (rl_editing_mode != vi_mode)
+#endif
+    history_set_pos (oldpos);
+
+  make_history_line_current (entry);
+
+  rl_point = 0;
+  rl_mark = rl_end;
+
+  rl_clear_message ();
+  return 1;
+}
+
+static _rl_search_cxt *
+_rl_nsearch_init (dir, pchar)
+     int dir, pchar;
+{
+  _rl_search_cxt *cxt;
+  char *p;
+
+  cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
+  if (dir < 0)
+    cxt->sflags |= SF_REVERSE;         /* not strictly needed */
+
+  cxt->direction = dir;
+  cxt->history_pos = cxt->save_line;
+
+  rl_maybe_save_line ();
+
+  /* Clear the undo list, since reading the search string should create its
+     own undo list, and the whole list will end up being freed when we
+     finish reading the search string. */
+  rl_undo_list = 0;
+
+  /* Use the line buffer to read the search string. */
+  rl_line_buffer[0] = 0;
+  rl_end = rl_point = 0;
+
+  p = _rl_make_prompt_for_search (pchar ? pchar : ':');
+  rl_message (p, 0, 0);
+  free (p);
+
+  RL_SETSTATE(RL_STATE_NSEARCH);
+
+  _rl_nscxt = cxt;
+
+  return cxt;
+}
+
+static int
+_rl_nsearch_cleanup (cxt, r)
+     _rl_search_cxt *cxt;
+     int r;
+{
+  _rl_scxt_dispose (cxt, 0);
+  _rl_nscxt = 0;
+
+  RL_UNSETSTATE(RL_STATE_NSEARCH);
+
+  return (r != 1);
+}
+
+static void
+_rl_nsearch_abort (cxt)
+     _rl_search_cxt *cxt;
+{
+  rl_maybe_unsave_line ();
+  rl_clear_message ();
+  rl_point = cxt->save_point;
+  rl_mark = cxt->save_mark;
+  rl_restore_prompt ();
+
+  RL_UNSETSTATE (RL_STATE_NSEARCH);
+}
+
+/* Process just-read character C according to search context CXT.  Return -1
+   if the caller should abort the search, 0 if we should break out of the
+   loop, and 1 if we should continue to read characters. */
+static int
+_rl_nsearch_dispatch (cxt, c)
+     _rl_search_cxt *cxt;
+     int c;
+{
+  switch (c)
+    {
+    case CTRL('W'):
+      rl_unix_word_rubout (1, c);
+      break;
+
+    case CTRL('U'):
+      rl_unix_line_discard (1, c);
+      break;
+
+    case RETURN:
+    case NEWLINE:
+      return 0;
+
+    case CTRL('H'):
+    case RUBOUT:
+      if (rl_point == 0)
+       {
+         _rl_nsearch_abort (cxt);
+         return -1;
+       }
+      _rl_rubout_char (1, c);
+      break;
+
+    case CTRL('C'):
+    case CTRL('G'):
+      rl_ding ();
+      _rl_nsearch_abort (cxt);
+      return -1;
+
+    default:
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+       rl_insert_text (cxt->mb);
+      else
+#endif
+       _rl_insert_char (1, c);
+      break;
+    }
+
+  (*rl_redisplay_function) ();
+  return 1;
+}
+
+/* Perform one search according to CXT, using NONINC_SEARCH_STRING.  Return
+   -1 if the search should be aborted, any other value means to clean up
+   using _rl_nsearch_cleanup ().  Returns 1 if the search was successful,
+   0 otherwise. */
+static int
+_rl_nsearch_dosearch (cxt)
+     _rl_search_cxt *cxt;
+{
+  rl_mark = cxt->save_mark;
+
+  /* If rl_point == 0, we want to re-use the previous search string and
+     start from the saved history position.  If there's no previous search
+     string, punt. */
+  if (rl_point == 0)
+    {
+      if (noninc_search_string == 0)
+       {
+         rl_ding ();
+         rl_restore_prompt ();
+         RL_UNSETSTATE (RL_STATE_NSEARCH);
+         return -1;
+       }
+    }
+  else
+    {
+      /* We want to start the search from the current history position. */
+      noninc_history_pos = cxt->save_line;
+      FREE (noninc_search_string);
+      noninc_search_string = savestring (rl_line_buffer);
+
+      /* If we don't want the subsequent undo list generated by the search
+        matching a history line to include the contents of the search string,
+        we need to clear rl_line_buffer here.  For now, we just clear the
+        undo list generated by reading the search string.  (If the search
+        fails, the old undo list will be restored by rl_maybe_unsave_line.) */
+      rl_free_undo_list ();
+    }
+
+  rl_restore_prompt ();
+  return (noninc_dosearch (noninc_search_string, cxt->direction));
+}
+
+/* Search non-interactively through the history list.  DIR < 0 means to
+   search backwards through the history of previous commands; otherwise
+   the search is for commands subsequent to the current position in the
+   history list.  PCHAR is the character to use for prompting when reading
+   the search string; if not specified (0), it defaults to `:'. */
+static int
+noninc_search (dir, pchar)
+     int dir;
+     int pchar;
+{
+  _rl_search_cxt *cxt;
+  int c, r;
+
+  cxt = _rl_nsearch_init (dir, pchar);
+
+  if (RL_ISSTATE (RL_STATE_CALLBACK))
+    return (0);
+
+  /* Read the search string. */
+  r = 0;
+  while (1)
+    {
+      c = _rl_search_getchar (cxt);
+
+      if (c == 0)
+       break;
+
+      r = _rl_nsearch_dispatch (cxt, c);
+      if (r < 0)
+        return 1;
+      else if (r == 0)
+       break;        
+    }
+
+  r = _rl_nsearch_dosearch (cxt);
+  return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
+}
+
+/* Search forward through the history list for a string.  If the vi-mode
+   code calls this, KEY will be `?'. */
+int
+rl_noninc_forward_search (count, key)
+     int count, key;
+{
+  return noninc_search (1, (key == '?') ? '?' : 0);
+}
+
+/* Reverse search the history list for a string.  If the vi-mode code
+   calls this, KEY will be `/'. */
+int
+rl_noninc_reverse_search (count, key)
+     int count, key;
+{
+  return noninc_search (-1, (key == '/') ? '/' : 0);
+}
+
+/* Search forward through the history list for the last string searched
+   for.  If there is no saved search string, abort. */
+int
+rl_noninc_forward_search_again (count, key)
+     int count, key;
+{
+  int r;
+
+  if (!noninc_search_string)
+    {
+      rl_ding ();
+      return (-1);
+    }
+  r = noninc_dosearch (noninc_search_string, 1);
+  return (r != 1);
+}
+
+/* Reverse search in the history list for the last string searched
+   for.  If there is no saved search string, abort. */
+int
+rl_noninc_reverse_search_again (count, key)
+     int count, key;
+{
+  int r;
+
+  if (!noninc_search_string)
+    {
+      rl_ding ();
+      return (-1);
+    }
+  r = noninc_dosearch (noninc_search_string, -1);
+  return (r != 1);
+}
+
+#if defined (READLINE_CALLBACKS)
+int
+_rl_nsearch_callback (cxt)
+     _rl_search_cxt *cxt;
+{
+  int c, r;
+
+  c = _rl_search_getchar (cxt);
+  r = _rl_nsearch_dispatch (cxt, c);
+  if (r != 0)
+    return 1;
+
+  r = _rl_nsearch_dosearch (cxt);
+  return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
+}
+#endif
+  
+static int
+rl_history_search_internal (count, dir)
+     int count, dir;
+{
+  HIST_ENTRY *temp;
+  int ret, oldpos;
+
+  rl_maybe_save_line ();
+  temp = (HIST_ENTRY *)NULL;
+
+  /* Search COUNT times through the history for a line whose prefix
+     matches history_search_string.  When this loop finishes, TEMP,
+     if non-null, is the history line to copy into the line buffer. */
+  while (count)
+    {
+      ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
+      if (ret == -1)
+       break;
+
+      /* Get the history entry we found. */
+      rl_history_search_pos = ret;
+      oldpos = where_history ();
+      history_set_pos (rl_history_search_pos);
+      temp = current_history ();
+      history_set_pos (oldpos);
+
+      /* Don't find multiple instances of the same line. */
+      if (prev_line_found && STREQ (prev_line_found, temp->line))
+        continue;
+      prev_line_found = temp->line;
+      count--;
+    }
+
+  /* If we didn't find anything at all, return. */
+  if (temp == 0)
+    {
+      rl_maybe_unsave_line ();
+      rl_ding ();
+      /* If you don't want the saved history line (last match) to show up
+         in the line buffer after the search fails, change the #if 0 to
+         #if 1 */
+#if 0
+      if (rl_point > rl_history_search_len)
+        {
+          rl_point = rl_end = rl_history_search_len;
+          rl_line_buffer[rl_end] = '\0';
+          rl_mark = 0;
+        }
+#else
+      rl_point = rl_history_search_len;        /* rl_maybe_unsave_line changes it */
+      rl_mark = rl_end;
+#endif
+      return 1;
+    }
+
+  /* Copy the line we found into the current line buffer. */
+  make_history_line_current (temp);
+
+  rl_point = rl_history_search_len;
+  rl_mark = rl_end;
+
+  return 0;
+}
+
+static void
+rl_history_search_reinit ()
+{
+  rl_history_search_pos = where_history ();
+  rl_history_search_len = rl_point;
+  prev_line_found = (char *)NULL;
+  if (rl_point)
+    {
+      if (rl_history_search_len >= history_string_size - 2)
+       {
+         history_string_size = rl_history_search_len + 2;
+         history_search_string = (char *)xrealloc (history_search_string, history_string_size);
+       }
+      history_search_string[0] = '^';
+      strncpy (history_search_string + 1, rl_line_buffer, rl_point);
+      history_search_string[rl_point + 1] = '\0';
+    }
+  _rl_free_saved_history_line ();
+}
+
+/* Search forward in the history for the string of characters
+   from the start of the line to rl_point.  This is a non-incremental
+   search. */
+int
+rl_history_search_forward (count, ignore)
+     int count, ignore;
+{
+  if (count == 0)
+    return (0);
+
+  if (rl_last_func != rl_history_search_forward &&
+      rl_last_func != rl_history_search_backward)
+    rl_history_search_reinit ();
+
+  if (rl_history_search_len == 0)
+    return (rl_get_next_history (count, ignore));
+  return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
+}
+
+/* Search backward through the history for the string of characters
+   from the start of the line to rl_point.  This is a non-incremental
+   search. */
+int
+rl_history_search_backward (count, ignore)
+     int count, ignore;
+{
+  if (count == 0)
+    return (0);
+
+  if (rl_last_func != rl_history_search_forward &&
+      rl_last_func != rl_history_search_backward)
+    rl_history_search_reinit ();
+
+  if (rl_history_search_len == 0)
+    return (rl_get_previous_history (count, ignore));
+  return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
+}
index 4d6304c..1f73944 100644 (file)
@@ -285,6 +285,7 @@ sh_realpath (pathname, resolved)
     {
       strncpy (resolved, wd, PATH_MAX - 1);
       resolved[PATH_MAX - 1] = '\0';
+      free (wd);
       return resolved;
     }
   else
diff --git a/lib/sh/pathphys.c~ b/lib/sh/pathphys.c~
new file mode 100644 (file)
index 0000000..4d6304c
--- /dev/null
@@ -0,0 +1,295 @@
+/* pathphys.c -- Return pathname with all symlinks expanded. */
+
+/* Copyright (C) 2000 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>
+#ifndef _MINIX
+#  include <sys/param.h>
+#endif
+#include <posixstat.h>
+
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include <filecntl.h>
+#include <bashansi.h>
+#include <stdio.h>
+#include <chartypes.h>
+#include <errno.h>
+
+#include "shell.h"
+
+#if !defined (MAXSYMLINKS)
+#  define MAXSYMLINKS 32
+#endif
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+extern char *get_working_directory __P((char *));
+
+static int
+_path_readlink (path, buf, bufsiz)
+     char *path;
+     char *buf;
+     int bufsiz;
+{
+#ifdef HAVE_READLINK
+  return readlink (path, buf, bufsiz);
+#else
+  errno = EINVAL;
+  return -1;
+#endif
+}
+
+/* Look for ROOTEDPATH, PATHSEP, DIRSEP, and ISDIRSEP in ../../general.h */
+
+#define DOUBLE_SLASH(p)        ((p[0] == '/') && (p[1] == '/') && p[2] != '/')
+
+/*
+ * Return PATH with all symlinks expanded in newly-allocated memory.
+ * This always gets an absolute pathname.
+ */
+
+char *
+sh_physpath (path, flags)
+     char *path;
+     int flags;
+{
+  char tbuf[PATH_MAX+1], linkbuf[PATH_MAX+1];
+  char *result, *p, *q, *qsave, *qbase, *workpath;
+  int double_slash_path, linklen, nlink;
+
+  linklen = strlen (path);
+
+#if 0
+  /* First sanity check -- punt immediately if the name is too long. */
+  if (linklen >= PATH_MAX)
+    return (savestring (path));
+#endif
+
+  nlink = 0;
+  q = result = (char *)xmalloc (PATH_MAX + 1);
+
+  /* Even if we get something longer than PATH_MAX, we might be able to
+     shorten it, so we try. */
+  if (linklen >= PATH_MAX)
+    workpath = savestring (path);
+  else
+    {
+      workpath = (char *)xmalloc (PATH_MAX + 1);
+      strcpy (workpath, path);
+    }
+
+  /* This always gets an absolute pathname. */
+
+  /* POSIX.2 says to leave a leading `//' alone.  On cygwin, we skip over any
+     leading `x:' (dos drive name). */
+#if defined (__CYGWIN__)
+  qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
+#else
+  qbase = workpath + 1;
+#endif
+  double_slash_path = DOUBLE_SLASH (workpath);
+  qbase += double_slash_path;
+
+  for (p = workpath; p < qbase; )
+    *q++ = *p++;
+  qbase = q;
+
+  /*
+   * invariants:
+   *     qbase points to the portion of the result path we want to modify
+   *      p points at beginning of path element we're considering.
+   *      q points just past the last path element we wrote (no slash).
+   *
+   * XXX -- need to fix error checking for too-long pathnames
+   */
+
+  while (*p)
+    {
+      if (ISDIRSEP(p[0])) /* null element */
+       p++;
+      else if(p[0] == '.' && PATHSEP(p[1]))    /* . and ./ */
+       p += 1;         /* don't count the separator in case it is nul */
+      else if (p[0] == '.' && p[1] == '.' && PATHSEP(p[2])) /* .. and ../ */
+       {
+         p += 2; /* skip `..' */
+         if (q > qbase)
+           {
+             while (--q > qbase && ISDIRSEP(*q) == 0)
+               ;
+           }
+       }
+      else     /* real path element */
+       {
+         /* add separator if not at start of work portion of result */
+         qsave = q;
+         if (q != qbase)
+           *q++ = DIRSEP;
+         while (*p && (ISDIRSEP(*p) == 0))
+           {
+             if (q - result >= PATH_MAX)
+               {
+#ifdef ENAMETOOLONG
+                 errno = ENAMETOOLONG;
+#else
+                 errno = EINVAL;
+#endif
+                 goto error;
+               }
+               
+             *q++ = *p++;
+           }
+
+         *q = '\0';
+
+         linklen = _path_readlink (result, linkbuf, PATH_MAX);
+         if (linklen < 0)      /* if errno == EINVAL, it's not a symlink */
+           {
+             if (errno != EINVAL)
+               goto error;
+             continue;
+           }
+
+         /* It's a symlink, and the value is in LINKBUF. */
+         nlink++;
+         if (nlink > MAXSYMLINKS)
+           {
+#ifdef ELOOP
+             errno = ELOOP;
+#else
+             errno = EINVAL;
+#endif
+error:
+             free (result);
+             free (workpath);
+             return ((char *)NULL);
+           }
+
+         linkbuf[linklen] = '\0';
+
+         /* If the new path length would overrun PATH_MAX, punt now. */
+         if ((strlen (p) + linklen + 2) >= PATH_MAX)
+           {
+#ifdef ENAMETOOLONG
+             errno = ENAMETOOLONG;
+#else
+             errno = EINVAL;
+#endif
+             goto error;
+           }
+
+         /* Form the new pathname by copying the link value to a temporary
+            buffer and appending the rest of `workpath'.  Reset p to point
+            to the start of the rest of the path.  If the link value is an
+            absolute pathname, reset p, q, and qbase.  If not, reset p
+            and q. */
+         strcpy (tbuf, linkbuf);
+         tbuf[linklen] = '/';
+         strcpy (tbuf + linklen, p);
+         strcpy (workpath, tbuf);
+
+         if (ABSPATH(linkbuf))
+           {
+             q = result;
+             /* Duplicating some code here... */
+#if defined (__CYGWIN__)
+             qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1;
+#else
+             qbase = workpath + 1;
+#endif
+             double_slash_path = DOUBLE_SLASH (workpath);
+             qbase += double_slash_path;
+    
+             for (p = workpath; p < qbase; )
+               *q++ = *p++;
+             qbase = q;
+           }
+         else
+           {
+             p = workpath;
+             q = qsave;
+           }
+       }
+    }
+
+  *q = '\0';
+  free (workpath);
+
+  /* If the result starts with `//', but the original path does not, we
+     can turn the // into /.  Because of how we set `qbase', this should never
+     be true, but it's a sanity check. */
+  if (DOUBLE_SLASH(result) && double_slash_path == 0)
+    {
+      if (result[2] == '\0')   /* short-circuit for bare `//' */
+       result[1] = '\0';
+      else
+       strcpy (result, result + 1);
+    }
+
+  return (result);
+}
+
+char *
+sh_realpath (pathname, resolved)
+     const char *pathname;
+     char *resolved;
+{
+  char *tdir, *wd;
+
+  if (pathname == 0 || *pathname == '\0')
+    {
+      errno = (pathname == 0) ? EINVAL : ENOENT;
+      return ((char *)NULL);
+    }
+
+  if (ABSPATH (pathname) == 0)
+    {
+      wd = get_working_directory ("sh_realpath");
+      if (wd == 0)
+       return ((char *)NULL);
+      tdir = sh_makepath ((char *)pathname, wd, 0);
+      free (wd);
+    }
+  else
+    tdir = savestring (pathname);
+
+  wd = sh_physpath (tdir, 0);
+  free (tdir);
+
+  if (resolved == 0)
+    return (wd);
+
+  if (wd)
+    {
+      strncpy (resolved, wd, PATH_MAX - 1);
+      resolved[PATH_MAX - 1] = '\0';
+      return resolved;
+    }
+  else
+    {
+      resolved[0] = '\0';
+      return wd;
+    }
+}
index df543ac..494e76d 100644 (file)
--- a/nojobs.c
+++ b/nojobs.c
@@ -887,10 +887,8 @@ wait_for (pid)
   return (return_val);
 }
 
-/* Give PID SIGNAL.  This determines what job the pid belongs to (if any).
-   If PID does belong to a job, and the job is stopped, then CONTinue the
-   job after giving it SIGNAL.  Returns -1 on failure.  If GROUP is non-null,
-   then kill the process group associated with PID. */
+/* Send PID SIGNAL.  Returns -1 on failure, 0 on success.  If GROUP is non-zero,
+   or PID is less than -1, then kill the process group associated with PID. */
 int
 kill_pid (pid, signal, group)
      pid_t pid;
@@ -898,6 +896,11 @@ kill_pid (pid, signal, group)
 {
   int result;
 
+  if (pid < -1)
+    {
+      pid = -pid;
+      group = 1;
+    }
   result = group ? killpg (pid, signal) : kill (pid, signal);
   return (result);
 }