commit bash-20041005 snapshot

This commit is contained in:
Chet Ramey
2011-12-03 13:37:16 -05:00
parent 22e63b05c8
commit 43df7bbb63
28 changed files with 805 additions and 89 deletions
+126
View File
@@ -10155,3 +10155,129 @@ execute_cmd.c
execute_cmd.c
- make sure to call UNBLOCK_CHILD before returning on a pipe creation
failure in execute_pipeline
9/27
----
variables.c
- change get_bash_command to deal with the_printed_command_except_trap
being NULL
execute_cmd.c
- fix execute_simple_command to deal with the_printed_command being
NULL when assigning to the_printed_command_except_trap -- fixes
seg fault in savestring()
parse.y
- change the parser so that the closing `)' in a compound variable
assignment delimits a token -- ksh93 does it this way
doc/{bash.1,bashref.texi}
- change description of tilde expansion to note that expansion is
attempted only after the first =~ in an assignment statement
builtins/declare.def
- when assigning to an array variable with declare -a x=(...), make
sure the last character in the rhs of the variable assignment is
`)', not just that it appears somewhere
9/28
----
command.h
- add a `W_NOEXPAND' flag to inhibit all expansion except quote removal
- add a `W_COMPASSIGN' flag to denote a word is a compound assignment
statement
parse.y
- set W_COMPASSIGN on words that appear to be compound assignments
subst.c
- pass W_NOXPAND and W_COMPASSIGN through end of expand_word_internal
subst.[ch]
- new function, expand_assignment_string_to_string, calls
expand_string_assignment and then string_list on the result
variables.c
- assign_in_env now calls expand_assignment_string_to_string
9/30
----
builtins/common.c
- change get_job_spec so the null job `%' once again means the current
job
10/1
----
subst.c
- do_assignment_internal now takes a WORD_DESC * as its first
argument, and uses its `word' member as the assignment string
- change expand_word_list_internal to call do_word_assignment instead
of do_assignment, passing it `word' instead of, e.g., `word->word'
- change extract_array_assignment_list to just return the passed
string minus a trailing `)' if the last character is a right
paren
- change do_assignment_internal to call extract_array_assignment_list
subst.[ch]
- change do_assignment and do_assignment_no_expand to take a `char *'
instead of `const char *' first argument; change extern prototypes
- new function, do_word_assignment, takes a WORD_DESC * and calls
do_assignment_internal on it; add extern declaration with prototype
general.h
- new typedef, sh_wassign_func_t, like sh_assign_func_t but takes a
WORD_DESC * as its first argument
variables.[ch]
- assign_in_env now takes a WORD_DESC * as its first argument
10/2
----
command.h
- new word flag, W_ASSNBLTIN, denotes that the word is a builtin
command (in a command position) that takes assignment statements
as arguments, like `declare'
- new word flags, W_ASSIGNARG, denotes that word is an assignment
statement given as argument to assignment builtin
execute_cmd.c
- set W_ASSNBLTIN flag in fix_assignment_words if necessary (if there
are any arguments that are assignment statements)
- set W_ASSIGNARG flag in fix_assignment_words if necessary
subst.c
- new function, do_compound_assignment, encapsulates the necessary
code to perform a compound array assignment (including creation of
local variables); called from do_assignment_internal
- to fix the double-expansion problem with compound array assignments
that are arguments to builtins like `declare', changed
shell_expand_word_list to treat those arguments like assignment
statements (with proper creation of local variables inside shell
functions) and pass the attribute-setting portion of the statement
onto the builtin. This is what ksh93 appears to do, from inspection
of the `ksh93 -x' output
execute_cmd.c
- fix execute_simple_command: in case of pipeline or async command,
when forking early, set `subshell_environment' so that it can contain
both SUBSHELL_PIPE and SUBSHELL_ASYNC -- the two should not be
mutually exclusive. Fixes bug reported by pierre.humblet@ieee.org
- remove references to last_pid, old_command_subst_pid; use NO_PID as
a sentinel value to decide whether or not a child process has been
created and needs to be waited for. Submitted by
pierre.humblet@ieee.org to fix recycling-pid problem on cygwin
doc/{bash.1,bashref.texi}
- fixed documentation of `@(pattern)' extended globbing operator --
it succeeds if the string matches one of the patterns, not exactly
one. This is what ksh93 does, too
lib/readline/complete.c
- fixed rl_menu_complete so that a negative argument cycles backwards
through the list
10/3
----
subst.c
- use W_COMPASSIGN flag in do_assignment_internal instead of deciding
lexically which assignments are compound array assignments
+7 -1
View File
@@ -731,6 +731,8 @@ tests/extglob.tests f
tests/extglob.right f
tests/extglob2.tests f
tests/extglob2.right f
tests/extglob3.tests f
tests/extglob3.right f
tests/func.tests f
tests/func.right f
tests/func1.sub f
@@ -840,6 +842,7 @@ tests/run-execscript f
tests/run-exp-tests f
tests/run-extglob f
tests/run-extglob2 f
tests/run-extglob3 f
tests/run-func f
tests/run-getopts f
tests/run-glob-test f
@@ -873,6 +876,7 @@ tests/run-shopt f
tests/run-strip f
tests/run-test f
tests/run-tilde f
tests/run-tilde2 f
tests/run-trap f
tests/run-type f
tests/run-varenv f
@@ -886,8 +890,10 @@ tests/strip.tests f
tests/strip.right f
tests/test.tests f
tests/test.right f
tests/tilde-tests f
tests/tilde.tests f
tests/tilde.right f
tests/tilde2.tests f
tests/tilde2.right f
tests/trap.tests f
tests/trap.right f
tests/trap1.sub f 755
+16
View File
@@ -0,0 +1,16 @@
*** ../bash-3.0-patched/braces.c Wed Sep 8 11:07:53 2004
--- braces.c Fri Sep 17 18:42:36 2004
***************
*** 403,407 ****
pass_next = 1;
i++;
! level++;
continue;
}
--- 403,408 ----
pass_next = 1;
i++;
! if (quoted == 0)
! level++;
continue;
}
-1
View File
@@ -588,7 +588,6 @@ get_job_spec (list)
switch (*word)
{
case 0:
return NO_JOB;
case '%':
case '+':
return (current_job);
+6
View File
@@ -377,7 +377,13 @@ declare_internal (list, local_var)
#if defined (ARRAY_VARS)
if ((making_array_special || (flags_on & att_array) || array_p (var)) && offset)
{
int vlen;
vlen = STRLEN (value);
#if 0
if (value[0] == '(' && strchr (value, ')'))
#else
if (value[0] == '(' && value[vlen-1] == ')')
#endif
compound_array_assign = 1;
else
simple_array_assign = 1;
+203
View File
@@ -0,0 +1,203 @@
This file is reserved.def, in which the shell reserved words are defined.
It has no direct C file production, but defines builtins for the Bash
builtin help command.
Copyright (C) 1987-2002 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.
$BUILTIN for
$SHORT_DOC for NAME [in WORDS ... ;] do COMMANDS; done
The `for' loop executes a sequence of commands for each member in a
list of items. If `in WORDS ...;' is not present, then `in "$@"' is
assumed. For each element in WORDS, NAME is set to that element, and
the COMMANDS are executed.
$END
$BUILTIN for ((
$DOCNAME arith_for
$SHORT_DOC for (( exp1; exp2; exp3 )); do COMMANDS; done
Equivalent to
(( EXP1 ))
while (( EXP2 )); do
COMMANDS
(( EXP3 ))
done
EXP1, EXP2, and EXP3 are arithmetic expressions. If any expression is
omitted, it behaves as if it evaluates to 1.
$END
$BUILTIN select
$SHORT_DOC select NAME [in WORDS ... ;] do COMMANDS; done
The WORDS are expanded, generating a list of words. The
set of expanded words is printed on the standard error, each
preceded by a number. If `in WORDS' is not present, `in "$@"'
is assumed. The PS3 prompt is then displayed and a line read
from the standard input. If the line consists of the number
corresponding to one of the displayed words, then NAME is set
to that word. If the line is empty, WORDS and the prompt are
redisplayed. If EOF is read, the command completes. Any other
value read causes NAME to be set to null. The line read is saved
in the variable REPLY. COMMANDS are executed after each selection
until a break command is executed.
$END
$BUILTIN time
$SHORT_DOC time [-p] PIPELINE
Execute PIPELINE and print a summary of the real time, user CPU time,
and system CPU time spent executing PIPELINE when it terminates.
The return status is the return status of PIPELINE. The `-p' option
prints the timing summary in a slightly different format. This uses
the value of the TIMEFORMAT variable as the output format.
$END
$BUILTIN case
$SHORT_DOC case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
Selectively execute COMMANDS based upon WORD matching PATTERN. The
`|' is used to separate multiple patterns.
$END
$BUILTIN if
$SHORT_DOC if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
The if COMMANDS are executed. If the exit status is zero, then the then
COMMANDS are executed. Otherwise, each of the elif COMMANDS are executed
in turn, and if the exit status is zero, the corresponding then COMMANDS
are executed and the if command completes. Otherwise, the else COMMANDS
are executed, if present. The exit status is the exit status of the last
command executed, or zero if no condition tested true.
$END
$BUILTIN while
$SHORT_DOC while COMMANDS; do COMMANDS; done
Expand and execute COMMANDS as long as the final command in the
`while' COMMANDS has an exit status of zero.
$END
$BUILTIN until
$SHORT_DOC until COMMANDS; do COMMANDS; done
Expand and execute COMMANDS as long as the final command in the
`until' COMMANDS has an exit status which is not zero.
$END
$BUILTIN function
$SHORT_DOC function NAME { COMMANDS ; } or NAME () { COMMANDS ; }
Create a simple command invoked by NAME which runs COMMANDS.
Arguments on the command line along with NAME are passed to the
function as $0 .. $n.
$END
$BUILTIN { ... }
$DOCNAME grouping_braces
$SHORT_DOC { COMMANDS ; }
Run a set of commands in a group. This is one way to redirect an
entire set of commands.
$END
$BUILTIN %
$DOCNAME fg_percent
$SHORT_DOC job_spec [&]
Equivalent to the JOB_SPEC argument to the `fg' command. Resume a
stopped or background job. JOB_SPEC can specify either a job name
or a job number. Following JOB_SPEC with a `&' places the job in
the background, as if the job specification had been supplied as an
argument to `bg'.
$END
$BUILTIN (( ... ))
$DOCNAME arith
$SHORT_DOC (( expression ))
The EXPRESSION is evaluated according to the rules for arithmetic
evaluation. Equivalent to "let EXPRESSION".
$END
$BUILTIN [[ ... ]]
$DOCNAME conditional
$SHORT_DOC [[ expression ]]
Returns a status of 0 or 1 depending on the evaluation of the conditional
expression EXPRESSION. Expressions are composed of the same primaries used
by the `test' builtin, and may be combined using the following operators
( EXPRESSION ) Returns the value of EXPRESSION
! EXPRESSION True if EXPRESSION is false; else false
EXPR1 && EXPR2 True if both EXPR1 and EXPR2 are true; else false
EXPR1 || EXPR2 True if either EXPR1 or EXPR2 is true; else false
When the `==' and `!=' operators are used, the string to the right of the
operator is used as a pattern and pattern matching is performed. The
&& and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
determine the expression's value.
$END
$BUILTIN variables
$DOCNAME variable_help
$SHORT_DOC variables - Some variable names and meanings
BASH_VERSION Version information for this Bash.
CDPATH A colon separated list of directories to search
when the argument to `cd' is not found in the current
directory.
GLOBIGNORE A colon-separated list of patterns describing filenames to
be ignored by pathname expansion.
#if defined (HISTORY)
HISTFILE The name of the file where your command history is stored.
HISTFILESIZE The maximum number of lines this file can contain.
HISTSIZE The maximum number of history lines that a running
shell can access.
#endif /* HISTORY */
HOME The complete pathname to your login directory.
HOSTNAME The name of the current host.
HOSTTYPE The type of CPU this version of Bash is running under.
IGNOREEOF Controls the action of the shell on receipt of an EOF
character as the sole input. If set, then the value
of it is the number of EOF characters that can be seen
in a row on an empty line before the shell will exit
(default 10). When unset, EOF signifies the end of input.
MACHTYPE A string describing the current system Bash is running on.
MAILCHECK How often, in seconds, Bash checks for new mail.
MAILPATH A colon-separated list of filenames which Bash checks
for new mail.
OSTYPE The version of Unix this version of Bash is running on.
PATH A colon-separated list of directories to search when
looking for commands.
PROMPT_COMMAND A command to be executed before the printing of each
primary prompt.
PS1 The primary prompt string.
PS2 The secondary prompt string.
PWD The full pathname of the current directory.
SHELLOPTS A colon-separated list of enabled shell options.
TERM The name of the current terminal type.
TIMEFORMAT The output format for timing statistics displayed by the
`time' reserved word.
auto_resume Non-null means a command word appearing on a line by
itself is first looked for in the list of currently
stopped jobs. If found there, that job is foregrounded.
A value of `exact' means that the command word must
exactly match a command in the list of stopped jobs. A
value of `substring' means that the command word must
match a substring of the job. Any other value means that
the command must be a prefix of a stopped job.
#if defined (HISTORY)
# if defined (BANG_HISTORY)
histchars Characters controlling history expansion and quick
substitution. The first character is the history
substitution character, usually `!'. The second is
the `quick substitution' character, usually `^'. The
third is the `history comment' character, usually `#'.
# endif /* BANG_HISTORY */
HISTIGNORE A colon-separated list of patterns used to decide which
commands should be saved on the history list.
#endif /* HISTORY */
$END
+18 -14
View File
@@ -67,20 +67,24 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
cm_arith, cm_cond, cm_arith_for, cm_subshell };
/* Possible values for the `flags' field of a WORD_DESC. */
#define W_HASDOLLAR 0x0001 /* Dollar sign present. */
#define W_QUOTED 0x0002 /* Some form of quote character is present. */
#define W_ASSIGNMENT 0x0004 /* This word is a variable assignment. */
#define W_GLOBEXP 0x0008 /* This word is the result of a glob expansion. */
#define W_NOSPLIT 0x0010 /* Do not perform word splitting on this word. */
#define W_NOGLOB 0x0020 /* Do not perform globbing on this word. */
#define W_NOSPLIT2 0x0040 /* Don't split word except for $@ expansion. */
#define W_TILDEEXP 0x0080 /* Tilde expand this assignment word */
#define W_DOLLARAT 0x0100 /* $@ and its special handling */
#define W_DOLLARSTAR 0x0200 /* $* and its special handling */
#define W_NOCOMSUB 0x0400 /* Don't perform command substitution on this word */
#define W_ASSIGNRHS 0x0800 /* Word is rhs of an assignment statement */
#define W_NOTILDE 0x1000 /* Don't perform tilde expansion on this word */
#define W_ITILDE 0x2000 /* Internal flag for word expansion */
#define W_HASDOLLAR 0x00001 /* Dollar sign present. */
#define W_QUOTED 0x00002 /* Some form of quote character is present. */
#define W_ASSIGNMENT 0x00004 /* This word is a variable assignment. */
#define W_GLOBEXP 0x00008 /* This word is the result of a glob expansion. */
#define W_NOSPLIT 0x00010 /* Do not perform word splitting on this word. */
#define W_NOGLOB 0x00020 /* Do not perform globbing on this word. */
#define W_NOSPLIT2 0x00040 /* Don't split word except for $@ expansion. */
#define W_TILDEEXP 0x00080 /* Tilde expand this assignment word */
#define W_DOLLARAT 0x00100 /* $@ and its special handling */
#define W_DOLLARSTAR 0x00200 /* $* and its special handling */
#define W_NOCOMSUB 0x00400 /* Don't perform command substitution on this word */
#define W_ASSIGNRHS 0x00800 /* Word is rhs of an assignment statement */
#define W_NOTILDE 0x01000 /* Don't perform tilde expansion on this word */
#define W_ITILDE 0x02000 /* Internal flag for word expansion */
#define W_NOEXPAND 0x04000 /* Don't expand at all -- do quote removal */
#define W_COMPASSIGN 0x08000 /* Compound assignment */
#define W_ASSNBLTIN 0x10000 /* word is a builtin command that takes assignments */
#define W_ASSIGNARG 0x20000 /* word is assignment argument to command */
/* Possible values for subshell_environment */
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
+6 -4
View File
@@ -6,12 +6,12 @@
.\" Case Western Reserve University
.\" chet@po.CWRU.Edu
.\"
.\" Last Change: Fri Sep 17 22:44:17 EDT 2004
.\" Last Change: Sat Oct 2 18:05:57 EDT 2004
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2004 Sep 17" "GNU Bash-3.0"
.TH BASH 1 "2004 Oct 2" "GNU Bash-3.1-devel"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -2236,7 +2236,7 @@ is unchanged.
Each variable assignment is checked for unquoted tilde-prefixes immediately
following a
.B :
or
or the first
.BR = .
In these cases, tilde expansion is also performed.
Consequently, one may use file names with tildes in assignments to
@@ -2853,7 +2853,7 @@ Matches zero or more occurrences of the given patterns
Matches one or more occurrences of the given patterns
.TP
\fB@(\fP\^\fIpattern-list\^\fP\fB)\fP
Matches exactly one of the given patterns
Matches one of the given patterns
.TP
\fB!(\fP\^\fIpattern-list\^\fP\fB)\fP
Matches anything except one of the given patterns
@@ -4063,6 +4063,8 @@ command), the current job is always flagged with a
.BR + ,
and the previous job with a
.BR \- .
A single % (with no accompanying job specification) also refers to the
current job.
.PP
Simply naming a job can be used to bring it into the
foreground:
+8 -7
View File
@@ -1456,7 +1456,7 @@ If the login name is invalid, or the tilde expansion fails, the word is
left unchanged.
Each variable assignment is checked for unquoted tilde-prefixes immediately
following a @samp{:} or @samp{=}.
following a @samp{:} or the first @samp{=}.
In these cases, tilde expansion is also performed.
Consequently, one may use file names with tildes in assignments to
@env{PATH}, @env{MAILPATH}, and @env{CDPATH},
@@ -1931,7 +1931,7 @@ Matches zero or more occurrences of the given patterns.
Matches one or more occurrences of the given patterns.
@item @@(@var{pattern-list})
Matches exactly one of the given patterns.
Matches one of the given patterns.
@item !(@var{pattern-list})
Matches anything except one of the given patterns.
@@ -6118,11 +6118,12 @@ There are a number of ways to refer to a job in the shell. The
character @samp{%} introduces a job name.
Job number @code{n} may be referred to as @samp{%n}.
The symbols @samp{%%} and
@samp{%+} refer to the shell's notion of the current job, which
is the last job stopped while it was in the foreground or started
in the background. The
previous job may be referenced using @samp{%-}. In output
The symbols @samp{%%} and @samp{%+} refer to the shell's notion of the
current job, which is the last job stopped while it was in the foreground
or started in the background.
A single @samp{%} (with no accompanying job specification) also refers
to the current job.
The previous job may be referenced using @samp{%-}. In output
pertaining to jobs (e.g., the output of the @code{jobs} command),
the current job is always flagged with a @samp{+}, and the
previous job with a @samp{-}.
+5 -5
View File
@@ -2,9 +2,9 @@
Copyright (C) 1988-2004 Free Software Foundation, Inc.
@end ignore
@set EDITION 3.0
@set VERSION 3.0
@set UPDATED 17 September 2004
@set UPDATED-MONTH September 2004
@set EDITION 3.1-devel
@set VERSION 3.1-devel
@set UPDATED 2 October 2004
@set UPDATED-MONTH October 2004
@set LASTCHANGE Fri Sep 17 22:43:56 EDT 2004
@set LASTCHANGE Sat Oct 2 18:05:41 EDT 2004
+20 -21
View File
@@ -160,7 +160,7 @@ static int execute_while_command __P((WHILE_COM *));
static int execute_until_command __P((WHILE_COM *));
static int execute_while_or_until __P((WHILE_COM *, int));
static int execute_if_command __P((IF_COM *));
static int execute_null_command __P((REDIRECT *, int, int, int, pid_t));
static int execute_null_command __P((REDIRECT *, int, int, int));
static void fix_assignment_words __P((WORD_LIST *));
static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
static int execute_builtin __P((sh_builtin_func_t *, WORD_LIST *, int, int));
@@ -491,7 +491,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
{
int exec_result, invert, ignore_return, was_error_trap;
REDIRECT *my_undo_list, *exec_undo_list;
volatile pid_t last_pid;
volatile int save_line_number;
if (command == 0 || breaking || continuing || read_but_dont_execute)
@@ -648,7 +647,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
/* We can't rely on variables retaining their values across a
call to execute_simple_command if a longjmp occurs as the
result of a `return' builtin. This is true for sure with gcc. */
last_pid = last_made_pid;
last_made_pid = NO_PID;
was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
if (ignore_return && command->value.Simple)
@@ -678,7 +677,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
/* XXX - this is something to watch out for if there are problems
when the shell is compiled without job control. */
if (already_making_children && pipe_out == NO_PIPE &&
last_pid != last_made_pid)
last_made_pid != NO_PID)
{
stop_pipeline (asynchronous, (COMMAND *)NULL);
@@ -698,14 +697,6 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
subshells forked to execute builtin commands (e.g., in
pipelines) to be waited for twice. */
exec_result = wait_for (last_made_pid);
#if defined (RECYCLES_PIDS)
/* LynxOS, for one, recycles pids very quickly -- so quickly
that a new process may have the same pid as the last one
created. This has been reported to fix the problem on that
OS, and a similar problem on Cygwin. */
if (exec_result == 0)
last_made_pid = NO_PID;
#endif
}
}
@@ -2583,10 +2574,9 @@ bind_lastarg (arg)
to be run asynchronously. This handles all the side effects that are
supposed to take place. */
static int
execute_null_command (redirects, pipe_in, pipe_out, async, old_last_command_subst_pid)
execute_null_command (redirects, pipe_in, pipe_out, async)
REDIRECT *redirects;
int pipe_in, pipe_out, async;
pid_t old_last_command_subst_pid;
{
int r;
@@ -2632,7 +2622,7 @@ execute_null_command (redirects, pipe_in, pipe_out, async, old_last_command_subs
if (r != 0)
return (EXECUTION_FAILURE);
else if (old_last_command_subst_pid != last_command_subst_pid)
else if (last_command_subst_pid != NO_PID)
return (last_command_exit_value);
else
return (EXECUTION_SUCCESS);
@@ -2661,8 +2651,10 @@ fix_assignment_words (words)
b = builtin_address_internal (words->word->word, 0);
if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
return;
else if (b && (b->flags & ASSIGNMENT_BUILTIN))
words->word->flags |= W_ASSNBLTIN;
}
w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP);
w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG);
}
}
@@ -2678,7 +2670,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
WORD_LIST *words, *lastword;
char *command_line, *lastarg, *temp;
int first_word_quoted, result, builtin_is_special, already_forked, dofork;
pid_t old_last_command_subst_pid, old_last_async_pid;
pid_t old_last_async_pid;
sh_builtin_func_t *builtin;
SHELL_VAR *func;
@@ -2697,7 +2689,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
if (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0))
{
FREE (the_printed_command_except_trap);
the_printed_command_except_trap = savestring (the_printed_command);
the_printed_command_except_trap = the_printed_command ? savestring (the_printed_command) : (char *)0;
}
/* Run the debug trap before each simple command, but do it after we
@@ -2713,7 +2705,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
first_word_quoted =
simple_command->words ? (simple_command->words->word->flags & W_QUOTED): 0;
old_last_command_subst_pid = last_command_subst_pid;
last_command_subst_pid = NO_PID;
old_last_async_pid = last_asynchronous_pid;
already_forked = dofork = 0;
@@ -2752,9 +2744,17 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
already_forked = 1;
simple_command->flags |= CMD_NO_FORK;
#if 0
subshell_environment = (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
? (SUBSHELL_PIPE|SUBSHELL_FORK)
: (SUBSHELL_ASYNC|SUBSHELL_FORK);
#else
subshell_environment = SUBSHELL_FORK;
if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
subshell_environment |= SUBSHELL_PIPE;
if (async)
subshell_environment |= SUBSHELL_ASYNC;
#endif
/* We need to do this before piping to handle some really
pathological cases where one of the pipe file descriptors
@@ -2799,8 +2799,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
this_command_name = 0;
result = execute_null_command (simple_command->redirects,
pipe_in, pipe_out,
already_forked ? 0 : async,
old_last_command_subst_pid);
already_forked ? 0 : async);
if (already_forked)
exit (result);
else
+1
View File
@@ -216,6 +216,7 @@ typedef void sh_resetsig_func_t __P((int)); /* sh_vintfunc_t */
typedef int sh_ignore_func_t __P((const char *)); /* sh_icpfunc_t */
typedef int sh_assign_func_t __P((const char *)); /* sh_icpfunc_t */
typedef int sh_wassign_func_t __P((WORD_DESC *));
typedef int sh_builtin_func_t __P((WORD_LIST *)); /* sh_wlist_func_t */
+2 -1
View File
@@ -129,7 +129,8 @@ extern int errno;
#endif /* !MUST_REINSTALL_SIGHANDLERS */
/* Some systems let waitpid(2) tell callers about stopped children. */
#if !defined (WCONTINUED)
#if !defined (WCONTINUED) || defined (WCONTINUED_BROKEN)
# undef WCONTINUED
# define WCONTINUED 0
#endif
#if !defined (WIFCONTINUED)
+3 -1
View File
@@ -2178,9 +2178,11 @@ rl_menu_complete (count, ignore)
return (0);
}
match_list_index = (match_list_index + count) % match_list_size;
match_list_index += count;
if (match_list_index < 0)
match_list_index += match_list_size;
else
match_list_index %= match_list_size;
if (match_list_index == 0 && match_list_size > 1)
{
+12 -1
View File
@@ -3285,6 +3285,10 @@ read_token_word (character)
/* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
int dollar_present;
/* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
assignment. */
int compound_assignment;
/* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
int quoted;
@@ -3304,7 +3308,7 @@ read_token_word (character)
token_index = 0;
all_digit_token = DIGIT (character);
dollar_present = quoted = pass_next_character = 0;
dollar_present = quoted = pass_next_character = compound_assignment = 0;
for (;;)
{
@@ -3543,7 +3547,12 @@ read_token_word (character)
token[token_index++] = ')';
FREE (ttok);
all_digit_token = 0;
compound_assignment = 1;
#if 0
goto next_character;
#else
goto got_token; /* ksh93 seems to do this */
#endif
}
else
shell_ungetc (peek_char);
@@ -3638,6 +3647,8 @@ got_token:
the_word->flags |= W_HASDOLLAR;
if (quoted)
the_word->flags |= W_QUOTED;
if (compound_assignment)
the_word->flags |= W_COMPASSIGN;
/* A word is an assignment if it appears at the beginning of a
simple command, or after another assignment word. This is
context-dependent, so it cannot be handled in the grammar. */
+129 -20
View File
@@ -204,7 +204,10 @@ static char *remove_quoted_nulls __P((char *));
static int unquoted_substring __P((char *, char *));
static int unquoted_member __P((int, char *));
static int do_assignment_internal __P((const char *, int));
#if defined (ARRAY_VARS)
static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
#endif
static int do_assignment_internal __P((const WORD_DESC *, int));
static char *string_extract_verbatim __P((char *, int *, char *));
static char *string_extract __P((char *, int *, char *, int));
@@ -983,12 +986,28 @@ extract_process_subst (string, starter, sindex)
#endif /* PROCESS_SUBSTITUTION */
#if defined (ARRAY_VARS)
/* This can be fooled by unquoted right parens in the passed string. If
each caller verifies that the last character in STRING is a right paren,
we don't even need to call extract_delimited_string. */
char *
extract_array_assignment_list (string, sindex)
char *string;
int *sindex;
{
#if 0
return (extract_delimited_string (string, sindex, "(", (char *)NULL, ")", 0));
#else
int slen;
char *ret;
slen = strlen (string); /* ( */
if (string[slen - 1] == ')')
{
ret = substring (string, *sindex, slen - 1);
*sindex = slen - 1;
return ret;
}
#endif
}
#endif
@@ -2122,17 +2141,40 @@ list_string_with_quotes (string)
/* */
/********************************************************/
#if defined (ARRAY_VARS)
static SHELL_VAR *
do_compound_assignment (name, value, mklocal)
char *name, *value;
int mklocal;
{
SHELL_VAR *v;
int off;
if (mklocal && variable_context)
{
v = find_variable (name);
if (v == 0 || array_p (v) == 0)
v = make_local_array_variable (name);
v = assign_array_var_from_string (v, value);
}
else
v = assign_array_from_string (name, value);
return (v);
}
#endif
/* 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 parameter expansion, command substitution, and arithmetic
expansion on the right-hand side. Perform tilde expansion in any
case. Do not perform word splitting on the result of expansion. */
static int
do_assignment_internal (string, expand)
const char *string;
do_assignment_internal (word, expand)
const WORD_DESC *word;
int expand;
{
int offset;
int offset, tlen;
char *name, *value;
SHELL_VAR *entry;
#if defined (ARRAY_VARS)
@@ -2140,7 +2182,12 @@ do_assignment_internal (string, expand)
int ni;
#endif
int assign_list = 0;
const char *string;
if (word == 0 || word->word == 0)
return 0;
string = word->word;
offset = assignment (string, 0);
name = savestring (string);
value = (char *)NULL;
@@ -2151,17 +2198,21 @@ do_assignment_internal (string, expand)
name[offset] = 0;
temp = name + offset + 1;
tlen = STRLEN (temp);
#if defined (ARRAY_VARS)
if (expand && temp[0] == LPAREN && xstrchr (temp, RPAREN))
# if 0
if (expand && temp[0] == LPAREN && temp[tlen-1] == RPAREN)
#else
if (expand && (word->flags & W_COMPASSIGN))
#endif
{
assign_list = ni = 1;
value = extract_delimited_string (temp, &ni, "(", (char *)NULL, ")", 0);
value = extract_array_assignment_list (temp, &ni);
}
else
#endif
/* Perform tilde expansion. */
if (expand && temp[0])
value = expand_string_if_necessary (temp, 0, expand_string_assignment);
else
@@ -2192,7 +2243,7 @@ do_assignment_internal (string, expand)
ASSIGN_RETURN (0);
}
else if (assign_list)
entry = assign_array_from_string (name, value);
entry = do_compound_assignment (name, value, (word->flags & W_ASSIGNARG));
else
#endif /* ARRAY_VARS */
entry = bind_variable (name, value);
@@ -2207,22 +2258,39 @@ do_assignment_internal (string, expand)
}
/* Perform the assignment statement in STRING, and expand the
right side by doing command and parameter expansion. */
right side by doing tilde, command and parameter expansion. */
int
do_assignment (string)
const char *string;
char *string;
{
return do_assignment_internal (string, 1);
WORD_DESC td;
td.flags = W_ASSIGNMENT;
td.word = string;
return do_assignment_internal (&td, 1);
}
int
do_word_assignment (word)
WORD_DESC *word;
{
return do_assignment_internal (word, 1);
}
/* Given STRING, an assignment string, get the value of the right side
of the `=', and bind it to the left side. Do not do command and
parameter substitution on the right hand side. */
of the `=', and bind it to the left side. Do not perform any word
expansions on the right hand side. */
int
do_assignment_no_expand (string)
const char *string;
char *string;
{
return do_assignment_internal (string, 0);
WORD_DESC td;
td.flags = W_ASSIGNMENT;
td.word = string;
do_assignment_internal (&td, 0);
}
/***************************************************
@@ -2445,6 +2513,14 @@ expand_string_unsplit_to_string (string, quoted)
return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
}
char *
expand_assignment_string_to_string (string, quoted)
char *string;
int quoted;
{
return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
}
#if defined (COND_COMMAND)
/* Just remove backslashes in STRING. Returns a new string. */
char *
@@ -6845,8 +6921,12 @@ finished_with_string:
list = make_word_list (tword, (WORD_LIST *)NULL);
if (word->flags & W_ASSIGNMENT)
tword->flags |= W_ASSIGNMENT; /* XXX */
if (word->flags & W_COMPASSIGN)
tword->flags |= W_COMPASSIGN; /* XXX */
if (word->flags & W_NOGLOB)
tword->flags |= W_NOGLOB; /* XXX */
if (word->flags & W_NOEXPAND)
tword->flags |= W_NOEXPAND; /* XXX */
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
tword->flags |= W_QUOTED;
}
@@ -6872,8 +6952,12 @@ finished_with_string:
tword->flags |= W_QUOTED;
if (word->flags & W_ASSIGNMENT)
tword->flags |= W_ASSIGNMENT;
if (word->flags & W_COMPASSIGN)
tword->flags |= W_COMPASSIGN;
if (word->flags & W_NOGLOB)
tword->flags |= W_NOGLOB;
if (word->flags & W_NOEXPAND)
tword->flags |= W_NOEXPAND;
}
}
@@ -7435,6 +7519,31 @@ shell_expand_word_list (tlist, eflags)
next = tlist->next;
#if defined (ARRAY_VARS)
/* If this is a compound array assignment to a builtin that accepts
such assignments (e.g., `declare'), take the assignment and perform
it separately, handling the semantics of declarations inside shell
functions. This avoids the double-evaluation of such arguments,
because `declare' does some evaluation of compound assignments on
its own. */
if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
{
int t;
t = do_word_assignment (tlist->word);
if (t == 0)
{
last_command_exit_value = EXECUTION_FAILURE;
exp_jump_to_top_level (DISCARD);
}
/* Now transform the word as ksh93 appears to do and go on */
t = assignment (tlist->word->word, 0);
tlist->word->word[t] = '\0';
tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG);
}
#endif
expanded_something = 0;
expanded = expand_word_internal
(tlist->word, 0, 0, &has_dollar_at, &expanded_something);
@@ -7521,7 +7630,7 @@ expand_word_list_internal (list, eflags)
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL; /* no arithmetic errors */
tint = do_assignment (temp_list->word->word);
tint = do_word_assignment (temp_list->word);
/* Variable assignment errors in non-interactive shells
running in Posix.2 mode cause the shell to exit. */
if (tint == 0)
@@ -7569,23 +7678,23 @@ expand_word_list_internal (list, eflags)
if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
{
sh_assign_func_t *assign_func;
sh_wassign_func_t *assign_func;
/* If the remainder of the words expand to nothing, Posix.2 requires
that the variable and environment assignments affect the shell's
environment. */
assign_func = new_list ? assign_in_env : do_assignment;
assign_func = new_list ? assign_in_env : do_word_assignment;
tempenv_assign_error = 0;
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
{
this_command_name = (char *)NULL;
tint = (*assign_func) (temp_list->word->word);
tint = (*assign_func) (temp_list->word);
/* Variable assignment errors in non-interactive shells running
in Posix.2 mode cause the shell to exit. */
if (tint == 0)
{
if (assign_func == do_assignment)
if (assign_func == do_word_assignment)
{
last_command_exit_value = EXECUTION_FAILURE;
if (interactive_shell == 0 && posixly_correct)
+7 -5
View File
@@ -93,11 +93,12 @@ 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 parameter expansion, command substitution, and arithmetic
expansion on the right-hand side. Perform tilde expansion in any
case. Do not perform word splitting on the result of expansion. */
extern int do_assignment __P((const char *));
extern int do_assignment_no_expand __P((const char *));
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
@@ -144,6 +145,7 @@ extern WORD_LIST *expand_string __P((char *, int));
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));
/* De-quoted quoted characters in STRING. */
extern char *dequote_string __P((char *));
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/bash/bash-current
BUILD_DIR=/usr/local/build/chet/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+26
View File
@@ -0,0 +1,26 @@
match 1
match 2
match 3
match 4
match 1a
match 1b
match 2a
match 2b
match 3a
match 3b
match 4a
match 4b
match 5
match 6
match 7
match 8
match 9
match 10
match 11
match 12
match 13
match 14
match 15
match 16
match 17
match 18
+53
View File
@@ -0,0 +1,53 @@
shopt -s extglob
[[ ab/../ == @(ab|+([^/]))/..?(/) ]] && echo match 1
[[ ab/../ == +([^/])/..?(/) ]] && echo match 2
[[ ab/../ == @(ab|?b)/..?(/) ]] && echo match 3
[[ ab/../ == +([^/])/../ ]] && echo match 4
[[ ab/../ == +([!/])/..?(/) ]] && echo match 1a
[[ ab/../ == @(ab|+([!/]))/..?(/) ]] && echo match 1b
[[ ab/../ == +([!/])/../ ]] && echo match 2a
[[ ab/../ == +([!/])/..?(/) ]] && echo match 2b
[[ ab/../ == +([!/])/..@(/) ]] && echo match 3a
[[ ab/../ == +(ab)/..?(/) ]] && echo match 3b
[[ ab/../ == [!/][!/]/../ ]] && echo match 4a
[[ ab/../ == @(ab|?b)/..?(/) ]] && echo match 4b
[[ ab/../ == [^/][^/]/../ ]] && echo match 5
[[ ab/../ == ?b/..?(/) ]] && echo match 6
[[ ab/../ == +(?b)/..?(/) ]] && echo match 7
[[ ab/../ == +(?b|?b)/..?(/) ]] && echo match 8
[[ ab/../ == @(?b|?b)/..?(/) ]] && echo match 9
[[ ab/../ == @(a?|?b)/..?(/) ]] && echo match 10
[[ ab/../ == ?(ab)/..?(/) ]] && echo match 11
[[ ab/../ == ?(ab|??)/..?(/) ]] && echo match 12
[[ ab/../ == @(??)/..?(/) ]] && echo match 13
[[ ab/../ == @(??|a*)/..?(/) ]] && echo match 14
[[ ab/../ == @(a*)/..?(/) ]] && echo match 15
[[ ab/../ == +(??)/..?(/) ]] && echo match 16
[[ ab/../ == +(??|a*)/..?(/) ]] && echo match 17
[[ ab/../ == +(a*)/..?(/) ]] && echo match 18
+4
View File
@@ -0,0 +1,4 @@
PATH=$PATH:`pwd`
export PATH
${THIS_SH} ./extglob3.tests > /tmp/xx
diff /tmp/xx extglob3.right && rm -f /tmp/xx
+1 -1
View File
@@ -1,2 +1,2 @@
${THIS_SH} ./tilde-tests > /tmp/xx
${THIS_SH} ./tilde.tests > /tmp/xx
diff /tmp/xx tilde.right && rm -f /tmp/xx
+2
View File
@@ -0,0 +1,2 @@
${THIS_SH} ./tilde2.tests > /tmp/xx
diff /tmp/xx tilde2.right && rm -f /tmp/xx
+66
View File
@@ -0,0 +1,66 @@
# this is needed because posix mode restricts tilde expansion to assignment
# statements preceding a command, instead of the default of expanding all
# assignment statements on the line (e.g., after `export'). Without this,
# the next-to-last test fails
set +o posix
HOME=/usr/xyz
SHELL=~/bash
echo ~ch\et
echo ~/"foo"
echo "~chet"/"foo"
echo \~chet/"foo"
echo \~chet/bar
echo ~\chet/bar
echo ~chet""/bar
echo ":~chet/"
echo abcd~chet
echo "SHELL=~/bash"
echo $SHELL
echo abcd:~chet
path=/usr/ucb:/bin:~/bin:~/tmp/bin:/usr/bin
echo $path
cd /usr
cd /tmp
echo ~-
echo ~+
XPATH=/bin:/usr/bin:.
# yes tilde expansion
PPATH=$XPATH:~/bin
echo "$PPATH"
# no tilde expansion
PPATH="$XPATH:~/bin"
echo "$PPATH"
# yes tilde expansion
export PPATH=$XPATH:~/bin
echo "$PPATH"
declare -x PPATH=$XPATH:~/bin
echo "$PPATH"
# no tilde expansion
export PPATH="$XPATH:~/bin"
echo "$PPATH"
declare -x PPATH="$XPATH:~/bin"
echo "$PPATH"
# more tests of tilde expansion when executing case commands
case ~ in
$HOME) echo ok 1;;
*) echo bad 1 ;;
esac
case ~ in
~) echo ok 2 ;;
\~) echo bad 2a ;;
*) echo bad 2b ;;
esac
case $unset in
"") echo ok 3 ;;
*) echo bad 3 ;;
esac
+17
View File
@@ -0,0 +1,17 @@
PATH=~/bin:/bin:/usr/bin:.
/usr/xyz/bin:~/bin2:/bin:/usr/bin:.
PATH=~/bin:~/bin2:/bin:/usr/bin:.
~/bin
~
/usr/xyz
~
~
~
argv[1] = <\a>
argv[1] = <\a>
/usr/xyz/bash
ok
~
~
make -k FOO=/usr/xyz/mumble
/usr/xyz/mumble
+46
View File
@@ -0,0 +1,46 @@
HOME=/usr/xyz
XPATH=/bin:/usr/bin:.
ADDPATH=PATH=~/bin:$XPATH
echo $ADDPATH
unset ADDPATH
: ${ADDPATH:=~/bin:~/bin2:$XPATH}
echo $ADDPATH
unset ADDPATH
: ${ADDPATH:=PATH=~/bin:~/bin2:$XPATH}
echo $ADDPATH
cat << !
~/bin
!
echo "~"
echo ${TPATH:-~}
echo "${TPATH:-~}"
echo "${TPATH:-"~"}"
echo "${XPATH+~}"
recho "\a"
recho "${TPATH:-\a}"
SHELL=~/bash
echo $SHELL
case $SHELL in
~/bash) echo ok;;
*) echo bad;;
esac
somevar=
echo "${somevar:-~}"
echo "${somevar:-"~"}"
echo make -k FOO=~/mumble
typeset FOO=~/mumble
echo "$FOO"
+18 -5
View File
@@ -320,7 +320,7 @@ initialize_shell_variables (env, privmode)
#if defined (ARRAY_VARS)
# if 0
/* Array variables may not yet be exported. */
else if (*string == '(' && string[1] == '[' && xstrchr (string, ')'))
else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
{
string_length = 1;
temp_string = extract_array_assignment_list (string, &string_length);
@@ -1228,7 +1228,14 @@ get_bash_command (var)
{
char *p;
p = savestring (the_printed_command_except_trap);
if (the_printed_command_except_trap)
p = savestring (the_printed_command_except_trap);
else
{
p = (char *)xmalloc (1);
p[0] = '\0';
}
FREE (value_cell (var));
var_setvalue (var, p);
return (var);
@@ -2067,12 +2074,15 @@ bind_function_def (name, value)
responsible for moving the main temporary env to one of the other
temporary environments. The expansion code in subst.c calls this. */
int
assign_in_env (string)
const char *string;
assign_in_env (word)
WORD_DESC *word;
{
int offset;
char *name, *temp, *value;
SHELL_VAR *var;
const char *string;
string = word->word;
offset = assignment (string, 0);
name = savestring (string);
@@ -2092,10 +2102,13 @@ assign_in_env (string)
}
temp = name + offset + 1;
#if 0
temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
value = expand_string_unsplit_to_string (temp, 0);
free (temp);
#else
value = expand_assignment_string_to_string (temp, 0);
#endif
}
if (temporary_env == 0)
+2 -1
View File
@@ -256,7 +256,8 @@ extern SHELL_VAR *bind_variable_value __P((SHELL_VAR *, char *));
extern SHELL_VAR *bind_int_variable __P((char *, char *));
extern SHELL_VAR *bind_var_to_int __P((char *, intmax_t));
extern int assign_in_env __P((const char *));
extern int assign_in_env __P((WORD_DESC *));
extern int unbind_variable __P((const char *));
extern int unbind_func __P((const char *));
extern int unbind_function_def __P((const char *));