mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-07-10 05:30:49 +02:00
commit bash-20070523 snapshot
This commit is contained in:
+90
-2
@@ -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
|
||||
|
||||
+101
-1
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+10
-12
@@ -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...] */
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
+5
-1
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+62
-2
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+66
-6
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-6
@@ -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);
|
||||
|
||||
+5
-10
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
+399
@@ -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_ */
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-1
@@ -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
|
||||
|
||||
+17
-18
@@ -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
|
||||
|
||||
+3
-1
@@ -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));
|
||||
|
||||
+858
@@ -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;
|
||||
}
|
||||
+10
-6
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+24
-35
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ()
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
{
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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_ */
|
||||
@@ -51,4 +51,6 @@ this is ohio-state
|
||||
0
|
||||
1
|
||||
testb
|
||||
bash: no job control in this shell
|
||||
expand_aliases on
|
||||
after
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1 @@
|
||||
shopt expand_aliases
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -380,3 +380,5 @@ echo ${a//\\?/ }
|
||||
echo ${a//\?/ }
|
||||
|
||||
${THIS_SH} ./exp1.sub
|
||||
|
||||
${THIS_SH} ./exp2.sub
|
||||
|
||||
@@ -378,3 +378,5 @@ a="a?b?c"
|
||||
echo ${a//\\?/ }
|
||||
|
||||
echo ${a//\?/ }
|
||||
|
||||
${THIS_SH} ./exp1.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
|
||||
@@ -0,0 +1,4 @@
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
@@ -8,3 +8,6 @@ ok 2
|
||||
aéb
|
||||
0000000 141 303 251 142
|
||||
0000004
|
||||
-абвгдежзиклмноп - 16
|
||||
-абвгдежзиклмноп- 15
|
||||
-абвгд- 5
|
||||
|
||||
@@ -36,3 +36,6 @@ set a b
|
||||
|
||||
printf '%s\n' "$*"
|
||||
printf '%s' "$*" | od -b
|
||||
|
||||
# display differences make this problematic
|
||||
${THIS_SH} ./intl1.sub
|
||||
|
||||
@@ -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
|
||||
@@ -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}
|
||||
Binary file not shown.
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>&-
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -46,3 +46,8 @@ file
|
||||
hits command
|
||||
3 /tmp/bash
|
||||
1 /bin/sh
|
||||
f is a function
|
||||
f ()
|
||||
{
|
||||
v='^A'
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
+14
-1
@@ -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
|
||||
|
||||
+8
-2
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user