- lcut: new builtin that does what cut does but on a string supplied
as an argument (only one string for now)
+ 4/17
+ ----
+jobs.h
+ - FORK_SYNC,FORK_ASYNC,FORK_NOJOB: new flag values for the second
+ argument to make_child
+
+jobs.c
+ - make_child: now takes a set of flags as the second argument
+
+execute_cmd.c
+ - make_child: change callers to pass FORK_ASYNC instead of a non-zero
+ value as the second argument
+
+subst.c
+ - make_child: change callers to pass FORK_ASYNC instead of a non-zero
+ value as the second argument
+
+doc/{bash.1,bashref.texi}
+ - document that the words in a compound array assignment undergo all
+ the shell word expansions, including filename generation and word
+ splitting. From a report from E. Choroba <choroba@matfyz.cz>
+
+ 4/18
+ ----
+subst.c
+ - command_substitute: use JOB_CONTROL instead of INTERACTIVE in the
+ test to determine whether or not to give the terminal back to
+ pipeline_pgrp
+
+jobs.c
+ - make_child: if FORK_NOTERM is set in the flags argument, don't call
+ give_terminal_to
+
+{jobs,nojobs}.c,jobs.h
+ - wait_for: now takes a second argument, a flags word
+
+{execute_cmd,subst}.c
+ - wait_for: change all callers to add second argument to wait_for
+
+jobs.c
+ - wait_for: if JWAIT_NOTERM is set in the flags argument, don't call
+ give_terminal_to
+
+ 4/19
+ ----
+subst.c
+ - command_substitute: block SIGINT around call to read_comsub, so we
+ let any interrupts affect the command substitution. Fixes issue
+ reported by DALECKI Léo <leo.dalecki@ntymail.com>
+
+hashcmd.h
+ - FILENAME_HASH_BUCKETS: increase to 256
+
+assoc.h
+ - ASSOC_HASH_BUCKETS: new define, set to 1024
+
+variables.c
+ - make_new_assoc_variable,make_local_assoc_variable: call assoc_create
+ with ASSOC_HASH_BUCKETS as argument. This changes the hash function
+ and how the array keys are ordered (which is not guaranteed)
+
+builtins/read.def
+ - read_builtin: in posix mode, or if the read call returns -1/EINTR,
+ don't call run_pending_traps until the read command returns. This
+ allows a trap action to see the same exit status that the read
+ builtin would return when it exits on a signal (e.g., SIGINT == 130).
+ From a suggestion by <gentoo_eshoes@tutanota.com>
/* assoc.h -- definitions for the interface exported by assoc.c that allows
the rest of the shell to manipulate associative array variables. */
-/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
+/* Copyright (C) 2008,2009-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
#include "stdc.h"
#include "hashlib.h"
+#define ASSOC_HASH_BUCKETS 1024
+
#define assoc_empty(h) ((h)->nentries == 0)
#define assoc_num_elements(h) ((h)->nentries)
#define assoc_walk(h, f) (hash_walk((h), (f))
-extern void assoc_dispose __P((HASH_TABLE *));
-extern void assoc_flush __P((HASH_TABLE *));
+extern void assoc_dispose PARAMS((HASH_TABLE *));
+extern void assoc_flush PARAMS((HASH_TABLE *));
-extern int assoc_insert __P((HASH_TABLE *, char *, char *));
-extern PTR_T assoc_replace __P((HASH_TABLE *, char *, char *));
-extern void assoc_remove __P((HASH_TABLE *, char *));
+extern int assoc_insert PARAMS((HASH_TABLE *, char *, char *));
+extern PTR_T assoc_replace PARAMS((HASH_TABLE *, char *, char *));
+extern void assoc_remove PARAMS((HASH_TABLE *, char *));
-extern char *assoc_reference __P((HASH_TABLE *, char *));
+extern char *assoc_reference PARAMS((HASH_TABLE *, char *));
-extern char *assoc_subrange __P((HASH_TABLE *, arrayind_t, arrayind_t, int, int, int));
-extern char *assoc_patsub __P((HASH_TABLE *, char *, char *, int));
-extern char *assoc_modcase __P((HASH_TABLE *, char *, int, int));
+extern char *assoc_subrange PARAMS((HASH_TABLE *, arrayind_t, arrayind_t, int, int, int));
+extern char *assoc_patsub PARAMS((HASH_TABLE *, char *, char *, int));
+extern char *assoc_modcase PARAMS((HASH_TABLE *, char *, int, int));
-extern HASH_TABLE *assoc_quote __P((HASH_TABLE *));
-extern HASH_TABLE *assoc_quote_escapes __P((HASH_TABLE *));
-extern HASH_TABLE *assoc_dequote __P((HASH_TABLE *));
-extern HASH_TABLE *assoc_dequote_escapes __P((HASH_TABLE *));
-extern HASH_TABLE *assoc_remove_quoted_nulls __P((HASH_TABLE *));
+extern HASH_TABLE *assoc_quote PARAMS((HASH_TABLE *));
+extern HASH_TABLE *assoc_quote_escapes PARAMS((HASH_TABLE *));
+extern HASH_TABLE *assoc_dequote PARAMS((HASH_TABLE *));
+extern HASH_TABLE *assoc_dequote_escapes PARAMS((HASH_TABLE *));
+extern HASH_TABLE *assoc_remove_quoted_nulls PARAMS((HASH_TABLE *));
-extern char *assoc_to_kvpair __P((HASH_TABLE *, int));
-extern char *assoc_to_assign __P((HASH_TABLE *, int));
+extern char *assoc_to_kvpair PARAMS((HASH_TABLE *, int));
+extern char *assoc_to_assign PARAMS((HASH_TABLE *, int));
-extern WORD_LIST *assoc_to_word_list __P((HASH_TABLE *));
-extern WORD_LIST *assoc_keys_to_word_list __P((HASH_TABLE *));
+extern WORD_LIST *assoc_to_word_list PARAMS((HASH_TABLE *));
+extern WORD_LIST *assoc_keys_to_word_list PARAMS((HASH_TABLE *));
-extern char *assoc_to_string __P((HASH_TABLE *, char *, int));
+extern char *assoc_to_string PARAMS((HASH_TABLE *, char *, int));
#endif /* _ASSOC_H_ */
lastsig = LASTSIG();
if (lastsig == 0)
lastsig = trapped_signal_received;
+#if 0
run_pending_traps (); /* because interrupt_immediately is not set */
+#endif
}
else
lastsig = 0;
.\" Case Western Reserve University
.\" chet.ramey@case.edu
.\"
-.\" Last Change: Thu Apr 9 11:50:30 EDT 2020
+.\" Last Change: Fri Apr 17 16:30:01 EDT 2020
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
-.TH BASH 1 "2020 April 9" "GNU Bash 5.0"
+.TH BASH 1 "2020 April 17" "GNU Bash 5.0"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
\fIname\fP=\fB(\fPvalue\fI1\fP ... value\fIn\fP\fB)\fP, where each
\fIvalue\fP may be of the form [\fIsubscript\fP]=\fIstring\fP.
Indexed array assignments do not require anything but \fIstring\fP.
+Each \fIvalue\fP in the list is expanded using all the shell expansions
+described below under
+.SM
+.BR EXPANSION .
When assigning to indexed arrays, if the optional brackets and subscript
are supplied, that index is assigned to;
otherwise the index of the element assigned is the last index assigned
otherwise the index of the element assigned is the last index assigned
to by the statement plus one. Indexing starts at zero.
+Each @var{value} in the list undergoes all the shell expansions
+described above (@pxref{Shell Expansions}).
+
When assigning to an associative array, the words in a compound assignment
may be either assignment statements, for which the subscript is required,
or a list of words that is interpreted as a sequence of alternating keys
Copyright (C) 1988-2020 Free Software Foundation, Inc.
@end ignore
-@set LASTCHANGE Thu Apr 9 11:58:06 EDT 2020
+@set LASTCHANGE Fri Apr 17 16:30:16 EDT 2020
@set EDITION 5.0
@set VERSION 5.0
-@set UPDATED 9 April 2020
+@set UPDATED 17 April 2020
@set UPDATED-MONTH April 2020
int pipe_in, pipe_out;
struct fd_bitmap *fds_to_close;
{
- int exec_result, user_subshell, invert, ignore_return, was_error_trap;
+ int exec_result, user_subshell, invert, ignore_return, was_error_trap, fork_flags;
REDIRECT *my_undo_list, *exec_undo_list;
char *tcmd;
volatile int save_line_number;
line_number_for_err_trap = line_number = command->value.Subshell->line; /* XXX - save value? */
/* Otherwise we defer setting line_number */
tcmd = make_command_string (command);
- paren_pid = make_child (p = savestring (tcmd), asynchronous);
+ fork_flags = asynchronous ? FORK_ASYNC : 0;
+ paren_pid = make_child (p = savestring (tcmd), fork_flags);
if (user_subshell && signal_is_trapped (ERROR_TRAP) &&
signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
invert = (command->flags & CMD_INVERT_RETURN) != 0;
ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
- exec_result = wait_for (paren_pid);
+ exec_result = wait_for (paren_pid, 0);
/* If we have to, invert the return value. */
if (invert)
the function to be waited for twice. This also causes
subshells forked to execute builtin commands (e.g., in
pipelines) to be waited for twice. */
- exec_result = wait_for (last_made_pid);
+ exec_result = wait_for (last_made_pid, 0);
}
}
last_command_exit_value = exec_result;
run_pending_traps ();
-#if 0
- if (running_trap == 0)
-#endif
- currently_executing_command = (COMMAND *)NULL;
+ currently_executing_command = (COMMAND *)NULL;
return (last_command_exit_value);
}
BLOCK_SIGNAL (SIGCHLD, set, oset);
- coproc_pid = make_child (p = savestring (tcmd), 1);
+ coproc_pid = make_child (p = savestring (tcmd), FORK_ASYNC);
if (coproc_pid == 0)
{
if (INVALID_JOB (lastpipe_jid) == 0)
{
append_process (savestring (the_printed_command_except_trap), dollar_dollar_pid, exec_result, lastpipe_jid);
- lstdin = wait_for (lastpid);
+ lstdin = wait_for (lastpid, 0);
}
else
lstdin = wait_for_single_pid (lastpid, 0); /* checks bgpids list */
#else
- lstdin = wait_for (lastpid);
+ lstdin = wait_for (lastpid, 0);
#endif
#if defined (JOB_CONTROL)
int pipe_in, pipe_out, async;
{
int r;
- int forcefork;
+ int forcefork, fork_flags;
REDIRECT *rd;
for (forcefork = 0, rd = redirects; rd; rd = rd->next)
{
/* We have a null command, but we really want a subshell to take
care of it. Just fork, do piping and redirections, and exit. */
- if (make_child ((char *)NULL, async) == 0)
+ fork_flags = async ? FORK_ASYNC : 0;
+ if (make_child ((char *)NULL, fork_flags) == 0)
{
/* Cancel traps, in trap.c. */
restore_original_signals (); /* XXX */
WORD_LIST *words, *lastword;
char *command_line, *lastarg, *temp;
int first_word_quoted, result, builtin_is_special, already_forked, dofork;
+ int fork_flags;
pid_t old_last_async_pid;
sh_builtin_func_t *builtin;
SHELL_VAR *func;
/* Don't let a DEBUG trap overwrite the command string to be saved with
the process/job associated with this child. */
- if (make_child (p = savestring (the_printed_command_except_trap), async) == 0)
+ fork_flags = async ? FORK_ASYNC : 0;
+ if (make_child (p = savestring (the_printed_command_except_trap), fork_flags) == 0)
{
already_forked = 1;
simple_command->flags |= CMD_NO_FORK;
int cmdflags;
{
char *pathname, *command, **args, *p;
- int nofork, stdpath, result;
+ int nofork, stdpath, result, fork_flags;
pid_t pid;
SHELL_VAR *hookf;
WORD_LIST *wl;
if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
pid = 0;
else
- pid = make_child (p = savestring (command_line), async);
+ {
+ fork_flags = async ? FORK_ASYNC : 0;
+ pid = make_child (p = savestring (command_line), fork_flags);
+ }
if (pid == 0)
{
/* hashcmd.h - Common defines for hashing filenames. */
-/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2020 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
#include "stdc.h"
#include "hashlib.h"
-#define FILENAME_HASH_BUCKETS 64 /* must be power of two */
+#define FILENAME_HASH_BUCKETS 256 /* must be power of two */
extern HASH_TABLE *hashed_filenames;
#define pathdata(x) ((PATH_DATA *)(x)->data)
-extern void phash_create __P((void));
-extern void phash_flush __P((void));
+extern void phash_create PARAMS((void));
+extern void phash_flush PARAMS((void));
-extern void phash_insert __P((char *, char *, int, int));
-extern int phash_remove __P((const char *));
-extern char *phash_search __P((const char *));
+extern void phash_insert PARAMS((char *, char *, int, int));
+extern int phash_remove PARAMS((const char *));
+extern char *phash_search PARAMS((const char *));
return -1;
if (p->running == PS_DONE)
return (p->status);
- r = wait_for (p->pid);
+ r = wait_for (p->pid, 0);
return (r); /* defer removing until later */
}
{
if (p->running == PS_DONE)
continue;
- r = wait_for (p->pid);
+ r = wait_for (p->pid, 0);
}
}
In this case, we don't want to give the terminal to the
shell's process group (we could be in the middle of a
pipeline, for example). */
- if (async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&(SUBSHELL_ASYNC|SUBSHELL_PIPE)) == 0) && running_in_background == 0)
+ if ((flags & FORK_NOTERM) == 0 && async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&(SUBSHELL_ASYNC|SUBSHELL_PIPE)) == 0) && running_in_background == 0)
give_terminal_to (pipeline_pgrp, 0);
#if defined (PGRP_PIPE)
alive = 0;
do
{
- r = wait_for (pid);
+ r = wait_for (pid, 0);
if ((flags & JWAIT_FORCE) == 0)
break;
the jobs table. Returns -1 if waitchld() returns -1, indicating
that there are no unwaited-for child processes. */
int
-wait_for (pid)
+wait_for (pid, flags)
pid_t pid;
+ int flags;
{
int job, termination_state, r;
WAIT s;
do
{
- r = wait_for (pid);
+ r = wait_for (pid, 0);
if (r == -1 && errno == ECHILD)
mark_all_jobs_as_dead ();
CHECK_WAIT_INTR;
errno = 0;
- r = wait_for (ANY_PID); /* special sentinel value for wait_for */
+ r = wait_for (ANY_PID, 0); /* special sentinel value for wait_for */
if (r == -1 && errno == ECHILD)
mark_all_jobs_as_dead ();
pid = find_last_pid (job, 0);
UNBLOCK_CHILD (oset);
- st = wait_for (pid);
+ st = wait_for (pid, 0);
shell_tty_info = save_stty;
set_tty_state ();
return (st);
/* I looked it up. For pretty_print_job (). The real answer is 24. */
#define LONGEST_SIGNAL_DESC 24
-/* Defines for the wait_for functions and for the wait builtin to use */
-#define JWAIT_PERROR 0x01
-#define JWAIT_FORCE 0x02
-#define JWAIT_NOWAIT 0x04 /* don't waitpid(), just return status if already exited */
-#define JWAIT_WAITING 0x08 /* wait for jobs marked J_WAITING only */
+/* Defines for the wait_for_* functions and for the wait builtin to use */
+#define JWAIT_PERROR (1 << 0)
+#define JWAIT_FORCE (1 << 1)
+#define JWAIT_NOWAIT (1 << 2) /* don't waitpid(), just return status if already exited */
+#define JWAIT_WAITING (1 << 3) /* wait for jobs marked J_WAITING only */
+
+/* flags for wait_for */
+#define JWAIT_NOTERM (1 << 8) /* wait_for doesn't give terminal away */
/* The max time to sleep while retrying fork() on EAGAIN failure */
#define FORKSLEEP_MAX 16
#define ANY_PID (pid_t)-1
/* flags for make_child () */
-#define FORK_SYNC 0
-#define FORK_ASYNC 1
-#define FORK_NOJOB 2
+#define FORK_SYNC 0 /* normal synchronous process */
+#define FORK_ASYNC 1 /* background process */
+#define FORK_NOJOB 2 /* don't put process in separate pgrp */
+#define FORK_NOTERM 4 /* don't give terminal to any pgrp */
/* System calls. */
#if !defined (HAVE_UNISTD_H)
extern int wait_for_single_pid PARAMS((pid_t, int));
extern void wait_for_background_pids PARAMS((struct procstat *));
-extern int wait_for PARAMS((pid_t));
+extern int wait_for PARAMS((pid_t, int));
extern int wait_for_job PARAMS((int, int, struct procstat *));
extern int wait_for_any_job PARAMS((int, struct procstat *));
/* Wait for pid (one of our children) to terminate. This is called only
by the execution code in execute_cmd.c. */
int
-wait_for (pid)
+wait_for (pid, flags)
pid_t pid;
+ int flags;
{
int return_val, pstatus;
pid_t got_pid;
{
if (fifo_list[i].proc != (pid_t)-1 && fifo_list[i].proc > 0)
{
- r = wait_for (fifo_list[i].proc);
+ r = wait_for (fifo_list[i].proc, 0);
save_proc_status (fifo_list[i].proc, r);
fifo_list[i].proc = (pid_t)-1;
}
{
if (dev_fd_list[i] != (pid_t)-1 && dev_fd_list[i] > 0)
{
- r = wait_for (dev_fd_list[i]);
+ r = wait_for (dev_fd_list[i], 0);
save_proc_status (dev_fd_list[i], r);
dev_fd_list[i] = (pid_t)-1;
}
save_pipeline (1);
#endif /* JOB_CONTROL */
- pid = make_child ((char *)NULL, 1);
+ pid = make_child ((char *)NULL, FORK_ASYNC);
if (pid == 0)
{
interactive = 0;
mb_cur_max = MB_CUR_MAX;
nullbyte = 0;
- /* Read the output of the command through the pipe. This may need to be
- changed to understand multibyte characters in the future. */
+ /* Read the output of the command through the pipe. */
while (1)
{
if (fd < 0)
#endif
istring[istring_index++] = c;
-
-#if 0
-#if defined (__CYGWIN__)
- if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
- {
- istring_index--;
- istring[istring_index - 1] = '\n';
- }
-#endif
-#endif
}
if (istring)
{
pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
char *istring, *s;
- int result, fildes[2], function_value, pflags, rc, tflag;
+ int result, fildes[2], function_value, pflags, rc, tflag, fork_flags;
WORD_DESC *ret;
+ sigset_t set, oset;
istring = (char *)NULL;
#endif /* JOB_CONTROL */
old_async_pid = last_asynchronous_pid;
- pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
+ fork_flags = (subshell_environment&SUBSHELL_ASYNC) ? FORK_ASYNC : 0;
+ pid = make_child ((char *)NULL, fork_flags);
last_asynchronous_pid = old_async_pid;
if (pid == 0)
dummyfd = fildes[0];
add_unwind_protect (close, dummyfd);
+ /* Block SIGINT while we're reading from the pipe. If the child
+ process gets a SIGINT, it will either handle it or die, and the
+ read will return. */
+ BLOCK_SIGNAL (SIGINT, set, oset);
tflag = 0;
istring = read_comsub (fildes[0], quoted, flags, &tflag);
close (fildes[0]);
discard_unwind_frame ("read-comsub");
+ UNBLOCK_SIGNAL (oset);
current_command_subst_pid = pid;
- last_command_exit_value = wait_for (pid);
+ last_command_exit_value = wait_for (pid, 0);
last_command_subst_pid = pid;
last_made_pid = old_pid;
-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
16
./appendop.tests: line 97: x: readonly variable
declare -A foo=([two]="baz" [three]="quux" [one]="bar" )
-declare -A foo=([two]="baz" [0]="zero" [three]="quux" [one]="bar" )
-declare -A foo=([two]="baz" [0]="zero" [three]="quux" [four]="four" [one]="bar" )
+declare -A foo=([0]="zero" [two]="baz" [three]="quux" [one]="bar" )
+declare -A foo=([four]="four" [0]="zero" [two]="baz" [three]="quux" [one]="bar" )
declare -ai iarr=([0]="3" [1]="2" [2]="3")
declare -ai iarr=([0]="3" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6")
25 25
version.agent
version[agent]
version.agent
-version[agent] foo[bar]
-version.agent bowl
-foo foobar] foo[bar]
-bbb bleh bleh
+foo[bar] version[agent]
+bowl version.agent
+foobar] foo foo[bar]
+bleh bbb bleh
ab]
bar
1
declare -A fluff=([foo]="one" [bar]="two" )
declare -A fluff=([foo]="one" [bar]="two" )
declare -A fluff=([bar]="two" )
-declare -A fluff=([bar]="newval" [qux]="assigned" )
+declare -A fluff=([qux]="assigned" [bar]="newval" )
./assoc.tests: line 39: chaff: four: must use subscript when assigning associative array
declare -A BASH_ALIASES=()
declare -A BASH_CMDS=()
-declare -Ai chaff=([zero]="5" [one]="10" )
-declare -Ar waste=([lineno]="41" [source]="./assoc.tests" [version]="4.0-devel" [pid]="42134" )
-declare -A wheat=([two]="b" [three]="c" [zero]="0" [one]="a" )
-declare -A chaff=(["hello world"]="flip" [zero]="5" [one]="10" )
+declare -Ai chaff=([one]="10" [zero]="5" )
+declare -Ar waste=([pid]="42134" [lineno]="41" [source]="./assoc.tests" [version]="4.0-devel" )
+declare -A wheat=([two]="b" [three]="c" [one]="a" [zero]="0" )
+declare -A chaff=(["hello world"]="flip" [one]="10" [zero]="5" )
./assoc.tests: line 51: waste: readonly variable
./assoc.tests: line 52: unset: waste: cannot unset: readonly variable
./assoc.tests: line 53: chaff[*]: bad array subscript
./assoc.tests: line 71: declare: chaff: cannot destroy array variables in this way
./assoc.tests: line 73: chaff[*]: bad array subscript
./assoc.tests: line 74: [*]=12: invalid associative array key
-declare -A wheat=(["foo bar"]="qux qix" [six]="6" )
+declare -A wheat=([six]="6" ["foo bar"]="qux qix" )
argv[1] = <qux>
argv[2] = <qix>
argv[1] = <qux qix>
-declare -A wheat=(["foo bar"]="qux qix" [six]="6" )
+declare -A wheat=([six]="6" ["foo bar"]="qux qix" )
argv[1] = <2>
argv[1] = <7>
argv[1] = <qux>
argv[1] = <qux qix blat>
argv[1] = <16>
argv[1] = <16>
-argv[1] = <flix>
-argv[2] = <6>
-argv[1] = <foo>
-argv[2] = <bar>
-argv[3] = <six>
-argv[1] = <foo bar>
-argv[2] = <six>
+argv[1] = <6>
+argv[2] = <flix>
+argv[1] = <six>
+argv[2] = <foo>
+argv[3] = <bar>
+argv[1] = <six>
+argv[2] = <foo bar>
8
-/sbin /usr/bin /bin /usr/ucb /usr/local/bin . /usr/sbin /bin
-sbin bin bin ucb bin . sbin bin
+/usr/local/bin /bin . /usr/bin /usr/ucb /usr/sbin /bin /sbin
+bin bin . bin ucb sbin bin sbin
bin
/ / / / / / /
/
argv[1] = <sbin>
argv[1] = </>
8
-/sbin /usr/bin /bin /usr/ucb /usr/local/bin . /usr/sbin /bin
-sbin bin bin ucb bin . sbin bin
+/usr/local/bin /bin . /usr/bin /usr/ucb /usr/sbin /bin /sbin
+bin bin . bin ucb sbin bin sbin
/ / / / / / /
8
4 -- /bin
-^sbin ^usr^bin ^bin ^usr^ucb ^usr^local^bin . ^usr^sbin ^bin
-^sbin ^usr^bin ^bin ^usr^ucb ^usr^local^bin . ^usr^sbin ^bin
-\sbin \usr/bin \bin \usr/ucb \usr/local/bin . \usr/sbin \bin
-\sbin \usr\bin \bin \usr\ucb \usr\local\bin . \usr\sbin \bin
-\sbin \usr\bin \bin \usr\ucb \usr\local\bin . \usr\sbin \bin
+^usr^local^bin ^bin . ^usr^bin ^usr^ucb ^usr^sbin ^bin ^sbin
+^usr^local^bin ^bin . ^usr^bin ^usr^ucb ^usr^sbin ^bin ^sbin
+\usr/local/bin \bin . \usr/bin \usr/ucb \usr/sbin \bin \sbin
+\usr\local\bin \bin . \usr\bin \usr\ucb \usr\sbin \bin \sbin
+\usr\local\bin \bin . \usr\bin \usr\ucb \usr\sbin \bin \sbin
([a]=1)
foo qux
/usr/sbin/foo /usr/local/bin/qux
hits command
- 0 /sbin/blat
0 /usr/sbin/foo
0 /bin/sh
+ 0 /sbin/blat
0 /usr/local/bin/qux
-blat foo sh qux
-/sbin/blat /usr/sbin/foo /bin/sh /usr/local/bin/qux
+foo sh blat qux
+/usr/sbin/foo /bin/sh /sbin/blat /usr/local/bin/qux
foo qux
argv[1] = </usr/sbin/foo>
outside: outside
declare -A BASH_ALIASES=()
declare -A BASH_CMDS=()
-declare -A afoo=(["foo bar"]="foo quux" [six]="six" )
+declare -A afoo=([six]="six" ["foo bar"]="foo quux" )
argv[1] = <inside:>
-argv[2] = <foo quux>
-argv[3] = <six>
+argv[2] = <six>
+argv[3] = <foo quux>
outside 2: outside
argv[1] = </barq//fooq>
argv[1] = <>
def
def
./assoc5.sub: line 26: declare: `myarray[foo[bar]=bleh': not a valid identifier
-bleh def abc
-myarray=([foo]="bleh" ["]"]="def" ["a]=test1;#a"]="123" ["a]a"]="abc" )
+def bleh abc
+myarray=(["]"]="def" [foo]="bleh" ["a]a"]="abc" ["a]=test1;#a"]="123" )
123
-myarray=([foo]="bleh" ["]"]="def" ["a]=test2;#a"]="def" ["a]=test1;#a"]="123" ["a]a"]="abc" )
+myarray=(["]"]="def" ["a]=test2;#a"]="def" [foo]="bleh" ["a]a"]="abc" ["a]=test1;#a"]="123" )
bar"bie
doll
declare -A foo=(["bar\"bie"]="doll" )
declare -A a=([3]="" [1]="2" )
declare -A foo=([d]="4" [c]="3" [b]="2" [a]="1" )
foo=( d "4" c "3" b "2" a "1" )
-declare -A foo=(["spa ces"]="2" ["\\"]="5" ["@"]="3" ["holy hell this works"]="4" ["a b"]="1" )
-foo=( echo "spa ces" "2" "\\" "5" "@" "3" "holy hell this works" "4" "a b" "1" )
+declare -A foo=(["\\"]="5" ["@"]="3" ["holy hell this works"]="4" ["a b"]="1" ["spa ces"]="2" )
+foo=( echo "\\" "5" "@" "3" "holy hell this works" "4" "a b" "1" "spa ces" "2" )
./assoc11.sub: line 34: "": bad array subscript
-declare -A foo=(["foo[bar"]="bleh" [";"]="semicolon" ["]"]="def" [a=b]="assignment" ["a]a"]="abc" )
-foo=( "foo[bar" "bleh" ";" "semicolon" "]" "def" a=b "assignment" "a]a" "abc" )
+declare -A foo=([";"]="semicolon" ["]"]="def" [a=b]="assignment" ["a]a"]="abc" ["foo[bar"]="bleh" )
+foo=( ";" "semicolon" "]" "def" a=b "assignment" "a]a" "abc" "foo[bar" "bleh" )
declare -A foo=(["'"]="squote" ["\""]="dquote" ["\\"]="bslash" ["\`"]="backquote" )
foo=( "'" "squote" "\"" "dquote" "\\" "bslash" "\`" "backquote" )
declare -A foo=(["bar]bie"]="doll" ["a]=test1;#a"]="123" ["bar\"bie"]="doll" )
set -- 'ab' 'cd ef' '' 'gh'
declare -a A=([0]="ab" [1]="cd ef" [2]="" [3]="gh")
declare -a B=()
-declare -A A=([two]="b c" [three]="" [four]="de" [one]="1" )
+declare -A A=([four]="de" [two]="b c" [three]="" [one]="1" )
r
a
A
bash is hashed (/tmp/bash)
file
hits command
- 3 /tmp/bash
1 /bin/sh
+ 3 /tmp/bash
f is a function
f ()
{
./varenv11.sub: line 18: qux: readonly variable
declare -A foo=([zero]="zero" [one]="one" )
declare -a bar=([0]="zero" [1]="one")
-declare -A foo=([zero]="zero" [one]="one" )
+declare -A foo=([one]="one" [zero]="zero" )
declare -a bar=([0]="zero" [1]="one")
./varenv11.sub: line 42: a: readonly variable
foo=abc
HASH_TABLE *hash;
entry = make_new_variable (name, global_variables->table);
- hash = assoc_create (0);
+ hash = assoc_create (ASSOC_HASH_BUCKETS);
var_setassoc (entry, hash);
VSETATTR (entry, att_assoc);
internal_warning ("%s: cannot inherit value from incompatible type", name);
VUNSETATTR (var, att_array);
dispose_variable_value (var);
- hash = assoc_create (0);
+ hash = assoc_create (ASSOC_HASH_BUCKETS);
var_setassoc (var, hash);
}
else if (localvar_inherit)
else
{
dispose_variable_value (var);
- hash = assoc_create (0);
+ hash = assoc_create (ASSOC_HASH_BUCKETS);
var_setassoc (var, hash);
}