mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-23 13:57:58 +02:00
commit bash-20040928 snapshot
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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_ */
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user