]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20070523 snapshot
authorChet Ramey <chet.ramey@case.edu>
Wed, 7 Dec 2011 14:08:27 +0000 (09:08 -0500)
committerChet Ramey <chet.ramey@case.edu>
Wed, 7 Dec 2011 14:08:27 +0000 (09:08 -0500)
63 files changed:
CWRU/CWRU.chlog
CWRU/CWRU.chlog~
MANIFEST
MANIFEST~
builtins/declare.def
builtins/declare.def~
builtins/help.def
builtins/help.def~ [new file with mode: 0644]
builtins/printf.def
builtins/printf.def~
builtins/read.def
builtins/read.def.save1
builtins/read.def~
builtins/setattr.def
builtins/setattr.def~
builtins/type.def
builtins/type.def~
display-ctrl-r.patch [new file with mode: 0644]
error.c
error.c~
externs.h
externs.h~ [new file with mode: 0644]
jobs.c.patch [new file with mode: 0644]
jobs.c~
lib/readline/display.c
lib/readline/display.c~
make_cmd.c
make_cmd.c~ [new file with mode: 0644]
print_cmd.c
print_cmd.c~
redir.c
shell.c
subst.c
subst.c~
subst.h
subst.h~ [new file with mode: 0644]
tests/exec.right
tests/exec.right~ [new file with mode: 0644]
tests/exec8.sub [new file with mode: 0644]
tests/execscript
tests/exp.right
tests/exp.tests
tests/exp.tests~
tests/exp2.sub [new file with mode: 0644]
tests/infile [new file with mode: 0644]
tests/intl.right
tests/intl.tests
tests/intl.tests~ [new file with mode: 0644]
tests/intl1.sub [new file with mode: 0644]
tests/printf.right
tests/printf.tests
tests/printf.tests~
tests/redir.right
tests/redir.tests
tests/redir.tests~ [new file with mode: 0644]
tests/redir8.sub [new file with mode: 0644]
tests/run-array
tests/run-array~ [new file with mode: 0644]
tests/type.right
tests/type.tests
tests/type.tests~ [new file with mode: 0644]
variables.c
variables.c~

index b084d1e742a60485ac1365602b73113e8010d4bc..61aafbca4989a841053c287e140bd591aa5eabbc 100644 (file)
@@ -14577,7 +14577,8 @@ subst.c
          memory.  If word expansions (particularly brace expansions) are
          required, the expansion code will free the string passed to
          expand_word_internal, and we don't want to free unallocated memory
-         (patstr++) or have duplicate frees (patstr)
+         (patstr++) or have duplicate frees (patstr).  Fixes bug reported on
+         Red Hat bugzilla
 
                                    5/9
                                    ---
@@ -14604,10 +14605,97 @@ execute_cmd.c
          and restored by execute_simple_command
 
 subst.c
-       - new variablem, assigning_in_environment, set and unset around calls
+       - new variable, assigning_in_environment, set and unset around calls
          to assign_in_env by the expansion code
 
 variables.c
        - use executing_builtin and assigning_in_environment to decide whether
          or not to look into temporary_env when calling find_variable_internal.
          Fixes problem reported by Kevin Quinn <kevquinn@gentoo.org>
+
+                                  5/22
+                                  ----
+redir.c
+       - change add_undo_redirect to differentiate between file descriptors
+         greater than SHELL_FD_BASE (currently 10) used internally to save
+         others and then being the targets of user redirection and fds that
+         are just the target of user redirections.  The former need to have
+         an `exec undo' redirect added to undo it in case exec throws away
+         redirections; the latter does not.  We use the close-on-exec flag
+         for this:  if it's set, we assume that the file descriptor is being
+         used internally to save another.  Fixes problem reported by Ian
+         Jackson <ian@davenant.greenend.org.uk>
+
+shell.c
+       - new function, init_interactive_script(), does interactive initialization
+         for a script run with `bash -i script' -- does everything the same
+         as init_interactive except set `interactive == 1', which causes the
+         shell to read from the standard input, after calling
+         init_noninteractive
+       - call init_interactive_script if a script is run as `bash -i script'.
+         Fixes problem reported by Joseph Michaud <jmichaud@sgi.com>
+
+                                  5/24
+                                  ----
+builtins/printf.def
+       - change vbadd to only call FASTCOPY if the passed buffer length is
+         > 1
+       - if the `-v' option is supplied and `vbuf' is already non-null from a
+         previous `printf -v var' call, set vbuf[0]=0 explicitly instead of
+         relying on vbadd to do it -- vbadd may not be called.
+       - fix PRETURN macro to set vbuf[0] == 0 if vbuf is not freed.  These
+         should fix problem reported by Elmar Stellnberger <estellnb@yahoo.de>
+
+lib/readline/display.c
+        - fix update_line to deal with the case where col_lendiff > 0 (meaning
+          the new string takes up more screen real estate than the old) but
+          lendiff < 0 (meaning that it takes fewer bytes to do so).  This can
+          happen when a multibyte prompt string is replaced with a longer one
+          containing only single-byte characters (e.g., when doing a reverse
+          i-search).  Fixes gentoo bug reported by Peter Volkov
+          <torre_cremata@mail.ru>
+
+builtins/read.def
+       - make sure we only print $PS2 if the standard input is a terminal
+       - new function, read_mbchar, to read a multibyte character so we
+         can make sure we read entire multibyte chars when `read -n' is
+         used, rather than bytes.  Only called when -n is supplied.
+         Fixes problem reported by Stanislav Brabec <sbrabec@suse.cz>
+
+                                  5/25
+                                  ----
+externs.h
+       - new #defines for third argument to named_function_string:
+         FUNC_MULTILINE (don't suppress newlines) and FUNC_EXTERNAL (convert
+         to external display form)
+
+subst.h
+       - new extern declaration for remove_quoted_escapes
+
+subst.c
+       - remove_quoted_escapes is now global
+
+print_cmd.c
+       - in named_function_string, if FUNC_EXTERNAL is in the flags argument,
+         call remove_quoted_escapes to convert from internal to external form.
+         Fixes bug reported by Bo Andresen <bo.andresen@zlin.dk>
+
+variables.c,builtins/{declare,setattr,type}.def
+       - use FUNC_MULTILINE in calls to named_function_string as appropriate
+       - add FUNC_EXTERNAL to calls to named_function_string as appropriate
+
+                                  5/27
+                                  ----
+{make_cmd,variables}.c
+       - changes to enable the shell to compile when debugger support is
+         configured out (function_def hash table and access functions).  Fixes
+         bug reported by Horst Wente <horst.wente@acm.org>
+
+builtins/help.def
+       - fix bug in `help' two-column printing to avoid referencing
+         shell_builtins[num_shell_builtins]
+
+error.c
+       - in get_name_for_error, use dollar_vars[0] if the name returned from
+         looking in $BASH_SOURCE[0] is the empty string as well as if it's
+         null
index 51d9ed5a67f1b22d685a33134ec20c36732b0f83..09f9fbd398d13d40fbb8d250dccc6a6bdc0f4daf 100644 (file)
@@ -14577,7 +14577,8 @@ subst.c
          memory.  If word expansions (particularly brace expansions) are
          required, the expansion code will free the string passed to
          expand_word_internal, and we don't want to free unallocated memory
-         (patstr++) or have duplicate frees (patstr)
+         (patstr++) or have duplicate frees (patstr).  Fixes bug reported on
+         Red Hat bugzilla
 
                                    5/9
                                    ---
@@ -14594,3 +14595,102 @@ jobs.c
        - change reset_job_indices to avoid infinite looping when js.j_firstj
          == 0 or js.j_firstj == js.j_jobslots upon function entry.  Fixes
          bug reported by osicka@post.cz
+
+                                  5/20
+                                  ----
+
+execute_cmd.c
+       - new variable, executing_builtin, keeps track of number of "levels"
+         of builtins being executed; incremented by execute_builtin; saved
+         and restored by execute_simple_command
+
+subst.c
+       - new variable, assigning_in_environment, set and unset around calls
+         to assign_in_env by the expansion code
+
+variables.c
+       - use executing_builtin and assigning_in_environment to decide whether
+         or not to look into temporary_env when calling find_variable_internal.
+         Fixes problem reported by Kevin Quinn <kevquinn@gentoo.org>
+
+                                  5/22
+                                  ----
+redir.c
+       - change add_undo_redirect to differentiate between file descriptors
+         greater than SHELL_FD_BASE (currently 10) used internally to save
+         others and then being the targets of user redirection and fds that
+         are just the target of user redirections.  The former need to have
+         an `exec undo' redirect added to undo it in case exec throws away
+         redirections; the latter does not.  We use the close-on-exec flag
+         for this:  if it's set, we assume that the file descriptor is being
+         used internally to save another.  Fixes problem reported by Ian
+         Jackson <ian@davenant.greenend.org.uk>
+
+shell.c
+       - new function, init_interactive_script(), does interactive initialization
+         for a script run with `bash -i script' -- does everything the same
+         as init_interactive except set `interactive == 1', which causes the
+         shell to read from the standard input, after calling
+         init_noninteractive
+       - call init_interactive_script if a script is run as `bash -i script'.
+         Fixes problem reported by Joseph Michaud <jmichaud@sgi.com>
+
+                                  5/24
+                                  ----
+builtins/printf.def
+       - change vbadd to only call FASTCOPY if the passed buffer length is
+         > 1
+       - if the `-v' option is supplied and `vbuf' is already non-null from a
+         previous `printf -v var' call, set vbuf[0]=0 explicitly instead of
+         relying on vbadd to do it -- vbadd may not be called.
+       - fix PRETURN macro to set vbuf[0] == 0 if vbuf is not freed.  These
+         should fix problem reported by Elmar Stellnberger <estellnb@yahoo.de>
+
+lib/readline/display.c
+        - fix update_line to deal with the case where col_lendiff > 0 (meaning
+          the new string takes up more screen real estate than the old) but
+          lendiff < 0 (meaning that it takes fewer bytes to do so).  This can
+          happen when a multibyte prompt string is replaced with a longer one
+          containing only single-byte characters (e.g., when doing a reverse
+          i-search).  Fixes gentoo bug reported by Peter Volkov
+          <torre_cremata@mail.ru>
+
+builtins/read.def
+       - make sure we only print $PS2 if the standard input is a terminal
+       - new function, read_mbchar, to read a multibyte character so we
+         can make sure we read entire multibyte chars when `read -n' is
+         used, rather than bytes.  Only called when -n is supplied.
+         Fixes problem reported by Stanislav Brabec <sbrabec@suse.cz>
+
+                                  5/25
+                                  ----
+externs.h
+       - new #defines for third argument to named_function_string:
+         FUNC_MULTILINE (don't suppress newlines) and FUNC_EXTERNAL (convert
+         to external display form)
+
+subst.h
+       - new extern declaration for remove_quoted_escapes
+
+subst.c
+       - remove_quoted_escapes is now global
+
+print_cmd.c
+       - in named_function_string, if FUNC_EXTERNAL is in the flags argument,
+         call remove_quoted_escapes to convert from internal to external form.
+         Fixes bug reported by Bo Andresen <bo.andresen@zlin.dk>
+
+variables.c,builtins/{declare,setattr,type}.def
+       - use FUNC_MULTILINE in calls to named_function_string as appropriate
+       - add FUNC_EXTERNAL to calls to named_function_string as appropriate
+
+                                  5/27
+                                  ----
+{make_cmd,variables}.c
+       - changes to enable the shell to compile when debugger support is
+         configured out (function_def hash table and access functions).  Fixes
+         bug reported by Horst Wente <horst.wente@acm.org>
+
+builtins/help.def
+       - fix bug in `help' two-column printing to avoid referencing
+         shell_builtins[num_shell_builtins]
index 28a45217020a2e61778222840a2127c42c470d01..732527dd21b0b5bf06b7066d7f9b1be62695e166 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -754,6 +754,7 @@ tests/exec7.sub             f
 tests/exp.tests                f
 tests/exp.right                f
 tests/exp1.sub         f
+tests/exp2.sub         f
 tests/extglob.tests    f
 tests/extglob.right    f
 tests/extglob1.sub     f
@@ -795,6 +796,7 @@ tests/input-line.sh f
 tests/input-line.sub   f
 tests/input.right      f
 tests/intl.tests       f
+tests/intl1.sub                f
 tests/intl.right       f
 tests/iquote.tests     f
 tests/iquote.right     f
@@ -857,6 +859,7 @@ tests/redir4.in1    f
 tests/redir5.sub       f
 tests/redir6.sub       f
 tests/redir7.sub       f
+tests/redir8.sub       f
 tests/rhs-exp.tests    f
 tests/rhs-exp.right    f
 tests/rsh.tests                f
index 28a45217020a2e61778222840a2127c42c470d01..ce98d7e4fff53d879bd87ca510411c96e41a127a 100644 (file)
--- a/MANIFEST~
+++ b/MANIFEST~
@@ -754,6 +754,7 @@ tests/exec7.sub             f
 tests/exp.tests                f
 tests/exp.right                f
 tests/exp1.sub         f
+tests/exp2.sub         f
 tests/extglob.tests    f
 tests/extglob.right    f
 tests/extglob1.sub     f
@@ -857,6 +858,7 @@ tests/redir4.in1    f
 tests/redir5.sub       f
 tests/redir6.sub       f
 tests/redir7.sub       f
+tests/redir8.sub       f
 tests/rhs-exp.tests    f
 tests/rhs-exp.right    f
 tests/rsh.tests                f
index 2bb9e1d2de461e6f4f2fe1cedad2fce92d7819a4..f8fe32bfc422908d6d8954f48f188d8137c123bd 100644 (file)
@@ -1,7 +1,7 @@
 This file is declare.def, from which is created declare.c.
 It implements the builtins "declare" and "local" in Bash.
 
-Copyright (C) 1987-2006 Free Software Foundation, Inc.
+Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -332,7 +332,7 @@ declare_internal (list, local_var)
 #endif /* DEBUGGER */
                        {       
                          t = nodefs ? var->name
-                                    : named_function_string (name, function_cell (var), 1);
+                                    : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
                          printf ("%s\n", t);
                          any_failed = sh_chkwrite (any_failed);
                        }
index c472a86c48283e25c32442c38700613fbaf9c2e5..31c09012c25e521d185517a359b397bff549ec6f 100644 (file)
@@ -1,7 +1,7 @@
 This file is declare.def, from which is created declare.c.
 It implements the builtins "declare" and "local" in Bash.
 
-Copyright (C) 1987-2004 Free Software Foundation, Inc.
+Copyright (C) 1987-2006 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -89,10 +89,11 @@ declare_builtin (list)
 
 $BUILTIN local
 $FUNCTION local_builtin
-$SHORT_DOC local name[=value] ...
+$SHORT_DOC local [option] name[=value] ...
 Create a local variable called NAME, and give it VALUE.  LOCAL
 can only be used within a function; it makes the variable NAME
 have a visible scope restricted to that function and its children.
+OPTION can be any of the options accepted by `declare'.
 $END
 int
 local_builtin (list)
@@ -190,16 +191,12 @@ declare_internal (list, local_var)
              free (vlist);
            }
        }
+      else if (flags_on == 0)
+       return (set_builtin ((WORD_LIST *)NULL));
       else
-       {
-         if (flags_on == 0)
-           set_builtin ((WORD_LIST *)NULL);
-         else
-           set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
-       }
+       set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
 
-      fflush (stdout);
-      return (EXECUTION_SUCCESS);
+      return (sh_chkwrite (EXECUTION_SUCCESS));
     }
 
   if (pflag)   /* declare -p [-afFirtx] name [name...] */
@@ -213,7 +210,7 @@ declare_internal (list, local_var)
              any_failed++;
            }
        }
-      return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
+      return (sh_chkwrite (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS));
     }
 
 #define NEXT_VARIABLE() free (name); list = list->next; continue
@@ -335,8 +332,9 @@ declare_internal (list, local_var)
 #endif /* DEBUGGER */
                        {       
                          t = nodefs ? var->name
-                                    : named_function_string (name, function_cell (var), 1);
+                                    : named_function_string (name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL);
                          printf ("%s\n", t);
+                         any_failed = sh_chkwrite (any_failed);
                        }
                    }
                  else          /* declare -[fF] -[rx] name [name...] */
index 059f98660fc038b137ed64a05d0b410d3f3b7794..743685b111f4349c29d7927edf5a82548008bf4d 100644 (file)
@@ -208,7 +208,7 @@ A star (*) next to a name means that the command is disabled.\n\
       blurb[width - 2] = '>';          /* indicate truncation */
       blurb[width - 1] = '\0';
       printf ("%s", blurb);
