summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChet Ramey <chet.ramey@case.edu>2011-12-07 09:08:27 -0500
committerChet Ramey <chet.ramey@case.edu>2011-12-07 09:08:27 -0500
commitb0c16657b4514191b4f6c328615d162726758247 (patch)
tree699cabe601ecbb4ffb42f52bc78e3c6d972d1f9c
parentd7f499903c4fd2559900f12ec3712d234869eddc (diff)
downloadbash-b0c16657b4514191b4f6c328615d162726758247.tar.gz
commit bash-20070523 snapshot
-rw-r--r--CWRU/CWRU.chlog92
-rw-r--r--CWRU/CWRU.chlog~102
-rw-r--r--MANIFEST3
-rw-r--r--MANIFEST~2
-rw-r--r--builtins/declare.def4
-rw-r--r--builtins/declare.def~22
-rw-r--r--builtins/help.def2
-rw-r--r--builtins/help.def~229
-rw-r--r--builtins/printf.def6
-rw-r--r--builtins/printf.def~6
-rw-r--r--builtins/read.def64
-rw-r--r--builtins/read.def.save110
-rw-r--r--builtins/read.def~72
-rw-r--r--builtins/setattr.def4
-rw-r--r--builtins/setattr.def~14
-rw-r--r--builtins/type.def8
-rw-r--r--builtins/type.def~15
-rw-r--r--display-ctrl-r.patch47
-rw-r--r--error.c2
-rw-r--r--error.c~6
-rw-r--r--externs.h3
-rw-r--r--externs.h~399
-rw-r--r--jobs.c.patch65
-rw-r--r--jobs.c~6
-rw-r--r--lib/readline/display.c22
-rw-r--r--lib/readline/display.c~35
-rw-r--r--make_cmd.c4
-rw-r--r--make_cmd.c~858
-rw-r--r--print_cmd.c16
-rw-r--r--print_cmd.c~59
-rw-r--r--redir.c31
-rw-r--r--shell.c14
-rw-r--r--subst.c3
-rw-r--r--subst.c~6
-rw-r--r--subst.h5
-rw-r--r--subst.h~270
-rw-r--r--tests/exec.right2
-rw-r--r--tests/exec.right~57
-rw-r--r--tests/exec8.sub1
-rw-r--r--tests/execscript2
-rw-r--r--tests/exp.right6
-rw-r--r--tests/exp.tests2
-rw-r--r--tests/exp.tests~2
-rw-r--r--tests/exp2.sub12
-rw-r--r--tests/infile4
-rw-r--r--tests/intl.right3
-rw-r--r--tests/intl.tests3
-rw-r--r--tests/intl.tests~40
-rw-r--r--tests/intl1.sub11
-rw-r--r--tests/printf.rightbin1504 -> 1510 bytes
-rw-r--r--tests/printf.tests7
-rw-r--r--tests/printf.tests~9
-rw-r--r--tests/redir.right14
-rw-r--r--tests/redir.tests11
-rw-r--r--tests/redir.tests~176
-rw-r--r--tests/redir8.sub60
-rw-r--r--tests/run-array2
-rw-r--r--tests/run-array~4
-rw-r--r--tests/type.right5
-rw-r--r--tests/type.tests7
-rw-r--r--tests/type.tests~82
-rw-r--r--variables.c15
-rw-r--r--variables.c~10
63 files changed, 2904 insertions, 149 deletions
diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog
index b084d1e7..61aafbca 100644
--- a/CWRU/CWRU.chlog
+++ b/CWRU/CWRU.chlog
@@ -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
diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~
index 51d9ed5a..09f9fbd3 100644
--- a/CWRU/CWRU.chlog~
+++ b/CWRU/CWRU.chlog~
@@ -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]
diff --git a/MANIFEST b/MANIFEST
index 28a45217..732527dd 100644
--- 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
diff --git a/MANIFEST~ b/MANIFEST~
index 28a45217..ce98d7e4 100644
--- 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
diff --git a/builtins/declare.def b/builtins/declare.def
index 2bb9e1d2..f8fe32bf 100644
--- a/builtins/declare.def
+++ b/builtins/declare.def
@@ -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);
}
diff --git a/builtins/declare.def~ b/builtins/declare.def~
index c472a86c..31c09012 100644
--- a/builtins/declare.def~
+++ b/builtins/declare.def~
@@ -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...] */
diff --git a/builtins/help.def b/builtins/help.def
index 059f9866..743685b1 100644
--- a/builtins/help.def
+++ b/builtins/help.def
@@ -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
index 00000000..067b83cf
--- /dev/null
+++ b/builtins/help.def~
@@ -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 */
diff --git a/builtins/printf.def b/builtins/printf.def
index e283323c..865b0478 100644
--- a/builtins/printf.def
+++ b/builtins/printf.def
@@ -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;
diff --git a/builtins/printf.def~ b/builtins/printf.def~
index f268180a..5daface1 100644
--- a/builtins/printf.def~
+++ b/builtins/printf.def~
@@ -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;
diff --git a/builtins/read.def b/builtins/read.def
index 0739059f..e5aff643 100644
--- a/builtins/read.def
+++ b/builtins/read.def
@@ -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;
diff --git a/builtins/read.def.save1 b/builtins/read.def.save1
index e22f8228..5bfe00b4 100644
--- a/builtins/read.def.save1
+++ b/builtins/read.def.save1
@@ -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;
diff --git a/builtins/read.def~ b/builtins/read.def~
index e22f8228..9680c425 100644
--- a/builtins/read.def~
+++ b/builtins/read.def~
@@ -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;
diff --git a/builtins/setattr.def b/builtins/setattr.def
index 8507120b..a44bfde8 100644
--- a/builtins/setattr.def
+++ b/builtins/setattr.def
@@ -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
diff --git a/builtins/setattr.def~ b/builtins/setattr.def~
index 90f8dcc8..72bde0d1 100644
--- a/builtins/setattr.def~
+++ b/builtins/setattr.def~
@@ -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
diff --git a/builtins/type.def b/builtins/type.def
index 370e596c..fa40ad25 100644
--- a/builtins/type.def
+++ b/builtins/type.def
@@ -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);
diff --git a/builtins/type.def~ b/builtins/type.def~
index d03ccb2d..54801235 100644
--- a/builtins/type.def~
+++ b/builtins/type.def~
@@ -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
index 00000000..e4d5318c
--- /dev/null
+++ b/display-ctrl-r.patch
@@ -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 c83a9861..ceedc2c9 100644
--- 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];
}
diff --git a/error.c~ b/error.c~
index c400f449..c83a9861 100644
--- 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 */
diff --git a/externs.h b/externs.h
index 834b767b..b8a2910f 100644
--- 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
index 00000000..834b767b
--- /dev/null
+++ b/externs.h~
@@ -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
index 00000000..8b2d1632
--- /dev/null
+++ b/jobs.c.patch
@@ -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 7b3c2595..0ff2d591 100644
--- 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));
}
}
}
diff --git a/lib/readline/display.c b/lib/readline/display.c
index b4847777..1fbd9e59 100644
--- a/lib/readline/display.c
+++ b/lib/readline/display.c
@@ -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
diff --git a/lib/readline/display.c~ b/lib/readline/display.c~
index f0d5e2d2..ce811709 100644
--- a/lib/readline/display.c~
+++ b/lib/readline/display.c~
@@ -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
diff --git a/make_cmd.c b/make_cmd.c
index 6d5409cc..08eed18a 100644
--- a/make_cmd.c
+++ b/make_cmd.c
@@ -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
index 00000000..a5909319
--- /dev/null
+++ b/make_cmd.c~
@@ -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;
+}
diff --git a/print_cmd.c b/print_cmd.c
index d1dfd1a7..0386a78a 100644
--- a/print_cmd.c
+++ b/print_cmd.c
@@ -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);
}
diff --git a/print_cmd.c~ b/print_cmd.c~
index e68619fe..fe76e0b0 100644
--- a/print_cmd.c~
+++ b/print_cmd.c~
@@ -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 68565dd6..283b07db 100644
--- 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 c643f0c1..4f440428 100644
--- 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 216cf572..955eba64 100644
--- 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;
{
diff --git a/subst.c~ b/subst.c~
index 3c444b5f..b18d56db 100644
--- 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 0af50240..181f10aa 100644
--- 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
index 00000000..a2aff011
--- /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_ */
diff --git a/tests/exec.right b/tests/exec.right
index d65b89df..07591295 100644
--- a/tests/exec.right
+++ b/tests/exec.right
@@ -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
index 00000000..6e74b22c
--- /dev/null
+++ b/tests/exec.right~
@@ -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
index 00000000..014726dc
--- /dev/null
+++ b/tests/exec8.sub
@@ -0,0 +1 @@
+shopt expand_aliases
diff --git a/tests/execscript b/tests/execscript
index 09a4ba5f..5e11e235 100644
--- a/tests/execscript
+++ b/tests/execscript
@@ -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
diff --git a/tests/exp.right b/tests/exp.right
index d7fbe464..faafad2b 100644
--- a/tests/exp.right
+++ b/tests/exp.right
@@ -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
diff --git a/tests/exp.tests b/tests/exp.tests
index ed23d0cb..42fbf724 100644
--- a/tests/exp.tests
+++ b/tests/exp.tests
@@ -380,3 +380,5 @@ echo ${a//\\?/ }
echo ${a//\?/ }
${THIS_SH} ./exp1.sub
+
+${THIS_SH} ./exp2.sub
diff --git a/tests/exp.tests~ b/tests/exp.tests~
index 884b5a69..ed23d0cb 100644
--- a/tests/exp.tests~
+++ b/tests/exp.tests~
@@ -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
index 00000000..a70179ec
--- /dev/null
+++ b/tests/exp2.sub
@@ -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
index 00000000..94ebaf90
--- /dev/null
+++ b/tests/infile
@@ -0,0 +1,4 @@
+1
+2
+3
+4
diff --git a/tests/intl.right b/tests/intl.right
index 21a3b4fd..449d5b09 100644
--- a/tests/intl.right
+++ b/tests/intl.right
@@ -8,3 +8,6 @@ ok 2
aéb
0000000 141 303 251 142
0000004
+-абвгдежзиклмноп - 16
+-абвгдежзиклмноп- 15
+-абвгд- 5
diff --git a/tests/intl.tests b/tests/intl.tests
index d4c2373e..cd919dfb 100644
--- a/tests/intl.tests
+++ b/tests/intl.tests
@@ -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
index 00000000..3f5ea9a9
--- /dev/null
+++ b/tests/intl.tests~
@@ -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
index 00000000..a03648fb
--- /dev/null
+++ b/tests/intl1.sub
@@ -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}
diff --git a/tests/printf.right b/tests/printf.right
index 5a8749ef..a6bb04d6 100644
--- a/tests/printf.right
+++ b/tests/printf.right
Binary files differ
diff --git a/tests/printf.tests b/tests/printf.tests
index 7cfeebd0..80966d71 100644
--- a/tests/printf.tests
+++ b/tests/printf.tests
@@ -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"
diff --git a/tests/printf.tests~ b/tests/printf.tests~
index 04241085..9b12f8d4 100644
--- a/tests/printf.tests~
+++ b/tests/printf.tests~
@@ -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"
diff --git a/tests/redir.right b/tests/redir.right
index e56b9804..45fb384c 100644
--- a/tests/redir.right
+++ b/tests/redir.right
@@ -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
diff --git a/tests/redir.tests b/tests/redir.tests
index 2669cd40..08b48547 100644
--- a/tests/redir.tests
+++ b/tests/redir.tests
@@ -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
index 00000000..644e435c
--- /dev/null
+++ b/tests/redir.tests~
@@ -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
index 00000000..da12cc76
--- /dev/null
+++ b/tests/redir8.sub
@@ -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
+
+
+
diff --git a/tests/run-array b/tests/run-array
index 44207d9c..6fdbae49 100644
--- a/tests/run-array
+++ b/tests/run-array
@@ -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
index 00000000..44207d9c
--- /dev/null
+++ b/tests/run-array~
@@ -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
diff --git a/tests/type.right b/tests/type.right
index dbd51caf..abdd02fb 100644
--- a/tests/type.right
+++ b/tests/type.right
@@ -46,3 +46,8 @@ file
hits command
3 /tmp/bash
1 /bin/sh
+f is a function
+f ()
+{
+ v='^A'
+}
diff --git a/tests/type.tests b/tests/type.tests
index d47ae647..15106f0f 100644
--- a/tests/type.tests
+++ b/tests/type.tests
@@ -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
index 00000000..d47ae647
--- /dev/null
+++ b/tests/type.tests~
@@ -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
diff --git a/variables.c b/variables.c
index ceabb52d..3bb0ce79 100644
--- a/variables.c
+++ b/variables.c
@@ -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
diff --git a/variables.c~ b/variables.c~
index 34920882..0e37af21 100644
--- a/variables.c~
+++ b/variables.c~
@@ -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.