mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 15:43:18 +02:00
commit bash-20130720 snapshot
This commit is contained in:
@@ -37,6 +37,21 @@ i. Fixed the nameref circular reference checking to be less strict and only
|
||||
j. Fixed a bug that caused trap handlers to be executed recursively,
|
||||
corrupting internal data structures.
|
||||
|
||||
k. Fixed a bug that could result in bash not compiling if certain options were
|
||||
not enabled.
|
||||
|
||||
l. Fixed a bug that caused the arithmetic expansion code to attempt variable
|
||||
assignments when operator precedence prohibited them.
|
||||
|
||||
m. Word expansions like ${foo##bar} now understand indirect variable references.
|
||||
|
||||
n. Fixed a bug that caused `declare -fp name' to not display a function
|
||||
definition.
|
||||
|
||||
o. Fixed a bug that caused asynchronous child processes to modify the stdin
|
||||
file pointer when bash was using it to read a script, which modified the
|
||||
parent's value as well.
|
||||
|
||||
2. Changes to Readline
|
||||
|
||||
a. Fixed a bug in vi mode that caused the arrow keys to set the saved last
|
||||
@@ -51,10 +66,25 @@ c. Fixed a bug with vi mode that prevented `.' from repeating a command
|
||||
d. Fixed a bug that could cause completion to core dump if it was interrupted
|
||||
by a signal.
|
||||
|
||||
e. Readline now sends the meta-key enable string to the terminal if the
|
||||
terminal has been successfully initialized.
|
||||
|
||||
f. Readline now calls the signal hook after resizing the terminal when it
|
||||
receives a SIGWINCH.
|
||||
|
||||
g. Fixed a bug that could cause the history list code to perform an out-of-
|
||||
bounds array reference if the history list is empty.
|
||||
|
||||
3. New Features in Bash
|
||||
|
||||
a. Shells started to run process substitutions now run any trap set on EXIT.
|
||||
|
||||
b. There is now a configure-time option to enable the globasciiranges option
|
||||
by default.
|
||||
|
||||
c. The read builtin now checks its first variable argument for validity before
|
||||
trying to read any input.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
This document details the changes between this version, bash-4.3-alpha,
|
||||
and the previous version, bash-4.2-release.
|
||||
|
||||
+27
-555
@@ -37,6 +37,21 @@ i. Fixed the nameref circular reference checking to be less strict and only
|
||||
j. Fixed a bug that caused trap handlers to be executed recursively,
|
||||
corrupting internal data structures.
|
||||
|
||||
k. Fixed a bug that could result in bash not compiling if certain options were
|
||||
not enabled.
|
||||
|
||||
l. Fixed a bug that caused the arithmetic expansion code to attempt variable
|
||||
assignments when operator precedence prohibited them.
|
||||
|
||||
m. Word expansions like ${foo##bar} now understand indirect variable references.
|
||||
|
||||
n. Fixed a bug that caused `declare -fp name' to not display a function
|
||||
definition.
|
||||
|
||||
o. Fixed a bug that caused asynchronous child processes to modify the stdin
|
||||
file pointer when bash was using it to read a script, which modified the
|
||||
parent's value as well.
|
||||
|
||||
2. Changes to Readline
|
||||
|
||||
a. Fixed a bug in vi mode that caused the arrow keys to set the saved last
|
||||
@@ -51,564 +66,21 @@ c. Fixed a bug with vi mode that prevented `.' from repeating a command
|
||||
d. Fixed a bug that could cause completion to core dump if it was interrupted
|
||||
by a signal.
|
||||
|
||||
e. Readline now sends the meta-key enable string to the terminal if the
|
||||
terminal has been successfully initialized.
|
||||
|
||||
f. Readline now calls the signal hook after resizing the terminal when it
|
||||
receives a SIGWINCH.
|
||||
|
||||
g. Fixed a bug that could cause the history list code to perform an out-of-
|
||||
bounds array reference if the history list is empty.
|
||||
|
||||
3. New Features in Bash
|
||||
|
||||
a. Shells started to run process substitutions now run any trap set on EXIT.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
This document details the changes between this version, bash-4.3-alpha,
|
||||
and the previous version, bash-4.2-release.
|
||||
|
||||
1. Changes to Bash
|
||||
|
||||
a. Fixed several bugs concerning incomplete bracket expressions in filename
|
||||
generation (globbing) patterns.
|
||||
|
||||
b. Fixed a bug with single quotes and WORD in ${param op WORD} when running
|
||||
in Posix mode.
|
||||
|
||||
c. Fixed a bug that caused the pattern removal and pattern substitution word
|
||||
expansions and case statement word expansion to not match the empty string.
|
||||
|
||||
d. Fixed a bug that caused the tzset() function to not work after changing
|
||||
the TZ enviroment variable.
|
||||
|
||||
e. Fixed a bug that caused the RHS of an assignment statement to undergo
|
||||
word splitting when it contained an unquoted $@.
|
||||
|
||||
f. Fixed bugs that caused the shell to not react to a SIGINT sent while
|
||||
waiting for a child process to exit.
|
||||
|
||||
g. Bash doesn't try to run things in a signal handler context when it gets a
|
||||
signal (SIGINT/SIGHUP/etc) while reading input using readline but still
|
||||
be responsive to terminating signals.
|
||||
|
||||
h. Fixed a bug that caused bash to go into an infinite loop if a filename
|
||||
to be matched contained an invalid multibyte character.
|
||||
|
||||
i. Fixed a bug that caused PS4 to end up being truncated if it is longer
|
||||
than 128 bytes.
|
||||
|
||||
j. Fixed a bug that caused brace expansion to not skip over double-quoted
|
||||
command substitution.
|
||||
|
||||
k. System-specific updates for: DJGPP, HP/UX, Mac OS X
|
||||
|
||||
l. Fixed a bug in displaying commands that caused redirections to be associated
|
||||
with the wrong part of the command.
|
||||
|
||||
m. Fixed the coproc cleanup to unset the appropriate shell variables when a
|
||||
coproc terminates.
|
||||
|
||||
n. Fixed a bug that caused `fc' to dump core due to incorrect calculation of
|
||||
the last history entry.
|
||||
|
||||
o. Added workarounds for FreeBSD's implementation of faccessat/eaccess and
|
||||
`test -x'.
|
||||
|
||||
p. Fixed a bug that caused the shell to not match patterns containing
|
||||
control-A.
|
||||
|
||||
q. Fixed a bug that could result in doubled error messages when the `printf'
|
||||
builtin got a write error.
|
||||
|
||||
r. Fixed a bug that caused the shell to not correctly expand words containing
|
||||
multiple consecutive quoted empty strings (""""""aa).
|
||||
|
||||
s. Fixed a bug that caused the shell to not correctly parse multi-line
|
||||
process substitutions containing comments and quoted strings.
|
||||
|
||||
t. Fixed a problem with the bash malloc's internal idea of the top of the
|
||||
memory heap that resulted in incorrect decisions to try to reduce the
|
||||
break and give memory back to the kernel.
|
||||
|
||||
u. There are changes to the expansions peformed on compound array assignments,
|
||||
in an effort to make foo=( [ind1]=bar [ind2]=baz ) identical to
|
||||
foo[ind1]=bar foo[ind2]=baz.
|
||||
|
||||
v. Bash now reports an error if `read -a name' is used when `name' is an
|
||||
existing associative array.
|
||||
|
||||
w. Fixed a bug that allowed an attempted assignment to a readonly variable
|
||||
in an arithmetic expression to not return failure.
|
||||
|
||||
x. Fixed several bugs that caused completion functions to be invoked even when
|
||||
the cursor was before the first word in the command.
|
||||
|
||||
y. Fixed a bug that caused parsing a command substitution to overwrite the
|
||||
parsing state associated with the complete input line.
|
||||
|
||||
z. Fixed several bugs with the built-in snprintf replacement and field widths
|
||||
and floating point.
|
||||
|
||||
aa. Fixed a bug that caused incorrect offset calculations and input buffer
|
||||
corruption when reading files longer than 2^31 bytes.
|
||||
|
||||
bb. Fixed several bugs where bash performed arithmetic evaluation in contexts
|
||||
where evaluation is suppressed.
|
||||
|
||||
cc. Fixed a bug that caused bash to close FIFOs used for process substitution
|
||||
too early when a shell function was executing, but protect against using
|
||||
all file descriptors when the shell functions are invoked inside loops.
|
||||
|
||||
dd. Added checks for printable (and non-printable) multibyte characters for
|
||||
use in error messages.
|
||||
|
||||
ee. Fixed a bug that caused ^O (operate-and-get-next) to not work correctly
|
||||
at the end of the history list.
|
||||
|
||||
ff. Fixed a bug that caused command-oriented history to incorrectly combine
|
||||
here documents into one line.
|
||||
|
||||
gg. Fixed a bug that caused importing SHELLOPTS from the environment into a
|
||||
Posix-mode shell to print an error message and refuse to parse it.
|
||||
|
||||
hh. Fixed a bug that caused the shell to delete an extra history entry when
|
||||
using `history -s'.
|
||||
|
||||
ii. Fixed a bug that caused floating-point exceptions and overflow errors
|
||||
for the / and % arithmetic operators when using INTMAX_MIN and -1.
|
||||
|
||||
jj. Fixed a bug that caused parsing errors when reading an arithmetic for
|
||||
loop inside a command substitution.
|
||||
|
||||
kk. Fixed a bug that caused a readonly function to be unset when unset was
|
||||
called without the -f or -v option.
|
||||
|
||||
ll. Fixed several bugs in the code that quotes characters special to regular
|
||||
expressions when used in a quoted string on the RHS of the =~ operator
|
||||
to the [[ command.
|
||||
|
||||
mm. Fixed a bug that caused redirections to fail because the file descriptor
|
||||
limit was set to a value less than 10.
|
||||
|
||||
nn. Fixed a bug that caused the `read' builtin to execute code in a signal
|
||||
handler context if read timed out.
|
||||
|
||||
oo. Fixed a bug that caused extended globbing patterns to not match files
|
||||
beginning with `.' correctly when a `.' was explicitly supplied in the
|
||||
pattern.
|
||||
|
||||
pp. Fixed a bug that caused key sequences longer than two characters to not
|
||||
work when used with `bind -x'.
|
||||
|
||||
qq. Fixed a bug that resulted in redefined functions having the wrong source
|
||||
file names in BASH_SOURCE.
|
||||
|
||||
rr. Fixed a bug that caused the read builtin to assign null strings to variables
|
||||
when using `read -N', which caused core dumps when referenced
|
||||
|
||||
ss. Fixed a bug that caused `bash -m script' to not enable job control while
|
||||
running the script.
|
||||
|
||||
tt. Fixed a bug that caused `printf -v var' to dump core when used with the
|
||||
%b format code.
|
||||
|
||||
uu. Fixed a bug that caused the shell to exit with the wrong status if -e was
|
||||
active and the shell exited on a substitution error.
|
||||
|
||||
vv. Fixed a bug that caused the shell to seg fault if an array variable with
|
||||
the same name as an existing associative array was implicitly created by
|
||||
an assignment (declare a[n]=b).
|
||||
|
||||
ww. Fixed a bug that caused a redirection to misbehave if the number specified
|
||||
for a file descriptor overflows an intmax_t.
|
||||
|
||||
xx. Fixed several bugs with the handling of valid and invalid unicode character
|
||||
values when used with the \u and \U escape sequences to printf and $'...'.
|
||||
|
||||
yy. Fixed a bug that caused tildes to not be escaped in expanded filenames,
|
||||
making them subject to later expansion.
|
||||
|
||||
zz. When using the pattern substitution word expansion, bash now runs the
|
||||
replacement string through quote removal, since it allows quotes in that
|
||||
string to act as escape characters. This is not backwards compatible, so
|
||||
it can be disabled by setting the bash compatibility mode to 4.2.
|
||||
|
||||
aaa. Fixed the rest of the cases where the shell runs non-allowed code in a
|
||||
signal handler context.
|
||||
|
||||
bbb. Fixed a bug that caused spurious DEL characters (\177) to appear in
|
||||
double-quoted expansion where the RHS is evaluated to the empty string.
|
||||
|
||||
ccc. Fixed a bug that caused the use of the shell's internal random number
|
||||
generator for temporary file names to perturb the random number
|
||||
sequence.
|
||||
|
||||
ddd. Fixed several bugs that caused `declare -g' to not set the right global
|
||||
variables or to misbehave when declaring global indexed arrays.
|
||||
|
||||
eee. Fixed a logic bug that caused extended globbing in a multibyte locale to
|
||||
cause failures when using the pattern substititution word expansions.
|
||||
|
||||
fff. Fixed a bug that caused the `lastpipe' option to corrupt the file
|
||||
descriptor used to read the script.
|
||||
|
||||
ggg. Fixed a bug that causes the shell to delete DEL characters in the
|
||||
expanded value of variables used in the same quoted string as variables
|
||||
that expand to nothing.
|
||||
|
||||
hhh. Fixed a bug that caused the shell to assign the wrong value from an
|
||||
assignment like (( x=7 )) when `x' was an existing array variable.
|
||||
|
||||
iii. Fixed a bug that caused the shell to misbehave when generating sequences
|
||||
and the boundary values overflow an intmax_t.
|
||||
|
||||
jjj. Fixed a bug caused expansion errors if an expansion of "$@" appeared
|
||||
next to another expansion (e.g.. "${@}${x}").
|
||||
|
||||
kkk. Fixed a potential buffer overflow bug when performing /dev/fd expansion.
|
||||
|
||||
lll. Fixed a bug that resulted in an extra semicolon being added to compound
|
||||
assignments when they were added to the history list.
|
||||
|
||||
mmm. Fixed a bug that caused mapfile to read one extra line from the input.
|
||||
|
||||
nnn. Fixed a bug that caused the mail checking code to use uninitialized
|
||||
values.
|
||||
|
||||
ooo. Fixed a bug that prevented history timestamps from being saved if the
|
||||
history comment character is unset.
|
||||
|
||||
ppp. Fixed a bug that caused the case-modifying expansions to not work with
|
||||
multibyte characters.
|
||||
|
||||
qqq. Fixed a bug that caused the edit-and-execute bindable readline command
|
||||
to see the wrong data if invoked in the middle of a multi-line quoted
|
||||
string.
|
||||
|
||||
rrr. Fixed a bug that resulted in the shell returning the wrong exit status
|
||||
for a background command on systems that recycle PIDs very quickly.
|
||||
|
||||
sss. Fixed a bug that caused asynchronous group commands to not run any EXIT
|
||||
trap defined in the body of the command.
|
||||
|
||||
ttt. Fixed a bug that caused `eval "... ; return"' to not clean up properly.
|
||||
|
||||
uuu. Fixed a bug that caused the shell to dump core if `read' reads an escaped
|
||||
IFS whitespace character.
|
||||
|
||||
vvv. Fixed a bug that caused BASH_COMMAND to be set to an incorrect value when
|
||||
executing a (...) subshell.
|
||||
|
||||
www. Fixed a couple of pointer aliasing bugs with the token string in arithmetic
|
||||
evaluation.
|
||||
|
||||
xxx. Fixed a bug with parsing multi-line command substitutions when reading
|
||||
the `do' keyword followed by whitespace.
|
||||
|
||||
yyy. Fixed a bug that caused the shell to seg fault if the time given to the
|
||||
printf %(...)T format overflowed the value accepted by localtime(3).
|
||||
|
||||
zzz. Fixed a problem with displaying help topics in two columns when the
|
||||
translated text contained multibyte characters.
|
||||
|
||||
aaaa. Fixed a bug with the extended globbing pattern matcher where a `*' was
|
||||
followed by a negated extended glob pattern.
|
||||
|
||||
bbbb. Fixed a race condition with short-lived coproc creation and reaping that
|
||||
caused the child process to be reaped before the various coproc shell
|
||||
variables were initialized.
|
||||
|
||||
cccc. Fixed a bug where turning off `errexit' in command substitution subshells
|
||||
was not reflected in $SHELLOPTS.
|
||||
|
||||
dddd. Partially fixed an inconsistency in how the shell treated shell
|
||||
functions run from an EXIT trap.
|
||||
|
||||
eeee. Fixed a bug in how the shell invalidated FIFOs used for process
|
||||
substitution when executing a pipeline (once rather than in every child).
|
||||
|
||||
ffff. Fixed a bug that occurred when expanding a special variable ($@, $*)
|
||||
within double quotes and the expansion resulted in an empty string.
|
||||
|
||||
gggg. Fixed bugs with executing a SIGCHLD trap handler to make sure that it's
|
||||
executed once per exited child.
|
||||
|
||||
hhhh. Fixed a bug that caused `declare' and `test' to find variables that
|
||||
had been given attributes but not assigned values. Such variables are
|
||||
not set.
|
||||
|
||||
iiii. Fixed a bug that caused commands in process substitutions to not look in
|
||||
the local temporary environment when performing word expansions.
|
||||
|
||||
jjjj. Fixed several problems with globstar expansions (**/**) returning null
|
||||
filenames and multiple instances of the same pathname.
|
||||
|
||||
kkkk. Fixed an oversight that did not allow the exit status of `coproc' to
|
||||
be inverted using `!'.
|
||||
|
||||
llll. Fixed a bug that caused the -e option to be re-enabled using `set -e'
|
||||
even when executing in a context where -e is ignored.
|
||||
|
||||
mmmm. Fixed a (mostly theoretical) bug with input lines longer than SIZE_MAX.
|
||||
|
||||
nnnn. Fixed a bug that could result in double evaluation of command
|
||||
substitutions when they appear in failed redirections.
|
||||
|
||||
oooo. Fixed a bug that could cause seg faults during `mapfile' callbacks if
|
||||
the callback unsets the array variable mapfile is using.
|
||||
|
||||
pppp. Fixed several problems with variable assignments using ${var:=value}
|
||||
when the variable assignment is supposed to have side effects.
|
||||
|
||||
qqqq. Fixed a bug that caused a failure of an assignment statement preceding a
|
||||
builtin caused the next invocation of a special builtin to exit the shell.
|
||||
|
||||
rrrr. Fixed several problems with IFS when it appears in the temporary environment
|
||||
and is used in redirections.
|
||||
|
||||
ssss. Fixed a problem that caused IFS changes using ${IFS:=value} to modify
|
||||
how preceding expansions were split.
|
||||
|
||||
tttt. Fixed a problem that caused subshells to not run an EXIT trap they set.
|
||||
|
||||
uuuu. Fixed a problem that caused shells started in posix mode to attempt to
|
||||
import shell functions with invalid names from the environment. We now
|
||||
print a warning.
|
||||
|
||||
vvvv. Worked around a kernel problem that caused SIGCHLD to interrupt open(2)
|
||||
on a FIFO used for process substitution, even if the SIGCHLD handler was
|
||||
installed with the SA_RESTART flag.
|
||||
|
||||
wwww. Fixed a problem that resulted in inconsistent expansion of $* and ${a[*]}.
|
||||
|
||||
xxxx. Fixed a problem that caused `read -t' to crash when interrupted by
|
||||
SIGINT.
|
||||
|
||||
yyyy. Fixed a problem that caused pattern removal to fail randomly because the
|
||||
pattern matcher read beyond the end of a string.
|
||||
|
||||
zzzz. Fixed a bug that caused core dumps when shell functions tried to create
|
||||
local shadow copies of special variables like GROUPS.
|
||||
|
||||
aaaaa. Fixed a bug that caused SIGTERM to be occasionally lost by children of
|
||||
interactive shells when it arrived before the child process reset the
|
||||
handler from SIG_DFL.
|
||||
|
||||
bbbbb. Fixed a bug that caused redirections like <&n- to leave file descriptor
|
||||
n closed if executed with a builtin command.
|
||||
|
||||
ccccc. Fixed a bug that caused incorrect completion quoting when completing a
|
||||
word containing a globbing character with `show-all-if-ambiguous' set.
|
||||
|
||||
ddddd. Fixed a bug that caused printf's %q format specifier not to quote a
|
||||
tilde even if it appeared in a location where it would be subject to
|
||||
tilde expansion.
|
||||
|
||||
2. Changes to Readline
|
||||
|
||||
a. Fixed a bug that did not allow the `dd', `cc', or `yy' vi editing mode
|
||||
commands to work on the entire line.
|
||||
|
||||
b. Fixed a bug that caused redisplay problems with prompts longer than 128
|
||||
characters and history searches.
|
||||
|
||||
c. Fixed a bug that caused readline to try and run code to modify its idea
|
||||
of the screen size in a signal handler context upon receiving a SIGWINCH.
|
||||
|
||||
d. Fixed a bug that caused the `meta' key to be enabled beyond the duration
|
||||
of an individual call top readline().
|
||||
|
||||
e. Added a workaround for a wcwidth bug in Mac OS X that caused readline's
|
||||
redisplay to mishandle zero-width combining characters.
|
||||
|
||||
f. Fixed a bug that caused readline to `forget' part of a key sequence when
|
||||
a multiple-key sequence caused it to break out of an incremental search.
|
||||
|
||||
g. Fixed bugs that caused readline to execute code in a signal handler
|
||||
context if interrupted while reading from the file system during completion.
|
||||
|
||||
h. Fixed a bug that caused readline to `forget' part of a key sequence when
|
||||
reading an unbound multi-character key sequence.
|
||||
|
||||
i. Fixed a bug that caused Readline's signal handlers to be installed beyond
|
||||
the bounds of a single call to readline().
|
||||
|
||||
j. Fixed a bug that caused the `.' command to not redo the most recent `R'
|
||||
command in vi mode.
|
||||
|
||||
k. Fixed a bug that caused ignoring case in completion matches to result in
|
||||
readline using the wrong match.
|
||||
|
||||
l. Paren matching now works in vi insert mode.
|
||||
|
||||
m. Fix menu-completion to make show-all-if-ambiguous and menu-complete-display-prefix
|
||||
work together.
|
||||
|
||||
n. Fixed a bug that didn't allow the `cc', `dd', or `yy' commands to be redone
|
||||
in vi editing mode.
|
||||
|
||||
o. Fixed a bug that caused the filename comparison code to not compare
|
||||
multibyte characters correctly when using case-sensitive or case-mapping
|
||||
comparisons.
|
||||
|
||||
p. Fixed the input reading loop to call the input hook function only when there
|
||||
is no terminal input available.
|
||||
|
||||
q. Fixed a bug that caused binding a macro to a multi-character key sequence
|
||||
where the sequence and macro value share a common prefix to not perform
|
||||
the macro replacement.
|
||||
|
||||
r. Fixed several redisplay errors with multibyte characters and prompts
|
||||
containing invisible characters when using horizontal scrolling.
|
||||
|
||||
s. Fixed a bug that caused redisplay errors when trying to overwrite
|
||||
existing characters using multibyte characters.
|
||||
|
||||
3. New Features in Bash
|
||||
|
||||
a. The `helptopic' completion action now maps to all the help topics, not just
|
||||
the shell builtins.
|
||||
|
||||
b. The `help' builtin no longer does prefix substring matching, so `help read'
|
||||
does not match `readonly'.
|
||||
|
||||
c. The shell can be compiled to not display a message about processes that
|
||||
terminate due to SIGTERM.
|
||||
|
||||
d. Non-interactive shells now react to the setting of checkwinsize and set
|
||||
LINES and COLUMNS after a foreground job exits.
|
||||
|
||||
e. There is a new shell option, `globasciiranges', which, when set to on,
|
||||
forces globbing range comparisons to use character ordering as if they
|
||||
were run in the C locale.
|
||||
|
||||
f. There is a new shell option, `direxpand', which makes filename completion
|
||||
expand variables in directory names in the way bash-4.1 did.
|
||||
|
||||
g. In Posix mode, the `command' builtin does not change whether or not a
|
||||
builtin it shadows is treated as an assignment builtin.
|
||||
|
||||
h. The `return' and `exit' builtins accept negative exit status arguments.
|
||||
|
||||
i. The word completion code checks whether or not a filename containing a
|
||||
shell variable expands to a directory name and appends `/' to the word
|
||||
as appropriate. The same code expands shell variables in command names
|
||||
when performing command completion.
|
||||
|
||||
j. In Posix mode, it is now an error to attempt to define a shell function
|
||||
with the same name as a Posix special builtin.
|
||||
|
||||
k. When compiled for strict Posix conformance, history expansion is disabled
|
||||
b. There is now a configure-time option to enable the globasciiranges option
|
||||
by default.
|
||||
|
||||
l. The history expansion character (!) does not cause history expansion when
|
||||
followed by the closing quote in a double-quoted string.
|
||||
|
||||
m. `complete' and its siblings compgen/compopt now takes a new `-o noquote'
|
||||
option to inhibit quoting of the completions.
|
||||
|
||||
n. Setting HISTSIZE to a value less than zero causes the history list to be
|
||||
unlimited (setting it 0 zero disables the history list).
|
||||
|
||||
o. Setting HISTFILESIZE to a value less than zero causes the history file size
|
||||
to be unlimited (setting it to 0 causes the history file to be truncated
|
||||
to zero size).
|
||||
|
||||
p. The `read' builtin now skips NUL bytes in the input.
|
||||
|
||||
q. There is a new `bind -X' option to print all key sequences bound to Unix
|
||||
commands.
|
||||
|
||||
r. When in Posix mode, `read' is interruptible by a trapped signal. After
|
||||
running the trap handler, read returns 128+signal and throws away any
|
||||
partially-read input.
|
||||
|
||||
s. The command completion code skips whitespace and assignment statements
|
||||
before looking for the command name word to be completed.
|
||||
|
||||
t. The build process has a new mechanism for constructing separate help files
|
||||
that better reflects the current set of compilation options.
|
||||
|
||||
u. The -nt and -ot options to test now work with files with nanosecond
|
||||
timestamp resolution.
|
||||
|
||||
v. The shell saves the command history in any shell for which history is
|
||||
enabled and HISTFILE is set, not just interactive shells.
|
||||
|
||||
w. The shell has `nameref' variables and new -n(/+n) options to declare and
|
||||
unset to use them, and a `test -R' option to test for them.
|
||||
|
||||
x. The shell now allows assigning, referencing, and unsetting elements of
|
||||
indexed arrays using negative subscripts (a[-1]=2, echo ${a[-1]}) which
|
||||
count back from the last element of the array.
|
||||
|
||||
y. The {x}<word redirection feature now allows words like {array[ind]} and
|
||||
can use variables with special meanings to the shell (e.g., BASH_XTRACEFD).
|
||||
|
||||
z. There is a new CHILD_MAX special shell variable; its value controls the
|
||||
number of exited child statues the shell remembers.
|
||||
|
||||
aa. There is a new configuration option (--enable-direxpand-default) that
|
||||
causes the `direxpand' shell option to be enabled by default.
|
||||
|
||||
bb. Bash does not do anything special to ensure that the file descriptor
|
||||
assigned to X in {x}<foo remains open after the block containing it
|
||||
completes.
|
||||
|
||||
cc. The `wait' builtin has a new `-n' option to wait for the next child to
|
||||
change status.
|
||||
|
||||
dd. The `printf' %(...)T format specifier now uses the current time if no
|
||||
argument is supplied.
|
||||
|
||||
ee. There is a new variable, BASH_COMPAT, that controls the current shell
|
||||
compatibility level.
|
||||
|
||||
ff. The `popd' builtin now treats additional arguments as errors.
|
||||
|
||||
gg. The brace expansion code now treats a failed sequence expansion as a
|
||||
simple string and will continue to expand brace terms in the remainder
|
||||
of the word.
|
||||
|
||||
4. New Features in Readline
|
||||
|
||||
a. Readline is now more responsive to SIGHUP and other fatal signals when
|
||||
reading input from the terminal or performing word completion but no
|
||||
longer attempts to run any not-allowable functions from a signal handler
|
||||
context.
|
||||
|
||||
b. There are new bindable commands to search the history for the string of
|
||||
characters between the beginning of the line and the point
|
||||
(history-substring-search-forward, history-substring-search-backward)
|
||||
|
||||
c. Readline allows quoted strings as the values of variables when setting
|
||||
them with `set'. As a side effect, trailing spaces and tabs are ignored
|
||||
when setting a string variable's value.
|
||||
|
||||
d. The history library creates a backup of the history file when writing it
|
||||
and restores the backup on a write error.
|
||||
|
||||
e. New application-settable variable: rl_filename_stat_hook: a function called
|
||||
with a filename before using it in a call to stat(2). Bash uses it to
|
||||
expand shell variables so things like $HOME/Downloads have a slash
|
||||
appended.
|
||||
|
||||
f. New bindable function `print-last-kbd-macro', prints the most-recently-
|
||||
defined keyboard macro in a reusable format.
|
||||
|
||||
g. New user-settable variable `colored-stats', enables use of colored text
|
||||
to denote file types when displaying possible completions (colored analog
|
||||
of visible-stats).
|
||||
|
||||
h. New user-settable variable `keyseq-timout', acts as an inter-character
|
||||
timeout when reading input or incremental search strings.
|
||||
|
||||
i. New application-callable function: rl_clear_history. Clears the history list
|
||||
and frees all readline-associated private data.
|
||||
|
||||
j. New user-settable variable, show-mode-in-prompt, adds a characters to the
|
||||
beginning of the prompt indicating the current editing mode.
|
||||
|
||||
k. New application-settable variable: rl_input_available_hook; function to be
|
||||
called when readline detects there is data available on its input file
|
||||
descriptor.
|
||||
|
||||
l. Readline calls an application-set event hook (rl_signal_event_hook) after
|
||||
it gets a signal while reading input (read returns -1/EINTR but readline
|
||||
does not handle the signal immediately) to allow the application to handle
|
||||
or otherwise note it. Not currently called for SIGHUP or SIGTERM.
|
||||
|
||||
m. If the user-settable variable `history-size' is set to a value less than
|
||||
0, the history list size is unlimited.
|
||||
c. The read builtin now checks its first variable argument for validity before
|
||||
trying to read any input.
|
||||
|
||||
@@ -5079,3 +5079,36 @@ redir.c
|
||||
doc/{bash.1,bashref.texi}
|
||||
- slight change to add a description of `shopt -o' suggested by Bruce
|
||||
Korb <bruce.korb@gmail.com>
|
||||
|
||||
7/19
|
||||
----
|
||||
lib/readline/histfile.c
|
||||
- history_do_write: if close returns < 0, make sure we restore the
|
||||
backup history file and return a non-zero value
|
||||
- history_truncate_file: if write or close return < 0, make sure we
|
||||
return a non-zero value
|
||||
|
||||
[bash-4.3-beta frozen]
|
||||
|
||||
7/21
|
||||
----
|
||||
lib/readline/isearch.c
|
||||
- rl_display_search: now takes an entire search context flags word as
|
||||
the second argument, instead of just reverse flag; changed callers
|
||||
- rl_display_search: if the search has failed, add `failed ' to the
|
||||
beginning of the search prompt
|
||||
- _rl_isearch_dispatch: if the search has failed, display the entire
|
||||
search string with an indication that the search failed but with the
|
||||
last matching line. Suggested by jidanni@jidanni.org
|
||||
|
||||
command.h
|
||||
- W_ASSIGNINT: new word flag; used internally for make_internal_declare
|
||||
and set by fix_assignment_words
|
||||
|
||||
execute_cmd.c
|
||||
- fix_assignment_words: set W_ASSIGNINT if compound assignment and -i
|
||||
given as option. We don't do anything with the value yet
|
||||
|
||||
subst.c
|
||||
- shell_expand_word_list: rework the way the option list that is
|
||||
passed to make_internal_declare is created
|
||||
|
||||
@@ -5073,3 +5073,42 @@ redir.c
|
||||
the parent process as well, since parents and children share the
|
||||
file pointer. Fixes problem originally reported in March 2013 by
|
||||
Martin Jackson <mjackson220.list@gmail.com>
|
||||
|
||||
7/13
|
||||
----
|
||||
doc/{bash.1,bashref.texi}
|
||||
- slight change to add a description of `shopt -o' suggested by Bruce
|
||||
Korb <bruce.korb@gmail.com>
|
||||
|
||||
7/19
|
||||
----
|
||||
lib/readline/histfile.c
|
||||
- history_do_write: if close returns < 0, make sure we restore the
|
||||
backup history file and return a non-zero value
|
||||
- history_truncate_file: if write or close return < 0, make sure we
|
||||
return a non-zero value
|
||||
|
||||
[bash-4.3-beta frozen]
|
||||
|
||||
7/21
|
||||
----
|
||||
lib/readline/isearch.c
|
||||
- rl_display_search: now takes an entire search context flags word as
|
||||
the second argument, instead of just reverse flag; changed callers
|
||||
- rl_display_search: if the search has failed, add `failed ' to the
|
||||
beginning of the search prompt
|
||||
- _rl_isearch_dispatch: if the search has failed, display the entire
|
||||
search string with an indication that the search failed but with the
|
||||
last matching line. Suggested by jidanni@jidanni.org
|
||||
|
||||
command.h
|
||||
- W_ASSIGNINT: new word flag; used internally for make_internal_declare
|
||||
and set by fix_assignment_words
|
||||
|
||||
execute_cmd.c
|
||||
- fix_assignment_words: set W_ASSIGNINT if compound assignment and -i
|
||||
given as option
|
||||
|
||||
subst.c
|
||||
- shell_expand_word_list: rework the way the option list that is
|
||||
passed to make_internal_declare is created
|
||||
|
||||
@@ -801,6 +801,7 @@ tests/array11.sub f
|
||||
tests/array12.sub f
|
||||
tests/array13.sub f
|
||||
tests/array14.sub f
|
||||
tests/array15.sub f
|
||||
tests/array-at-star f
|
||||
tests/array2.right f
|
||||
tests/assoc.tests f
|
||||
|
||||
@@ -110,6 +110,12 @@ gg. The brace expansion code now treats a failed sequence expansion as a
|
||||
|
||||
hh. Shells started to run process substitutions now run any trap set on EXIT.
|
||||
|
||||
ii. There is now a configure-time option to enable the globasciiranges option
|
||||
by default.
|
||||
|
||||
jj. The read builtin now checks its first variable argument for validity before
|
||||
trying to read any input.
|
||||
|
||||
2. New Features in Readline
|
||||
|
||||
a. Readline is now more responsive to SIGHUP and other fatal signals when
|
||||
@@ -164,4 +170,3 @@ m. If the user-settable variable `history-size' is set to a value less than
|
||||
n. New application-settable variable: rl_signal_event_hook; function that is
|
||||
called when readline is reading terminal input and read(2) is interrupted
|
||||
by a signal. Currently not called for SIGHUP or SIGTERM.
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
#define W_ARRAYIND 0x1000000 /* word is an array index being expanded */
|
||||
#define W_ASSNGLOBAL 0x2000000 /* word is a global assignment to declare (declare/typeset -g) */
|
||||
#define W_NOBRACE 0x4000000 /* Don't perform brace expansion */
|
||||
#define W_ASSIGNINT 0x8000000 /* word is an integer assignment to declare */
|
||||
|
||||
/* Possible values for subshell_environment */
|
||||
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
||||
|
||||
+391
@@ -0,0 +1,391 @@
|
||||
/* command.h -- The structures used internally to represent commands, and
|
||||
the extern declarations of the functions used to create them. */
|
||||
|
||||
/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined (_COMMAND_H_)
|
||||
#define _COMMAND_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
/* Instructions describing what kind of thing to do for a redirection. */
|
||||
enum r_instruction {
|
||||
r_output_direction, r_input_direction, r_inputa_direction,
|
||||
r_appending_to, r_reading_until, r_reading_string,
|
||||
r_duplicating_input, r_duplicating_output, r_deblank_reading_until,
|
||||
r_close_this, r_err_and_out, r_input_output, r_output_force,
|
||||
r_duplicating_input_word, r_duplicating_output_word,
|
||||
r_move_input, r_move_output, r_move_input_word, r_move_output_word,
|
||||
r_append_err_and_out
|
||||
};
|
||||
|
||||
/* Redirection flags; values for rflags */
|
||||
#define REDIR_VARASSIGN 0x01
|
||||
|
||||
/* Redirection errors. */
|
||||
#define AMBIGUOUS_REDIRECT -1
|
||||
#define NOCLOBBER_REDIRECT -2
|
||||
#define RESTRICTED_REDIRECT -3 /* can only happen in restricted shells. */
|
||||
#define HEREDOC_REDIRECT -4 /* here-doc temp file can't be created */
|
||||
#define BADVAR_REDIRECT -5 /* something wrong with {varname}redir */
|
||||
|
||||
#define CLOBBERING_REDIRECT(ri) \
|
||||
(ri == r_output_direction || ri == r_err_and_out)
|
||||
|
||||
#define OUTPUT_REDIRECT(ri) \
|
||||
(ri == r_output_direction || ri == r_input_output || ri == r_err_and_out || ri == r_append_err_and_out)
|
||||
|
||||
#define INPUT_REDIRECT(ri) \
|
||||
(ri == r_input_direction || ri == r_inputa_direction || ri == r_input_output)
|
||||
|
||||
#define WRITE_REDIRECT(ri) \
|
||||
(ri == r_output_direction || \
|
||||
ri == r_input_output || \
|
||||
ri == r_err_and_out || \
|
||||
ri == r_appending_to || \
|
||||
ri == r_append_err_and_out || \
|
||||
ri == r_output_force)
|
||||
|
||||
/* redirection needs translation */
|
||||
#define TRANSLATE_REDIRECT(ri) \
|
||||
(ri == r_duplicating_input_word || ri == r_duplicating_output_word || \
|
||||
ri == r_move_input_word || ri == r_move_output_word)
|
||||
|
||||
/* Command Types: */
|
||||
enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
cm_connection, cm_function_def, cm_until, cm_group,
|
||||
cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc };
|
||||
|
||||
/* Possible values for the `flags' field of a WORD_DESC. */
|
||||
#define W_HASDOLLAR 0x000001 /* Dollar sign present. */
|
||||
#define W_QUOTED 0x000002 /* Some form of quote character is present. */
|
||||
#define W_ASSIGNMENT 0x000004 /* This word is a variable assignment. */
|
||||
#define W_SPLITSPACE 0x000008 /* Split this word on " " regardless of IFS */
|
||||
#define W_NOSPLIT 0x000010 /* Do not perform word splitting on this word because ifs is empty string. */
|
||||
#define W_NOGLOB 0x000020 /* Do not perform globbing on this word. */
|
||||
#define W_NOSPLIT2 0x000040 /* Don't split word except for $@ expansion (using spaces) because context does not allow it. */
|
||||
#define W_TILDEEXP 0x000080 /* Tilde expand this assignment word */
|
||||
#define W_DOLLARAT 0x000100 /* $@ and its special handling */
|
||||
#define W_DOLLARSTAR 0x000200 /* $* and its special handling */
|
||||
#define W_NOCOMSUB 0x000400 /* Don't perform command substitution on this word */
|
||||
#define W_ASSIGNRHS 0x000800 /* Word is rhs of an assignment statement */
|
||||
#define W_NOTILDE 0x001000 /* Don't perform tilde expansion on this word */
|
||||
#define W_ITILDE 0x002000 /* Internal flag for word expansion */
|
||||
#define W_NOEXPAND 0x004000 /* Don't expand at all -- do quote removal */
|
||||
#define W_COMPASSIGN 0x008000 /* Compound assignment */
|
||||
#define W_ASSNBLTIN 0x010000 /* word is a builtin command that takes assignments */
|
||||
#define W_ASSIGNARG 0x020000 /* word is assignment argument to command */
|
||||
#define W_HASQUOTEDNULL 0x040000 /* word contains a quoted null character */
|
||||
#define W_DQUOTE 0x080000 /* word should be treated as if double-quoted */
|
||||
#define W_NOPROCSUB 0x100000 /* don't perform process substitution */
|
||||
#define W_HASCTLESC 0x200000 /* word contains literal CTLESC characters */
|
||||
#define W_ASSIGNASSOC 0x400000 /* word looks like associative array assignment */
|
||||
#define W_ASSIGNARRAY 0x800000 /* word looks like a compound indexed array assignment */
|
||||
#define W_ARRAYIND 0x1000000 /* word is an array index being expanded */
|
||||
#define W_ASSNGLOBAL 0x2000000 /* word is a global assignment to declare (declare/typeset -g) */
|
||||
#define W_NOBRACE 0x4000000 /* Don't perform brace expansion */
|
||||
|
||||
/* Possible values for subshell_environment */
|
||||
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
||||
#define SUBSHELL_PAREN 0x02 /* subshell caused by ( ... ) */
|
||||
#define SUBSHELL_COMSUB 0x04 /* subshell caused by `command` or $(command) */
|
||||
#define SUBSHELL_FORK 0x08 /* subshell caused by executing a disk command */
|
||||
#define SUBSHELL_PIPE 0x10 /* subshell from a pipeline element */
|
||||
#define SUBSHELL_PROCSUB 0x20 /* subshell caused by <(command) or >(command) */
|
||||
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
|
||||
#define SUBSHELL_RESETTRAP 0x80 /* subshell needs to reset trap strings on first call to trap */
|
||||
|
||||
/* A structure which represents a word. */
|
||||
typedef struct word_desc {
|
||||
char *word; /* Zero terminated string. */
|
||||
int flags; /* Flags associated with this word. */
|
||||
} WORD_DESC;
|
||||
|
||||
/* A linked list of words. */
|
||||
typedef struct word_list {
|
||||
struct word_list *next;
|
||||
WORD_DESC *word;
|
||||
} WORD_LIST;
|
||||
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Shell Command Structs */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* What a redirection descriptor looks like. If the redirection instruction
|
||||
is ri_duplicating_input or ri_duplicating_output, use DEST, otherwise
|
||||
use the file in FILENAME. Out-of-range descriptors are identified by a
|
||||
negative DEST. */
|
||||
|
||||
typedef union {
|
||||
int dest; /* Place to redirect REDIRECTOR to, or ... */
|
||||
WORD_DESC *filename; /* filename to redirect to. */
|
||||
} REDIRECTEE;
|
||||
|
||||
/* Structure describing a redirection. If REDIRECTOR is negative, the parser
|
||||
(or translator in redir.c) encountered an out-of-range file descriptor. */
|
||||
typedef struct redirect {
|
||||
struct redirect *next; /* Next element, or NULL. */
|
||||
REDIRECTEE redirector; /* Descriptor or varname to be redirected. */
|
||||
int rflags; /* Private flags for this redirection */
|
||||
int flags; /* Flag value for `open'. */
|
||||
enum r_instruction instruction; /* What to do with the information. */
|
||||
REDIRECTEE redirectee; /* File descriptor or filename */
|
||||
char *here_doc_eof; /* The word that appeared in <<foo. */
|
||||
} REDIRECT;
|
||||
|
||||
/* An element used in parsing. A single word or a single redirection.
|
||||
This is an ephemeral construct. */
|
||||
typedef struct element {
|
||||
WORD_DESC *word;
|
||||
REDIRECT *redirect;
|
||||
} ELEMENT;
|
||||
|
||||
/* Possible values for command->flags. */
|
||||
#define CMD_WANT_SUBSHELL 0x01 /* User wants a subshell: ( command ) */
|
||||
#define CMD_FORCE_SUBSHELL 0x02 /* Shell needs to force a subshell. */
|
||||
#define CMD_INVERT_RETURN 0x04 /* Invert the exit value. */
|
||||
#define CMD_IGNORE_RETURN 0x08 /* Ignore the exit value. For set -e. */
|
||||
#define CMD_NO_FUNCTIONS 0x10 /* Ignore functions during command lookup. */
|
||||
#define CMD_INHIBIT_EXPANSION 0x20 /* Do not expand the command words. */
|
||||
#define CMD_NO_FORK 0x40 /* Don't fork; just call execve */
|
||||
#define CMD_TIME_PIPELINE 0x80 /* Time a pipeline */
|
||||
#define CMD_TIME_POSIX 0x100 /* time -p; use POSIX.2 time output spec. */
|
||||
#define CMD_AMPERSAND 0x200 /* command & */
|
||||
#define CMD_STDIN_REDIR 0x400 /* async command needs implicit </dev/null */
|
||||
#define CMD_COMMAND_BUILTIN 0x0800 /* command executed by `command' builtin */
|
||||
#define CMD_COPROC_SUBSHELL 0x1000
|
||||
#define CMD_LASTPIPE 0x2000
|
||||
|
||||
/* What a command looks like. */
|
||||
typedef struct command {
|
||||
enum command_type type; /* FOR CASE WHILE IF CONNECTION or SIMPLE. */
|
||||
int flags; /* Flags controlling execution environment. */
|
||||
int line; /* line number the command starts on */
|
||||
REDIRECT *redirects; /* Special redirects for FOR CASE, etc. */
|
||||
union {
|
||||
struct for_com *For;
|
||||
struct case_com *Case;
|
||||
struct while_com *While;
|
||||
struct if_com *If;
|
||||
struct connection *Connection;
|
||||
struct simple_com *Simple;
|
||||
struct function_def *Function_def;
|
||||
struct group_com *Group;
|
||||
#if defined (SELECT_COMMAND)
|
||||
struct select_com *Select;
|
||||
#endif
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
struct arith_com *Arith;
|
||||
#endif
|
||||
#if defined (COND_COMMAND)
|
||||
struct cond_com *Cond;
|
||||
#endif
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
struct arith_for_com *ArithFor;
|
||||
#endif
|
||||
struct subshell_com *Subshell;
|
||||
struct coproc_com *Coproc;
|
||||
} value;
|
||||
} COMMAND;
|
||||
|
||||
/* Structure used to represent the CONNECTION type. */
|
||||
typedef struct connection {
|
||||
int ignore; /* Unused; simplifies make_command (). */
|
||||
COMMAND *first; /* Pointer to the first command. */
|
||||
COMMAND *second; /* Pointer to the second command. */
|
||||
int connector; /* What separates this command from others. */
|
||||
} CONNECTION;
|
||||
|
||||
/* Structures used to represent the CASE command. */
|
||||
|
||||
/* Values for FLAGS word in a PATTERN_LIST */
|
||||
#define CASEPAT_FALLTHROUGH 0x01
|
||||
#define CASEPAT_TESTNEXT 0x02
|
||||
|
||||
/* Pattern/action structure for CASE_COM. */
|
||||
typedef struct pattern_list {
|
||||
struct pattern_list *next; /* Clause to try in case this one failed. */
|
||||
WORD_LIST *patterns; /* Linked list of patterns to test. */
|
||||
COMMAND *action; /* Thing to execute if a pattern matches. */
|
||||
int flags;
|
||||
} PATTERN_LIST;
|
||||
|
||||
/* The CASE command. */
|
||||
typedef struct case_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `case' keyword appears on */
|
||||
WORD_DESC *word; /* The thing to test. */
|
||||
PATTERN_LIST *clauses; /* The clauses to test against, or NULL. */
|
||||
} CASE_COM;
|
||||
|
||||
/* FOR command. */
|
||||
typedef struct for_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `for' keyword appears on */
|
||||
WORD_DESC *name; /* The variable name to get mapped over. */
|
||||
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
|
||||
COMMAND *action; /* The action to execute.
|
||||
During execution, NAME is bound to successive
|
||||
members of MAP_LIST. */
|
||||
} FOR_COM;
|
||||
|
||||
#if defined (ARITH_FOR_COMMAND)
|
||||
typedef struct arith_for_com {
|
||||
int flags;
|
||||
int line; /* generally used for error messages */
|
||||
WORD_LIST *init;
|
||||
WORD_LIST *test;
|
||||
WORD_LIST *step;
|
||||
COMMAND *action;
|
||||
} ARITH_FOR_COM;
|
||||
#endif
|
||||
|
||||
#if defined (SELECT_COMMAND)
|
||||
/* KSH SELECT command. */
|
||||
typedef struct select_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the `select' keyword appears on */
|
||||
WORD_DESC *name; /* The variable name to get mapped over. */
|
||||
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
|
||||
COMMAND *action; /* The action to execute.
|
||||
During execution, NAME is bound to the member of
|
||||
MAP_LIST chosen by the user. */
|
||||
} SELECT_COM;
|
||||
#endif /* SELECT_COMMAND */
|
||||
|
||||
/* IF command. */
|
||||
typedef struct if_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
COMMAND *test; /* Thing to test. */
|
||||
COMMAND *true_case; /* What to do if the test returned non-zero. */
|
||||
COMMAND *false_case; /* What to do if the test returned zero. */
|
||||
} IF_COM;
|
||||
|
||||
/* WHILE command. */
|
||||
typedef struct while_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
COMMAND *test; /* Thing to test. */
|
||||
COMMAND *action; /* Thing to do while test is non-zero. */
|
||||
} WHILE_COM;
|
||||
|
||||
#if defined (DPAREN_ARITHMETIC)
|
||||
/* The arithmetic evaluation command, ((...)). Just a set of flags and
|
||||
a WORD_LIST, of which the first element is the only one used, for the
|
||||
time being. */
|
||||
typedef struct arith_com {
|
||||
int flags;
|
||||
int line;
|
||||
WORD_LIST *exp;
|
||||
} ARITH_COM;
|
||||
#endif /* DPAREN_ARITHMETIC */
|
||||
|
||||
/* The conditional command, [[...]]. This is a binary tree -- we slippped
|
||||
a recursive-descent parser into the YACC grammar to parse it. */
|
||||
#define COND_AND 1
|
||||
#define COND_OR 2
|
||||
#define COND_UNARY 3
|
||||
#define COND_BINARY 4
|
||||
#define COND_TERM 5
|
||||
#define COND_EXPR 6
|
||||
|
||||
typedef struct cond_com {
|
||||
int flags;
|
||||
int line;
|
||||
int type;
|
||||
WORD_DESC *op;
|
||||
struct cond_com *left, *right;
|
||||
} COND_COM;
|
||||
|
||||
/* The "simple" command. Just a collection of words and redirects. */
|
||||
typedef struct simple_com {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* line number the command starts on */
|
||||
WORD_LIST *words; /* The program name, the arguments,
|
||||
variable assignments, etc. */
|
||||
REDIRECT *redirects; /* Redirections to perform. */
|
||||
} SIMPLE_COM;
|
||||
|
||||
/* The "function definition" command. */
|
||||
typedef struct function_def {
|
||||
int flags; /* See description of CMD flags. */
|
||||
int line; /* Line number the function def starts on. */
|
||||
WORD_DESC *name; /* The name of the function. */
|
||||
COMMAND *command; /* The parsed execution tree. */
|
||||
char *source_file; /* file in which function was defined, if any */
|
||||
} FUNCTION_DEF;
|
||||
|
||||
/* A command that is `grouped' allows pipes and redirections to affect all
|
||||
commands in the group. */
|
||||
typedef struct group_com {
|
||||
int ignore; /* See description of CMD flags. */
|
||||
COMMAND *command;
|
||||
} GROUP_COM;
|
||||
|
||||
typedef struct subshell_com {
|
||||
int flags;
|
||||
COMMAND *command;
|
||||
} SUBSHELL_COM;
|
||||
|
||||
#define COPROC_RUNNING 0x01
|
||||
#define COPROC_DEAD 0x02
|
||||
|
||||
typedef struct coproc {
|
||||
char *c_name;
|
||||
pid_t c_pid;
|
||||
int c_rfd;
|
||||
int c_wfd;
|
||||
int c_rsave;
|
||||
int c_wsave;
|
||||
int c_flags;
|
||||
int c_status;
|
||||
int c_lock;
|
||||
} Coproc;
|
||||
|
||||
typedef struct coproc_com {
|
||||
int flags;
|
||||
char *name;
|
||||
COMMAND *command;
|
||||
} COPROC_COM;
|
||||
|
||||
extern COMMAND *global_command;
|
||||
extern Coproc sh_coproc;
|
||||
|
||||
/* Possible command errors */
|
||||
#define CMDERR_DEFAULT 0
|
||||
#define CMDERR_BADTYPE 1
|
||||
#define CMDERR_BADCONN 2
|
||||
#define CMDERR_BADJUMP 3
|
||||
|
||||
#define CMDERR_LAST 3
|
||||
|
||||
/* Forward declarations of functions declared in copy_cmd.c. */
|
||||
|
||||
extern FUNCTION_DEF *copy_function_def_contents __P((FUNCTION_DEF *, FUNCTION_DEF *));
|
||||
extern FUNCTION_DEF *copy_function_def __P((FUNCTION_DEF *));
|
||||
|
||||
extern WORD_DESC *copy_word __P((WORD_DESC *));
|
||||
extern WORD_LIST *copy_word_list __P((WORD_LIST *));
|
||||
extern REDIRECT *copy_redirect __P((REDIRECT *));
|
||||
extern REDIRECT *copy_redirects __P((REDIRECT *));
|
||||
extern COMMAND *copy_command __P((COMMAND *));
|
||||
|
||||
#endif /* _COMMAND_H_ */
|
||||
@@ -0,0 +1,385 @@
|
||||
*** ../bash-4.2-patched/lib/readline/readline.c 2010-07-25 17:07:40.000000000 -0400
|
||||
--- lib/readline/readline.c 2013-07-21 15:52:16.000000000 -0400
|
||||
***************
|
||||
*** 2,6 ****
|
||||
with emacs style editing and completion. */
|
||||
|
||||
! /* Copyright (C) 1987-2009 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
--- 2,6 ----
|
||||
with emacs style editing and completion. */
|
||||
|
||||
! /* Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
***************
|
||||
*** 113,117 ****
|
||||
Keymap _rl_keymap = emacs_standard_keymap;
|
||||
|
||||
-
|
||||
/* The current style of editing. */
|
||||
int rl_editing_mode = emacs_mode;
|
||||
--- 113,116 ----
|
||||
***************
|
||||
*** 246,249 ****
|
||||
--- 245,267 ----
|
||||
_rl_keyseq_cxt *_rl_kscxt = 0;
|
||||
|
||||
+ int rl_executing_key;
|
||||
+ char *rl_executing_keyseq = 0;
|
||||
+ int _rl_executing_keyseq_size = 0;
|
||||
+
|
||||
+ /* Timeout (specified in milliseconds) when reading characters making up an
|
||||
+ ambiguous multiple-key sequence */
|
||||
+ int _rl_keyseq_timeout = 500;
|
||||
+
|
||||
+ #define RESIZE_KEYSEQ_BUFFER() \
|
||||
+ do \
|
||||
+ { \
|
||||
+ if (rl_key_sequence_length + 2 >= _rl_executing_keyseq_size) \
|
||||
+ { \
|
||||
+ _rl_executing_keyseq_size += 16; \
|
||||
+ rl_executing_keyseq = xrealloc (rl_executing_keyseq, _rl_executing_keyseq_size); \
|
||||
+ } \
|
||||
+ } \
|
||||
+ while (0);
|
||||
+
|
||||
/* Forward declarations used by the display, termcap, and history code. */
|
||||
|
||||
***************
|
||||
*** 280,283 ****
|
||||
--- 298,305 ----
|
||||
int _rl_echo_control_chars = 1;
|
||||
|
||||
+ /* Non-zero means to prefix the displayed prompt with a character indicating
|
||||
+ the editing mode: @ for emacs, : for vi-command, + for vi-insert. */
|
||||
+ int _rl_show_mode_in_prompt = 0;
|
||||
+
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
***************
|
||||
*** 353,356 ****
|
||||
--- 375,383 ----
|
||||
#endif
|
||||
|
||||
+ #if HAVE_DECL_AUDIT_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
|
||||
+ if (value)
|
||||
+ _rl_audit_tty (value);
|
||||
+ #endif
|
||||
+
|
||||
return (value);
|
||||
}
|
||||
***************
|
||||
*** 370,376 ****
|
||||
--- 397,413 ----
|
||||
_rl_out_stream = rl_outstream;
|
||||
|
||||
+ /* Enable the meta key only for the duration of readline(), if this
|
||||
+ terminal has one and the terminal has been initialized */
|
||||
+ if (_rl_enable_meta & RL_ISSTATE (RL_STATE_TERMPREPPED))
|
||||
+ _rl_enable_meta_key ();
|
||||
+
|
||||
if (rl_startup_hook)
|
||||
(*rl_startup_hook) ();
|
||||
|
||||
+ #if defined (VI_MODE)
|
||||
+ if (rl_editing_mode == vi_mode)
|
||||
+ rl_vi_insertion_mode (1, 'i'); /* don't want to reset last */
|
||||
+ #endif /* VI_MODE */
|
||||
+
|
||||
/* If we're not echoing, we still want to at least print a prompt, because
|
||||
rl_redisplay will not do it for us. If the calling application has a
|
||||
***************
|
||||
*** 395,403 ****
|
||||
}
|
||||
|
||||
- #if defined (VI_MODE)
|
||||
- if (rl_editing_mode == vi_mode)
|
||||
- rl_vi_insert_mode (1, 'i');
|
||||
- #endif /* VI_MODE */
|
||||
-
|
||||
if (rl_pre_input_hook)
|
||||
(*rl_pre_input_hook) ();
|
||||
--- 432,435 ----
|
||||
***************
|
||||
*** 438,441 ****
|
||||
--- 470,478 ----
|
||||
rl_free_undo_list ();
|
||||
|
||||
+ /* Disable the meta key, if this terminal has one and we were told to use it.
|
||||
+ The check whether or not we sent the enable string is in
|
||||
+ _rl_disable_meta_key(); the flag is set in _rl_enable_meta_key */
|
||||
+ _rl_disable_meta_key ();
|
||||
+
|
||||
/* Restore normal cursor, if available. */
|
||||
_rl_set_insert_mode (RL_IM_INSERT, 0);
|
||||
***************
|
||||
*** 493,497 ****
|
||||
--- 530,538 ----
|
||||
lk = _rl_last_command_was_kill;
|
||||
|
||||
+ #if defined (HAVE_POSIX_SIGSETJMP)
|
||||
+ code = sigsetjmp (_rl_top_level, 0);
|
||||
+ #else
|
||||
code = setjmp (_rl_top_level);
|
||||
+ #endif
|
||||
|
||||
if (code)
|
||||
***************
|
||||
*** 512,515 ****
|
||||
--- 553,557 ----
|
||||
_rl_reset_argument ();
|
||||
rl_key_sequence_length = 0;
|
||||
+ rl_executing_keyseq[0] = 0;
|
||||
}
|
||||
|
||||
***************
|
||||
*** 520,524 ****
|
||||
/* look at input.c:rl_getc() for the circumstances under which this will
|
||||
be returned; punt immediately on read error without converting it to
|
||||
! a newline. */
|
||||
if (c == READERR)
|
||||
{
|
||||
--- 562,567 ----
|
||||
/* look at input.c:rl_getc() for the circumstances under which this will
|
||||
be returned; punt immediately on read error without converting it to
|
||||
! a newline; assume that rl_read_key has already called the signal
|
||||
! handler. */
|
||||
if (c == READERR)
|
||||
{
|
||||
***************
|
||||
*** 532,536 ****
|
||||
}
|
||||
|
||||
! /* EOF typed to a non-blank line is a <NL>. */
|
||||
if (c == EOF && rl_end)
|
||||
c = NEWLINE;
|
||||
--- 575,581 ----
|
||||
}
|
||||
|
||||
! /* EOF typed to a non-blank line is a <NL>. If we want to change this,
|
||||
! to force any existing line to be ignored when read(2) reads EOF,
|
||||
! for example, this is the place to change. */
|
||||
if (c == EOF && rl_end)
|
||||
c = NEWLINE;
|
||||
***************
|
||||
*** 744,750 ****
|
||||
if (RL_ISSTATE (RL_STATE_MACRODEF))
|
||||
_rl_add_macro_char (ESC);
|
||||
map = FUNCTION_TO_KEYMAP (map, ESC);
|
||||
key = UNMETA (key);
|
||||
- rl_key_sequence_length += 2;
|
||||
return (_rl_dispatch (key, map));
|
||||
}
|
||||
--- 789,796 ----
|
||||
if (RL_ISSTATE (RL_STATE_MACRODEF))
|
||||
_rl_add_macro_char (ESC);
|
||||
+ RESIZE_KEYSEQ_BUFFER ();
|
||||
+ rl_executing_keyseq[rl_key_sequence_length++] = ESC;
|
||||
map = FUNCTION_TO_KEYMAP (map, ESC);
|
||||
key = UNMETA (key);
|
||||
return (_rl_dispatch (key, map));
|
||||
}
|
||||
***************
|
||||
*** 766,776 ****
|
||||
/* Special case rl_do_lowercase_version (). */
|
||||
if (func == rl_do_lowercase_version)
|
||||
return (_rl_dispatch (_rl_to_lower (key), map));
|
||||
|
||||
rl_executing_keymap = map;
|
||||
|
||||
rl_dispatching = 1;
|
||||
RL_SETSTATE(RL_STATE_DISPATCHING);
|
||||
! (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
|
||||
RL_UNSETSTATE(RL_STATE_DISPATCHING);
|
||||
rl_dispatching = 0;
|
||||
--- 812,828 ----
|
||||
/* Special case rl_do_lowercase_version (). */
|
||||
if (func == rl_do_lowercase_version)
|
||||
+ /* Should we do anything special if key == ANYOTHERKEY? */
|
||||
return (_rl_dispatch (_rl_to_lower (key), map));
|
||||
|
||||
rl_executing_keymap = map;
|
||||
+ rl_executing_key = key;
|
||||
+
|
||||
+ RESIZE_KEYSEQ_BUFFER();
|
||||
+ rl_executing_keyseq[rl_key_sequence_length++] = key;
|
||||
+ rl_executing_keyseq[rl_key_sequence_length] = '\0';
|
||||
|
||||
rl_dispatching = 1;
|
||||
RL_SETSTATE(RL_STATE_DISPATCHING);
|
||||
! r = (*func) (rl_numeric_arg * rl_arg_sign, key);
|
||||
RL_UNSETSTATE(RL_STATE_DISPATCHING);
|
||||
rl_dispatching = 0;
|
||||
***************
|
||||
*** 789,793 ****
|
||||
shadow function that was overridden when the current keymap
|
||||
was created. Return -2 to note that. */
|
||||
! _rl_unget_char (key);
|
||||
return -2;
|
||||
}
|
||||
--- 841,848 ----
|
||||
shadow function that was overridden when the current keymap
|
||||
was created. Return -2 to note that. */
|
||||
! if (RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
! _rl_prev_macro_key ();
|
||||
! else
|
||||
! _rl_unget_char (key);
|
||||
return -2;
|
||||
}
|
||||
***************
|
||||
*** 798,802 ****
|
||||
we need to back up the recursion chain and find the last
|
||||
subsequence that is bound to a function. */
|
||||
! _rl_unget_char (key);
|
||||
return -1;
|
||||
}
|
||||
--- 853,860 ----
|
||||
we need to back up the recursion chain and find the last
|
||||
subsequence that is bound to a function. */
|
||||
! if (RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
! _rl_prev_macro_key ();
|
||||
! else
|
||||
! _rl_unget_char (key);
|
||||
return -1;
|
||||
}
|
||||
***************
|
||||
*** 821,831 ****
|
||||
will be if an arrow key has been pressed, and, if there's not,
|
||||
just dispatch to (what we assume is) rl_vi_movement_mode right
|
||||
! away. This is essentially an input test with a zero timeout. */
|
||||
if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
|
||||
! && _rl_input_queued (0) == 0)
|
||||
return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
|
||||
#endif
|
||||
|
||||
! rl_key_sequence_length++;
|
||||
_rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key);
|
||||
|
||||
--- 879,893 ----
|
||||
will be if an arrow key has been pressed, and, if there's not,
|
||||
just dispatch to (what we assume is) rl_vi_movement_mode right
|
||||
! away. This is essentially an input test with a zero timeout (by
|
||||
! default) or a timeout determined by the value of `keyseq-timeout' */
|
||||
! /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
|
||||
! takes microseconds, so multiply by 1000 */
|
||||
if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
|
||||
! && _rl_input_queued ((_rl_keyseq_timeout > 0) ? _rl_keyseq_timeout*1000 : 0) == 0)
|
||||
return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
|
||||
#endif
|
||||
|
||||
! RESIZE_KEYSEQ_BUFFER ();
|
||||
! rl_executing_keyseq[rl_key_sequence_length++] = key;
|
||||
_rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key);
|
||||
|
||||
***************
|
||||
*** 856,859 ****
|
||||
--- 918,933 ----
|
||||
#endif
|
||||
|
||||
+ /* Tentative inter-character timeout for potential multi-key
|
||||
+ sequences? If no input within timeout, abort sequence and
|
||||
+ act as if we got non-matching input. */
|
||||
+ /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
|
||||
+ takes microseconds, so multiply by 1000 */
|
||||
+ if (_rl_keyseq_timeout > 0 &&
|
||||
+ (RL_ISSTATE (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT) == 0) &&
|
||||
+ _rl_pushed_input_available () == 0 &&
|
||||
+ _rl_dispatching_keymap[ANYOTHERKEY].function &&
|
||||
+ _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
|
||||
+ return (_rl_subseq_result (-2, map, key, got_subseq));
|
||||
+
|
||||
newkey = _rl_subseq_getchar (key);
|
||||
if (newkey < 0)
|
||||
***************
|
||||
*** 876,879 ****
|
||||
--- 950,954 ----
|
||||
if (map[key].function != 0)
|
||||
{
|
||||
+ rl_executing_keyseq[rl_key_sequence_length] = '\0';
|
||||
macro = savestring ((char *)map[key].function);
|
||||
_rl_with_macro_input (macro);
|
||||
***************
|
||||
*** 885,888 ****
|
||||
--- 960,964 ----
|
||||
if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
|
||||
key != ANYOTHERKEY &&
|
||||
+ rl_key_sequence_length == 1 && /* XXX */
|
||||
_rl_vi_textmod_command (key))
|
||||
_rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
|
||||
***************
|
||||
*** 936,940 ****
|
||||
tell the caller that it should try ANYOTHERKEY for an
|
||||
overridden function. */
|
||||
! _rl_unget_char (key);
|
||||
_rl_dispatching_keymap = map;
|
||||
return -2;
|
||||
--- 1012,1019 ----
|
||||
tell the caller that it should try ANYOTHERKEY for an
|
||||
overridden function. */
|
||||
! if (RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
! _rl_prev_macro_key ();
|
||||
! else
|
||||
! _rl_unget_char (key);
|
||||
_rl_dispatching_keymap = map;
|
||||
return -2;
|
||||
***************
|
||||
*** 943,947 ****
|
||||
{
|
||||
/* OK, back up the chain. */
|
||||
! _rl_unget_char (key);
|
||||
_rl_dispatching_keymap = map;
|
||||
return -1;
|
||||
--- 1022,1029 ----
|
||||
{
|
||||
/* OK, back up the chain. */
|
||||
! if (RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
! _rl_prev_macro_key ();
|
||||
! else
|
||||
! _rl_unget_char (key);
|
||||
_rl_dispatching_keymap = map;
|
||||
return -1;
|
||||
***************
|
||||
*** 1092,1103 ****
|
||||
bind_arrow_keys ();
|
||||
|
||||
- /* Enable the meta key, if this terminal has one. */
|
||||
- if (_rl_enable_meta)
|
||||
- _rl_enable_meta_key ();
|
||||
-
|
||||
/* If the completion parser's default word break characters haven't
|
||||
been set yet, then do so now. */
|
||||
if (rl_completer_word_break_characters == (char *)NULL)
|
||||
rl_completer_word_break_characters = (char *)rl_basic_word_break_characters;
|
||||
}
|
||||
|
||||
--- 1174,1190 ----
|
||||
bind_arrow_keys ();
|
||||
|
||||
/* If the completion parser's default word break characters haven't
|
||||
been set yet, then do so now. */
|
||||
if (rl_completer_word_break_characters == (char *)NULL)
|
||||
rl_completer_word_break_characters = (char *)rl_basic_word_break_characters;
|
||||
+
|
||||
+ #if defined (COLOR_SUPPORT)
|
||||
+ if (_rl_colored_stats)
|
||||
+ _rl_parse_colors ();
|
||||
+ #endif
|
||||
+
|
||||
+ rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16);
|
||||
+ if (rl_executing_keyseq)
|
||||
+ rl_executing_keyseq[0] = '\0';
|
||||
}
|
||||
|
||||
***************
|
||||
*** 1160,1163 ****
|
||||
--- 1247,1254 ----
|
||||
rl_bind_keyseq_if_unbound ("\340M", rl_forward_char);
|
||||
rl_bind_keyseq_if_unbound ("\340K", rl_backward_char);
|
||||
+ rl_bind_keyseq_if_unbound ("\340G", rl_beg_of_line);
|
||||
+ rl_bind_keyseq_if_unbound ("\340O", rl_end_of_line);
|
||||
+ rl_bind_keyseq_if_unbound ("\340S", rl_delete);
|
||||
+ rl_bind_keyseq_if_unbound ("\340R", rl_overwrite_mode);
|
||||
#endif
|
||||
|
||||
+7
-3
@@ -607,7 +607,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
want to note this before execute_in_subshell modifies the
|
||||
COMMAND struct. Need to keep in mind that execute_in_subshell
|
||||
runs the exit trap for () subshells itself. */
|
||||
/* This handles { command; } &
|
||||
/* This handles { command; } & */
|
||||
s = user_subshell == 0 && command->type == cm_group && pipe_in == NO_PIPE && pipe_out == NO_PIPE && asynchronous;
|
||||
/* run exit trap for : | { ...; } and { ...; } | : */
|
||||
/* run exit trap for : | ( ...; ) and ( ...; ) | : */
|
||||
@@ -3748,13 +3748,13 @@ fix_assignment_words (words)
|
||||
{
|
||||
WORD_LIST *w, *wcmd;
|
||||
struct builtin *b;
|
||||
int assoc, global, array;
|
||||
int assoc, global, array, integer;
|
||||
|
||||
if (words == 0)
|
||||
return;
|
||||
|
||||
b = 0;
|
||||
assoc = global = array = 0;
|
||||
assoc = global = array = integer = 0;
|
||||
|
||||
/* Skip over assignment statements preceding a command name */
|
||||
wcmd = words;
|
||||
@@ -3789,6 +3789,8 @@ fix_assignment_words (words)
|
||||
#endif
|
||||
if (global)
|
||||
w->word->flags |= W_ASSNGLOBAL;
|
||||
if (integer)
|
||||
w->word->flags |= W_ASSIGNINT;
|
||||
}
|
||||
#if defined (ARRAY_VARS)
|
||||
/* Note that we saw an associative array option to a builtin that takes
|
||||
@@ -3814,6 +3816,8 @@ fix_assignment_words (words)
|
||||
array = 1;
|
||||
if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'g'))
|
||||
global = 1;
|
||||
if ((wcmd->word->flags & W_ASSNBLTIN) && strchr (w->word->word+1, 'i'))
|
||||
integer = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5408
File diff suppressed because it is too large
Load Diff
@@ -411,14 +411,16 @@ history_truncate_file (fname, lines)
|
||||
truncate to. */
|
||||
if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
|
||||
{
|
||||
write (file, bp, chars_read - (bp - buffer));
|
||||
if (write (file, bp, chars_read - (bp - buffer)) < 0)
|
||||
rv = errno;
|
||||
|
||||
#if defined (__BEOS__)
|
||||
/* BeOS ignores O_TRUNC. */
|
||||
ftruncate (file, chars_read - (bp - buffer));
|
||||
#endif
|
||||
|
||||
close (file);
|
||||
if (close (file) < 0 && rv == 0)
|
||||
rv = errno;
|
||||
}
|
||||
|
||||
truncate_exit:
|
||||
@@ -547,7 +549,8 @@ mmap_error:
|
||||
#endif
|
||||
}
|
||||
|
||||
close (file);
|
||||
if (close (file) < 0 && rv == 0)
|
||||
rv = errno;
|
||||
|
||||
if (rv != 0 && output && bakname)
|
||||
rename (bakname, output);
|
||||
|
||||
+14
-7
@@ -156,16 +156,16 @@ rl_forward_search_history (sign, key)
|
||||
WHERE is the history list number of the current line. If it is
|
||||
-1, then this line is the starting one. */
|
||||
static void
|
||||
rl_display_search (search_string, reverse_p, where)
|
||||
rl_display_search (search_string, flags, where)
|
||||
char *search_string;
|
||||
int reverse_p, where;
|
||||
int flags, where;
|
||||
{
|
||||
char *message;
|
||||
int msglen, searchlen;
|
||||
|
||||
searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
|
||||
|
||||
message = (char *)xmalloc (searchlen + 33);
|
||||
message = (char *)xmalloc (searchlen + 64);
|
||||
msglen = 0;
|
||||
|
||||
#if defined (NOTDEF)
|
||||
@@ -178,7 +178,13 @@ rl_display_search (search_string, reverse_p, where)
|
||||
|
||||
message[msglen++] = '(';
|
||||
|
||||
if (reverse_p)
|
||||
if (flags & SF_FAILED)
|
||||
{
|
||||
strcpy (message + msglen, "failed ");
|
||||
msglen += 7;
|
||||
}
|
||||
|
||||
if (flags & SF_REVERSE)
|
||||
{
|
||||
strcpy (message + msglen, "reverse-");
|
||||
msglen += 8;
|
||||
@@ -517,7 +523,7 @@ add_character:
|
||||
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
|
||||
strcpy (cxt->search_string, last_isearch_string);
|
||||
cxt->search_string_index = last_isearch_string_len;
|
||||
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
|
||||
rl_display_search (cxt->search_string, cxt->sflags, -1);
|
||||
break;
|
||||
}
|
||||
return (1);
|
||||
@@ -691,6 +697,7 @@ add_character:
|
||||
/* We cannot find the search string. Ding the bell. */
|
||||
rl_ding ();
|
||||
cxt->history_pos = cxt->last_found_line;
|
||||
rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -703,7 +710,7 @@ add_character:
|
||||
rl_replace_line (cxt->lines[cxt->history_pos], 0);
|
||||
rl_point = cxt->sline_index;
|
||||
cxt->last_found_line = cxt->history_pos;
|
||||
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
|
||||
rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -738,7 +745,7 @@ rl_search_history (direction, invoking_key)
|
||||
RL_SETSTATE(RL_STATE_ISEARCH);
|
||||
cxt = _rl_isearch_init (direction);
|
||||
|
||||
rl_display_search (cxt->search_string, (cxt->sflags & SF_REVERSE), -1);
|
||||
rl_display_search (cxt->search_string, cxt->sflags, -1);
|
||||
|
||||
/* If we are using the callback interface, all we do is set up here and
|
||||
return. The key is that we leave RL_STATE_ISEARCH set. */
|
||||
|
||||
@@ -0,0 +1,789 @@
|
||||
/* isearch.c - incremental searching */
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* I-Search and Searching */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
Readline is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Readline is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Readline. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif
|
||||
|
||||
#include "rldefs.h"
|
||||
#include "rlmbutil.h"
|
||||
|
||||
#include "readline.h"
|
||||
#include "history.h"
|
||||
|
||||
#include "rlprivate.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* Variables exported to other files in the readline library. */
|
||||
char *_rl_isearch_terminators = (char *)NULL;
|
||||
|
||||
_rl_search_cxt *_rl_iscxt = 0;
|
||||
|
||||
/* Variables imported from other files in the readline library. */
|
||||
extern HIST_ENTRY *_rl_saved_line_for_history;
|
||||
|
||||
static int rl_search_history PARAMS((int, int));
|
||||
|
||||
static _rl_search_cxt *_rl_isearch_init PARAMS((int));
|
||||
static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
|
||||
static int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int));
|
||||
|
||||
/* Last line found by the current incremental search, so we don't `find'
|
||||
identical lines many times in a row. Now part of isearch context. */
|
||||
/* static char *prev_line_found; */
|
||||
|
||||
/* Last search string and its length. */
|
||||
static char *last_isearch_string;
|
||||
static int last_isearch_string_len;
|
||||
|
||||
static char * const default_isearch_terminators = "\033\012";
|
||||
|
||||
_rl_search_cxt *
|
||||
_rl_scxt_alloc (type, flags)
|
||||
int type, flags;
|
||||
{
|
||||
_rl_search_cxt *cxt;
|
||||
|
||||
cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt));
|
||||
|
||||
cxt->type = type;
|
||||
cxt->sflags = flags;
|
||||
|
||||
cxt->search_string = 0;
|
||||
cxt->search_string_size = cxt->search_string_index = 0;
|
||||
|
||||
cxt->lines = 0;
|
||||
cxt->allocated_line = 0;
|
||||
cxt->hlen = cxt->hindex = 0;
|
||||
|
||||
cxt->save_point = rl_point;
|
||||
cxt->save_mark = rl_mark;
|
||||
cxt->save_line = where_history ();
|
||||
cxt->last_found_line = cxt->save_line;
|
||||
cxt->prev_line_found = 0;
|
||||
|
||||
cxt->save_undo_list = 0;
|
||||
|
||||
cxt->keymap = _rl_keymap;
|
||||
cxt->okeymap = _rl_keymap;
|
||||
|
||||
cxt->history_pos = 0;
|
||||
cxt->direction = 0;
|
||||
|
||||
cxt->prevc = cxt->lastc = 0;
|
||||
|
||||
cxt->sline = 0;
|
||||
cxt->sline_len = cxt->sline_index = 0;
|
||||
|
||||
cxt->search_terminators = 0;
|
||||
|
||||
return cxt;
|
||||
}
|
||||
|
||||
void
|
||||
_rl_scxt_dispose (cxt, flags)
|
||||
_rl_search_cxt *cxt;
|
||||
int flags;
|
||||
{
|
||||
FREE (cxt->search_string);
|
||||
FREE (cxt->allocated_line);
|
||||
FREE (cxt->lines);
|
||||
|
||||
xfree (cxt);
|
||||
}
|
||||
|
||||
/* Search backwards through the history looking for a string which is typed
|
||||
interactively. Start with the current line. */
|
||||
int
|
||||
rl_reverse_search_history (sign, key)
|
||||
int sign, key;
|
||||
{
|
||||
return (rl_search_history (-sign, key));
|
||||
}
|
||||
|
||||
/* Search forwards through the history looking for a string which is typed
|
||||
interactively. Start with the current line. */
|
||||
int
|
||||
rl_forward_search_history (sign, key)
|
||||
int sign, key;
|
||||
{
|
||||
return (rl_search_history (sign, key));
|
||||
}
|
||||
|
||||
/* Display the current state of the search in the echo-area.
|
||||
SEARCH_STRING contains the string that is being searched for,
|
||||
DIRECTION is zero for forward, or non-zero for reverse,
|
||||
WHERE is the history list number of the current line. If it is
|
||||
-1, then this line is the starting one. */
|
||||
static void
|
||||
rl_display_search (search_string, flags, where)
|
||||
char *search_string;
|
||||
int flags, where;
|
||||
{
|
||||
char *message;
|
||||
int msglen, searchlen;
|
||||
|
||||
searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
|
||||
|
||||
message = (char *)xmalloc (searchlen + 64);
|
||||
msglen = 0;
|
||||
|
||||
#if defined (NOTDEF)
|
||||
if (where != -1)
|
||||
{
|
||||
sprintf (message, "[%d]", where + history_base);
|
||||
msglen = strlen (message);
|
||||
}
|
||||
#endif /* NOTDEF */
|
||||
|
||||
message[msglen++] = '(';
|
||||
|
||||
if (flags & SF_FAILED)
|
||||
{
|
||||
strcpy (message + msglen, "failed ");
|
||||
msglen += 7;
|
||||
}
|
||||
|
||||
if (flags & SF_REVERSE)
|
||||
{
|
||||
strcpy (message + msglen, "reverse-");
|
||||
msglen += 8;
|
||||
}
|
||||
|
||||
strcpy (message + msglen, "i-search)`");
|
||||
msglen += 10;
|
||||
|
||||
if (search_string)
|
||||
{
|
||||
strcpy (message + msglen, search_string);
|
||||
msglen += searchlen;
|
||||
}
|
||||
|
||||
strcpy (message + msglen, "': ");
|
||||
|
||||
rl_message ("%s", message);
|
||||
xfree (message);
|
||||
(*rl_redisplay_function) ();
|
||||
}
|
||||
|
||||
static _rl_search_cxt *
|
||||
_rl_isearch_init (direction)
|
||||
int direction;
|
||||
{
|
||||
_rl_search_cxt *cxt;
|
||||
register int i;
|
||||
HIST_ENTRY **hlist;
|
||||
|
||||
cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
|
||||
if (direction < 0)
|
||||
cxt->sflags |= SF_REVERSE;
|
||||
|
||||
cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
|
||||
: default_isearch_terminators;
|
||||
|
||||
/* Create an arrary of pointers to the lines that we want to search. */
|
||||
hlist = history_list ();
|
||||
rl_maybe_replace_line ();
|
||||
i = 0;
|
||||
if (hlist)
|
||||
for (i = 0; hlist[i]; i++);
|
||||
|
||||
/* Allocate space for this many lines, +1 for the current input line,
|
||||
and remember those lines. */
|
||||
cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *));
|
||||
for (i = 0; i < cxt->hlen; i++)
|
||||
cxt->lines[i] = hlist[i]->line;
|
||||
|
||||
if (_rl_saved_line_for_history)
|
||||
cxt->lines[i] = _rl_saved_line_for_history->line;
|
||||
else
|
||||
{
|
||||
/* Keep track of this so we can free it. */
|
||||
cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
|
||||
strcpy (cxt->allocated_line, &rl_line_buffer[0]);
|
||||
cxt->lines[i] = cxt->allocated_line;
|
||||
}
|
||||
|
||||
cxt->hlen++;
|
||||
|
||||
/* The line where we start the search. */
|
||||
cxt->history_pos = cxt->save_line;
|
||||
|
||||
rl_save_prompt ();
|
||||
|
||||
/* Initialize search parameters. */
|
||||
cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
|
||||
cxt->search_string[cxt->search_string_index = 0] = '\0';
|
||||
|
||||
/* Normalize DIRECTION into 1 or -1. */
|
||||
cxt->direction = (direction >= 0) ? 1 : -1;
|
||||
|
||||
cxt->sline = rl_line_buffer;
|
||||
cxt->sline_len = strlen (cxt->sline);
|
||||
cxt->sline_index = rl_point;
|
||||
|
||||
_rl_iscxt = cxt; /* save globally */
|
||||
|
||||
return cxt;
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_isearch_fini (cxt)
|
||||
_rl_search_cxt *cxt;
|
||||
{
|
||||
/* First put back the original state. */
|
||||
strcpy (rl_line_buffer, cxt->lines[cxt->save_line]);
|
||||
|
||||
rl_restore_prompt ();
|
||||
|
||||
/* Save the search string for possible later use. */
|
||||
FREE (last_isearch_string);
|
||||
last_isearch_string = cxt->search_string;
|
||||
last_isearch_string_len = cxt->search_string_index;
|
||||
cxt->search_string = 0;
|
||||
|
||||
if (cxt->last_found_line < cxt->save_line)
|
||||
rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
|
||||
else
|
||||
rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
|
||||
|
||||
/* If the string was not found, put point at the end of the last matching
|
||||
line. If last_found_line == orig_line, we didn't find any matching
|
||||
history lines at all, so put point back in its original position. */
|
||||
if (cxt->sline_index < 0)
|
||||
{
|
||||
if (cxt->last_found_line == cxt->save_line)
|
||||
cxt->sline_index = cxt->save_point;
|
||||
else
|
||||
cxt->sline_index = strlen (rl_line_buffer);
|
||||
rl_mark = cxt->save_mark;
|
||||
}
|
||||
|
||||
rl_point = cxt->sline_index;
|
||||
/* Don't worry about where to put the mark here; rl_get_previous_history
|
||||
and rl_get_next_history take care of it. */
|
||||
|
||||
rl_clear_message ();
|
||||
}
|
||||
|
||||
int
|
||||
_rl_search_getchar (cxt)
|
||||
_rl_search_cxt *cxt;
|
||||
{
|
||||
int c;
|
||||
|
||||
/* Read a key and decide how to proceed. */
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
c = cxt->lastc = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* This ends up with C (and LASTC) being set to the last byte of the
|
||||
multibyte character. In most cases c == lastc == mb[0] */
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
|
||||
#endif
|
||||
|
||||
RL_CHECK_SIGNALS ();
|
||||
return c;
|
||||
}
|
||||
|
||||
#define ENDSRCH_CHAR(c) \
|
||||
((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
|
||||
|
||||
/* Process just-read character C according to isearch context CXT. Return
|
||||
-1 if the caller should just free the context and return, 0 if we should
|
||||
break out of the loop, and 1 if we should continue to read characters. */
|
||||
int
|
||||
_rl_isearch_dispatch (cxt, c)
|
||||
_rl_search_cxt *cxt;
|
||||
int c;
|
||||
{
|
||||
int n, wstart, wlen, limit, cval;
|
||||
rl_command_func_t *f;
|
||||
|
||||
f = (rl_command_func_t *)NULL;
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
cxt->sflags |= SF_FAILED;
|
||||
cxt->history_pos = cxt->last_found_line;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we are moving into a new keymap, modify cxt->keymap and go on.
|
||||
This can be a problem if c == ESC and we want to terminate the
|
||||
incremental search, so we check */
|
||||
if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
|
||||
{
|
||||
/* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
|
||||
takes microseconds, so multiply by 1000. If we don't get any
|
||||
additional input and we this keymap shadows another function, process
|
||||
that key as if it was all we read. */
|
||||
if (_rl_keyseq_timeout > 0 &&
|
||||
RL_ISSTATE (RL_STATE_CALLBACK) == 0 &&
|
||||
RL_ISSTATE (RL_STATE_INPUTPENDING) == 0 &&
|
||||
_rl_pushed_input_available () == 0 &&
|
||||
((Keymap)(cxt->keymap[c].function))[ANYOTHERKEY].function &&
|
||||
_rl_input_queued (_rl_keyseq_timeout*1000) == 0)
|
||||
goto add_character;
|
||||
|
||||
cxt->okeymap = cxt->keymap;
|
||||
cxt->keymap = FUNCTION_TO_KEYMAP (cxt->keymap, c);
|
||||
cxt->sflags |= SF_CHGKMAP;
|
||||
/* XXX - we should probably save this sequence, so we can do
|
||||
something useful if this doesn't end up mapping to a command we
|
||||
interpret here. Right now we just save the most recent character
|
||||
that caused the index into a new keymap. */
|
||||
cxt->prevc = c;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
if (cxt->mb[1] == 0)
|
||||
{
|
||||
cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
|
||||
cxt->pmb[1] = '\0';
|
||||
}
|
||||
else
|
||||
memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
add_character:
|
||||
|
||||
/* Translate the keys we do something with to opcodes. */
|
||||
if (c >= 0 && cxt->keymap[c].type == ISFUNC)
|
||||
{
|
||||
f = cxt->keymap[c].function;
|
||||
|
||||
if (f == rl_reverse_search_history)
|
||||
cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
|
||||
else if (f == rl_forward_search_history)
|
||||
cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
|
||||
else if (f == rl_rubout)
|
||||
cxt->lastc = -3;
|
||||
else if (c == CTRL ('G') || f == rl_abort)
|
||||
cxt->lastc = -4;
|
||||
else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
|
||||
cxt->lastc = -5;
|
||||
else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
|
||||
cxt->lastc = -6;
|
||||
}
|
||||
|
||||
/* If we changed the keymap earlier while translating a key sequence into
|
||||
a command, restore it now that we've succeeded. */
|
||||
if (cxt->sflags & SF_CHGKMAP)
|
||||
{
|
||||
cxt->keymap = cxt->okeymap;
|
||||
cxt->sflags &= ~SF_CHGKMAP;
|
||||
/* If we indexed into a new keymap, but didn't map to a command that
|
||||
affects the search (lastc > 0), and the character that mapped to a
|
||||
new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
|
||||
handle that now as if the previous char would have ended the search
|
||||
and we would have read the current character. */
|
||||
/* XXX - should we check cxt->mb? */
|
||||
if (cxt->lastc > 0 && ENDSRCH_CHAR (cxt->prevc))
|
||||
{
|
||||
rl_stuff_char (cxt->lastc);
|
||||
rl_execute_next (cxt->prevc);
|
||||
/* XXX - do we insert everything in cxt->pmb? */
|
||||
return (0);
|
||||
}
|
||||
/* Otherwise, if the current character is mapped to self-insert or
|
||||
nothing (i.e., not an editing command), and the previous character
|
||||
was a keymap index, then we need to insert both the previous
|
||||
character and the current character into the search string. */
|
||||
else if (cxt->lastc > 0 && cxt->prevc > 0 &&
|
||||
cxt->keymap[cxt->prevc].type == ISKMAP &&
|
||||
(f == 0 || f == rl_insert))
|
||||
{
|
||||
/* Make lastc be the next character read */
|
||||
/* XXX - do we insert everything in cxt->mb? */
|
||||
rl_execute_next (cxt->lastc);
|
||||
/* Dispatch on the previous character (insert into search string) */
|
||||
cxt->lastc = cxt->prevc;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
/* Have to overwrite cxt->mb here because dispatch uses it below */
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
if (cxt->pmb[1] == 0)
|
||||
{
|
||||
cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
|
||||
cxt->mb[1] = '\0';
|
||||
}
|
||||
else
|
||||
memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
|
||||
}
|
||||
#endif
|
||||
cxt->prevc = 0;
|
||||
}
|
||||
else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
|
||||
{
|
||||
rl_stuff_char (cxt->lastc);
|
||||
rl_execute_next (cxt->prevc);
|
||||
/* XXX - do we insert everything in cxt->pmb? */
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* The characters in isearch_terminators (set from the user-settable
|
||||
variable isearch-terminators) are used to terminate the search but
|
||||
not subsequently execute the character as a command. The default
|
||||
value is "\033\012" (ESC and C-J). */
|
||||
if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
|
||||
{
|
||||
/* ESC still terminates the search, but if there is pending
|
||||
input or if input arrives within 0.1 seconds (on systems
|
||||
with select(2)) it is used as a prefix character
|
||||
with rl_execute_next. WATCH OUT FOR THIS! This is intended
|
||||
to allow the arrow keys to be used like ^F and ^B are used
|
||||
to terminate the search and execute the movement command.
|
||||
XXX - since _rl_input_available depends on the application-
|
||||
settable keyboard timeout value, this could alternatively
|
||||
use _rl_input_queued(100000) */
|
||||
if (cxt->lastc == ESC && _rl_input_available ())
|
||||
rl_execute_next (ESC);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
|
||||
{
|
||||
/* This sets rl_pending_input to LASTC; it will be picked up the next
|
||||
time rl_read_key is called. */
|
||||
rl_execute_next (cxt->lastc);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
|
||||
{
|
||||
/* This sets rl_pending_input to LASTC; it will be picked up the next
|
||||
time rl_read_key is called. */
|
||||
rl_execute_next (cxt->lastc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Now dispatch on the character. `Opcodes' affect the search string or
|
||||
state. Other characters are added to the string. */
|
||||
switch (cxt->lastc)
|
||||
{
|
||||
/* search again */
|
||||
case -1:
|
||||
if (cxt->search_string_index == 0)
|
||||
{
|
||||
if (last_isearch_string)
|
||||
{
|
||||
cxt->search_string_size = 64 + last_isearch_string_len;
|
||||
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
|
||||
strcpy (cxt->search_string, last_isearch_string);
|
||||
cxt->search_string_index = last_isearch_string_len;
|
||||
rl_display_search (cxt->search_string, cxt->sflags, -1);
|
||||
break;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
else if (cxt->sflags & SF_REVERSE)
|
||||
cxt->sline_index--;
|
||||
else if (cxt->sline_index != cxt->sline_len)
|
||||
cxt->sline_index++;
|
||||
else
|
||||
rl_ding ();
|
||||
break;
|
||||
|
||||
/* switch directions */
|
||||
case -2:
|
||||
cxt->direction = -cxt->direction;
|
||||
if (cxt->direction < 0)
|
||||
cxt->sflags |= SF_REVERSE;
|
||||
else
|
||||
cxt->sflags &= ~SF_REVERSE;
|
||||
break;
|
||||
|
||||
/* delete character from search string. */
|
||||
case -3: /* C-H, DEL */
|
||||
/* This is tricky. To do this right, we need to keep a
|
||||
stack of search positions for the current search, with
|
||||
sentinels marking the beginning and end. But this will
|
||||
do until we have a real isearch-undo. */
|
||||
if (cxt->search_string_index == 0)
|
||||
rl_ding ();
|
||||
else
|
||||
cxt->search_string[--cxt->search_string_index] = '\0';
|
||||
break;
|
||||
|
||||
case -4: /* C-G, abort */
|
||||
rl_replace_line (cxt->lines[cxt->save_line], 0);
|
||||
rl_point = cxt->save_point;
|
||||
rl_mark = cxt->save_mark;
|
||||
rl_restore_prompt();
|
||||
rl_clear_message ();
|
||||
|
||||
return -1;
|
||||
|
||||
case -5: /* C-W */
|
||||
/* skip over portion of line we already matched and yank word */
|
||||
wstart = rl_point + cxt->search_string_index;
|
||||
if (wstart >= rl_end)
|
||||
{
|
||||
rl_ding ();
|
||||
break;
|
||||
}
|
||||
|
||||
/* if not in a word, move to one. */
|
||||
cval = _rl_char_value (rl_line_buffer, wstart);
|
||||
if (_rl_walphabetic (cval) == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
break;
|
||||
}
|
||||
n = MB_NEXTCHAR (rl_line_buffer, wstart, 1, MB_FIND_NONZERO);;
|
||||
while (n < rl_end)
|
||||
{
|
||||
cval = _rl_char_value (rl_line_buffer, n);
|
||||
if (_rl_walphabetic (cval) == 0)
|
||||
break;
|
||||
n = MB_NEXTCHAR (rl_line_buffer, n, 1, MB_FIND_NONZERO);;
|
||||
}
|
||||
wlen = n - wstart + 1;
|
||||
if (cxt->search_string_index + wlen + 1 >= cxt->search_string_size)
|
||||
{
|
||||
cxt->search_string_size += wlen + 1;
|
||||
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
|
||||
}
|
||||
for (; wstart < n; wstart++)
|
||||
cxt->search_string[cxt->search_string_index++] = rl_line_buffer[wstart];
|
||||
cxt->search_string[cxt->search_string_index] = '\0';
|
||||
break;
|
||||
|
||||
case -6: /* C-Y */
|
||||
/* skip over portion of line we already matched and yank rest */
|
||||
wstart = rl_point + cxt->search_string_index;
|
||||
if (wstart >= rl_end)
|
||||
{
|
||||
rl_ding ();
|
||||
break;
|
||||
}
|
||||
n = rl_end - wstart + 1;
|
||||
if (cxt->search_string_index + n + 1 >= cxt->search_string_size)
|
||||
{
|
||||
cxt->search_string_size += n + 1;
|
||||
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
|
||||
}
|
||||
for (n = wstart; n < rl_end; n++)
|
||||
cxt->search_string[cxt->search_string_index++] = rl_line_buffer[n];
|
||||
cxt->search_string[cxt->search_string_index] = '\0';
|
||||
break;
|
||||
|
||||
/* Add character to search string and continue search. */
|
||||
default:
|
||||
if (cxt->search_string_index + 2 >= cxt->search_string_size)
|
||||
{
|
||||
cxt->search_string_size += 128;
|
||||
cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
|
||||
}
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
{
|
||||
int j, l;
|
||||
|
||||
if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
|
||||
else
|
||||
for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
|
||||
cxt->search_string[cxt->search_string_index] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
|
||||
{
|
||||
limit = cxt->sline_len - cxt->search_string_index + 1;
|
||||
|
||||
/* Search the current line. */
|
||||
while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
|
||||
{
|
||||
if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
|
||||
{
|
||||
cxt->sflags |= SF_FOUND;
|
||||
break;
|
||||
}
|
||||
else
|
||||
cxt->sline_index += cxt->direction;
|
||||
}
|
||||
if (cxt->sflags & SF_FOUND)
|
||||
break;
|
||||
|
||||
/* Move to the next line, but skip new copies of the line
|
||||
we just found and lines shorter than the string we're
|
||||
searching for. */
|
||||
do
|
||||
{
|
||||
/* Move to the next line. */
|
||||
cxt->history_pos += cxt->direction;
|
||||
|
||||
/* At limit for direction? */
|
||||
if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
|
||||
{
|
||||
cxt->sflags |= SF_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We will need these later. */
|
||||
cxt->sline = cxt->lines[cxt->history_pos];
|
||||
cxt->sline_len = strlen (cxt->sline);
|
||||
}
|
||||
while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
|
||||
(cxt->search_string_index > cxt->sline_len));
|
||||
|
||||
if (cxt->sflags & SF_FAILED)
|
||||
break;
|
||||
|
||||
/* Now set up the line for searching... */
|
||||
cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
|
||||
}
|
||||
|
||||
if (cxt->sflags & SF_FAILED)
|
||||
{
|
||||
/* We cannot find the search string. Ding the bell. */
|
||||
rl_ding ();
|
||||
cxt->history_pos = cxt->last_found_line;
|
||||
rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We have found the search string. Just display it. But don't
|
||||
actually move there in the history list until the user accepts
|
||||
the location. */
|
||||
if (cxt->sflags & SF_FOUND)
|
||||
{
|
||||
cxt->prev_line_found = cxt->lines[cxt->history_pos];
|
||||
rl_replace_line (cxt->lines[cxt->history_pos], 0);
|
||||
rl_point = cxt->sline_index;
|
||||
cxt->last_found_line = cxt->history_pos;
|
||||
rl_display_search (cxt->search_string, cxt->sflags, (cxt->history_pos == cxt->save_line) ? -1 : cxt->history_pos);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_isearch_cleanup (cxt, r)
|
||||
_rl_search_cxt *cxt;
|
||||
int r;
|
||||
{
|
||||
if (r >= 0)
|
||||
_rl_isearch_fini (cxt);
|
||||
_rl_scxt_dispose (cxt, 0);
|
||||
_rl_iscxt = 0;
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_ISEARCH);
|
||||
|
||||
return (r != 0);
|
||||
}
|
||||
|
||||
/* Search through the history looking for an interactively typed string.
|
||||
This is analogous to i-search. We start the search in the current line.
|
||||
DIRECTION is which direction to search; >= 0 means forward, < 0 means
|
||||
backwards. */
|
||||
static int
|
||||
rl_search_history (direction, invoking_key)
|
||||
int direction, invoking_key;
|
||||
{
|
||||
_rl_search_cxt *cxt; /* local for now, but saved globally */
|
||||
int c, r;
|
||||
|
||||
RL_SETSTATE(RL_STATE_ISEARCH);
|
||||
cxt = _rl_isearch_init (direction);
|
||||
|
||||
rl_display_search (cxt->search_string, cxt->sflags, -1);
|
||||
|
||||
/* If we are using the callback interface, all we do is set up here and
|
||||
return. The key is that we leave RL_STATE_ISEARCH set. */
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
return (0);
|
||||
|
||||
r = -1;
|
||||
for (;;)
|
||||
{
|
||||
c = _rl_search_getchar (cxt);
|
||||
/* We might want to handle EOF here (c == 0) */
|
||||
r = _rl_isearch_dispatch (cxt, cxt->lastc);
|
||||
if (r <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* The searching is over. The user may have found the string that she
|
||||
was looking for, or else she may have exited a failing search. If
|
||||
LINE_INDEX is -1, then that shows that the string searched for was
|
||||
not found. We use this to determine where to place rl_point. */
|
||||
return (_rl_isearch_cleanup (cxt, r));
|
||||
}
|
||||
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
/* Called from the callback functions when we are ready to read a key. The
|
||||
callback functions know to call this because RL_ISSTATE(RL_STATE_ISEARCH).
|
||||
If _rl_isearch_dispatch finishes searching, this function is responsible
|
||||
for turning off RL_STATE_ISEARCH, which it does using _rl_isearch_cleanup. */
|
||||
int
|
||||
_rl_isearch_callback (cxt)
|
||||
_rl_search_cxt *cxt;
|
||||
{
|
||||
int c, r;
|
||||
|
||||
c = _rl_search_getchar (cxt);
|
||||
/* We might want to handle EOF here */
|
||||
r = _rl_isearch_dispatch (cxt, cxt->lastc);
|
||||
|
||||
return (r <= 0) ? _rl_isearch_cleanup (cxt, r) : 0;
|
||||
}
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
/* readline.c -- a general facility for reading lines of input
|
||||
with emacs style editing and completion. */
|
||||
|
||||
/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library (Readline), a library
|
||||
for reading lines of text with interactive input and history editing.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -380,6 +380,11 @@ dump_word_flags (flags)
|
||||
f &= ~W_ASSNGLOBAL;
|
||||
fprintf (stderr, "W_ASSNGLOBAL%s", f ? "|" : "");
|
||||
}
|
||||
if (f & W_ASSIGNINT)
|
||||
{
|
||||
f &= ~W_ASSIGNINT;
|
||||
fprintf (stderr, "W_ASSIGNINT%s", f ? "|" : "");
|
||||
}
|
||||
if (f & W_COMPASSIGN)
|
||||
{
|
||||
f &= ~W_COMPASSIGN;
|
||||
@@ -9430,17 +9435,38 @@ shell_expand_word_list (tlist, eflags)
|
||||
if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
|
||||
{
|
||||
int t;
|
||||
char opts[8], opti;
|
||||
|
||||
opti = 0;
|
||||
if (tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL|W_ASSIGNARRAY))
|
||||
opts[opti++] = '-';
|
||||
|
||||
if ((tlist->word->flags & (W_ASSIGNASSOC|W_ASSNGLOBAL)) == (W_ASSIGNASSOC|W_ASSNGLOBAL))
|
||||
make_internal_declare (tlist->word->word, "-gA");
|
||||
{
|
||||
opts[opti++] = 'g';
|
||||
opts[opti++] = 'A';
|
||||
}
|
||||
else if (tlist->word->flags & W_ASSIGNASSOC)
|
||||
make_internal_declare (tlist->word->word, "-A");
|
||||
opts[opti++] = 'A';
|
||||
else if ((tlist->word->flags & (W_ASSIGNARRAY|W_ASSNGLOBAL)) == (W_ASSIGNARRAY|W_ASSNGLOBAL))
|
||||
make_internal_declare (tlist->word->word, "-ga");
|
||||
{
|
||||
opts[opti++] = 'g';
|
||||
opts[opti++] = 'a';
|
||||
}
|
||||
else if (tlist->word->flags & W_ASSIGNARRAY)
|
||||
make_internal_declare (tlist->word->word, "-a");
|
||||
opts[opti++] = 'a';
|
||||
else if (tlist->word->flags & W_ASSNGLOBAL)
|
||||
make_internal_declare (tlist->word->word, "-g");
|
||||
opts[opti++] = 'g';
|
||||
|
||||
#if 0
|
||||
/* If we have special handling note the integer attribute */
|
||||
if (opti > 0 && (tlist->word->flags & W_ASSIGNINT))
|
||||
opts[opti++] = 'i';
|
||||
#endif
|
||||
|
||||
opts[opti] = '\0';
|
||||
if (opti > 0)
|
||||
make_internal_declare (tlist->word->word, opts);
|
||||
|
||||
t = do_word_assignment (tlist->word, 0);
|
||||
if (t == 0)
|
||||
|
||||
+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
|
||||
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
BUILD_DIR=/usr/local/build/chet/bash/bash-current
|
||||
THIS_SH=$BUILD_DIR/bash
|
||||
PATH=$PATH:$BUILD_DIR
|
||||
|
||||
export THIS_SH PATH
|
||||
|
||||
rm -f /tmp/xx
|
||||
|
||||
/bin/sh "$@"
|
||||
@@ -375,3 +375,6 @@ declare -a x='([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5foo")'
|
||||
declare -a x='([0]="0" [1]="1" [2]="2" [3]="3" [4]="4" [5]="5")'
|
||||
declare -a x='([0]="0" [1]="1" [2]="2" [3]="3" [4]="4four" [5]="5")'
|
||||
strlen(4four) = 5
|
||||
1 2 0 3
|
||||
1 2 0 3
|
||||
1 2 0 3
|
||||
|
||||
@@ -396,3 +396,5 @@ ${THIS_SH} ./array12.sub
|
||||
${THIS_SH} ./array13.sub
|
||||
|
||||
${THIS_SH} ./array14.sub
|
||||
|
||||
${THIS_SH} ./array15.sub
|
||||
|
||||
@@ -0,0 +1,398 @@
|
||||
# this is needed so that the bad assignments (b[]=bcde, for example) do not
|
||||
# cause fatal shell errors when in posix mode
|
||||
set +o posix
|
||||
|
||||
set +a
|
||||
# The calls to egrep -v are to filter out builtin array variables that are
|
||||
# automatically set and possibly contain values that vary.
|
||||
|
||||
# first make sure we handle the basics
|
||||
x=()
|
||||
echo ${x[@]}
|
||||
unset x
|
||||
|
||||
# this should be an error
|
||||
test=(first & second)
|
||||
echo $?
|
||||
unset test
|
||||
|
||||
# make sure declare -a converts an existing variable to an array
|
||||
unset a
|
||||
a=abcde
|
||||
declare -a a
|
||||
echo ${a[0]}
|
||||
|
||||
unset a
|
||||
a=abcde
|
||||
a[2]=bdef
|
||||
|
||||
unset b
|
||||
declare -a b[256]
|
||||
|
||||
unset c[2]
|
||||
unset c[*]
|
||||
|
||||
a[1]=
|
||||
|
||||
_ENV=/bin/true
|
||||
x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]}
|
||||
|
||||
declare -r c[100]
|
||||
|
||||
echo ${a[0]} ${a[4]}
|
||||
echo ${a[@]}
|
||||
|
||||
echo ${a[*]}
|
||||
|
||||
# this should print out values, too
|
||||
declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)'
|
||||
|
||||
unset a[7]
|
||||
echo ${a[*]}
|
||||
|
||||
unset a[4]
|
||||
echo ${a[*]}
|
||||
|
||||
echo ${a}
|
||||
echo "${a}"
|
||||
echo $a
|
||||
|
||||
unset a[0]
|
||||
echo ${a}
|
||||
|
||||
echo ${a[@]}
|
||||
|
||||
a[5]="hello world"
|
||||
echo ${a[5]}
|
||||
echo ${#a[5]}
|
||||
|
||||
echo ${#a[@]}
|
||||
|
||||
a[4+5/2]="test expression"
|
||||
declare a["7 + 8"]="test 2"
|
||||
a[7 + 8]="test 2"
|
||||
echo ${a[@]}
|
||||
|
||||
readonly a[5]
|
||||
readonly a
|
||||
# these two lines should output `declare' commands
|
||||
readonly -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)'
|
||||
declare -ar | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)'
|
||||
# this line should output `readonly' commands, even for arrays
|
||||
set -o posix
|
||||
readonly -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)'
|
||||
set +o posix
|
||||
|
||||
declare -a d='([1]="" [2]="bdef" [5]="hello world" "test")'
|
||||
d[9]="ninth element"
|
||||
|
||||
declare -a e[10]=test # this works in post-bash-2.05 versions
|
||||
declare -a e[10]='(test)'
|
||||
|
||||
pass=/etc/passwd
|
||||
declare -a f='("${d[@]}")'
|
||||
b=([0]=this [1]=is [2]=a [3]=test [4]="$PS1" [5]=$pass)
|
||||
|
||||
echo ${b[@]:2:3}
|
||||
|
||||
declare -pa | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)'
|
||||
|
||||
a[3]="this is a test"
|
||||
|
||||
b[]=bcde
|
||||
b[*]=aaa
|
||||
echo ${b[ ]}
|
||||
|
||||
c[-2]=4
|
||||
echo ${c[-4]}
|
||||
|
||||
d[7]=(abdedfegeee)
|
||||
|
||||
d=([]=abcde [1]="test test" [*]=last [-65]=negative )
|
||||
|
||||
unset d[12]
|
||||
unset e[*]
|
||||
|
||||
declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)'
|
||||
|
||||
ps1='hello'
|
||||
unset ps1[2]
|
||||
unset ${ps1[2]}
|
||||
|
||||
declare +a ps1
|
||||
declare +a c
|
||||
|
||||
# the prompt should not print when using a here doc
|
||||
read -p "array test: " -a rv <<!
|
||||
this is a test of read using arrays
|
||||
!
|
||||
|
||||
echo ${rv[0]} ${rv[4]}
|
||||
echo ${rv[@]}
|
||||
|
||||
# the variable should be converted to an array when `read -a' is done
|
||||
vv=1
|
||||
read -a vv <<!
|
||||
this is a test of arrays
|
||||
!
|
||||
echo ${vv[0]} ${vv[3]}
|
||||
echo ${vv[@]}
|
||||
unset vv
|
||||
|
||||
declare -a | egrep -v '(BASH_VERSINFO|PIPESTATUS|GROUPS)'
|
||||
|
||||
export rv
|
||||
#set
|
||||
|
||||
x[4]=bbb
|
||||
x=abde
|
||||
echo $x
|
||||
echo ${x[0]}
|
||||
echo ${x[4]}
|
||||
echo efgh | ( read x[1] ; echo ${x[1]} )
|
||||
echo wxyz | ( declare -a x ; read x ; echo $x ; echo ${x[0]} )
|
||||
|
||||
# Make sure that arrays can be used to save the positional paramters verbatim
|
||||
set -- a 'b c' d 'e f g' h
|
||||
|
||||
ARGV=( [0]=$0 "$@" )
|
||||
|
||||
for z in "${ARGV[@]}"
|
||||
do
|
||||
echo "$z"
|
||||
done
|
||||
|
||||
echo "$0"
|
||||
for z in "$@"
|
||||
do
|
||||
echo "$z"
|
||||
done
|
||||
|
||||
# do various pattern removal and length tests
|
||||
XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin
|
||||
|
||||
xpath=( $( IFS=: ; echo $XPATH ) )
|
||||
|
||||
echo ${xpath[@]}
|
||||
echo ${xpath[@]##*/}
|
||||
echo ${xpath[0]##*/}
|
||||
echo ${xpath[@]%%[!/]*}
|
||||
echo ${xpath[0]%%[!/]*}
|
||||
recho ${xpath##*/}
|
||||
recho ${xpath%%[!/]*}
|
||||
recho ${xpath[5]##*/}
|
||||
recho ${xpath[5]%%[!/]*}
|
||||
|
||||
# let's try to make it a DOS-style path
|
||||
|
||||
zecho "${xpath[@]/\//\\}"
|
||||
zecho "${xpath[@]//\//\\}"
|
||||
zecho "${xpath[@]//[\/]/\\}"
|
||||
|
||||
# length of the first element of the array, since array without subscript
|
||||
# is equivalent to referencing first element
|
||||
echo ${#xpath} -- ${#xpath[0]}
|
||||
|
||||
# number of elements in the array
|
||||
nelem=${#xpath[@]}
|
||||
echo ${#xpath[@]} -- $nelem
|
||||
|
||||
# total length of all elements in the array, including space separators
|
||||
xx="${xpath[*]}"
|
||||
echo ${#xx}
|
||||
|
||||
# total length of all elements in the array
|
||||
xx=$( IFS='' ; echo "${xpath[*]}" )
|
||||
echo ${#xx}
|
||||
|
||||
unset xpath[nelem-1]
|
||||
|
||||
nelem=${#xpath[@]}
|
||||
echo ${#xpath[@]} -- $nelem
|
||||
|
||||
# arrays and things that look like index assignments
|
||||
array=(42 [1]=14 [2]=44)
|
||||
|
||||
array2=(grep [ 123 ] \*)
|
||||
|
||||
echo ${array[@]}
|
||||
echo "${array2[@]}"
|
||||
|
||||
# arrays and implicit arithmetic evaluation
|
||||
declare -i -a iarray
|
||||
|
||||
iarray=( 2+4 1+6 7+2 )
|
||||
echo ${iarray[@]}
|
||||
|
||||
iarray[4]=4+1
|
||||
echo ${iarray[@]}
|
||||
|
||||
# make sure assignment using the compound assignment syntax removes all
|
||||
# of the old elements from the array value
|
||||
barray=(old1 old2 old3 old4 old5)
|
||||
barray=(new1 new2 new3)
|
||||
echo "length = ${#barray[@]}"
|
||||
echo "value = ${barray[*]}"
|
||||
|
||||
# make sure the array code behaves correctly with respect to unset variables
|
||||
set -u
|
||||
( echo ${#narray[4]} )
|
||||
|
||||
${THIS_SH} ./array1.sub
|
||||
${THIS_SH} ./array2.sub
|
||||
|
||||
# some old bugs and ksh93 compatibility tests
|
||||
${THIS_SH} ./array3.sub
|
||||
|
||||
# some compound assingment parsing problems that showed up in bash-3.1-release
|
||||
${THIS_SH} ./array4.sub
|
||||
|
||||
set +u
|
||||
cd /tmp
|
||||
|
||||
touch 1=bar
|
||||
foo=([10]="bar")
|
||||
echo ${foo[0]}
|
||||
rm 1=bar
|
||||
|
||||
cd $OLDPWD
|
||||
|
||||
foo=(a b c d e f g)
|
||||
echo ${foo[@]}
|
||||
|
||||
# quoted reserved words are ok
|
||||
foo=(\for \case \if \then \else)
|
||||
echo ${foo[@]}
|
||||
|
||||
# quoted metacharacters are ok
|
||||
foo=( [1]='<>' [2]='<' [3]='>' [4]='!' )
|
||||
echo ${foo[@]}
|
||||
|
||||
# numbers are just words when not in a redirection context
|
||||
foo=( 12 14 16 18 20 )
|
||||
echo ${foo[@]}
|
||||
|
||||
foo=( 4414758999202 )
|
||||
echo ${foo[@]}
|
||||
|
||||
# this was a bug in all versions of bash 2.x up to and including bash-2.04
|
||||
declare -a ddd=(aaa
|
||||
bbb)
|
||||
echo ${ddd[@]}
|
||||
|
||||
# errors until post-bash-2.05a; now reserved words are OK
|
||||
foo=(a b c for case if then else)
|
||||
|
||||
foo=(for case if then else)
|
||||
|
||||
# errors
|
||||
metas=( <> < > ! )
|
||||
metas=( [1]=<> [2]=< [3]=> [4]=! )
|
||||
|
||||
# various expansions that didn't really work right until post-bash-2.04
|
||||
foo='abc'
|
||||
echo ${foo[0]} ${#foo[0]}
|
||||
echo ${foo[1]} ${#foo[1]}
|
||||
echo ${foo[@]} ${#foo[@]}
|
||||
echo ${foo[*]} ${#foo[*]}
|
||||
|
||||
foo=''
|
||||
echo ${foo[0]} ${#foo[0]}
|
||||
echo ${foo[1]} ${#foo[1]}
|
||||
echo ${foo[@]} ${#foo[@]}
|
||||
echo ${foo[*]} ${#foo[*]}
|
||||
|
||||
# new expansions added after bash-2.05b
|
||||
x[0]=zero
|
||||
x[1]=one
|
||||
x[4]=four
|
||||
x[10]=ten
|
||||
|
||||
recho ${!x[@]}
|
||||
recho "${!x[@]}"
|
||||
recho ${!x[*]}
|
||||
recho "${!x[*]}"
|
||||
|
||||
# sparse array tests for code fixed in bash-3.0
|
||||
unset av
|
||||
av[1]='one'
|
||||
av[2]=''
|
||||
|
||||
av[3]=three
|
||||
av[5]=five
|
||||
av[7]=seven
|
||||
|
||||
echo include null element -- expect one
|
||||
echo ${av[@]:1:2} # what happens when we include a null element?
|
||||
echo include unset element -- expect three five
|
||||
echo ${av[@]:3:2} # what happens when we include an unset element?
|
||||
echo start at unset element -- expect five seven
|
||||
echo ${av[@]:4:2} # what happens when we start at an unset element?
|
||||
|
||||
echo too many elements -- expect three five seven
|
||||
echo ${av[@]:3:5} # how about too many elements?
|
||||
|
||||
echo positive offset - expect five seven
|
||||
echo ${av[@]:5:2}
|
||||
echo negative offset to unset element - expect seven
|
||||
echo ${av[@]: -2:2}
|
||||
|
||||
echo positive offset 2 - expect seven
|
||||
echo ${av[@]: 6:2}
|
||||
echo negative offset 2 - expect seven
|
||||
echo ${av[@]: -1:2}
|
||||
|
||||
echo out-of-range offset
|
||||
echo ${av[@]:12}
|
||||
|
||||
# parsing problems and other inconsistencies not fixed until post bash-3.0
|
||||
unset x
|
||||
declare -a x=(')' $$)
|
||||
[ ${x[1]} -eq $$ ] || echo bad
|
||||
|
||||
unset x
|
||||
declare -a x=(a b c d e)
|
||||
echo ${x[4]}
|
||||
|
||||
z=([1]=one [4]=four [7]=seven [10]=ten)
|
||||
|
||||
echo ${#z[@]}
|
||||
|
||||
echo ${!z[@]}
|
||||
|
||||
unset x
|
||||
declare -a x=(a \'b c\')
|
||||
|
||||
echo "${x[1]}"
|
||||
|
||||
unset x
|
||||
declare -a x=(a 'b c')
|
||||
|
||||
echo "${x[1]}"
|
||||
|
||||
unset x
|
||||
declare -a x=($0)
|
||||
[ "${x[@]}" = $0 ] || echo double expansion of \$0
|
||||
declare -a x=(\$0)
|
||||
echo "${x[@]}"
|
||||
|
||||
# tests for bash-3.1 problems
|
||||
${THIS_SH} ./array5.sub
|
||||
|
||||
# tests for post-bash-3.2 problems, most fixed in bash-3.2 patches
|
||||
${THIS_SH} ./array6.sub
|
||||
${THIS_SH} ./array7.sub
|
||||
|
||||
${THIS_SH} ./array8.sub
|
||||
|
||||
${THIS_SH} ./array9.sub
|
||||
|
||||
${THIS_SH} ./array10.sub
|
||||
|
||||
${THIS_SH} ./array11.sub
|
||||
|
||||
${THIS_SH} ./array12.sub
|
||||
|
||||
${THIS_SH} ./array13.sub
|
||||
|
||||
${THIS_SH} ./array14.sub
|
||||
@@ -0,0 +1,24 @@
|
||||
# fixes for make_internal_declare not handling integer attribute for arrays
|
||||
declare -ai -g foo=(1 2 xx 3)
|
||||
echo "${foo[@]}"
|
||||
|
||||
unset foo
|
||||
declare -ai -g foo='(1 2 xx 3)'
|
||||
echo "${foo[@]}"
|
||||
|
||||
unset foo
|
||||
declare -ia -g foo=(1 2 xx 3)
|
||||
echo "${foo[@]}"
|
||||
|
||||
unset foo
|
||||
declare -ia -g foo='(1 2 xx 3)'
|
||||
echo "${foo[@]}"
|
||||
|
||||
unset foo
|
||||
func()
|
||||
{
|
||||
declare -ai -g foo=(1 2 xx 3)
|
||||
}
|
||||
|
||||
func
|
||||
echo "${foo[@]}"
|
||||
@@ -0,0 +1,22 @@
|
||||
# fixes for make_internal_declare not handling integer attribute for arrays
|
||||
declare -ai -g foo=(1 2 xx 3)
|
||||
echo "${foo[@]}"
|
||||
|
||||
declare -ai -g foo='(1 2 xx 3)'
|
||||
echo "${foo[@]}"
|
||||
|
||||
unset foo
|
||||
declare -ia -g foo=(1 2 xx 3)
|
||||
echo "${foo[@]}"
|
||||
|
||||
declare -ia -g foo='(1 2 xx 3)'
|
||||
echo "${foo[@]}"
|
||||
|
||||
unset foo
|
||||
func()
|
||||
{
|
||||
declare -ai -g foo=(1 2 xx 3)
|
||||
}
|
||||
|
||||
func
|
||||
echo "${foo[@]}"
|
||||
@@ -93,16 +93,6 @@ sleep 2
|
||||
wait $!
|
||||
exit
|
||||
in trap EXIT
|
||||
works
|
||||
bar
|
||||
bar
|
||||
foo
|
||||
trap -- '' SIGINT
|
||||
trap -- '' SIGUSR2
|
||||
foo
|
||||
bar
|
||||
foo
|
||||
bar
|
||||
caught a child death
|
||||
caught a child death
|
||||
caught a child death
|
||||
|
||||
+2
-1
@@ -70,7 +70,8 @@ ${THIS_SH} ./trap3.sub
|
||||
|
||||
${THIS_SH} ./trap4.sub
|
||||
|
||||
${THIS_SH} ./trap5.sub
|
||||
# This doesn't work right on all Unix versions
|
||||
#${THIS_SH} ./trap5.sub
|
||||
|
||||
#
|
||||
# show that setting a trap on SIGCHLD is not disastrous.
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# test the trap code
|
||||
|
||||
trap 'echo exiting' 0
|
||||
trap 'echo aborting' 1 2 3 6 15
|
||||
|
||||
# make sure a user-specified subshell runs the exit trap, but does not
|
||||
# inherit the exit trap from a parent shell
|
||||
( trap 'echo subshell exit' 0; exit 0 )
|
||||
( exit 0 )
|
||||
|
||||
trap
|
||||
|
||||
func()
|
||||
{
|
||||
trap 'echo ${FUNCNAME:-$0}[$LINENO] funcdebug' DEBUG
|
||||
echo funcdebug line
|
||||
}
|
||||
|
||||
trap 'echo [$LINENO] debug' DEBUG
|
||||
echo debug line
|
||||
|
||||
trap
|
||||
|
||||
func
|
||||
|
||||
trap
|
||||
|
||||
trap 'echo ${FUNCNAME:-$0}[$LINENO] debug' DEBUG
|
||||
func2()
|
||||
{
|
||||
echo func2debug line
|
||||
}
|
||||
declare -ft func2
|
||||
func2
|
||||
|
||||
unset -f func2
|
||||
|
||||
trap '' DEBUG
|
||||
|
||||
trap
|
||||
|
||||
trap - debug
|
||||
|
||||
trap
|
||||
|
||||
trap - HUP
|
||||
trap hup
|
||||
trap '' INT
|
||||
trap '' int
|
||||
|
||||
trap
|
||||
|
||||
# exit 0 in exit trap should set exit status
|
||||
(
|
||||
set -e
|
||||
trap 'exit 0' EXIT
|
||||
false
|
||||
echo bad
|
||||
)
|
||||
echo $?
|
||||
|
||||
# hmmm...should this set the handling to SIG_IGN for children, too?
|
||||
trap '' USR2
|
||||
./trap1.sub
|
||||
|
||||
# test ERR trap
|
||||
./trap2.sub
|
||||
|
||||
${THIS_SH} ./trap3.sub
|
||||
|
||||
${THIS_SH} ./trap4.sub
|
||||
|
||||
${THIS_SH} ./trap5.sub
|
||||
|
||||
#
|
||||
# show that setting a trap on SIGCHLD is not disastrous.
|
||||
#
|
||||
set -o monitor
|
||||
|
||||
trap 'echo caught a child death' SIGCHLD
|
||||
|
||||
sleep 7 & sleep 6 & sleep 5 &
|
||||
|
||||
# this will only catch the first, since there's a trap on SIGCHLD
|
||||
wait
|
||||
|
||||
trap -p SIGCHLD
|
||||
|
||||
# Now reset some of the signals the shell handles specially back to
|
||||
# their default values (with or without the SIG prefix)
|
||||
trap - SIGINT QUIT TERM
|
||||
|
||||
trap
|
||||
|
||||
trap - SIGCHLD
|
||||
wait
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
# make sure process substitution runs the exit trap
|
||||
[[ -n $(< <(trap "tee /dev/fd/3" EXIT)) ]] 3>&1 <<<works || echo "fail :("
|
||||
[[ -n $(< <(trap "cat /dev/fd/0" EXIT)) ]] <<<works && echo works || echo "fail :("
|
||||
|
||||
read foo < <(trap "echo bar" EXIT)
|
||||
echo $foo
|
||||
|
||||
Reference in New Issue
Block a user