-      if ((i << 1) == num_shell_builtins)
+      if (((i << 1) >= num_shell_builtins) || (i+height >= num_shell_builtins))
        {
          printf ("\n");
          break;
diff --git a/builtins/help.def~ b/builtins/help.def~
new file mode 100644 (file)
index 0000000..067b83c
--- /dev/null
@@ -0,0 +1,229 @@
+This file is help.def, from which is created help.c.
+It implements the builtin "help" in Bash.
+
+Copyright (C) 1987-2006 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.
+
+$PRODUCES help.c
+
+$BUILTIN help
+$FUNCTION help_builtin
+$DEPENDS_ON HELP_BUILTIN
+$SHORT_DOC help [-s] [pattern ...]
+Display helpful information about builtin commands.  If PATTERN is
+specified, gives detailed help on all commands matching PATTERN,
+otherwise a list of the builtins is printed.  The -s option
+restricts the output for each builtin command matching PATTERN to
+a short usage synopsis.
+$END
+
+#include <config.h>
+
+#if defined (HELP_BUILTIN)
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
+#endif
+
+#include <errno.h>
+
+#include <filecntl.h>
+
+#include "../bashintl.h"
+
+#include "../shell.h"
+#include "../builtins.h"
+#include "../pathexp.h"
+#include "common.h"
+#include "bashgetopt.h"
+
+#include <glob/strmatch.h>
+#include <glob/glob.h>
+
+#ifndef errno
+extern int errno;
+#endif
+
+static void show_builtin_command_help __P((void));
+static void show_longdoc __P((int));
+
+/* Print out a list of the known functions in the shell, and what they do.
+   If LIST is supplied, print out the list which matches for each pattern
+   specified. */
+int
+help_builtin (list)
+     WORD_LIST *list;
+{
+  register int i;
+  char *pattern, *name;
+  int plen, match_found, sflag;
+
+  sflag = 0;
+  reset_internal_getopt ();
+  while ((i = internal_getopt (list, "s")) != -1)
+    {
+      switch (i)
+       {
+       case 's':
+         sflag = 1;
+         break;
+       default:
+         builtin_usage ();
+         return (EX_USAGE);
+       }
+    }
+  list = loptend;
+
+  if (list == 0)
+    {
+      show_shell_version (0);
+      show_builtin_command_help ();
+      return (EXECUTION_SUCCESS);
+    }
+
+  /* We should consider making `help bash' do something. */
+
+  if (glob_pattern_p (list->word->word))
+    {
+      if (list->next)
+       printf (_("Shell commands matching keywords `"));
+      else
+       printf (_("Shell commands matching keyword `"));
+      print_word_list (list, ", ");
+      printf ("'\n\n");
+    }
+
+  for (match_found = 0, pattern = ""; list; list = list->next)
+    {
+      pattern = list->word->word;
+      plen = strlen (pattern);
+
+      for (i = 0; name = shell_builtins[i].name; i++)
+       {
+         QUIT;
+         if ((strncmp (pattern, name, plen) == 0) ||
+             (strmatch (pattern, name, FNMATCH_EXTFLAG) != FNM_NOMATCH))
+           {
+             printf ("%s: %s\n", name, shell_builtins[i].short_doc);
+
+             if (sflag == 0)
+               show_longdoc (i);
+
+             match_found++;
+           }
+       }
+    }
+
+  if (match_found == 0)
+    {
+      builtin_error (_("no help topics match `%s'.  Try `help help' or `man -k %s' or `info %s'."), pattern, pattern, pattern);
+      return (EXECUTION_FAILURE);
+    }
+
+  fflush (stdout);
+  return (EXECUTION_SUCCESS);
+}
+
+/* By convention, enforced by mkbuiltins.c, if separate help files are being
+   used, the long_doc array contains one string -- the full pathname of the
+   help file for this builtin.  */
+static void
+show_longdoc (i)
+     int i;
+{
+  register int j;
+  char * const *doc;
+  int fd;
+
+  doc = shell_builtins[i].long_doc;
+
+  if (doc && doc[0] && *doc[0] == '/' && doc[1] == (char *)NULL)
+    {
+      fd = open (doc[0], O_RDONLY);
+      if (fd == -1)
+       {
+         builtin_error (_("%s: cannot open: %s"), doc[0], strerror (errno));
+         return;
+       }
+      zcatfd (fd, 1, doc[0]);
+      close (fd);
+    }
+  else
+    for (j = 0; doc[j]; j++)
+      printf ("%*s%s\n", BASE_INDENT, " ", _(doc[j]));
+}
+
+static void
+show_builtin_command_help ()
+{
+  int i, j;
+  int height, width;
+  char *t, blurb[128];
+
+  printf (
+_("These shell commands are defined internally.  Type `help' to see this list.\n\
+Type `help name' to find out more about the function `name'.\n\
+Use `info bash' to find out more about the shell in general.\n\
+Use `man -k' or `info' to find out more about commands not in this list.\n\
+\n\
+A star (*) next to a name means that the command is disabled.\n\
+\n"));
+
+  t = get_string_value ("COLUMNS");
+  width = (t && *t) ? atoi (t) : 80;
+  if (width <= 0)
+    width = 80;
+
+  width /= 2;
+  if (width > sizeof (blurb))
+    width = sizeof (blurb);
+  height = (num_shell_builtins + 1) / 2;       /* number of rows */
+
+  for (i = 0; i < height; i++)
+    {
+      QUIT;
+
+      /* first column */
+      blurb[0] = (shell_builtins[i].flags & BUILTIN_ENABLED) ? ' ' : '*';
+      strncpy (blurb + 1, shell_builtins[i].short_doc, width - 2);
+      blurb[width - 2] = '>';          /* indicate truncation */
+      blurb[width - 1] = '\0';
+      printf ("%s", blurb);
+      if (((i << 1) >= num_shell_builtins)) /* || (i+height >= num_shell_builtins)) */
+       {
+         printf ("\n");
+         break;
+       }
+
+      /* two spaces */
+      for (j = strlen (blurb); j < width; j++)
+        putc (' ', stdout);
+
+      /* second column */
+      blurb[0] = (shell_builtins[i+height].flags & BUILTIN_ENABLED) ? ' ' : '*';
+      strncpy (blurb + 1, shell_builtins[i+height].short_doc, width - 3);
+      blurb[width - 3] = '>';          /* indicate truncation */
+      blurb[width - 2] = '\0';
+      printf ("%s\n", blurb);
+    }
+}
+#endif /* HELP_BUILTIN */
index e283323ce851a5f7bb2144e9630e6f13ad7bd728..865b04784026844ca00a8a135b3711141447d88c 100644 (file)
@@ -148,6 +148,8 @@ extern int errno;
          vbsize = 0; \
          vbuf = 0; \
        } \
