mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-29 00:19:51 +02:00
commit bash-20080605 snapshot
This commit is contained in:
@@ -15989,3 +15989,82 @@ parse.y
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document the effect of setting PROMPT_DIRTRIM
|
||||
|
||||
6/3
|
||||
---
|
||||
builtins/ulimit.def
|
||||
- make the multiplier (block size) for -c and -f 512 bytes only if in
|
||||
Posix mode and 1024 bytes otherwise (as in previous versions). Uses
|
||||
POSIXBLK and BLOCK_SIZE defines to parameterize size based on value
|
||||
of posixly_correct
|
||||
|
||||
doc/bashref.texi
|
||||
- document this addition to posix mode
|
||||
|
||||
builtins/common.c
|
||||
- change get_numeric_arg to have a calling sequence and return value
|
||||
more closely mimicking general.c:legal_number(), with the addition
|
||||
of a flags word
|
||||
- add extra value for `fatal' argument to get_numeric_arg to force it
|
||||
to return failure to the caller rather than longjmping
|
||||
|
||||
builtins/common.h
|
||||
- change prototype declaration for get_numeric_arg
|
||||
|
||||
builtins/{break,shift}.def
|
||||
- change calls to get_numeric_arg to deal with new semantics and calling
|
||||
sequence
|
||||
|
||||
builtins/history.def
|
||||
- display_history now returns an int
|
||||
- change calling sequence for get_numeric_arg in display_history
|
||||
- display_history now returns failure to the caller if get_numeric_arg
|
||||
detects an invalid number, rather than jumping back to the top level
|
||||
- use value returned by display_history as return status of history
|
||||
builtin, filtered through sh_chkwrite
|
||||
- history no longer aborts compound commands on invalid arguments.
|
||||
fixes problem reported by Chu Li <chul@cn.fujitsu.com>
|
||||
|
||||
{braces,subst}.c
|
||||
- extract_command_subst now takes a third flags argument; passed flags
|
||||
are ORd into flags passed to other functions; changed callers
|
||||
|
||||
subst.h
|
||||
- move SX_* defines here from subst.c so parse.y:xparse_dolparen can
|
||||
see them and behave appropriately
|
||||
- extract_command_subst now takes a third flags argument; change
|
||||
prototype
|
||||
|
||||
subst.c
|
||||
- change extract_command_subst to call xparse_dolparen when extracting
|
||||
a $() construct
|
||||
- change calls to extract_delimited_string to extract_command_subst
|
||||
as appropriate
|
||||
- if command_substitute returns a NULL word desc, don't call
|
||||
dispose_word_desc on it
|
||||
|
||||
parse.y
|
||||
- change xparse_dolparen to use the SX_* flags now in subst.h
|
||||
|
||||
6/16
|
||||
----
|
||||
subst.c
|
||||
- in quote_list, set W_HASQUOTEDNULL flag in the word if quote_string
|
||||
turns "" into CTLNUL
|
||||
- in dequote_list, turn off W_HASQUOTEDNULL flag in the word if
|
||||
dequote_string turns CTLNUL into ""
|
||||
- new function, string_list_pos_params, encapsulates everything
|
||||
needed to turn the positional parameters or an array indexed with
|
||||
'@' or '*' into a string, including taking care of quoting and
|
||||
using the first char of $IFS, when used in another expansion like
|
||||
pattern removal or pattern substitution
|
||||
- change list_remove_pattern, pos_params, pos_params_pat_subst to
|
||||
call string_list_pos_params. Fixes problems reported by
|
||||
Stephane Chazelas <stephane_chazelas@yahoo.fr>
|
||||
|
||||
6/22
|
||||
----
|
||||
variables.h
|
||||
- include assoc.h for associative arrays
|
||||
- defines for case-modifying expansions and associative array variables
|
||||
- sh_var_assign_func_t functions now take an extra char * parameter
|
||||
|
||||
@@ -15979,3 +15979,85 @@ parse.y
|
||||
substitution. From bash-4.0-devel branch
|
||||
- changes to parse_matched_pair to combine most of the flag variables
|
||||
(was_dollar, in_comment, and so on) into a local flags word
|
||||
|
||||
6/2
|
||||
---
|
||||
parse.y
|
||||
- call trim_pathname, which retains only the last $PROMPT_DIRTRIM
|
||||
directories and replaces the intervening characters with `...',
|
||||
when expanding \w and \W
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document the effect of setting PROMPT_DIRTRIM
|
||||
|
||||
6/3
|
||||
---
|
||||
builtins/ulimit.def
|
||||
- make the multiplier (block size) for -c and -f 512 bytes only if in
|
||||
Posix mode and 1024 bytes otherwise (as in previous versions). Uses
|
||||
POSIXBLK and BLOCK_SIZE defines to parameterize size based on value
|
||||
of posixly_correct
|
||||
|
||||
doc/bashref.texi
|
||||
- document this addition to posix mode
|
||||
|
||||
builtins/common.c
|
||||
- change get_numeric_arg to have a calling sequence and return value
|
||||
more closely mimicking general.c:legal_number(), with the addition
|
||||
of a flags word
|
||||
- add extra value for `fatal' argument to get_numeric_arg to force it
|
||||
to return failure to the caller rather than longjmping
|
||||
|
||||
builtins/common.h
|
||||
- change prototype declaration for get_numeric_arg
|
||||
|
||||
builtins/{break,shift}.def
|
||||
- change calls to get_numeric_arg to deal with new semantics and calling
|
||||
sequence
|
||||
|
||||
builtins/history.def
|
||||
- display_history now returns an int
|
||||
- change calling sequence for get_numeric_arg in display_history
|
||||
- display_history now returns failure to the caller if get_numeric_arg
|
||||
detects an invalid number, rather than jumping back to the top level
|
||||
- use value returned by display_history as return status of history
|
||||
builtin, filtered through sh_chkwrite
|
||||
- history no longer aborts compound commands on invalid arguments.
|
||||
fixes problem reported by Chu Li <chul@cn.fujitsu.com>
|
||||
|
||||
{braces,subst}.c
|
||||
- extract_command_subst now takes a third flags argument; passed flags
|
||||
are ORd into flags passed to other functions; changed callers
|
||||
|
||||
subst.h
|
||||
- move SX_* defines here from subst.c so parse.y:xparse_dolparen can
|
||||
see them and behave appropriately
|
||||
- extract_command_subst now takes a third flags argument; change
|
||||
prototype
|
||||
|
||||
subst.c
|
||||
- change extract_command_subst to call xparse_dolparen when extracting
|
||||
a $() construct
|
||||
- change calls to extract_delimited_string to extract_command_subst
|
||||
as appropriate
|
||||
- if command_substitute returns a NULL word desc, don't call
|
||||
dispose_word_desc on it
|
||||
|
||||
parse.y
|
||||
- change xparse_dolparen to use the SX_* flags now in subst.h
|
||||
|
||||
6/16
|
||||
----
|
||||
subst.c
|
||||
- in quote_list, set W_HASQUOTEDNULL flag in the word if quote_string
|
||||
turns "" into CTLNUL
|
||||
- in dequote_list, turn off W_HASQUOTEDNULL flag in the word if
|
||||
dequote_string turns CTLNUL into ""
|
||||
- new function, string_list_pos_params, encapsulates everything
|
||||
needed to turn the positional parameters or an array indexed with
|
||||
'@' or '*' into a string, including taking care of quoting and
|
||||
using the first char of $IFS, when used in another expansion like
|
||||
pattern removal or pattern substitution
|
||||
- change list_remove_pattern, pos_params, pos_params_pat_subst to
|
||||
call string_list_pos_params. Fixes problems reported by
|
||||
Stephane Chazelas <stephane_chazelas@yahoo.fr>
|
||||
|
||||
@@ -763,6 +763,9 @@ tests/case.tests f
|
||||
tests/case.right f
|
||||
tests/comsub.tests f
|
||||
tests/comsub.right f
|
||||
tests/comsub-posix.tests f
|
||||
tests/comsub-posix.right f
|
||||
tests/comsub-posix1.sub f
|
||||
tests/cond.tests f
|
||||
tests/cond.right f
|
||||
tests/cond-regexp.sub f
|
||||
@@ -925,6 +928,7 @@ tests/run-braces f
|
||||
tests/run-builtins f
|
||||
tests/run-case f
|
||||
tests/run-comsub f
|
||||
tests/run-comsub-posix f
|
||||
tests/run-cond f
|
||||
tests/run-cprint f
|
||||
tests/run-dbg-support f
|
||||
|
||||
@@ -759,8 +759,12 @@ tests/source3.sub f
|
||||
tests/source4.sub f
|
||||
tests/source5.sub f
|
||||
tests/source6.sub f
|
||||
tests/case.tests f
|
||||
tests/case.right f
|
||||
tests/comsub.tests f
|
||||
tests/comsub.right f
|
||||
tests/comsub-posix.tests f
|
||||
tests/comsub-posix.right f
|
||||
tests/cond.tests f
|
||||
tests/cond.right f
|
||||
tests/cond-regexp.sub f
|
||||
@@ -921,7 +925,9 @@ tests/run-array f
|
||||
tests/run-array2 f
|
||||
tests/run-braces f
|
||||
tests/run-builtins f
|
||||
tests/run-case f
|
||||
tests/run-comsub f
|
||||
tests/run-comsub-posix f
|
||||
tests/run-cond f
|
||||
tests/run-cprint f
|
||||
tests/run-dbg-support f
|
||||
|
||||
@@ -538,7 +538,7 @@ brace_gobbler (text, tlen, indx, satisfy)
|
||||
if ((c == '$' || c == '<' || c == '>') && text[i+1] == '(') /* ) */
|
||||
{
|
||||
si = i + 2;
|
||||
t = extract_command_subst (text, &si);
|
||||
t = extract_command_subst (text, &si, 0);
|
||||
i = si;
|
||||
free (t);
|
||||
i++;
|
||||
|
||||
+2
-2
@@ -71,7 +71,7 @@ break_builtin (list)
|
||||
if (check_loop_level () == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
newbreak = get_numeric_arg (list, 1);
|
||||
(void)get_numeric_arg (list, 1, &newbreak);
|
||||
|
||||
if (newbreak <= 0)
|
||||
{
|
||||
@@ -111,7 +111,7 @@ continue_builtin (list)
|
||||
if (check_loop_level () == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
newcont = get_numeric_arg (list, 1);
|
||||
(void)get_numeric_arg (list, 1, &newcont);
|
||||
|
||||
if (newcont <= 0)
|
||||
{
|
||||
|
||||
+18
-13
@@ -399,30 +399,35 @@ set_dollar_vars_changed ()
|
||||
/* Read a numeric arg for this_command_name, the name of the shell builtin
|
||||
that wants it. LIST is the word list that the arg is to come from.
|
||||
Accept only the numeric argument; report an error if other arguments
|
||||
follow. If FATAL is true, call throw_to_top_level, which exits the
|
||||
shell; if not, call jump_to_top_level (DISCARD), which aborts the
|
||||
current command. */
|
||||
intmax_t
|
||||
get_numeric_arg (list, fatal)
|
||||
follow. If FATAL is 1, call throw_to_top_level, which exits the
|
||||
shell; if it's 2, call jump_to_top_level (DISCARD), which aborts the
|
||||
current command; if FATAL is 0, return an indication of an invalid
|
||||
number by setting *NUMOK == 0 and return -1. */
|
||||
int
|
||||
get_numeric_arg (list, fatal, count)
|
||||
WORD_LIST *list;
|
||||
int fatal;
|
||||
intmax_t *count;
|
||||
{
|
||||
intmax_t count = 1;
|
||||
char *arg;
|
||||
|
||||
if (count)
|
||||
*count = 1;
|
||||
|
||||
if (list && list->word && ISOPTION (list->word->word, '-'))
|
||||
list = list->next;
|
||||
|
||||
if (list)
|
||||
{
|
||||
register char *arg;
|
||||
|
||||
arg = list->word->word;
|
||||
if (arg == 0 || (legal_number (arg, &count) == 0))
|
||||
if (arg == 0 || (legal_number (arg, count) == 0))
|
||||
{
|
||||
sh_neednumarg (list->word->word);
|
||||
if (fatal)
|
||||
sh_neednumarg (list->word->word ? list->word->word : "`'");
|
||||
if (fatal == 0)
|
||||
return 0;
|
||||
else if (fatal == 1) /* fatal == 1; abort */
|
||||
throw_to_top_level ();
|
||||
else
|
||||
else /* fatal == 2; discard current command */
|
||||
{
|
||||
top_level_cleanup ();
|
||||
jump_to_top_level (DISCARD);
|
||||
@@ -431,7 +436,7 @@ get_numeric_arg (list, fatal)
|
||||
no_args (list->next);
|
||||
}
|
||||
|
||||
return (count);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Get an eight-bit status value from LIST */
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ extern int dollar_vars_changed __P((void));
|
||||
extern void set_dollar_vars_unchanged __P((void));
|
||||
extern void set_dollar_vars_changed __P((void));
|
||||
|
||||
extern intmax_t get_numeric_arg __P((WORD_LIST *, int));
|
||||
extern int get_numeric_arg __P((WORD_LIST *, int, intmax_t *));
|
||||
extern int get_exitstat __P((WORD_LIST *));
|
||||
extern int read_octal __P((char *));
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ extern int current_command_line_count;
|
||||
extern int force_append_history; /* shopt -s histappend */
|
||||
|
||||
static char *histtime __P((HIST_ENTRY *, const char *));
|
||||
static void display_history __P((WORD_LIST *));
|
||||
static int display_history __P((WORD_LIST *));
|
||||
static void push_history __P((WORD_LIST *));
|
||||
static int expand_and_print_history __P((WORD_LIST *));
|
||||
|
||||
@@ -197,8 +197,8 @@ history_builtin (list)
|
||||
}
|
||||
else if ((flags & (AFLAG|RFLAG|NFLAG|WFLAG|CFLAG)) == 0)
|
||||
{
|
||||
display_history (list);
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
result = display_history (list);
|
||||
return (sh_chkwrite (result));
|
||||
}
|
||||
|
||||
filename = list ? list->word->word : get_string_value ("HISTFILE");
|
||||
@@ -260,7 +260,7 @@ histtime (hlist, histtimefmt)
|
||||
return timestr;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
display_history (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
@@ -271,7 +271,9 @@ display_history (list)
|
||||
|
||||
if (list)
|
||||
{
|
||||
limit = get_numeric_arg (list, 0);
|
||||
if (get_numeric_arg (list, 0, &limit) == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
if (limit < 0)
|
||||
limit = -limit;
|
||||
}
|
||||
@@ -305,6 +307,8 @@ display_history (list)
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* Remove the last entry in the history list and add each argument in
|
||||
|
||||
+3
-2
@@ -51,7 +51,8 @@ Options:
|
||||
-t timeout time out and return failure if a complete line of input is
|
||||
not read withint TIMEOUT seconds. The value of the TMOUT
|
||||
variable is the default timeout. TIMEOUT may be a
|
||||
fractional number.
|
||||
fractional number. The exit status is greater than 128 if
|
||||
the timeout is exceeded
|
||||
-u fd read from file descriptor FD instead of the standard input
|
||||
|
||||
Exit Status:
|
||||
@@ -374,7 +375,7 @@ read_builtin (list)
|
||||
return (EXECUTION_FAILURE);
|
||||
#else
|
||||
input_string[i] = '\0'; /* make sure it's terminated */
|
||||
retval = EXECUTION_FAILURE;
|
||||
retval = 128+SIGALRM;;
|
||||
goto assign_vars;
|
||||
#endif
|
||||
}
|
||||
|
||||
+1
-1
@@ -573,7 +573,7 @@ add_char:
|
||||
if (tmsec > 0 || tmusec > 0)
|
||||
reset_alarm ();
|
||||
|
||||
< if (nchars > 0 || delim != '\n')
|
||||
if (nchars > 0 || delim != '\n')
|
||||
{
|
||||
#if defined (READLINE)
|
||||
if (edit)
|
||||
|
||||
+2
-1
@@ -62,7 +62,8 @@ shift_builtin (list)
|
||||
register int count;
|
||||
WORD_LIST *temp;
|
||||
|
||||
times = get_numeric_arg (list, 0);
|
||||
if (get_numeric_arg (list, 0, ×) == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
if (times == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
+12
-4
@@ -179,6 +179,14 @@ extern int errno;
|
||||
#define LIMIT_HARD 0x01
|
||||
#define LIMIT_SOFT 0x02
|
||||
|
||||
/* "Blocks" are defined as 512 bytes when in Posix mode and 1024 bytes
|
||||
otherwise. */
|
||||
#define POSIXBLK -2
|
||||
|
||||
#define BLOCKSIZE(x) (((x) == POSIXBLK && posixly_correct) ? 512 : 1024)
|
||||
|
||||
extern int posixly_correct;
|
||||
|
||||
static int _findlim __P((int));
|
||||
|
||||
static int ulimit_internal __P((int, char *, int, int));
|
||||
@@ -212,7 +220,7 @@ static RESOURCE_LIMITS limits[] = {
|
||||
{ 'b', RLIMIT_SBSIZE, 1, "socket buffer size", "bytes" },
|
||||
#endif
|
||||
#ifdef RLIMIT_CORE
|
||||
{ 'c', RLIMIT_CORE, 512, "core file size", "blocks" },
|
||||
{ 'c', RLIMIT_CORE, POSIXBLK, "core file size", "blocks" },
|
||||
#endif
|
||||
#ifdef RLIMIT_DATA
|
||||
{ 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
|
||||
@@ -220,7 +228,7 @@ static RESOURCE_LIMITS limits[] = {
|
||||
#ifdef RLIMIT_NICE
|
||||
{ 'e', RLIMIT_NICE, 1, "scheduling priority", (char *)NULL },
|
||||
#endif
|
||||
{ 'f', RLIMIT_FILESIZE, 512, "file size", "blocks" },
|
||||
{ 'f', RLIMIT_FILESIZE, POSIXBLK, "file size", "blocks" },
|
||||
#ifdef RLIMIT_SIGPENDING
|
||||
{ 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL },
|
||||
#endif
|
||||
@@ -438,7 +446,7 @@ ulimit_internal (cmd, cmdarg, mode, multiple)
|
||||
else if (all_digits (cmdarg))
|
||||
{
|
||||
limit = string_to_rlimtype (cmdarg);
|
||||
block_factor = limits[limind].block_factor;
|
||||
block_factor = BLOCKSIZE(limits[limind].block_factor);
|
||||
real_limit = limit * block_factor;
|
||||
|
||||
if ((real_limit / block_factor) != limit)
|
||||
@@ -702,7 +710,7 @@ printone (limind, curlim, pdesc)
|
||||
char unitstr[64];
|
||||
int factor;
|
||||
|
||||
factor = limits[limind].block_factor;
|
||||
factor = BLOCKSIZE(limits[limind].block_factor);
|
||||
if (pdesc)
|
||||
{
|
||||
if (limits[limind].units)
|
||||
|
||||
+15
-4
@@ -61,6 +61,9 @@ no option is given, then -f is assumed.
|
||||
Values are in 1024-byte increments, except for -t, which is in seconds,
|
||||
-p, which is in increments of 512 bytes, and -u, which is an unscaled
|
||||
number of processes.
|
||||
|
||||
Exit Status:
|
||||
Returns success unless an invalid option is supplied or an error occurs.
|
||||
$END
|
||||
|
||||
#if !defined (_MINIX)
|
||||
@@ -176,6 +179,14 @@ extern int errno;
|
||||
#define LIMIT_HARD 0x01
|
||||
#define LIMIT_SOFT 0x02
|
||||
|
||||
/* "Blocks" are defined as 512 bytes when in Posix mode and 1024 bytes
|
||||
otherwise. */
|
||||
#define POSIXBLK -2
|
||||
|
||||
#define BLOCKSIZE(x) (((x) == POSIXBLK && posixly_correct) ? 512 : (x))
|
||||
|
||||
extern int posixly_correct;
|
||||
|
||||
static int _findlim __P((int));
|
||||
|
||||
static int ulimit_internal __P((int, char *, int, int));
|
||||
@@ -209,7 +220,7 @@ static RESOURCE_LIMITS limits[] = {
|
||||
{ 'b', RLIMIT_SBSIZE, 1, "socket buffer size", "bytes" },
|
||||
#endif
|
||||
#ifdef RLIMIT_CORE
|
||||
{ 'c', RLIMIT_CORE, 512, "core file size", "blocks" },
|
||||
{ 'c', RLIMIT_CORE, POSIXBLK, "core file size", "blocks" },
|
||||
#endif
|
||||
#ifdef RLIMIT_DATA
|
||||
{ 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
|
||||
@@ -217,7 +228,7 @@ static RESOURCE_LIMITS limits[] = {
|
||||
#ifdef RLIMIT_NICE
|
||||
{ 'e', RLIMIT_NICE, 1, "scheduling priority", (char *)NULL },
|
||||
#endif
|
||||
{ 'f', RLIMIT_FILESIZE, 512, "file size", "blocks" },
|
||||
{ 'f', RLIMIT_FILESIZE, POSIXBLK, "file size", "blocks" },
|
||||
#ifdef RLIMIT_SIGPENDING
|
||||
{ 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL },
|
||||
#endif
|
||||
@@ -435,7 +446,7 @@ ulimit_internal (cmd, cmdarg, mode, multiple)
|
||||
else if (all_digits (cmdarg))
|
||||
{
|
||||
limit = string_to_rlimtype (cmdarg);
|
||||
block_factor = limits[limind].block_factor;
|
||||
block_factor = BLOCKSIZE(limits[limind].block_factor);
|
||||
real_limit = limit * block_factor;
|
||||
|
||||
if ((real_limit / block_factor) != limit)
|
||||
@@ -699,7 +710,7 @@ printone (limind, curlim, pdesc)
|
||||
char unitstr[64];
|
||||
int factor;
|
||||
|
||||
factor = limits[limind].block_factor;
|
||||
factor = BLOCKSIZE(limits[limind].block_factor);
|
||||
if (pdesc)
|
||||
{
|
||||
if (limits[limind].units)
|
||||
|
||||
+6
-2
@@ -4242,6 +4242,8 @@ The
|
||||
.I "previous job"
|
||||
may be referenced using
|
||||
.BR %\- .
|
||||
If there is only a single job, \fB%+\fP and \fB%\-\fP can both be used
|
||||
to refer to that job.
|
||||
In output pertaining to jobs (e.g., the output of the
|
||||
.B jobs
|
||||
command), the current job is always flagged with a
|
||||
@@ -7749,8 +7751,10 @@ Cause \fBread\fP to time out and return failure if a complete line of
|
||||
input is not read within \fItimeout\fP seconds.
|
||||
\fItimeout\fP may be a decimal number with a fractional portion following
|
||||
the decimal point.
|
||||
This option has no effect if \fBread\fP is not reading input from the
|
||||
terminal or a pipe.
|
||||
This option is only effective if \fBread\fP is reading input from a
|
||||
terminal, pipe, or other special file; it has no effect when reading
|
||||
from regular files.
|
||||
The exit status is greater than 128 if the timeout is exceeded.
|
||||
.TP
|
||||
.B \-u \fIfd\fP
|
||||
Read input from file descriptor \fIfd\fP.
|
||||
|
||||
+7
-4
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Sun May 25 10:41:29 EDT 2008
|
||||
.\" Last Change: Mon Jun 2 20:32:53 EDT 2008
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2008 May 25" "GNU Bash-4.0"
|
||||
.TH BASH 1 "2008 June 2" "GNU Bash-4.0"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -4242,6 +4242,8 @@ The
|
||||
.I "previous job"
|
||||
may be referenced using
|
||||
.BR %\- .
|
||||
If there is only a single job, \fB%+\fP and \fB%\-\fP can both be used
|
||||
to refer to that job.
|
||||
In output pertaining to jobs (e.g., the output of the
|
||||
.B jobs
|
||||
command), the current job is always flagged with a
|
||||
@@ -7749,8 +7751,9 @@ Cause \fBread\fP to time out and return failure if a complete line of
|
||||
input is not read within \fItimeout\fP seconds.
|
||||
\fItimeout\fP may be a decimal number with a fractional portion following
|
||||
the decimal point.
|
||||
This option has no effect if \fBread\fP is not reading input from the
|
||||
terminal or a pipe.
|
||||
This option is only effective if \fBread\fP is reading input from a
|
||||
terminal, pipe, or other special file; it has no effect when reading
|
||||
from regular files.
|
||||
.TP
|
||||
.B \-u \fIfd\fP
|
||||
Read input from file descriptor \fIfd\fP.
|
||||
|
||||
+13
-5
@@ -3661,8 +3661,10 @@ Cause @code{read} to time out and return failure if a complete line of
|
||||
input is not read within @var{timeout} seconds.
|
||||
@var{timeout} may be a decimal number with a fractional portion following
|
||||
the decimal point.
|
||||
This option has no effect if @code{read} is not reading input from the
|
||||
terminal or a pipe.
|
||||
This option is only effective if @code{read} is reading input from a
|
||||
terminal, pipe, or other special file; it has no effect when reading
|
||||
from regular files.
|
||||
The exit status is greater than 128 if the timeout is exceeded.
|
||||
|
||||
@item -u @var{fd}
|
||||
Read input from file descriptor @var{fd}.
|
||||
@@ -6351,6 +6353,10 @@ When the @code{xpg_echo} option is enabled, Bash does not attempt to interpret
|
||||
any arguments to @code{echo} as options. Each argument is displayed, after
|
||||
escape characters are converted.
|
||||
|
||||
@item
|
||||
The @code{ulimit} builtin uses a block size of 512 bytes for the @option{-c}
|
||||
and @option{-f} options.
|
||||
|
||||
@end enumerate
|
||||
|
||||
There is other @sc{posix} behavior that Bash does not implement by
|
||||
@@ -6454,9 +6460,11 @@ 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
|
||||
The previous job may be referenced using @samp{%-}.
|
||||
If there is only a single job, @samp{%+} and @samp{%-} can both be used
|
||||
to refer to that job.
|
||||
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{-}.
|
||||
|
||||
A job may also be referred to
|
||||
|
||||
+14
-6
@@ -3661,8 +3661,9 @@ Cause @code{read} to time out and return failure if a complete line of
|
||||
input is not read within @var{timeout} seconds.
|
||||
@var{timeout} may be a decimal number with a fractional portion following
|
||||
the decimal point.
|
||||
This option has no effect if @code{read} is not reading input from the
|
||||
terminal or a pipe.
|
||||
This option is only effective if @code{read} is reading input from a
|
||||
terminal, pipe, or other special file; it has no effect when reading
|
||||
from regular files.
|
||||
|
||||
@item -u @var{fd}
|
||||
Read input from file descriptor @var{fd}.
|
||||
@@ -6056,7 +6057,8 @@ The version of Bash (e.g., 2.00)
|
||||
@item \V
|
||||
The release of Bash, version + patchlevel (e.g., 2.00.0)
|
||||
@item \w
|
||||
The current working directory, with @env{$HOME} abbreviated with a tilde.
|
||||
The current working directory, with @env{$HOME} abbreviated with a tilde
|
||||
(uses the @env{$PROMPT_DIRTRIM} variable).
|
||||
@item \W
|
||||
The basename of @env{$PWD}, with @env{$HOME} abbreviated with a tilde.
|
||||
@item \!
|
||||
@@ -6350,6 +6352,10 @@ When the @code{xpg_echo} option is enabled, Bash does not attempt to interpret
|
||||
any arguments to @code{echo} as options. Each argument is displayed, after
|
||||
escape characters are converted.
|
||||
|
||||
@item
|
||||
The @code{ulimit} builtin uses a block size of 512 bytes for the @option{-c}
|
||||
and @option{-f} options.
|
||||
|
||||
@end enumerate
|
||||
|
||||
There is other @sc{posix} behavior that Bash does not implement by
|
||||
@@ -6453,9 +6459,11 @@ 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
|
||||
The previous job may be referenced using @samp{%-}.
|
||||
If there is only a single job, @samp{%+} and @samp{%-} can both be used
|
||||
to refer to that job.
|
||||
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{-}.
|
||||
|
||||
A job may also be referred to
|
||||
|
||||
@@ -372,6 +372,8 @@ inputunit: simple_list simple_list_terminator
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
/* discard_parser_constructs (0); */
|
||||
if (parser_state & PST_CMDSUBST)
|
||||
parser_state |= PST_EOFTOKEN;
|
||||
YYACCEPT;
|
||||
}
|
||||
| '\n'
|
||||
@@ -379,6 +381,8 @@ inputunit: simple_list simple_list_terminator
|
||||
/* Case of regular command, but not a very
|
||||
interesting one. Return a NULL command. */
|
||||
global_command = (COMMAND *)NULL;
|
||||
if (parser_state & PST_CMDSUBST)
|
||||
parser_state |= PST_EOFTOKEN;
|
||||
YYACCEPT;
|
||||
}
|
||||
| error '\n'
|
||||
@@ -770,7 +774,6 @@ function_def: WORD '(' ')' newline_list function_body
|
||||
{ $$ = make_function_def ($2, $4, function_dstart, function_bstart); }
|
||||
;
|
||||
|
||||
|
||||
function_body: shell_command
|
||||
{ $$ = $1; }
|
||||
| shell_command redirection_list
|
||||
@@ -953,6 +956,13 @@ simple_list: simple_list1
|
||||
$$ = $1;
|
||||
if (need_here_doc)
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
rewind_input_string ();
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
| simple_list1 '&'
|
||||
{
|
||||
@@ -962,12 +972,26 @@ simple_list: simple_list1
|
||||
$$ = command_connect ($1, (COMMAND *)NULL, '&');
|
||||
if (need_here_doc)
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
rewind_input_string ();
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
| simple_list1 ';'
|
||||
{
|
||||
$$ = $1;
|
||||
if (need_here_doc)
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
rewind_input_string ();
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2258,6 +2282,15 @@ yylex ()
|
||||
token_before_that = last_read_token;
|
||||
last_read_token = current_token;
|
||||
current_token = read_token (READ);
|
||||
|
||||
if ((parser_state & PST_EOFTOKEN) && current_token == shell_eof_token)
|
||||
{
|
||||
current_token = yacc_EOF;
|
||||
if (bash_input.type == st_string)
|
||||
rewind_input_string ();
|
||||
}
|
||||
parser_state &= ~PST_EOFTOKEN;
|
||||
|
||||
return (current_token);
|
||||
}
|
||||
|
||||
@@ -2686,6 +2719,7 @@ read_token (command)
|
||||
#if defined (ALIAS)
|
||||
parser_state &= ~PST_ALEXPNEXT;
|
||||
#endif /* ALIAS */
|
||||
|
||||
peek_char = shell_getc (1);
|
||||
if MBTEST(peek_char == '&')
|
||||
return (SEMI_SEMI_AND);
|
||||
@@ -2895,7 +2929,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
/* Not exactly right yet, should handle shell metacharacters, too. If
|
||||
any changes are made to this test, make analogous changes to subst.c:
|
||||
extract_delimited_string(). */
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind - 1])))
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
|
||||
tflags |= LEX_INCOMMENT;
|
||||
|
||||
if (tflags & LEX_PASSNEXT) /* last char was backslash */
|
||||
@@ -3015,7 +3049,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
if (open == ch) /* undo previous increment */
|
||||
count--;
|
||||
if (ch == '(') /* ) */
|
||||
nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE);
|
||||
nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
|
||||
else if (ch == '{') /* } */
|
||||
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
|
||||
else if (ch == '[') /* ] */
|
||||
@@ -3414,7 +3448,7 @@ xparse_dolparen (base, string, indp, flags)
|
||||
ostring = string;
|
||||
|
||||
sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
|
||||
if (flags & 0x010) /* EX_NOLONGJMP */
|
||||
if (flags & SX_NOLONGJMP)
|
||||
sflags |= SEVAL_NOLONGJMP;
|
||||
save_parser_state (&ps);
|
||||
|
||||
@@ -3436,7 +3470,8 @@ xparse_dolparen (base, string, indp, flags)
|
||||
if (ep[-1] != ')')
|
||||
{
|
||||
#if DEBUG
|
||||
itrace("xparse_dolparen:%d: ep[-1] != RPAREN (%d), ep = `%s'", line_number, ep[-1], ep);
|
||||
if (ep[-1] != '\n')
|
||||
itrace("xparse_dolparen:%d: ep[-1] != RPAREN (%d), ep = `%s'", line_number, ep[-1], ep);
|
||||
#endif
|
||||
while (ep > ostring && ep[-1] == '\n') ep--;
|
||||
}
|
||||
@@ -3450,7 +3485,7 @@ xparse_dolparen (base, string, indp, flags)
|
||||
itrace("xparse_dolparen:%d: base[%d] != RPAREN (%d), base = `%s'", line_number, *indp, base[*indp], base);
|
||||
#endif
|
||||
|
||||
if (flags & 1)
|
||||
if (flags & SX_NOALLOC)
|
||||
return (char *)NULL;
|
||||
|
||||
if (nc == 0)
|
||||
@@ -4017,7 +4052,7 @@ read_token_word (character)
|
||||
history literally rather than causing a possibly-
|
||||
incorrect `;' to be added. ) */
|
||||
push_delimiter (dstack, peek_char);
|
||||
ttok = parse_matched_pair (cd, '(', ')', &ttoklen, P_COMMAND);
|
||||
ttok = parse_comsub (cd, '(', ')', &ttoklen, P_COMMAND);
|
||||
pop_delimiter (dstack);
|
||||
}
|
||||
else
|
||||
@@ -4424,7 +4459,7 @@ history_delimiting_chars ()
|
||||
{
|
||||
/* Tricky. `for i\nin ...' should not have a semicolon, but
|
||||
`for i\ndo ...' should. We do what we can. */
|
||||
for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)
|
||||
for (i = shell_input_line_index; whitespace (shell_input_line[i]); i++)
|
||||
;
|
||||
if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
|
||||
return " ";
|
||||
|
||||
+5538
File diff suppressed because it is too large
Load Diff
@@ -372,6 +372,8 @@ inputunit: simple_list simple_list_terminator
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
/* discard_parser_constructs (0); */
|
||||
if (parser_state & PST_CMDSUBST)
|
||||
parser_state |= PST_EOFTOKEN;
|
||||
YYACCEPT;
|
||||
}
|
||||
| '\n'
|
||||
@@ -379,6 +381,8 @@ inputunit: simple_list simple_list_terminator
|
||||
/* Case of regular command, but not a very
|
||||
interesting one. Return a NULL command. */
|
||||
global_command = (COMMAND *)NULL;
|
||||
if (parser_state & PST_CMDSUBST)
|
||||
parser_state |= PST_EOFTOKEN;
|
||||
YYACCEPT;
|
||||
}
|
||||
| error '\n'
|
||||
@@ -762,12 +766,10 @@ case_command: CASE WORD newline_list IN newline_list ESAC
|
||||
|
||||
function_def: WORD '(' ')' newline_list function_body
|
||||
{ $$ = make_function_def ($1, $5, function_dstart, function_bstart); }
|
||||
|
||||
| FUNCTION WORD '(' ')' newline_list function_body
|
||||
{ $$ = make_function_def ($2, $6, function_dstart, function_bstart); }
|
||||
|
||||
| FUNCTION WORD newline_list function_body
|
||||
{ $$ = make_function_def ($2, $4, function_dstart, function_bstart); }
|
||||
| FUNCTION WORD '(' ')' newline_list function_body
|
||||
{ $$ = make_function_def ($2, $6, function_dstart, function_bstart); }
|
||||
;
|
||||
|
||||
|
||||
@@ -953,6 +955,13 @@ simple_list: simple_list1
|
||||
$$ = $1;
|
||||
if (need_here_doc)
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
rewind_input_string ();
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
| simple_list1 '&'
|
||||
{
|
||||
@@ -962,12 +971,26 @@ simple_list: simple_list1
|
||||
$$ = command_connect ($1, (COMMAND *)NULL, '&');
|
||||
if (need_here_doc)
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
rewind_input_string ();
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
| simple_list1 ';'
|
||||
{
|
||||
$$ = $1;
|
||||
if (need_here_doc)
|
||||
gather_here_documents ();
|
||||
if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
|
||||
{
|
||||
global_command = $1;
|
||||
eof_encountered = 0;
|
||||
rewind_input_string ();
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
@@ -2258,6 +2281,15 @@ yylex ()
|
||||
token_before_that = last_read_token;
|
||||
last_read_token = current_token;
|
||||
current_token = read_token (READ);
|
||||
|
||||
if ((parser_state & PST_EOFTOKEN) && current_token == shell_eof_token)
|
||||
{
|
||||
current_token = yacc_EOF;
|
||||
if (bash_input.type == st_string)
|
||||
rewind_input_string ();
|
||||
}
|
||||
parser_state &= ~PST_EOFTOKEN;
|
||||
|
||||
return (current_token);
|
||||
}
|
||||
|
||||
@@ -2686,6 +2718,7 @@ read_token (command)
|
||||
#if defined (ALIAS)
|
||||
parser_state &= ~PST_ALEXPNEXT;
|
||||
#endif /* ALIAS */
|
||||
|
||||
peek_char = shell_getc (1);
|
||||
if MBTEST(peek_char == '&')
|
||||
return (SEMI_SEMI_AND);
|
||||
@@ -2895,7 +2928,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
/* Not exactly right yet, should handle shell metacharacters, too. If
|
||||
any changes are made to this test, make analogous changes to subst.c:
|
||||
extract_delimited_string(). */
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind - 1])))
|
||||
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
|
||||
tflags |= LEX_INCOMMENT;
|
||||
|
||||
if (tflags & LEX_PASSNEXT) /* last char was backslash */
|
||||
@@ -3015,7 +3048,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
if (open == ch) /* undo previous increment */
|
||||
count--;
|
||||
if (ch == '(') /* ) */
|
||||
nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE);
|
||||
nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
|
||||
else if (ch == '{') /* } */
|
||||
nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
|
||||
else if (ch == '[') /* ] */
|
||||
@@ -3414,7 +3447,7 @@ xparse_dolparen (base, string, indp, flags)
|
||||
ostring = string;
|
||||
|
||||
sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
|
||||
if (flags & 0x010) /* EX_NOLONGJMP */
|
||||
if (flags & SX_NOLONGJMP)
|
||||
sflags |= SEVAL_NOLONGJMP;
|
||||
save_parser_state (&ps);
|
||||
|
||||
@@ -3436,7 +3469,8 @@ xparse_dolparen (base, string, indp, flags)
|
||||
if (ep[-1] != ')')
|
||||
{
|
||||
#if DEBUG
|
||||
itrace("xparse_dolparen:%d: ep[-1] != RPAREN (%d), ep = `%s'", line_number, ep[-1], ep);
|
||||
if (ep[-1] != '\n')
|
||||
itrace("xparse_dolparen:%d: ep[-1] != RPAREN (%d), ep = `%s'", line_number, ep[-1], ep);
|
||||
#endif
|
||||
while (ep > ostring && ep[-1] == '\n') ep--;
|
||||
}
|
||||
@@ -3450,7 +3484,7 @@ xparse_dolparen (base, string, indp, flags)
|
||||
itrace("xparse_dolparen:%d: base[%d] != RPAREN (%d), base = `%s'", line_number, *indp, base[*indp], base);
|
||||
#endif
|
||||
|
||||
if (flags & 1)
|
||||
if (flags & SX_NOALLOC)
|
||||
return (char *)NULL;
|
||||
|
||||
if (nc == 0)
|
||||
@@ -4017,7 +4051,7 @@ read_token_word (character)
|
||||
history literally rather than causing a possibly-
|
||||
incorrect `;' to be added. ) */
|
||||
push_delimiter (dstack, peek_char);
|
||||
ttok = parse_matched_pair (cd, '(', ')', &ttoklen, P_COMMAND);
|
||||
ttok = parse_comsub (cd, '(', ')', &ttoklen, P_COMMAND);
|
||||
pop_delimiter (dstack);
|
||||
}
|
||||
else
|
||||
@@ -4424,7 +4458,7 @@ history_delimiting_chars ()
|
||||
{
|
||||
/* Tricky. `for i\nin ...' should not have a semicolon, but
|
||||
`for i\ndo ...' should. We do what we can. */
|
||||
for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)
|
||||
for (i = shell_input_line_index; whitespace (shell_input_line[i]); i++)
|
||||
;
|
||||
if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
|
||||
return " ";
|
||||
@@ -4752,6 +4786,7 @@ decode_prompt_string (string)
|
||||
no longer than PATH_MAX - 1 characters. */
|
||||
strcpy (t_string, polite_directory_format (t_string));
|
||||
|
||||
temp = trim_pathname (t_string, PATH_MAX - 1);
|
||||
/* If we're going to be expanding the prompt string later,
|
||||
quote the directory name. */
|
||||
if (promptvars || posixly_correct)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -69,6 +69,7 @@ extern int errno;
|
||||
#define VT_POSPARMS 1
|
||||
#define VT_ARRAYVAR 2
|
||||
#define VT_ARRAYMEMBER 3
|
||||
#define VT_ASSOCVAR 4
|
||||
|
||||
#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
|
||||
|
||||
@@ -78,14 +79,6 @@ extern int errno;
|
||||
#define ST_SQUOTE 0x04 /* unused yet */
|
||||
#define ST_DQUOTE 0x08 /* unused yet */
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
|
||||
|
||||
/* Flags for the `pflags' argument to param_expand() */
|
||||
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
|
||||
|
||||
@@ -715,7 +708,7 @@ add_one_character:
|
||||
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_COMMAND); /*)*/
|
||||
ret = extract_command_subst (string, &si, 0);
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 1, 0);
|
||||
|
||||
@@ -817,7 +810,7 @@ skip_double_quoted (string, slen, sind)
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
ret = extract_command_subst (string, &si, SX_NOALLOC);
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
|
||||
@@ -940,6 +933,7 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mblength = MBLEN (string + i, slen - i);
|
||||
if (mblength > 1)
|
||||
@@ -987,13 +981,21 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
|
||||
/* Extract the $( construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$(".
|
||||
Make (SINDEX) get the position of the matching ")". ) */
|
||||
Make (SINDEX) get the position of the matching ")". )
|
||||
XFLAGS is additional flags to pass to other extraction functions, */
|
||||
char *
|
||||
extract_command_subst (string, sindex)
|
||||
extract_command_subst (string, sindex, xflags)
|
||||
char *string;
|
||||
int *sindex;
|
||||
int xflags;
|
||||
{
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", SX_COMMAND)); /*)*/
|
||||
if (string[*sindex] == '(') /*)*/
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
|
||||
else
|
||||
{
|
||||
xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
|
||||
return (xparse_dolparen (string, string+*sindex, sindex, xflags));
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string. (])
|
||||
@@ -1100,7 +1102,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
|
||||
/* Not exactly right yet; should handle shell metacharacters and
|
||||
multibyte characters, too. */
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
|
||||
{
|
||||
in_comment = 1;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
@@ -1265,7 +1267,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (string[i] == '$' && string[i+1] == LPAREN)
|
||||
{
|
||||
si = i + 2;
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|SX_NOALLOC|SX_COMMAND); /*)*/
|
||||
t = extract_command_subst (string, &si, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1953,6 +1955,55 @@ string_list_dollar_at (list, quoted)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Turn the positional paramters into a string, understanding quoting and
|
||||
the various subtleties of using the first character of $IFS as the
|
||||
separator. Calls string_list_dollar_at, string_list_dollar_star, and
|
||||
string_list as appropriate. */
|
||||
char *
|
||||
string_list_pos_params (pchar, list, quoted)
|
||||
int pchar;
|
||||
WORD_LIST *list;
|
||||
int quoted;
|
||||
{
|
||||
char *ret;
|
||||
WORD_LIST *tlist;
|
||||
|
||||
if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
|
||||
{
|
||||
tlist = quote_list (list);
|
||||
word_list_remove_quoted_nulls (tlist);
|
||||
ret = string_list_dollar_star (tlist);
|
||||
}
|
||||
else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
|
||||
{
|
||||
tlist = quote_list (list);
|
||||
word_list_remove_quoted_nulls (tlist);
|
||||
ret = string_list (tlist);
|
||||
}
|
||||
else if (pchar == '*')
|
||||
{
|
||||
/* Even when unquoted, string_list_dollar_star does the right thing
|
||||
making sure that the first character of $IFS is used as the
|
||||
separator. */
|
||||
ret = string_list_dollar_star (list);
|
||||
}
|
||||
else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
/* We use string_list_dollar_at, but only if the string is quoted, since
|
||||
that quotes the escapes if it's not, which we don't want. We could
|
||||
use string_list (the old code did), but that doesn't do the right
|
||||
thing if the first character of $IFS is not a space. We use
|
||||
string_list_dollar_star if the string is unquoted so we make sure that
|
||||
the elements of $@ are separated by the first character of $IFS for
|
||||
later splitting. */
|
||||
ret = string_list_dollar_at (list, quoted);
|
||||
else if (pchar == '@')
|
||||
ret = string_list_dollar_star (list);
|
||||
else
|
||||
ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the list of words present in STRING. Separate the string into
|
||||
words at any of the characters found in SEPARATORS. If QUOTED is
|
||||
non-zero then word in the list will have its quoted flag set, otherwise
|
||||
@@ -2578,17 +2629,9 @@ pos_params (string, start, end, quoted)
|
||||
}
|
||||
|
||||
t->next = (WORD_LIST *)NULL;
|
||||
if (string[0] == '*')
|
||||
{
|
||||
if (quoted & Q_DOUBLE_QUOTES)
|
||||
ret = string_list_dollar_star (quote_list (h));
|
||||
else if (quoted & Q_HERE_DOCUMENT)
|
||||
ret = string_list (quote_list (h));
|
||||
else
|
||||
ret = string_list (h);
|
||||
}
|
||||
else
|
||||
ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
|
||||
|
||||
ret = string_list_pos_params (string[0], h, quoted);
|
||||
|
||||
if (t != params)
|
||||
t->next = params;
|
||||
|
||||
@@ -3226,9 +3269,10 @@ quote_list (list)
|
||||
{
|
||||
t = w->word->word;
|
||||
w->word->word = quote_string (t);
|
||||
free (t);
|
||||
if (*t == 0)
|
||||
w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */
|
||||
w->word->flags |= W_QUOTED;
|
||||
/* XXX - turn on W_HAVEQUOTEDNULL here? */
|
||||
free (t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -3244,9 +3288,10 @@ dequote_list (list)
|
||||
for (tlist = list; tlist; tlist = tlist->next)
|
||||
{
|
||||
s = dequote_string (tlist->word->word);
|
||||
if (QUOTED_NULL (tlist->word->word))
|
||||
tlist->word->flags &= ~W_HASQUOTEDNULL;
|
||||
free (tlist->word->word);
|
||||
tlist->word->word = s;
|
||||
/* XXX - turn off W_HAVEQUOTEDNULL here? */
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -3983,12 +4028,9 @@ list_remove_pattern (list, pattern, patspec, itype, quoted)
|
||||
}
|
||||
|
||||
l = REVERSE_LIST (new, WORD_LIST *);
|
||||
if (itype == '*')
|
||||
tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
|
||||
else
|
||||
tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
|
||||
|
||||
tword = string_list_pos_params (itype, l, quoted);
|
||||
dispose_words (l);
|
||||
|
||||
return (tword);
|
||||
}
|
||||
|
||||
@@ -5813,6 +5855,7 @@ pos_params_pat_subst (string, pat, rep, mflags)
|
||||
WORD_LIST *save, *params;
|
||||
WORD_DESC *w;
|
||||
char *ret;
|
||||
int pchar, qflags;
|
||||
|
||||
save = params = list_rest_of_args ();
|
||||
if (save == 0)
|
||||
@@ -5827,10 +5870,22 @@ pos_params_pat_subst (string, pat, rep, mflags)
|
||||
params->word = w;
|
||||
}
|
||||
|
||||
pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
|
||||
qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
|
||||
|
||||
#if 0
|
||||
if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
|
||||
ret = string_list_dollar_star (quote_list (save));
|
||||
else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
|
||||
ret = string_list_dollar_star (save);
|
||||
else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
|
||||
ret = string_list_dollar_at (save, qflags);
|
||||
else
|
||||
ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
|
||||
ret = string_list_dollar_star (save);
|
||||
#else
|
||||
ret = string_list_pos_params (pchar, save, qflags);
|
||||
#endif
|
||||
|
||||
dispose_words (save);
|
||||
|
||||
return (ret);
|
||||
@@ -6137,6 +6192,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
|
||||
temp = (char *)NULL;
|
||||
goto bad_substitution;
|
||||
}
|
||||
|
||||
/* Indirect expansion begins with a `!'. A valid indirect expansion is
|
||||
either a variable name, one of the positional parameters or a special
|
||||
variable that expands to one of the positional parameters. */
|
||||
@@ -6676,7 +6732,7 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
case LPAREN:
|
||||
/* We have to extract the contents of this paren substitution. */
|
||||
t_index = zindex + 1;
|
||||
temp = extract_command_subst (string, &t_index);
|
||||
temp = extract_command_subst (string, &t_index, 0);
|
||||
zindex = t_index;
|
||||
|
||||
/* For Posix.2-style `$(( ))' arithmetic substitution,
|
||||
@@ -6735,7 +6791,8 @@ comsub:
|
||||
{
|
||||
tdesc = command_substitute (temp, quoted);
|
||||
temp1 = tdesc ? tdesc->word : (char *)NULL;
|
||||
dispose_word_desc (tdesc);
|
||||
if (tdesc)
|
||||
dispose_word_desc (tdesc);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -7153,7 +7210,8 @@ add_string:
|
||||
de_backslash (temp);
|
||||
tword = command_substitute (temp, quoted);
|
||||
temp1 = tword ? tword->word : (char *)NULL;
|
||||
dispose_word_desc (tword);
|
||||
if (tword)
|
||||
dispose_word_desc (tword);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
|
||||
+286
-136
@@ -4,7 +4,7 @@
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -69,6 +69,7 @@ extern int errno;
|
||||
#define VT_POSPARMS 1
|
||||
#define VT_ARRAYVAR 2
|
||||
#define VT_ARRAYMEMBER 3
|
||||
#define VT_ASSOCVAR 4
|
||||
|
||||
#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
|
||||
|
||||
@@ -78,13 +79,6 @@ extern int errno;
|
||||
#define ST_SQUOTE 0x04 /* unused yet */
|
||||
#define ST_DQUOTE 0x08 /* unused yet */
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
|
||||
/* Flags for the `pflags' argument to param_expand() */
|
||||
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
|
||||
|
||||
@@ -135,6 +129,8 @@ size_t ifs_firstc_len;
|
||||
unsigned char ifs_firstc;
|
||||
#endif
|
||||
|
||||
int assigning_in_environment;
|
||||
|
||||
/* Extern functions and variables from different files. */
|
||||
extern int last_command_exit_value, last_command_exit_signal;
|
||||
extern int subshell_environment;
|
||||
@@ -206,7 +202,6 @@ static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
|
||||
static char *dequote_escapes __P((char *));
|
||||
static char *make_quoted_char __P((int));
|
||||
static WORD_LIST *quote_list __P((WORD_LIST *));
|
||||
static char *remove_quoted_escapes __P((char *));
|
||||
static char *remove_quoted_nulls __P((char *));
|
||||
|
||||
static int unquoted_substring __P((char *, char *));
|
||||
@@ -713,7 +708,7 @@ add_one_character:
|
||||
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_COMMAND); /*)*/
|
||||
ret = extract_command_subst (string, &si, 0);
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 1, 0);
|
||||
|
||||
@@ -815,7 +810,7 @@ skip_double_quoted (string, slen, sind)
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
ret = extract_command_subst (string, &si, SX_NOALLOC);
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
|
||||
@@ -930,6 +925,14 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
/* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
|
||||
through, to protect the CTLNULs from later calls to
|
||||
remove_quoted_nulls. */
|
||||
else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
|
||||
{
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mblength = MBLEN (string + i, slen - i);
|
||||
@@ -978,13 +981,21 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
|
||||
/* Extract the $( construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$(".
|
||||
Make (SINDEX) get the position of the matching ")". ) */
|
||||
Make (SINDEX) get the position of the matching ")". )
|
||||
XFLAGS is additional flags to pass to other extraction functions, */
|
||||
char *
|
||||
extract_command_subst (string, sindex)
|
||||
extract_command_subst (string, sindex, xflags)
|
||||
char *string;
|
||||
int *sindex;
|
||||
int xflags;
|
||||
{
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", SX_COMMAND)); /*)*/
|
||||
if (string[*sindex] == '(') /*)*/
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
|
||||
else
|
||||
{
|
||||
xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
|
||||
return (xparse_dolparen (string, string+*sindex, sindex, xflags));
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string. (])
|
||||
@@ -1091,7 +1102,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
|
||||
/* Not exactly right yet; should handle shell metacharacters and
|
||||
multibyte characters, too. */
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
|
||||
{
|
||||
in_comment = 1;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
@@ -1256,7 +1267,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (string[i] == '$' && string[i+1] == LPAREN)
|
||||
{
|
||||
si = i + 2;
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|SX_NOALLOC|SX_COMMAND); /*)*/
|
||||
t = extract_command_subst (string, &si, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1353,6 +1364,91 @@ unquote_bang (string)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
|
||||
|
||||
/* Skip characters in STRING until we find a character in DELIMS, and return
|
||||
the index of that character. START is the index into string at which we
|
||||
begin. This is similar in spirit to strpbrk, but it returns an index into
|
||||
STRING and takes a starting index. This little piece of code knows quite
|
||||
a lot of shell syntax. It's very similar to skip_double_quoted and other
|
||||
functions of that ilk. */
|
||||
int
|
||||
skip_to_delim (string, start, delims, flags)
|
||||
char *string;
|
||||
int start;
|
||||
char *delims;
|
||||
int flags;
|
||||
{
|
||||
int i, pass_next, backq, si, c;
|
||||
size_t slen;
|
||||
char *temp;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string + start) + start;
|
||||
if (flags & SD_NOJMP)
|
||||
no_longjmp_on_fatal_error = 1;
|
||||
i = start;
|
||||
pass_next = backq = 0;
|
||||
while (c = string[i])
|
||||
{
|
||||
if (pass_next)
|
||||
{
|
||||
pass_next = 0;
|
||||
if (c == 0)
|
||||
CQ_RETURN(i);
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
pass_next = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (backq)
|
||||
{
|
||||
if (c == '`')
|
||||
backq = 0;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '`')
|
||||
{
|
||||
backq = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\'' || c == '"')
|
||||
{
|
||||
i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
|
||||
: skip_double_quoted (string, slen, ++i);
|
||||
/* no increment, the skip functions increment past the closing quote. */
|
||||
}
|
||||
else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[si] == '\0')
|
||||
CQ_RETURN(si);
|
||||
|
||||
if (string[i+1] == LPAREN)
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
i = si;
|
||||
if (string[i] == '\0') /* don't increment i past EOS in loop */
|
||||
break;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (member (c, delims))
|
||||
break;
|
||||
else
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
}
|
||||
|
||||
CQ_RETURN(i);
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
|
||||
an unclosed quoted string), or if the character at EINDEX is quoted
|
||||
@@ -1362,8 +1458,6 @@ unquote_bang (string)
|
||||
recognizes need to be the same as the contents of
|
||||
rl_completer_quote_characters. */
|
||||
|
||||
#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
|
||||
|
||||
int
|
||||
char_is_quoted (string, eindex)
|
||||
char *string;
|
||||
@@ -1456,87 +1550,6 @@ unclosed_pair (string, eindex, openstr)
|
||||
return (openc);
|
||||
}
|
||||
|
||||
/* Skip characters in STRING until we find a character in DELIMS, and return
|
||||
the index of that character. START is the index into string at which we
|
||||
begin. This is similar in spirit to strpbrk, but it returns an index into
|
||||
STRING and takes a starting index. This little piece of code knows quite
|
||||
a lot of shell syntax. It's very similar to skip_double_quoted and other
|
||||
functions of that ilk. */
|
||||
int
|
||||
skip_to_delim (string, start, delims)
|
||||
char *string;
|
||||
int start;
|
||||
char *delims;
|
||||
{
|
||||
int i, pass_next, backq, si, c;
|
||||
size_t slen;
|
||||
char *temp;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string + start) + start;
|
||||
no_longjmp_on_fatal_error = 1;
|
||||
i = start;
|
||||
pass_next = backq = 0;
|
||||
while (c = string[i])
|
||||
{
|
||||
if (pass_next)
|
||||
{
|
||||
pass_next = 0;
|
||||
if (c == 0)
|
||||
CQ_RETURN(i);
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
pass_next = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (backq)
|
||||
{
|
||||
if (c == '`')
|
||||
backq = 0;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '`')
|
||||
{
|
||||
backq = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\'' || c == '"')
|
||||
{
|
||||
i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
|
||||
: skip_double_quoted (string, slen, ++i);
|
||||
/* no increment, the skip functions increment past the closing quote. */
|
||||
}
|
||||
else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[si] == '\0')
|
||||
CQ_RETURN(si);
|
||||
|
||||
if (string[i+1] == LPAREN)
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
i = si;
|
||||
if (string[i] == '\0') /* don't increment i past EOS in loop */
|
||||
break;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (member (c, delims))
|
||||
break;
|
||||
else
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
}
|
||||
|
||||
CQ_RETURN(i);
|
||||
}
|
||||
|
||||
/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
|
||||
individual words. If DELIMS is NULL, the current value of $IFS is used
|
||||
to split the string, and the function follows the shell field splitting
|
||||
@@ -1621,7 +1634,7 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
|
||||
cw = -1;
|
||||
while (1)
|
||||
{
|
||||
te = skip_to_delim (string, ts, d);
|
||||
te = skip_to_delim (string, ts, d, SD_NOJMP);
|
||||
|
||||
/* If we have a non-whitespace delimiter character, use it to make a
|
||||
separate field. This is just about what $IFS splitting does and
|
||||
@@ -1787,6 +1800,42 @@ string_list (list)
|
||||
return (string_list_internal (list, " "));
|
||||
}
|
||||
|
||||
/* An external interface that can be used by the rest of the shell to
|
||||
obtain a string containing the first character in $IFS. Handles all
|
||||
the multibyte complications. If LENP is non-null, it is set to the
|
||||
length of the returned string. */
|
||||
char *
|
||||
ifs_firstchar (lenp)
|
||||
int *lenp;
|
||||
{
|
||||
char *ret;
|
||||
int len;
|
||||
|
||||
ret = xmalloc (MB_LEN_MAX + 1);
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (ifs_firstc_len == 1)
|
||||
{
|
||||
ret[0] = ifs_firstc[0];
|
||||
ret[1] = '\0';
|
||||
len = ret[0] ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (ret, ifs_firstc, ifs_firstc_len);
|
||||
ret[len = ifs_firstc_len] = '\0';
|
||||
}
|
||||
#else
|
||||
ret[0] = ifs_firstc;
|
||||
ret[1] = '\0';
|
||||
len = ret[0] ? 0 : 1;
|
||||
#endif
|
||||
|
||||
if (lenp)
|
||||
*lenp = len;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return a single string of all the words present in LIST, obeying the
|
||||
quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
|
||||
expansion [of $*] appears within a double quoted string, it expands
|
||||
@@ -1906,6 +1955,45 @@ string_list_dollar_at (list, quoted)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Turn the positional paramters into a string, understanding quoting and
|
||||
the various subtleties of using the first character of $IFS as the
|
||||
separator. Calls string_list_dollar_at, string_list_dollar_star, and
|
||||
string_list as appropriate. */
|
||||
char *
|
||||
string_list_pos_params (pchar, list, quoted)
|
||||
int pchar;
|
||||
WORD_LIST *list;
|
||||
int quoted;
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (pchar == '*')
|
||||
{
|
||||
if (quoted & Q_DOUBLE_QUOTES)
|
||||
ret = string_list_dollar_star (quote_list (list));
|
||||
else if (quoted & Q_HERE_DOCUMENT)
|
||||
ret = string_list (quote_list (list));
|
||||
else
|
||||
/* Even when unquoted, string_list_dollar_star does the right thing
|
||||
making sure that the first character of $IFS is used as the
|
||||
separator. */
|
||||
ret = string_list_dollar_star (list);
|
||||
}
|
||||
else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
/* We use string_list_dollar_at, but only if the string is quoted, since
|
||||
that quotes the escapes if it's not, which we don't want. We could
|
||||
use string_list (the old code did), but that doesn't do the right
|
||||
thing if the first character of $IFS is not a space. We use
|
||||
string_list_dollar_star if the string is unquoted so we make sure that
|
||||
the elements of $@ are separated by the first character of $IFS for
|
||||
later splitting. */
|
||||
ret = string_list_dollar_at (list, quoted);
|
||||
else
|
||||
ret = string_list_dollar_star (list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the list of words present in STRING. Separate the string into
|
||||
words at any of the characters found in SEPARATORS. If QUOTED is
|
||||
non-zero then word in the list will have its quoted flag set, otherwise
|
||||
@@ -1957,7 +2045,10 @@ list_string (string, separators, quoted)
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
{
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
|
||||
}
|
||||
|
||||
slen = 0;
|
||||
/* Remove sequences of whitespace at the beginning of STRING, as
|
||||
@@ -2076,7 +2167,10 @@ get_word_from_string (stringp, separators, endptr)
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
{
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
|
||||
}
|
||||
|
||||
s = *stringp;
|
||||
slen = 0;
|
||||
@@ -2264,7 +2358,7 @@ do_assignment_internal (word, expand)
|
||||
const WORD_DESC *word;
|
||||
int expand;
|
||||
{
|
||||
int offset, tlen, appendop, assign_list, aflags;
|
||||
int offset, tlen, appendop, assign_list, aflags, retval;
|
||||
char *name, *value;
|
||||
SHELL_VAR *entry;
|
||||
#if defined (ARRAY_VARS)
|
||||
@@ -2355,11 +2449,27 @@ do_assignment_internal (word, expand)
|
||||
|
||||
stupidly_hack_special_variables (name);
|
||||
|
||||
#if 1
|
||||
/* Return 1 if the assignment seems to have been performed correctly. */
|
||||
if (entry == 0 || readonly_p (entry))
|
||||
retval = 0; /* assignment failure */
|
||||
else if (noassign_p (entry))
|
||||
{
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
retval = 1; /* error status, but not assignment failure */
|
||||
}
|
||||
else
|
||||
retval = 1;
|
||||
ASSIGN_RETURN (retval);
|
||||
|
||||
if (entry && retval != 0)
|
||||
VUNSETATTR (entry, att_invisible);
|
||||
#else
|
||||
if (entry)
|
||||
VUNSETATTR (entry, att_invisible);
|
||||
|
||||
/* Return 1 if the assignment seems to have been performed correctly. */
|
||||
ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Perform the assignment statement in STRING, and expand the
|
||||
@@ -2509,17 +2619,9 @@ pos_params (string, start, end, quoted)
|
||||
}
|
||||
|
||||
t->next = (WORD_LIST *)NULL;
|
||||
if (string[0] == '*')
|
||||
{
|
||||
if (quoted & Q_DOUBLE_QUOTES)
|
||||
ret = string_list_dollar_star (quote_list (h));
|
||||
else if (quoted & Q_HERE_DOCUMENT)
|
||||
ret = string_list (quote_list (h));
|
||||
else
|
||||
ret = string_list (h);
|
||||
}
|
||||
else
|
||||
ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
|
||||
|
||||
ret = string_list_pos_params (string[0], h, quoted);
|
||||
|
||||
if (t != params)
|
||||
t->next = params;
|
||||
|
||||
@@ -2825,9 +2927,10 @@ expand_string_assignment (string, quoted)
|
||||
passed string when an error occurs. Might want to trap other calls
|
||||
to jump_to_top_level here so we don't endlessly loop. */
|
||||
WORD_LIST *
|
||||
expand_prompt_string (string, quoted)
|
||||
expand_prompt_string (string, quoted, wflags)
|
||||
char *string;
|
||||
int quoted;
|
||||
int wflags;
|
||||
{
|
||||
WORD_LIST *value;
|
||||
WORD_DESC td;
|
||||
@@ -2835,7 +2938,7 @@ expand_prompt_string (string, quoted)
|
||||
if (string == 0 || *string == 0)
|
||||
return ((WORD_LIST *)NULL);
|
||||
|
||||
td.flags = 0;
|
||||
td.flags = wflags;
|
||||
td.word = savestring (string);
|
||||
|
||||
no_longjmp_on_fatal_error = 1;
|
||||
@@ -2953,7 +3056,7 @@ quote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces, skip_ctlesc;
|
||||
int quote_spaces, skip_ctlesc, skip_ctlnul;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
@@ -2961,15 +3064,15 @@ quote_escapes (string)
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
|
||||
for (skip_ctlesc = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC;
|
||||
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
|
||||
|
||||
t = result = (char *)xmalloc ((slen * 2) + 1);
|
||||
s = string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if ((skip_ctlesc == 0 && *s == CTLESC) || *s == CTLNUL || (quote_spaces && *s == ' '))
|
||||
if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
|
||||
*t++ = CTLESC;
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
@@ -3183,7 +3286,7 @@ dequote_list (list)
|
||||
|
||||
/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
|
||||
string. */
|
||||
static char *
|
||||
char *
|
||||
remove_quoted_escapes (string)
|
||||
char *string;
|
||||
{
|
||||
@@ -3992,7 +4095,11 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
|
||||
if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
|
||||
patstr++;
|
||||
|
||||
pattern = getpattern (patstr, quoted, 1);
|
||||
/* Need to pass getpattern newly-allocated memory in case of expansion --
|
||||
the expansion code will free the passed string on an error. */
|
||||
temp1 = savestring (patstr);
|
||||
pattern = getpattern (temp1, quoted, 1);
|
||||
free (temp1);
|
||||
|
||||
temp1 = (char *)NULL; /* shut up gcc */
|
||||
switch (vtype)
|
||||
@@ -4356,6 +4463,7 @@ process_substitute (string, open_for_read_in_child)
|
||||
#if defined (JOB_CONTROL)
|
||||
set_sigchld_handler ();
|
||||
stop_making_children ();
|
||||
/* XXX - should we only do this in the parent? (as in command subst) */
|
||||
pipeline_pgrp = old_pipeline_pgrp;
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
@@ -4474,14 +4582,14 @@ read_comsub (fd, quoted, rflag)
|
||||
int *rflag;
|
||||
{
|
||||
char *istring, buf[128], *bufp, *s;
|
||||
int istring_index, istring_size, c, tflag, skip_ctlesc;
|
||||
int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
|
||||
ssize_t bufn;
|
||||
|
||||
istring = (char *)NULL;
|
||||
istring_index = istring_size = bufn = tflag = 0;
|
||||
|
||||
for (skip_ctlesc = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC;
|
||||
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
|
||||
@@ -4524,7 +4632,7 @@ read_comsub (fd, quoted, rflag)
|
||||
tflag |= W_HASCTLESC;
|
||||
istring[istring_index++] = CTLESC;
|
||||
}
|
||||
else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
istring[istring_index++] = CTLESC;
|
||||
|
||||
istring[istring_index++] = c;
|
||||
@@ -4645,9 +4753,11 @@ command_substitute (string, quoted)
|
||||
reset_signal_handlers ();
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
/* XXX DO THIS ONLY IN PARENT ? XXX */
|
||||
set_sigchld_handler ();
|
||||
stop_making_children ();
|
||||
pipeline_pgrp = old_pipeline_pgrp;
|
||||
if (pid != 0)
|
||||
pipeline_pgrp = old_pipeline_pgrp;
|
||||
#else
|
||||
stop_making_children ();
|
||||
#endif /* JOB_CONTROL */
|
||||
@@ -4937,10 +5047,11 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
char *temp, *tt;
|
||||
intmax_t arg_index;
|
||||
SHELL_VAR *var;
|
||||
int atype;
|
||||
int atype, rflags;
|
||||
|
||||
ret = 0;
|
||||
temp = 0;
|
||||
rflags = 0;
|
||||
|
||||
/* Handle multiple digit arguments, as in ${11}. */
|
||||
if (legal_number (name, &arg_index))
|
||||
@@ -4973,6 +5084,8 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
rflags |= W_HASQUOTEDNULL;
|
||||
}
|
||||
#endif
|
||||
else if (var = find_variable (name))
|
||||
@@ -5000,6 +5113,7 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
{
|
||||
ret = alloc_word_desc ();
|
||||
ret->word = temp;
|
||||
ret->flags |= rflags;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -5749,7 +5863,14 @@ pos_params_pat_subst (string, pat, rep, mflags)
|
||||
if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
|
||||
ret = string_list_dollar_star (quote_list (save));
|
||||
else
|
||||
#if 0
|
||||
ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
|
||||
#else
|
||||
if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
|
||||
ret = string_list_dollar_star (quote_list (save));
|
||||
else
|
||||
ret = string_list (save);
|
||||
#endif
|
||||
dispose_words (save);
|
||||
|
||||
return (ret);
|
||||
@@ -5764,7 +5885,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
char *varname, *value, *patsub;
|
||||
int quoted;
|
||||
{
|
||||
int vtype, mflags, starsub;
|
||||
int vtype, mflags, starsub, delim;
|
||||
char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
|
||||
SHELL_VAR *v;
|
||||
|
||||
@@ -5799,10 +5920,21 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
|
||||
/* If the pattern starts with a `/', make sure we skip over it when looking
|
||||
for the replacement delimiter. */
|
||||
#if 0
|
||||
if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
|
||||
*rep++ = '\0';
|
||||
else
|
||||
rep = (char *)NULL;
|
||||
#else
|
||||
delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
|
||||
if (lpatsub[delim] == '/')
|
||||
{
|
||||
lpatsub[delim] = 0;
|
||||
rep = lpatsub + delim + 1;
|
||||
}
|
||||
else
|
||||
rep = (char *)NULL;
|
||||
#endif
|
||||
|
||||
if (rep && *rep == '\0')
|
||||
rep = (char *)NULL;
|
||||
@@ -5960,7 +6092,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
|
||||
int t_index, sindex, c, tflag;
|
||||
intmax_t number;
|
||||
|
||||
value = (char *)NULL;
|
||||
temp = temp1 = value = (char *)NULL;
|
||||
var_is_set = var_is_null = var_is_special = check_nullness = 0;
|
||||
want_substring = want_indir = want_patsub = 0;
|
||||
|
||||
@@ -6585,7 +6717,7 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
case LPAREN:
|
||||
/* We have to extract the contents of this paren substitution. */
|
||||
t_index = zindex + 1;
|
||||
temp = extract_command_subst (string, &t_index);
|
||||
temp = extract_command_subst (string, &t_index, 0);
|
||||
zindex = t_index;
|
||||
|
||||
/* For Posix.2-style `$(( ))' arithmetic substitution,
|
||||
@@ -6644,7 +6776,8 @@ comsub:
|
||||
{
|
||||
tdesc = command_substitute (temp, quoted);
|
||||
temp1 = tdesc ? tdesc->word : (char *)NULL;
|
||||
dispose_word_desc (tdesc);
|
||||
if (tdesc)
|
||||
dispose_word_desc (tdesc);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -6657,6 +6790,13 @@ comsub:
|
||||
t_index = zindex + 1;
|
||||
temp = extract_arithmetic_subst (string, &t_index);
|
||||
zindex = t_index;
|
||||
if (temp == 0)
|
||||
{
|
||||
temp = savestring (string);
|
||||
if (expanded_something)
|
||||
*expanded_something = 0;
|
||||
goto return0;
|
||||
}
|
||||
|
||||
/* Do initial variable expansion. */
|
||||
temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
|
||||
@@ -6986,7 +7126,7 @@ add_string:
|
||||
free (temp);
|
||||
temp = temp1;
|
||||
sindex += t_index;
|
||||
goto add_string;
|
||||
goto add_quoted_string; /* XXX was add_string */
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7055,7 +7195,8 @@ add_string:
|
||||
de_backslash (temp);
|
||||
tword = command_substitute (temp, quoted);
|
||||
temp1 = tword ? tword->word : (char *)NULL;
|
||||
dispose_word_desc (tword);
|
||||
if (tword)
|
||||
dispose_word_desc (tword);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -7483,6 +7624,11 @@ string_quote_removal (string, quoted)
|
||||
{
|
||||
case '\\':
|
||||
c = string[++sindex];
|
||||
if (c == 0)
|
||||
{
|
||||
*r++ = '\\';
|
||||
break;
|
||||
}
|
||||
if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
|
||||
*r++ = '\\';
|
||||
/* FALLTHROUGH */
|
||||
@@ -7683,7 +7829,9 @@ exp_jump_to_top_level (v)
|
||||
/* Cleanup code goes here. */
|
||||
expand_no_split_dollar_star = 0; /* XXX */
|
||||
expanding_redir = 0;
|
||||
assigning_in_environment = 0;
|
||||
|
||||
top_level_cleanup (); /* from sig.c */
|
||||
jump_to_top_level (v);
|
||||
}
|
||||
|
||||
@@ -7901,7 +8049,7 @@ glob_expand_word_list (tlist, eflags)
|
||||
else if (fail_glob_expansion != 0)
|
||||
{
|
||||
report_error (_("no match: %s"), tlist->word->word);
|
||||
jump_to_top_level (DISCARD);
|
||||
exp_jump_to_top_level (DISCARD);
|
||||
}
|
||||
else if (allow_null_glob_expansion == 0)
|
||||
{
|
||||
@@ -8183,7 +8331,9 @@ expand_word_list_internal (list, eflags)
|
||||
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
|
||||
{
|
||||
this_command_name = (char *)NULL;
|
||||
assigning_in_environment = (assign_func == assign_in_env);
|
||||
tint = (*assign_func) (temp_list->word);
|
||||
assigning_in_environment = 0;
|
||||
/* Variable assignment errors in non-interactive shells running
|
||||
in Posix.2 mode cause the shell to exit. */
|
||||
if (tint == 0)
|
||||
|
||||
+282
-143
@@ -4,7 +4,7 @@
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -69,6 +69,7 @@ extern int errno;
|
||||
#define VT_POSPARMS 1
|
||||
#define VT_ARRAYVAR 2
|
||||
#define VT_ARRAYMEMBER 3
|
||||
#define VT_ASSOCVAR 4
|
||||
|
||||
#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
|
||||
|
||||
@@ -78,13 +79,6 @@ extern int errno;
|
||||
#define ST_SQUOTE 0x04 /* unused yet */
|
||||
#define ST_DQUOTE 0x08 /* unused yet */
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
|
||||
/* Flags for the `pflags' argument to param_expand() */
|
||||
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
|
||||
|
||||
@@ -135,6 +129,8 @@ size_t ifs_firstc_len;
|
||||
unsigned char ifs_firstc;
|
||||
#endif
|
||||
|
||||
int assigning_in_environment;
|
||||
|
||||
/* Extern functions and variables from different files. */
|
||||
extern int last_command_exit_value, last_command_exit_signal;
|
||||
extern int subshell_environment;
|
||||
@@ -206,7 +202,6 @@ static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
|
||||
static char *dequote_escapes __P((char *));
|
||||
static char *make_quoted_char __P((int));
|
||||
static WORD_LIST *quote_list __P((WORD_LIST *));
|
||||
static char *remove_quoted_escapes __P((char *));
|
||||
static char *remove_quoted_nulls __P((char *));
|
||||
|
||||
static int unquoted_substring __P((char *, char *));
|
||||
@@ -713,7 +708,7 @@ add_one_character:
|
||||
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_COMMAND); /*)*/
|
||||
ret = extract_command_subst (string, &si, 0);
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 1, 0);
|
||||
|
||||
@@ -815,7 +810,7 @@ skip_double_quoted (string, slen, sind)
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
ret = extract_command_subst (string, &si, SX_NOALLOC);
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
|
||||
@@ -933,11 +928,12 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
/* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
|
||||
through, to protect the CTLNULs from later calls to
|
||||
remove_quoted_nulls. */
|
||||
else if (c == CTLESC && string[i+1] == CTLNUL)
|
||||
else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
|
||||
{
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mblength = MBLEN (string + i, slen - i);
|
||||
if (mblength > 1)
|
||||
@@ -985,13 +981,21 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
|
||||
/* Extract the $( construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$(".
|
||||
Make (SINDEX) get the position of the matching ")". ) */
|
||||
Make (SINDEX) get the position of the matching ")". )
|
||||
XFLAGS is additional flags to pass to other extraction functions, */
|
||||
char *
|
||||
extract_command_subst (string, sindex)
|
||||
extract_command_subst (string, sindex, xflags)
|
||||
char *string;
|
||||
int *sindex;
|
||||
int xflags;
|
||||
{
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", SX_COMMAND)); /*)*/
|
||||
if (string[*sindex] == '(') /*)*/
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
|
||||
else
|
||||
{
|
||||
xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
|
||||
return (xparse_dolparen (string, string+*sindex, sindex, xflags));
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string. (])
|
||||
@@ -1098,7 +1102,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
|
||||
/* Not exactly right yet; should handle shell metacharacters and
|
||||
multibyte characters, too. */
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
|
||||
{
|
||||
in_comment = 1;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
@@ -1263,7 +1267,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (string[i] == '$' && string[i+1] == LPAREN)
|
||||
{
|
||||
si = i + 2;
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|SX_NOALLOC|SX_COMMAND); /*)*/
|
||||
t = extract_command_subst (string, &si, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1360,6 +1364,91 @@ unquote_bang (string)
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
|
||||
|
||||
/* Skip characters in STRING until we find a character in DELIMS, and return
|
||||
the index of that character. START is the index into string at which we
|
||||
begin. This is similar in spirit to strpbrk, but it returns an index into
|
||||
STRING and takes a starting index. This little piece of code knows quite
|
||||
a lot of shell syntax. It's very similar to skip_double_quoted and other
|
||||
functions of that ilk. */
|
||||
int
|
||||
skip_to_delim (string, start, delims, flags)
|
||||
char *string;
|
||||
int start;
|
||||
char *delims;
|
||||
int flags;
|
||||
{
|
||||
int i, pass_next, backq, si, c;
|
||||
size_t slen;
|
||||
char *temp;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string + start) + start;
|
||||
if (flags & SD_NOJMP)
|
||||
no_longjmp_on_fatal_error = 1;
|
||||
i = start;
|
||||
pass_next = backq = 0;
|
||||
while (c = string[i])
|
||||
{
|
||||
if (pass_next)
|
||||
{
|
||||
pass_next = 0;
|
||||
if (c == 0)
|
||||
CQ_RETURN(i);
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
pass_next = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (backq)
|
||||
{
|
||||
if (c == '`')
|
||||
backq = 0;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '`')
|
||||
{
|
||||
backq = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\'' || c == '"')
|
||||
{
|
||||
i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
|
||||
: skip_double_quoted (string, slen, ++i);
|
||||
/* no increment, the skip functions increment past the closing quote. */
|
||||
}
|
||||
else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[si] == '\0')
|
||||
CQ_RETURN(si);
|
||||
|
||||
if (string[i+1] == LPAREN)
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
i = si;
|
||||
if (string[i] == '\0') /* don't increment i past EOS in loop */
|
||||
break;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (member (c, delims))
|
||||
break;
|
||||
else
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
}
|
||||
|
||||
CQ_RETURN(i);
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
|
||||
an unclosed quoted string), or if the character at EINDEX is quoted
|
||||
@@ -1369,8 +1458,6 @@ unquote_bang (string)
|
||||
recognizes need to be the same as the contents of
|
||||
rl_completer_quote_characters. */
|
||||
|
||||
#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
|
||||
|
||||
int
|
||||
char_is_quoted (string, eindex)
|
||||
char *string;
|
||||
@@ -1463,87 +1550,6 @@ unclosed_pair (string, eindex, openstr)
|
||||
return (openc);
|
||||
}
|
||||
|
||||
/* Skip characters in STRING until we find a character in DELIMS, and return
|
||||
the index of that character. START is the index into string at which we
|
||||
begin. This is similar in spirit to strpbrk, but it returns an index into
|
||||
STRING and takes a starting index. This little piece of code knows quite
|
||||
a lot of shell syntax. It's very similar to skip_double_quoted and other
|
||||
functions of that ilk. */
|
||||
int
|
||||
skip_to_delim (string, start, delims)
|
||||
char *string;
|
||||
int start;
|
||||
char *delims;
|
||||
{
|
||||
int i, pass_next, backq, si, c;
|
||||
size_t slen;
|
||||
char *temp;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string + start) + start;
|
||||
no_longjmp_on_fatal_error = 1;
|
||||
i = start;
|
||||
pass_next = backq = 0;
|
||||
while (c = string[i])
|
||||
{
|
||||
if (pass_next)
|
||||
{
|
||||
pass_next = 0;
|
||||
if (c == 0)
|
||||
CQ_RETURN(i);
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '\\')
|
||||
{
|
||||
pass_next = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (backq)
|
||||
{
|
||||
if (c == '`')
|
||||
backq = 0;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '`')
|
||||
{
|
||||
backq = 1;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (c == '\'' || c == '"')
|
||||
{
|
||||
i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
|
||||
: skip_double_quoted (string, slen, ++i);
|
||||
/* no increment, the skip functions increment past the closing quote. */
|
||||
}
|
||||
else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[si] == '\0')
|
||||
CQ_RETURN(si);
|
||||
|
||||
if (string[i+1] == LPAREN)
|
||||
temp = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
else
|
||||
temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
i = si;
|
||||
if (string[i] == '\0') /* don't increment i past EOS in loop */
|
||||
break;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else if (member (c, delims))
|
||||
break;
|
||||
else
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
}
|
||||
|
||||
CQ_RETURN(i);
|
||||
}
|
||||
|
||||
/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
|
||||
individual words. If DELIMS is NULL, the current value of $IFS is used
|
||||
to split the string, and the function follows the shell field splitting
|
||||
@@ -1628,7 +1634,7 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
|
||||
cw = -1;
|
||||
while (1)
|
||||
{
|
||||
te = skip_to_delim (string, ts, d);
|
||||
te = skip_to_delim (string, ts, d, SD_NOJMP);
|
||||
|
||||
/* If we have a non-whitespace delimiter character, use it to make a
|
||||
separate field. This is just about what $IFS splitting does and
|
||||
@@ -1794,6 +1800,42 @@ string_list (list)
|
||||
return (string_list_internal (list, " "));
|
||||
}
|
||||
|
||||
/* An external interface that can be used by the rest of the shell to
|
||||
obtain a string containing the first character in $IFS. Handles all
|
||||
the multibyte complications. If LENP is non-null, it is set to the
|
||||
length of the returned string. */
|
||||
char *
|
||||
ifs_firstchar (lenp)
|
||||
int *lenp;
|
||||
{
|
||||
char *ret;
|
||||
int len;
|
||||
|
||||
ret = xmalloc (MB_LEN_MAX + 1);
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (ifs_firstc_len == 1)
|
||||
{
|
||||
ret[0] = ifs_firstc[0];
|
||||
ret[1] = '\0';
|
||||
len = ret[0] ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (ret, ifs_firstc, ifs_firstc_len);
|
||||
ret[len = ifs_firstc_len] = '\0';
|
||||
}
|
||||
#else
|
||||
ret[0] = ifs_firstc;
|
||||
ret[1] = '\0';
|
||||
len = ret[0] ? 0 : 1;
|
||||
#endif
|
||||
|
||||
if (lenp)
|
||||
*lenp = len;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return a single string of all the words present in LIST, obeying the
|
||||
quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
|
||||
expansion [of $*] appears within a double quoted string, it expands
|
||||
@@ -1913,6 +1955,47 @@ string_list_dollar_at (list, quoted)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Turn the positional paramters into a string, understanding quoting and
|
||||
the various subtleties of using the first character of $IFS as the
|
||||
separator. Calls string_list_dollar_at, string_list_dollar_star, and
|
||||
string_list as appropriate. */
|
||||
char *
|
||||
string_list_pos_params (pchar, list, quoted)
|
||||
int pchar;
|
||||
WORD_LIST *list;
|
||||
int quoted;
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (pchar == '*')
|
||||
{
|
||||
if (quoted & Q_DOUBLE_QUOTES)
|
||||
ret = string_list_dollar_star (quote_list (list));
|
||||
else if (quoted & Q_HERE_DOCUMENT)
|
||||
ret = string_list (quote_list (list));
|
||||
else
|
||||
/* Even when unquoted, string_list_dollar_star does the right thing
|
||||
making sure that the first character of $IFS is used as the
|
||||
separator. */
|
||||
ret = string_list_dollar_star (list);
|
||||
}
|
||||
else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
/* We use string_list_dollar_at, but only if the string is quoted, since
|
||||
that quotes the escapes if it's not, which we don't want. We could
|
||||
use string_list (the old code did), but that doesn't do the right
|
||||
thing if the first character of $IFS is not a space. We use
|
||||
string_list_dollar_star if the string is unquoted so we make sure that
|
||||
the elements of $@ are separated by the first character of $IFS for
|
||||
later splitting. */
|
||||
ret = string_list_dollar_at (list, quoted);
|
||||
else if (pchar == '@')
|
||||
ret = string_list_dollar_star (list);
|
||||
else
|
||||
ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the list of words present in STRING. Separate the string into
|
||||
words at any of the characters found in SEPARATORS. If QUOTED is
|
||||
non-zero then word in the list will have its quoted flag set, otherwise
|
||||
@@ -1964,7 +2047,10 @@ list_string (string, separators, quoted)
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
{
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
|
||||
}
|
||||
|
||||
slen = 0;
|
||||
/* Remove sequences of whitespace at the beginning of STRING, as
|
||||
@@ -2083,7 +2169,10 @@ get_word_from_string (stringp, separators, endptr)
|
||||
separators[2] == '\n' &&
|
||||
separators[3] == '\0';
|
||||
for (xflags = 0, s = ifs_value; s && *s; s++)
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
{
|
||||
if (*s == CTLESC) xflags |= SX_NOCTLESC;
|
||||
if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
|
||||
}
|
||||
|
||||
s = *stringp;
|
||||
slen = 0;
|
||||
@@ -2271,7 +2360,7 @@ do_assignment_internal (word, expand)
|
||||
const WORD_DESC *word;
|
||||
int expand;
|
||||
{
|
||||
int offset, tlen, appendop, assign_list, aflags;
|
||||
int offset, tlen, appendop, assign_list, aflags, retval;
|
||||
char *name, *value;
|
||||
SHELL_VAR *entry;
|
||||
#if defined (ARRAY_VARS)
|
||||
@@ -2362,11 +2451,27 @@ do_assignment_internal (word, expand)
|
||||
|
||||
stupidly_hack_special_variables (name);
|
||||
|
||||
#if 1
|
||||
/* Return 1 if the assignment seems to have been performed correctly. */
|
||||
if (entry == 0 || readonly_p (entry))
|
||||
retval = 0; /* assignment failure */
|
||||
else if (noassign_p (entry))
|
||||
{
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
retval = 1; /* error status, but not assignment failure */
|
||||
}
|
||||
else
|
||||
retval = 1;
|
||||
ASSIGN_RETURN (retval);
|
||||
|
||||
if (entry && retval != 0)
|
||||
VUNSETATTR (entry, att_invisible);
|
||||
#else
|
||||
if (entry)
|
||||
VUNSETATTR (entry, att_invisible);
|
||||
|
||||
/* Return 1 if the assignment seems to have been performed correctly. */
|
||||
ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Perform the assignment statement in STRING, and expand the
|
||||
@@ -2516,17 +2621,9 @@ pos_params (string, start, end, quoted)
|
||||
}
|
||||
|
||||
t->next = (WORD_LIST *)NULL;
|
||||
if (string[0] == '*')
|
||||
{
|
||||
if (quoted & Q_DOUBLE_QUOTES)
|
||||
ret = string_list_dollar_star (quote_list (h));
|
||||
else if (quoted & Q_HERE_DOCUMENT)
|
||||
ret = string_list (quote_list (h));
|
||||
else
|
||||
ret = string_list (h);
|
||||
}
|
||||
else
|
||||
ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
|
||||
|
||||
ret = string_list_pos_params (string[0], h, quoted);
|
||||
|
||||
if (t != params)
|
||||
t->next = params;
|
||||
|
||||
@@ -2832,9 +2929,10 @@ expand_string_assignment (string, quoted)
|
||||
passed string when an error occurs. Might want to trap other calls
|
||||
to jump_to_top_level here so we don't endlessly loop. */
|
||||
WORD_LIST *
|
||||
expand_prompt_string (string, quoted)
|
||||
expand_prompt_string (string, quoted, wflags)
|
||||
char *string;
|
||||
int quoted;
|
||||
int wflags;
|
||||
{
|
||||
WORD_LIST *value;
|
||||
WORD_DESC td;
|
||||
@@ -2842,7 +2940,7 @@ expand_prompt_string (string, quoted)
|
||||
if (string == 0 || *string == 0)
|
||||
return ((WORD_LIST *)NULL);
|
||||
|
||||
td.flags = 0;
|
||||
td.flags = wflags;
|
||||
td.word = savestring (string);
|
||||
|
||||
no_longjmp_on_fatal_error = 1;
|
||||
@@ -2960,7 +3058,7 @@ quote_escapes (string)
|
||||
register char *s, *t;
|
||||
size_t slen;
|
||||
char *result, *send;
|
||||
int quote_spaces, skip_ctlesc;
|
||||
int quote_spaces, skip_ctlesc, skip_ctlnul;
|
||||
DECLARE_MBSTATE;
|
||||
|
||||
slen = strlen (string);
|
||||
@@ -2968,15 +3066,15 @@ quote_escapes (string)
|
||||
|
||||
quote_spaces = (ifs_value && *ifs_value == 0);
|
||||
|
||||
for (skip_ctlesc = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC;
|
||||
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
|
||||
|
||||
t = result = (char *)xmalloc ((slen * 2) + 1);
|
||||
s = string;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if ((skip_ctlesc == 0 && *s == CTLESC) || *s == CTLNUL || (quote_spaces && *s == ' '))
|
||||
if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
|
||||
*t++ = CTLESC;
|
||||
COPY_CHAR_P (t, s, send);
|
||||
}
|
||||
@@ -3190,7 +3288,7 @@ dequote_list (list)
|
||||
|
||||
/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
|
||||
string. */
|
||||
static char *
|
||||
char *
|
||||
remove_quoted_escapes (string)
|
||||
char *string;
|
||||
{
|
||||
@@ -3920,12 +4018,9 @@ list_remove_pattern (list, pattern, patspec, itype, quoted)
|
||||
}
|
||||
|
||||
l = REVERSE_LIST (new, WORD_LIST *);
|
||||
if (itype == '*')
|
||||
tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
|
||||
else
|
||||
tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
|
||||
|
||||
tword = string_list_pos_params (itype, l, quoted);
|
||||
dispose_words (l);
|
||||
|
||||
return (tword);
|
||||
}
|
||||
|
||||
@@ -3999,7 +4094,11 @@ parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
|
||||
if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
|
||||
patstr++;
|
||||
|
||||
pattern = getpattern (patstr, quoted, 1);
|
||||
/* Need to pass getpattern newly-allocated memory in case of expansion --
|
||||
the expansion code will free the passed string on an error. */
|
||||
temp1 = savestring (patstr);
|
||||
pattern = getpattern (temp1, quoted, 1);
|
||||
free (temp1);
|
||||
|
||||
temp1 = (char *)NULL; /* shut up gcc */
|
||||
switch (vtype)
|
||||
@@ -4363,6 +4462,7 @@ process_substitute (string, open_for_read_in_child)
|
||||
#if defined (JOB_CONTROL)
|
||||
set_sigchld_handler ();
|
||||
stop_making_children ();
|
||||
/* XXX - should we only do this in the parent? (as in command subst) */
|
||||
pipeline_pgrp = old_pipeline_pgrp;
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
@@ -4481,14 +4581,14 @@ read_comsub (fd, quoted, rflag)
|
||||
int *rflag;
|
||||
{
|
||||
char *istring, buf[128], *bufp, *s;
|
||||
int istring_index, istring_size, c, tflag, skip_ctlesc;
|
||||
int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
|
||||
ssize_t bufn;
|
||||
|
||||
istring = (char *)NULL;
|
||||
istring_index = istring_size = bufn = tflag = 0;
|
||||
|
||||
for (skip_ctlesc = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC;
|
||||
for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
|
||||
skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
|
||||
@@ -4531,7 +4631,7 @@ read_comsub (fd, quoted, rflag)
|
||||
tflag |= W_HASCTLESC;
|
||||
istring[istring_index++] = CTLESC;
|
||||
}
|
||||
else if (c == CTLNUL || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
|
||||
istring[istring_index++] = CTLESC;
|
||||
|
||||
istring[istring_index++] = c;
|
||||
@@ -4652,9 +4752,11 @@ command_substitute (string, quoted)
|
||||
reset_signal_handlers ();
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
/* XXX DO THIS ONLY IN PARENT ? XXX */
|
||||
set_sigchld_handler ();
|
||||
stop_making_children ();
|
||||
pipeline_pgrp = old_pipeline_pgrp;
|
||||
if (pid != 0)
|
||||
pipeline_pgrp = old_pipeline_pgrp;
|
||||
#else
|
||||
stop_making_children ();
|
||||
#endif /* JOB_CONTROL */
|
||||
@@ -4944,10 +5046,11 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
char *temp, *tt;
|
||||
intmax_t arg_index;
|
||||
SHELL_VAR *var;
|
||||
int atype;
|
||||
int atype, rflags;
|
||||
|
||||
ret = 0;
|
||||
temp = 0;
|
||||
rflags = 0;
|
||||
|
||||
/* Handle multiple digit arguments, as in ${11}. */
|
||||
if (legal_number (name, &arg_index))
|
||||
@@ -4980,6 +5083,8 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
? quote_string (temp)
|
||||
: quote_escapes (temp);
|
||||
else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
|
||||
rflags |= W_HASQUOTEDNULL;
|
||||
}
|
||||
#endif
|
||||
else if (var = find_variable (name))
|
||||
@@ -5007,6 +5112,7 @@ parameter_brace_expand_word (name, var_is_special, quoted)
|
||||
{
|
||||
ret = alloc_word_desc ();
|
||||
ret->word = temp;
|
||||
ret->flags |= rflags;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -5739,6 +5845,7 @@ pos_params_pat_subst (string, pat, rep, mflags)
|
||||
WORD_LIST *save, *params;
|
||||
WORD_DESC *w;
|
||||
char *ret;
|
||||
int pchar;
|
||||
|
||||
save = params = list_rest_of_args ();
|
||||
if (save == 0)
|
||||
@@ -5755,8 +5862,11 @@ pos_params_pat_subst (string, pat, rep, mflags)
|
||||
|
||||
if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
|
||||
ret = string_list_dollar_star (quote_list (save));
|
||||
else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
|
||||
ret = string_list_dollar_star (quote_list (save));
|
||||
else
|
||||
ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
|
||||
ret = string_list_dollar_star (save);
|
||||
|
||||
dispose_words (save);
|
||||
|
||||
return (ret);
|
||||
@@ -5771,7 +5881,7 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
char *varname, *value, *patsub;
|
||||
int quoted;
|
||||
{
|
||||
int vtype, mflags, starsub;
|
||||
int vtype, mflags, starsub, delim;
|
||||
char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
|
||||
SHELL_VAR *v;
|
||||
|
||||
@@ -5806,10 +5916,21 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
|
||||
/* If the pattern starts with a `/', make sure we skip over it when looking
|
||||
for the replacement delimiter. */
|
||||
#if 0
|
||||
if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
|
||||
*rep++ = '\0';
|
||||
else
|
||||
rep = (char *)NULL;
|
||||
#else
|
||||
delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
|
||||
if (lpatsub[delim] == '/')
|
||||
{
|
||||
lpatsub[delim] = 0;
|
||||
rep = lpatsub + delim + 1;
|
||||
}
|
||||
else
|
||||
rep = (char *)NULL;
|
||||
#endif
|
||||
|
||||
if (rep && *rep == '\0')
|
||||
rep = (char *)NULL;
|
||||
@@ -5967,7 +6088,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
|
||||
int t_index, sindex, c, tflag;
|
||||
intmax_t number;
|
||||
|
||||
value = (char *)NULL;
|
||||
temp = temp1 = value = (char *)NULL;
|
||||
var_is_set = var_is_null = var_is_special = check_nullness = 0;
|
||||
want_substring = want_indir = want_patsub = 0;
|
||||
|
||||
@@ -6592,7 +6713,7 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
case LPAREN:
|
||||
/* We have to extract the contents of this paren substitution. */
|
||||
t_index = zindex + 1;
|
||||
temp = extract_command_subst (string, &t_index);
|
||||
temp = extract_command_subst (string, &t_index, 0);
|
||||
zindex = t_index;
|
||||
|
||||
/* For Posix.2-style `$(( ))' arithmetic substitution,
|
||||
@@ -6651,7 +6772,8 @@ comsub:
|
||||
{
|
||||
tdesc = command_substitute (temp, quoted);
|
||||
temp1 = tdesc ? tdesc->word : (char *)NULL;
|
||||
dispose_word_desc (tdesc);
|
||||
if (tdesc)
|
||||
dispose_word_desc (tdesc);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -6664,6 +6786,13 @@ comsub:
|
||||
t_index = zindex + 1;
|
||||
temp = extract_arithmetic_subst (string, &t_index);
|
||||
zindex = t_index;
|
||||
if (temp == 0)
|
||||
{
|
||||
temp = savestring (string);
|
||||
if (expanded_something)
|
||||
*expanded_something = 0;
|
||||
goto return0;
|
||||
}
|
||||
|
||||
/* Do initial variable expansion. */
|
||||
temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
|
||||
@@ -6993,7 +7122,7 @@ add_string:
|
||||
free (temp);
|
||||
temp = temp1;
|
||||
sindex += t_index;
|
||||
goto add_string;
|
||||
goto add_quoted_string; /* XXX was add_string */
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -7062,7 +7191,8 @@ add_string:
|
||||
de_backslash (temp);
|
||||
tword = command_substitute (temp, quoted);
|
||||
temp1 = tword ? tword->word : (char *)NULL;
|
||||
dispose_word_desc (tword);
|
||||
if (tword)
|
||||
dispose_word_desc (tword);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -7490,6 +7620,11 @@ string_quote_removal (string, quoted)
|
||||
{
|
||||
case '\\':
|
||||
c = string[++sindex];
|
||||
if (c == 0)
|
||||
{
|
||||
*r++ = '\\';
|
||||
break;
|
||||
}
|
||||
if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
|
||||
*r++ = '\\';
|
||||
/* FALLTHROUGH */
|
||||
@@ -7690,7 +7825,9 @@ exp_jump_to_top_level (v)
|
||||
/* Cleanup code goes here. */
|
||||
expand_no_split_dollar_star = 0; /* XXX */
|
||||
expanding_redir = 0;
|
||||
assigning_in_environment = 0;
|
||||
|
||||
top_level_cleanup (); /* from sig.c */
|
||||
jump_to_top_level (v);
|
||||
}
|
||||
|
||||
@@ -7908,7 +8045,7 @@ glob_expand_word_list (tlist, eflags)
|
||||
else if (fail_glob_expansion != 0)
|
||||
{
|
||||
report_error (_("no match: %s"), tlist->word->word);
|
||||
jump_to_top_level (DISCARD);
|
||||
exp_jump_to_top_level (DISCARD);
|
||||
}
|
||||
else if (allow_null_glob_expansion == 0)
|
||||
{
|
||||
@@ -8190,7 +8327,9 @@ expand_word_list_internal (list, eflags)
|
||||
for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
|
||||
{
|
||||
this_command_name = (char *)NULL;
|
||||
assigning_in_environment = (assign_func == assign_in_env);
|
||||
tint = (*assign_func) (temp_list->word);
|
||||
assigning_in_environment = 0;
|
||||
/* Variable assignment errors in non-interactive shells running
|
||||
in Posix.2 mode cause the shell to exit. */
|
||||
if (tint == 0)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/* ``Have a little faith, there's magic in the night. You ain't a
|
||||
beauty, but, hey, you're alright.'' */
|
||||
|
||||
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -69,6 +69,7 @@ extern int errno;
|
||||
#define VT_POSPARMS 1
|
||||
#define VT_ARRAYVAR 2
|
||||
#define VT_ARRAYMEMBER 3
|
||||
#define VT_ASSOCVAR 4
|
||||
|
||||
#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
|
||||
|
||||
@@ -78,14 +79,6 @@ extern int errno;
|
||||
#define ST_SQUOTE 0x04 /* unused yet */
|
||||
#define ST_DQUOTE 0x08 /* unused yet */
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
|
||||
|
||||
/* Flags for the `pflags' argument to param_expand() */
|
||||
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
|
||||
|
||||
@@ -715,7 +708,7 @@ add_one_character:
|
||||
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_COMMAND); /*)*/
|
||||
ret = extract_command_subst (string, &si, 0);
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 1, 0);
|
||||
|
||||
@@ -817,7 +810,7 @@ skip_double_quoted (string, slen, sind)
|
||||
{
|
||||
si = i + 2;
|
||||
if (string[i + 1] == LPAREN)
|
||||
ret = extract_delimited_string (string, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
|
||||
ret = extract_command_subst (string, &si, SX_NOALLOC);
|
||||
else
|
||||
ret = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
|
||||
|
||||
@@ -940,6 +933,7 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mblength = MBLEN (string + i, slen - i);
|
||||
if (mblength > 1)
|
||||
@@ -987,13 +981,21 @@ string_extract_verbatim (string, slen, sindex, charlist, flags)
|
||||
|
||||
/* Extract the $( construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$(".
|
||||
Make (SINDEX) get the position of the matching ")". ) */
|
||||
Make (SINDEX) get the position of the matching ")". )
|
||||
XFLAGS is additional flags to pass to other extraction functions, */
|
||||
char *
|
||||
extract_command_subst (string, sindex)
|
||||
extract_command_subst (string, sindex, xflags)
|
||||
char *string;
|
||||
int *sindex;
|
||||
int xflags;
|
||||
{
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", SX_COMMAND)); /*)*/
|
||||
if (string[*sindex] == '(') /*)*/
|
||||
return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
|
||||
else
|
||||
{
|
||||
xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
|
||||
return (xparse_dolparen (string, string+*sindex, sindex, xflags));
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string. (])
|
||||
@@ -1100,7 +1102,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
|
||||
|
||||
/* Not exactly right yet; should handle shell metacharacters and
|
||||
multibyte characters, too. */
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
|
||||
if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
|
||||
{
|
||||
in_comment = 1;
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
@@ -1265,7 +1267,7 @@ extract_dollar_brace_string (string, sindex, quoted, flags)
|
||||
if (string[i] == '$' && string[i+1] == LPAREN)
|
||||
{
|
||||
si = i + 2;
|
||||
t = extract_delimited_string (string, &si, "$(", "(", ")", flags|SX_NOALLOC|SX_COMMAND); /*)*/
|
||||
t = extract_command_subst (string, &si, flags|SX_NOALLOC);
|
||||
i = si + 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1953,6 +1955,55 @@ string_list_dollar_at (list, quoted)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Turn the positional paramters into a string, understanding quoting and
|
||||
the various subtleties of using the first character of $IFS as the
|
||||
separator. Calls string_list_dollar_at, string_list_dollar_star, and
|
||||
string_list as appropriate. */
|
||||
char *
|
||||
string_list_pos_params (pchar, list, quoted)
|
||||
int pchar;
|
||||
WORD_LIST *list;
|
||||
int quoted;
|
||||
{
|
||||
char *ret;
|
||||
WORD_LIST *tlist;
|
||||
|
||||
if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
|
||||
{
|
||||
tlist = quote_list (list);
|
||||
word_list_remove_quoted_nulls (tlist);
|
||||
ret = string_list_dollar_star (tlist);
|
||||
}
|
||||
else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
|
||||
{
|
||||
tlist = quote_list (list);
|
||||
word_list_remove_quoted_nulls (tlist);
|
||||
ret = string_list (tlist);
|
||||
}
|
||||
else if (pchar == '*')
|
||||
{
|
||||
/* Even when unquoted, string_list_dollar_star does the right thing
|
||||
making sure that the first character of $IFS is used as the
|
||||
separator. */
|
||||
ret = string_list_dollar_star (list);
|
||||
}
|
||||
else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
/* We use string_list_dollar_at, but only if the string is quoted, since
|
||||
that quotes the escapes if it's not, which we don't want. We could
|
||||
use string_list (the old code did), but that doesn't do the right
|
||||
thing if the first character of $IFS is not a space. We use
|
||||
string_list_dollar_star if the string is unquoted so we make sure that
|
||||
the elements of $@ are separated by the first character of $IFS for
|
||||
later splitting. */
|
||||
ret = string_list_dollar_at (list, quoted);
|
||||
else if (pchar == '@')
|
||||
ret = string_list_dollar_star (list);
|
||||
else
|
||||
ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the list of words present in STRING. Separate the string into
|
||||
words at any of the characters found in SEPARATORS. If QUOTED is
|
||||
non-zero then word in the list will have its quoted flag set, otherwise
|
||||
@@ -2578,17 +2629,9 @@ pos_params (string, start, end, quoted)
|
||||
}
|
||||
|
||||
t->next = (WORD_LIST *)NULL;
|
||||
if (string[0] == '*')
|
||||
{
|
||||
if (quoted & Q_DOUBLE_QUOTES)
|
||||
ret = string_list_dollar_star (quote_list (h));
|
||||
else if (quoted & Q_HERE_DOCUMENT)
|
||||
ret = string_list (quote_list (h));
|
||||
else
|
||||
ret = string_list (h);
|
||||
}
|
||||
else
|
||||
ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
|
||||
|
||||
ret = string_list_pos_params (string[0], h, quoted);
|
||||
|
||||
if (t != params)
|
||||
t->next = params;
|
||||
|
||||
@@ -2894,9 +2937,10 @@ expand_string_assignment (string, quoted)
|
||||
passed string when an error occurs. Might want to trap other calls
|
||||
to jump_to_top_level here so we don't endlessly loop. */
|
||||
WORD_LIST *
|
||||
expand_prompt_string (string, quoted)
|
||||
expand_prompt_string (string, quoted, wflags)
|
||||
char *string;
|
||||
int quoted;
|
||||
int wflags;
|
||||
{
|
||||
WORD_LIST *value;
|
||||
WORD_DESC td;
|
||||
@@ -2904,7 +2948,7 @@ expand_prompt_string (string, quoted)
|
||||
if (string == 0 || *string == 0)
|
||||
return ((WORD_LIST *)NULL);
|
||||
|
||||
td.flags = 0;
|
||||
td.flags = wflags;
|
||||
td.word = savestring (string);
|
||||
|
||||
no_longjmp_on_fatal_error = 1;
|
||||
@@ -3225,9 +3269,10 @@ quote_list (list)
|
||||
{
|
||||
t = w->word->word;
|
||||
w->word->word = quote_string (t);
|
||||
free (t);
|
||||
if (*t == 0)
|
||||
w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */
|
||||
w->word->flags |= W_QUOTED;
|
||||
/* XXX - turn on W_HAVEQUOTEDNULL here? */
|
||||
free (t);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -3243,9 +3288,10 @@ dequote_list (list)
|
||||
for (tlist = list; tlist; tlist = tlist->next)
|
||||
{
|
||||
s = dequote_string (tlist->word->word);
|
||||
if (QUOTED_NULL (tlist->word->word))
|
||||
tlist->word->flags &= ~W_HASQUOTEDNULL;
|
||||
free (tlist->word->word);
|
||||
tlist->word->word = s;
|
||||
/* XXX - turn off W_HAVEQUOTEDNULL here? */
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -3982,12 +4028,22 @@ list_remove_pattern (list, pattern, patspec, itype, quoted)
|
||||
}
|
||||
|
||||
l = REVERSE_LIST (new, WORD_LIST *);
|
||||
if (itype == '*')
|
||||
tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
|
||||
#if 0
|
||||
if (itype == '*' && (quoted & Q_DOUBLE_QUOTES))
|
||||
tword = string_list_dollar_star (quote_list (l));
|
||||
else if (itype == '*')
|
||||
tword = string_list_dollar_star (l);
|
||||
else if (itype == '@' && (quoted & Q_DOUBLE_QUOTES))
|
||||
tword = string_list_dollar_at (l, quoted);
|
||||
else if (itype == '@')
|
||||
tword = string_list_dollar_star (l);
|
||||
else
|
||||
tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
|
||||
|
||||
tword = string_list (l);
|
||||
#else
|
||||
tword = string_list_pos_params (itype, l, quoted);
|
||||
#endif
|
||||
dispose_words (l);
|
||||
|
||||
return (tword);
|
||||
}
|
||||
|
||||
@@ -5812,6 +5868,7 @@ pos_params_pat_subst (string, pat, rep, mflags)
|
||||
WORD_LIST *save, *params;
|
||||
WORD_DESC *w;
|
||||
char *ret;
|
||||
int pchar, qflags;
|
||||
|
||||
save = params = list_rest_of_args ();
|
||||
if (save == 0)
|
||||
@@ -5826,10 +5883,22 @@ pos_params_pat_subst (string, pat, rep, mflags)
|
||||
params->word = w;
|
||||
}
|
||||
|
||||
pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
|
||||
qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
|
||||
|
||||
#if 0
|
||||
if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
|
||||
ret = string_list_dollar_star (quote_list (save));
|
||||
else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
|
||||
ret = string_list_dollar_star (save);
|
||||
else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
|
||||
ret = string_list_dollar_at (save, qflags);
|
||||
else
|
||||
ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
|
||||
ret = string_list_dollar_star (save);
|
||||
#else
|
||||
ret = string_list_pos_params (pchar, save, qflags);
|
||||
#endif
|
||||
|
||||
dispose_words (save);
|
||||
|
||||
return (ret);
|
||||
@@ -6136,6 +6205,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
|
||||
temp = (char *)NULL;
|
||||
goto bad_substitution;
|
||||
}
|
||||
|
||||
/* Indirect expansion begins with a `!'. A valid indirect expansion is
|
||||
either a variable name, one of the positional parameters or a special
|
||||
variable that expands to one of the positional parameters. */
|
||||
@@ -6675,7 +6745,7 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
case LPAREN:
|
||||
/* We have to extract the contents of this paren substitution. */
|
||||
t_index = zindex + 1;
|
||||
temp = extract_command_subst (string, &t_index);
|
||||
temp = extract_command_subst (string, &t_index, 0);
|
||||
zindex = t_index;
|
||||
|
||||
/* For Posix.2-style `$(( ))' arithmetic substitution,
|
||||
@@ -6734,7 +6804,8 @@ comsub:
|
||||
{
|
||||
tdesc = command_substitute (temp, quoted);
|
||||
temp1 = tdesc ? tdesc->word : (char *)NULL;
|
||||
dispose_word_desc (tdesc);
|
||||
if (tdesc)
|
||||
dispose_word_desc (tdesc);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -7152,7 +7223,8 @@ add_string:
|
||||
de_backslash (temp);
|
||||
tword = command_substitute (temp, quoted);
|
||||
temp1 = tword ? tword->word : (char *)NULL;
|
||||
dispose_word_desc (tword);
|
||||
if (tword)
|
||||
dispose_word_desc (tword);
|
||||
}
|
||||
FREE (temp);
|
||||
temp = temp1;
|
||||
@@ -7580,6 +7652,11 @@ string_quote_removal (string, quoted)
|
||||
{
|
||||
case '\\':
|
||||
c = string[++sindex];
|
||||
if (c == 0)
|
||||
{
|
||||
*r++ = '\\';
|
||||
break;
|
||||
}
|
||||
if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
|
||||
*r++ = '\\';
|
||||
/* FALLTHROUGH */
|
||||
|
||||
@@ -43,6 +43,15 @@
|
||||
#define ASS_APPEND 0x01
|
||||
#define ASS_MKLOCAL 0x02
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
|
||||
#define SX_NOLONGJMP 0x40 /* don't longjmp on fatal error */
|
||||
|
||||
/* Remove backslashes which are quoting backquotes from STRING. Modifies
|
||||
STRING, and returns a pointer to it. */
|
||||
extern char * de_backslash __P((char *));
|
||||
@@ -52,8 +61,9 @@ extern void unquote_bang __P((char *));
|
||||
|
||||
/* Extract the $( construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$(".
|
||||
Make (SINDEX) get the position just after the matching ")". */
|
||||
extern char *extract_command_subst __P((char *, int *));
|
||||
Make (SINDEX) get the position just after the matching ")".
|
||||
XFLAGS is additional flags to pass to other extraction functions, */
|
||||
extern char *extract_command_subst __P((char *, int *, int));
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$[".
|
||||
@@ -84,6 +94,12 @@ extern char *string_list_dollar_star __P((WORD_LIST *));
|
||||
/* Expand $@ into a single string, obeying POSIX rules. */
|
||||
extern char *string_list_dollar_at __P((WORD_LIST *, int));
|
||||
|
||||
/* Turn the positional paramters into a string, understanding quoting and
|
||||
the various subtleties of using the first character of $IFS as the
|
||||
separator. Calls string_list_dollar_at, string_list_dollar_star, and
|
||||
string_list as appropriate. */
|
||||
extern char *string_list_pos_params __P((int, WORD_LIST *, int));
|
||||
|
||||
/* Perform quoted null character removal on each element of LIST.
|
||||
This modifies LIST. */
|
||||
extern void word_list_remove_quoted_nulls __P((WORD_LIST *));
|
||||
|
||||
@@ -43,6 +43,15 @@
|
||||
#define ASS_APPEND 0x01
|
||||
#define ASS_MKLOCAL 0x02
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
|
||||
#define SX_NOLONGJMP 0x40 /* don't longjmp on fatal error */
|
||||
|
||||
/* Remove backslashes which are quoting backquotes from STRING. Modifies
|
||||
STRING, and returns a pointer to it. */
|
||||
extern char * de_backslash __P((char *));
|
||||
@@ -52,8 +61,9 @@ extern void unquote_bang __P((char *));
|
||||
|
||||
/* Extract the $( construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$(".
|
||||
Make (SINDEX) get the position just after the matching ")". */
|
||||
extern char *extract_command_subst __P((char *, int *));
|
||||
Make (SINDEX) get the position just after the matching ")".
|
||||
XFLAGS is additional flags to pass to other extraction functions, */
|
||||
extern char *extract_command_subst __P((char *, int *, int));
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$[".
|
||||
@@ -136,7 +146,7 @@ extern WORD_LIST *expand_string_unsplit __P((char *, int));
|
||||
extern WORD_LIST *expand_string_assignment __P((char *, int));
|
||||
|
||||
/* Expand a prompt string. */
|
||||
extern WORD_LIST *expand_prompt_string __P((char *, int));
|
||||
extern WORD_LIST *expand_prompt_string __P((char *, int, int));
|
||||
|
||||
/* Expand STRING just as if you were expanding a word. This also returns
|
||||
a list of words. Note that filename globbing is *NOT* done for word
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
abmnopyz
|
||||
abmnopyz
|
||||
ab
|
||||
|
||||
|
||||
abcd
|
||||
sh_352.26ax
|
||||
sh_352.26ay
|
||||
sh_352.25a sh_352.25b
|
||||
sh_352.27 ) ) )
|
||||
abc
|
||||
here doc with )
|
||||
)
|
||||
bad' syntax
|
||||
a
|
||||
sh_352.26a
|
||||
sh_352.26a
|
||||
sh_352.26
|
||||
sh_352.26
|
||||
sh_352.26
|
||||
1
|
||||
sh_352.28 )
|
||||
sh_352.28 )
|
||||
k
|
||||
abcd
|
||||
ab
|
||||
ab
|
||||
abcde
|
||||
|
||||
argv[1] = <abcde^J >
|
||||
abcdefoo
|
||||
argv[1] = <abcde>
|
||||
argv[2] = <foo>
|
||||
argv[1] = <wxabcdeyz>
|
||||
argv[1] = <abcde>
|
||||
'
|
||||
after 1
|
||||
'
|
||||
after 2
|
||||
'
|
||||
after 3
|
||||
`
|
||||
after 4
|
||||
hello
|
||||
after 5
|
||||
'
|
||||
after 6
|
||||
x
|
||||
x
|
||||
quoted )
|
||||
comment
|
||||
here-doc with )
|
||||
here-doc terminated with a parenthesis
|
||||
' # or a single back- or doublequote
|
||||
./comsub-posix1.sub: command substitution: line 2: syntax error near unexpected token `)'
|
||||
./comsub-posix1.sub: command substitution: line 2: ` if x; then echo foo )'
|
||||
after
|
||||
@@ -0,0 +1,199 @@
|
||||
|
||||
# works right
|
||||
echo ab$(echo mnop)yz
|
||||
# works right
|
||||
echo ab$(echo mnop
|
||||
)yz
|
||||
#
|
||||
# works right
|
||||
echo $(echo ab
|
||||
)
|
||||
# works right
|
||||
echo $(
|
||||
)
|
||||
echo $()
|
||||
echo ab$()cd
|
||||
|
||||
echo $(case a in (a) echo sh_352.26ax; esac )
|
||||
echo $(case a in (a) echo sh_352.26ay; esac)
|
||||
|
||||
echo $((echo sh_352.25a);(echo sh_352.25b))
|
||||
|
||||
echo $(echo sh_352.27 ')' ")" \)
|
||||
# ) comment
|
||||
)
|
||||
|
||||
echo $(
|
||||
echo abc # a comment with )
|
||||
)
|
||||
|
||||
echo $(
|
||||
cat <<eof
|
||||
here doc with )
|
||||
eof
|
||||
)
|
||||
|
||||
echo $(
|
||||
echo ')'
|
||||
)
|
||||
|
||||
unset x
|
||||
x=$(cat <<"EOF"
|
||||
bad' syntax
|
||||
EOF
|
||||
)
|
||||
echo "$x"
|
||||
unset x
|
||||
|
||||
echo $(for f in \); do echo a; done )
|
||||
echo $(case a in a) echo sh_352.26a; esac )
|
||||
echo $(case a in a) echo sh_352.26a; esac)
|
||||
|
||||
echo $(case a in
|
||||
(a) echo sh_352.26
|
||||
;;
|
||||
esac
|
||||
)
|
||||
|
||||
echo $(case a in
|
||||
a) echo sh_352.26
|
||||
;;
|
||||
esac
|
||||
)
|
||||
|
||||
|
||||
echo $(case a in
|
||||
a) echo sh_352.26
|
||||
;;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
esac
|
||||
|
||||
)
|
||||
|
||||
echo $(( 4<(2+3) ? 1 : 32))
|
||||
|
||||
echo $(cat << end
|
||||
sh_352.28 )
|
||||
end
|
||||
)
|
||||
|
||||
echo $(cat <<- end
|
||||
sh_352.28 )
|
||||
end
|
||||
)
|
||||
|
||||
k=$(case x in x) echo k;; esac)
|
||||
echo $k
|
||||
|
||||
x=$(
|
||||
case $(ls) in
|
||||
example) echo foobix;;
|
||||
esac
|
||||
)
|
||||
|
||||
echo $( echo ab\
|
||||
cd)
|
||||
|
||||
echo `echo ab
|
||||
cd`
|
||||
|
||||
echo `echo ab #xyz
|
||||
cd`
|
||||
|
||||
echo "$(echo abcde)
|
||||
"
|
||||
|
||||
recho "$(echo abcde)
|
||||
"
|
||||
|
||||
echo $(echo abcde)\
|
||||
foo
|
||||
|
||||
recho $(echo abcde)\
|
||||
foo
|
||||
|
||||
recho "wx$(echo abcde)yz"
|
||||
recho "$(echo abcde)"
|
||||
|
||||
echo $(cat <<eof
|
||||
'
|
||||
eof
|
||||
)
|
||||
|
||||
echo after 1
|
||||
|
||||
echo $(cat <<\eof
|
||||
'
|
||||
eof
|
||||
)
|
||||
|
||||
echo after 2
|
||||
|
||||
echo "$(cat <<\eof
|
||||
'
|
||||
eof
|
||||
)"
|
||||
|
||||
echo after 3
|
||||
|
||||
echo "$(cat <<\eof
|
||||
`
|
||||
eof
|
||||
)"
|
||||
|
||||
echo after 4
|
||||
|
||||
echo $(
|
||||
cat << ')'
|
||||
hello
|
||||
)
|
||||
)
|
||||
|
||||
echo after 5
|
||||
|
||||
echo $(cat <<'eof'
|
||||
'
|
||||
eof
|
||||
)
|
||||
|
||||
echo after 6
|
||||
|
||||
echo $(
|
||||
case x in x) echo x;; esac
|
||||
)
|
||||
|
||||
echo $(
|
||||
case x in (x) echo x;; esac
|
||||
)
|
||||
|
||||
echo $(
|
||||
echo 'quoted )'
|
||||
)
|
||||
|
||||
echo $(
|
||||
echo comment # with )
|
||||
)
|
||||
|
||||
echo $(
|
||||
cat <<\eof
|
||||
here-doc with )
|
||||
eof
|
||||
)
|
||||
|
||||
echo $(
|
||||
cat <<\)
|
||||
here-doc terminated with a parenthesis
|
||||
)
|
||||
)
|
||||
|
||||
echo $(
|
||||
cat <<\eof
|
||||
' # or a single back- or doublequote
|
||||
eof
|
||||
)
|
||||
|
||||
${THIS_SH} ./comsub-posix1.sub
|
||||
@@ -0,0 +1,197 @@
|
||||
|
||||
# works right
|
||||
echo ab$(echo mnop)yz
|
||||
# works right
|
||||
echo ab$(echo mnop
|
||||
)yz
|
||||
#
|
||||
# works right
|
||||
echo $(echo ab
|
||||
)
|
||||
# works right
|
||||
echo $(
|
||||
)
|
||||
echo $()
|
||||
echo ab$()cd
|
||||
|
||||
echo $(case a in (a) echo sh_352.26ax; esac )
|
||||
echo $(case a in (a) echo sh_352.26ay; esac)
|
||||
|
||||
echo $((echo sh_352.25a);(echo sh_352.25b))
|
||||
|
||||
echo $(echo sh_352.27 ')' ")" \)
|
||||
# ) comment
|
||||
)
|
||||
|
||||
echo $(
|
||||
echo abc # a comment with )
|
||||
)
|
||||
|
||||
echo $(
|
||||
cat <<eof
|
||||
here doc with )
|
||||
eof
|
||||
)
|
||||
|
||||
echo $(
|
||||
echo ')'
|
||||
)
|
||||
|
||||
unset x
|
||||
x=$(cat <<"EOF"
|
||||
bad' syntax
|
||||
EOF
|
||||
)
|
||||
echo "$x"
|
||||
unset x
|
||||
|
||||
echo $(for f in \); do echo a; done )
|
||||
echo $(case a in a) echo sh_352.26a; esac )
|
||||
echo $(case a in a) echo sh_352.26a; esac)
|
||||
|
||||
echo $(case a in
|
||||
(a) echo sh_352.26
|
||||
;;
|
||||
esac
|
||||
)
|
||||
|
||||
echo $(case a in
|
||||
a) echo sh_352.26
|
||||
;;
|
||||
esac
|
||||
)
|
||||
|
||||
|
||||
echo $(case a in
|
||||
a) echo sh_352.26
|
||||
;;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
esac
|
||||
|
||||
)
|
||||
|
||||
echo $(( 4<(2+3) ? 1 : 32))
|
||||
|
||||
echo $(cat << end
|
||||
sh_352.28 )
|
||||
end
|
||||
)
|
||||
|
||||
echo $(cat <<- end
|
||||
sh_352.28 )
|
||||
end
|
||||
)
|
||||
|
||||
k=$(case x in x) echo k;; esac)
|
||||
echo $k
|
||||
|
||||
x=$(
|
||||
case $(ls) in
|
||||
example) echo foobix;;
|
||||
esac
|
||||
)
|
||||
|
||||
echo $( echo ab\
|
||||
cd)
|
||||
|
||||
echo `echo ab
|
||||
cd`
|
||||
|
||||
echo `echo ab #xyz
|
||||
cd`
|
||||
|
||||
echo "$(echo abcde)
|
||||
"
|
||||
|
||||
recho "$(echo abcde)
|
||||
"
|
||||
|
||||
echo $(echo abcde)\
|
||||
foo
|
||||
|
||||
recho $(echo abcde)\
|
||||
foo
|
||||
|
||||
recho "wx$(echo abcde)yz"
|
||||
recho "$(echo abcde)"
|
||||
|
||||
echo $(cat <<eof
|
||||
'
|
||||
eof
|
||||
)
|
||||
|
||||
echo after 1
|
||||
|
||||
echo $(cat <<\eof
|
||||
'
|
||||
eof
|
||||
)
|
||||
|
||||
echo after 2
|
||||
|
||||
echo "$(cat <<\eof
|
||||
'
|
||||
eof
|
||||
)"
|
||||
|
||||
echo after 3
|
||||
|
||||
echo "$(cat <<\eof
|
||||
`
|
||||
eof
|
||||
)"
|
||||
|
||||
echo after 4
|
||||
|
||||
echo $(
|
||||
cat << ')'
|
||||
hello
|
||||
)
|
||||
)
|
||||
|
||||
echo after 5
|
||||
|
||||
echo $(cat <<'eof'
|
||||
'
|
||||
eof
|
||||
)
|
||||
|
||||
echo after 6
|
||||
|
||||
echo $(
|
||||
case x in x) echo x;; esac
|
||||
)
|
||||
|
||||
echo $(
|
||||
case x in (x) echo x;; esac
|
||||
)
|
||||
|
||||
echo $(
|
||||
echo 'quoted )'
|
||||
)
|
||||
|
||||
echo $(
|
||||
echo comment # with )
|
||||
)
|
||||
|
||||
echo $(
|
||||
cat <<\eof
|
||||
here-doc with )
|
||||
eof
|
||||
)
|
||||
|
||||
echo $(
|
||||
cat <<\)
|
||||
here-doc terminated with a parenthesis
|
||||
)
|
||||
)
|
||||
|
||||
echo $(
|
||||
cat <<\eof
|
||||
' # or a single back- or doublequote
|
||||
eof
|
||||
)
|
||||
@@ -0,0 +1,3 @@
|
||||
echo $( if x; then echo foo )
|
||||
|
||||
echo after
|
||||
+4
-3
@@ -53,9 +53,10 @@ umask: usage: umask [-p] [-S] [mode]
|
||||
./errors.tests: line 159: declare: VAR: readonly variable
|
||||
./errors.tests: line 161: declare: unset: not found
|
||||
./errors.tests: line 164: VAR: readonly variable
|
||||
./errors.tests: command substitution: line 168: syntax error: unexpected end of file
|
||||
./errors.tests: command substitution: line 168: syntax error near unexpected token `done'
|
||||
./errors.tests: command substitution: line 168: ` for z in 1 2 3; done '
|
||||
./errors.tests: command substitution: line 168: syntax error near unexpected token `)'
|
||||
./errors.tests: command substitution: line 168: ` for z in 1 2 3; do )'
|
||||
./errors.tests: command substitution: line 169: syntax error near unexpected token `done'
|
||||
./errors.tests: command substitution: line 169: ` for z in 1 2 3; done )'
|
||||
./errors.tests: line 171: cd: HOME not set
|
||||
./errors.tests: line 172: cd: /tmp/xyz.bash: No such file or directory
|
||||
./errors.tests: line 174: cd: OLDPWD not set
|
||||
|
||||
@@ -54,4 +54,5 @@ exec 8<&0; cat <&8
|
||||
exec 0<&7
|
||||
exec 7<&-
|
||||
|
||||
rm -f infile
|
||||
exit 0
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
${THIS_SH} ./comsub-posix.tests > /tmp/xx 2>&1
|
||||
diff /tmp/xx comsub-posix.right && rm -f /tmp/xx
|
||||
+17
-3
@@ -1,6 +1,6 @@
|
||||
/* variables.h -- data structures for shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "stdc.h"
|
||||
#include "array.h"
|
||||
#include "assoc.h"
|
||||
|
||||
/* Shell variables and functions are stored in hash tables. */
|
||||
#include "hashlib.h"
|
||||
@@ -61,7 +62,7 @@ typedef struct var_context {
|
||||
/* 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));
|
||||
typedef struct variable *sh_var_assign_func_t __P((struct variable *, char *, arrayind_t, char *));
|
||||
|
||||
/* For the future */
|
||||
union _value {
|
||||
@@ -108,8 +109,11 @@ typedef struct _vlist {
|
||||
#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 att_uppercase 0x0000100 /* word converted to uppercase on assignment */
|
||||
#define att_lowercase 0x0000200 /* word converted to lowercase on assignment */
|
||||
#define att_capcase 0x0000400 /* word capitalized on assignment */
|
||||
|
||||
#define user_attrs (att_exported|att_readonly|att_integer|att_local|att_trace)
|
||||
#define user_attrs (att_exported|att_readonly|att_integer|att_local|att_trace|att_uppercase|att_lowercase|att_capcase)
|
||||
|
||||
#define attmask_user 0x0000fff
|
||||
|
||||
@@ -119,6 +123,7 @@ typedef struct _vlist {
|
||||
#define att_noassign 0x0004000 /* assignment not allowed */
|
||||
#define att_imported 0x0008000 /* came from environment */
|
||||
#define att_special 0x0010000 /* requires special handling */
|
||||
#define att_nofree 0x0020000 /* do not free value on unset */
|
||||
|
||||
#define attmask_int 0x00ff000
|
||||
|
||||
@@ -136,12 +141,16 @@ typedef struct _vlist {
|
||||
#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 uppercase_p(var) ((((var)->attributes) & (att_uppercase)))
|
||||
#define lowercase_p(var) ((((var)->attributes) & (att_lowercase)))
|
||||
#define capcase_p(var) ((((var)->attributes) & (att_capcase)))
|
||||
|
||||
#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 nofree_p(var) ((((var)->attributes) & (att_nofree)))
|
||||
|
||||
#define tempvar_p(var) ((((var)->attributes) & (att_tempvar)))
|
||||
|
||||
@@ -149,6 +158,7 @@ typedef struct _vlist {
|
||||
#define value_cell(var) ((var)->value)
|
||||
#define function_cell(var) (COMMAND *)((var)->value)
|
||||
#define array_cell(var) (ARRAY *)((var)->value)
|
||||
#define assoc_cell(var) (HASH_TABLE *)((var)->value)
|
||||
|
||||
#define var_isnull(var) ((var)->value == 0)
|
||||
#define var_isset(var) ((var)->value != 0)
|
||||
@@ -157,6 +167,7 @@ typedef struct _vlist {
|
||||
#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))
|
||||
#define var_setassoc(var, arr) ((var)->value = (char *)(arr))
|
||||
|
||||
/* Make VAR be auto-exported. */
|
||||
#define set_auto_export(var) \
|
||||
@@ -316,6 +327,9 @@ extern void print_var_function __P((SHELL_VAR *));
|
||||
extern SHELL_VAR *make_new_array_variable __P((char *));
|
||||
extern SHELL_VAR *make_local_array_variable __P((char *));
|
||||
|
||||
extern SHELL_VAR *make_new_assoc_variable __P((char *));
|
||||
extern SHELL_VAR *make_local_assoc_variable __P((char *));
|
||||
|
||||
extern void set_pipestatus_array __P((int *, int));
|
||||
#endif
|
||||
|
||||
|
||||
+21
-3
@@ -1,6 +1,6 @@
|
||||
/* variables.h -- data structures for shell variables. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2008 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "stdc.h"
|
||||
#include "array.h"
|
||||
#include "assoc.h"
|
||||
|
||||
/* Shell variables and functions are stored in hash tables. */
|
||||
#include "hashlib.h"
|
||||
@@ -61,7 +62,7 @@ typedef struct var_context {
|
||||
/* 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));
|
||||
typedef struct variable *sh_var_assign_func_t __P((struct variable *, char *, arrayind_t, char *));
|
||||
|
||||
/* For the future */
|
||||
union _value {
|
||||
@@ -108,8 +109,11 @@ typedef struct _vlist {
|
||||
#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 att_uppercase 0x0000100 /* word converted to uppercase on assignment */
|
||||
#define att_lowercase 0x0000200 /* word converted to lowercase on assignment */
|
||||
#define att_capcase 0x0000400 /* word capitalized on assignment */
|
||||
|
||||
#define user_attrs (att_exported|att_readonly|att_integer|att_local|att_trace)
|
||||
#define user_attrs (att_exported|att_readonly|att_integer|att_local|att_trace|att_uppercase|att_lowercase|att_capcase)
|
||||
|
||||
#define attmask_user 0x0000fff
|
||||
|
||||
@@ -119,6 +123,7 @@ typedef struct _vlist {
|
||||
#define att_noassign 0x0004000 /* assignment not allowed */
|
||||
#define att_imported 0x0008000 /* came from environment */
|
||||
#define att_special 0x0010000 /* requires special handling */
|
||||
#define att_nofree 0x0020000 /* do not free value on unset */
|
||||
|
||||
#define attmask_int 0x00ff000
|
||||
|
||||
@@ -136,12 +141,16 @@ typedef struct _vlist {
|
||||
#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 uppercase_p(var) ((((var)->attributes) & (att_uppercase)))
|
||||
#define lowercase_p(var) ((((var)->attributes) & (att_lowercase)))
|
||||
#define capcase_p(var) ((((var)->attributes) & (att_capcase)))
|
||||
|
||||
#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 nofree_p(var) ((((var)->attributes) & (att_nofree)))
|
||||
|
||||
#define tempvar_p(var) ((((var)->attributes) & (att_tempvar)))
|
||||
|
||||
@@ -149,6 +158,7 @@ typedef struct _vlist {
|
||||
#define value_cell(var) ((var)->value)
|
||||
#define function_cell(var) (COMMAND *)((var)->value)
|
||||
#define array_cell(var) (ARRAY *)((var)->value)
|
||||
#define assoc_cell(var) (HASH_TABLE *)((var)->value)
|
||||
|
||||
#define var_isnull(var) ((var)->value == 0)
|
||||
#define var_isset(var) ((var)->value != 0)
|
||||
@@ -157,6 +167,7 @@ typedef struct _vlist {
|
||||
#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))
|
||||
#define var_setassoc(var, arr) ((var)->value = (char *)(arr))
|
||||
|
||||
/* Make VAR be auto-exported. */
|
||||
#define set_auto_export(var) \
|
||||
@@ -316,6 +327,9 @@ extern void print_var_function __P((SHELL_VAR *));
|
||||
extern SHELL_VAR *make_new_array_variable __P((char *));
|
||||
extern SHELL_VAR *make_local_array_variable __P((char *));
|
||||
|
||||
extern SHELL_VAR *make_new_assoc_variable __P((char *));
|
||||
extern SHELL_VAR *make_local_assoc_variable __P((char *));
|
||||
|
||||
extern void set_pipestatus_array __P((int *, int));
|
||||
#endif
|
||||
|
||||
@@ -325,6 +339,10 @@ extern void set_pipestatus_from_exit __P((int));
|
||||
is one of the special ones where something special happens. */
|
||||
extern void stupidly_hack_special_variables __P((char *));
|
||||
|
||||
/* Reinitialize some special variables that have external effects upon unset
|
||||
when the shell reinitializes itself. */
|
||||
extern void reinit_special_variables __P((void));
|
||||
|
||||
extern int get_random_number __P((void));
|
||||
|
||||
/* The `special variable' functions that get called when a particular
|
||||
|
||||
Reference in New Issue
Block a user