mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
commit bash-20051222 snapshot
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
This document details the incompatibilites between this version of bash,
|
||||
bash-3.1, and a previous widely-available version, bash-1.14 (which
|
||||
is still the `standard' version for a few Linux distributions). These
|
||||
were discovered by users of bash-2.x and 3.x, so this list is not
|
||||
comprehensive. Some of these incompatibilities occur between the current
|
||||
version and versions 2.0 and above. (The differences between bash-1.14
|
||||
and bash-2.0 were significant.)
|
||||
This document details the incompatibilities between this version of bash,
|
||||
bash-3.1, and the previous widely-available versions, bash-1.14 (which is
|
||||
still the `standard' version for a few Linux distributions) and bash-2.x.
|
||||
These were discovered by users of bash-2.x and 3.x, so this list is not
|
||||
comprehensive. Some of these incompatibilities occur between the current
|
||||
version and versions 2.0 and above. (The differences between bash-1.14 and
|
||||
bash-2.0 were significant.)
|
||||
|
||||
1. Bash uses a new quoting syntax, $"...", to do locale-specific
|
||||
string translation. Users who have relied on the (undocumented)
|
||||
@@ -184,42 +184,73 @@ and bash-2.0 were significant.)
|
||||
with `z' and still allow individual users to change the collation order.
|
||||
Users may put the above command into their own profiles as well, of course.
|
||||
|
||||
14. Bash versions up to 1.14.7 included an undocumented `-l' operator to
|
||||
the `test/[' builtin. It was a unary operator that expanded to the
|
||||
length of its string argument. This let you do things like
|
||||
14. Bash versions up to 1.14.7 included an undocumented `-l' operator to
|
||||
the `test/[' builtin. It was a unary operator that expanded to the
|
||||
length of its string argument. This let you do things like
|
||||
|
||||
test -l $variable -lt 20
|
||||
|
||||
for example.
|
||||
for example.
|
||||
|
||||
This was included for backwards compatibility with old versions of the
|
||||
Bourne shell, which did not provide an easy way to obtain the length of
|
||||
the value of a shell variable.
|
||||
This was included for backwards compatibility with old versions of the
|
||||
Bourne shell, which did not provide an easy way to obtain the length of
|
||||
the value of a shell variable.
|
||||
|
||||
This operator is not part of the POSIX standard, because one can (and
|
||||
should) use ${#variable} to get the length of a variable's value.
|
||||
Bash-2.x does not support it.
|
||||
This operator is not part of the POSIX standard, because one can (and
|
||||
should) use ${#variable} to get the length of a variable's value.
|
||||
Bash-2.x does not support it.
|
||||
|
||||
15. Bash no longer auto-exports the HOME, PATH, SHELL, TERM, HOSTNAME,
|
||||
HOSTTYPE, MACHTYPE, or OSTYPE variables.
|
||||
15. Bash no longer auto-exports the HOME, PATH, SHELL, TERM, HOSTNAME,
|
||||
HOSTTYPE, MACHTYPE, or OSTYPE variables.
|
||||
|
||||
16. Bash no longer initializes the FUNCNAME, GROUPS, or DIRSTACK variables
|
||||
to have special behavior if they appear in the initial environment.
|
||||
16. Bash no longer initializes the FUNCNAME, GROUPS, or DIRSTACK variables
|
||||
to have special behavior if they appear in the initial environment.
|
||||
|
||||
17. Bash no longer removes the export attribute from the SSH_CLIENT or
|
||||
SSH2_CLIENT variables, and no longer attempts to discover whether or
|
||||
not it has been invoked by sshd in order to run the startup files.
|
||||
17. Bash no longer removes the export attribute from the SSH_CLIENT or
|
||||
SSH2_CLIENT variables, and no longer attempts to discover whether or
|
||||
not it has been invoked by sshd in order to run the startup files.
|
||||
|
||||
18. Bash no longer requires that the body of a function be a group command;
|
||||
any compound command is accepted.
|
||||
18. Bash no longer requires that the body of a function be a group command;
|
||||
any compound command is accepted.
|
||||
|
||||
19. As of bash-3.0, the pattern substitution operators no longer perform
|
||||
quote removal on the pattern before attempting the match. This is the
|
||||
way the pattern removal functions behave, and is more consistent.
|
||||
19. As of bash-3.0, the pattern substitution operators no longer perform
|
||||
quote removal on the pattern before attempting the match. This is the
|
||||
way the pattern removal functions behave, and is more consistent.
|
||||
|
||||
20. After bash-3.0 was released, I reimplemented tilde expansion, incorporating
|
||||
it into the mainline word expansion code. This fixes the bug that caused
|
||||
the results of tilde expansion to be re-expanded. There is one
|
||||
incompatibility: a ${paramOPword} expansion within double quotes will not
|
||||
perform tilde expansion on WORD. This is consistent with the other
|
||||
expansions, and what POSIX specifies.
|
||||
20. After bash-3.0 was released, I reimplemented tilde expansion, incorporating
|
||||
it into the mainline word expansion code. This fixes the bug that caused
|
||||
the results of tilde expansion to be re-expanded. There is one
|
||||
incompatibility: a ${paramOPword} expansion within double quotes will not
|
||||
perform tilde expansion on WORD. This is consistent with the other
|
||||
expansions, and what POSIX specifies.
|
||||
|
||||
21. A number of variables have the integer attribute by default, so the +=
|
||||
assignment operator returns expected results: RANDOM, LINENO, MAILCHECK,
|
||||
HISTCMD, OPTIND.
|
||||
|
||||
22. Bash-3.x is much stricter about $LINENO correctly reflecting the line
|
||||
number in a script; assignments to LINENO have little effect.
|
||||
|
||||
23. By default, readline binds the terminal special characters to their
|
||||
readline equivalents. As of bash-3.1/readline-5.1, this is optional and
|
||||
controlled by the bind-tty-special-chars readline variable.
|
||||
|
||||
24. The \W prompt string expansion abbreviates $HOME as `~'. The previous
|
||||
behavior is available with ${PWD##/*/}.
|
||||
|
||||
25. The arithmetic exponentiation operator is right-associative as of bash-3.1.
|
||||
|
||||
26. The rules concerning valid alias names are stricter, as per POSIX.2.
|
||||
|
||||
27. The Readline key binding functions now obey the convert-meta setting active
|
||||
when the binding takes place, as the dispatch code does when characters
|
||||
are read and processed.
|
||||
|
||||
28. The historical behavior of `trap' reverting signal disposition to the
|
||||
original handling in the absence of a valid first argument is implemented
|
||||
only if the first argument is a valid signal number.
|
||||
|
||||
29. In versions of bash after 3.1, the ${parameter//pattern/replacement}
|
||||
expansion does not interpret `%' or `#' specially. Those anchors don't
|
||||
have any real meaning when replacing every match.
|
||||
|
||||
|
||||
@@ -0,0 +1,225 @@
|
||||
This document details the incompatibilities between this version of bash,
|
||||
bash-3.1, and a previous widely-available version, bash-1.14 (which
|
||||
is still the `standard' version for a few Linux distributions). These
|
||||
were discovered by users of bash-2.x and 3.x, so this list is not
|
||||
comprehensive. Some of these incompatibilities occur between the current
|
||||
version and versions 2.0 and above. (The differences between bash-1.14
|
||||
and bash-2.0 were significant.)
|
||||
|
||||
1. Bash uses a new quoting syntax, $"...", to do locale-specific
|
||||
string translation. Users who have relied on the (undocumented)
|
||||
behavior of bash-1.14 will have to change their scripts. For
|
||||
instance, if you are doing something like this to get the value of
|
||||
a variable whose name is the value of a second variable:
|
||||
|
||||
eval var2=$"$var1"
|
||||
|
||||
you will have to change to a different syntax.
|
||||
|
||||
This capability is directly supported by bash-2.0:
|
||||
|
||||
var2=${!var1}
|
||||
|
||||
This alternate syntax will work portably between bash-1.14 and bash-2.0:
|
||||
|
||||
eval var2=\$${var1}
|
||||
|
||||
2. One of the bugs fixed in the YACC grammar tightens up the rules
|
||||
concerning group commands ( {...} ). The `list' that composes the
|
||||
body of the group command must be terminated by a newline or
|
||||
semicolon. That's because the braces are reserved words, and are
|
||||
recognized as such only when a reserved word is legal. This means
|
||||
that while bash-1.14 accepted shell function definitions like this:
|
||||
|
||||
foo() { : }
|
||||
|
||||
bash-2.0 requires this:
|
||||
|
||||
foo() { :; }
|
||||
|
||||
This is also an issue for commands like this:
|
||||
|
||||
mkdir dir || { echo 'could not mkdir' ; exit 1; }
|
||||
|
||||
The syntax required by bash-2.0 is also accepted by bash-1.14.
|
||||
|
||||
3. The options to `bind' have changed to make them more consistent with
|
||||
the rest of the bash builtins. If you are using `bind -d' to list
|
||||
the readline key bindings in a form that can be re-read, use `bind -p'
|
||||
instead. If you were using `bind -v' to list the key bindings, use
|
||||
`bind -P' instead.
|
||||
|
||||
4. The `long' invocation options must now be prefixed by `--' instead
|
||||
of `-'. (The old form is still accepted, for the time being.)
|
||||
|
||||
5. There was a bug in the version of readline distributed with bash-1.14
|
||||
that caused it to write badly-formatted key bindings when using
|
||||
`bind -d'. The only key sequences that were affected are C-\ (which
|
||||
should appear as \C-\\ in a key binding) and C-" (which should appear
|
||||
as \C-\"). If these key sequences appear in your inputrc, as, for
|
||||
example,
|
||||
|
||||
"\C-\": self-insert
|
||||
|
||||
they will need to be changed to something like the following:
|
||||
|
||||
"\C-\\": self-insert
|
||||
|
||||
6. A number of people complained about having to use ESC to terminate an
|
||||
incremental search, and asked for an alternate mechanism. Bash-2.03
|
||||
uses the value of the settable readline variable `isearch-terminators'
|
||||
to decide which characters should terminate an incremental search. If
|
||||
that variable has not been set, ESC and Control-J will terminate a
|
||||
search.
|
||||
|
||||
7. Some variables have been removed: MAIL_WARNING, notify, history_control,
|
||||
command_oriented_history, glob_dot_filenames, allow_null_glob_expansion,
|
||||
nolinks, hostname_completion_file, noclobber, no_exit_on_failed_exec, and
|
||||
cdable_vars. Most of them are now implemented with the new `shopt'
|
||||
builtin; others were already implemented by `set'. Here is a list of
|
||||
correspondences:
|
||||
|
||||
MAIL_WARNING shopt mailwarn
|
||||
notify set -o notify
|
||||
history_control HISTCONTROL
|
||||
command_oriented_history shopt cmdhist
|
||||
glob_dot_filenames shopt dotglob
|
||||
allow_null_glob_expansion shopt nullglob
|
||||
nolinks set -o physical
|
||||
hostname_completion_file HOSTFILE
|
||||
noclobber set -o noclobber
|
||||
no_exit_on_failed_exec shopt execfail
|
||||
cdable_vars shopt cdable_vars
|
||||
|
||||
8. `ulimit' now sets both hard and soft limits and reports the soft limit
|
||||
by default (when neither -H nor -S is specified). This is compatible
|
||||
with versions of sh and ksh that implement `ulimit'. The bash-1.14
|
||||
behavior of, for example,
|
||||
|
||||
ulimit -c 0
|
||||
|
||||
can be obtained with
|
||||
|
||||
ulimit -S -c 0
|
||||
|
||||
It may be useful to define an alias:
|
||||
|
||||
alias ulimit="ulimit -S"
|
||||
|
||||
9. Bash-2.01 uses a new quoting syntax, $'...' to do ANSI-C string
|
||||
translation. Backslash-escaped characters in ... are expanded and
|
||||
replaced as specified by the ANSI C standard.
|
||||
|
||||
10. The sourcing of startup files has changed somewhat. This is explained
|
||||
more completely in the INVOCATION section of the manual page.
|
||||
|
||||
A non-interactive shell not named `sh' and not in posix mode reads
|
||||
and executes commands from the file named by $BASH_ENV. A
|
||||
non-interactive shell started by `su' and not in posix mode will read
|
||||
startup files. No other non-interactive shells read any startup files.
|
||||
|
||||
An interactive shell started in posix mode reads and executes commands
|
||||
from the file named by $ENV.
|
||||
|
||||
11. The <> redirection operator was changed to conform to the POSIX.2 spec.
|
||||
In the absence of any file descriptor specification preceding the `<>',
|
||||
file descriptor 0 is used. In bash-1.14, this was the behavior only
|
||||
when in POSIX mode. The bash-1.14 behavior may be obtained with
|
||||
|
||||
<>filename 1>&0
|
||||
|
||||
12. The `alias' builtin now checks for invalid options and takes a `-p'
|
||||
option to display output in POSIX mode. If you have old aliases beginning
|
||||
with `-' or `+', you will have to add the `--' to the alias command
|
||||
that declares them:
|
||||
|
||||
alias -x='chmod a-x' --> alias -- -x='chmod a-x'
|
||||
|
||||
13. The behavior of range specificiers within bracket matching expressions
|
||||
in the pattern matcher (e.g., [A-Z]) depends on the current locale,
|
||||
specifically the value of the LC_COLLATE environment variable. Setting
|
||||
this variable to C or POSIX will result in the traditional ASCII behavior
|
||||
for range comparisons. If the locale is set to something else, e.g.,
|
||||
en_US (specified by the LANG or LC_ALL variables), collation order is
|
||||
locale-dependent. For example, the en_US locale sorts the upper and
|
||||
lower case letters like this:
|
||||
|
||||
AaBb...Zz
|
||||
|
||||
so a range specification like [A-Z] will match every letter except `z'.
|
||||
Other locales collate like
|
||||
|
||||
aAbBcC...zZ
|
||||
|
||||
which means that [A-Z] matches every letter except `a'.
|
||||
|
||||
The portable way to specify upper case letters is [:upper:] instead of
|
||||
A-Z; lower case may be specified as [:lower:] instead of a-z.
|
||||
|
||||
Look at the manual pages for setlocale(3), strcoll(3), and, if it is
|
||||
present, locale(1).
|
||||
|
||||
You can find your current locale information by running locale(1):
|
||||
|
||||
caleb.ins.cwru.edu(2)$ locale
|
||||
LANG=en_US
|
||||
LC_CTYPE="en_US"
|
||||
LC_NUMERIC="en_US"
|
||||
LC_TIME="en_US"
|
||||
LC_COLLATE="en_US"
|
||||
LC_MONETARY="en_US"
|
||||
LC_MESSAGES="en_US"
|
||||
LC_ALL=en_US
|
||||
|
||||
My advice is to put
|
||||
|
||||
export LC_COLLATE=C
|
||||
|
||||
into /etc/profile and inspect any shell scripts run from cron for
|
||||
constructs like [A-Z]. This will prevent things like
|
||||
|
||||
rm [A-Z]*
|
||||
|
||||
from removing every file in the current directory except those beginning
|
||||
with `z' and still allow individual users to change the collation order.
|
||||
Users may put the above command into their own profiles as well, of course.
|
||||
|
||||
14. Bash versions up to 1.14.7 included an undocumented `-l' operator to
|
||||
the `test/[' builtin. It was a unary operator that expanded to the
|
||||
length of its string argument. This let you do things like
|
||||
|
||||
test -l $variable -lt 20
|
||||
|
||||
for example.
|
||||
|
||||
This was included for backwards compatibility with old versions of the
|
||||
Bourne shell, which did not provide an easy way to obtain the length of
|
||||
the value of a shell variable.
|
||||
|
||||
This operator is not part of the POSIX standard, because one can (and
|
||||
should) use ${#variable} to get the length of a variable's value.
|
||||
Bash-2.x does not support it.
|
||||
|
||||
15. Bash no longer auto-exports the HOME, PATH, SHELL, TERM, HOSTNAME,
|
||||
HOSTTYPE, MACHTYPE, or OSTYPE variables.
|
||||
|
||||
16. Bash no longer initializes the FUNCNAME, GROUPS, or DIRSTACK variables
|
||||
to have special behavior if they appear in the initial environment.
|
||||
|
||||
17. Bash no longer removes the export attribute from the SSH_CLIENT or
|
||||
SSH2_CLIENT variables, and no longer attempts to discover whether or
|
||||
not it has been invoked by sshd in order to run the startup files.
|
||||
|
||||
18. Bash no longer requires that the body of a function be a group command;
|
||||
any compound command is accepted.
|
||||
|
||||
19. As of bash-3.0, the pattern substitution operators no longer perform
|
||||
quote removal on the pattern before attempting the match. This is the
|
||||
way the pattern removal functions behave, and is more consistent.
|
||||
|
||||
20. After bash-3.0 was released, I reimplemented tilde expansion, incorporating
|
||||
it into the mainline word expansion code. This fixes the bug that caused
|
||||
the results of tilde expansion to be re-expanded. There is one
|
||||
incompatibility: a ${paramOPword} expansion within double quotes will not
|
||||
perform tilde expansion on WORD. This is consistent with the other
|
||||
expansions, and what POSIX specifies.
|
||||
+158
@@ -12552,3 +12552,161 @@ parse.y
|
||||
- use CTLESC instead of literal '\001' when decode_prompt_string
|
||||
prefixes RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE
|
||||
|
||||
12/20
|
||||
-----
|
||||
lib/readline/display.c
|
||||
- don't treat RL_PROMPT_START_IGNORE specially inside a sequence of
|
||||
ignored characters
|
||||
- keep track of the start of the current sequence of ignored
|
||||
characters; make sure that an empty sequence of such characters
|
||||
really is an empty sequence, not one that happens to end with '\001'
|
||||
(RL_PROMPT_START_IGNORE)
|
||||
|
||||
12/21
|
||||
-----
|
||||
subst.c
|
||||
- change expand_word_internal to process rest of `tilde-word' as a
|
||||
regular part of the word if tilde expansion leaves the tilde-word
|
||||
unchanged. This means that ~$USER expands to ~chet, which seems
|
||||
more intuitive, and is effectively what bash-3.0 did
|
||||
|
||||
12/23
|
||||
-----
|
||||
subst.c
|
||||
- when making a local array variable in do_compound_assignment, make
|
||||
sure that we don't use a variable of the same name from a previous
|
||||
context
|
||||
|
||||
doc/bash.1
|
||||
- documented expansions for word and patterns in case statement
|
||||
|
||||
builtins/ulimit.def,doc/{bashref.texi,bash.1}
|
||||
- added new -e and -r (nice and rtprio) options to ulimit; documented
|
||||
them
|
||||
|
||||
12/26
|
||||
-----
|
||||
variables.c
|
||||
- use `hmax' instead of `num' in sv_histsize to avoid integer overflow
|
||||
problems with intmax_t
|
||||
|
||||
builtins/read.def
|
||||
- add unwind-protect to restore rl_attempted_completion_function in
|
||||
case of a timeout
|
||||
|
||||
{bashline,variables}.c
|
||||
- move initialization of HISTSIZE from initialization path to
|
||||
load_history, so it can be overridden by a value assigned in a
|
||||
startup file
|
||||
|
||||
lib/readline/misc.c
|
||||
- add a missing `return r' so that rl_digit_loop returns a meaningful
|
||||
value
|
||||
|
||||
lib/readline/{bind,callback,display,isearch,rltty,search,text,vi_mode}.c
|
||||
- minor cleanups to satisfy compiler warnings, mostly removing unused
|
||||
variables
|
||||
|
||||
12/27
|
||||
-----
|
||||
support/Makefile.in
|
||||
- add LIBS_FOR_BUILD support; defaults to ${LIBS}
|
||||
|
||||
Makefile.in
|
||||
- add LIBS_FOR_BUILD with no default value; use when linking programs
|
||||
using CC_FOR_BUILD (e.g., bashversion)
|
||||
|
||||
12/28
|
||||
-----
|
||||
lib/readline/bind.c
|
||||
- fix rl_translate_keyseq bad translation of \M-\C-x sequences
|
||||
|
||||
execute_cmd.c
|
||||
- in execute_arith_command, if the expression expands to more than one
|
||||
word, make sure we join the words into a single string and pass the
|
||||
entire thing to evalexp()
|
||||
|
||||
expr.c
|
||||
- new functions: _is_arithop(c), returns true if C is a valid single-
|
||||
character arithmetic operator; _is_multiop(c), returns true if C is
|
||||
a token corresponding to a valid multi-character arithmetic operator
|
||||
- if we encounter a character that isn't a valid arithmetic
|
||||
operator, throw an error. Try to be intelligent about what type of
|
||||
error message to print
|
||||
|
||||
subst.c
|
||||
- new function, expand_arith_string, calls expand_string_if_necessary;
|
||||
used where an arithmetic expression needs to be expanded
|
||||
|
||||
subst.h
|
||||
- new extern declaration for expand_arith_string
|
||||
|
||||
arrayfunc.c
|
||||
- in array_expand_index, call expand_arith_string to expand the
|
||||
subscript in a fashion consistent with other arithmetic expressions
|
||||
|
||||
subst.c
|
||||
- fix parameter_brace_patsub so that we don't try to anchor the pattern
|
||||
at the beginning or end of the string if we're doing global
|
||||
replacement -- that combination doesn't doesn't make sense, and
|
||||
the changed behavior is compatible with ksh93
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- changed description of pattern substitution to match the new
|
||||
semantics
|
||||
|
||||
tests/new-exp.tests
|
||||
- change tests to remove all ${pat//#rep} and ${pat//%rep}
|
||||
expansions, since they don't mean the same thing anymore
|
||||
|
||||
12/29
|
||||
-----
|
||||
support/signames.c
|
||||
- new file, initialize_signames() function from old mksignames.c. This
|
||||
file builds the signal_names array
|
||||
|
||||
support/mksignames.c
|
||||
- strip out initialize_signames(), move to signames.c. This file only
|
||||
writes signames.h
|
||||
- set up to only write a stub signames.h if CROSS_COMPILING is defined,
|
||||
with extern declaration for initialize_signames
|
||||
- if not cross compiling, #define initialize_signames to nothing
|
||||
|
||||
Makefile.in
|
||||
- mksignames is now linked from mksignames.o and buildsignames.o
|
||||
- add rules to build signames.o, assuming we're building it as part
|
||||
of the shell (cross-compiling)
|
||||
|
||||
trap.c
|
||||
- call initialize_signames from initialize_traps
|
||||
|
||||
configure.in
|
||||
- set SIGNAMES_O to nothing (normal) or signames.o (cross-compiling),
|
||||
substitute into Makefile
|
||||
- don't set SIGNAMES_H if cross-compiling any more
|
||||
|
||||
12/30
|
||||
-----
|
||||
command.h
|
||||
- new word flag: W_NOPROCSUB, inhibits process substitution on a word
|
||||
|
||||
subst.c
|
||||
- change expand_word_internal to suppress process substitution if the
|
||||
word has the W_NOPROCSUB flag
|
||||
|
||||
shell.c
|
||||
- --wordexp turns on W_NOPROCSUB in addition to W_NOCOMSUB
|
||||
|
||||
subst.c
|
||||
- change string_list_dollar_at and string_list_dollar_star so that
|
||||
MB_CUR_MAX is used to size an array only when using gcc, since gcc
|
||||
can handle non-constant array sizes using a mechanism like alloca.
|
||||
Other compilers, e.g. Sun's compiler, do not implement that
|
||||
extension
|
||||
|
||||
12/31
|
||||
-----
|
||||
builtins/mkbuiltins.c
|
||||
- when cross-compiling, don't include <config.h>, since it's for the
|
||||
target rather than the host system. Instead, choose a reasonable
|
||||
set of default #defines based on a minimal POSIX system
|
||||
|
||||
@@ -12545,3 +12545,161 @@ config.h.in
|
||||
config-bot.h
|
||||
- add HAVE_WCTYPE to the set of checks for HANDLE_MULTIBYTE. This
|
||||
should catch the deficient NetBSD multibyte support
|
||||
|
||||
12/16
|
||||
-----
|
||||
parse.y
|
||||
- use CTLESC instead of literal '\001' when decode_prompt_string
|
||||
prefixes RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE
|
||||
|
||||
12/20
|
||||
-----
|
||||
lib/readline/display.c
|
||||
- don't treat RL_PROMPT_START_IGNORE specially inside a sequence of
|
||||
ignored characters
|
||||
- keep track of the start of the current sequence of ignored
|
||||
characters; make sure that an empty sequence of such characters
|
||||
really is an empty sequence, not one that happens to end with '\001'
|
||||
(RL_PROMPT_START_IGNORE)
|
||||
|
||||
12/21
|
||||
-----
|
||||
subst.c
|
||||
- change expand_word_internal to process rest of `tilde-word' as a
|
||||
regular part of the word if tilde expansion leaves the tilde-word
|
||||
unchanged. This means that ~$USER expands to ~chet, which seems
|
||||
more intuitive, and is effectively what bash-3.0 did
|
||||
|
||||
12/23
|
||||
-----
|
||||
subst.c
|
||||
- when making a local array variable in do_compound_assignment, make
|
||||
sure that we don't use a variable of the same name from a previous
|
||||
context
|
||||
|
||||
doc/bash.1
|
||||
- documented expansions for word and patterns in case statement
|
||||
|
||||
builtins/ulimit.def,doc/{bashref.texi,bash.1}
|
||||
- added new -e and -r (nice and rtprio) options to ulimit; documented
|
||||
them
|
||||
|
||||
12/26
|
||||
-----
|
||||
variables.c
|
||||
- use `hmax' instead of `num' in sv_histsize to avoid integer overflow
|
||||
problems with intmax_t
|
||||
|
||||
builtins/read.def
|
||||
- add unwind-protect to restore rl_attempted_completion_function in
|
||||
case of a timeout
|
||||
|
||||
{bashline,variables}.c
|
||||
- move initialization of HISTSIZE from initialization path to
|
||||
load_history, so it can be overridden by a value assigned in a
|
||||
startup file
|
||||
|
||||
lib/readline/misc.c
|
||||
- add a missing `return r' so that rl_digit_loop returns a meaningful
|
||||
value
|
||||
|
||||
lib/readline/{bind,callback,display,isearch,rltty,search,text,vi_mode}.c
|
||||
- minor cleanups to satisfy compiler warnings, mostly removing unused
|
||||
variables
|
||||
|
||||
12/27
|
||||
-----
|
||||
support/Makefile.in
|
||||
- add LIBS_FOR_BUILD support; defaults to ${LIBS}
|
||||
|
||||
Makefile.in
|
||||
- add LIBS_FOR_BUILD with no default value; use when linking programs
|
||||
using CC_FOR_BUILD (e.g., bashversion)
|
||||
|
||||
12/28
|
||||
-----
|
||||
lib/readline/bind.c
|
||||
- fix rl_translate_keyseq bad translation of \M-\C-x sequences
|
||||
|
||||
execute_cmd.c
|
||||
- in execute_arith_command, if the expression expands to more than one
|
||||
word, make sure we join the words into a single string and pass the
|
||||
entire thing to evalexp()
|
||||
|
||||
expr.c
|
||||
- new functions: _is_arithop(c), returns true if C is a valid single-
|
||||
character arithmetic operator; _is_multiop(c), returns true if C is
|
||||
a token corresponding to a valid multi-character arithmetic operator
|
||||
- if we encounter a character that isn't a valid arithmetic
|
||||
operator, throw an error. Try to be intelligent about what type of
|
||||
error message to print
|
||||
|
||||
subst.c
|
||||
- new function, expand_arith_string, calls expand_string_if_necessary;
|
||||
used where an arithmetic expression needs to be expanded
|
||||
|
||||
subst.h
|
||||
- new extern declaration for expand_arith_string
|
||||
|
||||
arrayfunc.c
|
||||
- in array_expand_index, call expand_arith_string to expand the
|
||||
subscript in a fashion consistent with other arithmetic expressions
|
||||
|
||||
subst.c
|
||||
- fix parameter_brace_patsub so that we don't try to anchor the pattern
|
||||
at the beginning or end of the string if we're doing global
|
||||
replacement -- that combination doesn't doesn't make sense, and
|
||||
the changed behavior is compatible with ksh93
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- changed description of pattern substitution to match the new
|
||||
semantics
|
||||
|
||||
tests/new-exp.tests
|
||||
- change tests to remove all ${pat//#rep} and ${pat//%rep}
|
||||
expansions, since they don't mean the same thing anymore
|
||||
|
||||
12/29
|
||||
-----
|
||||
support/signames.c
|
||||
- new file, initialize_signames() function from old mksignames.c. This
|
||||
file builds the signal_names array
|
||||
|
||||
support/mksignames.c
|
||||
- strip out initialize_signames(), move to signames.c. This file only
|
||||
writes signames.h
|
||||
- set up to only write a stub signames.h if CROSS_COMPILING is defined,
|
||||
with extern declaration for initialize_signames
|
||||
- if not cross compiling, #define initialize_signames to nothing
|
||||
|
||||
Makefile.in
|
||||
- mksignames is now linked from mksignames.o and buildsignames.o
|
||||
- add rules to build signames.o, assuming we're building it as part
|
||||
of the shell (cross-compiling)
|
||||
|
||||
trap.c
|
||||
- call initialize_signames from initialize_traps
|
||||
|
||||
configure.in
|
||||
- set SIGNAMES_O to nothing (normal) or signames.o (cross-compiling),
|
||||
substitute into Makefile
|
||||
- don't set SIGNAMES_H if cross-compiling any more
|
||||
|
||||
12/30
|
||||
-----
|
||||
command.h
|
||||
- new word flag: W_NOPROCSUB, inhibits process substitution on a word
|
||||
|
||||
subst.c
|
||||
- change expand_word_internal to suppress process substitution if the
|
||||
word has the W_NOPROCSUB flag
|
||||
|
||||
shell.c
|
||||
- --wordexp turns on W_NOPROCSUB in addition to W_NOCOMSUB
|
||||
|
||||
subst.c
|
||||
- change string_list_dollar_at and string_list_dollar_star so that
|
||||
MB_CUR_MAX is used to size an array only when using gcc, since gcc
|
||||
can handle non-constant array sizes using a mechanism like alloca.
|
||||
Other compilers, e.g. Sun's compiler, do not implement that
|
||||
extension
|
||||
|
||||
@@ -203,9 +203,7 @@ builtins/bashgetopt.c f
|
||||
builtins/common.h f
|
||||
builtins/bashgetopt.h f
|
||||
cross-build/cygwin32.cache f
|
||||
cross-build/win32sig.h f
|
||||
cross-build/x86-beos.cache f
|
||||
cross-build/beos-sig.h f
|
||||
cross-build/opennt.cache f
|
||||
include/ansi_stdlib.h f
|
||||
include/chartypes.h f
|
||||
@@ -514,6 +512,7 @@ support/mkdirs f 755
|
||||
support/mkinstalldirs f 755
|
||||
support/mkversion.sh f 755
|
||||
support/mksignames.c f
|
||||
support/signames.c f
|
||||
support/bashbug.sh f
|
||||
support/man2html.c f
|
||||
support/recho.c f
|
||||
|
||||
@@ -0,0 +1,984 @@
|
||||
#
|
||||
# Master distribution manifest for bash
|
||||
#
|
||||
#
|
||||
# Filename type
|
||||
#
|
||||
CWRU d
|
||||
CWRU/misc d
|
||||
builtins d
|
||||
cross-build d
|
||||
doc d
|
||||
examples d
|
||||
examples/bashdb d
|
||||
examples/obashdb d
|
||||
examples/complete d
|
||||
examples/functions d
|
||||
examples/scripts d
|
||||
examples/scripts.v2 d
|
||||
examples/scripts.noah d
|
||||
examples/startup-files d
|
||||
examples/startup-files/apple d
|
||||
examples/misc d
|
||||
examples/loadables d
|
||||
examples/loadables/perl d
|
||||
include d
|
||||
lib d
|
||||
lib/glob d
|
||||
lib/glob/doc d
|
||||
lib/intl d
|
||||
lib/malloc d
|
||||
lib/readline d
|
||||
lib/readline/doc d
|
||||
lib/readline/examples d
|
||||
lib/sh d
|
||||
lib/termcap d
|
||||
lib/termcap/grot d
|
||||
lib/tilde d
|
||||
po d
|
||||
support d
|
||||
tests d
|
||||
tests/misc d
|
||||
ABOUT-NLS f
|
||||
CHANGES f
|
||||
COMPAT f
|
||||
COPYING f
|
||||
INSTALL f
|
||||
MANIFEST f
|
||||
NEWS f
|
||||
NOTES f
|
||||
POSIX f
|
||||
README f
|
||||
RBASH f
|
||||
AUTHORS f
|
||||
Y2K f
|
||||
configure.in f
|
||||
configure f
|
||||
Makefile.in f
|
||||
config-top.h f
|
||||
config-bot.h f
|
||||
config.h.in f
|
||||
aclocal.m4 f
|
||||
array.c f
|
||||
arrayfunc.c f
|
||||
eval.c f
|
||||
print_cmd.c f
|
||||
general.c f
|
||||
list.c f
|
||||
locale.c f
|
||||
stringlib.c f
|
||||
variables.c f
|
||||
make_cmd.c f
|
||||
copy_cmd.c f
|
||||
unwind_prot.c f
|
||||
dispose_cmd.c f
|
||||
bashhist.c f
|
||||
hashcmd.c f
|
||||
hashlib.c f
|
||||
parse.y f
|
||||
pathexp.c f
|
||||
subst.c f
|
||||
shell.c f
|
||||
trap.c f
|
||||
sig.c f
|
||||
siglist.c f
|
||||
version.c f
|
||||
flags.c f
|
||||
jobs.c f
|
||||
input.c f
|
||||
mailcheck.c f
|
||||
test.c f
|
||||
expr.c f
|
||||
alias.c f
|
||||
execute_cmd.c f
|
||||
findcmd.c f
|
||||
redir.c f
|
||||
bashline.c f
|
||||
braces.c f
|
||||
bracecomp.c f
|
||||
nojobs.c f
|
||||
error.c f
|
||||
xmalloc.c f
|
||||
pcomplete.c f
|
||||
pcomplib.c f
|
||||
mksyntax.c f
|
||||
alias.h f
|
||||
builtins.h f
|
||||
bashhist.h f
|
||||
bashline.h f
|
||||
conftypes.h f
|
||||
patchlevel.h f
|
||||
variables.h f
|
||||
array.h f
|
||||
arrayfunc.h f
|
||||
jobs.h f
|
||||
findcmd.h f
|
||||
hashlib.h f
|
||||
quit.h f
|
||||
flags.h f
|
||||
shell.h f
|
||||
syntax.h f
|
||||
pathexp.h f
|
||||
parser.h f
|
||||
pcomplete.h f
|
||||
sig.h f
|
||||
test.h f
|
||||
trap.h f
|
||||
general.h f
|
||||
unwind_prot.h f
|
||||
input.h f
|
||||
error.h f
|
||||
command.h f
|
||||
externs.h f
|
||||
siglist.h f
|
||||
subst.h f
|
||||
dispose_cmd.h f
|
||||
hashcmd.h f
|
||||
bashansi.h f
|
||||
bashjmp.h f
|
||||
bashintl.h f
|
||||
make_cmd.h f
|
||||
execute_cmd.h f
|
||||
redir.h f
|
||||
bashtypes.h f
|
||||
mailcheck.h f
|
||||
xmalloc.h f
|
||||
y.tab.c f
|
||||
y.tab.h f
|
||||
parser-built f
|
||||
pathnames.h.in f
|
||||
builtins/Makefile.in f
|
||||
builtins/alias.def f
|
||||
builtins/bind.def f
|
||||
builtins/break.def f
|
||||
builtins/builtin.def f
|
||||
builtins/caller.def f
|
||||
builtins/cd.def f
|
||||
builtins/colon.def f
|
||||
builtins/command.def f
|
||||
builtins/complete.def f
|
||||
builtins/common.c f
|
||||
builtins/declare.def f
|
||||
builtins/echo.def f
|
||||
builtins/enable.def f
|
||||
builtins/eval.def f
|
||||
builtins/evalfile.c f
|
||||
builtins/evalstring.c f
|
||||
builtins/exec.def f
|
||||
builtins/exit.def f
|
||||
builtins/fc.def f
|
||||
builtins/fg_bg.def f
|
||||
builtins/getopt.c f
|
||||
builtins/getopt.h f
|
||||
builtins/getopts.def f
|
||||
builtins/hash.def f
|
||||
builtins/help.def f
|
||||
builtins/let.def f
|
||||
builtins/history.def f
|
||||
builtins/jobs.def f
|
||||
builtins/kill.def f
|
||||
builtins/mkbuiltins.c f
|
||||
builtins/printf.def f
|
||||
builtins/pushd.def f
|
||||
builtins/read.def f
|
||||
builtins/reserved.def f
|
||||
builtins/return.def f
|
||||
builtins/set.def f
|
||||
builtins/setattr.def f
|
||||
builtins/shift.def f
|
||||
builtins/shopt.def f
|
||||
builtins/source.def f
|
||||
builtins/suspend.def f
|
||||
builtins/test.def f
|
||||
builtins/times.def f
|
||||
builtins/trap.def f
|
||||
builtins/type.def f
|
||||
builtins/ulimit.def f
|
||||
builtins/umask.def f
|
||||
builtins/wait.def f
|
||||
builtins/psize.c f
|
||||
builtins/psize.sh f
|
||||
builtins/inlib.def f
|
||||
builtins/bashgetopt.c f
|
||||
builtins/common.h f
|
||||
builtins/bashgetopt.h f
|
||||
cross-build/cygwin32.cache f
|
||||
cross-build/x86-beos.cache f
|
||||
cross-build/opennt.cache f
|
||||
include/ansi_stdlib.h f
|
||||
include/chartypes.h f
|
||||
include/filecntl.h f
|
||||
include/gettext.h f
|
||||
include/maxpath.h f
|
||||
include/memalloc.h f
|
||||
include/ocache.h f
|
||||
include/posixdir.h f
|
||||
include/posixjmp.h f
|
||||
include/posixstat.h f
|
||||
include/posixtime.h f
|
||||
include/posixwait.h f
|
||||
include/shmbutil.h f
|
||||
include/shtty.h f
|
||||
include/stdc.h f
|
||||
include/systimes.h f
|
||||
include/typemax.h f
|
||||
include/unionwait.h f
|
||||
lib/glob/Makefile.in f
|
||||
lib/glob/sm_loop.c f
|
||||
lib/glob/smatch.c f
|
||||
lib/glob/strmatch.c f
|
||||
lib/glob/strmatch.h f
|
||||
lib/glob/glob.c f
|
||||
lib/glob/glob.h f
|
||||
lib/glob/glob_loop.c f
|
||||
lib/glob/xmbsrtowcs.c f
|
||||
lib/glob/collsyms.h f
|
||||
lib/glob/doc/Makefile f
|
||||
lib/glob/doc/glob.texi f
|
||||
lib/glob/ndir.h f
|
||||
lib/intl/ChangeLog f
|
||||
lib/intl/Makefile.in f
|
||||
lib/intl/VERSION f
|
||||
lib/intl/bindtextdom.c f
|
||||
lib/intl/config.charset f
|
||||
lib/intl/dcgettext.c f
|
||||
lib/intl/dcigettext.c f
|
||||
lib/intl/dcngettext.c f
|
||||
lib/intl/dgettext.c f
|
||||
lib/intl/dngettext.c f
|
||||
lib/intl/eval-plural.h f
|
||||
lib/intl/explodename.c f
|
||||
lib/intl/finddomain.c f
|
||||
lib/intl/gettext.c f
|
||||
lib/intl/gettextP.h f
|
||||
lib/intl/gmo.h f
|
||||
lib/intl/hash-string.h f
|
||||
lib/intl/intl-compat.c f
|
||||
lib/intl/l10nflist.c f
|
||||
lib/intl/libgnuintl.h.in f
|
||||
lib/intl/loadinfo.h f
|
||||
lib/intl/loadmsgcat.c f
|
||||
lib/intl/localcharset.c f
|
||||
lib/intl/localcharset.h f
|
||||
lib/intl/locale.alias f
|
||||
lib/intl/localealias.c f
|
||||
lib/intl/localename.c f
|
||||
lib/intl/log.c f
|
||||
lib/intl/ngettext.c f
|
||||
lib/intl/os2compat.c f
|
||||
lib/intl/os2compat.h f
|
||||
lib/intl/osdep.c f
|
||||
lib/intl/plural-exp.c f
|
||||
lib/intl/plural-exp.h f
|
||||
lib/intl/plural.c f
|
||||
lib/intl/plural.y f
|
||||
lib/intl/ref-add.sin f
|
||||
lib/intl/ref-del.sin f
|
||||
lib/intl/relocatable.c f
|
||||
lib/intl/relocatable.h f
|
||||
lib/intl/textdomain.c f
|
||||
lib/malloc/Makefile.in f
|
||||
lib/malloc/getpagesize.h f
|
||||
lib/malloc/imalloc.h f
|
||||
lib/malloc/mstats.h f
|
||||
lib/malloc/shmalloc.h f
|
||||
lib/malloc/table.h f
|
||||
lib/malloc/watch.h f
|
||||
lib/malloc/alloca.c f
|
||||
lib/malloc/malloc.c f
|
||||
lib/malloc/stats.c f
|
||||
lib/malloc/table.c f
|
||||
lib/malloc/trace.c f
|
||||
lib/malloc/watch.c f
|
||||
lib/malloc/xmalloc.c f
|
||||
lib/malloc/xleaktrace f 755
|
||||
lib/malloc/stub.c f
|
||||
lib/malloc/i386-alloca.s f
|
||||
lib/malloc/x386-alloca.s f
|
||||
lib/readline/COPYING f
|
||||
lib/readline/Makefile.in f
|
||||
lib/readline/ChangeLog f
|
||||
lib/readline/README f
|
||||
lib/readline/STANDALONE f
|
||||
lib/readline/readline.c f
|
||||
lib/readline/vi_mode.c f
|
||||
lib/readline/emacs_keymap.c f
|
||||
lib/readline/vi_keymap.c f
|
||||
lib/readline/history.c f
|
||||
lib/readline/histexpand.c f
|
||||
lib/readline/histsearch.c f
|
||||
lib/readline/histfile.c f
|
||||
lib/readline/funmap.c f
|
||||
lib/readline/keymaps.c f
|
||||
lib/readline/util.c f
|
||||
lib/readline/terminal.c f
|
||||
lib/readline/xmalloc.c f
|
||||
lib/readline/search.c f
|
||||
lib/readline/isearch.c f
|
||||
lib/readline/parens.c f
|
||||
lib/readline/rltty.c f
|
||||
lib/readline/compat.c f
|
||||
lib/readline/complete.c f
|
||||
lib/readline/bind.c f
|
||||
lib/readline/display.c f
|
||||
lib/readline/signals.c f
|
||||
lib/readline/kill.c f
|
||||
lib/readline/text.c f
|
||||
lib/readline/undo.c f
|
||||
lib/readline/macro.c f
|
||||
lib/readline/input.c f
|
||||
lib/readline/callback.c f
|
||||
lib/readline/mbutil.c f
|
||||
lib/readline/misc.c f
|
||||
lib/readline/nls.c f
|
||||
lib/readline/shell.c f
|
||||
lib/readline/savestring.c f
|
||||
lib/readline/tilde.c f
|
||||
lib/readline/tilde.h f
|
||||
lib/readline/rldefs.h f
|
||||
lib/readline/rlconf.h f
|
||||
lib/readline/rlmbutil.h f
|
||||
lib/readline/rlshell.h f
|
||||
lib/readline/rltty.h f
|
||||
lib/readline/rltypedefs.h f
|
||||
lib/readline/rlwinsize.h f
|
||||
lib/readline/readline.h f
|
||||
lib/readline/tcap.h f
|
||||
lib/readline/keymaps.h f
|
||||
lib/readline/history.h f
|
||||
lib/readline/histlib.h f
|
||||
lib/readline/chardefs.h f
|
||||
lib/readline/posixdir.h f
|
||||
lib/readline/posixjmp.h f
|
||||
lib/readline/posixstat.h f
|
||||
lib/readline/ansi_stdlib.h f
|
||||
lib/readline/rlstdc.h f
|
||||
lib/readline/rlprivate.h f
|
||||
lib/readline/xmalloc.h f
|
||||
lib/readline/doc/Makefile f
|
||||
lib/readline/doc/version.texi f
|
||||
lib/readline/doc/rlman.texi f
|
||||
lib/readline/doc/rltech.texi f
|
||||
lib/readline/doc/rluser.texi f
|
||||
lib/readline/doc/rluserman.texi f
|
||||
lib/readline/doc/history.texi f
|
||||
lib/readline/doc/hstech.texi f
|
||||
lib/readline/doc/hsuser.texi f
|
||||
lib/readline/doc/fdl.texi f
|
||||
lib/readline/examples/Makefile f
|
||||
lib/readline/examples/excallback.c f
|
||||
lib/readline/examples/fileman.c f
|
||||
lib/readline/examples/manexamp.c f
|
||||
lib/readline/examples/histexamp.c f
|
||||
lib/readline/examples/rltest.c f
|
||||
lib/readline/examples/rl.c f
|
||||
lib/readline/examples/rlcat.c f
|
||||
lib/readline/examples/Inputrc f
|
||||
lib/sh/Makefile.in f
|
||||
lib/sh/clktck.c f
|
||||
lib/sh/clock.c f
|
||||
lib/sh/fmtullong.c f
|
||||
lib/sh/fmtulong.c f
|
||||
lib/sh/fmtumax.c f
|
||||
lib/sh/getcwd.c f
|
||||
lib/sh/getenv.c f
|
||||
lib/sh/inet_aton.c f
|
||||
lib/sh/itos.c f
|
||||
lib/sh/mailstat.c f
|
||||
lib/sh/makepath.c f
|
||||
lib/sh/memset.c f
|
||||
lib/sh/mktime.c f
|
||||
lib/sh/netconn.c f
|
||||
lib/sh/netopen.c f
|
||||
lib/sh/oslib.c f
|
||||
lib/sh/pathcanon.c f
|
||||
lib/sh/pathphys.c f
|
||||
lib/sh/rename.c f
|
||||
lib/sh/setlinebuf.c f
|
||||
lib/sh/shmatch.c f
|
||||
lib/sh/shquote.c f
|
||||
lib/sh/shtty.c f
|
||||
lib/sh/snprintf.c f
|
||||
lib/sh/spell.c f
|
||||
lib/sh/strcasecmp.c f
|
||||
lib/sh/strerror.c f
|
||||
lib/sh/strftime.c f
|
||||
lib/sh/strindex.c f
|
||||
lib/sh/stringlist.c f
|
||||
lib/sh/stringvec.c f
|
||||
lib/sh/strnlen.c f
|
||||
lib/sh/strpbrk.c f
|
||||
lib/sh/strstr.c f
|
||||
lib/sh/strtod.c f
|
||||
lib/sh/strtoimax.c f
|
||||
lib/sh/strtol.c f
|
||||
lib/sh/strtoll.c f
|
||||
lib/sh/strtoul.c f
|
||||
lib/sh/strtoull.c f
|
||||
lib/sh/strtoumax.c f
|
||||
lib/sh/strtrans.c f
|
||||
lib/sh/times.c f
|
||||
lib/sh/timeval.c f
|
||||
lib/sh/tmpfile.c f
|
||||
lib/sh/vprint.c f
|
||||
lib/sh/winsize.c f
|
||||
lib/sh/xstrchr.c f
|
||||
lib/sh/zcatfd.c f
|
||||
lib/sh/zread.c f
|
||||
lib/sh/zwrite.c f
|
||||
lib/termcap/Makefile.in f
|
||||
lib/termcap/ltcap.h f
|
||||
lib/termcap/termcap.c f
|
||||
lib/termcap/termcap.h f
|
||||
lib/termcap/tparam.c f
|
||||
lib/termcap/version.c f
|
||||
lib/termcap/grot/termcap.info f
|
||||
lib/termcap/grot/termcap.info-1 f
|
||||
lib/termcap/grot/termcap.info-2 f
|
||||
lib/termcap/grot/termcap.info-3 f
|
||||
lib/termcap/grot/termcap.info-4 f
|
||||
lib/termcap/grot/NEWS f
|
||||
lib/termcap/grot/INSTALL f
|
||||
lib/termcap/grot/ChangeLog f
|
||||
lib/termcap/grot/texinfo.tex f
|
||||
lib/termcap/grot/termcap.texi f
|
||||
lib/termcap/grot/Makefile.in f
|
||||
lib/termcap/grot/configure f
|
||||
lib/termcap/grot/configure.in f
|
||||
lib/termcap/grot/COPYING f
|
||||
lib/termcap/grot/README f
|
||||
lib/tilde/README f
|
||||
lib/tilde/Makefile.in f
|
||||
lib/tilde/tilde.c f
|
||||
lib/tilde/tilde.h f
|
||||
lib/tilde/shell.c f
|
||||
po/LINGUAS f
|
||||
po/Makefile.in.in f
|
||||
po/Makevars f
|
||||
po/POTFILES.in f
|
||||
po/Rules-builtins f
|
||||
po/Rules-quot f
|
||||
po/bash.pot f
|
||||
po/boldquot.sed f
|
||||
po/en@quot.header f
|
||||
po/en@boldquot.header f
|
||||
po/en@quot.po f
|
||||
po/en@boldquot.po f
|
||||
po/en@quot.gmo f
|
||||
po/en@boldquot.gmo f
|
||||
po/insert-header.sin f
|
||||
po/quot.sed f
|
||||
po/remove-potcdate.sin f
|
||||
CWRU/misc/open-files.c f
|
||||
CWRU/misc/sigs.c f
|
||||
CWRU/misc/sigstat.c f
|
||||
CWRU/misc/bison f
|
||||
CWRU/misc/errlist.c f
|
||||
CWRU/misc/hpux10-dlfcn.h f
|
||||
CWRU/PLATFORMS f
|
||||
CWRU/README f
|
||||
CWRU/changelog f
|
||||
CWRU/sh-redir-hack f
|
||||
CWRU/mh-folder-comp f
|
||||
doc/FAQ f
|
||||
doc/Makefile.in f
|
||||
doc/bash.1 f
|
||||
doc/bashbug.1 f
|
||||
doc/builtins.1 f
|
||||
doc/rbash.1 f
|
||||
doc/README f
|
||||
doc/INTRO f
|
||||
doc/texinfo.tex f
|
||||
doc/bashref.texi f
|
||||
doc/version.texi f
|
||||
doc/bashref.info f
|
||||
doc/article.ms f
|
||||
doc/htmlpost.sh f 755
|
||||
doc/infopost.sh f 755
|
||||
doc/fdl.texi f
|
||||
doc/fdl.txt f
|
||||
support/Makefile.in f
|
||||
support/bashversion.c f
|
||||
support/config.guess f
|
||||
support/config.rpath f 755
|
||||
support/config.sub f
|
||||
support/printenv.sh f 755
|
||||
support/printenv.c f
|
||||
support/bash.xbm f
|
||||
support/missing f 755
|
||||
support/mkclone f 755
|
||||
support/mkconffiles f 755
|
||||
support/mkdirs f 755
|
||||
support/mkinstalldirs f 755
|
||||
support/mkversion.sh f 755
|
||||
support/mksignames.c f
|
||||
support/signames.c f
|
||||
support/bashbug.sh f
|
||||
support/man2html.c f
|
||||
support/recho.c f
|
||||
support/zecho.c f
|
||||
support/SYMLINKS f
|
||||
support/fixlinks f 755
|
||||
support/install.sh f 755
|
||||
support/texi2dvi f 755
|
||||
support/texi2html f 755
|
||||
support/xenix-link.sh f 755
|
||||
support/shobj-conf f 755
|
||||
support/rlvers.sh f 755
|
||||
examples/bashdb/PERMISSION f
|
||||
examples/bashdb/README f
|
||||
examples/bashdb/bashdb f
|
||||
examples/bashdb/bashdb.el f
|
||||
examples/obashdb/PERMISSION f
|
||||
examples/obashdb/README f
|
||||
examples/obashdb/bashdb f
|
||||
examples/obashdb/bashdb.fns f
|
||||
examples/obashdb/bashdb.pre f
|
||||
examples/complete/complete-examples f
|
||||
examples/complete/complete.ianmac f
|
||||
examples/complete/complete2.ianmac f
|
||||
examples/complete/complete.freebsd f
|
||||
examples/complete/complete.gnu-longopt f
|
||||
examples/complete/bashcc-1.0.1.tar.gz f
|
||||
examples/loadables/README f
|
||||
examples/loadables/template.c f
|
||||
examples/loadables/Makefile.in f
|
||||
examples/loadables/necho.c f
|
||||
examples/loadables/hello.c f
|
||||
examples/loadables/print.c f
|
||||
examples/loadables/realpath.c f
|
||||
examples/loadables/sleep.c f
|
||||
examples/loadables/strftime.c f
|
||||
examples/loadables/truefalse.c f
|
||||
examples/loadables/getconf.h f
|
||||
examples/loadables/getconf.c f
|
||||
examples/loadables/finfo.c f
|
||||
examples/loadables/cat.c f
|
||||
examples/loadables/cut.c f
|
||||
examples/loadables/logname.c f
|
||||
examples/loadables/basename.c f
|
||||
examples/loadables/dirname.c f
|
||||
examples/loadables/tty.c f
|
||||
examples/loadables/pathchk.c f
|
||||
examples/loadables/tee.c f
|
||||
examples/loadables/rmdir.c f
|
||||
examples/loadables/head.c f
|
||||
examples/loadables/printenv.c f
|
||||
examples/loadables/push.c f
|
||||
examples/loadables/id.c f
|
||||
examples/loadables/whoami.c f
|
||||
examples/loadables/uname.c f
|
||||
examples/loadables/sync.c f
|
||||
examples/loadables/mkdir.c f
|
||||
examples/loadables/ln.c f
|
||||
examples/loadables/unlink.c f
|
||||
examples/loadables/perl/Makefile.in f
|
||||
examples/loadables/perl/README f
|
||||
examples/loadables/perl/bperl.c f
|
||||
examples/loadables/perl/iperl.c f
|
||||
examples/functions/array-stuff f
|
||||
examples/functions/array-to-string f
|
||||
examples/functions/autoload f
|
||||
examples/functions/autoload.v2 f
|
||||
examples/functions/autoload.v3 f
|
||||
examples/functions/basename f
|
||||
examples/functions/basename2 f
|
||||
examples/functions/coproc.bash f
|
||||
examples/functions/coshell.README f
|
||||
examples/functions/coshell.bash f
|
||||
examples/functions/csh-compat f
|
||||
examples/functions/dirfuncs f
|
||||
examples/functions/dirname f
|
||||
examples/functions/emptydir f
|
||||
examples/functions/exitstat f
|
||||
examples/functions/external f
|
||||
examples/functions/fact f
|
||||
examples/functions/fstty f
|
||||
examples/functions/func f
|
||||
examples/functions/gethtml f
|
||||
examples/functions/getoptx.bash f
|
||||
examples/functions/inetaddr f
|
||||
examples/functions/inpath f
|
||||
examples/functions/isnum.bash f
|
||||
examples/functions/isnum2 f
|
||||
examples/functions/isvalidip f
|
||||
examples/functions/jdate.bash f
|
||||
examples/functions/jj.bash f
|
||||
examples/functions/keep f
|
||||
examples/functions/ksh-cd f
|
||||
examples/functions/ksh-compat-test f
|
||||
examples/functions/kshenv f
|
||||
examples/functions/login f
|
||||
examples/functions/lowercase f
|
||||
examples/functions/manpage f
|
||||
examples/functions/mhfold f
|
||||
examples/functions/notify.bash f
|
||||
examples/functions/pathfuncs f
|
||||
examples/functions/recurse f
|
||||
examples/functions/repeat2 f
|
||||
examples/functions/repeat3 f
|
||||
examples/functions/seq f
|
||||
examples/functions/seq2 f
|
||||
examples/functions/shcat f
|
||||
examples/functions/shcat2 f
|
||||
examples/functions/sort-pos-params f
|
||||
examples/functions/substr f
|
||||
examples/functions/substr2 f
|
||||
examples/functions/term f
|
||||
examples/functions/whatis f
|
||||
examples/functions/whence f
|
||||
examples/functions/which f
|
||||
examples/functions/xalias.bash f
|
||||
examples/functions/xfind.bash f
|
||||
examples/scripts/adventure.sh f
|
||||
examples/scripts/bcsh.sh f
|
||||
examples/scripts/cat.sh f
|
||||
examples/scripts/center f
|
||||
examples/scripts/dd-ex.sh f
|
||||
examples/scripts/fixfiles.bash f
|
||||
examples/scripts/hanoi.bash f
|
||||
examples/scripts/inpath f
|
||||
examples/scripts/krand.bash f
|
||||
examples/scripts/line-input.bash f
|
||||
examples/scripts/nohup.bash f
|
||||
examples/scripts/precedence f
|
||||
examples/scripts/randomcard.bash f
|
||||
examples/scripts/scrollbar f
|
||||
examples/scripts/scrollbar2 f
|
||||
examples/scripts/self-repro f
|
||||
examples/scripts/showperm.bash f
|
||||
examples/scripts/shprompt f
|
||||
examples/scripts/spin.bash f
|
||||
examples/scripts/timeout f
|
||||
examples/scripts/vtree2 f
|
||||
examples/scripts/vtree3 f
|
||||
examples/scripts/vtree3a f
|
||||
examples/scripts/websrv.sh f
|
||||
examples/scripts/xterm_title f
|
||||
examples/scripts/zprintf f
|
||||
examples/startup-files/README f
|
||||
examples/startup-files/Bashrc.bfox f
|
||||
examples/startup-files/Bash_aliases f
|
||||
examples/startup-files/Bash_profile f
|
||||
examples/startup-files/bash-profile f
|
||||
examples/startup-files/bashrc f
|
||||
examples/startup-files/apple/README f
|
||||
examples/startup-files/apple/aliases f
|
||||
examples/startup-files/apple/bash.defaults f
|
||||
examples/startup-files/apple/environment f
|
||||
examples/startup-files/apple/login f
|
||||
examples/startup-files/apple/logout f
|
||||
examples/startup-files/apple/rc f
|
||||
examples/misc/suncmd.termcap f
|
||||
examples/misc/aliasconv.sh f
|
||||
examples/misc/aliasconv.bash f
|
||||
examples/misc/cshtobash f
|
||||
tests/README f
|
||||
tests/alias.tests f
|
||||
tests/alias.right f
|
||||
tests/appendop.tests f
|
||||
tests/appendop.right f
|
||||
tests/arith-for.tests f
|
||||
tests/arith-for.right f
|
||||
tests/arith.tests f
|
||||
tests/arith.right f
|
||||
tests/arith1.sub f
|
||||
tests/arith2.sub f
|
||||
tests/array.tests f
|
||||
tests/array.right f
|
||||
tests/array1.sub f
|
||||
tests/array2.sub f
|
||||
tests/array3.sub f
|
||||
tests/array4.sub f
|
||||
tests/array-at-star f
|
||||
tests/array2.right f
|
||||
tests/braces.tests f
|
||||
tests/braces.right f
|
||||
tests/builtins.tests f
|
||||
tests/builtins.right f
|
||||
tests/builtins1.sub f
|
||||
tests/builtins2.sub f
|
||||
tests/source1.sub f
|
||||
tests/source2.sub f
|
||||
tests/source3.sub f
|
||||
tests/source4.sub f
|
||||
tests/source5.sub f
|
||||
tests/cond.tests f
|
||||
tests/cond.right f
|
||||
tests/cprint.tests f
|
||||
tests/cprint.right f
|
||||
tests/dbg-support.right f
|
||||
tests/dbg-support.sub f
|
||||
tests/dbg-support.tests f
|
||||
tests/dbg-support2.right f
|
||||
tests/dbg-support2.tests f
|
||||
tests/dollar-at-star f
|
||||
tests/dollar-at1.sub f
|
||||
tests/dollar-at2.sub f
|
||||
tests/dollar-star1.sub f
|
||||
tests/dollar-star2.sub f
|
||||
tests/dollar.right f
|
||||
tests/dstack.tests f
|
||||
tests/dstack.right f
|
||||
tests/dstack2.tests f
|
||||
tests/dstack2.right f
|
||||
tests/errors.tests f
|
||||
tests/errors.right f
|
||||
tests/execscript f
|
||||
tests/exec.right f
|
||||
tests/exec1.sub f 755
|
||||
tests/exec2.sub f
|
||||
tests/exec3.sub f
|
||||
tests/exec4.sub f
|
||||
tests/exec5.sub f
|
||||
tests/exec6.sub f
|
||||
tests/exec7.sub f
|
||||
tests/exp-tests f
|
||||
tests/exp.right f
|
||||
tests/extglob.tests f
|
||||
tests/extglob.right f
|
||||
tests/extglob2.tests f
|
||||
tests/extglob2.right f
|
||||
tests/extglob3.tests f
|
||||
tests/extglob3.right f
|
||||
tests/func.tests f
|
||||
tests/func.right f
|
||||
tests/func1.sub f
|
||||
tests/func2.sub f
|
||||
tests/func3.sub f
|
||||
tests/getopts.tests f
|
||||
tests/getopts.right f
|
||||
tests/getopts1.sub f
|
||||
tests/getopts2.sub f
|
||||
tests/getopts3.sub f
|
||||
tests/getopts4.sub f
|
||||
tests/getopts5.sub f
|
||||
tests/getopts6.sub f
|
||||
tests/getopts7.sub f
|
||||
tests/glob-test f
|
||||
tests/glob1.sub f
|
||||
tests/glob.right f
|
||||
tests/heredoc.tests f
|
||||
tests/heredoc.right f
|
||||
tests/herestr.tests f
|
||||
tests/herestr.right f
|
||||
tests/histexp.tests f
|
||||
tests/histexp.right f
|
||||
tests/history.tests f
|
||||
tests/history.right f
|
||||
tests/history.list f 444
|
||||
tests/ifs.tests f
|
||||
tests/ifs.right f
|
||||
tests/ifs-posix.tests f
|
||||
tests/ifs-posix.right f
|
||||
tests/input-line.sh f
|
||||
tests/input-line.sub f
|
||||
tests/input.right f
|
||||
tests/intl.tests f
|
||||
tests/intl.right f
|
||||
tests/iquote.tests f
|
||||
tests/iquote.right f
|
||||
tests/invert.tests f
|
||||
tests/invert.right f
|
||||
tests/jobs.tests f
|
||||
tests/jobs1.sub f
|
||||
tests/jobs2.sub f
|
||||
tests/jobs3.sub f
|
||||
tests/jobs4.sub f
|
||||
tests/jobs.right f
|
||||
tests/more-exp.tests f
|
||||
tests/more-exp.right f
|
||||
tests/new-exp.tests f
|
||||
tests/new-exp1.sub f
|
||||
tests/new-exp2.sub f
|
||||
tests/new-exp3.sub f
|
||||
tests/new-exp4.sub f
|
||||
tests/new-exp5.sub f
|
||||
tests/new-exp.right f
|
||||
tests/nquote.tests f
|
||||
tests/nquote.right f
|
||||
tests/nquote1.tests f
|
||||
tests/nquote1.right f
|
||||
tests/nquote2.tests f
|
||||
tests/nquote2.right f
|
||||
tests/nquote3.tests f
|
||||
tests/nquote3.right f
|
||||
tests/nquote4.tests f
|
||||
tests/nquote4.right f
|
||||
tests/posix2.tests f
|
||||
tests/posix2.right f
|
||||
tests/posixpat.tests f
|
||||
tests/posixpat.right f
|
||||
tests/prec.right f
|
||||
tests/precedence f
|
||||
tests/printf.tests f
|
||||
tests/printf.right f
|
||||
tests/quote.tests f
|
||||
tests/quote.right f
|
||||
tests/read.tests f
|
||||
tests/read.right f
|
||||
tests/read1.sub f
|
||||
tests/read2.sub f
|
||||
tests/read3.sub f
|
||||
tests/read4.sub f
|
||||
tests/read5.sub f
|
||||
tests/redir.tests f
|
||||
tests/redir.right f
|
||||
tests/redir1.sub f
|
||||
tests/redir2.sub f
|
||||
tests/redir3.sub f
|
||||
tests/redir3.in1 f
|
||||
tests/redir3.in2 f
|
||||
tests/redir4.sub f
|
||||
tests/redir4.in1 f
|
||||
tests/redir5.sub f
|
||||
tests/redir6.sub f
|
||||
tests/redir7.sub f
|
||||
tests/rhs-exp.tests f
|
||||
tests/rhs-exp.right f
|
||||
tests/rsh.tests f
|
||||
tests/rsh.right f
|
||||
tests/run-all f
|
||||
tests/run-minimal f
|
||||
tests/run-alias f
|
||||
tests/run-appendop f
|
||||
tests/run-arith-for f
|
||||
tests/run-arith f
|
||||
tests/run-array f
|
||||
tests/run-array2 f
|
||||
tests/run-braces f
|
||||
tests/run-builtins f
|
||||
tests/run-cond f
|
||||
tests/run-cprint f
|
||||
tests/run-dbg-support f
|
||||
tests/run-dbg-support2 f
|
||||
tests/run-dirstack f
|
||||
tests/run-dollars f
|
||||
tests/run-errors f
|
||||
tests/run-execscript f
|
||||
tests/run-exp-tests f
|
||||
tests/run-extglob f
|
||||
tests/run-extglob2 f
|
||||
tests/run-extglob3 f
|
||||
tests/run-func f
|
||||
tests/run-getopts f
|
||||
tests/run-glob-test f
|
||||
tests/run-heredoc f
|
||||
tests/run-herestr f
|
||||
tests/run-histexpand f
|
||||
tests/run-history f
|
||||
tests/run-ifs f
|
||||
tests/run-ifs-posix f
|
||||
tests/run-input-test f
|
||||
tests/run-intl f
|
||||
tests/run-iquote f
|
||||
tests/run-invert f
|
||||
tests/run-jobs f
|
||||
tests/run-more-exp f
|
||||
tests/run-new-exp f
|
||||
tests/run-nquote f
|
||||
tests/run-nquote1 f
|
||||
tests/run-nquote2 f
|
||||
tests/run-nquote3 f
|
||||
tests/run-nquote4 f
|
||||
tests/run-posix2 f
|
||||
tests/run-posixpat f
|
||||
tests/run-precedence f
|
||||
tests/run-printf f
|
||||
tests/run-quote f
|
||||
tests/run-read f
|
||||
tests/run-redir f
|
||||
tests/run-rhs-exp f
|
||||
tests/run-rsh f
|
||||
tests/run-set-e f
|
||||
tests/run-set-x f
|
||||
tests/run-shopt f
|
||||
tests/run-strip f
|
||||
tests/run-test f
|
||||
tests/run-tilde f
|
||||
tests/run-tilde2 f
|
||||
tests/run-trap f
|
||||
tests/run-type f
|
||||
tests/run-varenv f
|
||||
tests/set-e-test f
|
||||
tests/set-e.right f
|
||||
tests/set-x.tests f
|
||||
tests/set-x.right f
|
||||
tests/shopt.tests f
|
||||
tests/shopt.right f
|
||||
tests/strip.tests f
|
||||
tests/strip.right f
|
||||
tests/test.tests f
|
||||
tests/test.right f
|
||||
tests/tilde.tests f
|
||||
tests/tilde.right f
|
||||
tests/tilde2.tests f
|
||||
tests/tilde2.right f
|
||||
tests/trap.tests f
|
||||
tests/trap.right f
|
||||
tests/trap1.sub f 755
|
||||
tests/trap2.sub f 755
|
||||
tests/trap2a.sub f 755
|
||||
tests/type.tests f
|
||||
tests/type.right f
|
||||
tests/varenv.right f
|
||||
tests/varenv.sh f
|
||||
tests/varenv1.sub f
|
||||
tests/varenv2.sub f
|
||||
tests/version f
|
||||
tests/version.mini f
|
||||
tests/misc/dev-tcp.tests f
|
||||
tests/misc/perf-script f
|
||||
tests/misc/perftest f
|
||||
tests/misc/read-nchars.tests f
|
||||
tests/misc/redir-t2.sh f
|
||||
tests/misc/run-r2.sh f
|
||||
tests/misc/sigint-1.sh f
|
||||
tests/misc/sigint-2.sh f
|
||||
tests/misc/sigint-3.sh f
|
||||
tests/misc/sigint-4.sh f
|
||||
tests/misc/test-minus-e.1 f
|
||||
tests/misc/test-minus-e.2 f
|
||||
tests/misc/wait-bg.tests f
|
||||
examples/scripts.v2/PERMISSION f
|
||||
examples/scripts.v2/README f
|
||||
examples/scripts.v2/arc2tarz f
|
||||
examples/scripts.v2/bashrand f
|
||||
examples/scripts.v2/cal2day.bash f
|
||||
examples/scripts.v2/cdhist.bash f
|
||||
examples/scripts.v2/corename f
|
||||
examples/scripts.v2/fman f
|
||||
examples/scripts.v2/frcp f
|
||||
examples/scripts.v2/lowercase f
|
||||
examples/scripts.v2/ncp f
|
||||
examples/scripts.v2/newext f
|
||||
examples/scripts.v2/nmv f
|
||||
examples/scripts.v2/pages f
|
||||
examples/scripts.v2/pf f
|
||||
examples/scripts.v2/ren f
|
||||
examples/scripts.v2/rename f
|
||||
examples/scripts.v2/repeat f
|
||||
examples/scripts.v2/untar f
|
||||
examples/scripts.v2/uudec f
|
||||
examples/scripts.v2/uuenc f
|
||||
examples/scripts.v2/vtree f
|
||||
examples/scripts.v2/where f
|
||||
examples/scripts.v2/pmtop f
|
||||
examples/scripts.v2/shprof f
|
||||
examples/scripts.noah/PERMISSION f
|
||||
examples/scripts.noah/README f
|
||||
examples/scripts.noah/aref.bash f
|
||||
examples/scripts.noah/bash.sub.bash f
|
||||
examples/scripts.noah/bash_version.bash f
|
||||
examples/scripts.noah/meta.bash f
|
||||
examples/scripts.noah/mktmp.bash f
|
||||
examples/scripts.noah/number.bash f
|
||||
examples/scripts.noah/prompt.bash f
|
||||
examples/scripts.noah/remap_keys.bash f
|
||||
examples/scripts.noah/require.bash f
|
||||
examples/scripts.noah/send_mail.bash f
|
||||
examples/scripts.noah/shcat.bash f
|
||||
examples/scripts.noah/source.bash f
|
||||
examples/scripts.noah/string.bash f
|
||||
examples/scripts.noah/stty.bash f
|
||||
examples/scripts.noah/y_or_n_p.bash f
|
||||
+29
-10
@@ -1,4 +1,4 @@
|
||||
# Makefile for bash-3.1, version 2.157
|
||||
# Makefile for bash-3.1, version 2.159
|
||||
#
|
||||
# Copyright (C) 1996-2005 Free Software Foundation, Inc.
|
||||
|
||||
@@ -128,6 +128,8 @@ LOCALE_DEFS = -DLOCALEDIR='"$(localedir)"' -DPACKAGE='"$(PACKAGE)"'
|
||||
|
||||
LOCAL_LIBS = @LOCAL_LIBS@
|
||||
LIBS = $(BUILTINS_LIB) $(LIBRARIES) @LIBS@
|
||||
LIBS_FOR_BUILD =
|
||||
|
||||
STATIC_LD = @STATIC_LD@
|
||||
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
|
||||
|
||||
@@ -418,6 +420,7 @@ SIGNAMES_H = @SIGNAMES_H@
|
||||
# object files chosen based on running of configure
|
||||
JOBS_O = @JOBS_O@
|
||||
SIGLIST_O = @SIGLIST_O@
|
||||
SIGNAMES_O = @SIGNAMES_O@
|
||||
|
||||
# Matching object files.
|
||||
OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
|
||||
@@ -426,7 +429,7 @@ OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
|
||||
trap.o input.o unwind_prot.o pathexp.o sig.o test.o version.o \
|
||||
alias.o array.o arrayfunc.o braces.o bracecomp.o bashhist.o \
|
||||
bashline.o $(SIGLIST_O) list.o stringlib.o locale.o findcmd.o redir.o \
|
||||
pcomplete.o pcomplib.o syntax.o xmalloc.o
|
||||
pcomplete.o pcomplib.o syntax.o xmalloc.o $(SIGNAMES_O)
|
||||
|
||||
# Where the source code of the shell builtins resides.
|
||||
BUILTIN_SRCDIR=$(srcdir)/builtins
|
||||
@@ -495,7 +498,7 @@ CREATED_SUPPORT = signames.h recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) \
|
||||
tests/recho$(EXEEXT) tests/zecho$(EXEEXT) \
|
||||
tests/printenv$(EXEEXT) mksignames$(EXEEXT) lsignames.h \
|
||||
mksyntax${EXEEXT} syntax.c $(VERSPROG) $(VERSOBJ) \
|
||||
buildversion.o
|
||||
buildversion.o mksignames.o signames.o
|
||||
CREATED_CONFIGURE = config.h config.cache config.status config.log \
|
||||
stamp-h po/POTFILES
|
||||
CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
|
||||
@@ -547,7 +550,7 @@ version.h: $(SOURCES) config.h Makefile
|
||||
&& mv newversion.h version.h
|
||||
|
||||
bashversion$(EXEEXT): patchlevel.h conftypes.h version.h buildversion.o $(SUPPORT_SRC)bashversion.c
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)bashversion.c buildversion.o
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)bashversion.c buildversion.o ${LIBS_FOR_BUILD}
|
||||
|
||||
buildversion.o: version.h conftypes.h patchlevel.h $(srcdir)/version.c
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -c -o $@ $(srcdir)/version.c
|
||||
@@ -609,11 +612,25 @@ ${INTL_LIBRARY}: config.h ${INTL_LIBDIR}/Makefile
|
||||
|
||||
${LIBINTL_H}: ${INTL_LIBRARY}
|
||||
|
||||
mksignames$(EXEEXT): $(SUPPORT_SRC)mksignames.c
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)mksignames.c
|
||||
signames.o: $(SUPPORT_SRC)signames.c
|
||||
$(RM) $@
|
||||
$(CC) $(CCFLAGS) -c $(SUPPORT_SRC)signames.c
|
||||
|
||||
buildsignames.o: $(SUPPORT_SRC)signames.c
|
||||
$(RM) $@
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -o $@ -c $(SUPPORT_SRC)signames.c
|
||||
|
||||
mksignames.o: $(SUPPORT_SRC)mksignames.c
|
||||
$(RM) $@
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -DBUILDTOOL -c $(SUPPORT_SRC)mksignames.c
|
||||
|
||||
mksignames$(EXEEXT): mksignames.o buildsignames.o
|
||||
$(RM) $@
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ mksignames.o buildsignames.o ${LIBS_FOR_BUILD}
|
||||
|
||||
mksyntax$(EXEEXT): ${srcdir}/mksyntax.c config.h syntax.h ${BASHINCDIR}/chartypes.h
|
||||
${CC_FOR_BUILD} ${CCFLAGS_FOR_BUILD} -o $@ ${srcdir}/mksyntax.c
|
||||
$(RM) $@
|
||||
${CC_FOR_BUILD} ${CCFLAGS_FOR_BUILD} -o $@ ${srcdir}/mksyntax.c ${LIBS_FOR_BUILD}
|
||||
|
||||
# make a list of signals for the local system -- this is done when we're
|
||||
# *not* cross-compiling
|
||||
@@ -782,13 +799,13 @@ maybe-clean:
|
||||
fi
|
||||
|
||||
recho$(EXEEXT): $(SUPPORT_SRC)recho.c
|
||||
@$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)recho.c
|
||||
@$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)recho.c ${LIBS_FOR_BUILD}
|
||||
|
||||
zecho$(EXEEXT): $(SUPPORT_SRC)zecho.c
|
||||
@$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)zecho.c
|
||||
@$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)zecho.c ${LIBS_FOR_BUILD}
|
||||
|
||||
printenv$(EXEEXT): $(SUPPORT_SRC)printenv.c
|
||||
@$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)printenv.c
|
||||
@$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)printenv.c ${LIBS_FOR_BUILD}
|
||||
|
||||
test tests check: force $(Program) $(TESTS_SUPPORT)
|
||||
@-test -d tests || mkdir tests
|
||||
@@ -1143,6 +1160,8 @@ variables.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
version.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
xmalloc.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
|
||||
|
||||
signames.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
|
||||
|
||||
# XXX - dependencies checked through here
|
||||
|
||||
# builtin c sources
|
||||
|
||||
+1439
File diff suppressed because it is too large
Load Diff
+1455
File diff suppressed because it is too large
Load Diff
Vendored
+2
-2
@@ -933,7 +933,7 @@ AC_DEFINE(HAVE_STRUCT_STAT_ST_BLOCKS)
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN(BASH_CHECK_LIB_TERMCAP,
|
||||
AC_DEFUN([BASH_CHECK_LIB_TERMCAP],
|
||||
[
|
||||
if test "X$bash_cv_termcap_lib" = "X"; then
|
||||
_bash_needmsg=yes
|
||||
@@ -1710,7 +1710,7 @@ dnl require:
|
||||
dnl AC_PROG_CC
|
||||
dnl BASH_CHECK_LIB_TERMCAP
|
||||
|
||||
AC_DEFUN(RL_LIB_READLINE_VERSION,
|
||||
AC_DEFUN([RL_LIB_READLINE_VERSION],
|
||||
[
|
||||
AC_REQUIRE([BASH_CHECK_LIB_TERMCAP])
|
||||
|
||||
|
||||
Vendored
+3962
File diff suppressed because it is too large
Load Diff
+2
-8
@@ -438,13 +438,11 @@ skipsubscript (s, i)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mbstate_t state, state_bak;
|
||||
size_t slength, mblength;
|
||||
size_t mb_cur_max;
|
||||
#endif
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (&state, '\0', sizeof (mbstate_t));
|
||||
slength = strlen (s + i);
|
||||
mb_cur_max = MB_CUR_MAX;
|
||||
#endif
|
||||
|
||||
count = 1;
|
||||
@@ -452,7 +450,7 @@ skipsubscript (s, i)
|
||||
{
|
||||
/* Advance one (possibly multibyte) character in S starting at I. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (mb_cur_max > 1)
|
||||
if (MB_CUR_MAX > 1)
|
||||
{
|
||||
state_bak = state;
|
||||
mblength = mbrlen (s + i, slength, &state);
|
||||
@@ -592,11 +590,7 @@ array_expand_index (s, len)
|
||||
exp = (char *)xmalloc (len);
|
||||
strncpy (exp, s, len - 1);
|
||||
exp[len - 1] = '\0';
|
||||
#if 0
|
||||
t = expand_string_to_string (exp, 0);
|
||||
#else
|
||||
t = expand_string_to_string (exp, Q_DOUBLE_QUOTES);
|
||||
#endif
|
||||
t = expand_arith_string (exp);
|
||||
this_command_name = (char *)NULL;
|
||||
val = evalexp (t, &expok);
|
||||
free (t);
|
||||
|
||||
+819
@@ -0,0 +1,819 @@
|
||||
/* arrayfunc.c -- High-level array functions used by other parts of the shell. */
|
||||
|
||||
/* Copyright (C) 2001-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bashintl.h"
|
||||
|
||||
#include "shell.h"
|
||||
|
||||
#include "shmbutil.h"
|
||||
|
||||
#include "builtins/common.h"
|
||||
|
||||
extern char *this_command_name;
|
||||
extern int last_command_exit_value;
|
||||
extern int array_needs_making;
|
||||
|
||||
static SHELL_VAR *bind_array_var_internal __P((SHELL_VAR *, arrayind_t, char *, int));
|
||||
|
||||
static void quote_array_assignment_chars __P((WORD_LIST *));
|
||||
static char *array_value_internal __P((char *, int, int, int *));
|
||||
|
||||
/* Standard error message to use when encountering an invalid array subscript */
|
||||
char *bash_badsub_errmsg = N_("bad array subscript");
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Functions to manipulate array variables and perform assignments */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Convert a shell variable to an array variable. The original value is
|
||||
saved as array[0]. */
|
||||
SHELL_VAR *
|
||||
convert_var_to_array (var)
|
||||
SHELL_VAR *var;
|
||||
{
|
||||
char *oldval;
|
||||
ARRAY *array;
|
||||
|
||||
oldval = value_cell (var);
|
||||
array = array_create ();
|
||||
if (oldval)
|
||||
array_insert (array, 0, oldval);
|
||||
|
||||
FREE (value_cell (var));
|
||||
var_setarray (var, array);
|
||||
|
||||
/* these aren't valid anymore */
|
||||
var->dynamic_value = (sh_var_value_func_t *)NULL;
|
||||
var->assign_func = (sh_var_assign_func_t *)NULL;
|
||||
|
||||
INVALIDATE_EXPORTSTR (var);
|
||||
if (exported_p (var))
|
||||
array_needs_making++;
|
||||
|
||||
VSETATTR (var, att_array);
|
||||
VUNSETATTR (var, att_invisible);
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
static SHELL_VAR *
|
||||
bind_array_var_internal (entry, ind, value, flags)
|
||||
SHELL_VAR *entry;
|
||||
arrayind_t ind;
|
||||
char *value;
|
||||
int flags;
|
||||
{
|
||||
SHELL_VAR *dentry;
|
||||
char *newval;
|
||||
|
||||
/* If we're appending, we need the old value of the array reference, so
|
||||
fake out make_variable_value with a dummy SHELL_VAR */
|
||||
if (flags & ASS_APPEND)
|
||||
{
|
||||
dentry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
|
||||
dentry->name = savestring (entry->name);
|
||||
newval = array_reference (array_cell (entry), ind);
|
||||
if (newval)
|
||||
dentry->value = savestring (newval);
|
||||
else
|
||||
{
|
||||
dentry->value = (char *)xmalloc (1);
|
||||
dentry->value[0] = '\0';
|
||||
}
|
||||
dentry->exportstr = 0;
|
||||
dentry->attributes = entry->attributes & ~(att_array|att_exported);
|
||||
/* Leave the rest of the members uninitialized; the code doesn't look
|
||||
at them. */
|
||||
newval = make_variable_value (dentry, value, flags);
|
||||
dispose_variable (dentry);
|
||||
}
|
||||
else
|
||||
newval = make_variable_value (entry, value, flags);
|
||||
|
||||
if (entry->assign_func)
|
||||
(*entry->assign_func) (entry, newval, ind);
|
||||
else
|
||||
array_insert (array_cell (entry), ind, newval);
|
||||
FREE (newval);
|
||||
|
||||
return (entry);
|
||||
}
|
||||
|
||||
/* Perform an array assignment name[ind]=value. If NAME already exists and
|
||||
is not an array, and IND is 0, perform name=value instead. If NAME exists
|
||||
and is not an array, and IND is not 0, convert it into an array with the
|
||||
existing value as name[0].
|
||||
|
||||
If NAME does not exist, just create an array variable, no matter what
|
||||
IND's value may be. */
|
||||
SHELL_VAR *
|
||||
bind_array_variable (name, ind, value, flags)
|
||||
char *name;
|
||||
arrayind_t ind;
|
||||
char *value;
|
||||
int flags;
|
||||
{
|
||||
SHELL_VAR *entry;
|
||||
|
||||
entry = var_lookup (name, shell_variables);
|
||||
|
||||
if (entry == (SHELL_VAR *) 0)
|
||||
entry = make_new_array_variable (name);
|
||||
else if (readonly_p (entry) || noassign_p (entry))
|
||||
{
|
||||
if (readonly_p (entry))
|
||||
err_readonly (name);
|
||||
return (entry);
|
||||
}
|
||||
else if (array_p (entry) == 0)
|
||||
entry = convert_var_to_array (entry);
|
||||
|
||||
/* ENTRY is an array variable, and ARRAY points to the value. */
|
||||
return (bind_array_var_internal (entry, ind, value, flags));
|
||||
}
|
||||
|
||||
/* Parse NAME, a lhs of an assignment statement of the form v[s], and
|
||||
assign VALUE to that array element by calling bind_array_variable(). */
|
||||
SHELL_VAR *
|
||||
assign_array_element (name, value, flags)
|
||||
char *name, *value;
|
||||
int flags;
|
||||
{
|
||||
char *sub, *vname;
|
||||
arrayind_t ind;
|
||||
int sublen;
|
||||
SHELL_VAR *entry;
|
||||
|
||||
vname = array_variable_name (name, &sub, &sublen);
|
||||
|
||||
if (vname == 0)
|
||||
return ((SHELL_VAR *)NULL);
|
||||
|
||||
if ((ALL_ELEMENT_SUB (sub[0]) && sub[1] == ']') || (sublen <= 1))
|
||||
{
|
||||
free (vname);
|
||||
err_badarraysub (name);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
|
||||
ind = array_expand_index (sub, sublen);
|
||||
if (ind < 0)
|
||||
{
|
||||
free (vname);
|
||||
err_badarraysub (name);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
|
||||
entry = bind_array_variable (vname, ind, value, flags);
|
||||
|
||||
free (vname);
|
||||
return (entry);
|
||||
}
|
||||
|
||||
/* Find the array variable corresponding to NAME. If there is no variable,
|
||||
create a new array variable. If the variable exists but is not an array,
|
||||
convert it to an indexed array. If CHECK_FLAGS is non-zero, an existing
|
||||
variable is checked for the readonly or noassign attribute in preparation
|
||||
for assignment (e.g., by the `read' builtin). */
|
||||
SHELL_VAR *
|
||||
find_or_make_array_variable (name, check_flags)
|
||||
char *name;
|
||||
int check_flags;
|
||||
{
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = find_variable (name);
|
||||
|
||||
if (var == 0)
|
||||
var = make_new_array_variable (name);
|
||||
else if (check_flags && (readonly_p (var) || noassign_p (var)))
|
||||
{
|
||||
if (readonly_p (var))
|
||||
err_readonly (name);
|
||||
return ((SHELL_VAR *)NULL);
|
||||
}
|
||||
else if (array_p (var) == 0)
|
||||
var = convert_var_to_array (var);
|
||||
|
||||
return (var);
|
||||
}
|
||||
|
||||
/* Perform a compound assignment statement for array NAME, where VALUE is
|
||||
the text between the parens: NAME=( VALUE ) */
|
||||
SHELL_VAR *
|
||||
assign_array_from_string (name, value, flags)
|
||||
char *name, *value;
|
||||
int flags;
|
||||
{
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = find_or_make_array_variable (name, 1);
|
||||
if (var == 0)
|
||||
return ((SHELL_VAR *)NULL);
|
||||
|
||||
return (assign_array_var_from_string (var, value, flags));
|
||||
}
|
||||
|
||||
/* Sequentially assign the indices of indexed array variable VAR from the
|
||||
words in LIST. */
|
||||
SHELL_VAR *
|
||||
assign_array_var_from_word_list (var, list, flags)
|
||||
SHELL_VAR *var;
|
||||
WORD_LIST *list;
|
||||
int flags;
|
||||
{
|
||||
register arrayind_t i;
|
||||
register WORD_LIST *l;
|
||||
ARRAY *a;
|
||||
|
||||
a = array_cell (var);
|
||||
i = (flags & ASS_APPEND) ? array_max_index (a) + 1 : 0;
|
||||
|
||||
for (l = list; l; l = l->next, i++)
|
||||
if (var->assign_func)
|
||||
(*var->assign_func) (var, l->word->word, i);
|
||||
else
|
||||
array_insert (a, i, l->word->word);
|
||||
return var;
|
||||
}
|
||||
|
||||
/* Perform a compound array assignment: VAR->name=( VALUE ). The
|
||||
VALUE has already had the parentheses stripped. */
|
||||
SHELL_VAR *
|
||||
assign_array_var_from_string (var, value, flags)
|
||||
SHELL_VAR *var;
|
||||
char *value;
|
||||
int flags;
|
||||
{
|
||||
ARRAY *a;
|
||||
WORD_LIST *list, *nlist;
|
||||
char *w, *val, *nval;
|
||||
int ni, len;
|
||||
arrayind_t ind, last_ind;
|
||||
|
||||
if (value == 0)
|
||||
return var;
|
||||
|
||||
/* If this is called from declare_builtin, value[0] == '(' and
|
||||
xstrchr(value, ')') != 0. In this case, we need to extract
|
||||
the value from between the parens before going on. */
|
||||
if (*value == '(') /*)*/
|
||||
{
|
||||
ni = 1;
|
||||
val = extract_array_assignment_list (value, &ni);
|
||||
if (val == 0)
|
||||
return var;
|
||||
}
|
||||
else
|
||||
val = value;
|
||||
|
||||
/* Expand the value string into a list of words, performing all the
|
||||
shell expansions including pathname generation and word splitting. */
|
||||
/* First we split the string on whitespace, using the shell parser
|
||||
(ksh93 seems to do this). */
|
||||
list = parse_string_to_word_list (val, 1, "array assign");
|
||||
|
||||
/* If we're using [subscript]=value, we need to quote each [ and ] to
|
||||
prevent unwanted filename expansion. */
|
||||
if (list)
|
||||
quote_array_assignment_chars (list);
|
||||
|
||||
/* Now that we've split it, perform the shell expansions on each
|
||||
word in the list. */
|
||||
nlist = list ? expand_words_no_vars (list) : (WORD_LIST *)NULL;
|
||||
|
||||
dispose_words (list);
|
||||
|
||||
if (val != value)
|
||||
free (val);
|
||||
|
||||
a = array_cell (var);
|
||||
|
||||
/* Now that we are ready to assign values to the array, kill the existing
|
||||
value. */
|
||||
if (a && (flags & ASS_APPEND) == 0)
|
||||
array_flush (a);
|
||||
last_ind = (flags & ASS_APPEND) ? array_max_index (a) + 1 : 0;
|
||||
|
||||
for (list = nlist; list; list = list->next)
|
||||
{
|
||||
w = list->word->word;
|
||||
|
||||
/* We have a word of the form [ind]=value */
|
||||
if ((list->word->flags & W_ASSIGNMENT) && w[0] == '[')
|
||||
{
|
||||
len = skipsubscript (w, 0);
|
||||
|
||||
#if 1
|
||||
/* XXX - changes for `+=' */
|
||||
if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
|
||||
#else
|
||||
if (w[len] != ']' || w[len+1] != '=')
|
||||
#endif
|
||||
{
|
||||
nval = make_variable_value (var, w, flags);
|
||||
if (var->assign_func)
|
||||
(*var->assign_func) (var, nval, last_ind);
|
||||
else
|
||||
array_insert (a, last_ind, nval);
|
||||
FREE (nval);
|
||||
last_ind++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len == 1)
|
||||
{
|
||||
err_badarraysub (w);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ALL_ELEMENT_SUB (w[1]) && len == 2)
|
||||
{
|
||||
report_error (_("%s: cannot assign to non-numeric index"), w);
|
||||
continue;
|
||||
}
|
||||
|
||||
ind = array_expand_index (w + 1, len);
|
||||
if (ind < 0)
|
||||
{
|
||||
err_badarraysub (w);
|
||||
continue;
|
||||
}
|
||||
last_ind = ind;
|
||||
/* XXX - changes for `+=' */
|
||||
if (w[len + 1] == '+' && w[len + 2] == '=')
|
||||
{
|
||||
flags |= ASS_APPEND;
|
||||
val = w + len + 3;
|
||||
}
|
||||
else
|
||||
val = w + len + 2;
|
||||
}
|
||||
else /* No [ind]=value, just a stray `=' */
|
||||
{
|
||||
ind = last_ind;
|
||||
val = w;
|
||||
}
|
||||
|
||||
if (integer_p (var))
|
||||
this_command_name = (char *)NULL; /* no command name for errors */
|
||||
bind_array_var_internal (var, ind, val, flags);
|
||||
last_ind++;
|
||||
}
|
||||
|
||||
dispose_words (nlist);
|
||||
return (var);
|
||||
}
|
||||
|
||||
/* For each word in a compound array assignment, if the word looks like
|
||||
[ind]=value, quote the `[' and `]' before the `=' to protect them from
|
||||
unwanted filename expansion. */
|
||||
static void
|
||||
quote_array_assignment_chars (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *s, *t, *nword;
|
||||
int saw_eq;
|
||||
WORD_LIST *l;
|
||||
|
||||
for (l = list; l; l = l->next)
|
||||
{
|
||||
if (l->word == 0 || l->word->word == 0 || l->word->word[0] == '\0')
|
||||
continue; /* should not happen, but just in case... */
|
||||
/* Don't bother if it doesn't look like [ind]=value */
|
||||
if (l->word->word[0] != '[' || xstrchr (l->word->word, '=') == 0) /* ] */
|
||||
continue;
|
||||
s = nword = (char *)xmalloc (strlen (l->word->word) * 2 + 1);
|
||||
saw_eq = 0;
|
||||
for (t = l->word->word; *t; )
|
||||
{
|
||||
if (*t == '=')
|
||||
saw_eq = 1;
|
||||
if (saw_eq == 0 && (*t == '[' || *t == ']'))
|
||||
*s++ = '\\';
|
||||
*s++ = *t++;
|
||||
}
|
||||
*s = '\0';
|
||||
free (l->word->word);
|
||||
l->word->word = nword;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function assumes s[i] == '['; returns with s[ret] == ']' if
|
||||
an array subscript is correctly parsed. */
|
||||
int
|
||||
skipsubscript (s, i)
|
||||
const char *s;
|
||||
int i;
|
||||
{
|
||||
int count, c;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mbstate_t state, state_bak;
|
||||
size_t slength, mblength;
|
||||
size_t mb_cur_max;
|
||||
#endif
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
memset (&state, '\0', sizeof (mbstate_t));
|
||||
slength = strlen (s + i);
|
||||
mb_cur_max = MB_CUR_MAX;
|
||||
#endif
|
||||
|
||||
count = 1;
|
||||
while (count)
|
||||
{
|
||||
/* Advance one (possibly multibyte) character in S starting at I. */
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (mb_cur_max > 1)
|
||||
{
|
||||
state_bak = state;
|
||||
mblength = mbrlen (s + i, slength, &state);
|
||||
|
||||
if (MB_INVALIDCH (mblength))
|
||||
{
|
||||
state = state_bak;
|
||||
i++;
|
||||
slength--;
|
||||
}
|
||||
else if (MB_NULLWCH (mblength))
|
||||
return i;
|
||||
else
|
||||
{
|
||||
i += mblength;
|
||||
slength -= mblength;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
++i;
|
||||
|
||||
c = s[i];
|
||||
|
||||
if (c == 0)
|
||||
break;
|
||||
else if (c == '[')
|
||||
count++;
|
||||
else if (c == ']')
|
||||
count--;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* This function is called with SUB pointing to just after the beginning
|
||||
`[' of an array subscript and removes the array element to which SUB
|
||||
expands from array VAR. A subscript of `*' or `@' unsets the array. */
|
||||
int
|
||||
unbind_array_element (var, sub)
|
||||
SHELL_VAR *var;
|
||||
char *sub;
|
||||
{
|
||||
int len;
|
||||
arrayind_t ind;
|
||||
ARRAY_ELEMENT *ae;
|
||||
|
||||
len = skipsubscript (sub, 0);
|
||||
if (sub[len] != ']' || len == 0)
|
||||
{
|
||||
builtin_error ("%s[%s: %s", var->name, sub, _(bash_badsub_errmsg));
|
||||
return -1;
|
||||
}
|
||||
sub[len] = '\0';
|
||||
|
||||
if (ALL_ELEMENT_SUB (sub[0]) && sub[1] == 0)
|
||||
{
|
||||
unbind_variable (var->name);
|
||||
return (0);
|
||||
}
|
||||
ind = array_expand_index (sub, len+1);
|
||||
if (ind < 0)
|
||||
{
|
||||
builtin_error ("[%s]: %s", sub, _(bash_badsub_errmsg));
|
||||
return -1;
|
||||
}
|
||||
ae = array_remove (array_cell (var), ind);
|
||||
if (ae)
|
||||
array_dispose_element (ae);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Format and output an array assignment in compound form VAR=(VALUES),
|
||||
suitable for re-use as input. */
|
||||
void
|
||||
print_array_assignment (var, quoted)
|
||||
SHELL_VAR *var;
|
||||
int quoted;
|
||||
{
|
||||
char *vstr;
|
||||
|
||||
vstr = array_to_assign (array_cell (var), quoted);
|
||||
|
||||
if (vstr == 0)
|
||||
printf ("%s=%s\n", var->name, quoted ? "'()'" : "()");
|
||||
else
|
||||
{
|
||||
printf ("%s=%s\n", var->name, vstr);
|
||||
free (vstr);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
/* */
|
||||
/* Utility functions to manage arrays and their contents for expansion */
|
||||
/* */
|
||||
/***********************************************************************/
|
||||
|
||||
/* Return 1 if NAME is a properly-formed array reference v[sub]. */
|
||||
int
|
||||
valid_array_reference (name)
|
||||
char *name;
|
||||
{
|
||||
char *t;
|
||||
int r, len;
|
||||
|
||||
t = xstrchr (name, '['); /* ] */
|
||||
if (t)
|
||||
{
|
||||
*t = '\0';
|
||||
r = legal_identifier (name);
|
||||
*t = '[';
|
||||
if (r == 0)
|
||||
return 0;
|
||||
/* Check for a properly-terminated non-blank subscript. */
|
||||
len = skipsubscript (t, 0);
|
||||
if (t[len] != ']' || len == 1)
|
||||
return 0;
|
||||
for (r = 1; r < len; r++)
|
||||
if (whitespace (t[r]) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Expand the array index beginning at S and extending LEN characters. */
|
||||
arrayind_t
|
||||
array_expand_index (s, len)
|
||||
char *s;
|
||||
int len;
|
||||
{
|
||||
char *exp, *t;
|
||||
int expok;
|
||||
arrayind_t val;
|
||||
|
||||
exp = (char *)xmalloc (len);
|
||||
strncpy (exp, s, len - 1);
|
||||
exp[len - 1] = '\0';
|
||||
t = expand_arith_string (exp);
|
||||
this_command_name = (char *)NULL;
|
||||
val = evalexp (t, &expok);
|
||||
free (t);
|
||||
free (exp);
|
||||
if (expok == 0)
|
||||
{
|
||||
last_command_exit_value = EXECUTION_FAILURE;
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Return the name of the variable specified by S without any subscript.
|
||||
If SUBP is non-null, return a pointer to the start of the subscript
|
||||
in *SUBP. If LENP is non-null, the length of the subscript is returned
|
||||
in *LENP. This returns newly-allocated memory. */
|
||||
char *
|
||||
array_variable_name (s, subp, lenp)
|
||||
char *s, **subp;
|
||||
int *lenp;
|
||||
{
|
||||
char *t, *ret;
|
||||
int ind, ni;
|
||||
|
||||
t = xstrchr (s, '[');
|
||||
if (t == 0)
|
||||
{
|
||||
if (subp)
|
||||
*subp = t;
|
||||
if (lenp)
|
||||
*lenp = 0;
|
||||
return ((char *)NULL);
|
||||
}
|
||||
ind = t - s;
|
||||
ni = skipsubscript (s, ind);
|
||||
if (ni <= ind + 1 || s[ni] != ']')
|
||||
{
|
||||
err_badarraysub (s);
|
||||
if (subp)
|
||||
*subp = t;
|
||||
if (lenp)
|
||||
*lenp = 0;
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
*t = '\0';
|
||||
ret = savestring (s);
|
||||
*t++ = '['; /* ] */
|
||||
|
||||
if (subp)
|
||||
*subp = t;
|
||||
if (lenp)
|
||||
*lenp = ni - ind;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the variable specified by S without any subscript. If SUBP is
|
||||
non-null, return a pointer to the start of the subscript in *SUBP.
|
||||
If LENP is non-null, the length of the subscript is returned in *LENP. */
|
||||
SHELL_VAR *
|
||||
array_variable_part (s, subp, lenp)
|
||||
char *s, **subp;
|
||||
int *lenp;
|
||||
{
|
||||
char *t;
|
||||
SHELL_VAR *var;
|
||||
|
||||
t = array_variable_name (s, subp, lenp);
|
||||
if (t == 0)
|
||||
return ((SHELL_VAR *)NULL);
|
||||
var = find_variable (t);
|
||||
|
||||
free (t);
|
||||
return (var == 0 || invisible_p (var)) ? (SHELL_VAR *)0 : var;
|
||||
}
|
||||
|
||||
/* Return a string containing the elements in the array and subscript
|
||||
described by S. If the subscript is * or @, obeys quoting rules akin
|
||||
to the expansion of $* and $@ including double quoting. If RTYPE
|
||||
is non-null it gets 1 if the array reference is name[@] or name[*]
|
||||
and 0 otherwise. */
|
||||
static char *
|
||||
array_value_internal (s, quoted, allow_all, rtype)
|
||||
char *s;
|
||||
int quoted, allow_all, *rtype;
|
||||
{
|
||||
int len;
|
||||
arrayind_t ind;
|
||||
char *retval, *t, *temp;
|
||||
WORD_LIST *l;
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = array_variable_part (s, &t, &len);
|
||||
|
||||
/* Expand the index, even if the variable doesn't exist, in case side
|
||||
effects are needed, like ${w[i++]} where w is unset. */
|
||||
#if 0
|
||||
if (var == 0)
|
||||
return (char *)NULL;
|
||||
#endif
|
||||
|
||||
if (len == 0)
|
||||
return ((char *)NULL); /* error message already printed */
|
||||
|
||||
/* [ */
|
||||
if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
|
||||
{
|
||||
if (rtype)
|
||||
*rtype = 1;
|
||||
if (allow_all == 0)
|
||||
{
|
||||
err_badarraysub (s);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
else if (var == 0 || value_cell (var) == 0)
|
||||
return ((char *)NULL);
|
||||
else if (array_p (var) == 0)
|
||||
l = add_string_to_list (value_cell (var), (WORD_LIST *)NULL);
|
||||
else
|
||||
{
|
||||
l = array_to_word_list (array_cell (var));
|
||||
if (l == (WORD_LIST *)NULL)
|
||||
return ((char *) NULL);
|
||||
}
|
||||
|
||||
if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
{
|
||||
temp = string_list_dollar_star (l);
|
||||
retval = quote_string (temp);
|
||||
free (temp);
|
||||
}
|
||||
else /* ${name[@]} or unquoted ${name[*]} */
|
||||
retval = string_list_dollar_at (l, quoted);
|
||||
|
||||
dispose_words (l);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rtype)
|
||||
*rtype = 0;
|
||||
ind = array_expand_index (t, len);
|
||||
if (ind < 0)
|
||||
{
|
||||
if (var)
|
||||
err_badarraysub (var->name);
|
||||
else
|
||||
{
|
||||
t[-1] = '\0';
|
||||
err_badarraysub (s);
|
||||
t[-1] = '['; /* ] */
|
||||
}
|
||||
return ((char *)NULL);
|
||||
}
|
||||
if (var == 0)
|
||||
return ((char *)NULL);
|
||||
if (array_p (var) == 0)
|
||||
return (ind == 0 ? value_cell (var) : (char *)NULL);
|
||||
retval = array_reference (array_cell (var), ind);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Return a string containing the elements described by the array and
|
||||
subscript contained in S, obeying quoting for subscripts * and @. */
|
||||
char *
|
||||
array_value (s, quoted, rtype)
|
||||
char *s;
|
||||
int quoted, *rtype;
|
||||
{
|
||||
return (array_value_internal (s, quoted, 1, rtype));
|
||||
}
|
||||
|
||||
/* Return the value of the array indexing expression S as a single string.
|
||||
If ALLOW_ALL is 0, do not allow `@' and `*' subscripts. This is used
|
||||
by other parts of the shell such as the arithmetic expression evaluator
|
||||
in expr.c. */
|
||||
char *
|
||||
get_array_value (s, allow_all, rtype)
|
||||
char *s;
|
||||
int allow_all, *rtype;
|
||||
{
|
||||
return (array_value_internal (s, 0, allow_all, rtype));
|
||||
}
|
||||
|
||||
char *
|
||||
array_keys (s, quoted)
|
||||
char *s;
|
||||
int quoted;
|
||||
{
|
||||
int len;
|
||||
char *retval, *t, *temp;
|
||||
WORD_LIST *l;
|
||||
SHELL_VAR *var;
|
||||
|
||||
var = array_variable_part (s, &t, &len);
|
||||
|
||||
/* [ */
|
||||
if (var == 0 || ALL_ELEMENT_SUB (t[0]) == 0 || t[1] != ']')
|
||||
return (char *)NULL;
|
||||
|
||||
if (array_p (var) == 0)
|
||||
l = add_string_to_list ("0", (WORD_LIST *)NULL);
|
||||
else
|
||||
{
|
||||
l = array_keys_to_word_list (array_cell (var));
|
||||
if (l == (WORD_LIST *)NULL)
|
||||
return ((char *) NULL);
|
||||
}
|
||||
|
||||
if (t[0] == '*' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
|
||||
{
|
||||
temp = string_list_dollar_star (l);
|
||||
retval = quote_string (temp);
|
||||
free (temp);
|
||||
}
|
||||
else /* ${!name[@]} or unquoted ${!name[*]} */
|
||||
retval = string_list_dollar_at (l, quoted);
|
||||
|
||||
dispose_words (l);
|
||||
return retval;
|
||||
}
|
||||
#endif /* ARRAY_VARS */
|
||||
@@ -1,5 +1,5 @@
|
||||
@%:@! /bin/sh
|
||||
@%:@ From configure.in for Bash 3.1, version 3.183.
|
||||
@%:@ From configure.in for Bash 3.2, version 3.186.
|
||||
@%:@ Guess values for system-dependent variables and create Makefiles.
|
||||
@%:@ Generated by GNU Autoconf 2.59 for bash 3.2-devel.
|
||||
@%:@
|
||||
@@ -312,7 +312,7 @@ ac_includes_default="\
|
||||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os EMACS lispdir DEBUGGER_START_FILE TESTSCRIPT PURIFY MALLOC_TARGET MALLOC_SRC MALLOC_LIB MALLOC_LIBRARY MALLOC_LDFLAGS MALLOC_DEP htmldir HELPDIR HELPDIRDEFINE HELPINSTALL HELPSTRINGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP CROSS_COMPILE SIGNAMES_H CC_FOR_BUILD STATIC_LD CFLAGS_FOR_BUILD CPPFLAGS_FOR_BUILD LDFLAGS_FOR_BUILD RL_VERSION RL_MAJOR RL_MINOR READLINE_LIB READLINE_DEP RL_LIBDIR RL_INCLUDEDIR RL_INCLUDE HISTORY_LIB HISTORY_DEP HIST_LIBDIR TILDE_LIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AR RANLIB ac_ct_RANLIB YACC SET_MAKE MAKE_SHELL SIZE MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE ALLOCA GLIBC21 LIBICONV LTLIBICONV INTLBISON BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT DATADIRNAME INSTOBJEXT GENCAT INTLOBJS INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB LIB@&t@OBJS INTL_DEP INTL_INC LIBINTL_H SIGLIST_O TERMCAP_LIB TERMCAP_DEP JOBS_O SHOBJ_CC SHOBJ_CFLAGS SHOBJ_LD SHOBJ_LDFLAGS SHOBJ_XLDFLAGS SHOBJ_LIBS SHOBJ_STATUS PROFILE_FLAGS incdir BUILD_DIR ARFLAGS BASHVERS RELSTATUS DEBUG MALLOC_DEBUG LOCAL_LIBS LOCAL_CFLAGS LOCAL_LDFLAGS LOCAL_DEFS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os EMACS lispdir DEBUGGER_START_FILE TESTSCRIPT PURIFY MALLOC_TARGET MALLOC_SRC MALLOC_LIB MALLOC_LIBRARY MALLOC_LDFLAGS MALLOC_DEP htmldir HELPDIR HELPDIRDEFINE HELPINSTALL HELPSTRINGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP CROSS_COMPILE SIGNAMES_H SIGNAMES_O CC_FOR_BUILD STATIC_LD CFLAGS_FOR_BUILD CPPFLAGS_FOR_BUILD LDFLAGS_FOR_BUILD RL_VERSION RL_MAJOR RL_MINOR READLINE_LIB READLINE_DEP RL_LIBDIR RL_INCLUDEDIR RL_INCLUDE HISTORY_LIB HISTORY_DEP HIST_LIBDIR TILDE_LIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AR RANLIB ac_ct_RANLIB YACC SET_MAKE MAKE_SHELL SIZE MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE ALLOCA GLIBC21 LIBICONV LTLIBICONV INTLBISON BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT DATADIRNAME INSTOBJEXT GENCAT INTLOBJS INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB LIB@&t@OBJS INTL_DEP INTL_INC LIBINTL_H SIGLIST_O TERMCAP_LIB TERMCAP_DEP JOBS_O SHOBJ_CC SHOBJ_CFLAGS SHOBJ_LD SHOBJ_LDFLAGS SHOBJ_XLDFLAGS SHOBJ_LIBS SHOBJ_STATUS PROFILE_FLAGS incdir BUILD_DIR ARFLAGS BASHVERS RELSTATUS DEBUG MALLOC_DEBUG LOCAL_LIBS LOCAL_CFLAGS LOCAL_LDFLAGS LOCAL_DEFS LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
@@ -4113,6 +4113,7 @@ fi
|
||||
|
||||
|
||||
|
||||
SIGNAMES_O=
|
||||
SIGNAMES_H=lsignames.h
|
||||
|
||||
|
||||
@@ -4121,14 +4122,12 @@ if test "x$cross_compiling" = "xyes"; then
|
||||
case "${host}" in
|
||||
*-cygwin*)
|
||||
cross_cache=${srcdir}/cross-build/cygwin32.cache
|
||||
SIGNAMES_H='$(srcdir)/cross-build/win32sig.h'
|
||||
;;
|
||||
*-mingw*)
|
||||
cross_cache=${srcdir}/cross-build/cygwin32.cache
|
||||
;;
|
||||
i[3456]86-*-beos*)
|
||||
cross_cache=${srcdir}/cross-build/x86-beos.cache
|
||||
SIGNAMES_H='${srcdir}/cross-build/beos-sig.h'
|
||||
;;
|
||||
*) echo "configure: cross-compiling for $host is not supported" >&2
|
||||
;;
|
||||
@@ -4138,11 +4137,13 @@ if test "x$cross_compiling" = "xyes"; then
|
||||
. ${cross_cache}
|
||||
fi
|
||||
unset cross_cache
|
||||
SIGNAMES_O='signames.o'
|
||||
CROSS_COMPILE='-DCROSS_COMPILING'
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test -z "$CC_FOR_BUILD"; then
|
||||
if test "x$cross_compiling" = "xno"; then
|
||||
CC_FOR_BUILD='$(CC)'
|
||||
@@ -27626,6 +27627,7 @@ s,@CPP@,$CPP,;t t
|
||||
s,@EGREP@,$EGREP,;t t
|
||||
s,@CROSS_COMPILE@,$CROSS_COMPILE,;t t
|
||||
s,@SIGNAMES_H@,$SIGNAMES_H,;t t
|
||||
s,@SIGNAMES_O@,$SIGNAMES_O,;t t
|
||||
s,@CC_FOR_BUILD@,$CC_FOR_BUILD,;t t
|
||||
s,@STATIC_LD@,$STATIC_LD,;t t
|
||||
s,@CFLAGS_FOR_BUILD@,$CFLAGS_FOR_BUILD,;t t
|
||||
|
||||
+866
-865
File diff suppressed because it is too large
Load Diff
@@ -270,6 +270,9 @@ load_history ()
|
||||
Note that the history file is automatically truncated to the
|
||||
size of HISTSIZE if the user does not explicitly set the size
|
||||
differently. */
|
||||
set_if_not ("HISTSIZE", "500");
|
||||
sv_histsize ("HISTSIZE");
|
||||
|
||||
set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
|
||||
sv_histsize ("HISTFILESIZE");
|
||||
|
||||
|
||||
+820
@@ -0,0 +1,820 @@
|
||||
/* bashhist.c -- bash interface to the GNU history library. */
|
||||
|
||||
/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#if defined (HISTORY)
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
# include <sys/types.h>
|
||||
# endif
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "bashtypes.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include "bashansi.h"
|
||||
#include "posixstat.h"
|
||||
#include "filecntl.h"
|
||||
|
||||
#include "bashintl.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include "flags.h"
|
||||
#include "input.h"
|
||||
#include "parser.h" /* for the struct dstack stuff. */
|
||||
#include "pathexp.h" /* for the struct ignorevar stuff */
|
||||
#include "bashhist.h" /* matching prototypes and declarations */
|
||||
#include "builtins/common.h"
|
||||
|
||||
#include <readline/history.h>
|
||||
#include <glob/glob.h>
|
||||
#include <glob/strmatch.h>
|
||||
|
||||
#if defined (READLINE)
|
||||
# include "bashline.h"
|
||||
extern int rl_done, rl_dispatching; /* should really include readline.h */
|
||||
#endif
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
static int histignore_item_func __P((struct ign *));
|
||||
static int check_history_control __P((char *));
|
||||
static void hc_erasedups __P((char *));
|
||||
static void really_add_history __P((char *));
|
||||
|
||||
static struct ignorevar histignore =
|
||||
{
|
||||
"HISTIGNORE",
|
||||
(struct ign *)0,
|
||||
0,
|
||||
(char *)0,
|
||||
(sh_iv_item_func_t *)histignore_item_func,
|
||||
};
|
||||
|
||||
#define HIGN_EXPAND 0x01
|
||||
|
||||
/* Declarations of bash history variables. */
|
||||
/* Non-zero means to remember lines typed to the shell on the history
|
||||
list. This is different than the user-controlled behaviour; this
|
||||
becomes zero when we read lines from a file, for example. */
|
||||
int remember_on_history = 1;
|
||||
|
||||
/* The number of lines that Bash has added to this history session. The
|
||||
difference between the number of the top element in the history list
|
||||
(offset from history_base) and the number of lines in the history file.
|
||||
Appending this session's history to the history file resets this to 0. */
|
||||
int history_lines_this_session;
|
||||
|
||||
/* The number of lines that Bash has read from the history file. */
|
||||
int history_lines_in_file;
|
||||
|
||||
#if defined (BANG_HISTORY)
|
||||
/* Non-zero means do no history expansion on this line, regardless
|
||||
of what history_expansion says. */
|
||||
int history_expansion_inhibited;
|
||||
#endif
|
||||
|
||||
/* With the old default, every line was saved in the history individually.
|
||||
I.e., if the user enters:
|
||||
bash$ for i in a b c
|
||||
> do
|
||||
> echo $i
|
||||
> done
|
||||
Each line will be individually saved in the history.
|
||||
bash$ history
|
||||
10 for i in a b c
|
||||
11 do
|
||||
12 echo $i
|
||||
13 done
|
||||
14 history
|
||||
If the variable command_oriented_history is set, multiple lines
|
||||
which form one command will be saved as one history entry.
|
||||
bash$ for i in a b c
|
||||
> do
|
||||
> echo $i
|
||||
> done
|
||||
bash$ history
|
||||
10 for i in a b c
|
||||
do
|
||||
echo $i
|
||||
done
|
||||
11 history
|
||||
The user can then recall the whole command all at once instead
|
||||
of just being able to recall one line at a time.
|
||||
|
||||
This is now enabled by default.
|
||||
*/
|
||||
int command_oriented_history = 1;
|
||||
|
||||
/* Set to 1 if the first line of a possibly-multi-line command was saved
|
||||
in the history list. Managed by maybe_add_history(), but global so
|
||||
the history-manipluating builtins can see it. */
|
||||
int current_command_first_line_saved = 0;
|
||||
|
||||
/* Non-zero means to store newlines in the history list when using
|
||||
command_oriented_history rather than trying to use semicolons. */
|
||||
int literal_history;
|
||||
|
||||
/* Non-zero means to append the history to the history file at shell
|
||||
exit, even if the history has been stifled. */
|
||||
int force_append_history;
|
||||
|
||||
/* A nit for picking at history saving. Flags have the following values:
|
||||
|
||||
Value == 0 means save all lines parsed by the shell on the history.
|
||||
Value & HC_IGNSPACE means save all lines that do not start with a space.
|
||||
Value & HC_IGNDUPS means save all lines that do not match the last
|
||||
line saved.
|
||||
Value & HC_ERASEDUPS means to remove all other matching lines from the
|
||||
history list before saving the latest line. */
|
||||
int history_control;
|
||||
|
||||
/* Set to 1 if the last command was added to the history list successfully
|
||||
as a separate history entry; set to 0 if the line was ignored or added
|
||||
to a previous entry as part of command-oriented-history processing. */
|
||||
int hist_last_line_added;
|
||||
|
||||
/* Set to 1 if builtins/history.def:push_history added the last history
|
||||
entry. */
|
||||
int hist_last_line_pushed;
|
||||
|
||||
#if defined (READLINE)
|
||||
/* If non-zero, and readline is being used, the user is offered the
|
||||
chance to re-edit a failed history expansion. */
|
||||
int history_reediting;
|
||||
|
||||
/* If non-zero, and readline is being used, don't directly execute a
|
||||
line with history substitution. Reload it into the editing buffer
|
||||
instead and let the user further edit and confirm with a newline. */
|
||||
int hist_verify;
|
||||
|
||||
#endif /* READLINE */
|
||||
|
||||
/* Non-zero means to not save function definitions in the history list. */
|
||||
int dont_save_function_defs;
|
||||
|
||||
/* Variables declared in other files used here. */
|
||||
extern int current_command_line_count;
|
||||
|
||||
extern struct dstack dstack;
|
||||
|
||||
static int bash_history_inhibit_expansion __P((char *, int));
|
||||
#if defined (READLINE)
|
||||
static void re_edit __P((char *));
|
||||
#endif
|
||||
static int history_expansion_p __P((char *));
|
||||
static int shell_comment __P((char *));
|
||||
static int should_expand __P((char *));
|
||||
static HIST_ENTRY *last_history_entry __P((void));
|
||||
static char *expand_histignore_pattern __P((char *));
|
||||
static int history_should_ignore __P((char *));
|
||||
|
||||
/* Is the history expansion starting at string[i] one that should not
|
||||
be expanded? */
|
||||
static int
|
||||
bash_history_inhibit_expansion (string, i)
|
||||
char *string;
|
||||
int i;
|
||||
{
|
||||
/* The shell uses ! as a pattern negation character in globbing [...]
|
||||
expressions, so let those pass without expansion. */
|
||||
if (i > 0 && (string[i - 1] == '[') && member (']', string + i + 1))
|
||||
return (1);
|
||||
/* The shell uses ! as the indirect expansion character, so let those
|
||||
expansions pass as well. */
|
||||
else if (i > 1 && string[i - 1] == '{' && string[i - 2] == '$' &&
|
||||
member ('}', string + i + 1))
|
||||
return (1);
|
||||
#if defined (EXTENDED_GLOB)
|
||||
else if (extended_glob && i > 1 && string[i+1] == '(' && member (')', string + i + 2))
|
||||
return (1);
|
||||
#endif
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
bash_initialize_history ()
|
||||
{
|
||||
history_quotes_inhibit_expansion = 1;
|
||||
history_search_delimiter_chars = ";&()|<>";
|
||||
history_inhibit_expansion_function = bash_history_inhibit_expansion;
|
||||
#if defined (BANG_HISTORY)
|
||||
sv_histchars ("histchars");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
bash_history_reinit (interact)
|
||||
int interact;
|
||||
{
|
||||
#if defined (BANG_HISTORY)
|
||||
history_expansion = interact != 0;
|
||||
history_expansion_inhibited = 1;
|
||||
#endif
|
||||
remember_on_history = interact != 0;
|
||||
history_inhibit_expansion_function = bash_history_inhibit_expansion;
|
||||
}
|
||||
|
||||
void
|
||||
bash_history_disable ()
|
||||
{
|
||||
remember_on_history = 0;
|
||||
#if defined (BANG_HISTORY)
|
||||
history_expansion_inhibited = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
bash_history_enable ()
|
||||
{
|
||||
remember_on_history = 1;
|
||||
#if defined (BANG_HISTORY)
|
||||
history_expansion_inhibited = 0;
|
||||
#endif
|
||||
history_inhibit_expansion_function = bash_history_inhibit_expansion;
|
||||
sv_history_control ("HISTCONTROL");
|
||||
sv_histignore ("HISTIGNORE");
|
||||
}
|
||||
|
||||
/* Load the history list from the history file. */
|
||||
void
|
||||
load_history ()
|
||||
{
|
||||
char *hf;
|
||||
struct stat buf;
|
||||
|
||||
/* Truncate history file for interactive shells which desire it.
|
||||
Note that the history file is automatically truncated to the
|
||||
size of HISTSIZE if the user does not explicitly set the size
|
||||
differently. */
|
||||
set_if_not ("HISTFILESIZE", get_string_value ("HISTSIZE"));
|
||||
sv_histsize ("HISTFILESIZE");
|
||||
|
||||
/* Read the history in HISTFILE into the history list. */
|
||||
hf = get_string_value ("HISTFILE");
|
||||
|
||||
if (hf && *hf && stat (hf, &buf) == 0)
|
||||
{
|
||||
read_history (hf);
|
||||
using_history ();
|
||||
history_lines_in_file = where_history ();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/* Write the existing history out to the history file. */
|
||||
void
|
||||
save_history ()
|
||||
{
|
||||
char *hf;
|
||||
struct stat buf;
|
||||
|
||||
hf = get_string_value ("HISTFILE");
|
||||
if (hf && *hf && stat (hf, &buf) == 0)
|
||||
{
|
||||
/* Append only the lines that occurred this session to
|
||||
the history file. */
|
||||
using_history ();
|
||||
|
||||
if (history_lines_this_session < where_history () || force_append_history)
|
||||
append_history (history_lines_this_session, hf);
|
||||
else
|
||||
write_history (hf);
|
||||
|
||||
sv_histsize ("HISTFILESIZE");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
maybe_append_history (filename)
|
||||
char *filename;
|
||||
{
|
||||
int fd, result;
|
||||
struct stat buf;
|
||||
|
||||
result = EXECUTION_SUCCESS;
|
||||
if (history_lines_this_session && (history_lines_this_session < where_history ()))
|
||||
{
|
||||
/* If the filename was supplied, then create it if necessary. */
|
||||
if (stat (filename, &buf) == -1 && errno == ENOENT)
|
||||
{
|
||||
fd = open (filename, O_WRONLY|O_CREAT, 0600);
|
||||
if (fd < 0)
|
||||
{
|
||||
builtin_error (_("%s: cannot create: %s"), filename, strerror (errno));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
result = append_history (history_lines_this_session, filename);
|
||||
history_lines_in_file += history_lines_this_session;
|
||||
history_lines_this_session = 0;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* If this is an interactive shell, then append the lines executed
|
||||
this session to the history file. */
|
||||
int
|
||||
maybe_save_shell_history ()
|
||||
{
|
||||
int result;
|
||||
char *hf;
|
||||
struct stat buf;
|
||||
|
||||
result = 0;
|
||||
if (history_lines_this_session)
|
||||
{
|
||||
hf = get_string_value ("HISTFILE");
|
||||
|
||||
if (hf && *hf)
|
||||
{
|
||||
/* If the file doesn't exist, then create it. */
|
||||
if (stat (hf, &buf) == -1)
|
||||
{
|
||||
int file;
|
||||
file = open (hf, O_CREAT | O_TRUNC | O_WRONLY, 0600);
|
||||
if (file != -1)
|
||||
close (file);
|
||||
}
|
||||
|
||||
/* Now actually append the lines if the history hasn't been
|
||||
stifled. If the history has been stifled, rewrite the
|
||||
history file. */
|
||||
using_history ();
|
||||
if (history_lines_this_session <= where_history () || force_append_history)
|
||||
{
|
||||
result = append_history (history_lines_this_session, hf);
|
||||
history_lines_in_file += history_lines_this_session;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = write_history (hf);
|
||||
history_lines_in_file = history_lines_this_session;
|
||||
}
|
||||
history_lines_this_session = 0;
|
||||
|
||||
sv_histsize ("HISTFILESIZE");
|
||||
}
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
/* Tell readline () that we have some text for it to edit. */
|
||||
static void
|
||||
re_edit (text)
|
||||
char *text;
|
||||
{
|
||||
if (bash_input.type == st_stdin)
|
||||
bash_re_edit (text);
|
||||
}
|
||||
#endif /* READLINE */
|
||||
|
||||
/* Return 1 if this line needs history expansion. */
|
||||
static int
|
||||
history_expansion_p (line)
|
||||
char *line;
|
||||
{
|
||||
register char *s;
|
||||
|
||||
for (s = line; *s; s++)
|
||||
if (*s == history_expansion_char || *s == history_subst_char)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Do pre-processing on LINE. If PRINT_CHANGES is non-zero, then
|
||||
print the results of expanding the line if there were any changes.
|
||||
If there is an error, return NULL, otherwise the expanded line is
|
||||
returned. If ADDIT is non-zero the line is added to the history
|
||||
list after history expansion. ADDIT is just a suggestion;
|
||||
REMEMBER_ON_HISTORY can veto, and does.
|
||||
Right now this does history expansion. */
|
||||
char *
|
||||
pre_process_line (line, print_changes, addit)
|
||||
char *line;
|
||||
int print_changes, addit;
|
||||
{
|
||||
char *history_value;
|
||||
char *return_value;
|
||||
int expanded;
|
||||
|
||||
return_value = line;
|
||||
expanded = 0;
|
||||
|
||||
# if defined (BANG_HISTORY)
|
||||
/* History expand the line. If this results in no errors, then
|
||||
add that line to the history if ADDIT is non-zero. */
|
||||
if (!history_expansion_inhibited && history_expansion && history_expansion_p (line))
|
||||
{
|
||||
expanded = history_expand (line, &history_value);
|
||||
|
||||
if (expanded)
|
||||
{
|
||||
if (print_changes)
|
||||
{
|
||||
if (expanded < 0)
|
||||
internal_error ("%s", history_value);
|
||||
#if defined (READLINE)
|
||||
else if (hist_verify == 0 || expanded == 2)
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
fprintf (stderr, "%s\n", history_value);
|
||||
}
|
||||
|
||||
/* If there was an error, return NULL. */
|
||||
if (expanded < 0 || expanded == 2) /* 2 == print only */
|
||||
{
|
||||
# if defined (READLINE)
|
||||
if (expanded == 2 && rl_dispatching == 0 && *history_value)
|
||||
# else
|
||||
if (expanded == 2 && *history_value)
|
||||
# endif /* !READLINE */
|
||||
maybe_add_history (history_value);
|
||||
|
||||
free (history_value);
|
||||
|
||||
# if defined (READLINE)
|
||||
/* New hack. We can allow the user to edit the
|
||||
failed history expansion. */
|
||||
if (history_reediting && expanded < 0 && rl_done)
|
||||
re_edit (line);
|
||||
# endif /* READLINE */
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
# if defined (READLINE)
|
||||
if (hist_verify && expanded == 1)
|
||||
{
|
||||
re_edit (history_value);
|
||||
return ((char *)NULL);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Let other expansions know that return_value can be free'ed,
|
||||
and that a line has been added to the history list. Note
|
||||
that we only add lines that have something in them. */
|
||||
expanded = 1;
|
||||
return_value = history_value;
|
||||
}
|
||||
# endif /* BANG_HISTORY */
|
||||
|
||||
if (addit && remember_on_history && *return_value)
|
||||
maybe_add_history (return_value);
|
||||
|
||||
#if 0
|
||||
if (expanded == 0)
|
||||
return_value = savestring (line);
|
||||
#endif
|
||||
|
||||
return (return_value);
|
||||
}
|
||||
|
||||
/* Return 1 if the first non-whitespace character in LINE is a `#', indicating
|
||||
* that the line is a shell comment. */
|
||||
static int
|
||||
shell_comment (line)
|
||||
char *line;
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = line; p && *p && whitespace (*p); p++)
|
||||
;
|
||||
return (p && *p == '#');
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/* Remove shell comments from LINE. A `#' and anything after it is a comment.
|
||||
This isn't really useful yet, since it doesn't handle quoting. */
|
||||
static char *
|
||||
filter_comments (line)
|
||||
char *line;
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = line; p && *p && *p != '#'; p++)
|
||||
;
|
||||
if (p && *p == '#')
|
||||
*p = '\0';
|
||||
return (line);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check LINE against what HISTCONTROL says to do. Returns 1 if the line
|
||||
should be saved; 0 if it should be discarded. */
|
||||
static int
|
||||
check_history_control (line)
|
||||
char *line;
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
int r;
|
||||
|
||||
if (history_control == 0)
|
||||
return 1;
|
||||
|
||||
/* ignorespace or ignoreboth */
|
||||
if ((history_control & HC_IGNSPACE) && *line == ' ')
|
||||
return 0;
|
||||
|
||||
/* ignoredups or ignoreboth */
|
||||
if (history_control & HC_IGNDUPS)
|
||||
{
|
||||
using_history ();
|
||||
temp = previous_history ();
|
||||
|
||||
r = (temp == 0 || STREQ (temp->line, line) == 0);
|
||||
|
||||
using_history ();
|
||||
|
||||
if (r == 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Remove all entries matching LINE from the history list. Triggered when
|
||||
HISTCONTROL includes `erasedups'. */
|
||||
static void
|
||||
hc_erasedups (line)
|
||||
char *line;
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
int r;
|
||||
|
||||
using_history ();
|
||||
while (temp = previous_history ())
|
||||
{
|
||||
if (STREQ (temp->line, line))
|
||||
{
|
||||
r = where_history ();
|
||||
remove_history (r);
|
||||
}
|
||||
}
|
||||
using_history ();
|
||||
}
|
||||
|
||||
/* Add LINE to the history list, handling possibly multi-line compound
|
||||
commands. We note whether or not we save the first line of each command
|
||||
(which is usually the entire command and history entry), and don't add
|
||||
the second and subsequent lines of a multi-line compound command if we
|
||||
didn't save the first line. We don't usually save shell comment lines in
|
||||
compound commands in the history, because they could have the effect of
|
||||
commenting out the rest of the command when the entire command is saved as
|
||||
a single history entry (when COMMAND_ORIENTED_HISTORY is enabled). If
|
||||
LITERAL_HISTORY is set, we're saving lines in the history with embedded
|
||||
newlines, so it's OK to save comment lines. We also make sure to save
|
||||
multiple-line quoted strings or other constructs. */
|
||||
void
|
||||
maybe_add_history (line)
|
||||
char *line;
|
||||
{
|
||||
hist_last_line_added = 0;
|
||||
|
||||
/* Don't use the value of history_control to affect the second
|
||||
and subsequent lines of a multi-line command (old code did
|
||||
this only when command_oriented_history is enabled). */
|
||||
if (current_command_line_count > 1)
|
||||
{
|
||||
if (current_command_first_line_saved &&
|
||||
(literal_history || dstack.delimiter_depth != 0 || shell_comment (line) == 0))
|
||||
bash_add_history (line);
|
||||
return;
|
||||
}
|
||||
|
||||
/* This is the first line of a (possible multi-line) command. Note whether
|
||||
or not we should save the first line and remember it. */
|
||||
current_command_first_line_saved = check_add_history (line, 0);
|
||||
}
|
||||
|
||||
/* Just check LINE against HISTCONTROL and HISTIGNORE and add it to the
|
||||
history if it's OK. Used by `history -s' as well as maybe_add_history().
|
||||
Returns 1 if the line was saved in the history, 0 otherwise. */
|
||||
int
|
||||
check_add_history (line, force)
|
||||
char *line;
|
||||
int force;
|
||||
{
|
||||
if (check_history_control (line) && history_should_ignore (line) == 0)
|
||||
{
|
||||
/* We're committed to saving the line. If the user has requested it,
|
||||
remove other matching lines from the history. */
|
||||
if (history_control & HC_ERASEDUPS)
|
||||
hc_erasedups (line);
|
||||
|
||||
if (force)
|
||||
{
|
||||
really_add_history (line);
|
||||
using_history ();
|
||||
}
|
||||
else
|
||||
bash_add_history (line);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add a line to the history list.
|
||||
The variable COMMAND_ORIENTED_HISTORY controls the style of history
|
||||
remembering; when non-zero, and LINE is not the first line of a
|
||||
complete parser construct, append LINE to the last history line instead
|
||||
of adding it as a new line. */
|
||||
void
|
||||
bash_add_history (line)
|
||||
char *line;
|
||||
{
|
||||
int add_it, offset, curlen;
|
||||
HIST_ENTRY *current, *old;
|
||||
char *chars_to_add, *new_line;
|
||||
|
||||
add_it = 1;
|
||||
if (command_oriented_history && current_command_line_count > 1)
|
||||
{
|
||||
chars_to_add = literal_history ? "\n" : history_delimiting_chars ();
|
||||
|
||||
using_history ();
|
||||
current = previous_history ();
|
||||
|
||||
if (current)
|
||||
{
|
||||
/* If the previous line ended with an escaped newline (escaped
|
||||
with backslash, but otherwise unquoted), then remove the quoted
|
||||
newline, since that is what happens when the line is parsed. */
|
||||
curlen = strlen (current->line);
|
||||
|
||||
if (dstack.delimiter_depth == 0 && current->line[curlen - 1] == '\\' &&
|
||||
current->line[curlen - 2] != '\\')
|
||||
{
|
||||
current->line[curlen - 1] = '\0';
|
||||
curlen--;
|
||||
chars_to_add = "";
|
||||
}
|
||||
|
||||
new_line = (char *)xmalloc (1
|
||||
+ curlen
|
||||
+ strlen (line)
|
||||
+ strlen (chars_to_add));
|
||||
sprintf (new_line, "%s%s%s", current->line, chars_to_add, line);
|
||||
offset = where_history ();
|
||||
old = replace_history_entry (offset, new_line, current->data);
|
||||
free (new_line);
|
||||
|
||||
if (old)
|
||||
free_history_entry (old);
|
||||
|
||||
add_it = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (add_it)
|
||||
really_add_history (line);
|
||||
|
||||
using_history ();
|
||||
}
|
||||
|
||||
static void
|
||||
really_add_history (line)
|
||||
char *line;
|
||||
{
|
||||
hist_last_line_added = 1;
|
||||
hist_last_line_pushed = 0;
|
||||
add_history (line);
|
||||
history_lines_this_session++;
|
||||
}
|
||||
|
||||
int
|
||||
history_number ()
|
||||
{
|
||||
using_history ();
|
||||
return (remember_on_history ? history_base + where_history () : 1);
|
||||
}
|
||||
|
||||
static int
|
||||
should_expand (s)
|
||||
char *s;
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (p = s; p && *p; p++)
|
||||
{
|
||||
if (*p == '\\')
|
||||
p++;
|
||||
else if (*p == '&')
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
histignore_item_func (ign)
|
||||
struct ign *ign;
|
||||
{
|
||||
if (should_expand (ign->val))
|
||||
ign->flags |= HIGN_EXPAND;
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
setup_history_ignore (varname)
|
||||
char *varname;
|
||||
{
|
||||
setup_ignore_patterns (&histignore);
|
||||
}
|
||||
|
||||
static HIST_ENTRY *
|
||||
last_history_entry ()
|
||||
{
|
||||
HIST_ENTRY *he;
|
||||
|
||||
using_history ();
|
||||
he = previous_history ();
|
||||
using_history ();
|
||||
return he;
|
||||
}
|
||||
|
||||
char *
|
||||
last_history_line ()
|
||||
{
|
||||
HIST_ENTRY *he;
|
||||
|
||||
he = last_history_entry ();
|
||||
if (he == 0)
|
||||
return ((char *)NULL);
|
||||
return he->line;
|
||||
}
|
||||
|
||||
static char *
|
||||
expand_histignore_pattern (pat)
|
||||
char *pat;
|
||||
{
|
||||
HIST_ENTRY *phe;
|
||||
char *ret;
|
||||
|
||||
phe = last_history_entry ();
|
||||
|
||||
if (phe == (HIST_ENTRY *)0)
|
||||
return (savestring (pat));
|
||||
|
||||
ret = strcreplace (pat, '&', phe->line, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return 1 if we should not put LINE into the history according to the
|
||||
patterns in HISTIGNORE. */
|
||||
static int
|
||||
history_should_ignore (line)
|
||||
char *line;
|
||||
{
|
||||
register int i, match;
|
||||
char *npat;
|
||||
|
||||
if (histignore.num_ignores == 0)
|
||||
return 0;
|
||||
|
||||
for (i = match = 0; i < histignore.num_ignores; i++)
|
||||
{
|
||||
if (histignore.ignores[i].flags & HIGN_EXPAND)
|
||||
npat = expand_histignore_pattern (histignore.ignores[i].val);
|
||||
else
|
||||
npat = histignore.ignores[i].val;
|
||||
|
||||
match = strmatch (npat, line, FNMATCH_EXTFLAG) != FNM_NOMATCH;
|
||||
|
||||
if (histignore.ignores[i].flags & HIGN_EXPAND)
|
||||
free (npat);
|
||||
|
||||
if (match)
|
||||
break;
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
#endif /* HISTORY */
|
||||
+12
-2
@@ -1,7 +1,7 @@
|
||||
/* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
|
||||
a single source file called builtins.def. */
|
||||
|
||||
/* Copyright (C) 1987-2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -19,7 +19,17 @@ You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include <config.h>
|
||||
/* #if !defined (CROSS_COMPILING) */
|
||||
#if 0
|
||||
# include <config.h>
|
||||
#else /* CROSS_COMPILING */
|
||||
/* A conservative set of defines based on POSIX/SUS3/XPG6 */
|
||||
# define HAVE_UNISTD_H
|
||||
# define HAVE_STRING_H
|
||||
# define HAVE_STDLIB_H
|
||||
|
||||
# define HAVE_RENAME
|
||||
#endif /* CROSS_COMPILING */
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# ifdef _MINIX
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+15
-1
@@ -90,6 +90,7 @@ extern int errno;
|
||||
extern int interrupt_immediately;
|
||||
|
||||
#if defined (READLINE)
|
||||
static void reset_attempted_completion_function __P((char *));
|
||||
static char *edit_line __P((char *));
|
||||
static void set_eol_delim __P((int));
|
||||
static void reset_eol_delim __P((char *));
|
||||
@@ -330,6 +331,8 @@ read_builtin (list)
|
||||
}
|
||||
old_alrm = set_signal_handler (SIGALRM, sigalrm);
|
||||
add_unwind_protect (reset_alarm, (char *)NULL);
|
||||
if (edit)
|
||||
add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
|
||||
alarm (tmout);
|
||||
}
|
||||
|
||||
@@ -692,7 +695,15 @@ bind_read_variable (name, value)
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
static rl_completion_func_t *old_attempted_completion_function;
|
||||
static rl_completion_func_t *old_attempted_completion_function = 0;
|
||||
|
||||
static void
|
||||
reset_attempted_completion_function (cp)
|
||||
char *cp;
|
||||
{
|
||||
if (rl_attempted_completion_function == 0 && old_attempted_completion_function)
|
||||
rl_attempted_completion_function = old_attempted_completion_function;
|
||||
}
|
||||
|
||||
static char *
|
||||
edit_line (p)
|
||||
@@ -703,10 +714,13 @@ edit_line (p)
|
||||
|
||||
if (bash_readline_initialized == 0)
|
||||
initialize_readline ();
|
||||
|
||||
old_attempted_completion_function = rl_attempted_completion_function;
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
ret = readline (p);
|
||||
rl_attempted_completion_function = old_attempted_completion_function;
|
||||
old_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
len = strlen (ret);
|
||||
|
||||
+20
-2
@@ -90,6 +90,7 @@ extern int errno;
|
||||
extern int interrupt_immediately;
|
||||
|
||||
#if defined (READLINE)
|
||||
static void reset_attempted_completion_function __P((char *));
|
||||
static char *edit_line __P((char *));
|
||||
static void set_eol_delim __P((int));
|
||||
static void reset_eol_delim __P((char *));
|
||||
@@ -330,6 +331,8 @@ read_builtin (list)
|
||||
}
|
||||
old_alrm = set_signal_handler (SIGALRM, sigalrm);
|
||||
add_unwind_protect (reset_alarm, (char *)NULL);
|
||||
if (edit)
|
||||
add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
|
||||
alarm (tmout);
|
||||
}
|
||||
|
||||
@@ -472,6 +475,7 @@ add_char:
|
||||
if (retval < 0)
|
||||
{
|
||||
builtin_error (_("read error: %d: %s"), fd, strerror (errno));
|
||||
run_unwind_frame ("read_builtin");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
#endif
|
||||
@@ -519,7 +523,10 @@ add_char:
|
||||
|
||||
var = find_or_make_array_variable (arrayname, 1);
|
||||
if (var == 0)
|
||||
return EXECUTION_FAILURE; /* readonly or noassign */
|
||||
{
|
||||
xfree (input_string);
|
||||
return EXECUTION_FAILURE; /* readonly or noassign */
|
||||
}
|
||||
array_flush (array_cell (var));
|
||||
|
||||
alist = list_string (input_string, ifs_chars, 0);
|
||||
@@ -688,7 +695,17 @@ bind_read_variable (name, value)
|
||||
}
|
||||
|
||||
#if defined (READLINE)
|
||||
static rl_completion_func_t *old_attempted_completion_function;
|
||||
static rl_completion_func_t *old_attempted_completion_function = 0;
|
||||
|
||||
static void
|
||||
reset_attempted_completion_function (cp)
|
||||
char *cp;
|
||||
{
|
||||
if (rl_attempted_completion_function == 0)
|
||||
rl_attempted_completion_function = old_attempted_completion_function ?
|
||||
old_attempted_completion_function :
|
||||
attempt_shell_completion;
|
||||
}
|
||||
|
||||
static char *
|
||||
edit_line (p)
|
||||
@@ -703,6 +720,7 @@ edit_line (p)
|
||||
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
|
||||
ret = readline (p);
|
||||
rl_attempted_completion_function = old_attempted_completion_function;
|
||||
old_attempted_completion_function = 0;
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
len = strlen (ret);
|
||||
|
||||
@@ -34,6 +34,7 @@ option is given, it is interpreted as follows:
|
||||
-a all current limits are reported
|
||||
-c the maximum size of core files created
|
||||
-d the maximum size of a process's data segment
|
||||
-e the maximum scheduling priority (`nice')
|
||||
-f the maximum size of files created by the shell
|
||||
-i the maximum number of pending signals
|
||||
-l the maximum size a process may lock into memory
|
||||
@@ -41,6 +42,7 @@ option is given, it is interpreted as follows:
|
||||
-n the maximum number of open file descriptors
|
||||
-p the pipe buffer size
|
||||
-q the maximum number of bytes in POSIX message queues
|
||||
-r the maximum real-time scheduling priority
|
||||
-s the maximum stack size
|
||||
-t the maximum amount of cpu time in seconds
|
||||
-u the maximum number of user processes
|
||||
@@ -201,6 +203,9 @@ static RESOURCE_LIMITS limits[] = {
|
||||
#endif
|
||||
#ifdef RLIMIT_DATA
|
||||
{ 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
|
||||
#endif
|
||||
#ifdef RLIMIT_NICE
|
||||
{ 'e', RLIMIT_NICE, 1, "scheduling priority", (char *)NULL },
|
||||
#endif
|
||||
{ 'f', RLIMIT_FILESIZE, 1024, "file size", "blocks" },
|
||||
#ifdef RLIMIT_SIGPENDING
|
||||
@@ -217,6 +222,9 @@ static RESOURCE_LIMITS limits[] = {
|
||||
#ifdef RLIMIT_MSGQUEUE
|
||||
{ 'q', RLIMIT_MSGQUEUE, 1, "POSIX message queues", "bytes" },
|
||||
#endif
|
||||
#ifdef RLIMIT_RTPRIO
|
||||
{ 'r', RLIMIT_RTPRIO, 1, "real-time priority", (char *)NULL },
|
||||
#endif
|
||||
#ifdef RLIMIT_STACK
|
||||
{ 's', RLIMIT_STACK, 1024, "stack size", "kbytes" },
|
||||
#endif
|
||||
|
||||
+11
-3
@@ -34,18 +34,20 @@ option is given, it is interpreted as follows:
|
||||
-a all current limits are reported
|
||||
-c the maximum size of core files created
|
||||
-d the maximum size of a process's data segment
|
||||
-e the maximum scheduling priority (`nice')
|
||||
-f the maximum size of files created by the shell
|
||||
-i the maximum number of pending signals
|
||||
-i the maximum number of pending signals
|
||||
-l the maximum size a process may lock into memory
|
||||
-m the maximum resident set size
|
||||
-n the maximum number of open file descriptors
|
||||
-p the pipe buffer size
|
||||
-q the maximum number of bytes in POSIX message queues
|
||||
-q the maximum number of bytes in POSIX message queues
|
||||
-r the maximum real-time scheduling priority
|
||||
-s the maximum stack size
|
||||
-t the maximum amount of cpu time in seconds
|
||||
-u the maximum number of user processes
|
||||
-v the size of virtual memory
|
||||
-x the maximum number of file locks
|
||||
-x the maximum number of file locks
|
||||
|
||||
If LIMIT is given, it is the new value of the specified resource;
|
||||
the special LIMIT values `soft', `hard', and `unlimited' stand for
|
||||
@@ -201,6 +203,9 @@ static RESOURCE_LIMITS limits[] = {
|
||||
#endif
|
||||
#ifdef RLIMIT_DATA
|
||||
{ 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
|
||||
#endif
|
||||
#ifdef RLIMIT_NICE
|
||||
{ 'e', RLIMIT_NICE, 1, "scheduling priority", (char *)NULL },
|
||||
#endif
|
||||
{ 'f', RLIMIT_FILESIZE, 1024, "file size", "blocks" },
|
||||
#ifdef RLIMIT_SIGPENDING
|
||||
@@ -217,6 +222,9 @@ static RESOURCE_LIMITS limits[] = {
|
||||
#ifdef RLIMIT_MSGQUEUE
|
||||
{ 'q', RLIMIT_MSGQUEUE, 1, "POSIX message queues", "bytes" },
|
||||
#endif
|
||||
#ifdef RLIMIT_RTPRIO
|
||||
{ 'r', RLIMIT_RTPRIO, 1, "real-time priority", (char *)NULL },
|
||||
#endif
|
||||
#ifdef RLIMIT_STACK
|
||||
{ 's', RLIMIT_STACK, 1024, "stack size", "kbytes" },
|
||||
#endif
|
||||
|
||||
@@ -67,26 +67,27 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
|
||||
cm_arith, cm_cond, cm_arith_for, cm_subshell };
|
||||
|
||||
/* Possible values for the `flags' field of a WORD_DESC. */
|
||||
#define W_HASDOLLAR 0x00001 /* Dollar sign present. */
|
||||
#define W_QUOTED 0x00002 /* Some form of quote character is present. */
|
||||
#define W_ASSIGNMENT 0x00004 /* This word is a variable assignment. */
|
||||
#define W_GLOBEXP 0x00008 /* This word is the result of a glob expansion. */
|
||||
#define W_NOSPLIT 0x00010 /* Do not perform word splitting on this word. */
|
||||
#define W_NOGLOB 0x00020 /* Do not perform globbing on this word. */
|
||||
#define W_NOSPLIT2 0x00040 /* Don't split word except for $@ expansion. */
|
||||
#define W_TILDEEXP 0x00080 /* Tilde expand this assignment word */
|
||||
#define W_DOLLARAT 0x00100 /* $@ and its special handling */
|
||||
#define W_DOLLARSTAR 0x00200 /* $* and its special handling */
|
||||
#define W_NOCOMSUB 0x00400 /* Don't perform command substitution on this word */
|
||||
#define W_ASSIGNRHS 0x00800 /* Word is rhs of an assignment statement */
|
||||
#define W_NOTILDE 0x01000 /* Don't perform tilde expansion on this word */
|
||||
#define W_ITILDE 0x02000 /* Internal flag for word expansion */
|
||||
#define W_NOEXPAND 0x04000 /* Don't expand at all -- do quote removal */
|
||||
#define W_COMPASSIGN 0x08000 /* Compound assignment */
|
||||
#define W_ASSNBLTIN 0x10000 /* word is a builtin command that takes assignments */
|
||||
#define W_ASSIGNARG 0x20000 /* word is assignment argument to command */
|
||||
#define W_HASQUOTEDNULL 0x40000 /* word contains a quoted null character */
|
||||
#define W_DQUOTE 0x80000 /* word should be treated as if double-quoted */
|
||||
#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_GLOBEXP 0x000008 /* This word is the result of a glob expansion. */
|
||||
#define W_NOSPLIT 0x000010 /* Do not perform word splitting on this word. */
|
||||
#define W_NOGLOB 0x000020 /* Do not perform globbing on this word. */
|
||||
#define W_NOSPLIT2 0x000040 /* Don't split word except for $@ expansion. */
|
||||
#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 */
|
||||
|
||||
/* Possible values for subshell_environment */
|
||||
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
|
||||
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
/* command.h -- The structures used internally to represent commands, and
|
||||
the extern declarations of the functions used to create them. */
|
||||
|
||||
/* Copyright (C) 1993-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#if !defined (_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
|
||||
};
|
||||
|
||||
/* 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 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)
|
||||
|
||||
#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_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 };
|
||||
|
||||
/* Possible values for the `flags' field of a WORD_DESC. */
|
||||
#define W_HASDOLLAR 0x00001 /* Dollar sign present. */
|
||||
#define W_QUOTED 0x00002 /* Some form of quote character is present. */
|
||||
#define W_ASSIGNMENT 0x00004 /* This word is a variable assignment. */
|
||||
#define W_GLOBEXP 0x00008 /* This word is the result of a glob expansion. */
|
||||
#define W_NOSPLIT 0x00010 /* Do not perform word splitting on this word. */
|
||||
#define W_NOGLOB 0x00020 /* Do not perform globbing on this word. */
|
||||
#define W_NOSPLIT2 0x00040 /* Don't split word except for $@ expansion. */
|
||||
#define W_TILDEEXP 0x00080 /* Tilde expand this assignment word */
|
||||
#define W_DOLLARAT 0x00100 /* $@ and its special handling */
|
||||
#define W_DOLLARSTAR 0x00200 /* $* and its special handling */
|
||||
#define W_NOCOMSUB 0x00400 /* Don't perform command substitution on this word */
|
||||
#define W_ASSIGNRHS 0x00800 /* Word is rhs of an assignment statement */
|
||||
#define W_NOTILDE 0x01000 /* Don't perform tilde expansion on this word */
|
||||
#define W_ITILDE 0x02000 /* Internal flag for word expansion */
|
||||
#define W_NOEXPAND 0x04000 /* Don't expand at all -- do quote removal */
|
||||
#define W_COMPASSIGN 0x08000 /* Compound assignment */
|
||||
#define W_ASSNBLTIN 0x10000 /* word is a builtin command that takes assignments */
|
||||
#define W_ASSIGNARG 0x20000 /* word is assignment argument to command */
|
||||
#define W_HASQUOTEDNULL 0x40000 /* word contains a quoted null character */
|
||||
#define W_DQUOTE 0x80000 /* word should be treated as if double-quoted */
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* 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. */
|
||||
int redirector; /* Descriptor to be redirected. */
|
||||
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 */
|
||||
|
||||
/* 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;
|
||||
} 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. */
|
||||
|
||||
/* 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;
|
||||
|
||||
extern COMMAND *global_command;
|
||||
|
||||
/* 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_ */
|
||||
@@ -1,5 +1,5 @@
|
||||
#! /bin/sh
|
||||
# From configure.in for Bash 3.1, version 3.183.
|
||||
# From configure.in for Bash 3.2, version 3.186.
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.59 for bash 3.2-devel.
|
||||
#
|
||||
@@ -312,7 +312,7 @@ ac_includes_default="\
|
||||
# include <unistd.h>
|
||||
#endif"
|
||||
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os EMACS lispdir DEBUGGER_START_FILE TESTSCRIPT PURIFY MALLOC_TARGET MALLOC_SRC MALLOC_LIB MALLOC_LIBRARY MALLOC_LDFLAGS MALLOC_DEP htmldir HELPDIR HELPDIRDEFINE HELPINSTALL HELPSTRINGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP CROSS_COMPILE SIGNAMES_H CC_FOR_BUILD STATIC_LD CFLAGS_FOR_BUILD CPPFLAGS_FOR_BUILD LDFLAGS_FOR_BUILD RL_VERSION RL_MAJOR RL_MINOR READLINE_LIB READLINE_DEP RL_LIBDIR RL_INCLUDEDIR RL_INCLUDE HISTORY_LIB HISTORY_DEP HIST_LIBDIR TILDE_LIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AR RANLIB ac_ct_RANLIB YACC SET_MAKE MAKE_SHELL SIZE MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE ALLOCA GLIBC21 LIBICONV LTLIBICONV INTLBISON BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT DATADIRNAME INSTOBJEXT GENCAT INTLOBJS INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB LIBOBJS INTL_DEP INTL_INC LIBINTL_H SIGLIST_O TERMCAP_LIB TERMCAP_DEP JOBS_O SHOBJ_CC SHOBJ_CFLAGS SHOBJ_LD SHOBJ_LDFLAGS SHOBJ_XLDFLAGS SHOBJ_LIBS SHOBJ_STATUS PROFILE_FLAGS incdir BUILD_DIR ARFLAGS BASHVERS RELSTATUS DEBUG MALLOC_DEBUG LOCAL_LIBS LOCAL_CFLAGS LOCAL_LDFLAGS LOCAL_DEFS LTLIBOBJS'
|
||||
ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os EMACS lispdir DEBUGGER_START_FILE TESTSCRIPT PURIFY MALLOC_TARGET MALLOC_SRC MALLOC_LIB MALLOC_LIBRARY MALLOC_LDFLAGS MALLOC_DEP htmldir HELPDIR HELPDIRDEFINE HELPINSTALL HELPSTRINGS CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP EGREP CROSS_COMPILE SIGNAMES_H SIGNAMES_O CC_FOR_BUILD STATIC_LD CFLAGS_FOR_BUILD CPPFLAGS_FOR_BUILD LDFLAGS_FOR_BUILD RL_VERSION RL_MAJOR RL_MINOR READLINE_LIB READLINE_DEP RL_LIBDIR RL_INCLUDEDIR RL_INCLUDE HISTORY_LIB HISTORY_DEP HIST_LIBDIR TILDE_LIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA AR RANLIB ac_ct_RANLIB YACC SET_MAKE MAKE_SHELL SIZE MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE ALLOCA GLIBC21 LIBICONV LTLIBICONV INTLBISON BUILD_INCLUDED_LIBINTL USE_INCLUDED_LIBINTL CATOBJEXT DATADIRNAME INSTOBJEXT GENCAT INTLOBJS INTL_LIBTOOL_SUFFIX_PREFIX INTLLIBS LIBINTL LTLIBINTL POSUB LIBOBJS INTL_DEP INTL_INC LIBINTL_H SIGLIST_O TERMCAP_LIB TERMCAP_DEP JOBS_O SHOBJ_CC SHOBJ_CFLAGS SHOBJ_LD SHOBJ_LDFLAGS SHOBJ_XLDFLAGS SHOBJ_LIBS SHOBJ_STATUS PROFILE_FLAGS incdir BUILD_DIR ARFLAGS BASHVERS RELSTATUS DEBUG MALLOC_DEBUG LOCAL_LIBS LOCAL_CFLAGS LOCAL_LDFLAGS LOCAL_DEFS LTLIBOBJS'
|
||||
ac_subst_files=''
|
||||
|
||||
# Initialize some variables set by options.
|
||||
@@ -4113,6 +4113,7 @@ fi
|
||||
|
||||
|
||||
|
||||
SIGNAMES_O=
|
||||
SIGNAMES_H=lsignames.h
|
||||
|
||||
|
||||
@@ -4121,14 +4122,12 @@ if test "x$cross_compiling" = "xyes"; then
|
||||
case "${host}" in
|
||||
*-cygwin*)
|
||||
cross_cache=${srcdir}/cross-build/cygwin32.cache
|
||||
SIGNAMES_H='$(srcdir)/cross-build/win32sig.h'
|
||||
;;
|
||||
*-mingw*)
|
||||
cross_cache=${srcdir}/cross-build/cygwin32.cache
|
||||
;;
|
||||
i[3456]86-*-beos*)
|
||||
cross_cache=${srcdir}/cross-build/x86-beos.cache
|
||||
SIGNAMES_H='${srcdir}/cross-build/beos-sig.h'
|
||||
;;
|
||||
*) echo "configure: cross-compiling for $host is not supported" >&2
|
||||
;;
|
||||
@@ -4138,11 +4137,13 @@ if test "x$cross_compiling" = "xyes"; then
|
||||
. ${cross_cache}
|
||||
fi
|
||||
unset cross_cache
|
||||
SIGNAMES_O='signames.o'
|
||||
CROSS_COMPILE='-DCROSS_COMPILING'
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test -z "$CC_FOR_BUILD"; then
|
||||
if test "x$cross_compiling" = "xno"; then
|
||||
CC_FOR_BUILD='$(CC)'
|
||||
@@ -27626,6 +27627,7 @@ s,@CPP@,$CPP,;t t
|
||||
s,@EGREP@,$EGREP,;t t
|
||||
s,@CROSS_COMPILE@,$CROSS_COMPILE,;t t
|
||||
s,@SIGNAMES_H@,$SIGNAMES_H,;t t
|
||||
s,@SIGNAMES_O@,$SIGNAMES_O,;t t
|
||||
s,@CC_FOR_BUILD@,$CC_FOR_BUILD,;t t
|
||||
s,@STATIC_LD@,$STATIC_LD,;t t
|
||||
s,@CFLAGS_FOR_BUILD@,$CFLAGS_FOR_BUILD,;t t
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
dnl
|
||||
dnl Configure script for bash-3.1
|
||||
dnl Configure script for bash-3.2
|
||||
dnl
|
||||
dnl report bugs to chet@po.cwru.edu
|
||||
dnl
|
||||
@@ -22,7 +22,7 @@ dnl Process this file with autoconf to produce a configure script.
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
AC_REVISION([for Bash 3.1, version 3.183])dnl
|
||||
AC_REVISION([for Bash 3.2, version 3.186])dnl
|
||||
|
||||
define(bashvers, 3.2)
|
||||
define(relstatus, devel)
|
||||
@@ -373,6 +373,7 @@ AC_SYS_LARGEFILE
|
||||
dnl BEGIN changes for cross-building (currently cygwin, minGW, and
|
||||
dnl (obsolete) BeOS)
|
||||
|
||||
SIGNAMES_O=
|
||||
SIGNAMES_H=lsignames.h
|
||||
|
||||
dnl load up the cross-building cache file -- add more cases and cache
|
||||
@@ -386,14 +387,12 @@ if test "x$cross_compiling" = "xyes"; then
|
||||
case "${host}" in
|
||||
*-cygwin*)
|
||||
cross_cache=${srcdir}/cross-build/cygwin32.cache
|
||||
SIGNAMES_H='$(srcdir)/cross-build/win32sig.h'
|
||||
;;
|
||||
*-mingw*)
|
||||
cross_cache=${srcdir}/cross-build/cygwin32.cache
|
||||
;;
|
||||
i[[3456]]86-*-beos*)
|
||||
cross_cache=${srcdir}/cross-build/x86-beos.cache
|
||||
SIGNAMES_H='${srcdir}/cross-build/beos-sig.h'
|
||||
;;
|
||||
*) echo "configure: cross-compiling for $host is not supported" >&2
|
||||
;;
|
||||
@@ -403,10 +402,12 @@ if test "x$cross_compiling" = "xyes"; then
|
||||
. ${cross_cache}
|
||||
fi
|
||||
unset cross_cache
|
||||
SIGNAMES_O='signames.o'
|
||||
CROSS_COMPILE='-DCROSS_COMPILING'
|
||||
AC_SUBST(CROSS_COMPILE)
|
||||
fi
|
||||
AC_SUBST(SIGNAMES_H)
|
||||
AC_SUBST(SIGNAMES_O)
|
||||
|
||||
if test -z "$CC_FOR_BUILD"; then
|
||||
if test "x$cross_compiling" = "xno"; then
|
||||
|
||||
+1112
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,152 @@
|
||||
*** ../bash-3.1/subst.c Mon Oct 24 09:51:13 2005
|
||||
--- subst.c Fri Dec 30 12:11:53 2005
|
||||
***************
|
||||
*** 2188,2192 ****
|
||||
{
|
||||
v = find_variable (name);
|
||||
! if (v == 0 || array_p (v) == 0)
|
||||
v = make_local_array_variable (name);
|
||||
v = assign_array_var_from_string (v, value, flags);
|
||||
--- 2188,2192 ----
|
||||
{
|
||||
v = find_variable (name);
|
||||
! if (v == 0 || array_p (v) == 0 || v->context != variable_context)
|
||||
v = make_local_array_variable (name);
|
||||
v = assign_array_var_from_string (v, value, flags);
|
||||
***************
|
||||
*** 2576,2579 ****
|
||||
--- 2576,2586 ----
|
||||
}
|
||||
|
||||
+ char *
|
||||
+ expand_arith_string (string)
|
||||
+ char *string;
|
||||
+ {
|
||||
+ return (expand_string_if_necessary (string, Q_DOUBLE_QUOTES, expand_string));
|
||||
+ }
|
||||
+
|
||||
#if defined (COND_COMMAND)
|
||||
/* Just remove backslashes in STRING. Returns a new string. */
|
||||
***************
|
||||
*** 5249,5253 ****
|
||||
--- 5256,5264 ----
|
||||
t = (char *)0;
|
||||
|
||||
+ #if 0
|
||||
temp1 = expand_string_if_necessary (substr, Q_DOUBLE_QUOTES, expand_string);
|
||||
+ #else
|
||||
+ temp1 = expand_arith_string (substr);
|
||||
+ #endif
|
||||
*e1p = evalexp (temp1, &expok);
|
||||
free (temp1);
|
||||
***************
|
||||
*** 5294,5298 ****
|
||||
--- 5305,5313 ----
|
||||
t++;
|
||||
temp2 = savestring (t);
|
||||
+ #if 0
|
||||
temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
|
||||
+ #else
|
||||
+ temp1 = expand_arith_string (temp2);
|
||||
+ #endif
|
||||
free (temp2);
|
||||
t[-1] = ':';
|
||||
***************
|
||||
*** 5666,5674 ****
|
||||
|
||||
mflags = 0;
|
||||
- if (*patsub == '/')
|
||||
- {
|
||||
- mflags |= MATCH_GLOBREP;
|
||||
- patsub++;
|
||||
- }
|
||||
|
||||
/* Malloc this because expand_string_if_necessary or one of the expansion
|
||||
--- 5681,5684 ----
|
||||
***************
|
||||
*** 5682,5686 ****
|
||||
mflags |= MATCH_STARSUB;
|
||||
|
||||
! if (rep = quoted_strchr (lpatsub, '/', ST_BACKSL))
|
||||
*rep++ = '\0';
|
||||
else
|
||||
--- 5692,5698 ----
|
||||
mflags |= MATCH_STARSUB;
|
||||
|
||||
! /* If the pattern starts with a `/', make sure we skip over it when looking
|
||||
! for the replacement delimiter. */
|
||||
! if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
|
||||
*rep++ = '\0';
|
||||
else
|
||||
***************
|
||||
*** 5702,5707 ****
|
||||
}
|
||||
|
||||
p = pat;
|
||||
! if (pat && pat[0] == '#')
|
||||
{
|
||||
mflags |= MATCH_BEG;
|
||||
--- 5714,5726 ----
|
||||
}
|
||||
|
||||
+ /* ksh93 doesn't allow the match specifier to be a part of the expanded
|
||||
+ pattern. This is an extension. */
|
||||
p = pat;
|
||||
! if (pat && pat[0] == '/')
|
||||
! {
|
||||
! mflags |= MATCH_GLOBREP|MATCH_ANY;
|
||||
! p++;
|
||||
! }
|
||||
! else if (pat && pat[0] == '#')
|
||||
{
|
||||
mflags |= MATCH_BEG;
|
||||
***************
|
||||
*** 6436,6440 ****
|
||||
--- 6455,6463 ----
|
||||
|
||||
/* Expand variables found inside the expression. */
|
||||
+ #if 0
|
||||
temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
|
||||
+ #else
|
||||
+ temp1 = expand_arith_string (temp2);
|
||||
+ #endif
|
||||
free (temp2);
|
||||
|
||||
***************
|
||||
*** 6478,6482 ****
|
||||
--- 6501,6509 ----
|
||||
|
||||
/* Do initial variable expansion. */
|
||||
+ #if 0
|
||||
temp1 = expand_string_if_necessary (temp, Q_DOUBLE_QUOTES, expand_string);
|
||||
+ #else
|
||||
+ temp1 = expand_arith_string (temp);
|
||||
+ #endif
|
||||
|
||||
goto arithsub;
|
||||
***************
|
||||
*** 6708,6712 ****
|
||||
case '>':
|
||||
{
|
||||
! if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & W_DQUOTE) || posixly_correct)
|
||||
{
|
||||
sindex--; /* add_character: label increments sindex */
|
||||
--- 6735,6739 ----
|
||||
case '>':
|
||||
{
|
||||
! if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
|
||||
{
|
||||
sindex--; /* add_character: label increments sindex */
|
||||
***************
|
||||
*** 6796,6799 ****
|
||||
--- 6823,6832 ----
|
||||
{
|
||||
temp1 = bash_tilde_expand (temp, tflag);
|
||||
+ if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
|
||||
+ {
|
||||
+ FREE (temp);
|
||||
+ FREE (temp1);
|
||||
+ goto add_character; /* tilde expansion failed */
|
||||
+ }
|
||||
free (temp);
|
||||
temp = temp1;
|
||||
@@ -1,4 +1,4 @@
|
||||
This is the Bash FAQ, version 3.32, for Bash version 3.1.
|
||||
This is the Bash FAQ, version 3.33, for Bash version 3.1.
|
||||
|
||||
This document contains a set of frequently-asked questions concerning
|
||||
Bash, the GNU Bourne-Again Shell. Bash is a freely-available command
|
||||
@@ -697,7 +697,7 @@ Things bash has that sh does not:
|
||||
read -e/-p/-a/-t/-n/-d/-s/-u,
|
||||
readonly -a/-f/name=value, trap -l, set +o,
|
||||
set -b/-m/-o option/-h/-p/-B/-C/-H/-P,
|
||||
unset -f/-v, ulimit -m/-p/-u,
|
||||
unset -f/-v, ulimit -i/-m/-p/-q/-u/-x,
|
||||
type -a/-p/-t/-f/-P, suspend -f, kill -n,
|
||||
test -o optname/s1 == s2/s1 < s2/s1 > s2/-nt/-ot/-ef/-O/-G/-S
|
||||
bash reads ~/.bashrc for interactive shells, $ENV for non-interactive
|
||||
@@ -793,8 +793,8 @@ Things bash has or uses that ksh88 does not:
|
||||
set -o braceexpand/-o histexpand/-o interactive-comments/
|
||||
-o notify/-o physical/-o posix/-o hashall/-o onecmd/
|
||||
-h/-B/-C/-b/-H/-P, set +o, suspend, trap -l, type,
|
||||
typeset -a/-F/-p, ulimit -u, umask -S, alias -p, shopt,
|
||||
disown, printf, complete, compgen
|
||||
typeset -a/-F/-p, ulimit -i/-q/-u/-x, umask -S, alias -p,
|
||||
shopt, disown, printf, complete, compgen
|
||||
`!' csh-style history expansion
|
||||
POSIX.2-style globbing character classes
|
||||
POSIX.2-style globbing equivalence classes
|
||||
@@ -1575,6 +1575,9 @@ this. These variables can be set in your .inputrc or using the bash
|
||||
The `set' commands between the single quotes may also be placed
|
||||
in ~/.inputrc.
|
||||
|
||||
The script examples/scripts.noah/meta.bash encapsulates the bind
|
||||
commands in a shell function.
|
||||
|
||||
G2) How do I write a function `x' to replace builtin command `x', but
|
||||
still invoke the command from within the function?
|
||||
|
||||
@@ -1748,13 +1751,9 @@ ftp.cwru.edu in the `pub/bash' directory.
|
||||
Cameron Newham and Bill Rosenblatt have written a book on bash, published
|
||||
by O'Reilly and Associates. The book is based on Bill Rosenblatt's Korn
|
||||
Shell book. The title is ``Learning the Bash Shell'', and the ISBN number
|
||||
is 1-56592-147-X. Look for it in fine bookstores near you. This book
|
||||
covers bash-1.14, but has an appendix describing some of the new features
|
||||
in bash-2.0.
|
||||
|
||||
A second edition of this book is available, published in January, 1998.
|
||||
The ISBN number is 1-56592-347-2. Look for it in the same fine bookstores
|
||||
or on the web.
|
||||
of the third edition, published in March, 2005, is 0-596-00965-8. Look for
|
||||
it in fine bookstores near you. This edition of the book has been updated
|
||||
to cover bash-3.0.
|
||||
|
||||
The GNU Bash Reference Manual has been published as a printed book by
|
||||
Network Theory Ltd (Paperback, ISBN: 0-9541617-7-7, Feb 2003). It covers
|
||||
@@ -1762,6 +1761,16 @@ bash-2.0 and is available from most online bookstores (see
|
||||
http://www.network-theory.co.uk/bash/manual/ for details). The publisher
|
||||
will donate $1 to the Free Software Foundation for each copy sold.
|
||||
|
||||
Arnold Robbins and Nelson Beebe have written ``Classic Shell Scripting'',
|
||||
published by O'Reilly. The first edition, with ISBN number 0-596-00595-4,
|
||||
was published in May, 2005.
|
||||
|
||||
Chris F. A. Johnson, a frequent contributor to comp.unix.shell and
|
||||
gnu.bash.bug, has written ``Shell Scripting Recipes: A Problem-Solution
|
||||
Approach,'' a new book on shell scripting, concentrating on features of
|
||||
the POSIX standard helpful to shell script writers. The first edition from
|
||||
Apress, with ISBN number 1-59059-471-1, was published in May, 2005.
|
||||
|
||||
H3) What's coming in future versions?
|
||||
|
||||
These are features I hope to include in a future version of bash.
|
||||
|
||||
+19
-12
@@ -6,12 +6,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Sat Aug 27 13:28:44 EDT 2005
|
||||
.\" Last Change: Wed Dec 28 19:58:45 EST 2005
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2005 Dec 10" "GNU Bash-3.1"
|
||||
.TH BASH 1 "2005 Dec 28" "GNU Bash-3.1"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -677,8 +677,8 @@ If the shell option
|
||||
.B nocasematch
|
||||
is enabled, the match is performed without regard to the case
|
||||
of alphabetic characters.
|
||||
The return value is 0 if the string matches or does not match
|
||||
the pattern, respectively, and 1 otherwise.
|
||||
The return value is 0 if the string matches (\fB==\fP) or does not match
|
||||
(\fB!=\fP) the pattern, and 1 otherwise.
|
||||
Any part of the pattern may be quoted to force it to be matched as a
|
||||
string.
|
||||
.if t .sp 0.5
|
||||
@@ -807,6 +807,12 @@ it against each \fIpattern\fP in turn, using the same matching rules
|
||||
as for pathname expansion (see
|
||||
.B Pathname Expansion
|
||||
below).
|
||||
The \fIword\fP is expanded using tilde
|
||||
expansion, parameter and variable expansion, arithmetic substituion,
|
||||
command substitution, process substitution and quote removal.
|
||||
Each \fIpattern\fP examined is expanded using tilde
|
||||
expansion, parameter and variable expansion, arithmetic substituion,
|
||||
command substitution, and process substitution.
|
||||
If the shell option
|
||||
.B nocasematch
|
||||
is enabled, the match is performed without regard to the case
|
||||
@@ -2525,17 +2531,12 @@ the pattern removal operation is applied to each member of the
|
||||
array in turn, and the expansion is the resultant list.
|
||||
.TP
|
||||
${\fIparameter\fP\fB/\fP\fIpattern\fP\fB/\fP\fIstring\fP}
|
||||
.PD 0
|
||||
.TP
|
||||
${\fIparameter\fP\fB//\fP\fIpattern\fP\fB/\fP\fIstring\fP}
|
||||
.PD
|
||||
The \fIpattern\fP is expanded to produce a pattern just as in
|
||||
pathname expansion.
|
||||
\fIParameter\fP is expanded and the longest match of \fIpattern\fP
|
||||
against its value is replaced with \fIstring\fP.
|
||||
In the first form, only the first match is replaced.
|
||||
The second form causes all matches of \fIpattern\fP to be
|
||||
replaced with \fIstring\fP.
|
||||
If \Ipattern\fP begins with \fB/\fP, all matches of \fIpattern\fP are
|
||||
replaced with \fIstring\fP. Normally only the first match is replaced.
|
||||
If \fIpattern\fP begins with \fB#\fP, it must match at the beginning
|
||||
of the expanded value of \fIparameter\fP.
|
||||
If \fIpattern\fP begins with \fB%\fP, it must match at the end
|
||||
@@ -8484,7 +8485,7 @@ option suppresses shell function lookup, as with the \fBcommand\fP builtin.
|
||||
returns true if any of the arguments are found, false if
|
||||
none are found.
|
||||
.TP
|
||||
\fBulimit\fP [\fB\-SHacdfilmnpqstuvx\fP [\fIlimit\fP]]
|
||||
\fBulimit\fP [\fB\-SHacdefilmnpqrstuvx\fP [\fIlimit\fP]]
|
||||
Provides control over the resources available to the shell and to
|
||||
processes started by it, on systems that allow such control.
|
||||
The \fB\-H\fP and \fB\-S\fP options specify that the hard or soft limit is
|
||||
@@ -8520,6 +8521,9 @@ The maximum size of core files created
|
||||
.B \-d
|
||||
The maximum size of a process's data segment
|
||||
.TP
|
||||
.B \-e
|
||||
The maximum scheduling priority ("nice")
|
||||
.TP
|
||||
.B \-f
|
||||
The maximum size of files created by the shell
|
||||
.TP
|
||||
@@ -8542,6 +8546,9 @@ The pipe size in 512-byte blocks (this may not be set)
|
||||
.B \-q
|
||||
The maximum number of bytes in POSIX message queues
|
||||
.TP
|
||||
.B \-r
|
||||
The maximum real-time scheduling priority
|
||||
.TP
|
||||
.B \-s
|
||||
The maximum stack size
|
||||
.TP
|
||||
|
||||
+17
-5
@@ -6,12 +6,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Sat Aug 27 13:28:44 EDT 2005
|
||||
.\" Last Change: Mon Dec 19 09:04:39 EST 2005
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2005 Aug 27" "GNU Bash-3.1"
|
||||
.TH BASH 1 "2005 Dec 19" "GNU Bash-3.1"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -677,8 +677,8 @@ If the shell option
|
||||
.B nocasematch
|
||||
is enabled, the match is performed without regard to the case
|
||||
of alphabetic characters.
|
||||
The return value is 0 if the string matches or does not match
|
||||
the pattern, respectively, and 1 otherwise.
|
||||
The return value is 0 if the string matches (\fB==\fP) or does not match
|
||||
(\fB!=\fP) the pattern, and 1 otherwise.
|
||||
Any part of the pattern may be quoted to force it to be matched as a
|
||||
string.
|
||||
.if t .sp 0.5
|
||||
@@ -807,6 +807,12 @@ it against each \fIpattern\fP in turn, using the same matching rules
|
||||
as for pathname expansion (see
|
||||
.B Pathname Expansion
|
||||
below).
|
||||
The \fIword\fP is expanded using tilde
|
||||
expansion, parameter and variable expansion, arithmetic substituion,
|
||||
command substitution, process substitution and quote removal.
|
||||
Each \fIpattern\fP examined is expanded using tilde
|
||||
expansion, parameter and variable expansion, arithmetic substituion,
|
||||
command substitution, and process substitution.
|
||||
If the shell option
|
||||
.B nocasematch
|
||||
is enabled, the match is performed without regard to the case
|
||||
@@ -8484,7 +8490,7 @@ option suppresses shell function lookup, as with the \fBcommand\fP builtin.
|
||||
returns true if any of the arguments are found, false if
|
||||
none are found.
|
||||
.TP
|
||||
\fBulimit\fP [\fB\-SHacdfilmnpqstuvx\fP [\fIlimit\fP]]
|
||||
\fBulimit\fP [\fB\-SHacdefilmnpqrstuvx\fP [\fIlimit\fP]]
|
||||
Provides control over the resources available to the shell and to
|
||||
processes started by it, on systems that allow such control.
|
||||
The \fB\-H\fP and \fB\-S\fP options specify that the hard or soft limit is
|
||||
@@ -8520,6 +8526,9 @@ The maximum size of core files created
|
||||
.B \-d
|
||||
The maximum size of a process's data segment
|
||||
.TP
|
||||
.B \-e
|
||||
The maximum scheduling priority ("nice")
|
||||
.TP
|
||||
.B \-f
|
||||
The maximum size of files created by the shell
|
||||
.TP
|
||||
@@ -8542,6 +8551,9 @@ The pipe size in 512-byte blocks (this may not be set)
|
||||
.B \-q
|
||||
The maximum number of bytes in POSIX message queues
|
||||
.TP
|
||||
.B \-r
|
||||
The maximum real-time scheduling priority
|
||||
.TP
|
||||
.B \-s
|
||||
The maximum stack size
|
||||
.TP
|
||||
|
||||
+14
-10
@@ -961,8 +961,8 @@ If the shell option @code{nocasematch}
|
||||
(see the description of @code{shopt} in @ref{Bash Builtins})
|
||||
is enabled, the match is performed without regard to the case
|
||||
of alphabetic characters.
|
||||
The return value is 0 if the string matches or does not match
|
||||
the pattern, respectively, and 1 otherwise.
|
||||
The return value is 0 if the string matches (@samp{==}) or does not
|
||||
match (@samp{!=})the pattern, and 1 otherwise.
|
||||
Any part of the pattern may be quoted to force it to be matched as a
|
||||
string.
|
||||
|
||||
@@ -1652,15 +1652,13 @@ the pattern removal operation is applied to each member of the
|
||||
array in turn, and the expansion is the resultant list.
|
||||
|
||||
@item $@{@var{parameter}/@var{pattern}/@var{string}@}
|
||||
@itemx $@{@var{parameter}//@var{pattern}/@var{string}@}
|
||||
|
||||
The @var{pattern} is expanded to produce a pattern just as in
|
||||
filename expansion.
|
||||
@var{Parameter} is expanded and the longest match of @var{pattern}
|
||||
against its value is replaced with @var{string}.
|
||||
In the first form, only the first match is replaced.
|
||||
The second form causes all matches of @var{pattern} to be
|
||||
replaced with @var{string}.
|
||||
If @var{pattern} begins with @samp{/}, all matches of @var{pattern} are
|
||||
replaced with @var{string}. Normally only the first match is replaced.
|
||||
If @var{pattern} begins with @samp{#}, it must match at the beginning
|
||||
of the expanded value of @var{parameter}.
|
||||
If @var{pattern} begins with @samp{%}, it must match at the end
|
||||
@@ -2598,7 +2596,7 @@ the command directly, without invoking another program.
|
||||
Builtin commands are necessary to implement functionality impossible
|
||||
or inconvenient to obtain with separate utilities.
|
||||
|
||||
This section briefly the builtins which Bash inherits from
|
||||
This section briefly describes the builtins which Bash inherits from
|
||||
the Bourne Shell, as well as the builtin commands which are unique
|
||||
to or have been extended in Bash.
|
||||
|
||||
@@ -3833,7 +3831,7 @@ builtin command.
|
||||
@item ulimit
|
||||
@btindex ulimit
|
||||
@example
|
||||
ulimit [-acdfilmnpqstuvxSH] [@var{limit}]
|
||||
ulimit [-acdefilmnpqrstuvxSH] [@var{limit}]
|
||||
@end example
|
||||
@code{ulimit} provides control over the resources available to processes
|
||||
started by the shell, on systems that allow such control. If an
|
||||
@@ -3854,6 +3852,9 @@ The maximum size of core files created.
|
||||
@item -d
|
||||
The maximum size of a process's data segment.
|
||||
|
||||
@item -e
|
||||
The maximum scheduling priority ("nice").
|
||||
|
||||
@item -f
|
||||
The maximum size of files created by the shell.
|
||||
|
||||
@@ -3875,6 +3876,9 @@ The pipe buffer size.
|
||||
@item -q
|
||||
The maximum number of bytes in POSIX message queues.
|
||||
|
||||
@item -r
|
||||
The maximum real-time scheduling priority.
|
||||
|
||||
@item -s
|
||||
The maximum stack size.
|
||||
|
||||
@@ -4098,8 +4102,8 @@ shell will exit.
|
||||
Print shell input lines as they are read.
|
||||
|
||||
@item -x
|
||||
Print a trace of simple commands, \fBfor\fP commands, \fBcase\fP
|
||||
commands, \fBselect\fP commands, and arithmetic \fBfor\fP commands
|
||||
Print a trace of simple commands, @code{for} commands, @code{case}
|
||||
commands, @code{select} commands, and arithmetic @code{for} commands
|
||||
and their arguments or associated word lists after they are
|
||||
expanded and before they are executed. The value of the @env{PS4}
|
||||
variable is expanded and the resultant value is printed before
|
||||
|
||||
+20
-7
@@ -961,8 +961,8 @@ If the shell option @code{nocasematch}
|
||||
(see the description of @code{shopt} in @ref{Bash Builtins})
|
||||
is enabled, the match is performed without regard to the case
|
||||
of alphabetic characters.
|
||||
The return value is 0 if the string matches or does not match
|
||||
the pattern, respectively, and 1 otherwise.
|
||||
The return value is 0 if the string matches (@samp{==}) or does not
|
||||
match (@samp{!=})the pattern, and 1 otherwise.
|
||||
Any part of the pattern may be quoted to force it to be matched as a
|
||||
string.
|
||||
|
||||
@@ -1652,15 +1652,13 @@ the pattern removal operation is applied to each member of the
|
||||
array in turn, and the expansion is the resultant list.
|
||||
|
||||
@item $@{@var{parameter}/@var{pattern}/@var{string}@}
|
||||
@itemx $@{@var{parameter}//@var{pattern}/@var{string}@}
|
||||
|
||||
The @var{pattern} is expanded to produce a pattern just as in
|
||||
filename expansion.
|
||||
@var{Parameter} is expanded and the longest match of @var{pattern}
|
||||
against its value is replaced with @var{string}.
|
||||
In the first form, only the first match is replaced.
|
||||
The second form causes all matches of @var{pattern} to be
|
||||
replaced with @var{string}.
|
||||
If @var{pattern} begins with @samp{/}, all matches of @var{pattern} are
|
||||
replaced with @var{string}. Normally only the first match is replaced.
|
||||
If @var{pattern} begins with @samp{#}, it must match at the beginning
|
||||
of the expanded value of @var{parameter}.
|
||||
If @var{pattern} begins with @samp{%}, it must match at the end
|
||||
@@ -3833,7 +3831,7 @@ builtin command.
|
||||
@item ulimit
|
||||
@btindex ulimit
|
||||
@example
|
||||
ulimit [-acdflmnpstuvSH] [@var{limit}]
|
||||
ulimit [-acdefilmnpqrstuvxSH] [@var{limit}]
|
||||
@end example
|
||||
@code{ulimit} provides control over the resources available to processes
|
||||
started by the shell, on systems that allow such control. If an
|
||||
@@ -3854,9 +3852,15 @@ The maximum size of core files created.
|
||||
@item -d
|
||||
The maximum size of a process's data segment.
|
||||
|
||||
@item -e
|
||||
The maximum scheduling priority ("nice").
|
||||
|
||||
@item -f
|
||||
The maximum size of files created by the shell.
|
||||
|
||||
@item -i
|
||||
The maximum number of pending signals.
|
||||
|
||||
@item -l
|
||||
The maximum size that may be locked into memory.
|
||||
|
||||
@@ -3869,6 +3873,12 @@ The maximum number of open file descriptors.
|
||||
@item -p
|
||||
The pipe buffer size.
|
||||
|
||||
@item -q
|
||||
The maximum number of bytes in POSIX message queues.
|
||||
|
||||
@item -r
|
||||
The maximum real-time scheduling priority.
|
||||
|
||||
@item -s
|
||||
The maximum stack size.
|
||||
|
||||
@@ -3881,6 +3891,9 @@ The maximum number of processes available to a single user.
|
||||
@item -v
|
||||
The maximum amount of virtual memory available to the process.
|
||||
|
||||
@item -x
|
||||
The maximum number of file locks.
|
||||
|
||||
@end table
|
||||
|
||||
If @var{limit} is given, it is the new value of the specified resource;
|
||||
|
||||
Binary file not shown.
+2
-2
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2005 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Sat Dec 10 19:58:23 EST 2005
|
||||
@set LASTCHANGE Fri Dec 30 10:50:51 EST 2005
|
||||
|
||||
@set EDITION 3.1
|
||||
@set VERSION 3.1
|
||||
@set UPDATED 10 December 2005
|
||||
@set UPDATED 30 December 2005
|
||||
@set UPDATED-MONTH December 2005
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2005 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Mon Sep 5 11:47:04 EDT 2005
|
||||
@set LASTCHANGE Wed Dec 28 19:59:13 EST 2005
|
||||
|
||||
@set EDITION 3.1
|
||||
@set VERSION 3.1
|
||||
@set UPDATED 5 September 2005
|
||||
@set UPDATED-MONTH September 2005
|
||||
@set UPDATED 28 December 2005
|
||||
@set UPDATED-MONTH December 2005
|
||||
|
||||
+5
-1
@@ -2396,6 +2396,7 @@ execute_arith_command (arith_command)
|
||||
int expok, save_line_number, retval;
|
||||
intmax_t expresult;
|
||||
WORD_LIST *new;
|
||||
char *exp;
|
||||
|
||||
expresult = 0;
|
||||
|
||||
@@ -2438,8 +2439,11 @@ execute_arith_command (arith_command)
|
||||
|
||||
if (new)
|
||||
{
|
||||
expresult = evalexp (new->word->word, &expok);
|
||||
exp = new->next ? string_list (new) : new->word->word;
|
||||
expresult = evalexp (exp, &expok);
|
||||
line_number = save_line_number;
|
||||
if (exp != new->word->word)
|
||||
free (exp);
|
||||
dispose_words (new);
|
||||
}
|
||||
else
|
||||
|
||||
+8
-2
@@ -865,17 +865,23 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
|
||||
? EXECUTION_FAILURE
|
||||
: EXECUTION_SUCCESS;
|
||||
|
||||
#if defined (DPAREN_ARITHMETIC) || defined (COND_COMMAND)
|
||||
/* This is where we set PIPESTATUS from the exit status of the appropriate
|
||||
compound commands (the ones that look enough like simple commands to
|
||||
cause confusion). We might be able to optimize by not doing this if
|
||||
subshell_environment != 0. */
|
||||
switch (command->type)
|
||||
{
|
||||
case cm_arith_for:
|
||||
# if defined (DPAREN_ARITHMETIC)
|
||||
case cm_arith:
|
||||
# endif
|
||||
# if defined (COND_COMMAND)
|
||||
case cm_cond:
|
||||
# endif
|
||||
set_pipestatus_from_exit (exec_result);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
last_command_exit_value = exec_result;
|
||||
run_pending_traps ();
|
||||
@@ -2192,7 +2198,7 @@ execute_case_command (case_command)
|
||||
if (echo_command_at_execute)
|
||||
xtrace_print_case_command_head (case_command);
|
||||
|
||||
if (signal_in_progress (DEBUG_TRAP == 0) && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
|
||||
if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
|
||||
{
|
||||
FREE (the_printed_command_except_trap);
|
||||
the_printed_command_except_trap = savestring (the_printed_command);
|
||||
|
||||
@@ -148,6 +148,7 @@ static intmax_t tokval; /* current token value */
|
||||
static int noeval; /* set to 1 if no assignment to be done */
|
||||
static procenv_t evalbuf;
|
||||
|
||||
static int _is_arithop __P((int));
|
||||
static void readtok __P((void)); /* lexical analyzer */
|
||||
|
||||
static intmax_t expr_streval __P((char *, int));
|
||||
@@ -949,6 +950,64 @@ expr_streval (tok, e)
|
||||
return (tval);
|
||||
}
|
||||
|
||||
static int
|
||||
_is_multiop (c)
|
||||
int c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case EQEQ:
|
||||
case NEQ:
|
||||
case LEQ:
|
||||
case GEQ:
|
||||
case LAND:
|
||||
case LOR:
|
||||
case LSH:
|
||||
case RSH:
|
||||
case OP_ASSIGN:
|
||||
case COND:
|
||||
case POWER:
|
||||
case PREINC:
|
||||
case PREDEC:
|
||||
case POSTINC:
|
||||
case POSTDEC:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_is_arithop (c)
|
||||
int c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case EQ:
|
||||
case GT:
|
||||
case LT:
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
case MUL:
|
||||
case DIV:
|
||||
case MOD:
|
||||
case NOT:
|
||||
case LPAR:
|
||||
case RPAR:
|
||||
case BAND:
|
||||
case BOR:
|
||||
case BXOR:
|
||||
case BNOT:
|
||||
return 1; /* operator tokens */
|
||||
case QUES:
|
||||
case COL:
|
||||
case COMMA:
|
||||
return 1; /* questionable */
|
||||
default:
|
||||
return 0; /* anything else is invalid */
|
||||
}
|
||||
}
|
||||
|
||||
/* Lexical analyzer/token reader for the expression evaluator. Reads the
|
||||
next token and puts its value into curtok, while advancing past it.
|
||||
Updates value of tp. May also set tokval (for number) or tokstr (for
|
||||
@@ -1104,8 +1163,22 @@ readtok ()
|
||||
assigntok = c; /* a OP= b */
|
||||
c = OP_ASSIGN;
|
||||
}
|
||||
else if (_is_arithop (c) == 0)
|
||||
{
|
||||
cp--;
|
||||
/* use curtok, since it hasn't been copied to lasttok yet */
|
||||
if (curtok == 0 || _is_arithop (curtok) || _is_multiop (curtok))
|
||||
evalerror (_("syntax error: operand expected"));
|
||||
else
|
||||
evalerror (_("syntax error: invalid arithmetic operator"));
|
||||
}
|
||||
else
|
||||
cp--; /* `unget' the character */
|
||||
|
||||
/* Should check here to make sure that the current character is one
|
||||
of the recognized operators and flag an error if not. Could create
|
||||
a character map the first time through and check it on subsequent
|
||||
calls. */
|
||||
lasttok = curtok;
|
||||
curtok = c;
|
||||
}
|
||||
|
||||
+11
-4
@@ -462,12 +462,21 @@ rl_translate_keyseq (seq, array, len)
|
||||
}
|
||||
else if (c == 'M')
|
||||
{
|
||||
i++;
|
||||
/* XXX - should obey convert-meta setting? */
|
||||
i++; /* seq[i] == '-' */
|
||||
/* XXX - obey convert-meta setting */
|
||||
if (_rl_convert_meta_chars_to_ascii && _rl_keymap[ESC].type == ISKMAP)
|
||||
array[l++] = ESC; /* ESC is meta-prefix */
|
||||
else if (seq[i+1] == '\\' && seq[i+2] == 'C' && seq[i+3] == '-')
|
||||
{
|
||||
i += 4;
|
||||
temp = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
|
||||
array[l++] = META (temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This doesn't yet handle things like \M-\a, which may
|
||||
or may not have any reasonable meaning. You're
|
||||
probably better off using straight octal or hex. */
|
||||
i++;
|
||||
array[l++] = META (seq[i]);
|
||||
}
|
||||
@@ -1507,7 +1516,6 @@ rl_variable_value (name)
|
||||
{
|
||||
register int i;
|
||||
int v;
|
||||
char *ret;
|
||||
|
||||
/* Check for simple variables first. */
|
||||
i = find_boolean_var (name);
|
||||
@@ -2170,7 +2178,6 @@ _rl_get_string_variable_value (name)
|
||||
{
|
||||
static char numbuf[32];
|
||||
char *ret;
|
||||
int n;
|
||||
|
||||
if (_rl_stricmp (name, "bell-style") == 0)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,7 @@
|
||||
#include "rldefs.h"
|
||||
#include "readline.h"
|
||||
#include "rlprivate.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* Private data for callback registration functions. See comments in
|
||||
rl_callback_read_char for more details. */
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/* callback.c -- functions to use readline as an X `callback' mechanism. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library, a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
|
||||
The GNU Readline Library is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version.
|
||||
|
||||
The GNU Readline Library 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.
|
||||
|
||||
The GNU General Public License is often shipped with GNU software, and
|
||||
is generally kept in a file called COPYING or LICENSE. If you do not
|
||||
have a copy of the license, write to the Free Software Foundation,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "rlconf.h"
|
||||
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
#include "readline.h"
|
||||
#include "rlprivate.h"
|
||||
|
||||
/* Private data for callback registration functions. See comments in
|
||||
rl_callback_read_char for more details. */
|
||||
_rl_callback_func_t *_rl_callback_func = 0;
|
||||
_rl_callback_generic_arg *_rl_callback_data = 0;
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Callback Readline Functions */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Allow using readline in situations where a program may have multiple
|
||||
things to handle at once, and dispatches them via select(). Call
|
||||
rl_callback_handler_install() with the prompt and a function to call
|
||||
whenever a complete line of input is ready. The user must then
|
||||
call rl_callback_read_char() every time some input is available, and
|
||||
rl_callback_read_char() will call the user's function with the complete
|
||||
text read in at each end of line. The terminal is kept prepped and
|
||||
signals handled all the time, except during calls to the user's function. */
|
||||
|
||||
rl_vcpfunc_t *rl_linefunc; /* user callback function */
|
||||
static int in_handler; /* terminal_prepped and signals set? */
|
||||
|
||||
/* Make sure the terminal is set up, initialize readline, and prompt. */
|
||||
static void
|
||||
_rl_callback_newline ()
|
||||
{
|
||||
rl_initialize ();
|
||||
|
||||
if (in_handler == 0)
|
||||
{
|
||||
in_handler = 1;
|
||||
|
||||
if (rl_prep_term_function)
|
||||
(*rl_prep_term_function) (_rl_meta_flag);
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
rl_set_signals ();
|
||||
#endif
|
||||
}
|
||||
|
||||
readline_internal_setup ();
|
||||
}
|
||||
|
||||
/* Install a readline handler, set up the terminal, and issue the prompt. */
|
||||
void
|
||||
rl_callback_handler_install (prompt, linefunc)
|
||||
const char *prompt;
|
||||
rl_vcpfunc_t *linefunc;
|
||||
{
|
||||
rl_set_prompt (prompt);
|
||||
RL_SETSTATE (RL_STATE_CALLBACK);
|
||||
rl_linefunc = linefunc;
|
||||
_rl_callback_newline ();
|
||||
}
|
||||
|
||||
/* Read one character, and dispatch to the handler if it ends the line. */
|
||||
void
|
||||
rl_callback_read_char ()
|
||||
{
|
||||
char *line;
|
||||
int eof, jcode;
|
||||
static procenv_t olevel;
|
||||
|
||||
if (rl_linefunc == NULL)
|
||||
{
|
||||
fprintf (stderr, "readline: readline_callback_read_char() called with no handler!\r\n");
|
||||
abort ();
|
||||
}
|
||||
|
||||
memcpy ((void *)olevel, (void *)readline_top_level, sizeof (procenv_t));
|
||||
jcode = setjmp (readline_top_level);
|
||||
if (jcode)
|
||||
{
|
||||
(*rl_redisplay_function) ();
|
||||
_rl_want_redisplay = 0;
|
||||
memcpy ((void *)readline_top_level, (void *)olevel, sizeof (procenv_t));
|
||||
return;
|
||||
}
|
||||
|
||||
if (RL_ISSTATE (RL_STATE_ISEARCH))
|
||||
{
|
||||
eof = _rl_isearch_callback (_rl_iscxt);
|
||||
if (eof == 0 && (RL_ISSTATE (RL_STATE_ISEARCH) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
|
||||
rl_callback_read_char ();
|
||||
|
||||
return;
|
||||
}
|
||||
else if (RL_ISSTATE (RL_STATE_NSEARCH))
|
||||
{
|
||||
eof = _rl_nsearch_callback (_rl_nscxt);
|
||||
return;
|
||||
}
|
||||
else if (RL_ISSTATE (RL_STATE_NUMERICARG))
|
||||
{
|
||||
eof = _rl_arg_callback (_rl_argcxt);
|
||||
if (eof == 0 && (RL_ISSTATE (RL_STATE_NUMERICARG) == 0) && RL_ISSTATE (RL_STATE_INPUTPENDING))
|
||||
rl_callback_read_char ();
|
||||
/* XXX - this should handle _rl_last_command_was_kill better */
|
||||
else if (RL_ISSTATE (RL_STATE_NUMERICARG) == 0)
|
||||
_rl_internal_char_cleanup ();
|
||||
|
||||
return;
|
||||
}
|
||||
else if (RL_ISSTATE (RL_STATE_MULTIKEY))
|
||||
{
|
||||
eof = _rl_dispatch_callback (_rl_kscxt); /* For now */
|
||||
while ((eof == -1 || eof == -2) && RL_ISSTATE (RL_STATE_MULTIKEY) && _rl_kscxt && (_rl_kscxt->flags & KSEQ_DISPATCHED))
|
||||
eof = _rl_dispatch_callback (_rl_kscxt);
|
||||
if (RL_ISSTATE (RL_STATE_MULTIKEY) == 0)
|
||||
{
|
||||
_rl_internal_char_cleanup ();
|
||||
_rl_want_redisplay = 1;
|
||||
}
|
||||
}
|
||||
else if (_rl_callback_func)
|
||||
{
|
||||
/* This allows functions that simply need to read an additional character
|
||||
(like quoted-insert) to register a function to be called when input is
|
||||
available. _rl_callback_data is simply a pointer to a struct that has
|
||||
the argument count originally passed to the registering function and
|
||||
space for any additional parameters. */
|
||||
eof = (*_rl_callback_func) (_rl_callback_data);
|
||||
/* If the function `deregisters' itself, make sure the data is cleaned
|
||||
up. */
|
||||
if (_rl_callback_func == 0)
|
||||
{
|
||||
if (_rl_callback_data)
|
||||
{
|
||||
_rl_callback_data_dispose (_rl_callback_data);
|
||||
_rl_callback_data = 0;
|
||||
}
|
||||
_rl_internal_char_cleanup ();
|
||||
}
|
||||
}
|
||||
else
|
||||
eof = readline_internal_char ();
|
||||
|
||||
if (rl_done == 0 && _rl_want_redisplay)
|
||||
{
|
||||
(*rl_redisplay_function) ();
|
||||
_rl_want_redisplay = 0;
|
||||
}
|
||||
|
||||
/* We loop in case some function has pushed input back with rl_execute_next. */
|
||||
for (;;)
|
||||
{
|
||||
if (rl_done)
|
||||
{
|
||||
line = readline_internal_teardown (eof);
|
||||
|
||||
if (rl_deprep_term_function)
|
||||
(*rl_deprep_term_function) ();
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
rl_clear_signals ();
|
||||
#endif
|
||||
in_handler = 0;
|
||||
(*rl_linefunc) (line);
|
||||
|
||||
/* If the user did not clear out the line, do it for him. */
|
||||
if (rl_line_buffer[0])
|
||||
_rl_init_line_state ();
|
||||
|
||||
/* Redisplay the prompt if readline_handler_{install,remove}
|
||||
not called. */
|
||||
if (in_handler == 0 && rl_linefunc)
|
||||
_rl_callback_newline ();
|
||||
}
|
||||
if (rl_pending_input || _rl_pushed_input_available () || RL_ISSTATE (RL_STATE_MACROINPUT))
|
||||
eof = readline_internal_char ();
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the handler, and make sure the terminal is in its normal state. */
|
||||
void
|
||||
rl_callback_handler_remove ()
|
||||
{
|
||||
rl_linefunc = NULL;
|
||||
RL_UNSETSTATE (RL_STATE_CALLBACK);
|
||||
if (in_handler)
|
||||
{
|
||||
in_handler = 0;
|
||||
if (rl_deprep_term_function)
|
||||
(*rl_deprep_term_function) ();
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
rl_clear_signals ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
_rl_callback_generic_arg *
|
||||
_rl_callback_data_alloc (count)
|
||||
int count;
|
||||
{
|
||||
_rl_callback_generic_arg *arg;
|
||||
|
||||
arg = (_rl_callback_generic_arg *)xmalloc (sizeof (_rl_callback_generic_arg));
|
||||
arg->count = count;
|
||||
|
||||
arg->i1 = arg->i2 = 0;
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
void _rl_callback_data_dispose (arg)
|
||||
_rl_callback_generic_arg *arg;
|
||||
{
|
||||
if (arg)
|
||||
free (arg);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -244,12 +244,12 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
|
||||
invfl = 0; /* invisible chars in first line of prompt */
|
||||
invflset = 0; /* we only want to set invfl once */
|
||||
|
||||
igstart = -1;
|
||||
igstart = 0;
|
||||
for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
|
||||
{
|
||||
/* This code strips the invisible character string markers
|
||||
RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
|
||||
if (*p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
|
||||
if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
|
||||
{
|
||||
ignoring = 1;
|
||||
igstart = p;
|
||||
@@ -258,7 +258,7 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
|
||||
else if (ignoring && *p == RL_PROMPT_END_IGNORE)
|
||||
{
|
||||
ignoring = 0;
|
||||
if (p[-1] != RL_PROMPT_START_IGNORE)
|
||||
if (p != (igstart + 1))
|
||||
last = r - ret - 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1166,7 +1166,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
|
||||
int col_lendiff, col_temp;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
mbstate_t ps_new, ps_old;
|
||||
int new_offset, old_offset, tmp;
|
||||
int new_offset, old_offset;
|
||||
#endif
|
||||
|
||||
/* If we're at the right edge of a terminal that supports xn, we're
|
||||
|
||||
@@ -220,7 +220,7 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
|
||||
char *pmt;
|
||||
int *lp, *lip, *niflp, *vlp;
|
||||
{
|
||||
char *r, *ret, *p;
|
||||
char *r, *ret, *p, *igstart;
|
||||
int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
|
||||
|
||||
/* Short-circuit if we can. */
|
||||
@@ -244,19 +244,21 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
|
||||
invfl = 0; /* invisible chars in first line of prompt */
|
||||
invflset = 0; /* we only want to set invfl once */
|
||||
|
||||
igstart = 0;
|
||||
for (rl = ignoring = last = ninvis = physchars = 0, p = pmt; p && *p; p++)
|
||||
{
|
||||
/* This code strips the invisible character string markers
|
||||
RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE */
|
||||
if (*p == RL_PROMPT_START_IGNORE)
|
||||
if (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
|
||||
{
|
||||
ignoring++;
|
||||
ignoring = 1;
|
||||
igstart = p;
|
||||
continue;
|
||||
}
|
||||
else if (ignoring && *p == RL_PROMPT_END_IGNORE)
|
||||
{
|
||||
ignoring = 0;
|
||||
if (p[-1] != RL_PROMPT_START_IGNORE)
|
||||
if (p != (igstart + 1))
|
||||
last = r - ret - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ 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. */
|
||||
static char *prev_line_found;
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,666 @@
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* I-Search and Searching */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file contains the Readline Library (the Library), a set of
|
||||
routines for providing Emacs style line input to programs that ask
|
||||
for it.
|
||||
|
||||
The Library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
The Library 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.
|
||||
|
||||
The GNU General Public License is often shipped with GNU software, and
|
||||
is generally kept in a file called COPYING or LICENSE. If you do not
|
||||
have a copy of the license, write to the Free Software Foundation,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
#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. */
|
||||
static char *prev_line_found;
|
||||
|
||||
/* Last search string and its length. */
|
||||
static char *last_isearch_string;
|
||||
static int last_isearch_string_len;
|
||||
|
||||
static char *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->history_pos = 0;
|
||||
cxt->direction = 0;
|
||||
|
||||
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);
|
||||
|
||||
free (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, reverse_p, where)
|
||||
char *search_string;
|
||||
int reverse_p, where;
|
||||
{
|
||||
char *message;
|
||||
int msglen, searchlen;
|
||||
|
||||
searchlen = (search_string && *search_string) ? strlen (search_string) : 0;
|
||||
|
||||
message = (char *)xmalloc (searchlen + 33);
|
||||
msglen = 0;
|
||||
|
||||
#if defined (NOTDEF)
|
||||
if (where != -1)
|
||||
{
|
||||
sprintf (message, "[%d]", where + history_base);
|
||||
msglen = strlen (message);
|
||||
}
|
||||
#endif /* NOTDEF */
|
||||
|
||||
message[msglen++] = '(';
|
||||
|
||||
if (reverse_p)
|
||||
{
|
||||
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);
|
||||
free (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)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
|
||||
#endif
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Translate the keys we do something with to opcodes. */
|
||||
if (c >= 0 && _rl_keymap[c].type == ISFUNC)
|
||||
{
|
||||
f = _rl_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'))
|
||||
cxt->lastc = -4;
|
||||
else if (c == CTRL ('W')) /* XXX */
|
||||
cxt->lastc = -5;
|
||||
else if (c == CTRL ('Y')) /* XXX */
|
||||
cxt->lastc = -6;
|
||||
}
|
||||
|
||||
/* 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 (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);
|
||||
}
|
||||
|
||||
#define ENDSRCH_CHAR(c) \
|
||||
((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
|
||||
|
||||
#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 c; 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 & SF_REVERSE), -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;
|
||||
for (j = 0, l = strlen (cxt->mb); j < l; )
|
||||
cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
cxt->search_string[cxt->search_string_index++] = c;
|
||||
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;
|
||||
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 & SF_REVERSE), (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 & SF_REVERSE), -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
|
||||
@@ -212,6 +212,8 @@ rl_digit_loop ()
|
||||
if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Create a default argument. */
|
||||
|
||||
@@ -0,0 +1,601 @@
|
||||
/* misc.c -- miscellaneous bindable readline functions. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library, a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
|
||||
The GNU Readline Library is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version.
|
||||
|
||||
The GNU Readline Library 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.
|
||||
|
||||
The GNU General Public License is often shipped with GNU software, and
|
||||
is generally kept in a file called COPYING or LICENSE. If you do not
|
||||
have a copy of the license, write to the Free Software Foundation,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if defined (HAVE_LOCALE_H)
|
||||
# include <locale.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
#include "rlmbutil.h"
|
||||
|
||||
/* Some standard library routines. */
|
||||
#include "readline.h"
|
||||
#include "history.h"
|
||||
|
||||
#include "rlprivate.h"
|
||||
#include "rlshell.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
static int rl_digit_loop PARAMS((void));
|
||||
static void _rl_history_set_point PARAMS((void));
|
||||
|
||||
/* Forward declarations used in this file */
|
||||
void _rl_free_history_entry PARAMS((HIST_ENTRY *));
|
||||
|
||||
/* If non-zero, rl_get_previous_history and rl_get_next_history attempt
|
||||
to preserve the value of rl_point from line to line. */
|
||||
int _rl_history_preserve_point = 0;
|
||||
|
||||
_rl_arg_cxt _rl_argcxt;
|
||||
|
||||
/* Saved target point for when _rl_history_preserve_point is set. Special
|
||||
value of -1 means that point is at the end of the line. */
|
||||
int _rl_history_saved_point = -1;
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Numeric Arguments */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
int
|
||||
_rl_arg_overflow ()
|
||||
{
|
||||
if (rl_numeric_arg > 1000000)
|
||||
{
|
||||
_rl_argcxt = 0;
|
||||
rl_explicit_arg = rl_numeric_arg = 0;
|
||||
rl_ding ();
|
||||
rl_restore_prompt ();
|
||||
rl_clear_message ();
|
||||
RL_UNSETSTATE(RL_STATE_NUMERICARG);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_rl_arg_init ()
|
||||
{
|
||||
rl_save_prompt ();
|
||||
_rl_argcxt = 0;
|
||||
RL_SETSTATE(RL_STATE_NUMERICARG);
|
||||
}
|
||||
|
||||
int
|
||||
_rl_arg_getchar ()
|
||||
{
|
||||
int c;
|
||||
|
||||
rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
c = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* Process C as part of the current numeric argument. Return -1 if the
|
||||
argument should be aborted, 0 if we should not read any more chars, and
|
||||
1 if we should continue to read chars. */
|
||||
int
|
||||
_rl_arg_dispatch (cxt, c)
|
||||
_rl_arg_cxt cxt;
|
||||
int c;
|
||||
{
|
||||
int key, r;
|
||||
|
||||
key = c;
|
||||
|
||||
/* If we see a key bound to `universal-argument' after seeing digits,
|
||||
it ends the argument but is otherwise ignored. */
|
||||
if (_rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
|
||||
{
|
||||
if ((cxt & NUM_SAWDIGITS) == 0)
|
||||
{
|
||||
rl_numeric_arg *= 4;
|
||||
return 1;
|
||||
}
|
||||
else if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
{
|
||||
_rl_argcxt |= NUM_READONE;
|
||||
return 0; /* XXX */
|
||||
}
|
||||
else
|
||||
{
|
||||
RL_SETSTATE(RL_STATE_MOREINPUT);
|
||||
key = rl_read_key ();
|
||||
RL_UNSETSTATE(RL_STATE_MOREINPUT);
|
||||
rl_restore_prompt ();
|
||||
rl_clear_message ();
|
||||
RL_UNSETSTATE(RL_STATE_NUMERICARG);
|
||||
return (_rl_dispatch (key, _rl_keymap));
|
||||
}
|
||||
}
|
||||
|
||||
c = UNMETA (c);
|
||||
|
||||
if (_rl_digit_p (c))
|
||||
{
|
||||
r = _rl_digit_value (c);
|
||||
rl_numeric_arg = rl_explicit_arg ? (rl_numeric_arg * 10) + r : r;
|
||||
rl_explicit_arg = 1;
|
||||
_rl_argcxt |= NUM_SAWDIGITS;
|
||||
}
|
||||
else if (c == '-' && rl_explicit_arg == 0)
|
||||
{
|
||||
rl_numeric_arg = 1;
|
||||
_rl_argcxt |= NUM_SAWMINUS;
|
||||
rl_arg_sign = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make M-- command equivalent to M--1 command. */
|
||||
if ((_rl_argcxt & NUM_SAWMINUS) && rl_numeric_arg == 1 && rl_explicit_arg == 0)
|
||||
rl_explicit_arg = 1;
|
||||
rl_restore_prompt ();
|
||||
rl_clear_message ();
|
||||
RL_UNSETSTATE(RL_STATE_NUMERICARG);
|
||||
|
||||
r = _rl_dispatch (key, _rl_keymap);
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
{
|
||||
/* At worst, this will cause an extra redisplay. Otherwise,
|
||||
we have to wait until the next character comes in. */
|
||||
if (rl_done == 0)
|
||||
(*rl_redisplay_function) ();
|
||||
r = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handle C-u style numeric args, as well as M--, and M-digits. */
|
||||
static int
|
||||
rl_digit_loop ()
|
||||
{
|
||||
int c, r;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (_rl_arg_overflow ())
|
||||
return 1;
|
||||
|
||||
c = _rl_arg_getchar ();
|
||||
|
||||
if (c < 0)
|
||||
{
|
||||
_rl_abort_internal ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = _rl_arg_dispatch (_rl_argcxt, c);
|
||||
if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a default argument. */
|
||||
void
|
||||
_rl_reset_argument ()
|
||||
{
|
||||
rl_numeric_arg = rl_arg_sign = 1;
|
||||
rl_explicit_arg = 0;
|
||||
_rl_argcxt = 0;
|
||||
}
|
||||
|
||||
/* Start a numeric argument with initial value KEY */
|
||||
int
|
||||
rl_digit_argument (ignore, key)
|
||||
int ignore, key;
|
||||
{
|
||||
_rl_arg_init ();
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
{
|
||||
_rl_arg_dispatch (_rl_argcxt, key);
|
||||
rl_message ("(arg: %d) ", rl_arg_sign * rl_numeric_arg);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rl_execute_next (key);
|
||||
return (rl_digit_loop ());
|
||||
}
|
||||
}
|
||||
|
||||
/* C-u, universal argument. Multiply the current argument by 4.
|
||||
Read a key. If the key has nothing to do with arguments, then
|
||||
dispatch on it. If the key is the abort character then abort. */
|
||||
int
|
||||
rl_universal_argument (count, key)
|
||||
int count, key;
|
||||
{
|
||||
_rl_arg_init ();
|
||||
rl_numeric_arg *= 4;
|
||||
|
||||
return (RL_ISSTATE (RL_STATE_CALLBACK) ? 0 : rl_digit_loop ());
|
||||
}
|
||||
|
||||
int
|
||||
_rl_arg_callback (cxt)
|
||||
_rl_arg_cxt cxt;
|
||||
{
|
||||
int c, r;
|
||||
|
||||
c = _rl_arg_getchar ();
|
||||
|
||||
if (_rl_argcxt & NUM_READONE)
|
||||
{
|
||||
_rl_argcxt &= ~NUM_READONE;
|
||||
rl_restore_prompt ();
|
||||
rl_clear_message ();
|
||||
RL_UNSETSTATE(RL_STATE_NUMERICARG);
|
||||
rl_execute_next (c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = _rl_arg_dispatch (cxt, c);
|
||||
return (r != 1);
|
||||
}
|
||||
|
||||
/* What to do when you abort reading an argument. */
|
||||
int
|
||||
rl_discard_argument ()
|
||||
{
|
||||
rl_ding ();
|
||||
rl_clear_message ();
|
||||
_rl_reset_argument ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* History Utilities */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* We already have a history library, and that is what we use to control
|
||||
the history features of readline. This is our local interface to
|
||||
the history mechanism. */
|
||||
|
||||
/* While we are editing the history, this is the saved
|
||||
version of the original line. */
|
||||
HIST_ENTRY *_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
|
||||
/* Set the history pointer back to the last entry in the history. */
|
||||
void
|
||||
_rl_start_using_history ()
|
||||
{
|
||||
using_history ();
|
||||
if (_rl_saved_line_for_history)
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
/* Free the contents (and containing structure) of a HIST_ENTRY. */
|
||||
void
|
||||
_rl_free_history_entry (entry)
|
||||
HIST_ENTRY *entry;
|
||||
{
|
||||
if (entry == 0)
|
||||
return;
|
||||
|
||||
FREE (entry->line);
|
||||
FREE (entry->timestamp);
|
||||
|
||||
free (entry);
|
||||
}
|
||||
|
||||
/* Perhaps put back the current line if it has changed. */
|
||||
int
|
||||
rl_maybe_replace_line ()
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
|
||||
temp = current_history ();
|
||||
/* If the current line has changed, save the changes. */
|
||||
if (temp && ((UNDO_LIST *)(temp->data) != rl_undo_list))
|
||||
{
|
||||
temp = replace_history_entry (where_history (), rl_line_buffer, (histdata_t)rl_undo_list);
|
||||
free (temp->line);
|
||||
FREE (temp->timestamp);
|
||||
free (temp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Restore the _rl_saved_line_for_history if there is one. */
|
||||
int
|
||||
rl_maybe_unsave_line ()
|
||||
{
|
||||
if (_rl_saved_line_for_history)
|
||||
{
|
||||
/* Can't call with `1' because rl_undo_list might point to an undo
|
||||
list from a history entry, as in rl_replace_from_history() below. */
|
||||
rl_replace_line (_rl_saved_line_for_history->line, 0);
|
||||
rl_undo_list = (UNDO_LIST *)_rl_saved_line_for_history->data;
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
rl_point = rl_end; /* rl_replace_line sets rl_end */
|
||||
}
|
||||
else
|
||||
rl_ding ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Save the current line in _rl_saved_line_for_history. */
|
||||
int
|
||||
rl_maybe_save_line ()
|
||||
{
|
||||
if (_rl_saved_line_for_history == 0)
|
||||
{
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
|
||||
_rl_saved_line_for_history->line = savestring (rl_line_buffer);
|
||||
_rl_saved_line_for_history->timestamp = (char *)NULL;
|
||||
_rl_saved_line_for_history->data = (char *)rl_undo_list;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_rl_free_saved_history_line ()
|
||||
{
|
||||
if (_rl_saved_line_for_history)
|
||||
{
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_history_set_point ()
|
||||
{
|
||||
rl_point = (_rl_history_preserve_point && _rl_history_saved_point != -1)
|
||||
? _rl_history_saved_point
|
||||
: rl_end;
|
||||
if (rl_point > rl_end)
|
||||
rl_point = rl_end;
|
||||
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode && _rl_keymap != vi_insertion_keymap)
|
||||
rl_point = 0;
|
||||
#endif /* VI_MODE */
|
||||
|
||||
if (rl_editing_mode == emacs_mode)
|
||||
rl_mark = (rl_point == rl_end ? 0 : rl_end);
|
||||
}
|
||||
|
||||
void
|
||||
rl_replace_from_history (entry, flags)
|
||||
HIST_ENTRY *entry;
|
||||
int flags; /* currently unused */
|
||||
{
|
||||
/* Can't call with `1' because rl_undo_list might point to an undo list
|
||||
from a history entry, just like we're setting up here. */
|
||||
rl_replace_line (entry->line, 0);
|
||||
rl_undo_list = (UNDO_LIST *)entry->data;
|
||||
rl_point = rl_end;
|
||||
rl_mark = 0;
|
||||
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode)
|
||||
{
|
||||
rl_point = 0;
|
||||
rl_mark = rl_end;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* History Commands */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* Meta-< goes to the start of the history. */
|
||||
int
|
||||
rl_beginning_of_history (count, key)
|
||||
int count, key;
|
||||
{
|
||||
return (rl_get_previous_history (1 + where_history (), key));
|
||||
}
|
||||
|
||||
/* Meta-> goes to the end of the history. (The current line). */
|
||||
int
|
||||
rl_end_of_history (count, key)
|
||||
int count, key;
|
||||
{
|
||||
rl_maybe_replace_line ();
|
||||
using_history ();
|
||||
rl_maybe_unsave_line ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Move down to the next history line. */
|
||||
int
|
||||
rl_get_next_history (count, key)
|
||||
int count, key;
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
|
||||
if (count < 0)
|
||||
return (rl_get_previous_history (-count, key));
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
rl_maybe_replace_line ();
|
||||
|
||||
/* either not saved by rl_newline or at end of line, so set appropriately. */
|
||||
if (_rl_history_saved_point == -1 && (rl_point || rl_end))
|
||||
_rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
|
||||
|
||||
temp = (HIST_ENTRY *)NULL;
|
||||
while (count)
|
||||
{
|
||||
temp = next_history ();
|
||||
if (!temp)
|
||||
break;
|
||||
--count;
|
||||
}
|
||||
|
||||
if (temp == 0)
|
||||
rl_maybe_unsave_line ();
|
||||
else
|
||||
{
|
||||
rl_replace_from_history (temp, 0);
|
||||
_rl_history_set_point ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the previous item out of our interactive history, making it the current
|
||||
line. If there is no previous history, just ding. */
|
||||
int
|
||||
rl_get_previous_history (count, key)
|
||||
int count, key;
|
||||
{
|
||||
HIST_ENTRY *old_temp, *temp;
|
||||
|
||||
if (count < 0)
|
||||
return (rl_get_next_history (-count, key));
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
/* either not saved by rl_newline or at end of line, so set appropriately. */
|
||||
if (_rl_history_saved_point == -1 && (rl_point || rl_end))
|
||||
_rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
|
||||
|
||||
/* If we don't have a line saved, then save this one. */
|
||||
rl_maybe_save_line ();
|
||||
|
||||
/* If the current line has changed, save the changes. */
|
||||
rl_maybe_replace_line ();
|
||||
|
||||
temp = old_temp = (HIST_ENTRY *)NULL;
|
||||
while (count)
|
||||
{
|
||||
temp = previous_history ();
|
||||
if (temp == 0)
|
||||
break;
|
||||
|
||||
old_temp = temp;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* If there was a large argument, and we moved back to the start of the
|
||||
history, that is not an error. So use the last value found. */
|
||||
if (!temp && old_temp)
|
||||
temp = old_temp;
|
||||
|
||||
if (temp == 0)
|
||||
rl_ding ();
|
||||
else
|
||||
{
|
||||
rl_replace_from_history (temp, 0);
|
||||
_rl_history_set_point ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Editing Modes */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
/* How to toggle back and forth between editing modes. */
|
||||
int
|
||||
rl_vi_editing_mode (count, key)
|
||||
int count, key;
|
||||
{
|
||||
#if defined (VI_MODE)
|
||||
_rl_set_insert_mode (RL_IM_INSERT, 1); /* vi mode ignores insert mode */
|
||||
rl_editing_mode = vi_mode;
|
||||
rl_vi_insertion_mode (1, key);
|
||||
#endif /* VI_MODE */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rl_emacs_editing_mode (count, key)
|
||||
int count, key;
|
||||
{
|
||||
rl_editing_mode = emacs_mode;
|
||||
_rl_set_insert_mode (RL_IM_INSERT, 1); /* emacs mode default is insert mode */
|
||||
_rl_keymap = emacs_standard_keymap;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function for the rest of the library to use to set insert/overwrite mode. */
|
||||
void
|
||||
_rl_set_insert_mode (im, force)
|
||||
int im, force;
|
||||
{
|
||||
#ifdef CURSOR_MODE
|
||||
_rl_set_cursor (im, force);
|
||||
#endif
|
||||
|
||||
rl_insert_mode = im;
|
||||
}
|
||||
|
||||
/* Toggle overwrite mode. A positive explicit argument selects overwrite
|
||||
mode. A negative or zero explicit argument selects insert mode. */
|
||||
int
|
||||
rl_overwrite_mode (count, key)
|
||||
int count, key;
|
||||
{
|
||||
if (rl_explicit_arg == 0)
|
||||
_rl_set_insert_mode (rl_insert_mode ^ 1, 0);
|
||||
else if (count > 0)
|
||||
_rl_set_insert_mode (RL_IM_OVERWRITE, 0);
|
||||
else
|
||||
_rl_set_insert_mode (RL_IM_INSERT, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -933,7 +933,6 @@ rltty_set_default_bindings (kmap)
|
||||
#if !defined (NO_TTY_DRIVER)
|
||||
TIOTYPE ttybuff;
|
||||
int tty;
|
||||
static int called = 0;
|
||||
|
||||
tty = fileno (rl_instream);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -70,7 +70,6 @@ static int rl_history_search_pos;
|
||||
static char *history_search_string;
|
||||
static int history_string_size;
|
||||
|
||||
static UNDO_LIST *noninc_saved_undo_list;
|
||||
static void make_history_line_current PARAMS((HIST_ENTRY *));
|
||||
static int noninc_search_from_pos PARAMS((char *, int, int));
|
||||
static int noninc_dosearch PARAMS((char *, int));
|
||||
|
||||
@@ -0,0 +1,572 @@
|
||||
/* search.c - code for non-incremental searching in emacs and vi modes. */
|
||||
|
||||
/* Copyright (C) 1992-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the Readline Library (the Library), a set of
|
||||
routines for providing Emacs style line input to programs that ask
|
||||
for it.
|
||||
|
||||
The Library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
The Library 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.
|
||||
|
||||
The GNU General Public License is often shipped with GNU software, and
|
||||
is generally kept in a file called COPYING or LICENSE. If you do not
|
||||
have a copy of the license, write to the Free Software Foundation,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
#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"
|
||||
|
||||
#ifdef abs
|
||||
# undef abs
|
||||
#endif
|
||||
#define abs(x) (((x) >= 0) ? (x) : -(x))
|
||||
|
||||
_rl_search_cxt *_rl_nscxt = 0;
|
||||
|
||||
extern HIST_ENTRY *_rl_saved_line_for_history;
|
||||
|
||||
/* Functions imported from the rest of the library. */
|
||||
extern int _rl_free_history_entry PARAMS((HIST_ENTRY *));
|
||||
|
||||
static char *noninc_search_string = (char *) NULL;
|
||||
static int noninc_history_pos;
|
||||
|
||||
static char *prev_line_found = (char *) NULL;
|
||||
|
||||
static int rl_history_search_len;
|
||||
static int rl_history_search_pos;
|
||||
static char *history_search_string;
|
||||
static int history_string_size;
|
||||
|
||||
static UNDO_LIST *noninc_saved_undo_list;
|
||||
static void make_history_line_current PARAMS((HIST_ENTRY *));
|
||||
static int noninc_search_from_pos PARAMS((char *, int, int));
|
||||
static int noninc_dosearch PARAMS((char *, int));
|
||||
static int noninc_search PARAMS((int, int));
|
||||
static int rl_history_search_internal PARAMS((int, int));
|
||||
static void rl_history_search_reinit PARAMS((void));
|
||||
|
||||
static _rl_search_cxt *_rl_nsearch_init PARAMS((int, int));
|
||||
static int _rl_nsearch_cleanup PARAMS((_rl_search_cxt *, int));
|
||||
static void _rl_nsearch_abort PARAMS((_rl_search_cxt *));
|
||||
static int _rl_nsearch_dispatch PARAMS((_rl_search_cxt *, int));
|
||||
|
||||
/* Make the data from the history entry ENTRY be the contents of the
|
||||
current line. This doesn't do anything with rl_point; the caller
|
||||
must set it. */
|
||||
static void
|
||||
make_history_line_current (entry)
|
||||
HIST_ENTRY *entry;
|
||||
{
|
||||
_rl_replace_text (entry->line, 0, rl_end);
|
||||
_rl_fix_point (1);
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode == vi_mode)
|
||||
/* POSIX.2 says that the `U' command doesn't affect the copy of any
|
||||
command lines to the edit line. We're going to implement that by
|
||||
making the undo list start after the matching line is copied to the
|
||||
current editing buffer. */
|
||||
rl_free_undo_list ();
|
||||
#endif
|
||||
|
||||
if (_rl_saved_line_for_history)
|
||||
_rl_free_history_entry (_rl_saved_line_for_history);
|
||||
_rl_saved_line_for_history = (HIST_ENTRY *)NULL;
|
||||
}
|
||||
|
||||
/* Search the history list for STRING starting at absolute history position
|
||||
POS. If STRING begins with `^', the search must match STRING at the
|
||||
beginning of a history line, otherwise a full substring match is performed
|
||||
for STRING. DIR < 0 means to search backwards through the history list,
|
||||
DIR >= 0 means to search forward. */
|
||||
static int
|
||||
noninc_search_from_pos (string, pos, dir)
|
||||
char *string;
|
||||
int pos, dir;
|
||||
{
|
||||
int ret, old;
|
||||
|
||||
if (pos < 0)
|
||||
return -1;
|
||||
|
||||
old = where_history ();
|
||||
if (history_set_pos (pos) == 0)
|
||||
return -1;
|
||||
|
||||
RL_SETSTATE(RL_STATE_SEARCH);
|
||||
if (*string == '^')
|
||||
ret = history_search_prefix (string + 1, dir);
|
||||
else
|
||||
ret = history_search (string, dir);
|
||||
RL_UNSETSTATE(RL_STATE_SEARCH);
|
||||
|
||||
if (ret != -1)
|
||||
ret = where_history ();
|
||||
|
||||
history_set_pos (old);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Search for a line in the history containing STRING. If DIR is < 0, the
|
||||
search is backwards through previous entries, else through subsequent
|
||||
entries. Returns 1 if the search was successful, 0 otherwise. */
|
||||
static int
|
||||
noninc_dosearch (string, dir)
|
||||
char *string;
|
||||
int dir;
|
||||
{
|
||||
int oldpos, pos;
|
||||
HIST_ENTRY *entry;
|
||||
|
||||
if (string == 0 || *string == '\0' || noninc_history_pos < 0)
|
||||
{
|
||||
rl_ding ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
pos = noninc_search_from_pos (string, noninc_history_pos + dir, dir);
|
||||
if (pos == -1)
|
||||
{
|
||||
/* Search failed, current history position unchanged. */
|
||||
rl_maybe_unsave_line ();
|
||||
rl_clear_message ();
|
||||
rl_point = 0;
|
||||
rl_ding ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
noninc_history_pos = pos;
|
||||
|
||||
oldpos = where_history ();
|
||||
history_set_pos (noninc_history_pos);
|
||||
entry = current_history ();
|
||||
#if defined (VI_MODE)
|
||||
if (rl_editing_mode != vi_mode)
|
||||
#endif
|
||||
history_set_pos (oldpos);
|
||||
|
||||
make_history_line_current (entry);
|
||||
|
||||
rl_point = 0;
|
||||
rl_mark = rl_end;
|
||||
|
||||
rl_clear_message ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static _rl_search_cxt *
|
||||
_rl_nsearch_init (dir, pchar)
|
||||
int dir, pchar;
|
||||
{
|
||||
_rl_search_cxt *cxt;
|
||||
char *p;
|
||||
|
||||
cxt = _rl_scxt_alloc (RL_SEARCH_NSEARCH, 0);
|
||||
if (dir < 0)
|
||||
cxt->sflags |= SF_REVERSE; /* not strictly needed */
|
||||
|
||||
cxt->direction = dir;
|
||||
cxt->history_pos = cxt->save_line;
|
||||
|
||||
rl_maybe_save_line ();
|
||||
|
||||
/* Clear the undo list, since reading the search string should create its
|
||||
own undo list, and the whole list will end up being freed when we
|
||||
finish reading the search string. */
|
||||
rl_undo_list = 0;
|
||||
|
||||
/* Use the line buffer to read the search string. */
|
||||
rl_line_buffer[0] = 0;
|
||||
rl_end = rl_point = 0;
|
||||
|
||||
p = _rl_make_prompt_for_search (pchar ? pchar : ':');
|
||||
rl_message (p, 0, 0);
|
||||
free (p);
|
||||
|
||||
RL_SETSTATE(RL_STATE_NSEARCH);
|
||||
|
||||
_rl_nscxt = cxt;
|
||||
|
||||
return cxt;
|
||||
}
|
||||
|
||||
static int
|
||||
_rl_nsearch_cleanup (cxt, r)
|
||||
_rl_search_cxt *cxt;
|
||||
int r;
|
||||
{
|
||||
_rl_scxt_dispose (cxt, 0);
|
||||
_rl_nscxt = 0;
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_NSEARCH);
|
||||
|
||||
return (r != 1);
|
||||
}
|
||||
|
||||
static void
|
||||
_rl_nsearch_abort (cxt)
|
||||
_rl_search_cxt *cxt;
|
||||
{
|
||||
rl_maybe_unsave_line ();
|
||||
rl_clear_message ();
|
||||
rl_point = cxt->save_point;
|
||||
rl_mark = cxt->save_mark;
|
||||
rl_restore_prompt ();
|
||||
|
||||
RL_UNSETSTATE (RL_STATE_NSEARCH);
|
||||
}
|
||||
|
||||
/* Process just-read character C according to search context CXT. Return -1
|
||||
if the caller should abort the search, 0 if we should break out of the
|
||||
loop, and 1 if we should continue to read characters. */
|
||||
static int
|
||||
_rl_nsearch_dispatch (cxt, c)
|
||||
_rl_search_cxt *cxt;
|
||||
int c;
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case CTRL('W'):
|
||||
rl_unix_word_rubout (1, c);
|
||||
break;
|
||||
|
||||
case CTRL('U'):
|
||||
rl_unix_line_discard (1, c);
|
||||
break;
|
||||
|
||||
case RETURN:
|
||||
case NEWLINE:
|
||||
return 0;
|
||||
|
||||
case CTRL('H'):
|
||||
case RUBOUT:
|
||||
if (rl_point == 0)
|
||||
{
|
||||
_rl_nsearch_abort (cxt);
|
||||
return -1;
|
||||
}
|
||||
_rl_rubout_char (1, c);
|
||||
break;
|
||||
|
||||
case CTRL('C'):
|
||||
case CTRL('G'):
|
||||
rl_ding ();
|
||||
_rl_nsearch_abort (cxt);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
|
||||
rl_insert_text (cxt->mb);
|
||||
else
|
||||
#endif
|
||||
_rl_insert_char (1, c);
|
||||
break;
|
||||
}
|
||||
|
||||
(*rl_redisplay_function) ();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Perform one search according to CXT, using NONINC_SEARCH_STRING. Return
|
||||
-1 if the search should be aborted, any other value means to clean up
|
||||
using _rl_nsearch_cleanup (). Returns 1 if the search was successful,
|
||||
0 otherwise. */
|
||||
static int
|
||||
_rl_nsearch_dosearch (cxt)
|
||||
_rl_search_cxt *cxt;
|
||||
{
|
||||
rl_mark = cxt->save_mark;
|
||||
|
||||
/* If rl_point == 0, we want to re-use the previous search string and
|
||||
start from the saved history position. If there's no previous search
|
||||
string, punt. */
|
||||
if (rl_point == 0)
|
||||
{
|
||||
if (noninc_search_string == 0)
|
||||
{
|
||||
rl_ding ();
|
||||
rl_restore_prompt ();
|
||||
RL_UNSETSTATE (RL_STATE_NSEARCH);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We want to start the search from the current history position. */
|
||||
noninc_history_pos = cxt->save_line;
|
||||
FREE (noninc_search_string);
|
||||
noninc_search_string = savestring (rl_line_buffer);
|
||||
|
||||
/* If we don't want the subsequent undo list generated by the search
|
||||
matching a history line to include the contents of the search string,
|
||||
we need to clear rl_line_buffer here. For now, we just clear the
|
||||
undo list generated by reading the search string. (If the search
|
||||
fails, the old undo list will be restored by rl_maybe_unsave_line.) */
|
||||
rl_free_undo_list ();
|
||||
}
|
||||
|
||||
rl_restore_prompt ();
|
||||
return (noninc_dosearch (noninc_search_string, cxt->direction));
|
||||
}
|
||||
|
||||
/* Search non-interactively through the history list. DIR < 0 means to
|
||||
search backwards through the history of previous commands; otherwise
|
||||
the search is for commands subsequent to the current position in the
|
||||
history list. PCHAR is the character to use for prompting when reading
|
||||
the search string; if not specified (0), it defaults to `:'. */
|
||||
static int
|
||||
noninc_search (dir, pchar)
|
||||
int dir;
|
||||
int pchar;
|
||||
{
|
||||
_rl_search_cxt *cxt;
|
||||
int c, r;
|
||||
|
||||
cxt = _rl_nsearch_init (dir, pchar);
|
||||
|
||||
if (RL_ISSTATE (RL_STATE_CALLBACK))
|
||||
return (0);
|
||||
|
||||
/* Read the search string. */
|
||||
r = 0;
|
||||
while (1)
|
||||
{
|
||||
c = _rl_search_getchar (cxt);
|
||||
|
||||
if (c == 0)
|
||||
break;
|
||||
|
||||
r = _rl_nsearch_dispatch (cxt, c);
|
||||
if (r < 0)
|
||||
return 1;
|
||||
else if (r == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
r = _rl_nsearch_dosearch (cxt);
|
||||
return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
|
||||
}
|
||||
|
||||
/* Search forward through the history list for a string. If the vi-mode
|
||||
code calls this, KEY will be `?'. */
|
||||
int
|
||||
rl_noninc_forward_search (count, key)
|
||||
int count, key;
|
||||
{
|
||||
return noninc_search (1, (key == '?') ? '?' : 0);
|
||||
}
|
||||
|
||||
/* Reverse search the history list for a string. If the vi-mode code
|
||||
calls this, KEY will be `/'. */
|
||||
int
|
||||
rl_noninc_reverse_search (count, key)
|
||||
int count, key;
|
||||
{
|
||||
return noninc_search (-1, (key == '/') ? '/' : 0);
|
||||
}
|
||||
|
||||
/* Search forward through the history list for the last string searched
|
||||
for. If there is no saved search string, abort. */
|
||||
int
|
||||
rl_noninc_forward_search_again (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!noninc_search_string)
|
||||
{
|
||||
rl_ding ();
|
||||
return (-1);
|
||||
}
|
||||
r = noninc_dosearch (noninc_search_string, 1);
|
||||
return (r != 1);
|
||||
}
|
||||
|
||||
/* Reverse search in the history list for the last string searched
|
||||
for. If there is no saved search string, abort. */
|
||||
int
|
||||
rl_noninc_reverse_search_again (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!noninc_search_string)
|
||||
{
|
||||
rl_ding ();
|
||||
return (-1);
|
||||
}
|
||||
r = noninc_dosearch (noninc_search_string, -1);
|
||||
return (r != 1);
|
||||
}
|
||||
|
||||
#if defined (READLINE_CALLBACKS)
|
||||
int
|
||||
_rl_nsearch_callback (cxt)
|
||||
_rl_search_cxt *cxt;
|
||||
{
|
||||
int c, r;
|
||||
|
||||
c = _rl_search_getchar (cxt);
|
||||
r = _rl_nsearch_dispatch (cxt, c);
|
||||
if (r != 0)
|
||||
return 1;
|
||||
|
||||
r = _rl_nsearch_dosearch (cxt);
|
||||
return ((r >= 0) ? _rl_nsearch_cleanup (cxt, r) : (r != 1));
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
rl_history_search_internal (count, dir)
|
||||
int count, dir;
|
||||
{
|
||||
HIST_ENTRY *temp;
|
||||
int ret, oldpos;
|
||||
|
||||
rl_maybe_save_line ();
|
||||
temp = (HIST_ENTRY *)NULL;
|
||||
|
||||
/* Search COUNT times through the history for a line whose prefix
|
||||
matches history_search_string. When this loop finishes, TEMP,
|
||||
if non-null, is the history line to copy into the line buffer. */
|
||||
while (count)
|
||||
{
|
||||
ret = noninc_search_from_pos (history_search_string, rl_history_search_pos + dir, dir);
|
||||
if (ret == -1)
|
||||
break;
|
||||
|
||||
/* Get the history entry we found. */
|
||||
rl_history_search_pos = ret;
|
||||
oldpos = where_history ();
|
||||
history_set_pos (rl_history_search_pos);
|
||||
temp = current_history ();
|
||||
history_set_pos (oldpos);
|
||||
|
||||
/* Don't find multiple instances of the same line. */
|
||||
if (prev_line_found && STREQ (prev_line_found, temp->line))
|
||||
continue;
|
||||
prev_line_found = temp->line;
|
||||
count--;
|
||||
}
|
||||
|
||||
/* If we didn't find anything at all, return. */
|
||||
if (temp == 0)
|
||||
{
|
||||
rl_maybe_unsave_line ();
|
||||
rl_ding ();
|
||||
/* If you don't want the saved history line (last match) to show up
|
||||
in the line buffer after the search fails, change the #if 0 to
|
||||
#if 1 */
|
||||
#if 0
|
||||
if (rl_point > rl_history_search_len)
|
||||
{
|
||||
rl_point = rl_end = rl_history_search_len;
|
||||
rl_line_buffer[rl_end] = '\0';
|
||||
rl_mark = 0;
|
||||
}
|
||||
#else
|
||||
rl_point = rl_history_search_len; /* rl_maybe_unsave_line changes it */
|
||||
rl_mark = rl_end;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy the line we found into the current line buffer. */
|
||||
make_history_line_current (temp);
|
||||
|
||||
rl_point = rl_history_search_len;
|
||||
rl_mark = rl_end;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rl_history_search_reinit ()
|
||||
{
|
||||
rl_history_search_pos = where_history ();
|
||||
rl_history_search_len = rl_point;
|
||||
prev_line_found = (char *)NULL;
|
||||
if (rl_point)
|
||||
{
|
||||
if (rl_history_search_len >= history_string_size - 2)
|
||||
{
|
||||
history_string_size = rl_history_search_len + 2;
|
||||
history_search_string = (char *)xrealloc (history_search_string, history_string_size);
|
||||
}
|
||||
history_search_string[0] = '^';
|
||||
strncpy (history_search_string + 1, rl_line_buffer, rl_point);
|
||||
history_search_string[rl_point + 1] = '\0';
|
||||
}
|
||||
_rl_free_saved_history_line ();
|
||||
}
|
||||
|
||||
/* Search forward in the history for the string of characters
|
||||
from the start of the line to rl_point. This is a non-incremental
|
||||
search. */
|
||||
int
|
||||
rl_history_search_forward (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
if (count == 0)
|
||||
return (0);
|
||||
|
||||
if (rl_last_func != rl_history_search_forward &&
|
||||
rl_last_func != rl_history_search_backward)
|
||||
rl_history_search_reinit ();
|
||||
|
||||
if (rl_history_search_len == 0)
|
||||
return (rl_get_next_history (count, ignore));
|
||||
return (rl_history_search_internal (abs (count), (count > 0) ? 1 : -1));
|
||||
}
|
||||
|
||||
/* Search backward through the history for the string of characters
|
||||
from the start of the line to rl_point. This is a non-incremental
|
||||
search. */
|
||||
int
|
||||
rl_history_search_backward (count, ignore)
|
||||
int count, ignore;
|
||||
{
|
||||
if (count == 0)
|
||||
return (0);
|
||||
|
||||
if (rl_last_func != rl_history_search_forward &&
|
||||
rl_last_func != rl_history_search_backward)
|
||||
rl_history_search_reinit ();
|
||||
|
||||
if (rl_history_search_len == 0)
|
||||
return (rl_get_previous_history (count, ignore));
|
||||
return (rl_history_search_internal (abs (count), (count > 0) ? -1 : 1));
|
||||
}
|
||||
+41
-1
@@ -160,6 +160,7 @@ rl_signal_handler (sig)
|
||||
rl_cleanup_after_signal ();
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&set);
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
|
||||
sigdelset (&set, sig);
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
@@ -288,9 +289,44 @@ rl_set_signals ()
|
||||
{
|
||||
sighandler_cxt dummy;
|
||||
SigHandler *oh;
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
static int sigmask_set = 0;
|
||||
static sigset_t bset, oset;
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
if (rl_catch_signals && sigmask_set == 0)
|
||||
{
|
||||
sigemptyset (&bset);
|
||||
|
||||
sigaddset (&bset, SIGINT);
|
||||
sigaddset (&bset, SIGINT);
|
||||
#if defined (SIGQUIT)
|
||||
sigaddset (&bset, SIGQUIT);
|
||||
#endif
|
||||
#if defined (SIGALRM)
|
||||
sigaddset (&bset, SIGALRM);
|
||||
#endif
|
||||
#if defined (SIGTSTP)
|
||||
sigaddset (&bset, SIGTSTP);
|
||||
#endif
|
||||
#if defined (SIGTTIN)
|
||||
sigaddset (&bset, SIGTTIN);
|
||||
#endif
|
||||
#if defined (SIGTTOU)
|
||||
sigaddset (&bset, SIGTTOU);
|
||||
#endif
|
||||
sigmask_set = 1;
|
||||
}
|
||||
#endif /* HAVE_POSIX_SIGNALS */
|
||||
|
||||
if (rl_catch_signals && signals_set_flag == 0)
|
||||
{
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&oset);
|
||||
sigprocmask (SIG_BLOCK, &bset, &oset);
|
||||
#endif
|
||||
|
||||
rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
|
||||
rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
|
||||
#if defined (SIGQUIT)
|
||||
@@ -324,6 +360,10 @@ rl_set_signals ()
|
||||
#endif /* SIGTTIN */
|
||||
|
||||
signals_set_flag = 1;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
@@ -390,8 +430,8 @@ rl_cleanup_after_signal ()
|
||||
_rl_clean_up_for_exit ();
|
||||
if (rl_deprep_term_function)
|
||||
(*rl_deprep_term_function) ();
|
||||
rl_clear_signals ();
|
||||
rl_clear_pending_input ();
|
||||
rl_clear_signals ();
|
||||
}
|
||||
|
||||
/* Reset the terminal and readline state after a signal handler returns. */
|
||||
|
||||
@@ -0,0 +1,470 @@
|
||||
/* signals.c -- signal handling support for readline. */
|
||||
|
||||
/* Copyright (C) 1987-2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU Readline Library, a library for
|
||||
reading lines of text with interactive input and history editing.
|
||||
|
||||
The GNU Readline Library is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version.
|
||||
|
||||
The GNU Readline Library 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.
|
||||
|
||||
The GNU General Public License is often shipped with GNU software, and
|
||||
is generally kept in a file called COPYING or LICENSE. If you do not
|
||||
have a copy of the license, write to the Free Software Foundation,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
#define READLINE_LIBRARY
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* Just for NULL. Yuck. */
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
|
||||
/* System-specific feature definitions and include files. */
|
||||
#include "rldefs.h"
|
||||
|
||||
#if defined (GWINSZ_IN_SYS_IOCTL)
|
||||
# include <sys/ioctl.h>
|
||||
#endif /* GWINSZ_IN_SYS_IOCTL */
|
||||
|
||||
#if defined (HANDLE_SIGNALS)
|
||||
/* Some standard library routines. */
|
||||
#include "readline.h"
|
||||
#include "history.h"
|
||||
|
||||
#include "rlprivate.h"
|
||||
|
||||
#if !defined (RETSIGTYPE)
|
||||
# if defined (VOID_SIGHANDLER)
|
||||
# define RETSIGTYPE void
|
||||
# else
|
||||
# define RETSIGTYPE int
|
||||
# endif /* !VOID_SIGHANDLER */
|
||||
#endif /* !RETSIGTYPE */
|
||||
|
||||
#if defined (VOID_SIGHANDLER)
|
||||
# define SIGHANDLER_RETURN return
|
||||
#else
|
||||
# define SIGHANDLER_RETURN return (0)
|
||||
#endif
|
||||
|
||||
/* This typedef is equivalent to the one for Function; it allows us
|
||||
to say SigHandler *foo = signal (SIGKILL, SIG_IGN); */
|
||||
typedef RETSIGTYPE SigHandler ();
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
typedef struct sigaction sighandler_cxt;
|
||||
# define rl_sigaction(s, nh, oh) sigaction(s, nh, oh)
|
||||
#else
|
||||
typedef struct { SigHandler *sa_handler; int sa_mask, sa_flags; } sighandler_cxt;
|
||||
# define sigemptyset(m)
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#ifndef SA_RESTART
|
||||
# define SA_RESTART 0
|
||||
#endif
|
||||
|
||||
static SigHandler *rl_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
|
||||
static void rl_maybe_set_sighandler PARAMS((int, SigHandler *, sighandler_cxt *));
|
||||
|
||||
/* Exported variables for use by applications. */
|
||||
|
||||
/* If non-zero, readline will install its own signal handlers for
|
||||
SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
|
||||
int rl_catch_signals = 1;
|
||||
|
||||
/* If non-zero, readline will install a signal handler for SIGWINCH. */
|
||||
#ifdef SIGWINCH
|
||||
int rl_catch_sigwinch = 1;
|
||||
#else
|
||||
int rl_catch_sigwinch = 0; /* for the readline state struct in readline.c */
|
||||
#endif
|
||||
|
||||
static int signals_set_flag;
|
||||
static int sigwinch_set_flag;
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Signal Handling */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
static sighandler_cxt old_int, old_term, old_alrm, old_quit;
|
||||
#if defined (SIGTSTP)
|
||||
static sighandler_cxt old_tstp, old_ttou, old_ttin;
|
||||
#endif
|
||||
#if defined (SIGWINCH)
|
||||
static sighandler_cxt old_winch;
|
||||
#endif
|
||||
|
||||
/* Readline signal handler functions. */
|
||||
|
||||
static RETSIGTYPE
|
||||
rl_signal_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigset_t set, pset;
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
long omask;
|
||||
# else /* !HAVE_BSD_SIGNALS */
|
||||
sighandler_cxt dummy_cxt; /* needed for rl_set_sighandler call */
|
||||
# endif /* !HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
RL_SETSTATE(RL_STATE_SIGHANDLER);
|
||||
|
||||
#if !defined (HAVE_BSD_SIGNALS) && !defined (HAVE_POSIX_SIGNALS)
|
||||
/* Since the signal will not be blocked while we are in the signal
|
||||
handler, ignore it until rl_clear_signals resets the catcher. */
|
||||
# if defined (SIGALRM)
|
||||
if (sig == SIGINT || sig == SIGALRM)
|
||||
# else
|
||||
if (sig == SIGINT)
|
||||
# endif
|
||||
rl_set_sighandler (sig, SIG_IGN, &dummy_cxt);
|
||||
#endif /* !HAVE_BSD_SIGNALS && !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&set);
|
||||
sigemptyset (&pset);
|
||||
#endif
|
||||
|
||||
switch (sig)
|
||||
{
|
||||
case SIGINT:
|
||||
rl_free_line_state ();
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case SIGTERM:
|
||||
#if defined (SIGTSTP)
|
||||
case SIGTSTP:
|
||||
case SIGTTOU:
|
||||
case SIGTTIN:
|
||||
#endif /* SIGTSTP */
|
||||
#if defined (SIGALRM)
|
||||
case SIGALRM:
|
||||
#endif
|
||||
#if defined (SIGQUIT)
|
||||
case SIGQUIT:
|
||||
#endif
|
||||
rl_cleanup_after_signal ();
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &set);
|
||||
sigdelset (&set, sig);
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
omask = sigblock (0);
|
||||
# endif /* HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
#if defined (__EMX__)
|
||||
signal (sig, SIG_ACK);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_KILL)
|
||||
kill (getpid (), sig);
|
||||
#else
|
||||
raise (sig); /* assume we have raise */
|
||||
#endif
|
||||
|
||||
/* Let the signal that we just sent through. */
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &set, (sigset_t *)NULL);
|
||||
#else /* !HAVE_POSIX_SIGNALS */
|
||||
# if defined (HAVE_BSD_SIGNALS)
|
||||
sigsetmask (omask & ~(sigmask (sig)));
|
||||
# endif /* HAVE_BSD_SIGNALS */
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
rl_reset_after_signal ();
|
||||
}
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_SIGHANDLER);
|
||||
SIGHANDLER_RETURN;
|
||||
}
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
static RETSIGTYPE
|
||||
rl_sigwinch_handler (sig)
|
||||
int sig;
|
||||
{
|
||||
SigHandler *oh;
|
||||
|
||||
#if defined (MUST_REINSTALL_SIGHANDLERS)
|
||||
sighandler_cxt dummy_winch;
|
||||
|
||||
/* We don't want to change old_winch -- it holds the state of SIGWINCH
|
||||
disposition set by the calling application. We need this state
|
||||
because we call the application's SIGWINCH handler after updating
|
||||
our own idea of the screen size. */
|
||||
rl_set_sighandler (SIGWINCH, rl_sigwinch_handler, &dummy_winch);
|
||||
#endif
|
||||
|
||||
RL_SETSTATE(RL_STATE_SIGHANDLER);
|
||||
rl_resize_terminal ();
|
||||
|
||||
/* If another sigwinch handler has been installed, call it. */
|
||||
oh = (SigHandler *)old_winch.sa_handler;
|
||||
if (oh && oh != (SigHandler *)SIG_IGN && oh != (SigHandler *)SIG_DFL)
|
||||
(*oh) (sig);
|
||||
|
||||
RL_UNSETSTATE(RL_STATE_SIGHANDLER);
|
||||
SIGHANDLER_RETURN;
|
||||
}
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
/* Functions to manage signal handling. */
|
||||
|
||||
#if !defined (HAVE_POSIX_SIGNALS)
|
||||
static int
|
||||
rl_sigaction (sig, nh, oh)
|
||||
int sig;
|
||||
sighandler_cxt *nh, *oh;
|
||||
{
|
||||
oh->sa_handler = signal (sig, nh->sa_handler);
|
||||
return 0;
|
||||
}
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
/* Set up a readline-specific signal handler, saving the old signal
|
||||
information in OHANDLER. Return the old signal handler, like
|
||||
signal(). */
|
||||
static SigHandler *
|
||||
rl_set_sighandler (sig, handler, ohandler)
|
||||
int sig;
|
||||
SigHandler *handler;
|
||||
sighandler_cxt *ohandler;
|
||||
{
|
||||
sighandler_cxt old_handler;
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = handler;
|
||||
act.sa_flags = (sig == SIGWINCH) ? SA_RESTART : 0;
|
||||
sigemptyset (&act.sa_mask);
|
||||
sigemptyset (&ohandler->sa_mask);
|
||||
sigaction (sig, &act, &old_handler);
|
||||
#else
|
||||
old_handler.sa_handler = (SigHandler *)signal (sig, handler);
|
||||
#endif /* !HAVE_POSIX_SIGNALS */
|
||||
|
||||
/* XXX -- assume we have memcpy */
|
||||
/* If rl_set_signals is called twice in a row, don't set the old handler to
|
||||
rl_signal_handler, because that would cause infinite recursion. */
|
||||
if (handler != rl_signal_handler || old_handler.sa_handler != rl_signal_handler)
|
||||
memcpy (ohandler, &old_handler, sizeof (sighandler_cxt));
|
||||
|
||||
return (ohandler->sa_handler);
|
||||
}
|
||||
|
||||
static void
|
||||
rl_maybe_set_sighandler (sig, handler, ohandler)
|
||||
int sig;
|
||||
SigHandler *handler;
|
||||
sighandler_cxt *ohandler;
|
||||
{
|
||||
sighandler_cxt dummy;
|
||||
SigHandler *oh;
|
||||
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
oh = rl_set_sighandler (sig, handler, ohandler);
|
||||
if (oh == (SigHandler *)SIG_IGN)
|
||||
rl_sigaction (sig, ohandler, &dummy);
|
||||
}
|
||||
|
||||
int
|
||||
rl_set_signals ()
|
||||
{
|
||||
sighandler_cxt dummy;
|
||||
SigHandler *oh;
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
static int sigmask_set = 0;
|
||||
static sigset_t bset, oset;
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
if (rl_catch_signals && sigmask_set == 0)
|
||||
{
|
||||
sigemptyset (&bset);
|
||||
|
||||
sigaddset (&bset, SIGINT);
|
||||
sigaddset (&bset, SIGINT);
|
||||
#if defined (SIGQUIT)
|
||||
sigaddset (&bset, SIGQUIT);
|
||||
#endif
|
||||
#if defined (SIGALRM)
|
||||
sigaddset (&bset, SIGALRM);
|
||||
#endif
|
||||
#if defined (SIGTSTP)
|
||||
sigaddset (&bset, SIGTSTP);
|
||||
#endif
|
||||
#if defined (SIGTTIN)
|
||||
sigaddset (&bset, SIGTTIN);
|
||||
#endif
|
||||
#if defined (SIGTTOU)
|
||||
sigaddset (&bset, SIGTTOU);
|
||||
#endif
|
||||
sigmask_set = 1;
|
||||
}
|
||||
#endif /* HAVE_POSIX_SIGNALS */
|
||||
|
||||
if (rl_catch_signals && signals_set_flag == 0)
|
||||
{
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigemptyset (&oset);
|
||||
sigprocmask (SIG_BLOCK, &bset, &oset);
|
||||
#endif
|
||||
|
||||
rl_maybe_set_sighandler (SIGINT, rl_signal_handler, &old_int);
|
||||
rl_maybe_set_sighandler (SIGTERM, rl_signal_handler, &old_term);
|
||||
#if defined (SIGQUIT)
|
||||
rl_maybe_set_sighandler (SIGQUIT, rl_signal_handler, &old_quit);
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM)
|
||||
oh = rl_set_sighandler (SIGALRM, rl_signal_handler, &old_alrm);
|
||||
if (oh == (SigHandler *)SIG_IGN)
|
||||
rl_sigaction (SIGALRM, &old_alrm, &dummy);
|
||||
#if defined (HAVE_POSIX_SIGNALS) && defined (SA_RESTART)
|
||||
/* If the application using readline has already installed a signal
|
||||
handler with SA_RESTART, SIGALRM will cause reads to be restarted
|
||||
automatically, so readline should just get out of the way. Since
|
||||
we tested for SIG_IGN above, we can just test for SIG_DFL here. */
|
||||
if (oh != (SigHandler *)SIG_DFL && (old_alrm.sa_flags & SA_RESTART))
|
||||
rl_sigaction (SIGALRM, &old_alrm, &dummy);
|
||||
#endif /* HAVE_POSIX_SIGNALS */
|
||||
#endif /* SIGALRM */
|
||||
|
||||
#if defined (SIGTSTP)
|
||||
rl_maybe_set_sighandler (SIGTSTP, rl_signal_handler, &old_tstp);
|
||||
#endif /* SIGTSTP */
|
||||
|
||||
#if defined (SIGTTOU)
|
||||
rl_maybe_set_sighandler (SIGTTOU, rl_signal_handler, &old_ttou);
|
||||
#endif /* SIGTTOU */
|
||||
|
||||
#if defined (SIGTTIN)
|
||||
rl_maybe_set_sighandler (SIGTTIN, rl_signal_handler, &old_ttin);
|
||||
#endif /* SIGTTIN */
|
||||
|
||||
signals_set_flag = 1;
|
||||
|
||||
#if defined (HAVE_POSIX_SIGNALS)
|
||||
sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
if (rl_catch_sigwinch && sigwinch_set_flag == 0)
|
||||
{
|
||||
rl_maybe_set_sighandler (SIGWINCH, rl_sigwinch_handler, &old_winch);
|
||||
sigwinch_set_flag = 1;
|
||||
}
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
rl_clear_signals ()
|
||||
{
|
||||
sighandler_cxt dummy;
|
||||
|
||||
if (rl_catch_signals && signals_set_flag == 1)
|
||||
{
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
|
||||
rl_sigaction (SIGINT, &old_int, &dummy);
|
||||
rl_sigaction (SIGTERM, &old_term, &dummy);
|
||||
#if defined (SIGQUIT)
|
||||
rl_sigaction (SIGQUIT, &old_quit, &dummy);
|
||||
#endif
|
||||
#if defined (SIGALRM)
|
||||
rl_sigaction (SIGALRM, &old_alrm, &dummy);
|
||||
#endif
|
||||
|
||||
#if defined (SIGTSTP)
|
||||
rl_sigaction (SIGTSTP, &old_tstp, &dummy);
|
||||
#endif /* SIGTSTP */
|
||||
|
||||
#if defined (SIGTTOU)
|
||||
rl_sigaction (SIGTTOU, &old_ttou, &dummy);
|
||||
#endif /* SIGTTOU */
|
||||
|
||||
#if defined (SIGTTIN)
|
||||
rl_sigaction (SIGTTIN, &old_ttin, &dummy);
|
||||
#endif /* SIGTTIN */
|
||||
|
||||
signals_set_flag = 0;
|
||||
}
|
||||
|
||||
#if defined (SIGWINCH)
|
||||
if (rl_catch_sigwinch && sigwinch_set_flag == 1)
|
||||
{
|
||||
sigemptyset (&dummy.sa_mask);
|
||||
rl_sigaction (SIGWINCH, &old_winch, &dummy);
|
||||
sigwinch_set_flag = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clean up the terminal and readline state after catching a signal, before
|
||||
resending it to the calling application. */
|
||||
void
|
||||
rl_cleanup_after_signal ()
|
||||
{
|
||||
_rl_clean_up_for_exit ();
|
||||
if (rl_deprep_term_function)
|
||||
(*rl_deprep_term_function) ();
|
||||
rl_clear_pending_input ();
|
||||
rl_clear_signals ();
|
||||
}
|
||||
|
||||
/* Reset the terminal and readline state after a signal handler returns. */
|
||||
void
|
||||
rl_reset_after_signal ()
|
||||
{
|
||||
if (rl_prep_term_function)
|
||||
(*rl_prep_term_function) (_rl_meta_flag);
|
||||
rl_set_signals ();
|
||||
}
|
||||
|
||||
/* Free up the readline variable line state for the current line (undo list,
|
||||
any partial history entry, any keyboard macros in progress, and any
|
||||
numeric arguments in process) after catching a signal, before calling
|
||||
rl_cleanup_after_signal(). */
|
||||
void
|
||||
rl_free_line_state ()
|
||||
{
|
||||
register HIST_ENTRY *entry;
|
||||
|
||||
rl_free_undo_list ();
|
||||
|
||||
entry = current_history ();
|
||||
if (entry)
|
||||
entry->data = (char *)NULL;
|
||||
|
||||
_rl_kill_kbd_macro ();
|
||||
rl_clear_message ();
|
||||
_rl_reset_argument ();
|
||||
}
|
||||
|
||||
#endif /* HANDLE_SIGNALS */
|
||||
+1
-1
@@ -1237,7 +1237,7 @@ rl_change_case (count, op)
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
wchar_t wc, nwc;
|
||||
char mb[MB_LEN_MAX+1];
|
||||
int mblen, p;
|
||||
int mblen;
|
||||
mbstate_t ps;
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1111,7 +1111,7 @@ int
|
||||
rl_vi_rubout (count, key)
|
||||
int count, key;
|
||||
{
|
||||
int p, opoint;
|
||||
int opoint;
|
||||
|
||||
if (count < 0)
|
||||
return (rl_vi_delete (-count, key));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4746,6 +4746,7 @@ parse_compound_assignment (retlenp)
|
||||
}
|
||||
|
||||
last_read_token = orig_last_token; /* XXX - was WORD? */
|
||||
|
||||
if (wl)
|
||||
{
|
||||
rl = REVERSE_LIST (wl, WORD_LIST *);
|
||||
|
||||
@@ -4248,7 +4248,7 @@ decode_prompt_string (string)
|
||||
break;
|
||||
}
|
||||
temp = (char *)xmalloc (3);
|
||||
temp[0] = '\001'; /* CTLESC */
|
||||
temp[0] = CTLESC;
|
||||
temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
|
||||
temp[2] = '\0';
|
||||
goto add_string;
|
||||
@@ -4745,7 +4745,11 @@ parse_compound_assignment (retlenp)
|
||||
jump_to_top_level (DISCARD);
|
||||
}
|
||||
|
||||
#if 0
|
||||
last_read_token = orig_last_token; /* XXX - was WORD? */
|
||||
#else
|
||||
last_read_token = WORD;
|
||||
#endif
|
||||
if (wl)
|
||||
{
|
||||
rl = REVERSE_LIST (wl, WORD_LIST *);
|
||||
|
||||
@@ -1208,7 +1208,7 @@ run_wordexp (words)
|
||||
wl = global_command->value.Simple->words;
|
||||
if (protected_mode)
|
||||
for (tl = wl; tl; tl = tl->next)
|
||||
tl->word->flags |= W_NOCOMSUB;
|
||||
tl->word->flags |= W_NOCOMSUB|W_NOPROCSUB;
|
||||
result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -946,7 +946,7 @@ string_extract_verbatim (string, slen, sindex, charlist)
|
||||
len = mbstowcs (wcharlist, charlist, 0);
|
||||
if (len == -1)
|
||||
len = 0;
|
||||
wcharlist = xmalloc ((sizeof (wchar_t) * len) + 1);
|
||||
wcharlist = (wchar_t *)xmalloc ((sizeof (wchar_t) * len) + 1);
|
||||
mbstowcs (wcharlist, charlist, len);
|
||||
}
|
||||
|
||||
@@ -1774,14 +1774,21 @@ char *
|
||||
string_list_dollar_star (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *ret;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# if defined (__GNUC__)
|
||||
char sep[MB_CUR_MAX + 1];
|
||||
# else
|
||||
char *sep = 0;
|
||||
# endif
|
||||
#else
|
||||
char sep[2];
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# if !defined (__GNUC__)
|
||||
sep = (char *)xmalloc (MB_CUR_MAX + 1);
|
||||
# endif /* !__GNUC__ */
|
||||
if (ifs_firstc_len == 1)
|
||||
{
|
||||
sep[0] = ifs_firstc[0];
|
||||
@@ -1797,7 +1804,11 @@ string_list_dollar_star (list)
|
||||
sep[1] = '\0';
|
||||
#endif
|
||||
|
||||
return (string_list_internal (list, sep));
|
||||
ret = string_list_internal (list, sep);
|
||||
#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
|
||||
free (sep);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
|
||||
@@ -1816,7 +1827,11 @@ string_list_dollar_at (list, quoted)
|
||||
{
|
||||
char *ifs, *ret;
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# if defined (__GNUC__)
|
||||
char sep[MB_CUR_MAX + 1];
|
||||
# else
|
||||
char *sep = 0;
|
||||
# endif /* !__GNUC__ */
|
||||
#else
|
||||
char sep[2];
|
||||
#endif
|
||||
@@ -1826,6 +1841,9 @@ string_list_dollar_at (list, quoted)
|
||||
ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
# if !defined (__GNUC__)
|
||||
sep = (char *)xmalloc (MB_CUR_MAX + 1);
|
||||
# endif /* !__GNUC__ */
|
||||
if (ifs && *ifs)
|
||||
{
|
||||
if (ifs_firstc_len == 1)
|
||||
@@ -1852,7 +1870,12 @@ string_list_dollar_at (list, quoted)
|
||||
tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
|
||||
? quote_list (list)
|
||||
: list_quote_escapes (list);
|
||||
return (string_list_internal (tlist, sep));
|
||||
|
||||
ret = string_list_internal (tlist, sep);
|
||||
#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
|
||||
free (sep);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return the list of words present in STRING. Separate the string into
|
||||
@@ -2187,7 +2210,7 @@ do_compound_assignment (name, value, flags)
|
||||
if (mklocal && variable_context)
|
||||
{
|
||||
v = find_variable (name);
|
||||
if (v == 0 || array_p (v) == 0)
|
||||
if (v == 0 || array_p (v) == 0 || v->context != variable_context)
|
||||
v = make_local_array_variable (name);
|
||||
v = assign_array_var_from_string (v, value, flags);
|
||||
}
|
||||
@@ -2575,6 +2598,13 @@ expand_assignment_string_to_string (string, quoted)
|
||||
return (expand_string_to_string_internal (string, quoted, expand_string_assignment));
|
||||
}
|
||||
|
||||
char *
|
||||
expand_arith_string (string)
|
||||
char *string;
|
||||
{
|
||||
return (expand_string_if_necessary (string, Q_DOUBLE_QUOTES, expand_string));
|
||||
}
|
||||
|
||||
#if defined (COND_COMMAND)
|
||||
/* Just remove backslashes in STRING. Returns a new string. */
|
||||
char *
|
||||
@@ -3408,7 +3438,7 @@ remove_pattern (param, pattern, op)
|
||||
free (wpattern);
|
||||
|
||||
n = strlen (param);
|
||||
xret = xmalloc (n + 1);
|
||||
xret = (char *)xmalloc (n + 1);
|
||||
memset (&ps, '\0', sizeof (mbstate_t));
|
||||
n = wcsrtombs (xret, (const wchar_t **)&ret, n, &ps);
|
||||
xret[n] = '\0'; /* just to make sure */
|
||||
@@ -3477,7 +3507,7 @@ match_upattern (string, pat, mtype, sp, ep)
|
||||
len = STRLEN (pat);
|
||||
if (pat[0] != '*' || pat[len - 1] != '*')
|
||||
{
|
||||
p = npat = xmalloc (len + 3);
|
||||
p = npat = (char *)xmalloc (len + 3);
|
||||
p1 = pat;
|
||||
if (*p1 != '*')
|
||||
*p++ = '*';
|
||||
@@ -3621,7 +3651,7 @@ match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
|
||||
len = wcslen (wpat);
|
||||
if (wpat[0] != L'*' || wpat[len - 1] != L'*')
|
||||
{
|
||||
wp = nwpat = xmalloc ((len + 3) * sizeof (wchar_t));
|
||||
wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
|
||||
wp1 = wpat;
|
||||
if (*wp1 != L'*')
|
||||
*wp++ = L'*';
|
||||
@@ -5248,7 +5278,11 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
|
||||
else
|
||||
t = (char *)0;
|
||||
|
||||
#if 0
|
||||
temp1 = expand_string_if_necessary (substr, Q_DOUBLE_QUOTES, expand_string);
|
||||
#else
|
||||
temp1 = expand_arith_string (substr);
|
||||
#endif
|
||||
*e1p = evalexp (temp1, &expok);
|
||||
free (temp1);
|
||||
if (expok == 0)
|
||||
@@ -5293,7 +5327,11 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
|
||||
{
|
||||
t++;
|
||||
temp2 = savestring (t);
|
||||
#if 0
|
||||
temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
|
||||
#else
|
||||
temp1 = expand_arith_string (temp2);
|
||||
#endif
|
||||
free (temp2);
|
||||
t[-1] = ':';
|
||||
*e2p = evalexp (temp1, &expok);
|
||||
@@ -5665,11 +5703,6 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
vtype &= ~VT_STARSUB;
|
||||
|
||||
mflags = 0;
|
||||
if (*patsub == '/')
|
||||
{
|
||||
mflags |= MATCH_GLOBREP;
|
||||
patsub++;
|
||||
}
|
||||
|
||||
/* Malloc this because expand_string_if_necessary or one of the expansion
|
||||
functions in its call chain may free it on a substitution error. */
|
||||
@@ -5681,7 +5714,9 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
if (starsub)
|
||||
mflags |= MATCH_STARSUB;
|
||||
|
||||
if (rep = quoted_strchr (lpatsub, '/', ST_BACKSL))
|
||||
/* If the pattern starts with a `/', make sure we skip over it when looking
|
||||
for the replacement delimiter. */
|
||||
if (rep = quoted_strchr ((*patsub == '/') ? lpatsub+1 : lpatsub, '/', ST_BACKSL))
|
||||
*rep++ = '\0';
|
||||
else
|
||||
rep = (char *)NULL;
|
||||
@@ -5701,8 +5736,15 @@ parameter_brace_patsub (varname, value, patsub, quoted)
|
||||
rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
|
||||
}
|
||||
|
||||
/* ksh93 doesn't allow the match specifier to be a part of the expanded
|
||||
pattern. This is an extension. */
|
||||
p = pat;
|
||||
if (pat && pat[0] == '#')
|
||||
if (pat && pat[0] == '/')
|
||||
{
|
||||
mflags |= MATCH_GLOBREP|MATCH_ANY;
|
||||
p++;
|
||||
}
|
||||
else if (pat && pat[0] == '#')
|
||||
{
|
||||
mflags |= MATCH_BEG;
|
||||
p++;
|
||||
@@ -6435,7 +6477,11 @@ param_expand (string, sindex, quoted, expanded_something,
|
||||
temp2[t_index] = '\0';
|
||||
|
||||
/* Expand variables found inside the expression. */
|
||||
#if 0
|
||||
temp1 = expand_string_if_necessary (temp2, Q_DOUBLE_QUOTES, expand_string);
|
||||
#else
|
||||
temp1 = expand_arith_string (temp2);
|
||||
#endif
|
||||
free (temp2);
|
||||
|
||||
arithsub:
|
||||
@@ -6477,7 +6523,11 @@ comsub:
|
||||
zindex = t_index;
|
||||
|
||||
/* Do initial variable expansion. */
|
||||
#if 0
|
||||
temp1 = expand_string_if_necessary (temp, Q_DOUBLE_QUOTES, expand_string);
|
||||
#else
|
||||
temp1 = expand_arith_string (temp);
|
||||
#endif
|
||||
|
||||
goto arithsub;
|
||||
|
||||
@@ -6707,7 +6757,7 @@ add_string:
|
||||
case '<':
|
||||
case '>':
|
||||
{
|
||||
if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & W_DQUOTE) || posixly_correct)
|
||||
if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & (W_DQUOTE|W_NOPROCSUB)) || posixly_correct)
|
||||
{
|
||||
sindex--; /* add_character: label increments sindex */
|
||||
goto add_character;
|
||||
@@ -6795,6 +6845,12 @@ add_string:
|
||||
if (temp && *temp && t_index > 0)
|
||||
{
|
||||
temp1 = bash_tilde_expand (temp, tflag);
|
||||
if (temp1 && *temp1 == '~' && STREQ (temp, temp1))
|
||||
{
|
||||
FREE (temp);
|
||||
FREE (temp1);
|
||||
goto add_character; /* tilde expansion failed */
|
||||
}
|
||||
free (temp);
|
||||
temp = temp1;
|
||||
sindex += t_index;
|
||||
|
||||
+8064
File diff suppressed because it is too large
Load Diff
@@ -151,6 +151,9 @@ extern char *expand_string_to_string __P((char *, int));
|
||||
extern char *expand_string_unsplit_to_string __P((char *, int));
|
||||
extern char *expand_assignment_string_to_string __P((char *, int));
|
||||
|
||||
/* Expand an arithmetic expression string */
|
||||
extern char *expand_arith_string __P((char *));
|
||||
|
||||
/* De-quoted quoted characters in STRING. */
|
||||
extern char *dequote_string __P((char *));
|
||||
|
||||
|
||||
@@ -0,0 +1,260 @@
|
||||
/* subst.h -- Names of externally visible functions in subst.c. */
|
||||
|
||||
/* Copyright (C) 1993-2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#if !defined (_SUBST_H_)
|
||||
#define _SUBST_H_
|
||||
|
||||
#include "stdc.h"
|
||||
|
||||
/* Constants which specify how to handle backslashes and quoting in
|
||||
expand_word_internal (). Q_DOUBLE_QUOTES means to use the function
|
||||
slashify_in_quotes () to decide whether the backslash should be
|
||||
retained. Q_HERE_DOCUMENT means slashify_in_here_document () to
|
||||
decide whether to retain the backslash. Q_KEEP_BACKSLASH means
|
||||
to unconditionally retain the backslash. Q_PATQUOTE means that we're
|
||||
expanding a pattern ${var%#[#%]pattern} in an expansion surrounded
|
||||
by double quotes. */
|
||||
#define Q_DOUBLE_QUOTES 0x01
|
||||
#define Q_HERE_DOCUMENT 0x02
|
||||
#define Q_KEEP_BACKSLASH 0x04
|
||||
#define Q_PATQUOTE 0x08
|
||||
#define Q_QUOTED 0x10
|
||||
#define Q_ADDEDQUOTES 0x20
|
||||
#define Q_QUOTEDNULL 0x40
|
||||
|
||||
/* Flag values controlling how assignment statements are treated. */
|
||||
#define ASS_APPEND 0x01
|
||||
#define ASS_MKLOCAL 0x02
|
||||
|
||||
/* Remove backslashes which are quoting backquotes from STRING. Modifies
|
||||
STRING, and returns a pointer to it. */
|
||||
extern char * de_backslash __P((char *));
|
||||
|
||||
/* Replace instances of \! in a string with !. */
|
||||
extern void unquote_bang __P((char *));
|
||||
|
||||
/* Extract the $( construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$(".
|
||||
Make (SINDEX) get the position just after the matching ")". */
|
||||
extern char *extract_command_subst __P((char *, int *));
|
||||
|
||||
/* Extract the $[ construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "$[".
|
||||
Make (SINDEX) get the position just after the matching "]". */
|
||||
extern char *extract_arithmetic_subst __P((char *, int *));
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
/* Extract the <( or >( construct in STRING, and return a new string.
|
||||
Start extracting at (SINDEX) as if we had just seen "<(".
|
||||
Make (SINDEX) get the position just after the matching ")". */
|
||||
extern char *extract_process_subst __P((char *, char *, int *));
|
||||
#endif /* PROCESS_SUBSTITUTION */
|
||||
|
||||
/* Extract the name of the variable to bind to from the assignment string. */
|
||||
extern char *assignment_name __P((char *));
|
||||
|
||||
/* Return a single string of all the words present in LIST, separating
|
||||
each word with SEP. */
|
||||
extern char *string_list_internal __P((WORD_LIST *, char *));
|
||||
|
||||
/* Return a single string of all the words present in LIST, separating
|
||||
each word with a space. */
|
||||
extern char *string_list __P((WORD_LIST *));
|
||||
|
||||
/* Turn $* into a single string, obeying POSIX rules. */
|
||||
extern char *string_list_dollar_star __P((WORD_LIST *));
|
||||
|
||||
/* Expand $@ into a single string, obeying POSIX rules. */
|
||||
extern char *string_list_dollar_at __P((WORD_LIST *, int));
|
||||
|
||||
/* Perform quoted null character removal on each element of LIST.
|
||||
This modifies LIST. */
|
||||
extern void word_list_remove_quoted_nulls __P((WORD_LIST *));
|
||||
|
||||
/* This performs word splitting and quoted null character removal on
|
||||
STRING. */
|
||||
extern WORD_LIST *list_string __P((char *, char *, int));
|
||||
|
||||
extern char *get_word_from_string __P((char **, char *, char **));
|
||||
extern char *strip_trailing_ifs_whitespace __P((char *, char *, int));
|
||||
|
||||
/* Given STRING, an assignment string, get the value of the right side
|
||||
of the `=', and bind it to the left side. If EXPAND is true, then
|
||||
perform tilde expansion, parameter expansion, command substitution,
|
||||
and arithmetic expansion on the right-hand side. Do not perform word
|
||||
splitting on the result of expansion. */
|
||||
extern int do_assignment __P((char *));
|
||||
extern int do_assignment_no_expand __P((char *));
|
||||
extern int do_word_assignment __P((WORD_DESC *));
|
||||
|
||||
/* Append SOURCE to TARGET at INDEX. SIZE is the current amount
|
||||
of space allocated to TARGET. SOURCE can be NULL, in which
|
||||
case nothing happens. Gets rid of SOURCE by free ()ing it.
|
||||
Returns TARGET in case the location has changed. */
|
||||
extern char *sub_append_string __P((char *, char *, int *, int *));
|
||||
|
||||
/* Append the textual representation of NUMBER to TARGET.
|
||||
INDEX and SIZE are as in SUB_APPEND_STRING. */
|
||||
extern char *sub_append_number __P((intmax_t, char *, int *, int *));
|
||||
|
||||
/* Return the word list that corresponds to `$*'. */
|
||||
extern WORD_LIST *list_rest_of_args __P((void));
|
||||
|
||||
/* Make a single large string out of the dollar digit variables,
|
||||
and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
|
||||
case of "$*" with respect to IFS. */
|
||||
extern char *string_rest_of_args __P((int));
|
||||
|
||||
extern int number_of_args __P((void));
|
||||
|
||||
/* Expand STRING by performing parameter expansion, command substitution,
|
||||
and arithmetic expansion. Dequote the resulting WORD_LIST before
|
||||
returning it, but do not perform word splitting. The call to
|
||||
remove_quoted_nulls () is made here because word splitting normally
|
||||
takes care of quote removal. */
|
||||
extern WORD_LIST *expand_string_unsplit __P((char *, int));
|
||||
|
||||
/* Expand the rhs of an assignment statement. */
|
||||
extern WORD_LIST *expand_string_assignment __P((char *, int));
|
||||
|
||||
/* Expand a prompt string. */
|
||||
extern WORD_LIST *expand_prompt_string __P((char *, int));
|
||||
|
||||
/* Expand STRING just as if you were expanding a word. This also returns
|
||||
a list of words. Note that filename globbing is *NOT* done for word
|
||||
or string expansion, just when the shell is expanding a command. This
|
||||
does parameter expansion, command substitution, arithmetic expansion,
|
||||
and word splitting. Dequote the resultant WORD_LIST before returning. */
|
||||
extern WORD_LIST *expand_string __P((char *, int));
|
||||
|
||||
/* Convenience functions that expand strings to strings, taking care of
|
||||
converting the WORD_LIST * returned by the expand_string* functions
|
||||
to a string and deallocating the WORD_LIST *. */
|
||||
extern char *expand_string_to_string __P((char *, int));
|
||||
extern char *expand_string_unsplit_to_string __P((char *, int));
|
||||
extern char *expand_assignment_string_to_string __P((char *, int));
|
||||
|
||||
/* De-quoted quoted characters in STRING. */
|
||||
extern char *dequote_string __P((char *));
|
||||
|
||||
/* Expand WORD, performing word splitting on the result. This does
|
||||
parameter expansion, command substitution, arithmetic expansion,
|
||||
word splitting, and quote removal. */
|
||||
extern WORD_LIST *expand_word __P((WORD_DESC *, int));
|
||||
|
||||
/* Expand WORD, but do not perform word splitting on the result. This
|
||||
does parameter expansion, command substitution, arithmetic expansion,
|
||||
and quote removal. */
|
||||
extern WORD_LIST *expand_word_unsplit __P((WORD_DESC *, int));
|
||||
extern WORD_LIST *expand_word_leave_quoted __P((WORD_DESC *, int));
|
||||
|
||||
/* Return the value of a positional parameter. This handles values > 10. */
|
||||
extern char *get_dollar_var_value __P((intmax_t));
|
||||
|
||||
/* Quote a string to protect it from word splitting. */
|
||||
extern char *quote_string __P((char *));
|
||||
|
||||
/* Quote escape characters (characters special to interals of expansion)
|
||||
in a string. */
|
||||
extern char *quote_escapes __P((char *));
|
||||
|
||||
/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
|
||||
backslash quoting rules for within double quotes. */
|
||||
extern char *string_quote_removal __P((char *, int));
|
||||
|
||||
/* Perform quote removal on word WORD. This allocates and returns a new
|
||||
WORD_DESC *. */
|
||||
extern WORD_DESC *word_quote_removal __P((WORD_DESC *, int));
|
||||
|
||||
/* Perform quote removal on all words in LIST. If QUOTED is non-zero,
|
||||
the members of the list are treated as if they are surrounded by
|
||||
double quotes. Return a new list, or NULL if LIST is NULL. */
|
||||
extern WORD_LIST *word_list_quote_removal __P((WORD_LIST *, int));
|
||||
|
||||
/* Called when IFS is changed to maintain some private variables. */
|
||||
extern void setifs __P((SHELL_VAR *));
|
||||
|
||||
/* Return the value of $IFS, or " \t\n" if IFS is unset. */
|
||||
extern char *getifs __P((void));
|
||||
|
||||
/* This splits a single word into a WORD LIST on $IFS, but only if the word
|
||||
is not quoted. list_string () performs quote removal for us, even if we
|
||||
don't do any splitting. */
|
||||
extern WORD_LIST *word_split __P((WORD_DESC *, char *));
|
||||
|
||||
/* Take the list of words in LIST and do the various substitutions. Return
|
||||
a new list of words which is the expanded list, and without things like
|
||||
variable assignments. */
|
||||
extern WORD_LIST *expand_words __P((WORD_LIST *));
|
||||
|
||||
/* Same as expand_words (), but doesn't hack variable or environment
|
||||
variables. */
|
||||
extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *));
|
||||
|
||||
/* Perform the `normal shell expansions' on a WORD_LIST. These are
|
||||
brace expansion, tilde expansion, parameter and variable substitution,
|
||||
command substitution, arithmetic expansion, and word splitting. */
|
||||
extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *));
|
||||
|
||||
extern char *command_substitute __P((char *, int));
|
||||
extern char *pat_subst __P((char *, char *, char *, int));
|
||||
|
||||
extern void unlink_fifo_list __P((void));
|
||||
|
||||
extern WORD_LIST *list_string_with_quotes __P((char *));
|
||||
|
||||
#if defined (ARRAY_VARS)
|
||||
extern char *extract_array_assignment_list __P((char *, int *));
|
||||
#endif
|
||||
|
||||
#if defined (COND_COMMAND)
|
||||
extern char *remove_backslashes __P((char *));
|
||||
extern char *cond_expand_word __P((WORD_DESC *, int));
|
||||
#endif
|
||||
|
||||
#if defined (READLINE)
|
||||
extern int char_is_quoted __P((char *, int));
|
||||
extern int unclosed_pair __P((char *, int, char *));
|
||||
extern int skip_to_delim __P((char *, int, char *));
|
||||
extern WORD_LIST *split_at_delims __P((char *, int, char *, int, int *, int *));
|
||||
#endif
|
||||
|
||||
/* Variables used to keep track of the characters in IFS. */
|
||||
extern SHELL_VAR *ifs_var;
|
||||
extern char *ifs_value;
|
||||
extern unsigned char ifs_cmap[];
|
||||
|
||||
#if defined (HANDLE_MULTIBYTE)
|
||||
extern unsigned char ifs_firstc[];
|
||||
extern size_t ifs_firstc_len;
|
||||
#else
|
||||
extern unsigned char ifs_firstc;
|
||||
#endif
|
||||
|
||||
/* Evaluates to 1 if C is a character in $IFS. */
|
||||
#define isifs(c) (ifs_cmap[(unsigned char)(c)] != 0)
|
||||
|
||||
/* How to determine the quoted state of the character C. */
|
||||
#define QUOTED_CHAR(c) ((c) == CTLESC)
|
||||
|
||||
/* Is the first character of STRING a quoted NULL character? */
|
||||
#define QUOTED_NULL(string) ((string)[0] == CTLNUL && (string)[1] == '\0')
|
||||
|
||||
#endif /* !_SUBST_H_ */
|
||||
+4
-2
@@ -53,8 +53,10 @@ LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
LIBS_FOR_BUILD = ${LIBS} # XXX
|
||||
|
||||
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
|
||||
LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
|
||||
LDFLAGS_FOR_BUILD = $(LDFLAGS)
|
||||
|
||||
@@ -76,7 +78,7 @@ OBJ1 = man2html.o
|
||||
all: man2html$(EXEEXT)
|
||||
|
||||
man2html$(EXEEXT): $(OBJ1)
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) $(OBJ1) -o $@ ${LIBS}
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) $(OBJ1) -o $@ ${LIBS_FOR_BUILD}
|
||||
|
||||
clean:
|
||||
$(RM) man2html$(EXEEXT)
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
#
|
||||
# Simple Makefile for the support programs.
|
||||
#
|
||||
# documentation support: man2html
|
||||
# testing support: printenv recho zecho
|
||||
#
|
||||
# bashbug lives here but is created by the top-level makefile
|
||||
#
|
||||
# Currently only man2html is built
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
|
||||
|
||||
#
|
||||
# Boilerplate
|
||||
#
|
||||
topdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = .:@srcdir@
|
||||
BUILD_DIR = @BUILD_DIR@
|
||||
|
||||
RM = rm -f
|
||||
SHELL = @MAKE_SHELL@
|
||||
CC = @CC@
|
||||
CC_FOR_BUILD = @CC_FOR_BUILD@
|
||||
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
#
|
||||
# Compiler options:
|
||||
#
|
||||
PROFILE_FLAGS = @PROFILE_FLAGS@
|
||||
|
||||
CFLAGS = @CFLAGS@
|
||||
CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
|
||||
LOCAL_CFLAGS = @LOCAL_CFLAGS@
|
||||
DEFS = @DEFS@
|
||||
LOCAL_DEFS = @LOCAL_DEFS@
|
||||
|
||||
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
|
||||
LIBS = @LIBS@
|
||||
LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
|
||||
LDFLAGS_FOR_BUILD = $(LDFLAGS)
|
||||
|
||||
INCLUDES = -I${BUILD_DIR} -I${topdir}
|
||||
|
||||
BASE_CCFLAGS = ${PROFILE_FLAGS} $(DEFS) $(LOCAL_DEFS) $(SYSTEM_FLAGS) \
|
||||
${INCLUDES} $(LOCAL_CFLAGS)
|
||||
|
||||
CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
|
||||
CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
|
||||
|
||||
SRC1 = man2html.c
|
||||
OBJ1 = man2html.o
|
||||
|
||||
.c.o:
|
||||
$(RM) $@
|
||||
$(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $<
|
||||
|
||||
all: man2html$(EXEEXT)
|
||||
|
||||
man2html$(EXEEXT): $(OBJ1)
|
||||
$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) $(OBJ1) -o $@ ${LIBS}
|
||||
|
||||
clean:
|
||||
$(RM) man2html$(EXEEXT)
|
||||
|
||||
distclean maintainer-clean mostlyclean: clean
|
||||
$(RM) $(OBJ1)
|
||||
|
||||
man2html.o: man2html.c
|
||||
+16
-354
@@ -1,7 +1,7 @@
|
||||
/* signames.c -- Create and write `signames.h', which contains an array of
|
||||
/* mksignames.c -- Create and write `signames.h', which contains an array of
|
||||
signal names. */
|
||||
|
||||
/* Copyright (C) 1992-2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1992-2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
@@ -22,371 +22,25 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
/* Duplicated from signames.c */
|
||||
#if !defined (NSIG)
|
||||
# define NSIG 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Special traps:
|
||||
* EXIT == 0
|
||||
* DEBUG == NSIG
|
||||
* ERR == NSIG+1
|
||||
* RETURN == NSIG+2
|
||||
*/
|
||||
#define LASTSIG NSIG+2
|
||||
|
||||
char *signal_names[2 * (LASTSIG)];
|
||||
|
||||
#define signal_names_size (sizeof(signal_names)/sizeof(signal_names[0]))
|
||||
/* Imported from signames.c */
|
||||
extern void initialize_signames ();
|
||||
extern char *signal_names[];
|
||||
|
||||
char *progname;
|
||||
|
||||
/* AIX 4.3 defines SIGRTMIN and SIGRTMAX as 888 and 999 respectively.
|
||||
I don't want to allocate so much unused space for the intervening signal
|
||||
numbers, so we just punt if SIGRTMAX is past the bounds of the
|
||||
signal_names array (handled in configure). */
|
||||
#if defined (SIGRTMAX) && defined (UNUSABLE_RT_SIGNALS)
|
||||
# undef SIGRTMAX
|
||||
# undef SIGRTMIN
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX) || defined (SIGRTMIN)
|
||||
# define RTLEN 14
|
||||
# define RTLIM 256
|
||||
#endif
|
||||
|
||||
void
|
||||
initialize_signames ()
|
||||
{
|
||||
register int i;
|
||||
#if defined (SIGRTMAX) || defined (SIGRTMIN)
|
||||
int rtmin, rtmax, rtcnt;
|
||||
#endif
|
||||
|
||||
for (i = 1; i < signal_names_size; i++)
|
||||
signal_names[i] = (char *)NULL;
|
||||
|
||||
/* `signal' 0 is what we do on exit. */
|
||||
signal_names[0] = "EXIT";
|
||||
|
||||
/* Place signal names which can be aliases for more common signal
|
||||
names first. This allows (for example) SIGABRT to overwrite SIGLOST. */
|
||||
|
||||
/* POSIX 1003.1b-1993 real time signals, but take care of incomplete
|
||||
implementations. Acoording to the standard, both, SIGRTMIN and
|
||||
SIGRTMAX must be defined, SIGRTMIN must be stricly less than
|
||||
SIGRTMAX, and the difference must be at least 7, that is, there
|
||||
must be at least eight distinct real time signals. */
|
||||
|
||||
/* The generated signal names are SIGRTMIN, SIGRTMIN+1, ...,
|
||||
SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number
|
||||
of RT signals is odd, there is an extra SIGRTMIN+(x+1).
|
||||
These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */
|
||||
|
||||
#if defined (SIGRTMIN)
|
||||
rtmin = SIGRTMIN;
|
||||
signal_names[rtmin] = "SIGRTMIN";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX)
|
||||
rtmax = SIGRTMAX;
|
||||
signal_names[rtmax] = "SIGRTMAX";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX) && defined (SIGRTMIN)
|
||||
if (rtmax > rtmin)
|
||||
{
|
||||
rtcnt = (rtmax - rtmin - 1) / 2;
|
||||
/* croak if there are too many RT signals */
|
||||
if (rtcnt >= RTLIM/2)
|
||||
{
|
||||
rtcnt = RTLIM/2-1;
|
||||
fprintf(stderr, "%s: error: more than %i real time signals, fix `%s'\n",
|
||||
progname, RTLIM, progname);
|
||||
}
|
||||
|
||||
for (i = 1; i <= rtcnt; i++)
|
||||
{
|
||||
signal_names[rtmin+i] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmin+i])
|
||||
sprintf (signal_names[rtmin+i], "SIGRTMIN+%d", i);
|
||||
signal_names[rtmax-i] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmax-i])
|
||||
sprintf (signal_names[rtmax-i], "SIGRTMAX-%d", i);
|
||||
}
|
||||
|
||||
if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
|
||||
{
|
||||
/* Need an extra RTMIN signal */
|
||||
signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmin+rtcnt+1])
|
||||
sprintf (signal_names[rtmin+rtcnt+1], "SIGRTMIN+%d", rtcnt+1);
|
||||
}
|
||||
}
|
||||
#endif /* SIGRTMIN && SIGRTMAX */
|
||||
|
||||
#if defined (SIGLOST) /* resource lost (eg, record-lock lost) */
|
||||
signal_names[SIGLOST] = "SIGLOST";
|
||||
#endif
|
||||
|
||||
/* AIX */
|
||||
#if defined (SIGMSG) /* HFT input data pending */
|
||||
signal_names[SIGMSG] = "SIGMSG";
|
||||
#endif
|
||||
|
||||
#if defined (SIGDANGER) /* system crash imminent */
|
||||
signal_names[SIGDANGER] = "SIGDANGER";
|
||||
#endif
|
||||
|
||||
#if defined (SIGMIGRATE) /* migrate process to another CPU */
|
||||
signal_names[SIGMIGRATE] = "SIGMIGRATE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPRE) /* programming error */
|
||||
signal_names[SIGPRE] = "SIGPRE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGVIRT) /* AIX virtual time alarm */
|
||||
signal_names[SIGVIRT] = "SIGVIRT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM1) /* m:n condition variables */
|
||||
signal_names[SIGALRM1] = "SIGALRM1";
|
||||
#endif
|
||||
|
||||
#if defined (SIGWAITING) /* m:n scheduling */
|
||||
signal_names[SIGWAITING] = "SIGWAITING";
|
||||
#endif
|
||||
|
||||
#if defined (SIGGRANT) /* HFT monitor mode granted */
|
||||
signal_names[SIGGRANT] = "SIGGRANT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKAP) /* keep alive poll from native keyboard */
|
||||
signal_names[SIGKAP] = "SIGKAP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRETRACT) /* HFT monitor mode retracted */
|
||||
signal_names[SIGRETRACT] = "SIGRETRACT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSOUND) /* HFT sound sequence has completed */
|
||||
signal_names[SIGSOUND] = "SIGSOUND";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSAK) /* Secure Attention Key */
|
||||
signal_names[SIGSAK] = "SIGSAK";
|
||||
#endif
|
||||
|
||||
/* SunOS5 */
|
||||
#if defined (SIGLWP) /* special signal used by thread library */
|
||||
signal_names[SIGLWP] = "SIGLWP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGFREEZE) /* special signal used by CPR */
|
||||
signal_names[SIGFREEZE] = "SIGFREEZE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTHAW) /* special signal used by CPR */
|
||||
signal_names[SIGTHAW] = "SIGTHAW";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCANCEL) /* thread cancellation signal used by libthread */
|
||||
signal_names[SIGCANCEL] = "SIGCANCEL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXRES) /* resource control exceeded */
|
||||
signal_names[SIGXRES] = "SIGXRES";
|
||||
#endif
|
||||
|
||||
/* HP-UX */
|
||||
#if defined (SIGDIL) /* DIL signal (?) */
|
||||
signal_names[SIGDIL] = "SIGDIL";
|
||||
#endif
|
||||
|
||||
/* System V */
|
||||
#if defined (SIGCLD) /* Like SIGCHLD. */
|
||||
signal_names[SIGCLD] = "SIGCLD";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPWR) /* power state indication */
|
||||
signal_names[SIGPWR] = "SIGPWR";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPOLL) /* Pollable event (for streams) */
|
||||
signal_names[SIGPOLL] = "SIGPOLL";
|
||||
#endif
|
||||
|
||||
/* Unknown */
|
||||
#if defined (SIGWINDOW)
|
||||
signal_names[SIGWINDOW] = "SIGWINDOW";
|
||||
#endif
|
||||
|
||||
/* Linux */
|
||||
#if defined (SIGSTKFLT)
|
||||
signal_names[SIGSTKFLT] = "SIGSTKFLT";
|
||||
#endif
|
||||
|
||||
/* FreeBSD */
|
||||
#if defined (SIGTHR) /* thread interrupt */
|
||||
signal_names[SIGTHR] = "SIGTHR";
|
||||
#endif
|
||||
|
||||
/* Common */
|
||||
#if defined (SIGHUP) /* hangup */
|
||||
signal_names[SIGHUP] = "SIGHUP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGINT) /* interrupt */
|
||||
signal_names[SIGINT] = "SIGINT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGQUIT) /* quit */
|
||||
signal_names[SIGQUIT] = "SIGQUIT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGILL) /* illegal instruction (not reset when caught) */
|
||||
signal_names[SIGILL] = "SIGILL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTRAP) /* trace trap (not reset when caught) */
|
||||
signal_names[SIGTRAP] = "SIGTRAP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGIOT) /* IOT instruction */
|
||||
signal_names[SIGIOT] = "SIGIOT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGABRT) /* Cause current process to dump core. */
|
||||
signal_names[SIGABRT] = "SIGABRT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGEMT) /* EMT instruction */
|
||||
signal_names[SIGEMT] = "SIGEMT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGFPE) /* floating point exception */
|
||||
signal_names[SIGFPE] = "SIGFPE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKILL) /* kill (cannot be caught or ignored) */
|
||||
signal_names[SIGKILL] = "SIGKILL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGBUS) /* bus error */
|
||||
signal_names[SIGBUS] = "SIGBUS";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSEGV) /* segmentation violation */
|
||||
signal_names[SIGSEGV] = "SIGSEGV";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSYS) /* bad argument to system call */
|
||||
signal_names[SIGSYS] = "SIGSYS";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPIPE) /* write on a pipe with no one to read it */
|
||||
signal_names[SIGPIPE] = "SIGPIPE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM) /* alarm clock */
|
||||
signal_names[SIGALRM] = "SIGALRM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTERM) /* software termination signal from kill */
|
||||
signal_names[SIGTERM] = "SIGTERM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGURG) /* urgent condition on IO channel */
|
||||
signal_names[SIGURG] = "SIGURG";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSTOP) /* sendable stop signal not from tty */
|
||||
signal_names[SIGSTOP] = "SIGSTOP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTSTP) /* stop signal from tty */
|
||||
signal_names[SIGTSTP] = "SIGTSTP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCONT) /* continue a stopped process */
|
||||
signal_names[SIGCONT] = "SIGCONT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCHLD) /* to parent on child stop or exit */
|
||||
signal_names[SIGCHLD] = "SIGCHLD";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTTIN) /* to readers pgrp upon background tty read */
|
||||
signal_names[SIGTTIN] = "SIGTTIN";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTTOU) /* like TTIN for output if (tp->t_local<OSTOP) */
|
||||
signal_names[SIGTTOU] = "SIGTTOU";
|
||||
#endif
|
||||
|
||||
#if defined (SIGIO) /* input/output possible signal */
|
||||
signal_names[SIGIO] = "SIGIO";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXCPU) /* exceeded CPU time limit */
|
||||
signal_names[SIGXCPU] = "SIGXCPU";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXFSZ) /* exceeded file size limit */
|
||||
signal_names[SIGXFSZ] = "SIGXFSZ";
|
||||
#endif
|
||||
|
||||
#if defined (SIGVTALRM) /* virtual time alarm */
|
||||
signal_names[SIGVTALRM] = "SIGVTALRM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPROF) /* profiling time alarm */
|
||||
signal_names[SIGPROF] = "SIGPROF";
|
||||
#endif
|
||||
|
||||
#if defined (SIGWINCH) /* window changed */
|
||||
signal_names[SIGWINCH] = "SIGWINCH";
|
||||
#endif
|
||||
|
||||
/* 4.4 BSD */
|
||||
#if defined (SIGINFO) && !defined (_SEQUENT_) /* information request */
|
||||
signal_names[SIGINFO] = "SIGINFO";
|
||||
#endif
|
||||
|
||||
#if defined (SIGUSR1) /* user defined signal 1 */
|
||||
signal_names[SIGUSR1] = "SIGUSR1";
|
||||
#endif
|
||||
|
||||
#if defined (SIGUSR2) /* user defined signal 2 */
|
||||
signal_names[SIGUSR2] = "SIGUSR2";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKILLTHR) /* BeOS: Kill Thread */
|
||||
signal_names[SIGKILLTHR] = "SIGKILLTHR";
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
if (signal_names[i] == (char *)NULL)
|
||||
{
|
||||
signal_names[i] = (char *)malloc (18);
|
||||
if (signal_names[i])
|
||||
sprintf (signal_names[i], "SIGJUNK(%d)", i);
|
||||
}
|
||||
|
||||
signal_names[NSIG] = "DEBUG";
|
||||
signal_names[NSIG+1] = "ERR";
|
||||
signal_names[NSIG+2] = "RETURN";
|
||||
}
|
||||
|
||||
void
|
||||
write_signames (stream)
|
||||
FILE *stream;
|
||||
@@ -395,16 +49,22 @@ write_signames (stream)
|
||||
|
||||
fprintf (stream, "/* This file was automatically created by %s.\n",
|
||||
progname);
|
||||
fprintf (stream, " Do not edit. Edit support/mksignames.c instead. */\n\n");
|
||||
fprintf (stream, " Do not edit. Edit support/signames.c instead. */\n\n");
|
||||
fprintf (stream,
|
||||
"/* A translation list so we can be polite to our users. */\n");
|
||||
#if defined (CROSS_COMPILING)
|
||||
fprintf (stream, "extern char *signal_names[];\n\n");
|
||||
fprintf (stream, "extern void initialize_signames __P((void));\n\n");
|
||||
#else
|
||||
fprintf (stream, "char *signal_names[NSIG + 4] = {\n");
|
||||
|
||||
for (i = 0; i <= LASTSIG; i++)
|
||||
fprintf (stream, " \"%s\",\n", signal_names[i]);
|
||||
|
||||
fprintf (stream, " (char *)0x0\n");
|
||||
fprintf (stream, "};\n");
|
||||
fprintf (stream, "};\n\n");
|
||||
fprintf (stream, "#define initialize_signames()\n\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -440,7 +100,9 @@ main (argc, argv)
|
||||
exit (2);
|
||||
}
|
||||
|
||||
#if !defined (CROSS_COMPILING)
|
||||
initialize_signames ();
|
||||
#endif
|
||||
write_signames (stream);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,446 @@
|
||||
/* mksignames.c -- Create and write `signames.h', which contains an array of
|
||||
signal names. */
|
||||
|
||||
/* Copyright (C) 1992-2003 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if !defined (NSIG)
|
||||
# define NSIG 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Special traps:
|
||||
* EXIT == 0
|
||||
* DEBUG == NSIG
|
||||
* ERR == NSIG+1
|
||||
* RETURN == NSIG+2
|
||||
*/
|
||||
#define LASTSIG NSIG+2
|
||||
|
||||
char *signal_names[2 * (LASTSIG)];
|
||||
|
||||
#define signal_names_size (sizeof(signal_names)/sizeof(signal_names[0]))
|
||||
|
||||
char *progname;
|
||||
|
||||
/* AIX 4.3 defines SIGRTMIN and SIGRTMAX as 888 and 999 respectively.
|
||||
I don't want to allocate so much unused space for the intervening signal
|
||||
numbers, so we just punt if SIGRTMAX is past the bounds of the
|
||||
signal_names array (handled in configure). */
|
||||
#if defined (SIGRTMAX) && defined (UNUSABLE_RT_SIGNALS)
|
||||
# undef SIGRTMAX
|
||||
# undef SIGRTMIN
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX) || defined (SIGRTMIN)
|
||||
# define RTLEN 14
|
||||
# define RTLIM 256
|
||||
#endif
|
||||
|
||||
void
|
||||
initialize_signames ()
|
||||
{
|
||||
register int i;
|
||||
#if defined (SIGRTMAX) || defined (SIGRTMIN)
|
||||
int rtmin, rtmax, rtcnt;
|
||||
#endif
|
||||
|
||||
for (i = 1; i < signal_names_size; i++)
|
||||
signal_names[i] = (char *)NULL;
|
||||
|
||||
/* `signal' 0 is what we do on exit. */
|
||||
signal_names[0] = "EXIT";
|
||||
|
||||
/* Place signal names which can be aliases for more common signal
|
||||
names first. This allows (for example) SIGABRT to overwrite SIGLOST. */
|
||||
|
||||
/* POSIX 1003.1b-1993 real time signals, but take care of incomplete
|
||||
implementations. Acoording to the standard, both, SIGRTMIN and
|
||||
SIGRTMAX must be defined, SIGRTMIN must be stricly less than
|
||||
SIGRTMAX, and the difference must be at least 7, that is, there
|
||||
must be at least eight distinct real time signals. */
|
||||
|
||||
/* The generated signal names are SIGRTMIN, SIGRTMIN+1, ...,
|
||||
SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number
|
||||
of RT signals is odd, there is an extra SIGRTMIN+(x+1).
|
||||
These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */
|
||||
|
||||
#if defined (SIGRTMIN)
|
||||
rtmin = SIGRTMIN;
|
||||
signal_names[rtmin] = "SIGRTMIN";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX)
|
||||
rtmax = SIGRTMAX;
|
||||
signal_names[rtmax] = "SIGRTMAX";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX) && defined (SIGRTMIN)
|
||||
if (rtmax > rtmin)
|
||||
{
|
||||
rtcnt = (rtmax - rtmin - 1) / 2;
|
||||
/* croak if there are too many RT signals */
|
||||
if (rtcnt >= RTLIM/2)
|
||||
{
|
||||
rtcnt = RTLIM/2-1;
|
||||
fprintf(stderr, "%s: error: more than %d real time signals, fix `%s'\n",
|
||||
progname, RTLIM, progname);
|
||||
}
|
||||
|
||||
for (i = 1; i <= rtcnt; i++)
|
||||
{
|
||||
signal_names[rtmin+i] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmin+i])
|
||||
sprintf (signal_names[rtmin+i], "SIGRTMIN+%d", i);
|
||||
signal_names[rtmax-i] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmax-i])
|
||||
sprintf (signal_names[rtmax-i], "SIGRTMAX-%d", i);
|
||||
}
|
||||
|
||||
if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
|
||||
{
|
||||
/* Need an extra RTMIN signal */
|
||||
signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmin+rtcnt+1])
|
||||
sprintf (signal_names[rtmin+rtcnt+1], "SIGRTMIN+%d", rtcnt+1);
|
||||
}
|
||||
}
|
||||
#endif /* SIGRTMIN && SIGRTMAX */
|
||||
|
||||
#if defined (SIGLOST) /* resource lost (eg, record-lock lost) */
|
||||
signal_names[SIGLOST] = "SIGLOST";
|
||||
#endif
|
||||
|
||||
/* AIX */
|
||||
#if defined (SIGMSG) /* HFT input data pending */
|
||||
signal_names[SIGMSG] = "SIGMSG";
|
||||
#endif
|
||||
|
||||
#if defined (SIGDANGER) /* system crash imminent */
|
||||
signal_names[SIGDANGER] = "SIGDANGER";
|
||||
#endif
|
||||
|
||||
#if defined (SIGMIGRATE) /* migrate process to another CPU */
|
||||
signal_names[SIGMIGRATE] = "SIGMIGRATE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPRE) /* programming error */
|
||||
signal_names[SIGPRE] = "SIGPRE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGVIRT) /* AIX virtual time alarm */
|
||||
signal_names[SIGVIRT] = "SIGVIRT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM1) /* m:n condition variables */
|
||||
signal_names[SIGALRM1] = "SIGALRM1";
|
||||
#endif
|
||||
|
||||
#if defined (SIGWAITING) /* m:n scheduling */
|
||||
signal_names[SIGWAITING] = "SIGWAITING";
|
||||
#endif
|
||||
|
||||
#if defined (SIGGRANT) /* HFT monitor mode granted */
|
||||
signal_names[SIGGRANT] = "SIGGRANT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKAP) /* keep alive poll from native keyboard */
|
||||
signal_names[SIGKAP] = "SIGKAP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRETRACT) /* HFT monitor mode retracted */
|
||||
signal_names[SIGRETRACT] = "SIGRETRACT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSOUND) /* HFT sound sequence has completed */
|
||||
signal_names[SIGSOUND] = "SIGSOUND";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSAK) /* Secure Attention Key */
|
||||
signal_names[SIGSAK] = "SIGSAK";
|
||||
#endif
|
||||
|
||||
/* SunOS5 */
|
||||
#if defined (SIGLWP) /* special signal used by thread library */
|
||||
signal_names[SIGLWP] = "SIGLWP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGFREEZE) /* special signal used by CPR */
|
||||
signal_names[SIGFREEZE] = "SIGFREEZE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTHAW) /* special signal used by CPR */
|
||||
signal_names[SIGTHAW] = "SIGTHAW";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCANCEL) /* thread cancellation signal used by libthread */
|
||||
signal_names[SIGCANCEL] = "SIGCANCEL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXRES) /* resource control exceeded */
|
||||
signal_names[SIGXRES] = "SIGXRES";
|
||||
#endif
|
||||
|
||||
/* HP-UX */
|
||||
#if defined (SIGDIL) /* DIL signal (?) */
|
||||
signal_names[SIGDIL] = "SIGDIL";
|
||||
#endif
|
||||
|
||||
/* System V */
|
||||
#if defined (SIGCLD) /* Like SIGCHLD. */
|
||||
signal_names[SIGCLD] = "SIGCLD";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPWR) /* power state indication */
|
||||
signal_names[SIGPWR] = "SIGPWR";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPOLL) /* Pollable event (for streams) */
|
||||
signal_names[SIGPOLL] = "SIGPOLL";
|
||||
#endif
|
||||
|
||||
/* Unknown */
|
||||
#if defined (SIGWINDOW)
|
||||
signal_names[SIGWINDOW] = "SIGWINDOW";
|
||||
#endif
|
||||
|
||||
/* Linux */
|
||||
#if defined (SIGSTKFLT)
|
||||
signal_names[SIGSTKFLT] = "SIGSTKFLT";
|
||||
#endif
|
||||
|
||||
/* FreeBSD */
|
||||
#if defined (SIGTHR) /* thread interrupt */
|
||||
signal_names[SIGTHR] = "SIGTHR";
|
||||
#endif
|
||||
|
||||
/* Common */
|
||||
#if defined (SIGHUP) /* hangup */
|
||||
signal_names[SIGHUP] = "SIGHUP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGINT) /* interrupt */
|
||||
signal_names[SIGINT] = "SIGINT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGQUIT) /* quit */
|
||||
signal_names[SIGQUIT] = "SIGQUIT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGILL) /* illegal instruction (not reset when caught) */
|
||||
signal_names[SIGILL] = "SIGILL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTRAP) /* trace trap (not reset when caught) */
|
||||
signal_names[SIGTRAP] = "SIGTRAP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGIOT) /* IOT instruction */
|
||||
signal_names[SIGIOT] = "SIGIOT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGABRT) /* Cause current process to dump core. */
|
||||
signal_names[SIGABRT] = "SIGABRT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGEMT) /* EMT instruction */
|
||||
signal_names[SIGEMT] = "SIGEMT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGFPE) /* floating point exception */
|
||||
signal_names[SIGFPE] = "SIGFPE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKILL) /* kill (cannot be caught or ignored) */
|
||||
signal_names[SIGKILL] = "SIGKILL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGBUS) /* bus error */
|
||||
signal_names[SIGBUS] = "SIGBUS";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSEGV) /* segmentation violation */
|
||||
signal_names[SIGSEGV] = "SIGSEGV";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSYS) /* bad argument to system call */
|
||||
signal_names[SIGSYS] = "SIGSYS";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPIPE) /* write on a pipe with no one to read it */
|
||||
signal_names[SIGPIPE] = "SIGPIPE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM) /* alarm clock */
|
||||
signal_names[SIGALRM] = "SIGALRM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTERM) /* software termination signal from kill */
|
||||
signal_names[SIGTERM] = "SIGTERM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGURG) /* urgent condition on IO channel */
|
||||
signal_names[SIGURG] = "SIGURG";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSTOP) /* sendable stop signal not from tty */
|
||||
signal_names[SIGSTOP] = "SIGSTOP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTSTP) /* stop signal from tty */
|
||||
signal_names[SIGTSTP] = "SIGTSTP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCONT) /* continue a stopped process */
|
||||
signal_names[SIGCONT] = "SIGCONT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCHLD) /* to parent on child stop or exit */
|
||||
signal_names[SIGCHLD] = "SIGCHLD";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTTIN) /* to readers pgrp upon background tty read */
|
||||
signal_names[SIGTTIN] = "SIGTTIN";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTTOU) /* like TTIN for output if (tp->t_local<OSTOP) */
|
||||
signal_names[SIGTTOU] = "SIGTTOU";
|
||||
#endif
|
||||
|
||||
#if defined (SIGIO) /* input/output possible signal */
|
||||
signal_names[SIGIO] = "SIGIO";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXCPU) /* exceeded CPU time limit */
|
||||
signal_names[SIGXCPU] = "SIGXCPU";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXFSZ) /* exceeded file size limit */
|
||||
signal_names[SIGXFSZ] = "SIGXFSZ";
|
||||
#endif
|
||||
|
||||
#if defined (SIGVTALRM) /* virtual time alarm */
|
||||
signal_names[SIGVTALRM] = "SIGVTALRM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPROF) /* profiling time alarm */
|
||||
signal_names[SIGPROF] = "SIGPROF";
|
||||
#endif
|
||||
|
||||
#if defined (SIGWINCH) /* window changed */
|
||||
signal_names[SIGWINCH] = "SIGWINCH";
|
||||
#endif
|
||||
|
||||
/* 4.4 BSD */
|
||||
#if defined (SIGINFO) && !defined (_SEQUENT_) /* information request */
|
||||
signal_names[SIGINFO] = "SIGINFO";
|
||||
#endif
|
||||
|
||||
#if defined (SIGUSR1) /* user defined signal 1 */
|
||||
signal_names[SIGUSR1] = "SIGUSR1";
|
||||
#endif
|
||||
|
||||
#if defined (SIGUSR2) /* user defined signal 2 */
|
||||
signal_names[SIGUSR2] = "SIGUSR2";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKILLTHR) /* BeOS: Kill Thread */
|
||||
signal_names[SIGKILLTHR] = "SIGKILLTHR";
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
if (signal_names[i] == (char *)NULL)
|
||||
{
|
||||
signal_names[i] = (char *)malloc (18);
|
||||
if (signal_names[i])
|
||||
sprintf (signal_names[i], "SIGJUNK(%d)", i);
|
||||
}
|
||||
|
||||
signal_names[NSIG] = "DEBUG";
|
||||
signal_names[NSIG+1] = "ERR";
|
||||
signal_names[NSIG+2] = "RETURN";
|
||||
}
|
||||
|
||||
void
|
||||
write_signames (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
register int i;
|
||||
|
||||
fprintf (stream, "/* This file was automatically created by %s.\n",
|
||||
progname);
|
||||
fprintf (stream, " Do not edit. Edit support/mksignames.c instead. */\n\n");
|
||||
fprintf (stream,
|
||||
"/* A translation list so we can be polite to our users. */\n");
|
||||
fprintf (stream, "char *signal_names[NSIG + 4] = {\n");
|
||||
|
||||
for (i = 0; i <= LASTSIG; i++)
|
||||
fprintf (stream, " \"%s\",\n", signal_names[i]);
|
||||
|
||||
fprintf (stream, " (char *)0x0\n");
|
||||
fprintf (stream, "};\n");
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *stream_name;
|
||||
FILE *stream;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
stream_name = "stdout";
|
||||
stream = stdout;
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
stream_name = argv[1];
|
||||
stream = fopen (stream_name, "w");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Usage: %s [output-file]\n", progname);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!stream)
|
||||
{
|
||||
fprintf (stderr, "%s: %s: cannot open for writing\n",
|
||||
progname, stream_name);
|
||||
exit (2);
|
||||
}
|
||||
|
||||
initialize_signames ();
|
||||
write_signames (stream);
|
||||
exit (0);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/* mksignames.c -- Create and write `signames.h', which contains an array of
|
||||
signal names. */
|
||||
|
||||
/* Copyright (C) 1992-2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
/* Duplicated from signames.c */
|
||||
#if !defined (NSIG)
|
||||
# define NSIG 64
|
||||
#endif
|
||||
|
||||
#define LASTSIG NSIG+2
|
||||
|
||||
/* Imported from signames.c */
|
||||
extern void initialize_signames ();
|
||||
extern char *signal_names[];
|
||||
|
||||
char *progname;
|
||||
|
||||
void
|
||||
write_signames (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
register int i;
|
||||
|
||||
fprintf (stream, "/* This file was automatically created by %s.\n",
|
||||
progname);
|
||||
fprintf (stream, " Do not edit. Edit support/signames.c instead. */\n\n");
|
||||
fprintf (stream,
|
||||
"/* A translation list so we can be polite to our users. */\n");
|
||||
#if defined (CROSS_COMPILING)
|
||||
fprintf (stream, "extern char *signal_names[];\n\n");
|
||||
fprintf (stream, "extern void initialize_signames __P((void))\n\n");
|
||||
#else
|
||||
fprintf (stream, "char *signal_names[NSIG + 4] = {\n");
|
||||
|
||||
for (i = 0; i <= LASTSIG; i++)
|
||||
fprintf (stream, " \"%s\",\n", signal_names[i]);
|
||||
|
||||
fprintf (stream, " (char *)0x0\n");
|
||||
fprintf (stream, "};\n\n");
|
||||
fprintf (stream, "#define initialize_signames()\n\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
char *stream_name;
|
||||
FILE *stream;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
stream_name = "stdout";
|
||||
stream = stdout;
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
stream_name = argv[1];
|
||||
stream = fopen (stream_name, "w");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Usage: %s [output-file]\n", progname);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!stream)
|
||||
{
|
||||
fprintf (stderr, "%s: %s: cannot open for writing\n",
|
||||
progname, stream_name);
|
||||
exit (2);
|
||||
}
|
||||
|
||||
#if !defined (CROSS_COMPILING)
|
||||
initialize_signames ();
|
||||
#endif
|
||||
write_signames (stream);
|
||||
exit (0);
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
/* signames.c -- Create an array of signal names. */
|
||||
|
||||
/* Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if !defined (NSIG)
|
||||
# define NSIG 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Special traps:
|
||||
* EXIT == 0
|
||||
* DEBUG == NSIG
|
||||
* ERR == NSIG+1
|
||||
* RETURN == NSIG+2
|
||||
*/
|
||||
#define LASTSIG NSIG+2
|
||||
|
||||
char *signal_names[2 * (LASTSIG)];
|
||||
|
||||
#define signal_names_size (sizeof(signal_names)/sizeof(signal_names[0]))
|
||||
|
||||
/* AIX 4.3 defines SIGRTMIN and SIGRTMAX as 888 and 999 respectively.
|
||||
I don't want to allocate so much unused space for the intervening signal
|
||||
numbers, so we just punt if SIGRTMAX is past the bounds of the
|
||||
signal_names array (handled in configure). */
|
||||
#if defined (SIGRTMAX) && defined (UNUSABLE_RT_SIGNALS)
|
||||
# undef SIGRTMAX
|
||||
# undef SIGRTMIN
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX) || defined (SIGRTMIN)
|
||||
# define RTLEN 14
|
||||
# define RTLIM 256
|
||||
#endif
|
||||
|
||||
#if defined (BUILDTOOL)
|
||||
extern char *progname;
|
||||
#endif
|
||||
|
||||
void
|
||||
initialize_signames ()
|
||||
{
|
||||
register int i;
|
||||
#if defined (SIGRTMAX) || defined (SIGRTMIN)
|
||||
int rtmin, rtmax, rtcnt;
|
||||
#endif
|
||||
|
||||
for (i = 1; i < signal_names_size; i++)
|
||||
signal_names[i] = (char *)NULL;
|
||||
|
||||
/* `signal' 0 is what we do on exit. */
|
||||
signal_names[0] = "EXIT";
|
||||
|
||||
/* Place signal names which can be aliases for more common signal
|
||||
names first. This allows (for example) SIGABRT to overwrite SIGLOST. */
|
||||
|
||||
/* POSIX 1003.1b-1993 real time signals, but take care of incomplete
|
||||
implementations. Acoording to the standard, both, SIGRTMIN and
|
||||
SIGRTMAX must be defined, SIGRTMIN must be stricly less than
|
||||
SIGRTMAX, and the difference must be at least 7, that is, there
|
||||
must be at least eight distinct real time signals. */
|
||||
|
||||
/* The generated signal names are SIGRTMIN, SIGRTMIN+1, ...,
|
||||
SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number
|
||||
of RT signals is odd, there is an extra SIGRTMIN+(x+1).
|
||||
These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */
|
||||
|
||||
#if defined (SIGRTMIN)
|
||||
rtmin = SIGRTMIN;
|
||||
signal_names[rtmin] = "SIGRTMIN";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX)
|
||||
rtmax = SIGRTMAX;
|
||||
signal_names[rtmax] = "SIGRTMAX";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX) && defined (SIGRTMIN)
|
||||
if (rtmax > rtmin)
|
||||
{
|
||||
rtcnt = (rtmax - rtmin - 1) / 2;
|
||||
/* croak if there are too many RT signals */
|
||||
if (rtcnt >= RTLIM/2)
|
||||
{
|
||||
rtcnt = RTLIM/2-1;
|
||||
#ifdef BUILDTOOL
|
||||
fprintf(stderr, "%s: error: more than %d real time signals, fix `%s'\n",
|
||||
progname, RTLIM, progname);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 1; i <= rtcnt; i++)
|
||||
{
|
||||
signal_names[rtmin+i] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmin+i])
|
||||
sprintf (signal_names[rtmin+i], "SIGRTMIN+%d", i);
|
||||
signal_names[rtmax-i] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmax-i])
|
||||
sprintf (signal_names[rtmax-i], "SIGRTMAX-%d", i);
|
||||
}
|
||||
|
||||
if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
|
||||
{
|
||||
/* Need an extra RTMIN signal */
|
||||
signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmin+rtcnt+1])
|
||||
sprintf (signal_names[rtmin+rtcnt+1], "SIGRTMIN+%d", rtcnt+1);
|
||||
v }
|
||||
}
|
||||
#endif /* SIGRTMIN && SIGRTMAX */
|
||||
|
||||
#if defined (SIGLOST) /* resource lost (eg, record-lock lost) */
|
||||
signal_names[SIGLOST] = "SIGLOST";
|
||||
#endif
|
||||
|
||||
/* AIX */
|
||||
#if defined (SIGMSG) /* HFT input data pending */
|
||||
signal_names[SIGMSG] = "SIGMSG";
|
||||
#endif
|
||||
|
||||
#if defined (SIGDANGER) /* system crash imminent */
|
||||
signal_names[SIGDANGER] = "SIGDANGER";
|
||||
#endif
|
||||
|
||||
#if defined (SIGMIGRATE) /* migrate process to another CPU */
|
||||
signal_names[SIGMIGRATE] = "SIGMIGRATE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPRE) /* programming error */
|
||||
signal_names[SIGPRE] = "SIGPRE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGVIRT) /* AIX virtual time alarm */
|
||||
signal_names[SIGVIRT] = "SIGVIRT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM1) /* m:n condition variables */
|
||||
signal_names[SIGALRM1] = "SIGALRM1";
|
||||
#endif
|
||||
|
||||
#if defined (SIGWAITING) /* m:n scheduling */
|
||||
signal_names[SIGWAITING] = "SIGWAITING";
|
||||
#endif
|
||||
|
||||
#if defined (SIGGRANT) /* HFT monitor mode granted */
|
||||
signal_names[SIGGRANT] = "SIGGRANT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKAP) /* keep alive poll from native keyboard */
|
||||
signal_names[SIGKAP] = "SIGKAP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRETRACT) /* HFT monitor mode retracted */
|
||||
signal_names[SIGRETRACT] = "SIGRETRACT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSOUND) /* HFT sound sequence has completed */
|
||||
signal_names[SIGSOUND] = "SIGSOUND";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSAK) /* Secure Attention Key */
|
||||
signal_names[SIGSAK] = "SIGSAK";
|
||||
#endif
|
||||
|
||||
/* SunOS5 */
|
||||
#if defined (SIGLWP) /* special signal used by thread library */
|
||||
signal_names[SIGLWP] = "SIGLWP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGFREEZE) /* special signal used by CPR */
|
||||
signal_names[SIGFREEZE] = "SIGFREEZE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTHAW) /* special signal used by CPR */
|
||||
signal_names[SIGTHAW] = "SIGTHAW";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCANCEL) /* thread cancellation signal used by libthread */
|
||||
signal_names[SIGCANCEL] = "SIGCANCEL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXRES) /* resource control exceeded */
|
||||
signal_names[SIGXRES] = "SIGXRES";
|
||||
#endif
|
||||
|
||||
/* HP-UX */
|
||||
#if defined (SIGDIL) /* DIL signal (?) */
|
||||
signal_names[SIGDIL] = "SIGDIL";
|
||||
#endif
|
||||
|
||||
/* System V */
|
||||
#if defined (SIGCLD) /* Like SIGCHLD. */
|
||||
signal_names[SIGCLD] = "SIGCLD";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPWR) /* power state indication */
|
||||
signal_names[SIGPWR] = "SIGPWR";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPOLL) /* Pollable event (for streams) */
|
||||
signal_names[SIGPOLL] = "SIGPOLL";
|
||||
#endif
|
||||
|
||||
/* Unknown */
|
||||
#if defined (SIGWINDOW)
|
||||
signal_names[SIGWINDOW] = "SIGWINDOW";
|
||||
#endif
|
||||
|
||||
/* Linux */
|
||||
#if defined (SIGSTKFLT)
|
||||
signal_names[SIGSTKFLT] = "SIGSTKFLT";
|
||||
#endif
|
||||
|
||||
/* FreeBSD */
|
||||
#if defined (SIGTHR) /* thread interrupt */
|
||||
signal_names[SIGTHR] = "SIGTHR";
|
||||
#endif
|
||||
|
||||
/* Common */
|
||||
#if defined (SIGHUP) /* hangup */
|
||||
signal_names[SIGHUP] = "SIGHUP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGINT) /* interrupt */
|
||||
signal_names[SIGINT] = "SIGINT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGQUIT) /* quit */
|
||||
signal_names[SIGQUIT] = "SIGQUIT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGILL) /* illegal instruction (not reset when caught) */
|
||||
signal_names[SIGILL] = "SIGILL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTRAP) /* trace trap (not reset when caught) */
|
||||
signal_names[SIGTRAP] = "SIGTRAP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGIOT) /* IOT instruction */
|
||||
signal_names[SIGIOT] = "SIGIOT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGABRT) /* Cause current process to dump core. */
|
||||
signal_names[SIGABRT] = "SIGABRT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGEMT) /* EMT instruction */
|
||||
signal_names[SIGEMT] = "SIGEMT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGFPE) /* floating point exception */
|
||||
signal_names[SIGFPE] = "SIGFPE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKILL) /* kill (cannot be caught or ignored) */
|
||||
signal_names[SIGKILL] = "SIGKILL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGBUS) /* bus error */
|
||||
signal_names[SIGBUS] = "SIGBUS";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSEGV) /* segmentation violation */
|
||||
signal_names[SIGSEGV] = "SIGSEGV";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSYS) /* bad argument to system call */
|
||||
signal_names[SIGSYS] = "SIGSYS";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPIPE) /* write on a pipe with no one to read it */
|
||||
signal_names[SIGPIPE] = "SIGPIPE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM) /* alarm clock */
|
||||
signal_names[SIGALRM] = "SIGALRM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTERM) /* software termination signal from kill */
|
||||
signal_names[SIGTERM] = "SIGTERM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGURG) /* urgent condition on IO channel */
|
||||
signal_names[SIGURG] = "SIGURG";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSTOP) /* sendable stop signal not from tty */
|
||||
signal_names[SIGSTOP] = "SIGSTOP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTSTP) /* stop signal from tty */
|
||||
signal_names[SIGTSTP] = "SIGTSTP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCONT) /* continue a stopped process */
|
||||
signal_names[SIGCONT] = "SIGCONT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCHLD) /* to parent on child stop or exit */
|
||||
signal_names[SIGCHLD] = "SIGCHLD";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTTIN) /* to readers pgrp upon background tty read */
|
||||
signal_names[SIGTTIN] = "SIGTTIN";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTTOU) /* like TTIN for output if (tp->t_local<OSTOP) */
|
||||
signal_names[SIGTTOU] = "SIGTTOU";
|
||||
#endif
|
||||
|
||||
#if defined (SIGIO) /* input/output possible signal */
|
||||
signal_names[SIGIO] = "SIGIO";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXCPU) /* exceeded CPU time limit */
|
||||
signal_names[SIGXCPU] = "SIGXCPU";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXFSZ) /* exceeded file size limit */
|
||||
signal_names[SIGXFSZ] = "SIGXFSZ";
|
||||
#endif
|
||||
|
||||
#if defined (SIGVTALRM) /* virtual time alarm */
|
||||
signal_names[SIGVTALRM] = "SIGVTALRM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPROF) /* profiling time alarm */
|
||||
signal_names[SIGPROF] = "SIGPROF";
|
||||
#endif
|
||||
|
||||
#if defined (SIGWINCH) /* window changed */
|
||||
signal_names[SIGWINCH] = "SIGWINCH";
|
||||
#endif
|
||||
|
||||
/* 4.4 BSD */
|
||||
#if defined (SIGINFO) && !defined (_SEQUENT_) /* information request */
|
||||
signal_names[SIGINFO] = "SIGINFO";
|
||||
#endif
|
||||
|
||||
#if defined (SIGUSR1) /* user defined signal 1 */
|
||||
signal_names[SIGUSR1] = "SIGUSR1";
|
||||
#endif
|
||||
|
||||
#if defined (SIGUSR2) /* user defined signal 2 */
|
||||
signal_names[SIGUSR2] = "SIGUSR2";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKILLTHR) /* BeOS: Kill Thread */
|
||||
signal_names[SIGKILLTHR] = "SIGKILLTHR";
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
if (signal_names[i] == (char *)NULL)
|
||||
{
|
||||
signal_names[i] = (char *)malloc (18);
|
||||
if (signal_names[i])
|
||||
sprintf (signal_names[i], "SIGJUNK(%d)", i);
|
||||
}
|
||||
|
||||
signal_names[NSIG] = "DEBUG";
|
||||
signal_names[NSIG+1] = "ERR";
|
||||
signal_names[NSIG+2] = "RETURN";
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
/* signames.c -- Create an array of signal names. */
|
||||
|
||||
/* Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if defined (HAVE_STDLIB_H)
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# include "ansi_stdlib.h"
|
||||
#endif /* HAVE_STDLIB_H */
|
||||
|
||||
#if !defined (NSIG)
|
||||
# define NSIG 64
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Special traps:
|
||||
* EXIT == 0
|
||||
* DEBUG == NSIG
|
||||
* ERR == NSIG+1
|
||||
* RETURN == NSIG+2
|
||||
*/
|
||||
#define LASTSIG NSIG+2
|
||||
|
||||
char *signal_names[2 * (LASTSIG)];
|
||||
|
||||
#define signal_names_size (sizeof(signal_names)/sizeof(signal_names[0]))
|
||||
|
||||
/* AIX 4.3 defines SIGRTMIN and SIGRTMAX as 888 and 999 respectively.
|
||||
I don't want to allocate so much unused space for the intervening signal
|
||||
numbers, so we just punt if SIGRTMAX is past the bounds of the
|
||||
signal_names array (handled in configure). */
|
||||
#if defined (SIGRTMAX) && defined (UNUSABLE_RT_SIGNALS)
|
||||
# undef SIGRTMAX
|
||||
# undef SIGRTMIN
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX) || defined (SIGRTMIN)
|
||||
# define RTLEN 14
|
||||
# define RTLIM 256
|
||||
#endif
|
||||
|
||||
#if defined (BUILDTOOL)
|
||||
extern char *progname;
|
||||
#endif
|
||||
|
||||
void
|
||||
initialize_signames ()
|
||||
{
|
||||
register int i;
|
||||
#if defined (SIGRTMAX) || defined (SIGRTMIN)
|
||||
int rtmin, rtmax, rtcnt;
|
||||
#endif
|
||||
|
||||
for (i = 1; i < signal_names_size; i++)
|
||||
signal_names[i] = (char *)NULL;
|
||||
|
||||
/* `signal' 0 is what we do on exit. */
|
||||
signal_names[0] = "EXIT";
|
||||
|
||||
/* Place signal names which can be aliases for more common signal
|
||||
names first. This allows (for example) SIGABRT to overwrite SIGLOST. */
|
||||
v
|
||||
/* POSIX 1003.1b-1993 real time signals, but take care of incomplete
|
||||
implementations. Acoording to the standard, both, SIGRTMIN and
|
||||
SIGRTMAX must be defined, SIGRTMIN must be stricly less than
|
||||
SIGRTMAX, and the difference must be at least 7, that is, there
|
||||
must be at least eight distinct real time signals. */
|
||||
|
||||
/* The generated signal names are SIGRTMIN, SIGRTMIN+1, ...,
|
||||
SIGRTMIN+x, SIGRTMAX-x, ..., SIGRTMAX-1, SIGRTMAX. If the number
|
||||
of RT signals is odd, there is an extra SIGRTMIN+(x+1).
|
||||
These names are the ones used by ksh and /usr/xpg4/bin/sh on SunOS5. */
|
||||
|
||||
#if defined (SIGRTMIN)
|
||||
rtmin = SIGRTMIN;
|
||||
signal_names[rtmin] = "SIGRTMIN";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX)
|
||||
rtmax = SIGRTMAX;
|
||||
signal_names[rtmax] = "SIGRTMAX";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRTMAX) && defined (SIGRTMIN)
|
||||
if (rtmax > rtmin)
|
||||
{
|
||||
rtcnt = (rtmax - rtmin - 1) / 2;
|
||||
/* croak if there are too many RT signals */
|
||||
if (rtcnt >= RTLIM/2)
|
||||
{
|
||||
rtcnt = RTLIM/2-1;
|
||||
#ifdef BUILDTOOL
|
||||
fprintf(stderr, "%s: error: more than %d real time signals, fix `%s'\n",
|
||||
progname, RTLIM, progname);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 1; i <= rtcnt; i++)
|
||||
{
|
||||
signal_names[rtmin+i] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmin+i])
|
||||
sprintf (signal_names[rtmin+i], "SIGRTMIN+%d", i);
|
||||
signal_names[rtmax-i] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmax-i])
|
||||
sprintf (signal_names[rtmax-i], "SIGRTMAX-%d", i);
|
||||
}
|
||||
|
||||
if (rtcnt < RTLIM/2-1 && rtcnt != (rtmax-rtmin)/2)
|
||||
{
|
||||
/* Need an extra RTMIN signal */
|
||||
signal_names[rtmin+rtcnt+1] = (char *)malloc(RTLEN);
|
||||
if (signal_names[rtmin+rtcnt+1])
|
||||
sprintf (signal_names[rtmin+rtcnt+1], "SIGRTMIN+%d", rtcnt+1);
|
||||
v }
|
||||
}
|
||||
#endif /* SIGRTMIN && SIGRTMAX */
|
||||
|
||||
#if defined (SIGLOST) /* resource lost (eg, record-lock lost) */
|
||||
signal_names[SIGLOST] = "SIGLOST";
|
||||
#endif
|
||||
|
||||
/* AIX */
|
||||
#if defined (SIGMSG) /* HFT input data pending */
|
||||
signal_names[SIGMSG] = "SIGMSG";
|
||||
#endif
|
||||
|
||||
#if defined (SIGDANGER) /* system crash imminent */
|
||||
signal_names[SIGDANGER] = "SIGDANGER";
|
||||
#endif
|
||||
|
||||
#if defined (SIGMIGRATE) /* migrate process to another CPU */
|
||||
signal_names[SIGMIGRATE] = "SIGMIGRATE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPRE) /* programming error */
|
||||
signal_names[SIGPRE] = "SIGPRE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGVIRT) /* AIX virtual time alarm */
|
||||
signal_names[SIGVIRT] = "SIGVIRT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM1) /* m:n condition variables */
|
||||
signal_names[SIGALRM1] = "SIGALRM1";
|
||||
#endif
|
||||
|
||||
#if defined (SIGWAITING) /* m:n scheduling */
|
||||
signal_names[SIGWAITING] = "SIGWAITING";
|
||||
#endif
|
||||
|
||||
#if defined (SIGGRANT) /* HFT monitor mode granted */
|
||||
signal_names[SIGGRANT] = "SIGGRANT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKAP) /* keep alive poll from native keyboard */
|
||||
signal_names[SIGKAP] = "SIGKAP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGRETRACT) /* HFT monitor mode retracted */
|
||||
signal_names[SIGRETRACT] = "SIGRETRACT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSOUND) /* HFT sound sequence has completed */
|
||||
signal_names[SIGSOUND] = "SIGSOUND";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSAK) /* Secure Attention Key */
|
||||
signal_names[SIGSAK] = "SIGSAK";
|
||||
#endif
|
||||
|
||||
/* SunOS5 */
|
||||
#if defined (SIGLWP) /* special signal used by thread library */
|
||||
signal_names[SIGLWP] = "SIGLWP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGFREEZE) /* special signal used by CPR */
|
||||
signal_names[SIGFREEZE] = "SIGFREEZE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTHAW) /* special signal used by CPR */
|
||||
signal_names[SIGTHAW] = "SIGTHAW";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCANCEL) /* thread cancellation signal used by libthread */
|
||||
signal_names[SIGCANCEL] = "SIGCANCEL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXRES) /* resource control exceeded */
|
||||
signal_names[SIGXRES] = "SIGXRES";
|
||||
#endif
|
||||
|
||||
/* HP-UX */
|
||||
#if defined (SIGDIL) /* DIL signal (?) */
|
||||
signal_names[SIGDIL] = "SIGDIL";
|
||||
#endif
|
||||
|
||||
/* System V */
|
||||
#if defined (SIGCLD) /* Like SIGCHLD. */
|
||||
signal_names[SIGCLD] = "SIGCLD";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPWR) /* power state indication */
|
||||
signal_names[SIGPWR] = "SIGPWR";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPOLL) /* Pollable event (for streams) */
|
||||
signal_names[SIGPOLL] = "SIGPOLL";
|
||||
#endif
|
||||
|
||||
/* Unknown */
|
||||
#if defined (SIGWINDOW)
|
||||
signal_names[SIGWINDOW] = "SIGWINDOW";
|
||||
#endif
|
||||
|
||||
/* Linux */
|
||||
#if defined (SIGSTKFLT)
|
||||
signal_names[SIGSTKFLT] = "SIGSTKFLT";
|
||||
#endif
|
||||
|
||||
/* FreeBSD */
|
||||
#if defined (SIGTHR) /* thread interrupt */
|
||||
signal_names[SIGTHR] = "SIGTHR";
|
||||
#endif
|
||||
|
||||
/* Common */
|
||||
#if defined (SIGHUP) /* hangup */
|
||||
signal_names[SIGHUP] = "SIGHUP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGINT) /* interrupt */
|
||||
signal_names[SIGINT] = "SIGINT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGQUIT) /* quit */
|
||||
signal_names[SIGQUIT] = "SIGQUIT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGILL) /* illegal instruction (not reset when caught) */
|
||||
signal_names[SIGILL] = "SIGILL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTRAP) /* trace trap (not reset when caught) */
|
||||
signal_names[SIGTRAP] = "SIGTRAP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGIOT) /* IOT instruction */
|
||||
signal_names[SIGIOT] = "SIGIOT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGABRT) /* Cause current process to dump core. */
|
||||
signal_names[SIGABRT] = "SIGABRT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGEMT) /* EMT instruction */
|
||||
signal_names[SIGEMT] = "SIGEMT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGFPE) /* floating point exception */
|
||||
signal_names[SIGFPE] = "SIGFPE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKILL) /* kill (cannot be caught or ignored) */
|
||||
signal_names[SIGKILL] = "SIGKILL";
|
||||
#endif
|
||||
|
||||
#if defined (SIGBUS) /* bus error */
|
||||
signal_names[SIGBUS] = "SIGBUS";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSEGV) /* segmentation violation */
|
||||
signal_names[SIGSEGV] = "SIGSEGV";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSYS) /* bad argument to system call */
|
||||
signal_names[SIGSYS] = "SIGSYS";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPIPE) /* write on a pipe with no one to read it */
|
||||
signal_names[SIGPIPE] = "SIGPIPE";
|
||||
#endif
|
||||
|
||||
#if defined (SIGALRM) /* alarm clock */
|
||||
signal_names[SIGALRM] = "SIGALRM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTERM) /* software termination signal from kill */
|
||||
signal_names[SIGTERM] = "SIGTERM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGURG) /* urgent condition on IO channel */
|
||||
signal_names[SIGURG] = "SIGURG";
|
||||
#endif
|
||||
|
||||
#if defined (SIGSTOP) /* sendable stop signal not from tty */
|
||||
signal_names[SIGSTOP] = "SIGSTOP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTSTP) /* stop signal from tty */
|
||||
signal_names[SIGTSTP] = "SIGTSTP";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCONT) /* continue a stopped process */
|
||||
signal_names[SIGCONT] = "SIGCONT";
|
||||
#endif
|
||||
|
||||
#if defined (SIGCHLD) /* to parent on child stop or exit */
|
||||
signal_names[SIGCHLD] = "SIGCHLD";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTTIN) /* to readers pgrp upon background tty read */
|
||||
signal_names[SIGTTIN] = "SIGTTIN";
|
||||
#endif
|
||||
|
||||
#if defined (SIGTTOU) /* like TTIN for output if (tp->t_local<OSTOP) */
|
||||
signal_names[SIGTTOU] = "SIGTTOU";
|
||||
#endif
|
||||
|
||||
#if defined (SIGIO) /* input/output possible signal */
|
||||
signal_names[SIGIO] = "SIGIO";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXCPU) /* exceeded CPU time limit */
|
||||
signal_names[SIGXCPU] = "SIGXCPU";
|
||||
#endif
|
||||
|
||||
#if defined (SIGXFSZ) /* exceeded file size limit */
|
||||
signal_names[SIGXFSZ] = "SIGXFSZ";
|
||||
#endif
|
||||
|
||||
#if defined (SIGVTALRM) /* virtual time alarm */
|
||||
signal_names[SIGVTALRM] = "SIGVTALRM";
|
||||
#endif
|
||||
|
||||
#if defined (SIGPROF) /* profiling time alarm */
|
||||
signal_names[SIGPROF] = "SIGPROF";
|
||||
#endif
|
||||
|
||||
#if defined (SIGWINCH) /* window changed */
|
||||
signal_names[SIGWINCH] = "SIGWINCH";
|
||||
#endif
|
||||
|
||||
/* 4.4 BSD */
|
||||
#if defined (SIGINFO) && !defined (_SEQUENT_) /* information request */
|
||||
signal_names[SIGINFO] = "SIGINFO";
|
||||
#endif
|
||||
|
||||
#if defined (SIGUSR1) /* user defined signal 1 */
|
||||
signal_names[SIGUSR1] = "SIGUSR1";
|
||||
#endif
|
||||
|
||||
#if defined (SIGUSR2) /* user defined signal 2 */
|
||||
signal_names[SIGUSR2] = "SIGUSR2";
|
||||
#endif
|
||||
|
||||
#if defined (SIGKILLTHR) /* BeOS: Kill Thread */
|
||||
signal_names[SIGKILLTHR] = "SIGKILLTHR";
|
||||
#endif
|
||||
|
||||
for (i = 0; i < NSIG; i++)
|
||||
if (signal_names[i] == (char *)NULL)
|
||||
{
|
||||
signal_names[i] = (char *)malloc (18);
|
||||
if (signal_names[i])
|
||||
sprintf (signal_names[i], "SIGJUNK(%d)", i);
|
||||
}
|
||||
|
||||
signal_names[NSIG] = "DEBUG";
|
||||
signal_names[NSIG+1] = "ERR";
|
||||
signal_names[NSIG+2] = "RETURN";
|
||||
}
|
||||
+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 "$@"
|
||||
+1
-1
@@ -430,7 +430,7 @@ Case05---3---A:B:C---
|
||||
Case06---1---A B C::---
|
||||
Case07---3---A:B:C---
|
||||
Case08---3---A:B:C---
|
||||
./new-exp.tests: line 506: ${$(($#-1))}: bad substitution
|
||||
./new-exp.tests: line 506: /${$(($#-1))}: bad substitution
|
||||
argv[1] = <a>
|
||||
argv[2] = <b>
|
||||
argv[3] = <c>
|
||||
|
||||
+7
-7
@@ -212,9 +212,9 @@ recho ${av[1]/??/za}
|
||||
expect '<zaza>'
|
||||
recho ${av[1]//??/za}
|
||||
expect '<zagh>'
|
||||
recho ${av[1]//#??/za}
|
||||
recho ${av[1]/#??/za}
|
||||
expect '<efza>'
|
||||
recho ${av[1]//%??/za}
|
||||
recho ${av[1]/%??/za}
|
||||
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/*/yyy}
|
||||
@@ -238,17 +238,17 @@ recho ${@/%??/xx}
|
||||
expect '<zaza>'
|
||||
recho ${3//??/za}
|
||||
expect '<efza>'
|
||||
recho ${3//%??/za}
|
||||
recho ${3/%??/za}
|
||||
expect '<zaza> <zaza> <zaza> <zaza> <zaza> <zaza>'
|
||||
recho ${@//??/za}
|
||||
expect '<zacd> <zagh> <zakl> <zaop> <zast> <zawx>'
|
||||
recho ${@//#??/za}
|
||||
recho ${@/#??/za}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${@//*/yyy}
|
||||
expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>'
|
||||
recho ${@//a*/yyy}
|
||||
expect '<abcd> <efgh> <ijkl> <mnop> <qrst> <uvwyyy>'
|
||||
recho ${@//%x*/yyy}
|
||||
recho ${@/%x*/yyy}
|
||||
|
||||
expect a newline
|
||||
echo $abmcde
|
||||
@@ -548,8 +548,8 @@ var=blah
|
||||
# these had better agree
|
||||
echo ${var[@]:3}
|
||||
echo ${var:3}
|
||||
echo ${var[@]//#/--}
|
||||
echo ${var//#/--}
|
||||
echo ${var[@]/#/--}
|
||||
echo ${var/#/--}
|
||||
echo ${var[@]##?}
|
||||
echo ${var##?}
|
||||
|
||||
|
||||
@@ -0,0 +1,558 @@
|
||||
# must do this because posix mode causes process substitution to be disabled
|
||||
# and flagged as a syntax error, which causes the shell to exit
|
||||
set +o posix
|
||||
|
||||
expect()
|
||||
{
|
||||
echo expect "$@"
|
||||
}
|
||||
|
||||
HOME=/usr/homes/chet # to make the check against new-exp.right work
|
||||
expect '<foo bar>'
|
||||
recho "${undef-"foo bar"}" # should be foo bar
|
||||
expect '<foo>'
|
||||
recho "${und="foo"}" # should be foo
|
||||
|
||||
expect "<$HOME>"
|
||||
recho ${HOME-"}"}
|
||||
expect "<$HOME>"
|
||||
recho "${HOME-'}'}"
|
||||
expect "<$HOME>"
|
||||
recho "${HOME-"}"}"
|
||||
|
||||
expect $0: 'HOME: }: syntax error: operand expected (error token is "}")'
|
||||
recho "${HOME:`echo }`}" # should be a math error -- bad substring substitution
|
||||
|
||||
expect unset
|
||||
_ENV=oops
|
||||
x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]}
|
||||
echo ${x:-unset}
|
||||
|
||||
expect "<$HOME>"
|
||||
recho ${HOME}
|
||||
expect "<$HOME>"
|
||||
recho ${HOME:-`echo }`}
|
||||
expect "<$HOME>"
|
||||
recho ${HOME:-`echo "}"`}
|
||||
expect "<$HOME>"
|
||||
recho "${HOME:-`echo "}"`}"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "${HOME}")"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "$(echo ${HOME})")"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "$(echo "${HOME}")")"
|
||||
|
||||
P=*@*
|
||||
expect '<*@>'
|
||||
recho "${P%"*"}" #
|
||||
expect '<*@>'
|
||||
recho "${P%'*'}" #
|
||||
expect '<@*>'
|
||||
recho "${P#\*}" # should be @*
|
||||
|
||||
expect '<)>'
|
||||
recho "$(echo ")")" # should be )
|
||||
expect '<")">'
|
||||
recho "$(echo "\")\"")" # should be ")"
|
||||
|
||||
foo='abcd '
|
||||
expect '<-abcd> <->'
|
||||
recho -${foo}- # should be -abcd -
|
||||
expect '<-abcd> <->'
|
||||
recho -${foo% *}- # should be -abcd -
|
||||
expect '<-abcd->'
|
||||
recho -${foo%% *}- # should be -abcd-
|
||||
|
||||
foo=bar
|
||||
expect '<bar foo>'
|
||||
echo -n $foo' ' ; echo foo
|
||||
|
||||
expect '<bar foo>'
|
||||
echo -n $foo" " ; echo foo
|
||||
|
||||
expect '<bar foo>'
|
||||
echo -n "$foo " ; echo foo
|
||||
|
||||
expect '<barfoo>'
|
||||
echo -e "$foo\c " ; echo foo
|
||||
|
||||
expect '<barfoo>'
|
||||
echo -e $foo"\c " ; echo foo
|
||||
|
||||
# make sure backslashes are preserved in front of characters that are not
|
||||
# valid backslash escapes
|
||||
expect '<\x>'
|
||||
echo -e '\x'
|
||||
|
||||
# substring tests
|
||||
z=abcdefghijklmnop
|
||||
expect '<abcd>'
|
||||
recho ${z:0:4}
|
||||
|
||||
expect '<efg> <nop>'
|
||||
recho ${z:4:3} ${z:${#z}-3:3}
|
||||
|
||||
expect '<efg> <nop>'
|
||||
recho ${z:4:3} ${z: -3:3}
|
||||
|
||||
expect '<hijklmnop>'
|
||||
recho ${z:7:30}
|
||||
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${z:0:100}
|
||||
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${z:0:${#z}}
|
||||
|
||||
set 'ab cd' 'ef' 'gh ij' 'kl mn' 'op'
|
||||
expect '<ab cd> <ef>'
|
||||
recho "${@:1:2}"
|
||||
|
||||
expect '<gh ij> <kl mn>'
|
||||
recho "${@:3:2}"
|
||||
|
||||
expect '<gh ij> <kl mn> <op>'
|
||||
recho "${@:3:4}"
|
||||
|
||||
expect '<ab cd> <ef> <gh ij> <kl mn> <op>'
|
||||
recho "${@:1:$#}"
|
||||
|
||||
# code to ad-hoc parse arithmetic expressions in substring expansions was
|
||||
# broken until post-2.04
|
||||
base=/home/chet/foo//bar
|
||||
string1=$base/abcabcabc
|
||||
x=1 j=4
|
||||
|
||||
expect '</home/chet/foo//bar/abcabcabc>'
|
||||
recho ${string1:0}
|
||||
|
||||
expect '<home/chet/foo//bar/abcabcabc>'
|
||||
recho ${string1:1}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:(j?1:0):j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:j?1:0:j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:(j?(x?1:0):0):j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:j?(x?1:0):0:j}
|
||||
|
||||
unset base string1 x j
|
||||
|
||||
# indirect variable references
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${!9:-$z}
|
||||
|
||||
ef=4
|
||||
expect '<4>'
|
||||
recho ${!2}
|
||||
|
||||
expect '<op>'
|
||||
recho ${!#}
|
||||
|
||||
set a b c d e
|
||||
a=
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${a:-$z}
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${!1:-$z}
|
||||
|
||||
expect nothing
|
||||
recho ${a-$z}
|
||||
expect nothing
|
||||
recho ${!1-$z}
|
||||
|
||||
set -u
|
||||
expect $0: ABX: unbound variable
|
||||
( recho ${ABX} )
|
||||
set +u
|
||||
|
||||
expect $0: '$6: cannot assign in this way'
|
||||
recho ${6="arg6"}
|
||||
|
||||
v=abcde
|
||||
|
||||
# sed-like variable substitution
|
||||
expect '<xxcde>'
|
||||
recho ${v/a[a-z]/xx}
|
||||
expect '<axxde>'
|
||||
recho ${v/a??/axx}
|
||||
expect '<abxyz>'
|
||||
recho ${v/c??/xyz}
|
||||
expect '<abbcde>'
|
||||
recho ${v/#a/ab}
|
||||
expect '<abcde>'
|
||||
recho ${v/#d/ab}
|
||||
expect '<abcabe>'
|
||||
recho ${v/d/ab}
|
||||
expect '<abcdlast>'
|
||||
recho ${v/%?/last}
|
||||
expect '<abcde>'
|
||||
recho ${v/%x/last}
|
||||
|
||||
av=(abcd efgh ijkl mnop qrst uvwx)
|
||||
|
||||
expect '<xxcd>'
|
||||
recho ${av/??/xx}
|
||||
expect '<abxx>'
|
||||
recho ${av/%??/xx}
|
||||
expect '<xxgh>'
|
||||
recho ${av[1]/??/xx}
|
||||
expect '<efgh>'
|
||||
recho ${av[1]/%ab/xx}
|
||||
expect '<xxfgh>'
|
||||
recho ${av[1]/#?/xx}
|
||||
expect '<zagh>'
|
||||
recho ${av[1]/??/za}
|
||||
expect '<zaza>'
|
||||
recho ${av[1]//??/za}
|
||||
expect '<zagh>'
|
||||
recho ${av[1]//#??/za}
|
||||
expect '<efza>'
|
||||
recho ${av[1]//%??/za}
|
||||
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/*/yyy}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/#*/yyy}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/%*/yyy}
|
||||
expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>'
|
||||
recho ${av[@]/a*/yyy}
|
||||
expect '<abxx> <efxx> <ijxx> <mnxx> <qrxx> <uvxx>'
|
||||
recho ${av[@]/%??/xx}
|
||||
|
||||
set abcd efgh ijkl mnop qrst uvwx
|
||||
|
||||
expect '<xxcd>'
|
||||
recho ${1/??/xx}
|
||||
expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>'
|
||||
recho ${@/??/xx}
|
||||
expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>'
|
||||
recho ${@/%??/xx}
|
||||
expect '<zaza>'
|
||||
recho ${3//??/za}
|
||||
expect '<efza>'
|
||||
recho ${3//%??/za}
|
||||
expect '<zaza> <zaza> <zaza> <zaza> <zaza> <zaza>'
|
||||
recho ${@//??/za}
|
||||
expect '<zacd> <zagh> <zakl> <zaop> <zast> <zawx>'
|
||||
recho ${@//#??/za}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${@//*/yyy}
|
||||
expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>'
|
||||
recho ${@//a*/yyy}
|
||||
expect '<abcd> <efgh> <ijkl> <mnop> <qrst> <uvwyyy>'
|
||||
recho ${@//%x*/yyy}
|
||||
|
||||
expect a newline
|
||||
echo $abmcde
|
||||
|
||||
# sneaky way to replace a newline in a variable value with something else
|
||||
AVAR=$'This\nstring\nhas\nmultiple\nlines.'
|
||||
echo "${AVAR}"
|
||||
|
||||
eval BVAR=\"\${AVAR//$'\n'/-}\"
|
||||
echo "$BVAR"
|
||||
|
||||
unset AVAR BVAR
|
||||
|
||||
# run process substitution tests in a subshell so that syntax errors
|
||||
# caused by a shell not implementing process substitution (e.g., one
|
||||
# built on a NeXT) will not cause the whole test to exit prematurely
|
||||
${THIS_SH} ./new-exp1.sub
|
||||
|
||||
# run the tests of $(<filename) in a subshell to avoid cluttering up
|
||||
# this script
|
||||
${THIS_SH} ./new-exp2.sub
|
||||
|
||||
expect '<6>'
|
||||
recho ${#:-foo}
|
||||
expect $0: '${#:}: bad substitution'
|
||||
echo ${#:}
|
||||
|
||||
expect "<'>"
|
||||
recho "'"
|
||||
expect '<">'
|
||||
recho '"'
|
||||
expect '<"hello">'
|
||||
recho "\"hello\""
|
||||
|
||||
shift $#
|
||||
unset foo
|
||||
z=abcdef
|
||||
z1='abc def'
|
||||
|
||||
expect '<>'
|
||||
recho ${foo:-""}
|
||||
expect nothing
|
||||
recho ${foo:-"$@"}
|
||||
expect '<>'
|
||||
recho "${foo:-$@}"
|
||||
|
||||
# unset var
|
||||
expect '<>'
|
||||
recho ${foo:-"$zbcd"}
|
||||
expect nothing
|
||||
recho ${foo:-$zbcd}
|
||||
|
||||
# set var
|
||||
expect '<abcdef>'
|
||||
recho ${foo:-"$z"}
|
||||
expect '<abc def>'
|
||||
recho ${foo:-"$z1"}
|
||||
|
||||
expect '<abcdef>'
|
||||
recho ${foo:-$z}
|
||||
expect '<abc> <def>'
|
||||
recho ${foo:-$z1}
|
||||
|
||||
expect '<abcdef>'
|
||||
recho "${foo:-$z}"
|
||||
expect '<abc def>'
|
||||
recho "${foo:-$z1}"
|
||||
|
||||
expect '<abcdef>'
|
||||
recho "${foo:-"$z"}"
|
||||
# this disagrees with sh and ksh, but I think it is right according
|
||||
# to posix.2.
|
||||
expect '<abc def>'
|
||||
recho "${foo:-"$z1"}"
|
||||
|
||||
set ab cd ef gh
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho ${foo:-"$@"}
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho "${foo:-$@}"
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho "${foo:-"$@"}"
|
||||
|
||||
shift $#
|
||||
expect nothing
|
||||
recho $xxx"$@"
|
||||
expect nothing
|
||||
recho ${foo:-$xxx"$@"}
|
||||
expect '<>'
|
||||
recho "${foo:-$xxx$@}"
|
||||
expect '<>'
|
||||
recho "${foo:-$xxx"$@"}"
|
||||
|
||||
expect nothing
|
||||
recho $xxx"$@"
|
||||
expect nothing
|
||||
recho "$xxx$@"
|
||||
expect nothing
|
||||
recho "$@"$xxx
|
||||
|
||||
expect '<>'
|
||||
recho $xxx""
|
||||
expect '<>'
|
||||
recho $xxx''
|
||||
expect '<>'
|
||||
recho ''$xxx
|
||||
expect '<>'
|
||||
recho ""$xxx
|
||||
|
||||
AB='abcdefghijklmnopqrstuvwxyz'
|
||||
|
||||
recho ${AB:7:15}
|
||||
recho ${AB:15:7}
|
||||
|
||||
recho ${AB:20}
|
||||
|
||||
recho ${AB:0}
|
||||
recho ${AB:0:20}
|
||||
|
||||
recho ${AB:10:7}
|
||||
recho ${AB:10:3+4}
|
||||
recho ${AB:20/2:3+4}
|
||||
|
||||
set 1 2 3 4 5 6
|
||||
recho \""${*:2:2}"\"
|
||||
|
||||
IFS=:
|
||||
recho \""${*:2:2}"\"
|
||||
|
||||
IFS=$' \t\n'
|
||||
|
||||
z=123456
|
||||
|
||||
recho \""${z:2:2}"\"
|
||||
recho \""${z:2}"\"
|
||||
recho \""${z:2:4}"\"
|
||||
recho \""${z:2:6}"\"
|
||||
|
||||
set $'\1' $'\2' $'\177'
|
||||
|
||||
recho $*
|
||||
recho $@
|
||||
|
||||
recho ${*}
|
||||
recho ${@}
|
||||
|
||||
xx=one/two/two
|
||||
recho ${xx%/*}
|
||||
recho ${xx/\/two}
|
||||
|
||||
yy=oneonetwo
|
||||
recho ${yy//one}
|
||||
recho ${yy/\/one}
|
||||
|
||||
xx=oneonetwo
|
||||
|
||||
recho ${xx/one}
|
||||
recho ${xx//one}
|
||||
recho ${xx/\/one}
|
||||
|
||||
# out-of-range substrings
|
||||
var=abc
|
||||
c=${var:3}
|
||||
expect nothing
|
||||
recho $c
|
||||
c=${var:4}
|
||||
expect nothing
|
||||
recho $c
|
||||
expect '<./new-exp.tests: -2: substring expression < 0>'
|
||||
c=${var:0:-2}
|
||||
|
||||
var=abcdefghi
|
||||
c=${var:3:12}
|
||||
recho $c
|
||||
c=${var:4:20}
|
||||
recho $c
|
||||
|
||||
# make sure null patterns work
|
||||
xxx=endocrine
|
||||
yyy=n
|
||||
unset zzz
|
||||
|
||||
recho ${xxx/$yyy/*}
|
||||
recho ${xxx//$yyy/*}
|
||||
|
||||
recho ${xxx/$zzz/*}
|
||||
recho ${xxx//$zzz/*}
|
||||
|
||||
recho ${xxx//%${zzz}/}
|
||||
recho ${xxx//%${zzz}}
|
||||
recho ${xxx//#${zzz}/}
|
||||
recho ${xxx//#${zzz}}
|
||||
|
||||
# another case that caused a core dump in bash-2.0
|
||||
XPATH=/usr/bin:/bin:/usr/local/bin:/usr/gnu/bin::/usr/bin/X11:/sbin:/usr/sbin
|
||||
|
||||
recho ${XPATH//:/ }
|
||||
|
||||
xx=(ar as at au av aw ax ay az)
|
||||
|
||||
recho ${xx[@]/a/}
|
||||
recho ${xx[@]//a/}
|
||||
|
||||
recho ${xx[*]/a/}
|
||||
recho ${xx[*]//a/}
|
||||
|
||||
recho ${xx[@]%?}
|
||||
recho ${xx[*]%?}
|
||||
|
||||
recho ${xx[@]#?}
|
||||
recho ${xx[*]#?}
|
||||
|
||||
set -- ar as at au av aw ax ay az
|
||||
|
||||
recho ${@/a/}
|
||||
recho ${@//a/}
|
||||
|
||||
recho ${*/a/}
|
||||
recho ${*//a/}
|
||||
|
||||
recho ${@%?}
|
||||
recho ${*%?}
|
||||
|
||||
recho ${@#?}
|
||||
recho ${*#?}
|
||||
|
||||
shift $#
|
||||
set -u
|
||||
( recho $9 ; echo after 1)
|
||||
( recho ${9} ; echo after 2)
|
||||
( recho $UNSET ; echo after 3)
|
||||
( recho ${UNSET} ; echo after 4)
|
||||
( recho "$UNSET" ; echo after 5)
|
||||
( recho "${UNSET}" ; echo after 6)
|
||||
( recho "${#UNSET}" ; echo after 7)
|
||||
set +u
|
||||
|
||||
RECEIVED="12345"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED="12345#"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED="#"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED=""
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
|
||||
# tests of new prefix expansion ${!prefix*}
|
||||
${THIS_SH} ./new-exp3.sub
|
||||
|
||||
# bug with indirect expansion through bash-2.05b
|
||||
${THIS_SH} ./new-exp4.sub
|
||||
|
||||
# these caused errors and core dumps in versions before bash-2.04
|
||||
c=""
|
||||
echo ${c//${$(($#-1))}/x/}
|
||||
|
||||
set a b c d e f g
|
||||
recho "$@"
|
||||
|
||||
set -- ${@:1:$(($# - 2))}
|
||||
recho "$@"
|
||||
|
||||
set a b
|
||||
recho ${@:1:$(($# - 2))}
|
||||
|
||||
recho ${@:1:0}
|
||||
recho ${@:1:1}
|
||||
recho ${@:1:2}
|
||||
|
||||
recho "${*:1:0}"
|
||||
|
||||
# this is an error -- negative expression
|
||||
set a
|
||||
recho ${@:1:$(($# - 2))}
|
||||
|
||||
XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin
|
||||
set $( IFS=: ; echo $XPATH )
|
||||
|
||||
recho ${@##*/}
|
||||
recho ${@%%[!/]*}
|
||||
|
||||
recho ${@#/*}
|
||||
recho ${@%*/}
|
||||
|
||||
set /full/path/to/x16 /another/full/path
|
||||
|
||||
recho ${1%/*}
|
||||
recho ${1%%[!/]*}
|
||||
recho ${1#*/}
|
||||
recho ${1##*/}
|
||||
|
||||
${THIS_SH} ./new-exp5.sub
|
||||
|
||||
unset var
|
||||
var=blah
|
||||
|
||||
# these had better agree
|
||||
echo ${var[@]:3}
|
||||
echo ${var:3}
|
||||
echo ${var[@]//#/--}
|
||||
echo ${var//#/--}
|
||||
echo ${var[@]##?}
|
||||
echo ${var##?}
|
||||
|
||||
# this must be last!
|
||||
expect $0: 'ABXD: parameter unset'
|
||||
recho ${ABXD:?"parameter unset"}
|
||||
@@ -0,0 +1,558 @@
|
||||
# must do this because posix mode causes process substitution to be disabled
|
||||
# and flagged as a syntax error, which causes the shell to exit
|
||||
set +o posix
|
||||
|
||||
expect()
|
||||
{
|
||||
echo expect "$@"
|
||||
}
|
||||
|
||||
HOME=/usr/homes/chet # to make the check against new-exp.right work
|
||||
expect '<foo bar>'
|
||||
recho "${undef-"foo bar"}" # should be foo bar
|
||||
expect '<foo>'
|
||||
recho "${und="foo"}" # should be foo
|
||||
|
||||
expect "<$HOME>"
|
||||
recho ${HOME-"}"}
|
||||
expect "<$HOME>"
|
||||
recho "${HOME-'}'}"
|
||||
expect "<$HOME>"
|
||||
recho "${HOME-"}"}"
|
||||
|
||||
expect $0: 'HOME: }: syntax error: operand expected (error token is "}")'
|
||||
recho "${HOME:`echo }`}" # should be a math error -- bad substring substitution
|
||||
|
||||
expect unset
|
||||
_ENV=oops
|
||||
x=${_ENV[(_$-=0)+(_=1)-_${-%%*i*}]}
|
||||
echo ${x:-unset}
|
||||
|
||||
expect "<$HOME>"
|
||||
recho ${HOME}
|
||||
expect "<$HOME>"
|
||||
recho ${HOME:-`echo }`}
|
||||
expect "<$HOME>"
|
||||
recho ${HOME:-`echo "}"`}
|
||||
expect "<$HOME>"
|
||||
recho "${HOME:-`echo "}"`}"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "${HOME}")"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "$(echo ${HOME})")"
|
||||
expect "<$HOME>"
|
||||
recho "$(echo "$(echo "${HOME}")")"
|
||||
|
||||
P=*@*
|
||||
expect '<*@>'
|
||||
recho "${P%"*"}" #
|
||||
expect '<*@>'
|
||||
recho "${P%'*'}" #
|
||||
expect '<@*>'
|
||||
recho "${P#\*}" # should be @*
|
||||
|
||||
expect '<)>'
|
||||
recho "$(echo ")")" # should be )
|
||||
expect '<")">'
|
||||
recho "$(echo "\")\"")" # should be ")"
|
||||
|
||||
foo='abcd '
|
||||
expect '<-abcd> <->'
|
||||
recho -${foo}- # should be -abcd -
|
||||
expect '<-abcd> <->'
|
||||
recho -${foo% *}- # should be -abcd -
|
||||
expect '<-abcd->'
|
||||
recho -${foo%% *}- # should be -abcd-
|
||||
|
||||
foo=bar
|
||||
expect '<bar foo>'
|
||||
echo -n $foo' ' ; echo foo
|
||||
|
||||
expect '<bar foo>'
|
||||
echo -n $foo" " ; echo foo
|
||||
|
||||
expect '<bar foo>'
|
||||
echo -n "$foo " ; echo foo
|
||||
|
||||
expect '<barfoo>'
|
||||
echo -e "$foo\c " ; echo foo
|
||||
|
||||
expect '<barfoo>'
|
||||
echo -e $foo"\c " ; echo foo
|
||||
|
||||
# make sure backslashes are preserved in front of characters that are not
|
||||
# valid backslash escapes
|
||||
expect '<\x>'
|
||||
echo -e '\x'
|
||||
|
||||
# substring tests
|
||||
z=abcdefghijklmnop
|
||||
expect '<abcd>'
|
||||
recho ${z:0:4}
|
||||
|
||||
expect '<efg> <nop>'
|
||||
recho ${z:4:3} ${z:${#z}-3:3}
|
||||
|
||||
expect '<efg> <nop>'
|
||||
recho ${z:4:3} ${z: -3:3}
|
||||
|
||||
expect '<hijklmnop>'
|
||||
recho ${z:7:30}
|
||||
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${z:0:100}
|
||||
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${z:0:${#z}}
|
||||
|
||||
set 'ab cd' 'ef' 'gh ij' 'kl mn' 'op'
|
||||
expect '<ab cd> <ef>'
|
||||
recho "${@:1:2}"
|
||||
|
||||
expect '<gh ij> <kl mn>'
|
||||
recho "${@:3:2}"
|
||||
|
||||
expect '<gh ij> <kl mn> <op>'
|
||||
recho "${@:3:4}"
|
||||
|
||||
expect '<ab cd> <ef> <gh ij> <kl mn> <op>'
|
||||
recho "${@:1:$#}"
|
||||
|
||||
# code to ad-hoc parse arithmetic expressions in substring expansions was
|
||||
# broken until post-2.04
|
||||
base=/home/chet/foo//bar
|
||||
string1=$base/abcabcabc
|
||||
x=1 j=4
|
||||
|
||||
expect '</home/chet/foo//bar/abcabcabc>'
|
||||
recho ${string1:0}
|
||||
|
||||
expect '<home/chet/foo//bar/abcabcabc>'
|
||||
recho ${string1:1}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:(j?1:0):j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:j?1:0:j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:(j?(x?1:0):0):j}
|
||||
|
||||
expect '<home>'
|
||||
recho ${string1:j?(x?1:0):0:j}
|
||||
|
||||
unset base string1 x j
|
||||
|
||||
# indirect variable references
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${!9:-$z}
|
||||
|
||||
ef=4
|
||||
expect '<4>'
|
||||
recho ${!2}
|
||||
|
||||
expect '<op>'
|
||||
recho ${!#}
|
||||
|
||||
set a b c d e
|
||||
a=
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${a:-$z}
|
||||
expect '<abcdefghijklmnop>'
|
||||
recho ${!1:-$z}
|
||||
|
||||
expect nothing
|
||||
recho ${a-$z}
|
||||
expect nothing
|
||||
recho ${!1-$z}
|
||||
|
||||
set -u
|
||||
expect $0: ABX: unbound variable
|
||||
( recho ${ABX} )
|
||||
set +u
|
||||
|
||||
expect $0: '$6: cannot assign in this way'
|
||||
recho ${6="arg6"}
|
||||
|
||||
v=abcde
|
||||
|
||||
# sed-like variable substitution
|
||||
expect '<xxcde>'
|
||||
recho ${v/a[a-z]/xx}
|
||||
expect '<axxde>'
|
||||
recho ${v/a??/axx}
|
||||
expect '<abxyz>'
|
||||
recho ${v/c??/xyz}
|
||||
expect '<abbcde>'
|
||||
recho ${v/#a/ab}
|
||||
expect '<abcde>'
|
||||
recho ${v/#d/ab}
|
||||
expect '<abcabe>'
|
||||
recho ${v/d/ab}
|
||||
expect '<abcdlast>'
|
||||
recho ${v/%?/last}
|
||||
expect '<abcde>'
|
||||
recho ${v/%x/last}
|
||||
|
||||
av=(abcd efgh ijkl mnop qrst uvwx)
|
||||
|
||||
expect '<xxcd>'
|
||||
recho ${av/??/xx}
|
||||
expect '<abxx>'
|
||||
recho ${av/%??/xx}
|
||||
expect '<xxgh>'
|
||||
recho ${av[1]/??/xx}
|
||||
expect '<efgh>'
|
||||
recho ${av[1]/%ab/xx}
|
||||
expect '<xxfgh>'
|
||||
recho ${av[1]/#?/xx}
|
||||
expect '<zagh>'
|
||||
recho ${av[1]/??/za}
|
||||
expect '<zaza>'
|
||||
recho ${av[1]//??/za}
|
||||
expect '<zagh>'
|
||||
recho ${av[1]/#??/za}
|
||||
expect '<efza>'
|
||||
recho ${av[1]/%??/za}
|
||||
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/*/yyy}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/#*/yyy}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${av[@]/%*/yyy}
|
||||
expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>'
|
||||
recho ${av[@]/a*/yyy}
|
||||
expect '<abxx> <efxx> <ijxx> <mnxx> <qrxx> <uvxx>'
|
||||
recho ${av[@]/%??/xx}
|
||||
|
||||
set abcd efgh ijkl mnop qrst uvwx
|
||||
|
||||
expect '<xxcd>'
|
||||
recho ${1/??/xx}
|
||||
expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>'
|
||||
recho ${@/??/xx}
|
||||
expect '<xxcd> <xxgh> <xxkl> <xxop> <xxst> <xxwx>'
|
||||
recho ${@/%??/xx}
|
||||
expect '<zaza>'
|
||||
recho ${3//??/za}
|
||||
expect '<efza>'
|
||||
recho ${3/%??/za}
|
||||
expect '<zaza> <zaza> <zaza> <zaza> <zaza> <zaza>'
|
||||
recho ${@//??/za}
|
||||
expect '<zacd> <zagh> <zakl> <zaop> <zast> <zawx>'
|
||||
recho ${@/#??/za}
|
||||
expect '<yyy> <yyy> <yyy> <yyy> <yyy> <yyy>'
|
||||
recho ${@//*/yyy}
|
||||
expect '<yyy> <efgh> <ijkl> <mnop> <qrst> <uvwx>'
|
||||
recho ${@//a*/yyy}
|
||||
expect '<abcd> <efgh> <ijkl> <mnop> <qrst> <uvwyyy>'
|
||||
recho ${@/%x*/yyy}
|
||||
|
||||
expect a newline
|
||||
echo $abmcde
|
||||
|
||||
# sneaky way to replace a newline in a variable value with something else
|
||||
AVAR=$'This\nstring\nhas\nmultiple\nlines.'
|
||||
echo "${AVAR}"
|
||||
|
||||
eval BVAR=\"\${AVAR//$'\n'/-}\"
|
||||
echo "$BVAR"
|
||||
|
||||
unset AVAR BVAR
|
||||
|
||||
# run process substitution tests in a subshell so that syntax errors
|
||||
# caused by a shell not implementing process substitution (e.g., one
|
||||
# built on a NeXT) will not cause the whole test to exit prematurely
|
||||
${THIS_SH} ./new-exp1.sub
|
||||
|
||||
# run the tests of $(<filename) in a subshell to avoid cluttering up
|
||||
# this script
|
||||
${THIS_SH} ./new-exp2.sub
|
||||
|
||||
expect '<6>'
|
||||
recho ${#:-foo}
|
||||
expect $0: '${#:}: bad substitution'
|
||||
echo ${#:}
|
||||
|
||||
expect "<'>"
|
||||
recho "'"
|
||||
expect '<">'
|
||||
recho '"'
|
||||
expect '<"hello">'
|
||||
recho "\"hello\""
|
||||
|
||||
shift $#
|
||||
unset foo
|
||||
z=abcdef
|
||||
z1='abc def'
|
||||
|
||||
expect '<>'
|
||||
recho ${foo:-""}
|
||||
expect nothing
|
||||
recho ${foo:-"$@"}
|
||||
expect '<>'
|
||||
recho "${foo:-$@}"
|
||||
|
||||
# unset var
|
||||
expect '<>'
|
||||
recho ${foo:-"$zbcd"}
|
||||
expect nothing
|
||||
recho ${foo:-$zbcd}
|
||||
|
||||
# set var
|
||||
expect '<abcdef>'
|
||||
recho ${foo:-"$z"}
|
||||
expect '<abc def>'
|
||||
recho ${foo:-"$z1"}
|
||||
|
||||
expect '<abcdef>'
|
||||
recho ${foo:-$z}
|
||||
expect '<abc> <def>'
|
||||
recho ${foo:-$z1}
|
||||
|
||||
expect '<abcdef>'
|
||||
recho "${foo:-$z}"
|
||||
expect '<abc def>'
|
||||
recho "${foo:-$z1}"
|
||||
|
||||
expect '<abcdef>'
|
||||
recho "${foo:-"$z"}"
|
||||
# this disagrees with sh and ksh, but I think it is right according
|
||||
# to posix.2.
|
||||
expect '<abc def>'
|
||||
recho "${foo:-"$z1"}"
|
||||
|
||||
set ab cd ef gh
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho ${foo:-"$@"}
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho "${foo:-$@}"
|
||||
expect '<ab> <cd> <ef> <gh>'
|
||||
recho "${foo:-"$@"}"
|
||||
|
||||
shift $#
|
||||
expect nothing
|
||||
recho $xxx"$@"
|
||||
expect nothing
|
||||
recho ${foo:-$xxx"$@"}
|
||||
expect '<>'
|
||||
recho "${foo:-$xxx$@}"
|
||||
expect '<>'
|
||||
recho "${foo:-$xxx"$@"}"
|
||||
|
||||
expect nothing
|
||||
recho $xxx"$@"
|
||||
expect nothing
|
||||
recho "$xxx$@"
|
||||
expect nothing
|
||||
recho "$@"$xxx
|
||||
|
||||
expect '<>'
|
||||
recho $xxx""
|
||||
expect '<>'
|
||||
recho $xxx''
|
||||
expect '<>'
|
||||
recho ''$xxx
|
||||
expect '<>'
|
||||
recho ""$xxx
|
||||
|
||||
AB='abcdefghijklmnopqrstuvwxyz'
|
||||
|
||||
recho ${AB:7:15}
|
||||
recho ${AB:15:7}
|
||||
|
||||
recho ${AB:20}
|
||||
|
||||
recho ${AB:0}
|
||||
recho ${AB:0:20}
|
||||
|
||||
recho ${AB:10:7}
|
||||
recho ${AB:10:3+4}
|
||||
recho ${AB:20/2:3+4}
|
||||
|
||||
set 1 2 3 4 5 6
|
||||
recho \""${*:2:2}"\"
|
||||
|
||||
IFS=:
|
||||
recho \""${*:2:2}"\"
|
||||
|
||||
IFS=$' \t\n'
|
||||
|
||||
z=123456
|
||||
|
||||
recho \""${z:2:2}"\"
|
||||
recho \""${z:2}"\"
|
||||
recho \""${z:2:4}"\"
|
||||
recho \""${z:2:6}"\"
|
||||
|
||||
set $'\1' $'\2' $'\177'
|
||||
|
||||
recho $*
|
||||
recho $@
|
||||
|
||||
recho ${*}
|
||||
recho ${@}
|
||||
|
||||
xx=one/two/two
|
||||
recho ${xx%/*}
|
||||
recho ${xx/\/two}
|
||||
|
||||
yy=oneonetwo
|
||||
recho ${yy//one}
|
||||
recho ${yy/\/one}
|
||||
|
||||
xx=oneonetwo
|
||||
|
||||
recho ${xx/one}
|
||||
recho ${xx//one}
|
||||
recho ${xx/\/one}
|
||||
|
||||
# out-of-range substrings
|
||||
var=abc
|
||||
c=${var:3}
|
||||
expect nothing
|
||||
recho $c
|
||||
c=${var:4}
|
||||
expect nothing
|
||||
recho $c
|
||||
expect '<./new-exp.tests: -2: substring expression < 0>'
|
||||
c=${var:0:-2}
|
||||
|
||||
var=abcdefghi
|
||||
c=${var:3:12}
|
||||
recho $c
|
||||
c=${var:4:20}
|
||||
recho $c
|
||||
|
||||
# make sure null patterns work
|
||||
xxx=endocrine
|
||||
yyy=n
|
||||
unset zzz
|
||||
|
||||
recho ${xxx/$yyy/*}
|
||||
recho ${xxx//$yyy/*}
|
||||
|
||||
recho ${xxx/$zzz/*}
|
||||
recho ${xxx//$zzz/*}
|
||||
|
||||
recho ${xxx//%${zzz}/}
|
||||
recho ${xxx//%${zzz}}
|
||||
recho ${xxx//#${zzz}/}
|
||||
recho ${xxx//#${zzz}}
|
||||
|
||||
# another case that caused a core dump in bash-2.0
|
||||
XPATH=/usr/bin:/bin:/usr/local/bin:/usr/gnu/bin::/usr/bin/X11:/sbin:/usr/sbin
|
||||
|
||||
recho ${XPATH//:/ }
|
||||
|
||||
xx=(ar as at au av aw ax ay az)
|
||||
|
||||
recho ${xx[@]/a/}
|
||||
recho ${xx[@]//a/}
|
||||
|
||||
recho ${xx[*]/a/}
|
||||
recho ${xx[*]//a/}
|
||||
|
||||
recho ${xx[@]%?}
|
||||
recho ${xx[*]%?}
|
||||
|
||||
recho ${xx[@]#?}
|
||||
recho ${xx[*]#?}
|
||||
|
||||
set -- ar as at au av aw ax ay az
|
||||
|
||||
recho ${@/a/}
|
||||
recho ${@//a/}
|
||||
|
||||
recho ${*/a/}
|
||||
recho ${*//a/}
|
||||
|
||||
recho ${@%?}
|
||||
recho ${*%?}
|
||||
|
||||
recho ${@#?}
|
||||
recho ${*#?}
|
||||
|
||||
shift $#
|
||||
set -u
|
||||
( recho $9 ; echo after 1)
|
||||
( recho ${9} ; echo after 2)
|
||||
( recho $UNSET ; echo after 3)
|
||||
( recho ${UNSET} ; echo after 4)
|
||||
( recho "$UNSET" ; echo after 5)
|
||||
( recho "${UNSET}" ; echo after 6)
|
||||
( recho "${#UNSET}" ; echo after 7)
|
||||
set +u
|
||||
|
||||
RECEIVED="12345"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED="12345#"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED="#"
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
RECEIVED=""
|
||||
recho "${RECEIVED:$((${#RECEIVED}-1)):1}"
|
||||
|
||||
# tests of new prefix expansion ${!prefix*}
|
||||
${THIS_SH} ./new-exp3.sub
|
||||
|
||||
# bug with indirect expansion through bash-2.05b
|
||||
${THIS_SH} ./new-exp4.sub
|
||||
|
||||
# these caused errors and core dumps in versions before bash-2.04
|
||||
c=""
|
||||
echo ${c//${$(($#-1))}/x/}
|
||||
|
||||
set a b c d e f g
|
||||
recho "$@"
|
||||
|
||||
set -- ${@:1:$(($# - 2))}
|
||||
recho "$@"
|
||||
|
||||
set a b
|
||||
recho ${@:1:$(($# - 2))}
|
||||
|
||||
recho ${@:1:0}
|
||||
recho ${@:1:1}
|
||||
recho ${@:1:2}
|
||||
|
||||
recho "${*:1:0}"
|
||||
|
||||
# this is an error -- negative expression
|
||||
set a
|
||||
recho ${@:1:$(($# - 2))}
|
||||
|
||||
XPATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:.:/sbin:/usr/sbin
|
||||
set $( IFS=: ; echo $XPATH )
|
||||
|
||||
recho ${@##*/}
|
||||
recho ${@%%[!/]*}
|
||||
|
||||
recho ${@#/*}
|
||||
recho ${@%*/}
|
||||
|
||||
set /full/path/to/x16 /another/full/path
|
||||
|
||||
recho ${1%/*}
|
||||
recho ${1%%[!/]*}
|
||||
recho ${1#*/}
|
||||
recho ${1##*/}
|
||||
|
||||
${THIS_SH} ./new-exp5.sub
|
||||
|
||||
unset var
|
||||
var=blah
|
||||
|
||||
# these had better agree
|
||||
echo ${var[@]:3}
|
||||
echo ${var:3}
|
||||
echo ${var[@]//#/--}
|
||||
echo ${var//#/--}
|
||||
echo ${var[@]##?}
|
||||
echo ${var##?}
|
||||
|
||||
# this must be last!
|
||||
expect $0: 'ABXD: parameter unset'
|
||||
recho ${ABXD:?"parameter unset"}
|
||||
@@ -22,3 +22,4 @@ abcd:~chet
|
||||
ok 1
|
||||
ok 2
|
||||
ok 3
|
||||
~root
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
~chet
|
||||
/usr/xyz/foo
|
||||
~chet/foo
|
||||
~chet/foo
|
||||
~chet/bar
|
||||
~chet/bar
|
||||
~chet/bar
|
||||
:~chet/
|
||||
abcd~chet
|
||||
SHELL=~/bash
|
||||
/usr/xyz/bash
|
||||
abcd:~chet
|
||||
/usr/ucb:/bin:/usr/xyz/bin:/usr/xyz/tmp/bin:/usr/bin
|
||||
/usr
|
||||
/tmp
|
||||
/bin:/usr/bin:.:/usr/xyz/bin
|
||||
/bin:/usr/bin:.:~/bin
|
||||
/bin:/usr/bin:.:/usr/xyz/bin
|
||||
/bin:/usr/bin:.:/usr/xyz/bin
|
||||
/bin:/usr/bin:.:~/bin
|
||||
/bin:/usr/bin:.:~/bin
|
||||
ok 1
|
||||
ok 2
|
||||
ok 3
|
||||
@@ -64,3 +64,6 @@ case $unset in
|
||||
"") echo ok 3 ;;
|
||||
*) echo bad 3 ;;
|
||||
esac
|
||||
|
||||
USER=root # should exist just about everywhere
|
||||
echo ~$USER
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
# this is needed because posix mode restricts tilde expansion to assignment
|
||||
# statements preceding a command, instead of the default of expanding all
|
||||
# assignment statements on the line (e.g., after `export'). Without this,
|
||||
# the next-to-last test fails
|
||||
set +o posix
|
||||
|
||||
HOME=/usr/xyz
|
||||
SHELL=~/bash
|
||||
echo ~ch\et
|
||||
echo ~/"foo"
|
||||
echo "~chet"/"foo"
|
||||
echo \~chet/"foo"
|
||||
echo \~chet/bar
|
||||
echo ~\chet/bar
|
||||
echo ~chet""/bar
|
||||
echo ":~chet/"
|
||||
echo abcd~chet
|
||||
echo "SHELL=~/bash"
|
||||
echo $SHELL
|
||||
echo abcd:~chet
|
||||
path=/usr/ucb:/bin:~/bin:~/tmp/bin:/usr/bin
|
||||
echo $path
|
||||
|
||||
cd /usr
|
||||
cd /tmp
|
||||
echo ~-
|
||||
echo ~+
|
||||
|
||||
XPATH=/bin:/usr/bin:.
|
||||
|
||||
# yes tilde expansion
|
||||
PPATH=$XPATH:~/bin
|
||||
echo "$PPATH"
|
||||
|
||||
# no tilde expansion
|
||||
PPATH="$XPATH:~/bin"
|
||||
echo "$PPATH"
|
||||
|
||||
# yes tilde expansion
|
||||
export PPATH=$XPATH:~/bin
|
||||
echo "$PPATH"
|
||||
declare -x PPATH=$XPATH:~/bin
|
||||
echo "$PPATH"
|
||||
|
||||
# no tilde expansion
|
||||
export PPATH="$XPATH:~/bin"
|
||||
echo "$PPATH"
|
||||
declare -x PPATH="$XPATH:~/bin"
|
||||
echo "$PPATH"
|
||||
|
||||
# more tests of tilde expansion when executing case commands
|
||||
case ~ in
|
||||
$HOME) echo ok 1;;
|
||||
*) echo bad 1 ;;
|
||||
esac
|
||||
|
||||
case ~ in
|
||||
~) echo ok 2 ;;
|
||||
\~) echo bad 2a ;;
|
||||
*) echo bad 2b ;;
|
||||
esac
|
||||
|
||||
case $unset in
|
||||
"") echo ok 3 ;;
|
||||
*) echo bad 3 ;;
|
||||
esac
|
||||
@@ -119,6 +119,8 @@ initialize_traps ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
initialize_signames();
|
||||
|
||||
trap_list[EXIT_TRAP] = trap_list[DEBUG_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
|
||||
sigmodes[EXIT_TRAP] = sigmodes[DEBUG_TRAP] = sigmodes[ERROR_TRAP] = sigmodes[RETURN_TRAP] = SIG_INHERITED;
|
||||
original_signals[EXIT_TRAP] = IMPOSSIBLE_TRAP_HANDLER;
|
||||
|
||||
+9
-7
@@ -483,8 +483,10 @@ initialize_shell_variables (env, privmode)
|
||||
set_if_not ("HISTFILE", name);
|
||||
free (name);
|
||||
|
||||
#if 0
|
||||
set_if_not ("HISTSIZE", "500");
|
||||
sv_histsize ("HISTSIZE");
|
||||
#endif
|
||||
}
|
||||
#endif /* HISTORY */
|
||||
|
||||
@@ -4016,19 +4018,19 @@ sv_histsize (name)
|
||||
{
|
||||
if (legal_number (temp, &num))
|
||||
{
|
||||
hmax = num;
|
||||
if (name[4] == 'S')
|
||||
{
|
||||
hmax = num;
|
||||
stifle_history (hmax);
|
||||
num = where_history ();
|
||||
if (history_lines_this_session > num)
|
||||
history_lines_this_session = num;
|
||||
hmax = where_history ();
|
||||
if (history_lines_this_session > hmax)
|
||||
history_lines_this_session = hmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
history_truncate_file (get_string_value ("HISTFILE"), (int)num);
|
||||
if (num <= history_lines_in_file)
|
||||
history_lines_in_file = num;
|
||||
history_truncate_file (get_string_value ("HISTFILE"), hmax);
|
||||
if (hmax <= history_lines_in_file)
|
||||
history_lines_in_file = hmax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-7
@@ -860,9 +860,11 @@ sh_set_lines_and_columns (lines, cols)
|
||||
{
|
||||
char val[INT_STRLEN_BOUND(int) + 1], *v;
|
||||
|
||||
#if defined (READLINE)
|
||||
/* If we are currently assigning to LINES or COLUMNS, don't do anything. */
|
||||
if (winsize_assignment)
|
||||
return;
|
||||
#endif
|
||||
|
||||
v = inttostr (lines, val, sizeof (val));
|
||||
bind_variable ("LINES", v, 0);
|
||||
@@ -4014,19 +4016,19 @@ sv_histsize (name)
|
||||
{
|
||||
if (legal_number (temp, &num))
|
||||
{
|
||||
hmax = num;
|
||||
if (name[4] == 'S')
|
||||
{
|
||||
hmax = num;
|
||||
stifle_history (hmax);
|
||||
num = where_history ();
|
||||
if (history_lines_this_session > num)
|
||||
history_lines_this_session = num;
|
||||
hmax = where_history ();
|
||||
if (history_lines_this_session > hmax)
|
||||
history_lines_this_session = hmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
history_truncate_file (get_string_value ("HISTFILE"), (int)num);
|
||||
if (num <= history_lines_in_file)
|
||||
history_lines_in_file = num;
|
||||
history_truncate_file (get_string_value ("HISTFILE"), hmax);
|
||||
if (hmax <= history_lines_in_file)
|
||||
history_lines_in_file = hmax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user