+      else if (vbuf) \
+       vbuf[0] = 0; \
       fflush (stdout); \
       if (ferror (stdout)) \
        { \
@@ -228,6 +230,8 @@ printf_builtin (list)
            {
              vflag = 1;
              vblen = 0;
+             if (vbuf)
+               vbuf[0] = 0;
            }
          else
            {
@@ -835,7 +839,7 @@ vbadd (buf, blen)
 
   if (blen == 1)
     vbuf[vblen++] = buf[0];
-  else
+  else if (blen > 1)
     {
       FASTCOPY (buf, vbuf  + vblen, blen);
       vblen += blen;
index f268180a964341380cfff26ccb6325fef59b56bf..5daface1f1ef1a9660830590edb2ec1874aa065a 100644 (file)
@@ -1,7 +1,7 @@
 This file is printf.def, from which is created printf.c.
 It implements the builtin "printf" in Bash.
 
-Copyright (C) 1997-2006 Free Software Foundation, Inc.
+Copyright (C) 1997-2007 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -228,6 +228,8 @@ printf_builtin (list)
            {
              vflag = 1;
              vblen = 0;
+             if (vbuf)
+               vbuf[0] = 0;
            }
          else
            {
@@ -835,7 +837,7 @@ vbadd (buf, blen)
 
   if (blen == 1)
     vbuf[vblen++] = buf[0];
-  else
+  else if (blen > 1)
     {
       FASTCOPY (buf, vbuf  + vblen, blen);
       vblen += blen;
index 0739059f9b93d87288ec27bf840a7b9bac78d3ee..e5aff643904fce490f398d55d5d1272fbc2c8831 100644 (file)
@@ -94,6 +94,9 @@ static void set_eol_delim __P((int));
 static void reset_eol_delim __P((char *));
 #endif
 static SHELL_VAR *bind_read_variable __P((char *, char *));
+#if defined (HANDLE_MULTIBYTE)
+static int read_mbchar __P((int, char *, int, int, int));
+#endif
 
 static sighandler sigalrm __P((int));
 static void reset_alarm __P((void));
@@ -441,7 +444,7 @@ read_builtin (list)
        }
 #endif
 
-      if (i + 2 >= size)
+      if (i + 4 >= size)       /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
        {
          input_string = (char *)xrealloc (input_string, size += 128);
          remove_unwind_protect ();
@@ -456,7 +459,7 @@ read_builtin (list)
          if (c == '\n')
            {
              i--;              /* back up over the CTLESC */
-             if (interactive && raw == 0)
+             if (interactive && input_is_tty && raw == 0)
                print_ps2 = 1;
            }
          else
@@ -487,6 +490,15 @@ read_builtin (list)
 
 add_char:
       input_string[i++] = c;
+
+#if defined (HANDLE_MULTIBYTE)
+      if (nchars > 0 && MB_CUR_MAX > 1)
+       {
+         input_string[i] = '\0';       /* for simplicity and debugging */
+         i += read_mbchar (fd, input_string, i, c, unbuffered_read);
+       }
+#endif
+
       nr++;
 
       if (nchars > 0 && nr >= nchars)
@@ -721,6 +733,54 @@ bind_read_variable (name, value)
 #endif /* !ARRAY_VARS */
 }
 
+#if defined (HANDLE_MULTIBYTE)
+static int
+read_mbchar (fd, string, ind, ch, unbuffered)
+     int fd;
+     char *string;
+     int ind, ch, unbuffered;
+{
+  char mbchar[MB_LEN_MAX + 1];
+  int i, n, r;
+  char c;
+  size_t ret;
+  mbstate_t ps, ps_back;
+  wchar_t wc;
+
+  memset (&ps, '\0', sizeof (mbstate_t));
+  memset (&ps_back, '\0', sizeof (mbstate_t));
+  
+  mbchar[0] = ch;
+  i = 1;
+  for (n = 0; n <= MB_LEN_MAX; n++)
+    {
+      ps_back = ps;
+      ret = mbrtowc (&wc, mbchar, i, &ps);
+      if (ret == (size_t)-2)
+       {
+         ps = ps_back;
+         if (unbuffered)
+           r = zread (fd, &c, 1);
+         else
+           r = zreadc (fd, &c);
+         if (r < 0)
+           goto mbchar_return;
+         mbchar[i++] = c;      
+         continue;
+       }
+      else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0)
+       break;
+    }
+
+mbchar_return:
+  if (i > 1)   /* read a multibyte char */
+    /* mbchar[0] is already string[ind-1] */
+    for (r = 1; r < i; r++)
+      string[ind+r-1] = mbchar[r];
+  return i - 1;
+}
+#endif
+
 #if defined (READLINE)
 static rl_completion_func_t *old_attempted_completion_function = 0;
 
index e22f8228d197b8905ccc4c49e6487bb40d5b005c..5bfe00b465e62307166c279d76c42835abb4170d 100644 (file)
@@ -128,7 +128,7 @@ read_builtin (list)
 {
   register char *varname;
   int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
-  int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc;
+  int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
   int raw, edit, nchars, silent, have_timeout, fd;
   unsigned int tmout;
   intmax_t intval;
@@ -263,8 +263,8 @@ read_builtin (list)
   ifs_chars = getifs ();
   if (ifs_chars == 0)          /* XXX - shouldn't happen */
     ifs_chars = "";
-  for (skip_ctlesc = 0, e = ifs_chars; *e; e++)
-    skip_ctlesc |= *e == CTLESC;
+  for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++)
+    skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL;
 
   input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
 
@@ -456,7 +456,7 @@ read_builtin (list)
          if (c == '\n')
            {
              i--;              /* back up over the CTLESC */
-             if (interactive && raw == 0)
+             if (interactive && input_is_tty && raw == 0)
                print_ps2 = 1;
            }
          else
@@ -479,7 +479,7 @@ read_builtin (list)
       if ((unsigned char)c == delim)
        break;
 
-      if ((skip_ctlesc == 0 && c == CTLESC) || c == CTLNUL)
+      if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
        {
          saw_escape++;
          input_string[i++] = CTLESC;
index e22f8228d197b8905ccc4c49e6487bb40d5b005c..9680c425a8dcea64c2e74688870fd52355d398d3 100644 (file)
@@ -94,6 +94,9 @@ static void set_eol_delim __P((int));
 static void reset_eol_delim __P((char *));
 #endif
 static SHELL_VAR *bind_read_variable __P((char *, char *));
+#if defined (HANDLE_MULTIBYTE)
+static int read_mbchar __P((int, char *, int, int, int));
+#endif
 
 static sighandler sigalrm __P((int));
 static void reset_alarm __P((void));
@@ -128,7 +131,7 @@ read_builtin (list)
 {
   register char *varname;
   int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
-  int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc;
+  int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
   int raw, edit, nchars, silent, have_timeout, fd;
   unsigned int tmout;
   intmax_t intval;
@@ -263,8 +266,8 @@ read_builtin (list)
   ifs_chars = getifs ();
   if (ifs_chars == 0)          /* XXX - shouldn't happen */
     ifs_chars = "";
-  for (skip_ctlesc = 0, e = ifs_chars; *e; e++)
-    skip_ctlesc |= *e == CTLESC;
+  for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++)
+    skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL;
 
   input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
 
@@ -441,7 +444,7 @@ read_builtin (list)
        }
 #endif
 
-      if (i + 2 >= size)
+      if (i + 4 >= size)       /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
        {
          input_string = (char *)xrealloc (input_string, size += 128);
          remove_unwind_protect ();
@@ -456,7 +459,7 @@ read_builtin (list)
          if (c == '\n')
            {
              i--;              /* back up over the CTLESC */
-             if (interactive && raw == 0)
+             if (interactive && input_is_tty && raw == 0)
                print_ps2 = 1;
            }
          else
@@ -479,7 +482,7 @@ read_builtin (list)
       if ((unsigned char)c == delim)
        break;
 
-      if ((skip_ctlesc == 0 && c == CTLESC) || c == CTLNUL)
+      if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
        {
          saw_escape++;
          input_string[i++] = CTLESC;
@@ -487,6 +490,15 @@ read_builtin (list)
 
 add_char:
       input_string[i++] = c;
+
+#if defined (HANDLE_MULTIBYTE)
+      if (MB_CUR_MAX > 1)
+       {
+         input_string[i] = '\0';       /* for simplicity and debugging */
+         i += read_mbchar (fd, input_string, i, c, unbuffered_read);
+       }
+#endif
+
       nr++;
 
       if (nchars > 0 && nr >= nchars)
@@ -721,6 +733,54 @@ bind_read_variable (name, value)
 #endif /* !ARRAY_VARS */
 }
 
+#if defined (HANDLE_MULTIBYTE)
+static int
+read_mbchar (fd, string, ind, ch, unbuffered)
+     int fd;
+     char *string;
+     int ind, ch, unbuffered;
+{
+  char mbchar[MB_LEN_MAX + 1];
+  int i, n, r;
+  char c;
+  size_t ret;
+  mbstate_t ps, ps_back;
+  wchar_t wc;
+
+  memset (&ps, '\0', sizeof (mbstate_t));
+  memset (&ps_back, '\0', sizeof (mbstate_t));
+  
+  mbchar[0] = ch;
+  i = 1;
+  for (n = 0; n <= MB_LEN_MAX; n++)
+    {
+      ps_back = ps;
+      ret = mbrtowc (&wc, mbchar, i, &ps);
+      if (ret == (size_t)-2)
+       {
+         ps = ps_back;
+         if (unbuffered)
+           r = zread (fd, &c, 1);
+         else
+           r = zreadc (fd, &c);
+         if (r < 0)
+           goto mbchar_return;
+         mbchar[i++] = c;      
+         continue;
+       }
+      else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0)
+       break;
+    }
+
+mbchar_return:
+  if (i > 1)   /* read a multibyte char */
+    /* mbchar[0] is already string[ind-1] */
+    for (r = 1; r < i; r++)
+      string[ind+r-1] = mbchar[r];
+  return i - 1;
+}
+#endif
+
 #if defined (READLINE)
 static rl_completion_func_t *old_attempted_completion_function = 0;
 
index 8507120bb569203ae0b437e99e3fa8ac92f2ef4a..a44bfde84a6167393b18128d3f63e722c0969539 100644 (file)
@@ -340,7 +340,7 @@ show_var_attributes (var, pattr, nodefs)
      reused as input to recreate the current state. */
   if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
     {
-      printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
+      printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
       nodefs++;
       if (pattr == 0 && i == 1 && flags[0] == 'f')
        return 0;               /* don't print `declare -f name' */
@@ -363,7 +363,7 @@ show_var_attributes (var, pattr, nodefs)
   if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
     printf ("%s\n", var->name);
   else if (function_p (var))
-    printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
+    printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE|FUNC_EXTERNAL));
   else if (invisible_p (var))
     printf ("%s\n", var->name);
   else
index 90f8dcc8b114572ff4d1e3306cabe6e6a7ceb699..72bde0d1de1d376621f59d3e4ad96d9c4e8fe1b8 100644 (file)
@@ -1,7 +1,7 @@
 This file is setattr.def, from which is created setattr.c.
 It implements the builtins "export" and "readonly", in Bash.
 
-Copyright (C) 1987-2006 Free Software Foundation, Inc.
+Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -52,7 +52,7 @@ extern int declare_builtin __P((WORD_LIST *));
 
 $BUILTIN export
 $FUNCTION export_builtin
-$SHORT_DOC export [-nf] [name[=value] ...] or export -p
+$SHORT_DOC export [-fn] [name[=value] ...] or export -p
 NAMEs are marked for automatic export to the environment of
 subsequently executed commands.  If the -f option is given,
 the NAMEs refer to functions.  If no NAMEs are given, or if `-p'
@@ -268,7 +268,11 @@ set_or_show_attributes (list, attribute, nodefs)
                continue;
 #endif
              if ((var->attributes & attribute))
-               show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
+               {
+                 show_var_attributes (var, READONLY_OR_EXPORT, nodefs);
+                 if (any_failed = sh_chkwrite (any_failed))
+                   break;
+               }
            }
          free (variable_list);
        }
@@ -336,7 +340,7 @@ show_var_attributes (var, pattr, nodefs)
      reused as input to recreate the current state. */
   if (function_p (var) && nodefs == 0 && (pattr == 0 || posixly_correct == 0))
     {
-      printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
+      printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE));
       nodefs++;
       if (pattr == 0 && i == 1 && flags[0] == 'f')
        return 0;               /* don't print `declare -f name' */
@@ -359,7 +363,7 @@ show_var_attributes (var, pattr, nodefs)
   if (nodefs || (function_p (var) && pattr != 0 && posixly_correct))
     printf ("%s\n", var->name);
   else if (function_p (var))
-    printf ("%s\n", named_function_string (var->name, function_cell (var), 1));
+    printf ("%s\n", named_function_string (var->name, function_cell (var), FUNC_MULTILINE));
   else if (invisible_p (var))
     printf ("%s\n", var->name);
   else
index 370e596c825c1555d5df59bbcec3d805c0ba075e..fa40ad25316a6932c5b8c9206da9890957497c1a 100644 (file)
@@ -1,7 +1,7 @@
 This file is type.def, from which is created type.c.
 It implements the builtin "type" in Bash.
 
-Copyright (C) 1987-2002 Free Software Foundation, Inc.
+Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -266,18 +266,14 @@ describe_command (command, dflags)
        puts ("function");
       else if (dflags & CDESC_SHORTDESC)
        {
-#define PRETTY_PRINT_FUNC 1
          char *result;
 
          printf (_("%s is a function\n"), command);
 
          /* We're blowing away THE_PRINTED_COMMAND here... */
 
-         result = named_function_string (command,
-                                         (COMMAND *) function_cell (func),
-                                         PRETTY_PRINT_FUNC);
+         result = named_function_string (command, function_cell (func), FUNC_MULTILINE|FUNC_EXTERNAL);
          printf ("%s\n", result);
-#undef PRETTY_PRINT_FUNC
        }
       else if (dflags & CDESC_REUSABLE)
        printf ("%s\n", command);
index d03ccb2d91bc7260c098fa4d8ccfd007531a5175..5480123569b77d6315eae16cdaa6b10831c1eb0b 100644 (file)
@@ -1,7 +1,7 @@
 This file is type.def, from which is created type.c.
 It implements the builtin "type" in Bash.
 
-Copyright (C) 1987-2002 Free Software Foundation, Inc.
+Copyright (C) 1987-2007 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -185,9 +185,8 @@ type_builtin (list)
       list = list->next;
     }
 
-  fflush (stdout);
-
-  return ((successful_finds != 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
+  opt = (successful_finds != 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
+  return (sh_chkwrite (opt));
 }
 
 /*
@@ -267,18 +266,14 @@ describe_command (command, dflags)
        puts ("function");
       else if (dflags & CDESC_SHORTDESC)
        {
-#define PRETTY_PRINT_FUNC 1
          char *result;
 
          printf (_("%s is a function\n"), command);
 
          /* We're blowing away THE_PRINTED_COMMAND here... */
 
-         result = named_function_string (command,
-                                         (COMMAND *) function_cell (func),
-                                         PRETTY_PRINT_FUNC);
+         result = named_function_string (command, function_cell (func), FUNC_MULTILINE);
          printf ("%s\n", result);
-#undef PRETTY_PRINT_FUNC
        }
       else if (dflags & CDESC_REUSABLE)
        printf ("%s\n", command);
@@ -390,7 +385,7 @@ describe_command (command, dflags)
       if (dflags & CDESC_TYPE)
        puts ("file");
       else if (dflags & CDESC_SHORTDESC)
-       printf ("%s is %s\n", command, full_path);
+       printf (_("%s is %s\n"), command, full_path);
       else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
        printf ("%s\n", full_path);
 
diff --git a/display-ctrl-r.patch b/display-ctrl-r.patch
new file mode 100644 (file)
index 0000000..e4d5318
--- /dev/null
@@ -0,0 +1,47 @@
+*** ../bash-3.2-patched/lib/readline/display.c Fri Apr 20 15:19:04 2007
+--- lib/readline/display.c     Thu May 24 14:13:57 2007
+***************
+*** 1518,1528 ****
+      {
+        /* Non-zero if we're increasing the number of lines. */
+        int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
+        /* Sometimes it is cheaper to print the characters rather than
+        use the terminal's capabilities.  If we're growing the number
+        of lines, make sure we actually cause the new line to wrap
+        around on auto-wrapping terminals. */
+!       if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+       {
+         /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
+            _rl_horizontal_scroll_mode == 1, inserting the characters with
+--- 1544,1574 ----
+      {
+        /* Non-zero if we're increasing the number of lines. */
+        int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
++       /* If col_lendiff is > 0, implying that the new string takes up more
++       screen real estate than the old, but lendiff is < 0, meaning that it
++       takes fewer bytes, we need to just output the characters starting
++       from the first difference.  These will overwrite what is on the
++       display, so there's no reason to do a smart update.  This can really
++       only happen in a multibyte environment. */
++       if (lendiff < 0)
++      {
++        _rl_output_some_chars (nfd, temp);
++        _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
++        /* If nfd begins before any invisible characters in the prompt,
++           adjust _rl_last_c_pos to account for wrap_offset and set
++           cpos_adjusted to let the caller know. */
++        if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
++          {
++            _rl_last_c_pos -= wrap_offset;
++            cpos_adjusted = 1;
++          }
++        return;
++      }
+        /* Sometimes it is cheaper to print the characters rather than
+        use the terminal's capabilities.  If we're growing the number
+        of lines, make sure we actually cause the new line to wrap
+        around on auto-wrapping terminals. */
+!       else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+       {
+         /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
+            _rl_horizontal_scroll_mode == 1, inserting the characters with
diff --git a/error.c b/error.c
index c83a9861195561906c2b9bc1a75b8a915c63658f..ceedc2c93a5c79915ef59b80aa3518ba2b3c74d1 100644 (file)
--- a/error.c
+++ b/error.c
@@ -108,7 +108,7 @@ get_name_for_error ()
       if (bash_source_v && array_p (bash_source_v) &&
          (bash_source_a = array_cell (bash_source_v)))
        name = array_reference (bash_source_a, 0);
-      if (name == 0)
+      if (name == 0 || *name == '\0')  /* XXX - was just name == 0 */
 #endif
        name = dollar_vars[0];
     }
index c400f44963e1528dd7919cc37b7db53fadfab8cf..c83a9861195561906c2b9bc1a75b8a915c63658f 100644 (file)
--- a/error.c~
+++ b/error.c~
@@ -59,7 +59,7 @@ extern int give_terminal_to __P((pid_t, int));
 #endif /* JOB_CONTROL */
 
 #if defined (ARRAY_VARS)
-extern char *bash_badsub_errmsg;
+extern const char * const bash_badsub_errmsg;
 #endif
 
 static void error_prolog __P((int));
@@ -70,7 +70,7 @@ static void error_prolog __P((int));
 #define MAINTAINER "bash-maintainers@gnu.org"
 #endif
 
-char *the_current_maintainer = MAINTAINER;
+const char * const the_current_maintainer = MAINTAINER;
 
 int gnu_error_format = 0;
 
@@ -399,7 +399,7 @@ trace (format, va_alist)
 /* **************************************************************** */
 
 
-static char *cmd_error_table[] = {
+static const char * const cmd_error_table[] = {
        N_("unknown command error"),    /* CMDERR_DEFAULT */
        N_("bad command type"),         /* CMDERR_BADTYPE */
        N_("bad connector"),            /* CMDERR_BADCONN */
index 834b767b6ba1b225e5333b569b9033762bb36f22..b8a2910f7e5add6361a25a70289c1dc83e9c5e46 100644 (file)
--- a/externs.h
+++ b/externs.h
@@ -30,6 +30,9 @@
 extern intmax_t evalexp __P((char *, int *));
 
 /* Functions from print_cmd.c. */
+#define FUNC_MULTILINE 0x01
+#define FUNC_EXTERNAL  0x02
+
 extern char *make_command_string __P((COMMAND *));
 extern char *named_function_string __P((char *, COMMAND *, int));
 
diff --git a/externs.h~ b/externs.h~
new file mode 100644 (file)
index 0000000..834b767
--- /dev/null
@@ -0,0 +1,399 @@
+/* externs.h -- extern function declarations which do not appear in their
+   own header file. */
+
+/* Copyright (C) 1993-2005 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. */
+
+/* Make sure that this is included *after* config.h! */
+
+#if !defined (_EXTERNS_H_)
+#  define _EXTERNS_H_
+
+#include "stdc.h"
+
+/* Functions from expr.c. */
+extern intmax_t evalexp __P((char *, int *));
+
+/* Functions from print_cmd.c. */
+extern char *make_command_string __P((COMMAND *));
+extern char *named_function_string __P((char *, COMMAND *, int));
+
+extern void print_command __P((COMMAND *));
+extern void print_simple_command __P((SIMPLE_COM *));
+extern void print_word_list __P((WORD_LIST *, char *));
+
+/* debugger support */
+extern void print_for_command_head __P((FOR_COM *));
+#if defined (SELECT_COMMAND)
+extern void print_select_command_head __P((SELECT_COM *));
+#endif
+extern void print_case_command_head __P((CASE_COM *));
+#if defined (DPAREN_ARITHMETIC)
+extern void print_arith_command __P((WORD_LIST *));
+#endif
+#if defined (COND_COMMAND)
+extern void print_cond_command __P((COND_COM *));
+#endif
+
+/* set -x support */
+extern char *indirection_level_string __P((void));
+extern void xtrace_print_assignment __P((char *, char *, int, int));
+extern void xtrace_print_word_list __P((WORD_LIST *, int));
+extern void xtrace_print_for_command_head __P((FOR_COM *));
+#if defined (SELECT_COMMAND)
+extern void xtrace_print_select_command_head __P((SELECT_COM *));
+#endif
+extern void xtrace_print_case_command_head __P((CASE_COM *));
+#if defined (DPAREN_ARITHMETIC)
+extern void xtrace_print_arith_cmd __P((WORD_LIST *));
+#endif
+#if defined (COND_COMMAND)
+extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *));
+#endif
+
+/* Functions from shell.c. */
+extern void exit_shell __P((int)) __attribute__((__noreturn__));
+extern void sh_exit __P((int)) __attribute__((__noreturn__));
+extern void disable_priv_mode __P((void));
+extern void unbind_args __P((void));
+
+#if defined (RESTRICTED_SHELL)
+extern int shell_is_restricted __P((char *));
+extern int maybe_make_restricted __P((char *));
+#endif
+
+extern void unset_bash_input __P((int));
+extern void get_current_user_info __P((void));
+
+/* Functions from eval.c. */
+extern int reader_loop __P((void));
+extern int parse_command __P((void));
+extern int read_command __P((void));
+
+/* Functions from braces.c. */
+#if defined (BRACE_EXPANSION)
+extern char **brace_expand __P((char *));
+#endif
+
+/* Miscellaneous functions from parse.y */
+extern int yyparse __P((void));
+extern int return_EOF __P((void));
+extern void reset_parser __P((void));
+extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
+
+extern void free_pushed_string_input __P((void));
+
+extern char *decode_prompt_string __P((char *));
+
+extern int get_current_prompt_level __P((void));
+extern void set_current_prompt_level __P((int));
+
+#if defined (HISTORY)
+extern char *history_delimiting_chars __P((void));
+#endif
+
+/* Declarations for functions defined in locale.c */
+extern void set_default_locale __P((void));
+extern void set_default_locale_vars __P((void));
+extern int set_locale_var __P((char *, char *));
+extern int set_lang __P((char *, char *));
+extern void set_default_lang __P((void));
+extern char *get_locale_var __P((char *));
+extern char *localetrans __P((char *, int, int *));
+extern char *mk_msgstr __P((char *, int *));
+extern char *localeexpand __P((char *, int, int, int, int *));
+
+/* Declarations for functions defined in list.c. */
+extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *));
+extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *));
+extern GENERIC_LIST *list_reverse ();
+extern int list_length ();
+extern GENERIC_LIST *list_append ();
+extern GENERIC_LIST *list_remove ();
+
+/* Declarations for functions defined in stringlib.c */
+extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
+extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int));
+extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int));
+
+extern char *substring __P((char *, int, int));
+extern char *strsub __P((char *, char *, char *, int));
+extern char *strcreplace __P((char *, int, char *, int));
+extern void strip_leading __P((char *));
+extern void strip_trailing __P((char *, int, int));
+extern void xbcopy __P((char *, char *, int));
+
+/* Functions from version.c. */
+extern char *shell_version_string __P((void));
+extern void show_shell_version __P((int));
+
+/* Functions from the bash library, lib/sh/libsh.a.  These should really
+   go into a separate include file. */
+
+/* declarations for functions defined in lib/sh/clktck.c */
+extern long get_clk_tck __P((void));
+
+/* declarations for functions defined in lib/sh/clock.c */
+extern void clock_t_to_secs ();
+extern void print_clock_t ();
+
+/* Declarations for functions defined in lib/sh/fmtulong.c */
+#define FL_PREFIX     0x01    /* add 0x, 0X, or 0 prefix as appropriate */
+#define FL_ADDBASE    0x02    /* add base# prefix to converted value */
+#define FL_HEXUPPER   0x04    /* use uppercase when converting to hex */
+#define FL_UNSIGNED   0x08    /* don't add any sign */
+
+extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
+
+/* Declarations for functions defined in lib/sh/fmtulong.c */
+#if defined (HAVE_LONG_LONG)
+extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
+#endif
+
+/* Declarations for functions defined in lib/sh/fmtumax.c */
+extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
+
+/* Declarations for functions defined in lib/sh/getcwd.c */
+#if !defined (HAVE_GETCWD)
+extern char *getcwd __P((char *, size_t));
+#endif
+
+/* Declarations for functions defined in lib/sh/itos.c */
+extern char *inttostr __P((intmax_t, char *, size_t));
+extern char *itos __P((intmax_t));
+extern char *uinttostr __P((uintmax_t, char *, size_t));
+extern char *uitos __P((uintmax_t));
+
+/* declarations for functions defined in lib/sh/makepath.c */
+#define MP_DOTILDE     0x01
+#define MP_DOCWD       0x02
+#define MP_RMDOT       0x04
+
+extern char *sh_makepath __P((const char *, const char *, int));
+
+/* declarations for functions defined in lib/sh/netconn.c */
+extern int isnetconn __P((int));
+
+/* declarations for functions defined in lib/sh/netopen.c */
+extern int netopen __P((char *));
+
+/* Declarations for  functions defined in lib/sh/oslib.c */
+
+#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
+extern int dup2 __P((int, int));
+#endif
+
+#if !defined (HAVE_GETDTABLESIZE)
+extern int getdtablesize __P((void));
+#endif /* !HAVE_GETDTABLESIZE */
+
+#if !defined (HAVE_GETHOSTNAME)
+extern int gethostname __P((char *, int));
+#endif /* !HAVE_GETHOSTNAME */
+
+extern int getmaxgroups __P((void));
+extern long getmaxchild __P((void));
+
+/* declarations for functions defined in lib/sh/pathcanon.c */
+#define PATH_CHECKDOTDOT       0x0001
+#define PATH_CHECKEXISTS       0x0002
+#define PATH_HARDPATH          0x0004
+#define PATH_NOALLOC           0x0008
+
+extern char *sh_canonpath __P((char *, int));
+
+/* declarations for functions defined in lib/sh/pathphys.c */
+extern char *sh_physpath __P((char *, int));
+extern char *sh_realpath __P((const char *, char *));
+
+/* declarations for functions defined in lib/sh/setlinebuf.c */
+#ifdef NEED_SH_SETLINEBUF_DECL
+extern int sh_setlinebuf __P((FILE *));
+#endif
+
+/* declarations for functions defined in lib/sh/shaccess.c */
+extern int sh_eaccess __P((char *, int));
+
+/* declarations for functions defined in lib/sh/shmatch.c */
+extern int sh_regmatch __P((const char *, const char *, int));
+
+/* defines for flags argument to sh_regmatch. */
+#define SHMAT_SUBEXP           0x001   /* save subexpressions in SH_REMATCH */
+#define SHMAT_PWARN            0x002   /* print a warning message on invalid regexp */
+
+/* declarations for functions defined in lib/sh/shquote.c */
+extern char *sh_single_quote __P((char *));
+extern char *sh_double_quote __P((char *));
+extern char *sh_mkdoublequoted __P((const char *, int, int));
+extern char *sh_un_double_quote __P((char *));
+extern char *sh_backslash_quote __P((char *));
+extern char *sh_backslash_quote_for_double_quotes __P((char *));
+extern int sh_contains_shell_metas __P((char *));
+
+/* declarations for functions defined in lib/sh/spell.c */
+extern int spname __P((char *, char *));
+
+/* declarations for functions defined in lib/sh/strcasecmp.c */
+#if !defined (HAVE_STRCASECMP)
+extern int strncasecmp __P((const char *, const char *, int));
+extern int strcasecmp __P((const char *, const char *));
+#endif /* HAVE_STRCASECMP */
+
+/* declarations for functions defined in lib/sh/strerror.c */
+#if !defined (HAVE_STRERROR) && !defined (strerror)
+extern char *strerror __P((int));
+#endif
+
+/* declarations for functions defined in lib/sh/strftime.c */
+#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL)
+extern size_t strftime __P((char *, size_t, const char *, const struct tm *));
+#endif
+
+/* declarations for functions defined in lib/sh/strindex.c */
+extern char *strindex __P((const char *, const char *));
+
+/* declarations for functions and structures defined in lib/sh/stringlist.c */
+
+/* This is a general-purpose argv-style array struct. */
+typedef struct _list_of_strings {
+  char **list;
+  int list_size;
+  int list_len;
+} STRINGLIST;
+
+typedef int sh_strlist_map_func_t __P((char *));
+
+extern STRINGLIST *strlist_create __P((int));
+extern STRINGLIST *strlist_resize __P((STRINGLIST *, int));
+extern void strlist_flush __P((STRINGLIST *));
+extern void strlist_dispose __P((STRINGLIST *));
+extern int strlist_remove __P((STRINGLIST *, char *));
+extern STRINGLIST *strlist_copy __P((STRINGLIST *));
+extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *));
+extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *));
+extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *));
+extern void strlist_print __P((STRINGLIST *, char *));
+extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *));
+extern void strlist_sort __P((STRINGLIST *));
+
+/* declarations for functions defined in lib/sh/stringvec.c */
+
+extern char **strvec_create __P((int));
+extern char **strvec_resize __P((char **, int));
+extern void strvec_flush __P((char **));
+extern void strvec_dispose __P((char **));
+extern int strvec_remove __P((char **, char *));
+extern int strvec_len __P((char **));
+extern int strvec_search __P((char **, char *));
+extern char **strvec_copy __P((char **));
+extern int strvec_strcmp __P((char **, char **));
+extern void strvec_sort __P((char **));
+
+extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
+extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
+
+/* declarations for functions defined in lib/sh/strnlen.c */
+#if !defined (HAVE_STRNLEN)
+extern size_t strnlen __P((const char *, size_t));
+#endif
+
+/* declarations for functions defined in lib/sh/strpbrk.c */
+#if !defined (HAVE_STRPBRK)
+extern char *strpbrk __P((const char *, const char *));
+#endif
+
+/* declarations for functions defined in lib/sh/strtod.c */
+#if !defined (HAVE_STRTOD)
+extern double strtod __P((const char *, char **));
+#endif
+
+/* declarations for functions defined in lib/sh/strtol.c */
+#if !HAVE_DECL_STRTOL
+extern long strtol __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strtoll.c */
+#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOLL
+extern long long strtoll __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strtoul.c */
+#if !HAVE_DECL_STRTOUL
+extern unsigned long strtoul __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strtoull.c */
+#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOULL
+extern unsigned long long strtoull __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strimax.c */
+#if !HAVE_DECL_STRTOIMAX
+extern intmax_t strtoimax __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strumax.c */
+#if !HAVE_DECL_STRTOUMAX
+extern uintmax_t strtoumax __P((const char *, char **, int));
+#endif
+
+/* declarations for functions defined in lib/sh/strtrans.c */
+extern char *ansicstr __P((char *, int, int, int *, int *));
+extern char *ansic_quote __P((char *, int, int *));
+extern int ansic_shouldquote __P((const char *));
+extern char *ansiexpand __P((char *, int, int, int *));
+
+/* declarations for functions defined in lib/sh/timeval.c.  No prototypes
+   so we don't have to count on having a definition of struct timeval in
+   scope when this file is included. */
+extern void timeval_to_secs ();
+extern void print_timeval ();
+
+/* declarations for functions defined in lib/sh/tmpfile.c */
+#define MT_USETMPDIR           0x0001
+#define MT_READWRITE           0x0002
+#define MT_USERANDOM           0x0004
+
+extern char *sh_mktmpname __P((char *, int));
+extern int sh_mktmpfd __P((char *, int, char **));
+/* extern FILE *sh_mktmpfp __P((char *, int, char **)); */
+
+/* declarations for functions defined in lib/sh/winsize.c */
+extern void get_new_window_size __P((int, int *, int *));
+
+/* declarations for functions defined in lib/sh/xstrchr.c */
+#undef xstrchr
+extern char *xstrchr __P((const char *, int));
+
+/* declarations for functions defined in lib/sh/zcatfd.c */
+extern int zcatfd __P((int, int, char *));
+
+/* declarations for functions defined in lib/sh/zmapfd.c */
+extern int zmapfd __P((int, char **, char *));
+
+/* declarations for functions defined in lib/sh/zread.c */
+extern ssize_t zread __P((int, char *, size_t));
+extern ssize_t zreadintr __P((int, char *, size_t));
+extern ssize_t zreadc __P((int, char *));
+extern void zreset __P((void));
+extern void zsyncfd __P((int));
+
+/* declarations for functions defined in lib/sh/zwrite.c */
+extern int zwrite __P((int, char *, size_t));
+
+#endif /* _EXTERNS_H_ */
diff --git a/jobs.c.patch b/jobs.c.patch
new file mode 100644 (file)
index 0000000..8b2d163
--- /dev/null
@@ -0,0 +1,65 @@
+*** ../bash-20070510/jobs.c    Thu Mar  8 16:05:50 2007
+--- jobs.c     Fri May 18 11:40:14 2007
+***************
+*** 784,792 ****
+      {
+        old = js.j_firstj++;
+        while (js.j_firstj != old)
+       {
+         if (js.j_firstj >= js.j_jobslots)
+           js.j_firstj = 0;
+!        if (jobs[js.j_firstj])
+           break;
+         js.j_firstj++;
+--- 784,794 ----
+      {
+        old = js.j_firstj++;
++       if (old >= js.j_jobslots)
++      old = js.j_jobslots - 1;
+        while (js.j_firstj != old)
+       {
+         if (js.j_firstj >= js.j_jobslots)
+           js.j_firstj = 0;
+!        if (jobs[js.j_firstj] || js.j_firstj == old)  /* needed if old == 0 */
+           break;
+         js.j_firstj++;
+***************
+*** 798,806 ****
+      {
+        old = js.j_lastj--;
+        while (js.j_lastj != old)
+       {
+         if (js.j_lastj < 0)
+           js.j_lastj = js.j_jobslots - 1;
+!        if (jobs[js.j_lastj])
+           break;
+         js.j_lastj--;
+--- 800,810 ----
+      {
+        old = js.j_lastj--;
++       if (old < 0)
++      old = 0;
+        while (js.j_lastj != old)
+       {
+         if (js.j_lastj < 0)
+           js.j_lastj = js.j_jobslots - 1;
+!        if (jobs[js.j_lastj] || js.j_lastj == old)    /* needed if old == js.j_jobslots */
+           break;
+         js.j_lastj--;
+***************
+*** 964,968 ****
+    realloc_jobs_list ();
+  
+!   return (js.j_lastj ? js.j_lastj + 1 : 0);
+  }
+  
+--- 975,983 ----
+    realloc_jobs_list ();
+  
+! #ifdef DEBUG
+!   itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
+! #endif
+! 
+!   return ((js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
+  }
+  
diff --git a/jobs.c~ b/jobs.c~
index 7b3c2595e3578353107b11e695524fb888535e19..0ff2d591e86ee9080741c31cf2322976ca98cb18 100644 (file)
--- a/jobs.c~
+++ b/jobs.c~
@@ -974,7 +974,10 @@ compact_jobs_list (flags)
   reap_dead_jobs ();
   realloc_jobs_list ();
 
-itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
+#ifdef DEBUG
+  itrace("compact_jobs_list: returning %d", (js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
+#endif
+
   return ((js.j_lastj || jobs[js.j_lastj]) ? js.j_lastj + 1 : 0);
 }
 
@@ -3554,6 +3557,7 @@ initialize_job_control (force)
                  setpgid (0, original_pgrp);
                  shell_pgrp = original_pgrp;
                  job_control = 0;
+internal_error ("cannot set terminal pgrp to %d: %s", shell_pgrp, strerror (errno));
                }
            }
        }
index b48477776f75fb34712963b3d1d89b580dffeb45..1fbd9e5910e9c55f16209b84020f725734c7cdc4 100644 (file)
@@ -1544,11 +1544,31 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
     {
       /* Non-zero if we're increasing the number of lines. */
       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
+      /* If col_lendiff is > 0, implying that the new string takes up more
+        screen real estate than the old, but lendiff is < 0, meaning that it
+        takes fewer bytes, we need to just output the characters starting
+        from the first difference.  These will overwrite what is on the
+        display, so there's no reason to do a smart update.  This can really
+        only happen in a multibyte environment. */
+      if (lendiff < 0)
+       {
+         _rl_output_some_chars (nfd, temp);
+         _rl_last_c_pos += _rl_col_width (nfd, 0, temp);
+         /* If nfd begins before any invisible characters in the prompt,
+            adjust _rl_last_c_pos to account for wrap_offset and set
+            cpos_adjusted to let the caller know. */
+         if (current_line == 0 && wrap_offset && ((nfd - new) <= prompt_last_invisible))
+           {
+             _rl_last_c_pos -= wrap_offset;
+             cpos_adjusted = 1;
+           }
+         return;
+       }
       /* Sometimes it is cheaper to print the characters rather than
         use the terminal's capabilities.  If we're growing the number
         of lines, make sure we actually cause the new line to wrap
         around on auto-wrapping terminals. */
-      if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+      else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
        {
          /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
             _rl_horizontal_scroll_mode == 1, inserting the characters with
index f0d5e2d2989e2726b42d1cf40871cd87a91c3c5f..ce811709b17d3e18d63a136859482d1a8c3b2cfc 100644 (file)
@@ -1317,9 +1317,6 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
     }
 
       
-_rl_trace("update_line: old = %p \"%s\"", old, old);
-_rl_trace("update_line: new = %p \"%s\"", new, new);
-
   /* Find first difference. */
 #if defined (HANDLE_MULTIBYTE)
   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1356,8 +1353,6 @@ _rl_trace("update_line: new = %p \"%s\"", new, new);
                }
            }
        }
-_rl_trace("update_line: ofd = %p \"%s\"", ofd, ofd);
-_rl_trace("update_line: nfd = %p \"%s\"", nfd, nfd);
     }
   else
 #endif
@@ -1372,9 +1367,6 @@ _rl_trace("update_line: nfd = %p \"%s\"", nfd, nfd);
   for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
   for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
 
-_rl_trace("update_line: oe = %p \"%s\"", oe, oe);
-_rl_trace("update_line: ne = %p \"%s\"", ne, ne);
-
   /* If no difference, continue to next line. */
   if (ofd == oe && nfd == ne)
     return;
@@ -1453,9 +1445,6 @@ _rl_trace("update_line: ne = %p \"%s\"", ne, ne);
        }
     }
 
-_rl_trace("update_line: ols = %p \"%s\"", ols, ols);
-_rl_trace("update_line: nls = %p \"%s\"", nls, nls);
-
   /* count of invisible characters in the current invisible line. */
   current_invis_chars = W_OFFSET (current_line, wrap_offset);
   if (_rl_last_v_pos != current_line)
@@ -1488,18 +1477,18 @@ _rl_trace("update_line: nls = %p \"%s\"", nls, nls);
 #else
       tputs (_rl_term_cr, 1, _rl_output_character_function);
 #endif
-_rl_trace("update_line: redrawing prompt");
+      if (modmark)
+       _rl_output_some_chars ("*", 1);
       _rl_output_some_chars (local_prompt, lendiff);
       if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
        {
          /* We take wrap_offset into account here so we can pass correct
             information to _rl_move_cursor_relative. */
-         _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset;
+         _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset + modmark;
          cpos_adjusted = 1;
        }
       else
-       _rl_last_c_pos = lendiff;
-_rl_trace("update_line: redrawing prompt: _rl_last_c_pos = %d", _rl_last_c_pos);
+       _rl_last_c_pos = lendiff + modmark;
     }
 
   /* When this function returns, _rl_last_c_pos is correct, and an absolute
@@ -1526,7 +1515,6 @@ _rl_trace("update_line: redrawing prompt: _rl_last_c_pos = %d", _rl_last_c_pos);
   else
     col_lendiff = lendiff;
 
-_rl_trace("update_line: lendiff = %d col_lendiff = %d", lendiff, col_lendiff);
   /* If we are changing the number of invisible characters in a line, and
      the spot of first difference is before the end of the invisible chars,
      lendiff needs to be adjusted. */
