mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-22 21:37:58 +02:00
commit bash-20160923 snapshot
This commit is contained in:
+127
@@ -11719,3 +11719,130 @@ print_cmd.c
|
||||
- print_deferred_heredocs: don't print heredoc headers, since they're
|
||||
now printed in print_redirection_list
|
||||
- print_deferred_heredocs: use print_heredoc_bodies
|
||||
|
||||
9/20
|
||||
----
|
||||
builtins/mapfile.def
|
||||
- readarray: update usage synopsis to include -d delim. Report and
|
||||
fix from jhankins@homewood.k12.al.us
|
||||
|
||||
test.c
|
||||
- test_binop: if op[0] == '-', make sure op[1] != 0 before checking
|
||||
op[2] or op[3]. Fixes out-of-bounds read reported by Franco
|
||||
Costantini <franco.costantini.20@gmail.com>
|
||||
|
||||
parse.y
|
||||
- cond_term: if yylval.word->word[0] == '-' make sure word[1] != 0
|
||||
before checking word[2] and calling test_unop. Fixes out-of-bounds
|
||||
read reported by Franco Costantini <franco.costantini.20@gmail.com>
|
||||
- make sure to check all instances of the return value of the
|
||||
simple_command production before trying to hook redirections onto it,
|
||||
since it can potentially return NULL.
|
||||
Reported by Franco Costantini <franco.costantini.20@gmail.com>
|
||||
|
||||
9/21
|
||||
----
|
||||
parse.y
|
||||
- token_is_assignment: make sure to check that the return value from
|
||||
assignment() finds the `=' we just added at index I to avoid false
|
||||
positives from g=g=g=g=g=g=(). Reported by Franco Costantini
|
||||
<franco.costantini.20@gmail.com>
|
||||
|
||||
9/22
|
||||
----
|
||||
parse.y
|
||||
- token_is_assignment: if we're not using the bash malloc (which has
|
||||
guard bytes after the requested allocation size), use a new
|
||||
buffer so we can make sure it's big enough to hold the current
|
||||
token and at least two additional characters. Reported by
|
||||
Franco Costantini <franco.costantini.20@gmail.com>
|
||||
|
||||
9/23
|
||||
----
|
||||
execute_command.c
|
||||
- execute_in_subshell: call without_job_control for both job control
|
||||
and non-job-control builds to avoid waiting for last_made_pid
|
||||
inherited from parent shell. Related to fix from 8/4 to
|
||||
initialize_subshell. Fixes bug reported by Martijn Dekker
|
||||
<martijn@inlv.org>
|
||||
|
||||
builtins/declare.def
|
||||
- local_builtin: allow `local --help' to work even when not executing
|
||||
a function. Suggestion from Norm Abramovitz <norm@starkandwayne.com>
|
||||
|
||||
9/25
|
||||
----
|
||||
builtins/printf.def
|
||||
- bexpand: if passed a null or empty string, return a newly-allocated
|
||||
empty string (so the return value can always be freed) instead of
|
||||
NULL.
|
||||
- printstr: if passed a null string, treat it as if it were an empty
|
||||
string so any precision or fieldwidth arguments are handled
|
||||
correctly. Report from isabella parakiss <izaberina@gmail.com>
|
||||
|
||||
subst.c
|
||||
- skip_matched_pair: make the flags argument of 1 affect whether or
|
||||
not backslash can quote characters in the string, so it affects
|
||||
all quoting mechanisms
|
||||
|
||||
arrayfunc.c
|
||||
- unbind_array_element: now takes a third (flags) argument; flags&1
|
||||
means to not expand an associative array index. This is only called
|
||||
from a shell builtin context, which means the argument should have
|
||||
already undergone word expansion, so it should be ok. Will still
|
||||
be a problem for uses like "unset -v 'var[$ind]'", quoted to avoid
|
||||
globbing
|
||||
- valid_array_reference: pass second flags argument to skipsubscript;
|
||||
still set to 0 by all callers
|
||||
|
||||
arrayfunc.h
|
||||
- unbind_array_element: updated prototype
|
||||
|
||||
builtins/set.def
|
||||
- unset_builtin: add third argument of 1 to unbind_array_element calls
|
||||
[TEMPORARILY DISABLED]
|
||||
- unset_builtin: call valid_array_reference with second arg of 1 to
|
||||
handle unmatched pairs of quotes and [/]
|
||||
|
||||
array.c
|
||||
- array_reference: optimize access locality as well as sequential
|
||||
access by adding ability to start from last-accessed element and move
|
||||
backwards or forwards depending on the desired index. Inspired by
|
||||
report from Tom McCurdy <tom.j.mccurdy@gmail.com> and followup from
|
||||
Christian Franke <Christian.Franke@t-online.de>
|
||||
|
||||
variables.c
|
||||
- all_array_variables: include associative arrays, not just indexed
|
||||
arrays. Reported by Grisha Levit <grishalevit@gmail.com>
|
||||
|
||||
execute_cmd.c
|
||||
- execute_disk_command: if we're optimizing out the fork (CMD_NO_FORK),
|
||||
decrement the shell level so we don't end up incrementing it twice.
|
||||
We should decrement the shell level for an implicit exec like an
|
||||
explicit one. Reported by Stephane Chazelas
|
||||
<stephane.chazelas@gmail.com>
|
||||
|
||||
builtins/exec.def
|
||||
- exec_builtin: don't bother to decrement the shell level if we are
|
||||
already in a `(command)' subshell. Reported by Stephane Chazelas
|
||||
<stephane.chazelas@gmail.com>
|
||||
|
||||
lib/readline/macro.c
|
||||
- macro_level: count of macro nesting level, maintained by
|
||||
_rl_push_executing_macro and _rl_pop_executing macro
|
||||
- _rl_with_macro_input: if current nesting level exceeds
|
||||
MAX_MACRO_LEVEL, abort the current command line with _rl_abort_internal
|
||||
and return to the top level. Reported by Christian Klomp
|
||||
<christianklomp@gmail.com>
|
||||
|
||||
lib/readine/history.c
|
||||
- add_history: if allocating the history list for the first time,
|
||||
make sure the max history list size isn't so large that it will
|
||||
cause allocation errors. Cap it at MAX_HISTORY_INITIAL_SIZE
|
||||
(8192). Reported by Sean Zha <freeman_cha@hotmail.com>
|
||||
|
||||
jobs.c
|
||||
- wait_for: if a foreground job with job control enabled is killed by a
|
||||
SIGINT and sourcelevel != 0, act as if we received the SIGINT so the
|
||||
file sourcing can be terminated. Reported by PePa
|
||||
<peterkelly@passchier.net>
|
||||
|
||||
@@ -67,6 +67,8 @@ static ARRAY_ELEMENT *lastref = 0;
|
||||
(IS_LASTREF(a) && i >= element_index(lastref)) ? lastref \
|
||||
: element_forw(a->head)
|
||||
|
||||
#define LASTREF(a) IS_LASTREF(a) ? lastref : element_forw(a->head)
|
||||
|
||||
#define INVALIDATE_LASTREF(a) \
|
||||
do { \
|
||||
if ((a) == lastarray) { \
|
||||
@@ -711,17 +713,31 @@ ARRAY *a;
|
||||
arrayind_t i;
|
||||
{
|
||||
register ARRAY_ELEMENT *ae, *start;
|
||||
arrayind_t startind;
|
||||
int direction;
|
||||
|
||||
if (a == 0 || array_empty(a))
|
||||
return((char *) NULL);
|
||||
if (i > array_max_index(a))
|
||||
return((char *)NULL); /* Keep roving pointer into array to optimize sequential access */
|
||||
start = LASTREF_START(a, i);
|
||||
for (ae = start; ae != a->head; ae = element_forw(ae))
|
||||
start = LASTREF(a); /* lastref pointer */
|
||||
startind = element_index(start);
|
||||
if (i < startind/2) { /* XXX - guess */
|
||||
start = element_forw(a->head);
|
||||
startind = element_index(start);
|
||||
direction = 1;
|
||||
} else if (i >= startind) {
|
||||
direction = 1;
|
||||
} else {
|
||||
direction = -1;
|
||||
}
|
||||
for (ae = start; ae != a->head; ) {
|
||||
if (element_index(ae) == i) {
|
||||
SET_LASTREF(a, ae);
|
||||
return(element_value(ae));
|
||||
}
|
||||
ae = (direction == 1) ? element_forw(ae) : element_back(ae);
|
||||
}
|
||||
UNSET_LASTREF(); /* XXX SET_LASTREF(a, start) ? */
|
||||
return((char *) NULL);
|
||||
}
|
||||
|
||||
+6
-4
@@ -760,9 +760,10 @@ quote_array_assignment_chars (list)
|
||||
`[' of an array subscript and removes the array element to which SUB
|
||||
expands from array VAR. A subscript of `*' or `@' unsets the array. */
|
||||
int
|
||||
unbind_array_element (var, sub)
|
||||
unbind_array_element (var, sub, flags)
|
||||
SHELL_VAR *var;
|
||||
char *sub;
|
||||
int flags;
|
||||
{
|
||||
int len;
|
||||
arrayind_t ind;
|
||||
@@ -790,7 +791,7 @@ unbind_array_element (var, sub)
|
||||
|
||||
if (assoc_p (var))
|
||||
{
|
||||
akey = expand_assignment_string_to_string (sub, 0); /* [ */
|
||||
akey = (flags & 1) ? sub : expand_assignment_string_to_string (sub, 0);
|
||||
if (akey == 0 || *akey == 0)
|
||||
{
|
||||
builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg));
|
||||
@@ -798,7 +799,8 @@ unbind_array_element (var, sub)
|
||||
return -1;
|
||||
}
|
||||
assoc_remove (assoc_cell (var), akey);
|
||||
free (akey);
|
||||
if (akey != sub)
|
||||
free (akey);
|
||||
}
|
||||
else if (array_p (var))
|
||||
{
|
||||
@@ -896,7 +898,7 @@ valid_array_reference (name, flags)
|
||||
if (r == 0)
|
||||
return 0;
|
||||
/* Check for a properly-terminated non-blank subscript. */
|
||||
len = skipsubscript (t, 0, 0);
|
||||
len = skipsubscript (t, 0, flags);
|
||||
if (t[len] != ']' || len == 1)
|
||||
return 0;
|
||||
if (t[len+1] != '\0')
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ extern WORD_LIST *expand_compound_array_assignment __P((SHELL_VAR *, char *, int
|
||||
extern void assign_compound_array_list __P((SHELL_VAR *, WORD_LIST *, int));
|
||||
extern SHELL_VAR *assign_array_var_from_string __P((SHELL_VAR *, char *, int));
|
||||
|
||||
extern int unbind_array_element __P((SHELL_VAR *, char *));
|
||||
extern int unbind_array_element __P((SHELL_VAR *, char *, int));
|
||||
extern int skipsubscript __P((const char *, int, int));
|
||||
|
||||
extern void print_array_assignment __P((SHELL_VAR *, int));
|
||||
|
||||
@@ -120,6 +120,13 @@ int
|
||||
local_builtin (list)
|
||||
register WORD_LIST *list;
|
||||
{
|
||||
/* Catch a straight `local --help' before checking function context */
|
||||
if (list && list->word && STREQ (list->word->word, "--help"))
|
||||
{
|
||||
builtin_help ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
if (variable_context)
|
||||
return (declare_internal (list, 1));
|
||||
else
|
||||
|
||||
+5
-2
@@ -190,8 +190,11 @@ exec_builtin (list)
|
||||
|
||||
/* Decrement SHLVL by 1 so a new shell started here has the same value,
|
||||
preserving the appearance. After we do that, we need to change the
|
||||
exported environment to include the new value. */
|
||||
if (cleanenv == 0)
|
||||
exported environment to include the new value. If we've already forked
|
||||
and are in a subshell, we don't want to decrement the shell level,
|
||||
since we are `increasing' the level */
|
||||
|
||||
if (cleanenv == 0 && (subshell_environment & SUBSHELL_PAREN) == 0)
|
||||
adjust_shell_level (-1);
|
||||
|
||||
if (cleanenv)
|
||||
|
||||
@@ -59,7 +59,7 @@ $END
|
||||
|
||||
$BUILTIN readarray
|
||||
$FUNCTION mapfile_builtin
|
||||
$SHORT_DOC readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
|
||||
$SHORT_DOC readarray [-d delim] [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
|
||||
Read lines from a file into an array variable.
|
||||
|
||||
A synonym for `mapfile'.
|
||||
|
||||
+5
-3
@@ -711,8 +711,8 @@ printstr (fmt, string, len, fieldwidth, precision)
|
||||
int fw, pr; /* fieldwidth and precision */
|
||||
intmax_t mfw, mpr;
|
||||
|
||||
if (string == 0 || len == 0)
|
||||
return 0;
|
||||
if (string == 0)
|
||||
string = "";
|
||||
|
||||
#if 0
|
||||
s = fmt;
|
||||
@@ -955,7 +955,9 @@ bexpand (string, len, sawc, lenp)
|
||||
*sawc = 0;
|
||||
if (lenp)
|
||||
*lenp = 0;
|
||||
return ((char *)NULL);
|
||||
ret = (char *)xmalloc (1);
|
||||
ret[0] = '\0';
|
||||
return (ret);
|
||||
}
|
||||
|
||||
ret = (char *)xmalloc (len + 1);
|
||||
|
||||
+12
-4
@@ -859,7 +859,7 @@ unset_builtin (list)
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
unset_array = 0;
|
||||
if (!unset_function && nameref == 0 && valid_array_reference (name, 0))
|
||||
if (!unset_function && nameref == 0 && valid_array_reference (name, 1)) /* XXX valid array reference second arg was 0 */
|
||||
{
|
||||
t = strchr (name, '[');
|
||||
*t++ = '\0';
|
||||
@@ -916,7 +916,11 @@ unset_builtin (list)
|
||||
if (var && unset_array)
|
||||
{
|
||||
/* Let unbind_array_element decide what to do with non-array vars */
|
||||
tem = unbind_array_element (var, t);
|
||||
#if 0
|
||||
tem = unbind_array_element (var, t, 1); /* XXX new third arg */
|
||||
#else
|
||||
tem = unbind_array_element (var, t, 0); /* XXX new third arg */
|
||||
#endif
|
||||
if (tem == -2 && array_p (var) == 0 && assoc_p (var) == 0)
|
||||
{
|
||||
builtin_error (_("%s: not an array variable"), var->name);
|
||||
@@ -938,8 +942,12 @@ unset_builtin (list)
|
||||
if (valid_array_reference (nameref_cell (var), 0))
|
||||
{
|
||||
tname = savestring (nameref_cell (var));
|
||||
if (var = array_variable_part (tname, &t, 0))
|
||||
tem = unbind_array_element (var, t);
|
||||
if (var = array_variable_part (tname, &t, (int *)0))
|
||||
#if 0
|
||||
tem = unbind_array_element (var, t, 1); /* XXX new third arg */
|
||||
#else
|
||||
tem = unbind_array_element (var, t, 0); /* XXX new third arg */
|
||||
#endif
|
||||
free (tname);
|
||||
}
|
||||
else
|
||||
|
||||
+1
-1
@@ -3202,7 +3202,7 @@ format that can be reused as input.
|
||||
.TP
|
||||
.B E
|
||||
The expansion is a string that is the value of \fIparameter\fP with backslash
|
||||
escape sequences expanded as with the \fB$'...'\fP quoting mechansim.
|
||||
escape sequences expanded as with the \fB$'...'\fP quoting mechanism.
|
||||
.TP
|
||||
.B P
|
||||
The expansion is a string that is the result of expanding the value of
|
||||
|
||||
+5
-2
@@ -1532,11 +1532,9 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
|
||||
|
||||
set_sigint_handler ();
|
||||
|
||||
#if defined (JOB_CONTROL)
|
||||
/* Delete all traces that there were any jobs running. This is
|
||||
only for subshells. */
|
||||
without_job_control ();
|
||||
#endif /* JOB_CONTROL */
|
||||
|
||||
if (fds_to_close)
|
||||
close_fd_bitmap (fds_to_close);
|
||||
@@ -5162,6 +5160,11 @@ execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
|
||||
|
||||
if (command)
|
||||
{
|
||||
/* If we're optimizing out the fork (implicit `exec'), decrement the
|
||||
shell level like `exec' would do. */
|
||||
if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
|
||||
adjust_shell_level (-1);
|
||||
|
||||
maybe_make_export_env ();
|
||||
put_command_name_into_env (command);
|
||||
}
|
||||
|
||||
@@ -1267,7 +1267,7 @@ readtok ()
|
||||
#if defined (ARRAY_VARS)
|
||||
if (c == '[')
|
||||
{
|
||||
e = skipsubscript (cp, 0, 0);
|
||||
e = skipsubscript (cp, 0, 1); /* XXX - arg 3 was 0 */
|
||||
if (cp[e] == ']')
|
||||
{
|
||||
cp += e + 1;
|
||||
|
||||
@@ -2866,6 +2866,10 @@ if (job == NO_JOB)
|
||||
loop. */
|
||||
else if (signal_is_trapped (SIGINT) && loop_level)
|
||||
ADDINTERRUPT;
|
||||
/* If an interactive shell with job control enabled is sourcing
|
||||
a file, allow the interrupt to terminate the file sourcing. */
|
||||
else if (interactive_shell && signal_is_trapped (SIGINT) == 0 && sourcelevel)
|
||||
ADDINTERRUPT;
|
||||
else
|
||||
{
|
||||
putchar ('\n');
|
||||
|
||||
+2
-2
@@ -390,10 +390,10 @@ xstrmatch (pattern, string, flags)
|
||||
wchar_t *wpattern, *wstring;
|
||||
size_t plen, slen, mplen, mslen;
|
||||
|
||||
if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
|
||||
if (MB_CUR_MAX == 1)
|
||||
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
|
||||
|
||||
if (MB_CUR_MAX == 1)
|
||||
if (mbsmbchar (string) == 0 && mbsmbchar (pattern) == 0)
|
||||
return (internal_strmatch ((unsigned char *)pattern, (unsigned char *)string, flags));
|
||||
|
||||
n = xdupmbstowcs (&wpattern, NULL, pattern);
|
||||
|
||||
@@ -57,6 +57,8 @@ extern int errno;
|
||||
/* How big to make the_history when we first allocate it. */
|
||||
#define DEFAULT_HISTORY_INITIAL_SIZE 502
|
||||
|
||||
#define MAX_HISTORY_INITIAL_SIZE 8192
|
||||
|
||||
/* The number of slots to increase the_history by. */
|
||||
#define DEFAULT_HISTORY_GROW_SIZE 50
|
||||
|
||||
@@ -307,7 +309,9 @@ add_history (string)
|
||||
if (history_size == 0)
|
||||
{
|
||||
if (history_stifled && history_max_entries > 0)
|
||||
history_size = history_max_entries + 2;
|
||||
history_size = (history_max_entries > MAX_HISTORY_INITIAL_SIZE)
|
||||
? MAX_HISTORY_INITIAL_SIZE
|
||||
: history_max_entries + 2;
|
||||
else
|
||||
history_size = DEFAULT_HISTORY_INITIAL_SIZE;
|
||||
the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#include "rlprivate.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#define MAX_MACRO_LEVEL 16
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Hacking Keyboard Macros */
|
||||
@@ -83,12 +85,21 @@ struct saved_macro {
|
||||
/* The list of saved macros. */
|
||||
static struct saved_macro *macro_list = (struct saved_macro *)NULL;
|
||||
|
||||
static int macro_level = 0;
|
||||
|
||||
/* Set up to read subsequent input from STRING.
|
||||
STRING is free ()'ed when we are done with it. */
|
||||
void
|
||||
_rl_with_macro_input (string)
|
||||
char *string;
|
||||
{
|
||||
if (macro_level > MAX_MACRO_LEVEL)
|
||||
{
|
||||
_rl_errmsg ("maximum macro execution nesting level exceeded");
|
||||
_rl_abort_internal ();
|
||||
return;
|
||||
}
|
||||
|
||||
_rl_push_executing_macro ();
|
||||
rl_executing_macro = string;
|
||||
executing_macro_index = 0;
|
||||
@@ -146,6 +157,8 @@ _rl_push_executing_macro ()
|
||||
saver->string = rl_executing_macro;
|
||||
|
||||
macro_list = saver;
|
||||
|
||||
macro_level++;
|
||||
}
|
||||
|
||||
/* Discard the current macro, replacing it with the one
|
||||
@@ -168,6 +181,8 @@ _rl_pop_executing_macro ()
|
||||
xfree (macro);
|
||||
}
|
||||
|
||||
macro_level--;
|
||||
|
||||
if (rl_executing_macro == 0)
|
||||
RL_UNSETSTATE(RL_STATE_MACROINPUT);
|
||||
}
|
||||
|
||||
@@ -744,14 +744,14 @@ command: simple_command
|
||||
COMMAND *tc;
|
||||
|
||||
tc = $1;
|
||||
if (tc->redirects)
|
||||
if (tc && tc->redirects)
|
||||
{
|
||||
register REDIRECT *t;
|
||||
for (t = tc->redirects; t->next; t = t->next)
|
||||
;
|
||||
t->next = $2;
|
||||
}
|
||||
else
|
||||
else if (tc)
|
||||
tc->redirects = $2;
|
||||
$$ = $1;
|
||||
}
|
||||
@@ -830,21 +830,25 @@ for_command: FOR WORD newline_list DO compound_list DONE
|
||||
arith_for_command: FOR ARITH_FOR_EXPRS list_terminator newline_list DO compound_list DONE
|
||||
{
|
||||
$$ = make_arith_for_command ($2, $6, arith_for_lineno);
|
||||
/* if ($$ == 0) YYERROR; */
|
||||
if (word_top > 0) word_top--;
|
||||
}
|
||||
| FOR ARITH_FOR_EXPRS list_terminator newline_list '{' compound_list '}'
|
||||
{
|
||||
$$ = make_arith_for_command ($2, $6, arith_for_lineno);
|
||||
/* if ($$ == 0) YYERROR; */
|
||||
if (word_top > 0) word_top--;
|
||||
}
|
||||
| FOR ARITH_FOR_EXPRS DO compound_list DONE
|
||||
{
|
||||
$$ = make_arith_for_command ($2, $4, arith_for_lineno);
|
||||
/* if ($$ == 0) YYERROR; */
|
||||
if (word_top > 0) word_top--;
|
||||
}
|
||||
| FOR ARITH_FOR_EXPRS '{' compound_list '}'
|
||||
{
|
||||
$$ = make_arith_for_command ($2, $4, arith_for_lineno);
|
||||
/* if ($$ == 0) YYERROR; */
|
||||
if (word_top > 0) word_top--;
|
||||
}
|
||||
;
|
||||
@@ -928,14 +932,14 @@ function_body: shell_command
|
||||
redirection. The two are semantically equivalent,
|
||||
though -- the only difference is in how the
|
||||
command printing code displays the redirections. */
|
||||
if (tc->redirects)
|
||||
if (tc && tc->redirects)
|
||||
{
|
||||
register REDIRECT *t;
|
||||
for (t = tc->redirects; t->next; t = t->next)
|
||||
;
|
||||
t->next = $2;
|
||||
}
|
||||
else
|
||||
else if (tc)
|
||||
tc->redirects = $2;
|
||||
$$ = $1;
|
||||
}
|
||||
@@ -958,14 +962,14 @@ coproc: COPROC shell_command
|
||||
COMMAND *tc;
|
||||
|
||||
tc = $2;
|
||||
if (tc->redirects)
|
||||
if (tc && tc->redirects)
|
||||
{
|
||||
register REDIRECT *t;
|
||||
for (t = tc->redirects; t->next; t = t->next)
|
||||
;
|
||||
t->next = $3;
|
||||
}
|
||||
else
|
||||
else if (tc)
|
||||
tc->redirects = $3;
|
||||
$$ = make_coproc_command ("COPROC", $2);
|
||||
$$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
|
||||
@@ -980,14 +984,14 @@ coproc: COPROC shell_command
|
||||
COMMAND *tc;
|
||||
|
||||
tc = $3;
|
||||
if (tc->redirects)
|
||||
if (tc && tc->redirects)
|
||||
{
|
||||
register REDIRECT *t;
|
||||
for (t = tc->redirects; t->next; t = t->next)
|
||||
;
|
||||
t->next = $4;
|
||||
}
|
||||
else
|
||||
else if (tc)
|
||||
tc->redirects = $4;
|
||||
$$ = make_coproc_command ($2->word, $3);
|
||||
$$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
|
||||
@@ -4512,7 +4516,7 @@ cond_term ()
|
||||
if (term)
|
||||
term->flags |= CMD_INVERT_RETURN;
|
||||
}
|
||||
else if (tok == WORD && yylval.word->word[0] == '-' && yylval.word->word[2] == 0 && test_unop (yylval.word->word))
|
||||
else if (tok == WORD && yylval.word->word[0] == '-' && yylval.word->word[1] && yylval.word->word[2] == 0 && test_unop (yylval.word->word))
|
||||
{
|
||||
op = yylval.word;
|
||||
tok = read_token (READ);
|
||||
@@ -4651,14 +4655,34 @@ token_is_assignment (t, i)
|
||||
char *t;
|
||||
int i;
|
||||
{
|
||||
unsigned char c, c1;
|
||||
int r;
|
||||
|
||||
#if !defined (USING_BASH_MALLOC)
|
||||
static char *token = 0;
|
||||
|
||||
token = xrealloc (token, i + 3);
|
||||
memcpy (token, t, i);
|
||||
token[i] = '=';
|
||||
token[i+1] = '\0';
|
||||
|
||||
r = assignment (token, (parser_state & PST_COMPASSIGN) != 0);
|
||||
|
||||
if (i + 3 > 4096) /* keep it from getting too big */
|
||||
{
|
||||
free (token);
|
||||
token = 0;
|
||||
}
|
||||
#else
|
||||
unsigned char c, c1;
|
||||
|
||||
c = t[i]; c1 = t[i+1];
|
||||
t[i] = '='; t[i+1] = '\0';
|
||||
r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
|
||||
t[i] = c; t[i+1] = c1;
|
||||
return r;
|
||||
#endif
|
||||
/* XXX - check that r == i to avoid returning false positive for
|
||||
t containing `=' before t[i]. */
|
||||
return (r > 0 && r == i);
|
||||
}
|
||||
|
||||
/* XXX - possible changes here for `+=' */
|
||||
|
||||
@@ -1683,7 +1683,8 @@ unquote_bang (string)
|
||||
parse array subscripts. FLAGS & 1 means to not attempt to skip over
|
||||
matched pairs of quotes or backquotes, or skip word expansions; it is
|
||||
intended to be used after expansion has been performed and during final
|
||||
assignment parsing (see arrayfunc.c:assign_compound_array_list()). */
|
||||
assignment parsing (see arrayfunc.c:assign_compound_array_list()) or
|
||||
during execution by a builtin which has already undergone word expansion. */
|
||||
static int
|
||||
skip_matched_pair (string, start, open, close, flags)
|
||||
const char *string;
|
||||
@@ -1712,7 +1713,7 @@ skip_matched_pair (string, start, open, close, flags)
|
||||
ADVANCE_CHAR (string, slen, i);
|
||||
continue;
|
||||
}
|
||||
else if (c == '\\')
|
||||
else if ((flags & 1) == 0 && c == '\\')
|
||||
{
|
||||
pass_next = 1;
|
||||
i++;
|
||||
|
||||
@@ -670,7 +670,7 @@ test_binop (op)
|
||||
else if (op[2] == '\0' && op[1] == '~' && (op[0] == '=' || op[0] == '!'))
|
||||
return (1);
|
||||
#endif
|
||||
else if (op[0] != '-' || op[2] == '\0' || op[3] != '\0')
|
||||
else if (op[0] != '-' || op[1] == '\0' || op[2] == '\0' || op[3] != '\0')
|
||||
return (0);
|
||||
else
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
BUILD_DIR=/usr/local/build/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
|
||||
+4
-4
@@ -20,7 +20,7 @@ jkl mno
|
||||
fff is a function
|
||||
fff ()
|
||||
{
|
||||
ed /tmp/foo > /dev/null <<ENDOFINPUT
|
||||
ed /tmp/foo <<ENDOFINPUT > /dev/null
|
||||
/^name/d
|
||||
w
|
||||
q
|
||||
@@ -31,7 +31,7 @@ ENDOFINPUT
|
||||
fff is a function
|
||||
fff ()
|
||||
{
|
||||
ed /tmp/foo > /dev/null <<ENDOFINPUT
|
||||
ed /tmp/foo <<ENDOFINPUT > /dev/null
|
||||
/^name/d
|
||||
w
|
||||
q
|
||||
@@ -43,11 +43,11 @@ foo is a function
|
||||
foo ()
|
||||
{
|
||||
echo;
|
||||
cat <<END
|
||||
cat <<END
|
||||
bar
|
||||
END
|
||||
|
||||
cat <<EOF
|
||||
cat <<EOF
|
||||
qux
|
||||
EOF
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ b
|
||||
|
||||
xx
|
||||
xx
|
||||
< >< >
|
||||
one
|
||||
one\ctwo
|
||||
4\.2
|
||||
|
||||
+3
-1
@@ -308,6 +308,9 @@ shopt -s nullglob extglob
|
||||
echo "x$(printf "%b" @(hugo))x"
|
||||
printf -v var "%b" @(hugo); echo "x${var}x"
|
||||
|
||||
# make sure that missing arguments are always handled like the empty string
|
||||
printf "<%3s><%3b>\n"
|
||||
|
||||
# tests variable assignment with -v
|
||||
${THIS_SH} ./printf1.sub
|
||||
|
||||
@@ -316,4 +319,3 @@ ${THIS_SH} ./printf2.sub
|
||||
${THIS_SH} ./printf3.sub
|
||||
|
||||
${THIS_SH} ./printf4.sub
|
||||
|
||||
|
||||
+7
-7
@@ -65,11 +65,11 @@ foo is a function
|
||||
foo ()
|
||||
{
|
||||
echo;
|
||||
cat <<END
|
||||
cat <<END
|
||||
bar
|
||||
END
|
||||
|
||||
cat <<EOF
|
||||
cat <<EOF
|
||||
qux
|
||||
EOF
|
||||
|
||||
@@ -86,7 +86,7 @@ foo ()
|
||||
rm -f a b c;
|
||||
for f in a b c;
|
||||
do
|
||||
cat >> ${f} <<-EOF
|
||||
cat <<-EOF >> ${f}
|
||||
file
|
||||
EOF
|
||||
|
||||
@@ -99,7 +99,7 @@ c:file
|
||||
bb is a function
|
||||
bb ()
|
||||
{
|
||||
( cat <<EOF
|
||||
( cat <<EOF
|
||||
foo
|
||||
bar
|
||||
EOF
|
||||
@@ -110,13 +110,13 @@ mkcoprocs is a function
|
||||
mkcoprocs ()
|
||||
{
|
||||
coproc a {
|
||||
cat <<EOF1
|
||||
cat <<EOF1
|
||||
producer 1
|
||||
EOF1
|
||||
|
||||
}
|
||||
coproc b {
|
||||
cat <<EOF2
|
||||
cat <<EOF2
|
||||
producer 2
|
||||
EOF2
|
||||
|
||||
@@ -126,7 +126,7 @@ EOF2
|
||||
mkcoprocs is a function
|
||||
mkcoprocs ()
|
||||
{
|
||||
coproc COPROC ( b cat <<EOF
|
||||
coproc COPROC ( b cat <<EOF
|
||||
heredoc
|
||||
body
|
||||
EOF
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ line 3
|
||||
bar is a function
|
||||
bar ()
|
||||
{
|
||||
exec {v}<<EOF
|
||||
exec {v}<<EOF
|
||||
line 1
|
||||
line 2
|
||||
line 3
|
||||
|
||||
+2
-2
@@ -3030,7 +3030,7 @@ bind_int_variable (lhs, rhs)
|
||||
v = bind_array_variable (lhs, 0, rhs, 0);
|
||||
else
|
||||
#endif
|
||||
v = bind_variable (lhs, rhs, 0);
|
||||
v = bind_variable (lhs, rhs, 0); /* why not use bind_variable_value? */
|
||||
|
||||
if (v)
|
||||
{
|
||||
@@ -3960,7 +3960,7 @@ static int
|
||||
visible_array_vars (var)
|
||||
SHELL_VAR *var;
|
||||
{
|
||||
return (invisible_p (var) == 0 && array_p (var));
|
||||
return (invisible_p (var) == 0 && (array_p (var) || assoc_p (var)));
|
||||
}
|
||||
|
||||
SHELL_VAR **
|
||||
|
||||
Reference in New Issue
Block a user