mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 23:53:18 +02:00
commit bash-20041005 snapshot
This commit is contained in:
+126
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -588,7 +588,6 @@ get_job_spec (list)
|
||||
switch (*word)
|
||||
{
|
||||
case 0:
|
||||
return NO_JOB;
|
||||
case '%':
|
||||
case '+':
|
||||
return (current_job);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
${THIS_SH} ./tilde2.tests > /tmp/xx
|
||||
diff /tmp/xx tilde2.right && rm -f /tmp/xx
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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 *));
|
||||
|
||||
Reference in New Issue
Block a user