commit bash-20040928 snapshot

This commit is contained in:
Chet Ramey
2011-12-03 13:37:34 -05:00
parent 43df7bbb63
commit 7a2f2783f4
18 changed files with 733 additions and 81 deletions
+126
View File
@@ -10149,3 +10149,129 @@ subst.c
execute_cmd.c
- take out calls to bash_tilde_expand before calling word expansion
functions
9/26
----
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
+1 -7
View File
@@ -731,8 +731,6 @@ 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
@@ -842,7 +840,6 @@ 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
@@ -876,7 +873,6 @@ 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
@@ -890,10 +886,8 @@ 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
+6
View File
@@ -270,6 +270,12 @@ sh_notbuiltin (s)
builtin_error (_("%s: not a shell builtin"), s);
}
void
sh_wrerror ()
{
builtin_error (_("write error: %s"), strerror (errno));
}
/* **************************************************************** */
/* */
/* Shell positional parameter manipulation */
+17 -13
View File
@@ -67,19 +67,23 @@ 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_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 */
/* 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: Thu Sep 30 22:29:05 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 Sep 30" "GNU Bash-3.0"
.\"
.\" 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
@@ -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:
@@ -5285,7 +5287,7 @@ of an \fIinputrc\fP file.
.TP
.B dump\-macros
Print all of the readline key sequences bound to macros and the
strings they ouput. If a numeric argument is supplied,
strings they output. If a numeric argument is supplied,
the output is formatted in such a way that it can be made part
of an \fIinputrc\fP file.
.TP
+9 -8
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},
@@ -4787,7 +4787,7 @@ option).
@item --dump-po-strings
A list of all double-quoted strings preceded by @samp{$}
is printed on the standard ouput
is printed on the standard output
in the @sc{gnu} @code{gettext} PO (portable object) file format.
Equivalent to @option{-D} except for the output format.
@@ -4874,7 +4874,7 @@ when invoking an interactive shell.
@item -D
A list of all double-quoted strings preceded by @samp{$}
is printed on the standard ouput.
is printed on the standard output.
These are the strings that
are subject to language translation when the current locale
is not @code{C} or @code{POSIX} (@pxref{Locale Translation}).
@@ -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{-}.
+3 -3
View File
@@ -4,7 +4,7 @@ Copyright (C) 1988-2004 Free Software Foundation, Inc.
@set EDITION 3.0
@set VERSION 3.0
@set UPDATED 11 September 2004
@set UPDATED-MONTH September 2004
@set UPDATED 2 October 2004
@set UPDATED-MONTH October 2004
@set LASTCHANGE Sat Sep 11 10:13:36 EDT 2004
@set LASTCHANGE Sat Oct 2 18:05:41 EDT 2004
+13 -5
View File
@@ -1360,14 +1360,12 @@ execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
#if defined (JOB_CONTROL)
terminate_current_pipeline ();
kill_current_pipeline ();
UNBLOCK_CHILD (oset);
#endif /* JOB_CONTROL */
last_command_exit_value = EXECUTION_FAILURE;
/* The unwind-protects installed below will take care
of closing all of the open file descriptors. */
throw_to_top_level ();
#if defined (JOB_CONTROL)
UNBLOCK_CHILD (oset);
#endif
return (EXECUTION_FAILURE); /* XXX */
}
@@ -2663,8 +2661,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);
}
}
@@ -2699,7 +2699,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
@@ -2754,9 +2754,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
-1
View File
@@ -303,7 +303,6 @@ extern char *polite_directory_format __P((char *));
extern char *extract_colon_unit __P((char *, int *));
extern void tilde_initialize __P((void));
extern int unquoted_tilde_word __P((const char *));
extern char *bash_tilde_find_word __P((const char *, int, int *));
extern char *bash_tilde_expand __P((const char *, int));
+3 -1
View File
@@ -1433,7 +1433,9 @@ make_child (command, async_p)
last_made_pid = pid;
/* Unblock SIGINT and SIGCHLD. */
/* Unblock SIGINT and SIGCHLD unless creating a pipeline, in which case
SIGCHLD remains blocked until all commands in the pipeline have been
created. */
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
}
+9 -1
View File
@@ -1543,7 +1543,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
: stat (filename, &finfo);
if (s == 0 && S_ISDIR (finfo.st_mode))
{
if (_rl_complete_mark_directories && rl_completion_suppress_append == 0)
if (_rl_complete_mark_directories /* && rl_completion_suppress_append == 0 */)
{
/* This is clumsy. Avoid putting in a double slash if point
is at the end of the line and the previous character is a
@@ -2178,9 +2178,17 @@ rl_menu_complete (count, ignore)
return (0);
}
#if 0
match_list_index = (match_list_index + count) % match_list_size;
if (match_list_index < 0)
match_list_index += match_list_size;
#else
match_list_index += count;
if (match_list_index < 0)
match_list_index += match_list_size;
else
match_list_index %= match_list_size;
#endif
if (match_list_index == 0 && match_list_size > 1)
{
+127 -22
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,17 @@ 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 (expand && temp[0] == LPAREN && temp[tlen-1] == RPAREN)
{
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 +2239,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 +2254,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 +2509,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 *
@@ -6430,8 +6502,8 @@ add_string:
if (word->flags & W_NOTILDE)
goto add_character;
if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS)) &&
(posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
string[sindex+1] == '~')
(posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
string[sindex+1] == '~')
word->flags |= W_ITILDE;
goto add_character;
@@ -6845,8 +6917,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 +6948,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 +7515,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 +7626,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 +7674,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)
+9 -5
View File
@@ -93,11 +93,11 @@ 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 *));
/* Append SOURCE to TARGET at INDEX. SIZE is the current amount
of space allocated to TARGET. SOURCE can be NULL, in which
@@ -126,6 +126,9 @@ extern int number_of_args __P((void));
takes care of quote removal. */
extern WORD_LIST *expand_string_unsplit __P((char *, int));
/* Expand the rhs of an assignment statement. */
extern WORD_LIST *expand_string_assignment __P((char *, int));
/* Expand a prompt string. */
extern WORD_LIST *expand_prompt_string __P((char *, int));
@@ -141,6 +144,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/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+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
+25 -9
View File
@@ -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);
@@ -1419,11 +1426,11 @@ initialize_dynamic_variables ()
v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
# if defined (DEBUGGER)
v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, (att_invisible|att_noassign));
v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, (att_invisible|att_noassign));
v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset);
v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset);
# endif /* DEBUGGER */
v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, (att_invisible|att_noassign));
v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, (att_invisible|att_noassign));
v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
#endif
v = init_funcname_var ();
@@ -1599,7 +1606,10 @@ make_local_variable (name)
/* local foo; local foo; is a no-op. */
old_var = find_variable (name);
if (old_var && local_p (old_var) && old_var->context == variable_context)
return (old_var);
{
VUNSETATTR (old_var, att_invisible);
return (old_var);
}
was_tmpvar = old_var && tempvar_p (old_var);
if (was_tmpvar)
@@ -2064,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);
@@ -2089,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)
+359
View File
@@ -0,0 +1,359 @@
/* variables.h -- data structures for shell variables. */
/* 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. */
#if !defined (_VARIABLES_H_)
#define _VARIABLES_H_
#include "stdc.h"
#include "array.h"
/* Shell variables and functions are stored in hash tables. */
#include "hashlib.h"
#include "conftypes.h"
/* A variable context. */
typedef struct var_context {
char *name; /* empty or NULL means global context */
int scope; /* 0 means global context */
int flags;
struct var_context *up; /* previous function calls */
struct var_context *down; /* down towards global context */
HASH_TABLE *table; /* variables at this scope */
} VAR_CONTEXT;
/* Flags for var_context->flags */
#define VC_HASLOCAL 0x01
#define VC_HASTMPVAR 0x02
#define VC_FUNCENV 0x04 /* also function if name != NULL */
#define VC_BLTNENV 0x08 /* builtin_env */
#define VC_TEMPENV 0x10 /* temporary_env */
#define VC_TEMPFLAGS (VC_FUNCENV|VC_BLTNENV|VC_TEMPENV)
/* Accessing macros */
#define vc_isfuncenv(vc) (((vc)->flags & VC_FUNCENV) != 0)
#define vc_isbltnenv(vc) (((vc)->flags & VC_BLTNENV) != 0)
#define vc_istempenv(vc) (((vc)->flags & (VC_TEMPFLAGS)) == VC_TEMPENV)
#define vc_istempscope(vc) (((vc)->flags & (VC_TEMPENV|VC_BLTNENV)) != 0)
#define vc_haslocals(vc) (((vc)->flags & VC_HASLOCAL) != 0)
#define vc_hastmpvars(vc) (((vc)->flags & VC_HASTMPVAR) != 0)
/* What a shell variable looks like. */
typedef struct variable *sh_var_value_func_t __P((struct variable *));
typedef struct variable *sh_var_assign_func_t __P((struct variable *, char *, arrayind_t));
/* For the future */
union _value {
char *s; /* string value */
intmax_t i; /* int value */
COMMAND *f; /* function */
ARRAY *a; /* array */
HASH_TABLE *h; /* associative array */
double d; /* floating point number */
#if defined (HAVE_LONG_DOUBLE)
long double ld; /* long double */
#endif
struct variable *v; /* possible indirect variable use */
void *opaque; /* opaque data for future use */
};
typedef struct variable {
char *name; /* Symbol that the user types. */
char *value; /* Value that is returned. */
char *exportstr; /* String for the environment. */
sh_var_value_func_t *dynamic_value; /* Function called to return a `dynamic'
value for a variable, like $SECONDS
or $RANDOM. */
sh_var_assign_func_t *assign_func; /* Function called when this `special
variable' is assigned a value in
bind_variable. */
int attributes; /* export, readonly, array, invisible... */
int context; /* Which context this variable belongs to. */
} SHELL_VAR;
typedef struct _vlist {
SHELL_VAR **list;
int list_size; /* allocated size */
int list_len; /* current number of entries */
} VARLIST;
/* The various attributes that a given variable can have. */
/* First, the user-visible attributes */
#define att_exported 0x0000001 /* export to environment */
#define att_readonly 0x0000002 /* cannot change */
#define att_array 0x0000004 /* value is an array */
#define att_function 0x0000008 /* value is a function */
#define att_integer 0x0000010 /* internal representation is int */
#define att_local 0x0000020 /* variable is local to a function */
#define att_assoc 0x0000040 /* variable is an associative array */
#define att_trace 0x0000080 /* function is traced with DEBUG trap */
#define attmask_user 0x0000fff
/* Internal attributes used for bookkeeping */
#define att_invisible 0x0001000 /* cannot see */
#define att_nounset 0x0002000 /* cannot unset */
#define att_noassign 0x0004000 /* assignment not allowed */
#define att_imported 0x0008000 /* came from environment */
#define att_special 0x0010000 /* requires special handling */
#define attmask_int 0x00ff000
/* Internal attributes used for variable scoping. */
#define att_tempvar 0x0100000 /* variable came from the temp environment */
#define att_propagate 0x0200000 /* propagate to previous scope */
#define attmask_scope 0x0f00000
#define exported_p(var) ((((var)->attributes) & (att_exported)))
#define readonly_p(var) ((((var)->attributes) & (att_readonly)))
#define array_p(var) ((((var)->attributes) & (att_array)))
#define function_p(var) ((((var)->attributes) & (att_function)))
#define integer_p(var) ((((var)->attributes) & (att_integer)))
#define local_p(var) ((((var)->attributes) & (att_local)))
#define assoc_p(var) ((((var)->attributes) & (att_assoc)))
#define trace_p(var) ((((var)->attributes) & (att_trace)))
#define invisible_p(var) ((((var)->attributes) & (att_invisible)))
#define non_unsettable_p(var) ((((var)->attributes) & (att_nounset)))
#define noassign_p(var) ((((var)->attributes) & (att_noassign)))
#define imported_p(var) ((((var)->attributes) & (att_imported)))
#define specialvar_p(var) ((((var)->attributes) & (att_special)))
#define tempvar_p(var) ((((var)->attributes) & (att_tempvar)))
/* Acessing variable values: rvalues */
#define value_cell(var) ((var)->value)
#define function_cell(var) (COMMAND *)((var)->value)
#define array_cell(var) (ARRAY *)((var)->value)
#define var_isnull(var) ((var)->value == 0)
#define var_isset(var) ((var)->value != 0)
/* Assigning variable values: lvalues */
#define var_setvalue(var, str) ((var)->value = (str))
#define var_setfunc(var, func) ((var)->value = (char *)(func))
#define var_setarray(var, arr) ((var)->value = (char *)(arr))
/* Make VAR be auto-exported. */
#define set_auto_export(var) \
do { (var)->attributes |= att_exported; array_needs_making = 1; } while (0)
#define SETVARATTR(var, attr, undo) \
((undo == 0) ? ((var)->attributes |= (attr)) \
: ((var)->attributes &= ~(attr)))
#define VSETATTR(var, attr) ((var)->attributes |= (attr))
#define VUNSETATTR(var, attr) ((var)->attributes &= ~(attr))
#define VGETFLAGS(var) ((var)->attributes)
#define VSETFLAGS(var, flags) ((var)->attributes = (flags))
#define VCLRFLAGS(var) ((var)->attributes = 0)
/* Macros to perform various operations on `exportstr' member of a SHELL_VAR. */
#define CLEAR_EXPORTSTR(var) (var)->exportstr = (char *)NULL
#define COPY_EXPORTSTR(var) ((var)->exportstr) ? savestring ((var)->exportstr) : (char *)NULL
#define SET_EXPORTSTR(var, value) (var)->exportstr = (value)
#define SAVE_EXPORTSTR(var, value) (var)->exportstr = (value) ? savestring (value) : (char *)NULL
#define FREE_EXPORTSTR(var) \
do { if ((var)->exportstr) free ((var)->exportstr); } while (0)
#define CACHE_IMPORTSTR(var, value) \
(var)->exportstr = savestring (value)
#define INVALIDATE_EXPORTSTR(var) \
do { \
if ((var)->exportstr) \
{ \
free ((var)->exportstr); \
(var)->exportstr = (char *)NULL; \
} \
} while (0)
/* Stuff for hacking variables. */
typedef int sh_var_map_func_t __P((SHELL_VAR *));
/* Where we keep the variables and functions */
extern VAR_CONTEXT *global_variables;
extern VAR_CONTEXT *shell_variables;
extern HASH_TABLE *shell_functions;
extern HASH_TABLE *temporary_env;
extern int variable_context;
extern char *dollar_vars[];
extern char **export_env;
extern void initialize_shell_variables __P((char **, int));
extern SHELL_VAR *set_if_not __P((char *, char *));
extern void sh_set_lines_and_columns __P((int, int));
extern void set_pwd __P((void));
extern void set_ppid __P((void));
extern void make_funcname_visible __P((int));
extern SHELL_VAR *var_lookup __P((const char *, VAR_CONTEXT *));
extern SHELL_VAR *find_function __P((const char *));
extern FUNCTION_DEF *find_function_def __P((const char *));
extern SHELL_VAR *find_variable __P((const char *));
extern SHELL_VAR *find_variable_internal __P((const char *, int));
extern SHELL_VAR *find_tempenv_variable __P((const char *));
extern SHELL_VAR *copy_variable __P((SHELL_VAR *));
extern SHELL_VAR *make_local_variable __P((const char *));
extern SHELL_VAR *bind_variable __P((const char *, char *));
extern SHELL_VAR *bind_function __P((const char *, COMMAND *));
extern void bind_function_def __P((const char *, FUNCTION_DEF *));
extern SHELL_VAR **map_over __P((sh_var_map_func_t *, VAR_CONTEXT *));
SHELL_VAR **map_over_funcs __P((sh_var_map_func_t *));
extern SHELL_VAR **all_shell_variables __P((void));
extern SHELL_VAR **all_shell_functions __P((void));
extern SHELL_VAR **all_visible_variables __P((void));
extern SHELL_VAR **all_visible_functions __P((void));
extern SHELL_VAR **all_exported_variables __P((void));
extern SHELL_VAR **local_exported_variables __P((void));
extern SHELL_VAR **all_local_variables __P((void));
#if defined (ARRAY_VARS)
extern SHELL_VAR **all_array_variables __P((void));
#endif
extern char **all_variables_matching_prefix __P((const char *));
extern char **make_var_array __P((HASH_TABLE *));
extern char **add_or_supercede_exported_var __P((char *, int));
extern char *get_variable_value __P((SHELL_VAR *));
extern char *get_string_value __P((const char *));
extern char *sh_get_env_value __P((const char *));
extern char *make_variable_value __P((SHELL_VAR *, char *));
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 unbind_variable __P((const char *));
extern int unbind_func __P((const char *));
extern int unbind_function_def __P((const char *));
extern int makunbound __P((const char *, VAR_CONTEXT *));
extern int kill_local_variable __P((const char *));
extern void delete_all_variables __P((HASH_TABLE *));
extern void delete_all_contexts __P((VAR_CONTEXT *));
extern VAR_CONTEXT *new_var_context __P((char *, int));
extern void dispose_var_context __P((VAR_CONTEXT *));
extern VAR_CONTEXT *push_var_context __P((char *, int, HASH_TABLE *));
extern void pop_var_context __P((void));
extern VAR_CONTEXT *push_scope __P((int, HASH_TABLE *));
extern void pop_scope __P((int));
extern void push_context __P((char *, int, HASH_TABLE *));
extern void pop_context __P((void));
extern void push_dollar_vars __P((void));
extern void pop_dollar_vars __P((void));
extern void dispose_saved_dollar_vars __P((void));
extern void push_args __P((WORD_LIST *));
extern void pop_args __P((void));
extern void adjust_shell_level __P((int));
extern void non_unsettable __P((char *));
extern void dispose_variable __P((SHELL_VAR *));
extern void dispose_used_env_vars __P((void));
extern void dispose_function_env __P((void));
extern void dispose_builtin_env __P((void));
extern void merge_temporary_env __P((void));
extern void merge_builtin_env __P((void));
extern void kill_all_local_variables __P((void));
extern void set_var_read_only __P((char *));
extern void set_func_read_only __P((const char *));
extern void set_var_auto_export __P((char *));
extern void set_func_auto_export __P((const char *));
extern void sort_variables __P((SHELL_VAR **));
extern void maybe_make_export_env __P((void));
extern void update_export_env_inplace __P((char *, int, char *));
extern void put_command_name_into_env __P((char *));
extern void put_gnu_argv_flags_into_env __P((intmax_t, char *));
extern void print_var_list __P((SHELL_VAR **));
extern void print_func_list __P((SHELL_VAR **));
extern void print_assignment __P((SHELL_VAR *));
extern void print_var_value __P((SHELL_VAR *, int));
extern void print_var_function __P((SHELL_VAR *));
#if defined (ARRAY_VARS)
extern SHELL_VAR *make_new_array_variable __P((char *));
extern SHELL_VAR *make_local_array_variable __P((char *));
extern void set_pipestatus_array __P((int *, int));
#endif
extern void set_pipestatus_from_exit __P((int));
/* The variable in NAME has just had its state changed. Check to see if it
is one of the special ones where something special happens. */
extern void stupidly_hack_special_variables __P((char *));
extern int get_random_number __P((void));
/* The `special variable' functions that get called when a particular
variable is set. */
extern void sv_ifs __P((char *));
extern void sv_path __P((char *));
extern void sv_mail __P((char *));
extern void sv_globignore __P((char *));
extern void sv_ignoreeof __P((char *));
extern void sv_strict_posix __P((char *));
extern void sv_optind __P((char *));
extern void sv_opterr __P((char *));
extern void sv_locale __P((char *));
#if defined (READLINE)
extern void sv_comp_wordbreaks __P((char *));
extern void sv_terminal __P((char *));
extern void sv_hostfile __P((char *));
#endif
#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
extern void sv_tz __P((char *));
#endif
#if defined (HISTORY)
extern void sv_histsize __P((char *));
extern void sv_histignore __P((char *));
extern void sv_history_control __P((char *));
# if defined (BANG_HISTORY)
extern void sv_histchars __P((char *));
# endif
extern void sv_histtimefmt __P((char *));
#endif /* HISTORY */
#endif /* !_VARIABLES_H_ */
+18
View File
@@ -0,0 +1,18 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#ifndef errno
extern int errno;
#endif
main()
{
int x;
x = waitpid(-1, (int *)0, WNOHANG|WCONTINUED);
if (x == -1 && errno == ECHILD)
exit (0);
else
exit (1);
}