@@ -1545,7 +1533,6 @@ _rl_trace("update_line: lendiff = %d col_lendiff = %d", lendiff, col_lendiff);
        }
     }
 
-_rl_trace("update_line: after adjustment: lendiff = %d col_lendiff = %d", lendiff, col_lendiff);
   /* Insert (diff (len (old), len (new)) ch. */
   temp = ne - nfd;
   if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
@@ -1557,11 +1544,23 @@ _rl_trace("update_line: after adjustment: lendiff = %d col_lendiff = %d", lendif
     {
       /* Non-zero if we're increasing the number of lines. */
       int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
+      /* If col_lendiff is > 0, implying that the new string takes up more
+        screen real estate than the old, but lendiff is < 0, meaning that it
+        takes fewer bytes, we need to just output the characters starting
+        from the first difference.  These will overwrite what is on the
+        display, so there's no reason to do a smart update.  This can really
+        only happen in a multibyte environment. */
+      if (lendiff < 0)
+       {
+         _rl_output_some_chars (nfd, temp);
+         _rl_last_c_pos += col_temp;
+         return;
+       }
       /* Sometimes it is cheaper to print the characters rather than
         use the terminal's capabilities.  If we're growing the number
         of lines, make sure we actually cause the new line to wrap
         around on auto-wrapping terminals. */
-      if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
+      else if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
        {
          /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
             _rl_horizontal_scroll_mode == 1, inserting the characters with
index 6d5409cc68ca27b89ab6ace2b0e17d316a3580bb..08eed18a895b79303b4520bb8ce70216e475be28 100644 (file)
@@ -1,7 +1,7 @@
 /* make_cmd.c -- Functions for making instances of the various
    parser constructs. */
 
-/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
+/* Copyright (C) 1989-2007 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -771,7 +771,9 @@ make_function_def (name, command, lineno, lstart)
   if (bash_source_a && array_num_elements (bash_source_a) > 0)
     temp->source_file = array_reference (bash_source_a, 0);
 #endif
+#if defined (DEBUGGER)
   bind_function_def (name->word, temp);
+#endif
 
   temp->source_file = 0;
   return (make_command (cm_function_def, (SIMPLE_COM *)temp));
diff --git a/make_cmd.c~ b/make_cmd.c~
new file mode 100644 (file)
index 0000000..a590931
--- /dev/null
@@ -0,0 +1,858 @@
+/* make_cmd.c -- Functions for making instances of the various
+   parser constructs. */
+
+/* Copyright (C) 1989-2005 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 <stdio.h>
+#include "bashtypes.h"
+#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
+#  include <sys/file.h>
+#endif
+#include "filecntl.h"
+#include "bashansi.h"
+#if defined (HAVE_UNISTD_H)
+#  include <unistd.h>
+#endif
+
+#include "bashintl.h"
+
+#include "syntax.h"
+#include "command.h"
+#include "general.h"
+#include "error.h"
+#include "flags.h"
+#include "make_cmd.h"
+#include "dispose_cmd.h"
+#include "variables.h"
+#include "subst.h"
+#include "input.h"
+#include "ocache.h"
+#include "externs.h"
+
+#if defined (JOB_CONTROL)
+#include "jobs.h"
+#endif
+
+#include "shmbutil.h"
+
+extern int line_number, current_command_line_count;
+extern int last_command_exit_value;
+
+/* Object caching */
+sh_obj_cache_t wdcache = {0, 0, 0};
+sh_obj_cache_t wlcache = {0, 0, 0};
+
+#define WDCACHESIZE    60
+#define WLCACHESIZE    60
+
+static COMMAND *make_for_or_select __P((enum command_type, WORD_DESC *, WORD_LIST *, COMMAND *, int));
+#if defined (ARITH_FOR_COMMAND)
+static WORD_LIST *make_arith_for_expr __P((char *));
+#endif
+static COMMAND *make_until_or_while __P((enum command_type, COMMAND *, COMMAND *));
+
+void
+cmd_init ()
+{
+  ocache_create (wdcache, WORD_DESC, WDCACHESIZE);
+  ocache_create (wlcache, WORD_LIST, WLCACHESIZE);
+}
+
+WORD_DESC *
+alloc_word_desc ()
+{
+  WORD_DESC *temp;
+
+  ocache_alloc (wdcache, WORD_DESC, temp);
+  temp->flags = 0;
+  temp->word = 0;
+  return temp;
+}
+
+WORD_DESC *
+make_bare_word (string)
+     const char *string;
+{
+  WORD_DESC *temp;
+
+  temp = alloc_word_desc ();
+
+  if (*string)
+    temp->word = savestring (string);
+  else
+    {
+      temp->word = (char *)xmalloc (1);
+      temp->word[0] = '\0';
+    }
+
+  return (temp);
+}
+
+WORD_DESC *
+make_word_flags (w, string)
+     WORD_DESC *w;
+     const char *string;
+{
+  register int i;
+  size_t slen;
+  DECLARE_MBSTATE;
+
+  i = 0;
+  slen = strlen (string);
+  while (i < slen)
+    {
+      switch (string[i])
+       {
+       case '$':
+         w->flags |= W_HASDOLLAR;
+         break;
+       case '\\':
+         break;        /* continue the loop */
+       case '\'':
+       case '`':
+       case '"':
+         w->flags |= W_QUOTED;
+         break;
+       }
+
+      ADVANCE_CHAR (string, slen, i);
+    }
+
+  return (w);
+}
+
+WORD_DESC *
+make_word (string)
+     const char *string;
+{
+  WORD_DESC *temp;
+
+  temp = make_bare_word (string);
+  return (make_word_flags (temp, string));
+}
+
+WORD_DESC *
+make_word_from_token (token)
+     int token;
+{
+  char tokenizer[2];
+
+  tokenizer[0] = token;
+  tokenizer[1] = '\0';
+
+  return (make_word (tokenizer));
+}
+
+WORD_LIST *
+make_word_list (word, wlink)
+     WORD_DESC *word;
+     WORD_LIST *wlink;
+{
+  WORD_LIST *temp;
+
+  ocache_alloc (wlcache, WORD_LIST, temp);
+
+  temp->word = word;
+  temp->next = wlink;
+  return (temp);
+}
+
+COMMAND *
+make_command (type, pointer)
+     enum command_type type;
+     SIMPLE_COM *pointer;
+{
+  COMMAND *temp;
+
+  temp = (COMMAND *)xmalloc (sizeof (COMMAND));
+  temp->type = type;
+  temp->value.Simple = pointer;
+  temp->value.Simple->flags = temp->flags = 0;
+  temp->redirects = (REDIRECT *)NULL;
+  return (temp);
+}
+
+COMMAND *
+command_connect (com1, com2, connector)
+     COMMAND *com1, *com2;
+     int connector;
+{
+  CONNECTION *temp;
+
+  temp = (CONNECTION *)xmalloc (sizeof (CONNECTION));
+  temp->connector = connector;
+  temp->first = com1;
+  temp->second = com2;
+  return (make_command (cm_connection, (SIMPLE_COM *)temp));
+}
+
+static COMMAND *
+make_for_or_select (type, name, map_list, action, lineno)
+     enum command_type type;
+     WORD_DESC *name;
+     WORD_LIST *map_list;
+     COMMAND *action;
+     int lineno;
+{
+  FOR_COM *temp;
+
+  temp = (FOR_COM *)xmalloc (sizeof (FOR_COM));
+  temp->flags = 0;
+  temp->name = name;
+  temp->line = lineno;
+  temp->map_list = map_list;
+  temp->action = action;
+  return (make_command (type, (SIMPLE_COM *)temp));
+}
+
+COMMAND *
+make_for_command (name, map_list, action, lineno)
+     WORD_DESC *name;
+     WORD_LIST *map_list;
+     COMMAND *action;
+     int lineno;
+{
+  return (make_for_or_select (cm_for, name, map_list, action, lineno));
+}
+
+COMMAND *
+make_select_command (name, map_list, action, lineno)
+     WORD_DESC *name;
+     WORD_LIST *map_list;
+     COMMAND *action;
+     int lineno;
+{
+#if defined (SELECT_COMMAND)
+  return (make_for_or_select (cm_select, name, map_list, action, lineno));
+#else
+  last_command_exit_value = 2;
+  return ((COMMAND *)NULL);
+#endif
+}
+
+#if defined (ARITH_FOR_COMMAND)
+static WORD_LIST *
+make_arith_for_expr (s)
+     char *s;
+{
+  WORD_LIST *result;
+  WORD_DESC *wd;
+
+  if (s == 0 || *s == '\0')
+    return ((WORD_LIST *)NULL);
+  wd = make_word (s);
+  wd->flags |= W_NOGLOB|W_NOSPLIT|W_QUOTED|W_DQUOTE;   /* no word splitting or globbing */
+  result = make_word_list (wd, (WORD_LIST *)NULL);
+  return result;
+}
+#endif
+
+/* Note that this function calls dispose_words on EXPRS, since it doesn't
+   use the word list directly.  We free it here rather than at the caller
+   because no other function in this file requires that the caller free
+   any arguments. */
+COMMAND *
+make_arith_for_command (exprs, action, lineno)
+     WORD_LIST *exprs;
+     COMMAND *action;
+     int lineno;
+{
+#if defined (ARITH_FOR_COMMAND)
+  ARITH_FOR_COM *temp;
+  WORD_LIST *init, *test, *step;
+  char *s, *t, *start;
+  int nsemi;
+
+  init = test = step = (WORD_LIST *)NULL;
+  /* Parse the string into the three component sub-expressions. */
+  start = t = s = exprs->word->word;
+  for (nsemi = 0; ;)
+    {
+      /* skip whitespace at the start of each sub-expression. */
+      while (whitespace (*s))
+       s++;
+      start = s;
+      /* skip to the semicolon or EOS */
+      while (*s && *s != ';')
+       s++;
+
+      t = (s > start) ? substring (start, 0, s - start) : (char *)NULL;
+
+      nsemi++;
+      switch (nsemi)
+       {
+       case 1:
+         init = make_arith_for_expr (t);
+         break;
+       case 2:
+         test = make_arith_for_expr (t);
+         break;
+       case 3:
+         step = make_arith_for_expr (t);
+         break;
+       }
+
+      FREE (t);
+      if (*s == '\0')
+       break;
+      s++;     /* skip over semicolon */
+    }
+
+  if (nsemi != 3)
+    {
+      if (nsemi < 3)
+       parser_error (lineno, _("syntax error: arithmetic expression required"));
+      else
+       parser_error (lineno, _("syntax error: `;' unexpected"));
+      parser_error (lineno, _("syntax error: `((%s))'"), exprs->word->word);
+      last_command_exit_value = 2;
+      return ((COMMAND *)NULL);
+    }
+
+  temp = (ARITH_FOR_COM *)xmalloc (sizeof (ARITH_FOR_COM));
+  temp->flags = 0;
+  temp->line = lineno;
+  temp->init = init ? init : make_arith_for_expr ("1");
+  temp->test = test ? test : make_arith_for_expr ("1");
+  temp->step = step ? step : make_arith_for_expr ("1");
+  temp->action = action;
+
+  dispose_words (exprs);
+  return (make_command (cm_arith_for, (SIMPLE_COM *)temp));
+#else
+  dispose_words (exprs);
+  last_command_exit_value = 2;
+  return ((COMMAND *)NULL);
+#endif /* ARITH_FOR_COMMAND */
+}
+
+COMMAND *
+make_group_command (command)
+     COMMAND *command;
+{
+  GROUP_COM *temp;
+
+  temp = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
+  temp->command = command;
+  return (make_command (cm_group, (SIMPLE_COM *)temp));
+}
+
+COMMAND *
+make_case_command (word, clauses, lineno)
+     WORD_DESC *word;
+     PATTERN_LIST *clauses;
+     int lineno;
+{
+  CASE_COM *temp;
+
+  temp = (CASE_COM *)xmalloc (sizeof (CASE_COM));
+  temp->flags = 0;
+  temp->line = lineno;
+  temp->word = word;
+  temp->clauses = REVERSE_LIST (clauses, PATTERN_LIST *);
+  return (make_command (cm_case, (SIMPLE_COM *)temp));
+}
+
+PATTERN_LIST *
+make_pattern_list (patterns, action)
+     WORD_LIST *patterns;
+     COMMAND *action;
+{
+  PATTERN_LIST *temp;
+
+  temp = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
+  temp->patterns = REVERSE_LIST (patterns, WORD_LIST *);
+  temp->action = action;
+  temp->next = NULL;
+  temp->flags = 0;
+  return (temp);
+}
+
+COMMAND *
+make_if_command (test, true_case, false_case)
+     COMMAND *test, *true_case, *false_case;
+{
+  IF_COM *temp;
+
+  temp = (IF_COM *)xmalloc (sizeof (IF_COM));
+  temp->flags = 0;
+  temp->test = test;
+  temp->true_case = true_case;
+  temp->false_case = false_case;
+  return (make_command (cm_if, (SIMPLE_COM *)temp));
+}
+
+static COMMAND *
+make_until_or_while (which, test, action)
+     enum command_type which;
+     COMMAND *test, *action;
+{
+  WHILE_COM *temp;
+
+  temp = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
+  temp->flags = 0;
+  temp->test = test;
+  temp->action = action;
+  return (make_command (which, (SIMPLE_COM *)temp));
+}
+
+COMMAND *
+make_while_command (test, action)
+     COMMAND *test, *action;
+{
+  return (make_until_or_while (cm_while, test, action));
+}
+
+COMMAND *
+make_until_command (test, action)
+     COMMAND *test, *action;
+{
+  return (make_until_or_while (cm_until, test, action));
+}
+
+COMMAND *
+make_arith_command (exp)
+     WORD_LIST *exp;
+{
+#if defined (DPAREN_ARITHMETIC)
+  COMMAND *command;
+  ARITH_COM *temp;
+
+  command = (COMMAND *)xmalloc (sizeof (COMMAND));
+  command->value.Arith = temp = (ARITH_COM *)xmalloc (sizeof (ARITH_COM));
+
+  temp->flags = 0;
+  temp->line = line_number;
+  temp->exp = exp;
+
+  command->type = cm_arith;
+  command->redirects = (REDIRECT *)NULL;
+  command->flags = 0;
+
+  return (command);
+#else
+  last_command_exit_value = 2;
+  return ((COMMAND *)NULL);
+#endif
+}
+
+#if defined (COND_COMMAND)
+struct cond_com *
+make_cond_node (type, op, left, right)
+     int type;
+     WORD_DESC *op;
+     struct cond_com *left, *right;
+{
+  COND_COM *temp;
+
+  temp = (COND_COM *)xmalloc (sizeof (COND_COM));
+  temp->flags = 0;
+  temp->line = line_number;
+  temp->type = type;
+  temp->op = op;
+  temp->left = left;
+  temp->right = right;
+
+  return (temp);
+}
+#endif
+
+COMMAND *
+make_cond_command (cond_node)
+     COND_COM *cond_node;
+{
+#if defined (COND_COMMAND)
+  COMMAND *command;
+
+  command = (COMMAND *)xmalloc (sizeof (COMMAND));
+  command->value.Cond = cond_node;
+
+  command->type = cm_cond;
+  command->redirects = (REDIRECT *)NULL;
+  command->flags = 0;
+  command->line = cond_node ? cond_node->line : 0;
+
+  return (command);
+#else
+  last_command_exit_value = 2;
+  return ((COMMAND *)NULL);
+#endif
+}
+
+COMMAND *
+make_bare_simple_command ()
+{
+  COMMAND *command;
+  SIMPLE_COM *temp;
+
+  command = (COMMAND *)xmalloc (sizeof (COMMAND));
+  command->value.Simple = temp = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
+
+  temp->flags = 0;
+  temp->line = line_number;
+  temp->words = (WORD_LIST *)NULL;
+  temp->redirects = (REDIRECT *)NULL;
+
+  command->type = cm_simple;
+  command->redirects = (REDIRECT *)NULL;
+  command->flags = 0;
+
+  return (command);
+}
+
+/* Return a command which is the connection of the word or redirection
+   in ELEMENT, and the command * or NULL in COMMAND. */
+COMMAND *
+make_simple_command (element, command)
+     ELEMENT element;
+     COMMAND *command;
+{
+  /* If we are starting from scratch, then make the initial command
+     structure.  Also note that we have to fill in all the slots, since
+     malloc doesn't return zeroed space. */
+  if (!command)
+    command = make_bare_simple_command ();
+
+  if (element.word)
+    command->value.Simple->words = make_word_list (element.word, command->value.Simple->words);
+  else if (element.redirect)
+    {
+      REDIRECT *r = element.redirect;
+      /* Due to the way <> is implemented, there may be more than a single
+        redirection in element.redirect.  We just follow the chain as far
+        as it goes, and hook onto the end. */
+      while (r->next)
+       r = r->next;
+      r->next = command->value.Simple->redirects;
+      command->value.Simple->redirects = element.redirect;
+    }
+  return (command);
+}
+
+/* Because we are Bourne compatible, we read the input for this
+   << or <<- redirection now, from wherever input is coming from.
+   We store the input read into a WORD_DESC.  Replace the text of
+   the redirectee.word with the new input text.  If <<- is on,
+   then remove leading TABS from each line. */
+void
+make_here_document (temp)
+     REDIRECT *temp;
+{
+  int kill_leading, redir_len;
+  char *redir_word, *document, *full_line;
+  int document_index, document_size, delim_unquoted;
+
+  if (temp->instruction != r_deblank_reading_until &&
+      temp->instruction != r_reading_until)
+    {
+      internal_error (_("make_here_document: bad instruction type %d"), temp->instruction);
+      return;
+    }
+
+  kill_leading = temp->instruction == r_deblank_reading_until;
+
+  document = (char *)NULL;
+  document_index = document_size = 0;
+
+  /* Quote removal is the only expansion performed on the delimiter
+     for here documents, making it an extremely special case. */
+  redir_word = string_quote_removal (temp->redirectee.filename->word, 0);
+
+  /* redirection_expand will return NULL if the expansion results in
+     multiple words or no words.  Check for that here, and just abort
+     this here document if it does. */
+  if (redir_word)
+    redir_len = strlen (redir_word);
+  else
+    {
+      temp->here_doc_eof = (char *)xmalloc (1);
+      temp->here_doc_eof[0] = '\0';
+      goto document_done;
+    }
+
+  free (temp->redirectee.filename->word);
+  temp->here_doc_eof = redir_word;
+
+  /* Read lines from wherever lines are coming from.
+     For each line read, if kill_leading, then kill the
+     leading tab characters.
+     If the line matches redir_word exactly, then we have
+     manufactured the document.  Otherwise, add the line to the
+     list of lines in the document. */
+
+  /* If the here-document delimiter was quoted, the lines should
+     be read verbatim from the input.  If it was not quoted, we
+     need to perform backslash-quoted newline removal. */
+  delim_unquoted = (temp->redirectee.filename->flags & W_QUOTED) == 0;
+  while (full_line = read_secondary_line (delim_unquoted))
+    {
+      register char *line;
+      int len;
+
+      line = full_line;
+      line_number++;
+
+      /* If set -v is in effect, echo the line read.  read_secondary_line/
+        read_a_line leaves the newline at the end, so don't print another. */
+      if (echo_input_at_read)
+       fprintf (stderr, "%s", line);
+
+      if (kill_leading && *line)
+       {
+         /* Hack:  To be compatible with some Bourne shells, we
+            check the word before stripping the whitespace.  This
+            is a hack, though. */
+         if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n')
+           goto document_done;
+
+         while (*line == '\t')
+           line++;
+       }
+
+      if (*line == 0)
+       continue;
+
+      if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n')
+       goto document_done;
+
+      len = strlen (line);
+      if (len + document_index >= document_size)
+       {
+         document_size = document_size ? 2 * (document_size + len) : len + 2;
+         document = (char *)xrealloc (document, document_size);
+       }
+
+      /* len is guaranteed to be > 0 because of the check for line
+        being an empty string before the call to strlen. */
+      FASTCOPY (line, document + document_index, len);
+      document_index += len;
+    }
+
+document_done:
+  if (document)
+    document[document_index] = '\0';
+  else
+    {
+      document = (char *)xmalloc (1);
+      document[0] = '\0';
+    }
+  temp->redirectee.filename->word = document;
+}
+
+/* Generate a REDIRECT from SOURCE, DEST, and INSTRUCTION.
+   INSTRUCTION is the instruction type, SOURCE is a file descriptor,
+   and DEST is a file descriptor or a WORD_DESC *. */
+REDIRECT *
+make_redirection (source, instruction, dest_and_filename)
+     int source;
+     enum r_instruction instruction;
+     REDIRECTEE dest_and_filename;
+{
+  REDIRECT *temp;
+  WORD_DESC *w;
+  int wlen;
+  intmax_t lfd;
+
+  temp = (REDIRECT *)xmalloc (sizeof (REDIRECT));
+
+  /* First do the common cases. */
+  temp->redirector = source;
+  temp->redirectee = dest_and_filename;
+  temp->instruction = instruction;
+  temp->flags = 0;
+  temp->next = (REDIRECT *)NULL;
+
+  switch (instruction)
+    {
+
+    case r_output_direction:           /* >foo */
+    case r_output_force:               /* >| foo */
+    case r_err_and_out:                        /* command &>filename */
+      temp->flags = O_TRUNC | O_WRONLY | O_CREAT;
+      break;
+
+    case r_appending_to:               /* >>foo */
+      temp->flags = O_APPEND | O_WRONLY | O_CREAT;
+      break;
+
+    case r_input_direction:            /* <foo */
+    case r_inputa_direction:           /* foo & makes this. */
+      temp->flags = O_RDONLY;
+      break;
+
+    case r_input_output:               /* <>foo */
+      temp->flags = O_RDWR | O_CREAT;
+      break;
+
+    case r_deblank_reading_until:      /* <<-foo */
+    case r_reading_until:              /* << foo */
+    case r_reading_string:             /* <<< foo */
+    case r_close_this:                 /* <&- */
+    case r_duplicating_input:          /* 1<&2 */
+    case r_duplicating_output:         /* 1>&2 */
+      break;
+
+    /* the parser doesn't pass these. */
+    case r_move_input:                 /* 1<&2- */
+    case r_move_output:                        /* 1>&2- */
+    case r_move_input_word:            /* 1<&$foo- */
+    case r_move_output_word:           /* 1>&$foo- */
+      break;
+
+    /* The way the lexer works we have to do this here. */
+    case r_duplicating_input_word:     /* 1<&$foo */
+    case r_duplicating_output_word:    /* 1>&$foo */
+      w = dest_and_filename.filename;
+      wlen = strlen (w->word) - 1;
+      if (w->word[wlen] == '-')                /* Yuck */
+        {
+          w->word[wlen] = '\0';
+         if (all_digits (w->word) && legal_number (w->word, &lfd) && lfd == (int)lfd)
+           {
+             dispose_word (w);
+             temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input : r_move_output;
+             temp->redirectee.dest = lfd;
+           }
+         else
+           temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input_word : r_move_output_word;
+        }
+          
+      break;
+
+    default:
+      programming_error (_("make_redirection: redirection instruction `%d' out of range"), instruction);
+      abort ();
+      break;
+    }
+  return (temp);
+}
+
+COMMAND *
+make_function_def (name, command, lineno, lstart)
+     WORD_DESC *name;
+     COMMAND *command;
+     int lineno, lstart;
+{
+  FUNCTION_DEF *temp;
+#if defined (ARRAY_VARS)
+  SHELL_VAR *bash_source_v;
+  ARRAY *bash_source_a;
+#endif
+
+  temp = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
+  temp->command = command;
+  temp->name = name;
+  temp->line = lineno;
+  temp->flags = 0;
+  command->line = lstart;
+
+  /* Information used primarily for debugging. */
+  temp->source_file = 0;
+#if defined (ARRAY_VARS)
+  GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
+  if (bash_source_a && array_num_elements (bash_source_a) > 0)
+    temp->source_file = array_reference (bash_source_a, 0);
+#endif
+#if defined (DEBUGGER)
+  bind_function_def (name->word, temp);
+#endif
+
+  temp->source_file = 0;
+  return (make_command (cm_function_def, (SIMPLE_COM *)temp));
+}
+
+COMMAND *
+make_subshell_command (command)
+     COMMAND *command;
+{
+  SUBSHELL_COM *temp;
+
+  temp = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM));
+  temp->command = command;
+  temp->flags = CMD_WANT_SUBSHELL;
+  return (make_command (cm_subshell, (SIMPLE_COM *)temp));
+}
+
+/* Reverse the word list and redirection list in the simple command
+   has just been parsed.  It seems simpler to do this here the one
+   time then by any other method that I can think of. */
+COMMAND *
+clean_simple_command (command)
+     COMMAND *command;
+{
+  if (command->type != cm_simple)
+    command_error ("clean_simple_command", CMDERR_BADTYPE, command->type, 0);
+  else
+    {
+      command->value.Simple->words =
+       REVERSE_LIST (command->value.Simple->words, WORD_LIST *);
+      command->value.Simple->redirects =
+       REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
+    }
+
+  return (command);
+}
+
+/* The Yacc grammar productions have a problem, in that they take a
+   list followed by an ampersand (`&') and do a simple command connection,
+   making the entire list effectively asynchronous, instead of just
+   the last command.  This means that when the list is executed, all
+   the commands have stdin set to /dev/null when job control is not
+   active, instead of just the last.  This is wrong, and needs fixing
+   up.  This function takes the `&' and applies it to the last command
+   in the list.  This is done only for lists connected by `;'; it makes
+   `;' bind `tighter' than `&'. */
+COMMAND *
+connect_async_list (command, command2, connector)
+     COMMAND *command, *command2;
+     int connector;
+{
+  COMMAND *t, *t1, *t2;
+
+  t1 = command;
+  t = command->value.Connection->second;
+
+  if (!t || (command->flags & CMD_WANT_SUBSHELL) ||
+      command->value.Connection->connector != ';')
+    {
+      t = command_connect (command, command2, connector);
+      return t;
+    }
+
+  /* This is just defensive programming.  The Yacc precedence rules
+     will generally hand this function a command where t points directly
+     to the command we want (e.g. given a ; b ; c ; d &, t1 will point
+     to the `a ; b ; c' list and t will be the `d').  We only want to do
+     this if the list is not being executed as a unit in the background
+     with `( ... )', so we have to check for CMD_WANT_SUBSHELL.  That's
+     the only way to tell. */
+  while (((t->flags & CMD_WANT_SUBSHELL) == 0) && t->type == cm_connection &&
+        t->value.Connection->connector == ';')
+    {
+      t1 = t;
+      t = t->value.Connection->second;
+    }
+  /* Now we have t pointing to the last command in the list, and
+     t1->value.Connection->second == t. */
+  t2 = command_connect (t, command2, connector);
+  t1->value.Connection->second = t2;
+  return command;
+}
index d1dfd1a78be7ed92def9cbac50c01de36c1d9cf1..0386a78a32348a78674d3278578d2d891177e80a 100644 (file)
@@ -1039,13 +1039,14 @@ print_function_def (func)
 /* Return the string representation of the named function.
    NAME is the name of the function.
    COMMAND is the function body.  It should be a GROUP_COM.
-   MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
+   flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
+   flags&FUNC_EXTERNAL means convert from internal to external form
   */
 char *
-named_function_string (name, command, multi_line)
+named_function_string (name, command, flags)
      char *name;
      COMMAND *command;
-     int multi_line;
+     int flags;
 {
   char *result;
   int old_indent, old_amount;
@@ -1061,7 +1062,7 @@ named_function_string (name, command, multi_line)
 
   cprintf ("() ");
 
-  if (multi_line == 0)
+  if ((flags & FUNC_MULTILINE) == 0)
     {
       indentation = 1;
       indentation_amount = 0;
@@ -1074,7 +1075,7 @@ named_function_string (name, command, multi_line)
 
   inside_function_def++;
 
-  cprintf (multi_line ? "{ \n" : "{ ");
+  cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
 
   cmdcopy = copy_command (command);
   /* Take any redirections specified in the function definition (which should
@@ -1104,7 +1105,7 @@ named_function_string (name, command, multi_line)
 
   result = the_printed_command;
 
-  if (!multi_line)
+  if ((flags & FUNC_MULTILINE) == 0)
     {
 #if 0
       register int i;
@@ -1122,6 +1123,9 @@ named_function_string (name, command, multi_line)
 
   dispose_command (cmdcopy);
 
+  if (flags & FUNC_EXTERNAL)
+    result = remove_quoted_escapes (result);
+
   return (result);
 }
 
index e68619fed252b915eefd66199bcee2c7a835927a..fe76e0b079af53c2de24e301327422841a4824d2 100644 (file)
@@ -106,8 +106,6 @@ int command_string_index = 0;
 
 /* Non-zero means the stuff being printed is inside of a function def. */
 static int inside_function_def;
-
-static int inside_pipeline;
 static int skip_this_indent;
 static int was_heredoc;
 
@@ -135,7 +133,7 @@ char *
 make_command_string (command)
      COMMAND *command;
 {
-  command_string_index = was_heredoc = inside_pipeline = 0;
+  command_string_index = was_heredoc = 0;
   make_command_string_internal (command);
   return (the_printed_command);
 }
@@ -217,11 +215,7 @@ make_command_string_internal (command)
        case cm_connection:
 
          skip_this_indent++;
-         if (command->value.Connection->connector == '|')
-           inside_pipeline = 1;
          make_command_string_internal (command->value.Connection->first);
-         if (command->value.Connection->connector == '|')
-           inside_pipeline = 0;
 
          switch (command->value.Connection->connector)
            {
@@ -229,10 +223,7 @@ make_command_string_internal (command)
            case '|':
              {
                char c = command->value.Connection->connector;
-               if (c == '&' || was_heredoc == 0)
-                 cprintf (" %c", c);
-               else
-                 was_heredoc = 0;
+               cprintf (" %c", c);
                if (c != '&' || command->value.Connection->second)
                  {
                    cprintf (" ");
@@ -860,10 +851,6 @@ print_redirection_list (redirects)
      print the here documents. */
   if (heredocs)
     {
-if (inside_pipeline)
-{
-itrace("print_redirection_list: here documents inside pipeline");
-}
       cprintf (" "); 
       for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
        {
@@ -881,7 +868,6 @@ print_redirection (redirect)
 {
   int kill_leading, redirector, redir_fd;
   WORD_DESC *redirectee;
-  char *x;
 
   kill_leading = 0;
   redirectee = redirect->redirectee.filename;
@@ -919,16 +905,17 @@ print_redirection (redirect)
       if (redirector != 0)
        cprintf ("%d", redirector);
       /* If the here document delimiter is quoted, single-quote it. */
-      x = (redirect->redirectee.filename->flags & W_QUOTED)
-               ? sh_single_quote (redirect->here_doc_eof)
-               : redirect->here_doc_eof;
-      cprintf ("<<%s%s", kill_leading? "-" : "", x);
-      if (x != redirect->here_doc_eof)
-       free (x);
-if (inside_pipeline)
-  cprintf (" |");
-      cprintf ("\n");
-      cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
+      if (redirect->redirectee.filename->flags & W_QUOTED)
+       {
+         char *x;
+         x = sh_single_quote (redirect->here_doc_eof);
+         cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
+         free (x);
+       }
+      else
+       cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
+      cprintf ("%s%s",
+              redirect->redirectee.filename->word, redirect->here_doc_eof);
       break;
 
     case r_reading_string:
@@ -1004,7 +991,6 @@ reset_locals ()
 {
   inside_function_def = 0;
   indentation = 0;
-  inside_pipeline = 0;
 }
 
 static void
@@ -1024,7 +1010,7 @@ print_function_def (func)
   inside_function_def++;
   indentation += indentation_amount;
 
-  cmdcopy = copy_command (func->command);      /* possible mem leak on unwind-protect */
+  cmdcopy = copy_command (func->command);
   if (cmdcopy->type == cm_group)
     {
       func_redirects = cmdcopy->redirects;
@@ -1053,13 +1039,14 @@ print_function_def (func)
 /* Return the string representation of the named function.
    NAME is the name of the function.
    COMMAND is the function body.  It should be a GROUP_COM.
-   MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
+   flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
+   flags&FUNC_EXTERNAL means convert from internal to external form
   */
 char *
-named_function_string (name, command, multi_line)
+named_function_string (name, command, flags)
      char *name;
      COMMAND *command;
-     int multi_line;
+     int flags;
 {
   char *result;
   int old_indent, old_amount;
@@ -1069,14 +1056,13 @@ named_function_string (name, command, multi_line)
   old_indent = indentation;
   old_amount = indentation_amount;
   command_string_index = was_heredoc = 0;
-  inside_pipeline = 0;
 
   if (name && *name)
     cprintf ("%s ", name);
 
   cprintf ("() ");
 
-  if (multi_line == 0)
+  if ((flags & FUNC_MULTILINE) == 0)
     {
       indentation = 1;
       indentation_amount = 0;
@@ -1089,7 +1075,7 @@ named_function_string (name, command, multi_line)
 
   inside_function_def++;
 
-  cprintf (multi_line ? "{ \n" : "{ ");
+  cprintf ((flags & FUNC_MULTILINE) ? "{ \n" : "{ ");
 
   cmdcopy = copy_command (command);
   /* Take any redirections specified in the function definition (which should
@@ -1119,7 +1105,7 @@ named_function_string (name, command, multi_line)
 
   result = the_printed_command;
 
-  if (!multi_line)
+  if ((flags & FUNC_MULTILINE) == 0)
     {
 #if 0
       register int i;
@@ -1137,6 +1123,9 @@ named_function_string (name, command, multi_line)
 
   dispose_command (cmdcopy);
 
+  if (flags & FUNC_EXTERNAL)
+    remove_quoted_escapes (result);
+
   return (result);
 }
 
diff --git a/redir.c b/redir.c
index 68565dd6e92979109bf22de517f13106e769fc75..283b07db74306afde5283d9bb84696a49f345166 100644 (file)
--- a/redir.c
+++ b/redir.c
@@ -1,6 +1,6 @@
 /* redir.c -- Functions to perform input and output redirection. */
 
-/* Copyright (C) 1997-2005 Free Software Foundation, Inc.
+/* Copyright (C) 1997-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -54,6 +54,8 @@ extern int errno;
 #  include "input.h"
 #endif
 
+#define SHELL_FD_BASE  10
+
 int expanding_redir;
 
 extern int posixly_correct;
@@ -481,7 +483,7 @@ redir_special_open (spec, filename, flags, mode, ri)
       if (all_digits (filename+8) && legal_number (filename+8, &lfd) && lfd == (int)lfd)
        {
          fd = lfd;
-         fd = fcntl (fd, F_DUPFD, 10);
+         fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
        }
       else
        fd = AMBIGUOUS_REDIRECT;
@@ -490,13 +492,13 @@ redir_special_open (spec, filename, flags, mode, ri)
 
 #if !defined (HAVE_DEV_STDIN)
     case RF_DEVSTDIN:
-      fd = fcntl (0, F_DUPFD, 10);
+      fd = fcntl (0, F_DUPFD, SHELL_FD_BASE);
       break;
     case RF_DEVSTDOUT:
-      fd = fcntl (1, F_DUPFD, 10);
+      fd = fcntl (1, F_DUPFD, SHELL_FD_BASE);
       break;
     case RF_DEVSTDERR:
-      fd = fcntl (2, F_DUPFD, 10);
+      fd = fcntl (2, F_DUPFD, SHELL_FD_BASE);
       break;
 #endif
 
@@ -888,7 +890,6 @@ do_redirection_internal (redirect, flags)
              else
                add_undo_close_redirect (redirector);
            }
-
 #if defined (BUFFERED_INPUT)
          check_bash_input (redirector);
 #endif
@@ -949,8 +950,6 @@ do_redirection_internal (redirect, flags)
   return (0);
 }
 
-#define SHELL_FD_BASE  10
-
 /* Remember the file descriptor associated with the slot FD,
    on REDIRECTION_UNDO_LIST.  Note that the list will be reversed
    before it is executed.  Any redirections that need to be undone
@@ -996,17 +995,19 @@ add_undo_redirect (fd, ri)
 
   /* experimental:  if we're saving a redirection to undo for a file descriptor
      above SHELL_FD_BASE, add a redirection to be undone if the exec builtin
-     causes redirections to be discarded. */
-  if (fd >= SHELL_FD_BASE && ri != r_close_this)
+     causes redirections to be discarded.  There needs to be a difference
+     between fds that are used to save other fds and then are the target of
+     user redirctions and fds that are just the target of user redirections.
+     We use the close-on-exec flag to tell the difference; fds > SHELL_FD_BASE
+     that have the close-on-exec flag set are assumed to be fds used internally
+     to save others. */
+  if (fd >= SHELL_FD_BASE && ri != r_close_this && clexec_flag)
     {
       rd.dest = new_fd;
       new_redirect = make_redirection (fd, r_duplicating_output, rd);
-#if 0
-      closer = copy_redirects (new_redirect);
-      add_exec_redirect (closer);
-#else
+      new_redirect->flags |= RX_INTERNAL;
+
       add_exec_redirect (new_redirect);
-#endif     
     }
 
   /* File descriptors used only for saving others should always be
diff --git a/shell.c b/shell.c
index c643f0c1b97fa3adbc559c31fff48b771c1fde5f..4f440428df567c5354e6c7e635f58be3e03fe485 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -305,6 +305,7 @@ static int uidget __P((void));
 
 static void init_interactive __P((void));
 static void init_noninteractive __P((void));
+static void init_interactive_script __P((void));
 
 static void set_shell_name __P((char *));
 static void shell_initialize __P((void));
@@ -1480,7 +1481,7 @@ open_shell_script (script_name)
     /* But if a script is called with something like `bash -i scriptname',
        we need to do a non-interactive setup here, since we didn't do it
        before. */
-    init_noninteractive ();
+    init_interactive_script ();
 
   free (filename);
   return (fd);
@@ -1573,8 +1574,8 @@ set_shell_name (argv0)
 static void
 init_interactive ()
 {
-  interactive_shell = startup_state = interactive = 1;
-  expand_aliases = 1;
+  expand_aliases = interactive_shell = startup_state = 1;
+  interactive = 1;
 }
 
 static void
@@ -1591,6 +1592,13 @@ init_noninteractive ()
 #endif /* JOB_CONTROL */
 }
 
+static void
+init_interactive_script ()
+{
+  init_noninteractive ();
+  expand_aliases = interactive_shell = startup_state = 1;
+}
+
 void
 get_current_user_info ()
 {
diff --git a/subst.c b/subst.c
index 216cf57266e18d0ea7d6a48c9e48db4325002388..955eba64140656e5195ec5a6fbad94a362d2a2c8 100644 (file)
--- a/subst.c
+++ b/subst.c
@@ -211,7 +211,6 @@ static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
 static char *dequote_escapes __P((char *));
 static char *make_quoted_char __P((int));
 static WORD_LIST *quote_list __P((WORD_LIST *));
-static char *remove_quoted_escapes __P((char *));
 static char *remove_quoted_nulls __P((char *));
 
 static int unquoted_substring __P((char *, char *));
@@ -3201,7 +3200,7 @@ dequote_list (list)
 
 /* Remove CTLESC protecting a CTLESC or CTLNUL in place.  Return the passed
    string. */
-static char *
+char *
 remove_quoted_escapes (string)
      char *string;
 {
index 3c444b5f21ac5a431502b07bca748d9be72f8469..b18d56db7e5a59c4ad7b41754f35baf01337034a 100644 (file)
--- a/subst.c~
+++ b/subst.c~
@@ -136,6 +136,8 @@ size_t ifs_firstc_len;
 unsigned char ifs_firstc;
 #endif
 
+int assigning_in_environment;
+
 /* Extern functions and variables from different files. */
 extern int last_command_exit_value, last_command_exit_signal;
 extern int subshell_environment;
@@ -209,7 +211,7 @@ static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
 static char *dequote_escapes __P((char *));
 static char *make_quoted_char __P((int));
 static WORD_LIST *quote_list __P((WORD_LIST *));
-static char *remove_quoted_escapes __P((char *));
+/*static*/ char *remove_quoted_escapes __P((char *));
 static char *remove_quoted_nulls __P((char *));
 
 static int unquoted_substring __P((char *, char *));
@@ -3199,7 +3201,7 @@ dequote_list (list)
 
 /* Remove CTLESC protecting a CTLESC or CTLNUL in place.  Return the passed
    string. */
-static char *
+/*static*/ char *
 remove_quoted_escapes (string)
      char *string;
 {
diff --git a/subst.h b/subst.h
index 0af5024030ffe9cabc62869f8892b96bbf654e92..181f10aa2fadde38ea2bfcdf4b56c23b9466dcec 100644 (file)
--- a/subst.h
+++ b/subst.h
@@ -1,6 +1,6 @@
 /* subst.h -- Names of externally visible functions in subst.c. */
 
-/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2007 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -181,6 +181,9 @@ extern char *quote_string __P((char *));
    in a string. */
 extern char *quote_escapes __P((char *));
 
+/* And remove such quoted special characters. */
+extern char *remove_quoted_escapes __P((char *));
+
 /* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
    backslash quoting rules for within double quotes. */
 extern char *string_quote_removal __P((char *, int));
diff --git a/subst.h~ b/subst.h~
new file mode 100644 (file)
index 0000000..a2aff01
--- /dev/null
+++ b/subst.h~
@@ -0,0 +1,270 @@
+/* subst.h -- Names of externally visible functions in subst.c. */
+
+/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
+
+   This file is part of GNU Bash, the Bourne Again SHell.
+
+   Bash is free software; you can redistribute it and/or modify it under
+   the terms of the GNU General Public License as published by the Free
+   Software Foundation; either version 2, or (at your option) any later
+   version.
+
+   Bash is distributed in the hope that it will be useful, but WITHOUT ANY
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or
+   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+   for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with Bash; see the file COPYING.  If not, write to the Free Software
+   Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
+
+#if !defined (_SUBST_H_)
+#define _SUBST_H_
+
+#include "stdc.h"
+
+/* Constants which specify how to handle backslashes and quoting in
+   expand_word_internal ().  Q_DOUBLE_QUOTES means to use the function
+   slashify_in_quotes () to decide whether the backslash should be
+   retained.  Q_HERE_DOCUMENT means slashify_in_here_document () to
+   decide whether to retain the backslash.  Q_KEEP_BACKSLASH means
+   to unconditionally retain the backslash.  Q_PATQUOTE means that we're
+   expanding a pattern ${var%#[#%]pattern} in an expansion surrounded
+   by double quotes. */
+#define Q_DOUBLE_QUOTES  0x01
+#define Q_HERE_DOCUMENT  0x02
+#define Q_KEEP_BACKSLASH 0x04
+#define Q_PATQUOTE      0x08
+#define Q_QUOTED        0x10
+#define Q_ADDEDQUOTES   0x20
+#define Q_QUOTEDNULL    0x40
+
+/* Flag values controlling how assignment statements are treated. */
+#define ASS_APPEND     0x01
+#define ASS_MKLOCAL    0x02
+
+/* Remove backslashes which are quoting backquotes from STRING.  Modifies
+   STRING, and returns a pointer to it. */
+extern char * de_backslash __P((char *));
+
+/* Replace instances of \! in a string with !. */
+extern void unquote_bang __P((char *));
+
+/* Extract the $( construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "$(".
+   Make (SINDEX) get the position just after the matching ")". */
+extern char *extract_command_subst __P((char *, int *));
+
+/* Extract the $[ construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "$[".
+   Make (SINDEX) get the position just after the matching "]". */
+extern char *extract_arithmetic_subst __P((char *, int *));
+
+#if defined (PROCESS_SUBSTITUTION)
+/* Extract the <( or >( construct in STRING, and return a new string.
+   Start extracting at (SINDEX) as if we had just seen "<(".
+   Make (SINDEX) get the position just after the matching ")". */
+extern char *extract_process_subst __P((char *, char *, int *));
+#endif /* PROCESS_SUBSTITUTION */
+
+/* Extract the name of the variable to bind to from the assignment string. */
+extern char *assignment_name __P((char *));
+
+/* Return a single string of all the words present in LIST, separating
+   each word with SEP. */
+extern char *string_list_internal __P((WORD_LIST *, char *));
+
+/* Return a single string of all the words present in LIST, separating
+   each word with a space. */
+extern char *string_list __P((WORD_LIST *));
+
+/* Turn $* into a single string, obeying POSIX rules. */
+extern char *string_list_dollar_star __P((WORD_LIST *));
+
+/* Expand $@ into a single string, obeying POSIX rules. */
+extern char *string_list_dollar_at __P((WORD_LIST *, int));
+
+/* Perform quoted null character removal on each element of LIST.
+   This modifies LIST. */
+extern void word_list_remove_quoted_nulls __P((WORD_LIST *));
+
+/* This performs word splitting and quoted null character removal on
+   STRING. */
+extern WORD_LIST *list_string __P((char *, char *, int));
+
+extern char *get_word_from_string __P((char **, char *, char **));
+extern char *strip_trailing_ifs_whitespace __P((char *, char *, int));
+
+/* Given STRING, an assignment string, get the value of the right side
+   of the `=', and bind it to the left side.  If EXPAND is true, then
+   perform tilde expansion, parameter expansion, command substitution,
+   and arithmetic expansion on the right-hand side.  Do not perform word
+   splitting on the result of expansion. */
+extern int do_assignment __P((char *));
+extern int do_assignment_no_expand __P((char *));
+extern int do_word_assignment __P((WORD_DESC *));
+
+/* Append SOURCE to TARGET at INDEX.  SIZE is the current amount
+   of space allocated to TARGET.  SOURCE can be NULL, in which
+   case nothing happens.  Gets rid of SOURCE by free ()ing it.
+   Returns TARGET in case the location has changed. */
+extern char *sub_append_string __P((char *, char *, int *, int *));
+
+/* Append the textual representation of NUMBER to TARGET.
+   INDEX and SIZE are as in SUB_APPEND_STRING. */
+extern char *sub_append_number __P((intmax_t, char *, int *, int *));
+
+/* Return the word list that corresponds to `$*'. */
+extern WORD_LIST *list_rest_of_args __P((void));
+
+/* Make a single large string out of the dollar digit variables,
+   and the rest_of_args.  If DOLLAR_STAR is 1, then obey the special
+   case of "$*" with respect to IFS. */
+extern char *string_rest_of_args __P((int));
+
+extern int number_of_args __P((void));
+
+/* Expand STRING by performing parameter expansion, command substitution,
+   and arithmetic expansion.  Dequote the resulting WORD_LIST before
+   returning it, but do not perform word splitting.  The call to
+   remove_quoted_nulls () is made here because word splitting normally
+   takes care of quote removal. */
+extern WORD_LIST *expand_string_unsplit __P((char *, int));
+
+/* Expand the rhs of an assignment statement. */
+extern WORD_LIST *expand_string_assignment __P((char *, int));
+
+/* Expand a prompt string. */
+extern WORD_LIST *expand_prompt_string __P((char *, int));
+
+/* Expand STRING just as if you were expanding a word.  This also returns
+   a list of words.  Note that filename globbing is *NOT* done for word
+   or string expansion, just when the shell is expanding a command.  This
+   does parameter expansion, command substitution, arithmetic expansion,
+   and word splitting.  Dequote the resultant WORD_LIST before returning. */
+extern WORD_LIST *expand_string __P((char *, int));
+
+/* Convenience functions that expand strings to strings, taking care of
+   converting the WORD_LIST * returned by the expand_string* functions
+   to a string and deallocating the WORD_LIST *. */
+extern char *expand_string_to_string __P((char *, int));
+extern char *expand_string_unsplit_to_string __P((char *, int));
+extern char *expand_assignment_string_to_string __P((char *, int));
+
+/* Expand an arithmetic expression string */
+extern char *expand_arith_string __P((char *, int));
+
+/* De-quote quoted characters in STRING. */
+extern char *dequote_string __P((char *));
+
+/* De-quote quoted characters in each word in LIST. */
+extern WORD_LIST *dequote_list __P((WORD_LIST *));
+
+/* Expand WORD, performing word splitting on the result.  This does
+   parameter expansion, command substitution, arithmetic expansion,
+   word splitting, and quote removal. */
+extern WORD_LIST *expand_word __P((WORD_DESC *, int));
+
+/* Expand WORD, but do not perform word splitting on the result.  This
+   does parameter expansion, command substitution, arithmetic expansion,
+   and quote removal. */
+extern WORD_LIST *expand_word_unsplit __P((WORD_DESC *, int));
+extern WORD_LIST *expand_word_leave_quoted __P((WORD_DESC *, int));
+
+/* Return the value of a positional parameter.  This handles values > 10. */
+extern char *get_dollar_var_value __P((intmax_t));
+
+/* Quote a string to protect it from word splitting. */
+extern char *quote_string __P((char *));
+
+/* Quote escape characters (characters special to interals of expansion)
+   in a string. */
+extern char *quote_escapes __P((char *));
+
+/* And remove such quoted special characters. */
+extern char *remove_quoted_escapes __P((char *));
+
+/* Perform quote removal on STRING.  If QUOTED > 0, assume we are obeying the
+   backslash quoting rules for within double quotes. */
+extern char *string_quote_removal __P((char *, int));
+
+/* Perform quote removal on word WORD.  This allocates and returns a new
+   WORD_DESC *. */
+extern WORD_DESC *word_quote_removal __P((WORD_DESC *, int));
+
+/* Perform quote removal on all words in LIST.  If QUOTED is non-zero,
+   the members of the list are treated as if they are surrounded by
+   double quotes.  Return a new list, or NULL if LIST is NULL. */
+extern WORD_LIST *word_list_quote_removal __P((WORD_LIST *, int));
+
+/* Called when IFS is changed to maintain some private variables. */
+extern void setifs __P((SHELL_VAR *));
+
+/* Return the value of $IFS, or " \t\n" if IFS is unset. */
+extern char *getifs __P((void));
+
+/* This splits a single word into a WORD LIST on $IFS, but only if the word
+   is not quoted.  list_string () performs quote removal for us, even if we
+   don't do any splitting. */
+extern WORD_LIST *word_split __P((WORD_DESC *, char *));
+
+/* Take the list of words in LIST and do the various substitutions.  Return
+   a new list of words which is the expanded list, and without things like
+   variable assignments. */
+extern WORD_LIST *expand_words __P((WORD_LIST *));
+
+/* Same as expand_words (), but doesn't hack variable or environment
+   variables. */
+extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *));
+
+/* Perform the `normal shell expansions' on a WORD_LIST.  These are
+   brace expansion, tilde expansion, parameter and variable substitution,
+   command substitution, arithmetic expansion, and word splitting. */
+extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *));
+
+extern WORD_DESC *command_substitute __P((char *, int));
+extern char *pat_subst __P((char *, char *, char *, int));
+
+extern int fifos_pending __P((void));
+extern void unlink_fifo_list __P((void));
+
+extern WORD_LIST *list_string_with_quotes __P((char *));
+
+#if defined (ARRAY_VARS)
+extern char *extract_array_assignment_list __P((char *, int *));
+#endif
+
+#if defined (COND_COMMAND)
+extern char *remove_backslashes __P((char *));
+extern char *cond_expand_word __P((WORD_DESC *, int));
+#endif
+
+#if defined (READLINE)
+extern int char_is_quoted __P((char *, int));
+extern int unclosed_pair __P((char *, int, char *));
+extern int skip_to_delim __P((char *, int, char *));
+extern WORD_LIST *split_at_delims __P((char *, int, char *, int, int *, int *));
+#endif
+
+/* Variables used to keep track of the characters in IFS. */
+extern SHELL_VAR *ifs_var;
+extern char *ifs_value;
+extern unsigned char ifs_cmap[];
+
+#if defined (HANDLE_MULTIBYTE)
+extern unsigned char ifs_firstc[];
+extern size_t ifs_firstc_len;
+#else
+extern unsigned char ifs_firstc;
+#endif
+
+/* Evaluates to 1 if C is a character in $IFS. */
+#define isifs(c)       (ifs_cmap[(unsigned char)(c)] != 0)
+
+/* How to determine the quoted state of the character C. */
+#define QUOTED_CHAR(c)  ((c) == CTLESC)
+
+/* Is the first character of STRING a quoted NULL character? */
+#define QUOTED_NULL(string) ((string)[0] == CTLNUL && (string)[1] == '\0')
+
+#endif /* !_SUBST_H_ */
index d65b89df6a2480e15e663bef9afa0ce937ae6105..0759129583d812350d36e3c6b32e7c510153ca0c 100644 (file)
@@ -51,4 +51,6 @@ this is ohio-state
 0
 1
 testb
+bash: no job control in this shell
+expand_aliases         on
 after
diff --git a/tests/exec.right~ b/tests/exec.right~
new file mode 100644 (file)
index 0000000..6e74b22
--- /dev/null
@@ -0,0 +1,57 @@
+before exec1.sub: one two three
+calling exec1.sub
+aa bb cc dd ee
+after exec1.sub with args: 0
+
+after exec1.sub without args: 0
+./execscript: line 20: notthere: command not found
+127
+/tmp/bash: notthere: No such file or directory
+127
+/bin/sh: /bin/sh: cannot execute binary file
+126
+./execscript: line 39: /: is a directory
+126
+/: /: is a directory
+126
+./execscript: line 46: .: /: is a directory
+1
+127
+0
+this is bashenv
+./exec3.sub: line 3: /tmp/bash-notthere: No such file or directory
+./exec3.sub: line 3: exec: /tmp/bash-notthere: cannot execute: No such file or directory
+126
+./execscript: line 68: notthere: No such file or directory
+127
+./execscript: line 71: notthere: No such file or directory
+127
+./execscript: line 74: notthere: No such file or directory
+127
+this is sh
+this is sh
+unset
+ok
+5
+./exec5.sub: line 4: exec: bash-notthere: not found
+127
+this is ohio-state
+0
+1
+1
+0
+42
+42
+0
+1
+1
+0
+0
+1
+0
+1
+testb
+bash: cannot set terminal pgrp to 15044: Inappropriate ioctl for device
+bash: no job control in this shell
+expand_aliases         on
+after
diff --git a/tests/exec8.sub b/tests/exec8.sub
new file mode 100644 (file)
index 0000000..014726d
--- /dev/null
@@ -0,0 +1 @@
+shopt expand_aliases
index 09a4ba5f5bbd8f0ae8f7ecce16aabe308eb59f3b..5e11e235d8d521e544945088807290f23d28b1b3 100644 (file)
@@ -105,6 +105,8 @@ ${THIS_SH} ./exec6.sub
 # checks for properly deciding what constitutes an executable file
 ${THIS_SH} ./exec7.sub
 
+${THIS_SH} -i ./exec8.sub
+
 true | `echo true` &
 
 echo after
index d7fbe46417b87db6195b4ec1170a3e3c08fe6561..faafad2b1eb6e61df274374a900cebb93bedbbe0 100644 (file)
@@ -156,3 +156,9 @@ argv[2] = <^?>
 argv[1] = <^A^?>
 argv[1] = <^A^?^A^?>
 argv[1] = <^A^A^?>
+0.net
+0.net0
+
+0.net
+0.net
+0.net
index ed23d0cbb2dc72b7ea17b46c2b5f0d705a3f2200..42fbf72445b38a15212899c1860e26164e9a1a0d 100644 (file)
@@ -380,3 +380,5 @@ echo ${a//\\?/ }
 echo ${a//\?/ }
 
 ${THIS_SH} ./exp1.sub
+
+${THIS_SH} ./exp2.sub
index 884b5a699ef62a68dda87d24f36cf8c3ace2a67c..ed23d0cbb2dc72b7ea17b46c2b5f0d705a3f2200 100644 (file)
@@ -378,3 +378,5 @@ a="a?b?c"
 echo ${a//\\?/ }
 
 echo ${a//\?/ }
+
+${THIS_SH} ./exp1.sub
diff --git a/tests/exp2.sub b/tests/exp2.sub
new file mode 100644 (file)
index 0000000..a70179e
--- /dev/null
@@ -0,0 +1,12 @@
+K=dvb0.net A=${K#dvb} eval echo \$A
+unset K A
+x=${K:=dvb0.net0} A=${K#dvb} eval echo \$A
+
+unset K A
+K=dvb0.net A=${K#dvb} echo "$A"
+unset K A
+K=dvb0.net A=${K#dvb} ; echo "$A"
+unset K A
+K=dvb0.net A=${K#dvb} eval echo '$A'
+unset K A
+K=dvb0.net A=${K#dvb} eval echo \$A
diff --git a/tests/infile b/tests/infile
new file mode 100644 (file)
index 0000000..94ebaf9
--- /dev/null
@@ -0,0 +1,4 @@
+1
+2
+3
+4
index 21a3b4fd2c709bf453c7dbad399331eae5e44796..449d5b09517fa1a8c0b7b91bf79d37e32a5ef417 100644 (file)
@@ -8,3 +8,6 @@ ok 2
 aéb
 0000000   141 303 251 142                                                
 0000004
+-абвгдежзиклмноп - 16
+-абвгдежзиклмноп- 15
+-абвгд- 5
index d4c2373eb168b11ad6fa914a49ce0d0f020eece3..cd919dfb5530c756522a342e1fcedea83e5e6f56 100644 (file)
@@ -36,3 +36,6 @@ set a b
 
 printf '%s\n' "$*"
 printf '%s' "$*" | od -b
+
+# display differences make this problematic
+${THIS_SH} ./intl1.sub
diff --git a/tests/intl.tests~ b/tests/intl.tests~
new file mode 100644 (file)
index 0000000..3f5ea9a
--- /dev/null
@@ -0,0 +1,40 @@
+export LC_ALL=en_US.UTF-8
+
+a=$'\303\251'
+
+echo "$a"
+
+echo ${#a}
+
+b=$'A\303\251B'
+
+echo "$b"
+
+echo ${b: -1}
+
+c=AeB
+
+echo ${c: -1}
+
+unset a
+a=$(printf '%b' 'A\303\251B')
+IFS=$(printf '%b' '\303\251')
+
+case "$a" in
+"A${IFS}B")    echo ok 1 ;;
+*)             echo bad 1 ;;
+esac
+
+set $a
+
+case $1 in
+A)             echo ok 2 ;;
+*)             echo bad 2 ;;
+esac
+
+set a b
+
+printf '%s\n' "$*"
+printf '%s' "$*" | od -b
+
+${THIS_SH} ./intl1.sub
diff --git a/tests/intl1.sub b/tests/intl1.sub
new file mode 100644 (file)
index 0000000..a03648f
--- /dev/null
@@ -0,0 +1,11 @@
+LC_ALL=en_US.UTF-8
+LANG=en_US.UTF-8
+
+var='абвгдежзиклмноп '
+echo -"$var"- ${#var}
+
+read foo <<< "$var"
+echo -"$foo"- ${#foo}
+
+read -n 5 foo <<< "$var"
+echo -"$foo"- ${#foo}
index 5a8749ef162ac464abd76bb60fe75e678ddd1465..a6bb04d643ca9a1d2ab88cd5dd07e98a25376ad2 100644 (file)
Binary files a/tests/printf.right and b/tests/printf.right differ
index 7cfeebd02dc9e878bd27675243e9402653938341..80966d71f48840e7ceef8697df7d0d5d97eb2653 100644 (file)
@@ -300,3 +300,10 @@ printf "%s\n"
 echo b
 printf "%b\n" ''
 printf "%b\n"
+
+# bug in bash versions up to and including bash-3.2
+v=yyy
+printf -v var "%s" '/current/working/directory/*.@(m3|i3|ig|mg)'
+shopt -s nullglob extglob
+echo "x$(printf "%b" @(hugo))x"
+printf -v var "%b" @(hugo); echo "x${var}x"
index 04241085fdb4a4b79a7a8eadf0335aee49824f6d..9b12f8d4c9a2194f5a98bcf6c508297107bea236 100644 (file)
@@ -286,6 +286,8 @@ printf "%e\n" 4
 printf "%4.2E\n" 4
 printf "%4.2e\n" 4
 
+printf "%08X\n" 2604292517
+
 # make sure these format specifiers all output '' for empty string arguments
 echo q
 printf "%q\n" ""
@@ -298,3 +300,10 @@ printf "%s\n"
 echo b
 printf "%b\n" ''
 printf "%b\n"
+
+# bug in bash versions up to and including bash-3.2
+v-=yyy
+printf -v var "%s" '/current/working/directory/*.@(m3|i3|ig|mg)'
+shopt -s nullglob extglob
+echo "x$(printf "%b" @(hugo))x"
+printf -v var "%b" @(hugo); echo "x${var}x"
index e56b98048224d513ec404dee1ca8f7f6fad72068..45fb384c076031ca72688525a1e640a6fd750e3f 100644 (file)
@@ -100,3 +100,17 @@ c1 is 1
 c2 is 2
 c3 is 3
 c4 is 4
+fd 10
+fd 8
+fd 10
+fd 8
+1
+2
+3
+4
+1
+2
+3
+4
+cat /tmp/foo
+whatsis
index 2669cd406bb894940c0268b55f5f2310649ca4b3..08b485479e1f597c204e4d96736ab1defc9f8cb6 100644 (file)
@@ -172,3 +172,14 @@ echo before block
 echo after block
 
 ${THIS_SH} ./redir7.sub
+
+${THIS_SH} ./redir8.sub
+
+exec 9>&2
+command exec 2>/tmp/foo
+echo whatsis >&2
+echo cat /tmp/foo
+cat /tmp/foo
+rm -f /tmp/foo
+exec 2>&9
+exec 9>&-
diff --git a/tests/redir.tests~ b/tests/redir.tests~
new file mode 100644 (file)
index 0000000..644e435
--- /dev/null
@@ -0,0 +1,176 @@
+export LC_ALL=C
+export LANG=C
+
+# catch-all for remaining untested redirection stuff
+set +o posix
+
+echo abc > /tmp/redir-test
+cat /tmp/redir-test
+
+set -o noclobber
+
+#this should be an error
+echo def > /tmp/redir-test
+cat /tmp/redir-test
+
+# but this should succeed
+echo def > /tmp/redir-test-2
+cat /tmp/redir-test-2
+
+# and so should this
+echo def >| /tmp/redir-test
+cat /tmp/redir-test
+
+set +o noclobber
+rm /tmp/redir-test /tmp/redir-test-2
+
+# this should be an error
+z="a b"
+cat < $z
+
+echo "Point 1"
+
+exec 3</etc/passwd
+exec 4>/tmp/bash-a
+exec 5>/tmp/bash-b
+echo "Point 2"
+
+echo to a 1>&4
+echo to b 1>&5
+cat /tmp/bash-a
+cat /tmp/bash-b
+exec 11</dev/null
+echo "Point 3"
+
+echo to a 1>&4
+echo to b 1>&5
+cat /tmp/bash-a
+cat /tmp/bash-b
+
+exec 11<&-
+echo "Point 4"
+
+exec 6<>/tmp/bash-c
+echo to c 1>&6
+cat /tmp/bash-c
+echo "Point 5"
+
+rm -f /tmp/bash-a /tmp/bash-b /tmp/bash-c
+
+#
+# Test the effect of input buffering on the shell's input
+#
+${THIS_SH} < redir1.sub
+
+# more open, close, duplicate file descriptors
+${THIS_SH} ./redir3.sub < ./redir3.in1
+
+# still more redirections
+${THIS_SH} ./redir4.sub < redir4.in1
+
+# various forms of null redirection
+testf()
+{
+       if [ -f "$1" ]; then
+               rm -f "$1"
+       else
+               echo oops -- $1 not found
+       fi
+}
+
+> /tmp/null-redir-a
+testf /tmp/null-redir-a
+
+$EXIT > /tmp/null-redir-b
+testf /tmp/null-redir-b
+
+( > /tmp/null-redir-c )
+testf /tmp/null-redir-c
+
+$EXIT > /tmp/null-redir-d &
+wait
+testf /tmp/null-redir-d
+
+exit 3 | $EXIT > /tmp/null-redir-e
+echo $? -- ${PIPESTATUS[@]}
+testf /tmp/null-redir-e
+
+exit 4 | > /tmp/null-redir-f
+echo $? -- ${PIPESTATUS[@]}
+testf /tmp/null-redir-f
+
+> /tmp/null-redir-g &
+wait
+testf /tmp/null-redir-g
+
+exec >/tmp/null-redir-h &
+wait
+testf /tmp/null-redir-h
+
+# make sure async commands don't get /dev/null as stdin when an explicit
+# input redirection is supplied
+for x in 1 2 3; do
+       { read line ; echo $line ; } &
+       wait
+       { read line ; echo $line ; } &
+       wait
+done << EOF
+ab
+cd
+ef
+gh
+ij
+kl
+EOF
+
+# make sure async commands get /dev/null as stdin in the absence of any
+# input redirection
+/bin/cat &
+wait
+echo $?
+
+# make sure that loops work OK with here documents and are not run in
+# subshells
+while read line; do
+       echo $line
+       l2=$line
+done << EOF
+ab
+cd
+EOF
+echo $l2
+
+# These should not echo anything -- bug in versions before 2.04
+( ( echo hello 1>&3 ) 3>&1 ) >/dev/null 2>&1
+
+( ( echo hello 1>&3 ) 3>&1 ) >/dev/null 2>&1 | cat
+
+# in posix mode, non-interactive shells are not allowed to perform
+# filename expansion on input redirections, even if they expand to
+# a single filename
+set -o posix
+cat < redir1.*
+
+# test ksh93 dup-and-close (move fd) redirections
+${THIS_SH} ./redir5.sub
+
+# test behavior after a write error with a builtin command
+${THIS_SH} ./redir6.sub
+
+# problem with redirections using fds bash uses internally
+: ${TMPDIR:=/tmp}
+
+trap 'rm -f $TMPDIR/bash-redir-$$' 0 1 2 3 6 15
+
+echo before block
+{
+       echo before redir
+       exec 10>&1
+       echo after redir
+} > $TMPDIR/bash-redir-$$
+
+echo after block
+
+${THIS_SH} ./redir7.sub
+
+${THIS_SH} ./redir8.sub
diff --git a/tests/redir8.sub b/tests/redir8.sub
new file mode 100644 (file)
index 0000000..da12cc7
--- /dev/null
@@ -0,0 +1,60 @@
+rm -f u
+
+${THIS_SH} -c 'exec 10>&1; echo fd 10 >&10' 10>u
+cat u
+rm -f u
+
+${THIS_SH} -c 'exec 8>&1; echo fd 8 >&8' 8>u
+cat u
+rm -f u
+
+exec 10>u
+exec 10>&1; echo 'fd 10' >&10
+cat u
+rm -f u
+exec 10>&-
+
+exec 8>u
+exec 8>&1; echo 'fd 8' >&8
+cat u
+rm -f u
+exec 8>&-
+
+rm -f infile
+cat > infile <<EOF
+1
+2
+3
+4
+EOF
+
+exec 7<&0
+exec 10<infile
+exec 0<&10; cat <&10
+exec 0<&7
+exec 7<&-
+
+exec 7<&0
+exec 8<infile
+exec 0<&8 ; cat <&8
+exec 0<&7
+exec 7<&-
+
+exec 7<&0
+exec 0</dev/null
+exec 10<infile
+exec 10<&0; cat <&10
+exec 0<&7
+exec 7<&-
+
+exec 7<&0
+exec 0</dev/null
+exec 8<infile
+exec 8<&0; cat <&8
+exec 0<&7
+exec 7<&-
+
+exit 0
+
+
+
index 44207d9cc0a5c5414b606626355a43f46bcd0c70..6fdbae494cb90dce428d28e6ce3ebe89631a3cc2 100644 (file)
@@ -1,4 +1,6 @@
 echo "warning: all of these tests will fail if arrays have not" >&2
 echo "warning: been compiled into the shell" >&2
+echo "warning: the BASH_ARGC and BASH_ARGV tests will fail if debugging support" >&2
+echo "warning: has not been compiled into the shell" >&2
 ${THIS_SH} ./array.tests > /tmp/xx 2>&1
 diff /tmp/xx array.right && rm -f /tmp/xx
diff --git a/tests/run-array~ b/tests/run-array~
new file mode 100644 (file)
index 0000000..44207d9
--- /dev/null
@@ -0,0 +1,4 @@
+echo "warning: all of these tests will fail if arrays have not" >&2
+echo "warning: been compiled into the shell" >&2
+${THIS_SH} ./array.tests > /tmp/xx 2>&1
+diff /tmp/xx array.right && rm -f /tmp/xx
index dbd51caf21ec72dc3a4c0f2c1f84c550f790981c..abdd02fbff2cb227f809b0a73c8a964c5929d8aa 100644 (file)
@@ -46,3 +46,8 @@ file
 hits   command
    3   /tmp/bash
    1   /bin/sh
+f is a function
+f () 
+{ 
+    v='^A'
+}
index d47ae647bf364827f9bd1074662c46eb8bd968a0..15106f0f3d8e7ce1f5d2c3570d18d6722a3f2be2 100644 (file)
@@ -80,3 +80,10 @@ type -t $SHBASE
 
 # make sure the hash table looks right
 hash
+
+# bug in versions of bash up to and including bash-3.2
+f() {
+        v=$'\001'
+    }
+
+type f | cat -v
diff --git a/tests/type.tests~ b/tests/type.tests~
new file mode 100644 (file)
index 0000000..d47ae64
--- /dev/null
@@ -0,0 +1,82 @@
+set +o posix
+
+hash -r
+unalias -a
+
+# this should echo nothing
+type
+# this should be a usage error
+type -r ${THIS_SH}
+
+# these should behave identically
+type notthere
+command -v notthere
+
+alias m=more
+
+unset -f func 2>/dev/null
+func() { echo this is func; }
+
+type -t func
+type -t while
+type -t builtin
+type -t /bin/sh
+type -t ${THIS_SH}
+type -t mv
+
+type func
+# the following two should produce identical output
+type while
+type -a while
+type builtin
+type /bin/sh
+
+command -v func
+command -V func
+command -v while
+command -V while
+
+# the following two lines should produce the same output
+# post-3.0 patch makes command -v silent, as posix specifies
+# first test with alias expansion off (should all fail or produce no output)
+type -t m
+type m
+command -v m
+alias -p
+alias m
+
+# then test with alias expansion on 
+shopt -s expand_aliases
+type m
+type -t m
+command -v m
+alias -p
+alias m
+
+command -V m
+shopt -u expand_aliases
+
+command -v builtin
+command -V builtin
+command -v /bin/sh
+command -V /bin/sh
+
+unset -f func
+type func
+unalias m
+type m
+
+hash -r
+
+hash -p /bin/sh sh
+type -p sh
+
+SHBASE=${THIS_SH##*/}
+hash -p /tmp/$SHBASE $SHBASE
+type -p $SHBASE
+type $SHBASE
+
+type -t $SHBASE
+
+# make sure the hash table looks right
+hash
index ceabb52d7c97841ba91ab0e4665f6962d7f3b74c..3bb0ce796644a70a1c8a6591bf3b755384a3dfe8 100644 (file)
@@ -985,8 +985,13 @@ void
 print_var_function (var)
      SHELL_VAR *var;
 {
+  char *x;
+
   if (function_p (var) && var_isset (var))
-    printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
+    {
+      x = named_function_string ((char *)NULL, function_cell(var), FUNC_MULTILINE|FUNC_EXTERNAL);
+      printf ("%s", x);
+    }
 }
 
 /* **************************************************************** */
@@ -1599,7 +1604,11 @@ FUNCTION_DEF *
 find_function_def (name)
      const char *name;
 {
+#if defined (DEBUGGER)
   return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
+#else
+  return ((FUNCTION_DEF *)0);
+#endif
 }
 
 /* Return the value of VAR.  VAR is assumed to have been the result of a
@@ -2142,6 +2151,7 @@ bind_function (name, value)
   return (entry);
 }
 
+#if defined (DEBUGGER)
 /* Bind a function definition, which includes source file and line number
    information in addition to the command, into the FUNCTION_DEF hash table.*/
 void
@@ -2170,6 +2180,7 @@ bind_function_def (name, value)
       elt->data = (PTR_T *)entry;
     }
 }
+#endif /* DEBUGGER */
 
 /* Add STRING, which is of the form foo=bar, to the temporary environment
    HASH_TABLE (temporary_env).  The functions in execute_cmd.c are
@@ -2362,6 +2373,7 @@ unbind_func (name)
   return 0;  
 }
 
+#if defined (DEBUGGER)
 int
 unbind_function_def (name)
      const char *name;
@@ -2383,6 +2395,7 @@ unbind_function_def (name)
 
   return 0;  
 }
+#endif /* DEBUGGER */
 
 /* Make the variable associated with NAME go away.  HASH_LIST is the
    hash table from which this variable should be deleted (either
index 34920882b41b4550913db061942bcb061ffa4dc1..0e37af212da8d7a29867ef5743215b87935f15da 100644 (file)
@@ -93,6 +93,7 @@ extern char *this_command_name;
 extern char *command_execution_string;
 extern time_t shell_start_time;
 extern int assigning_in_environment;
+extern int executing_builtin;
 
 #if defined (READLINE)
 extern int no_line_editing;
@@ -984,8 +985,13 @@ void
 print_var_function (var)
      SHELL_VAR *var;
 {
+  char *x;
+
   if (function_p (var) && var_isset (var))
-    printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
+    {
+      x = named_function_string ((char *)NULL, function_cell(var), FUNC_MULTILINE|FUNC_EXTERNAL);
+      printf ("%s", x);
+    }
 }
 
 /* **************************************************************** */
@@ -1580,7 +1586,7 @@ SHELL_VAR *
 find_variable (name)
      const char *name;
 {
-  return (find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || this_shell_builtin != 0))));
+  return (find_variable_internal (name, (expanding_redir == 0 && (assigning_in_environment || executing_builtin))));
 }
 
 /* Look up the function entry whose name matches STRING.