summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COMPAT101
-rw-r--r--COMPAT~225
-rw-r--r--CWRU/CWRU.chlog158
-rw-r--r--CWRU/CWRU.chlog~158
-rw-r--r--MANIFEST3
-rw-r--r--MANIFEST~984
-rw-r--r--Makefile.in39
-rw-r--r--Makefile.in.save1439
-rw-r--r--Makefile.in~1455
-rw-r--r--aclocal.m44
-rw-r--r--aclocal.m4~3962
-rw-r--r--arrayfunc.c10
-rw-r--r--arrayfunc.c~819
-rw-r--r--autom4te.cache/output.010
-rw-r--r--autom4te.cache/traces.01693
-rw-r--r--bashhist.c3
-rw-r--r--bashhist.c~820
-rw-r--r--builtins/mkbuiltins.c14
-rw-r--r--builtins/mkbuiltins.c~1566
-rw-r--r--builtins/read.def16
-rw-r--r--builtins/read.def~22
-rw-r--r--builtins/ulimit.def8
-rw-r--r--builtins/ulimit.def~14
-rw-r--r--command.h41
-rw-r--r--command.h~345
-rwxr-xr-xconfigure10
-rw-r--r--configure.in9
-rw-r--r--configure.in~1112
-rw-r--r--dd~152
-rw-r--r--doc/FAQ31
-rw-r--r--doc/FAQ~1803
-rw-r--r--doc/bash.131
-rw-r--r--doc/bash.1~22
-rw-r--r--doc/bashref.texi24
-rw-r--r--doc/bashref.texi~27
-rw-r--r--doc/rose94.pdfbin150441 -> 228533 bytes
-rw-r--r--doc/version.texi4
-rw-r--r--doc/version.texi~6
-rw-r--r--execute_cmd.c6
-rw-r--r--execute_cmd.c~10
-rw-r--r--expr.c73
-rw-r--r--expr.c~1348
-rw-r--r--lib/readline/bind.c15
-rw-r--r--lib/readline/bind.c~2286
-rw-r--r--lib/readline/callback.c1
-rw-r--r--lib/readline/callback.c~260
-rw-r--r--lib/readline/display.c8
-rw-r--r--lib/readline/display.c~10
-rw-r--r--lib/readline/isearch.c4
-rw-r--r--lib/readline/isearch.c~666
-rw-r--r--lib/readline/misc.c2
-rw-r--r--lib/readline/misc.c~601
-rw-r--r--lib/readline/rltty.c1
-rw-r--r--lib/readline/rltty.c~1035
-rw-r--r--lib/readline/search.c1
-rw-r--r--lib/readline/search.c~572
-rw-r--r--lib/readline/signals.c42
-rw-r--r--lib/readline/signals.c~470
-rw-r--r--lib/readline/text.c2
-rw-r--r--lib/readline/text.c~1637
-rw-r--r--lib/readline/vi_mode.c2
-rw-r--r--lib/readline/vi_mode.c~1717
-rw-r--r--parse.y1
-rw-r--r--parse.y~6
-rw-r--r--shell.c2
-rw-r--r--shell.c~1793
-rw-r--r--subst.c88
-rw-r--r--subst.c.save18064
-rw-r--r--subst.c~8091
-rw-r--r--subst.h3
-rw-r--r--subst.h~260
-rw-r--r--support/Makefile.in6
-rw-r--r--support/Makefile.in~87
-rw-r--r--support/mksignames.c370
-rw-r--r--support/mksignames.c.save446
-rw-r--r--support/mksignames.c~110
-rw-r--r--support/signames.c393
-rw-r--r--support/signames.c~393
-rwxr-xr-xtests/RUN-ONE-TEST2
-rwxr-xr-xtests/RUN-ONE-TEST~9
-rw-r--r--tests/new-exp.right2
-rw-r--r--tests/new-exp.tests14
-rw-r--r--tests/new-exp.tests.save1558
-rw-r--r--tests/new-exp.tests~558
-rw-r--r--tests/tilde.right1
-rw-r--r--tests/tilde.right~24
-rw-r--r--tests/tilde.tests3
-rw-r--r--tests/tilde.tests~66
-rw-r--r--trap.c2
-rw-r--r--trap.c~1002
-rw-r--r--variables.c16
-rw-r--r--variables.c~16
92 files changed, 48883 insertions, 1412 deletions
diff --git a/COMPAT b/COMPAT
index 6d306633..5c93cd80 100644
--- a/COMPAT
+++ b/COMPAT
@@ -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.
+
diff --git a/COMPAT~ b/COMPAT~
new file mode 100644
index 00000000..4acbcdc0
--- /dev/null
+++ b/COMPAT~
@@ -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.
diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog
index e7b3d72f..8676d65a 100644
--- a/CWRU/CWRU.chlog
+++ b/CWRU/CWRU.chlog
@@ -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
diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~
index 9bb1963d..d0668890 100644
--- a/CWRU/CWRU.chlog~
+++ b/CWRU/CWRU.chlog~
@@ -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
diff --git a/MANIFEST b/MANIFEST
index 3af6d76c..ecf28852 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -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
diff --git a/MANIFEST~ b/MANIFEST~
new file mode 100644
index 00000000..ecf28852
--- /dev/null
+++ b/MANIFEST~
@@ -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
diff --git a/Makefile.in b/Makefile.in
index 57277b6d..c9f9aa21 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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
diff --git a/Makefile.in.save b/Makefile.in.save
new file mode 100644
index 00000000..7054cb40
--- /dev/null
+++ b/Makefile.in.save
@@ -0,0 +1,1439 @@
+# Makefile for bash-3.1, version 2.158
+#
+# Copyright (C) 1996-2005 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.
+
+# Make sure the first target in the makefile is the right one
+all: .made
+
+PACKAGE = @PACKAGE_NAME@
+VERSION = @PACKAGE_VERSION@
+
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+
+# Include some boilerplate Gnu makefile definitions.
+prefix = @prefix@
+
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+infodir = @infodir@
+includedir = @includedir@
+datadir = @datadir@
+localedir = $(datadir)/locale
+
+mandir = @mandir@
+manpfx = man
+
+man1ext = .1
+man1dir = $(mandir)/$(manpfx)1
+man3ext = .3
+man3dir = $(mandir)/$(manpfx)3
+
+htmldir = @htmldir@
+
+# Support an alternate destination root directory for package building
+DESTDIR =
+
+topdir = @top_srcdir@
+BUILD_DIR = @BUILD_DIR@
+top_builddir = @BUILD_DIR@
+srcdir = @srcdir@
+VPATH = .:@srcdir@
+
+@SET_MAKE@
+CC = @CC@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+YACC = @YACC@
+SHELL = @MAKE_SHELL@
+CP = cp
+RM = rm -f
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RANLIB = @RANLIB@
+SIZE = @SIZE@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALLMODE= -m 0755
+INSTALLMODE2 = -m 0555
+
+TESTSCRIPT = @TESTSCRIPT@
+
+#If you have purify, and want to use it, uncomment this definition or
+# run the make as `make PURIFY=purify'
+# or run configure with the --with-purify argument.
+PURIFY = @PURIFY@
+
+# Here is a rule for making .o files from .c files that does not
+# force the type of the machine (like -M_MACHINE) into the flags.
+.c.o:
+ $(RM) $@
+ $(CC) $(CCFLAGS) -c $<
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+
+# The name of this program and some version information.
+VERSPROG = bashversion$(EXEEXT)
+VERSOBJ = bashversion.$(OBJEXT)
+
+Program = bash$(EXEEXT)
+Version = @BASHVERS@
+PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p`
+RELSTATUS = @RELSTATUS@
+
+Machine = @host_cpu@
+OS = @host_os@
+VENDOR = @host_vendor@
+MACHTYPE = @host@
+
+# comment out for release
+DEBUG = @DEBUG@
+MALLOC_DEBUG = @MALLOC_DEBUG@
+
+THIS_SH = $(BUILD_DIR)/$(Program)
+
+# PROFILE_FLAGS is either -pg, to generate profiling info for use
+# with gprof, or nothing (the default).
+PROFILE_FLAGS= @PROFILE_FLAGS@
+
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ @CROSS_COMPILE@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG} ${MALLOC_DEBUG}
+DEFS = @DEFS@
+LOCAL_DEFS = @LOCAL_DEFS@
+
+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@
+
+SYSTEM_FLAGS = -DPROGRAM='"$(Program)"' -DCONF_HOSTTYPE='"$(Machine)"' -DCONF_OSTYPE='"$(OS)"' -DCONF_MACHTYPE='"$(MACHTYPE)"' -DCONF_VENDOR='"$(VENDOR)"' $(LOCALE_DEFS)
+
+BASE_CCFLAGS = $(PROFILE_FLAGS) $(SYSTEM_FLAGS) $(LOCAL_DEFS) \
+ $(DEFS) $(LOCAL_CFLAGS) $(INCLUDES)
+
+CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
+
+CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
+
+LDFLAGS = @LDFLAGS@ $(STATIC_LD) $(LOCAL_LDFLAGS) $(PROFILE_FLAGS) $(CFLAGS)
+LDFLAGS_FOR_BUILD = $(LDFLAGS)
+
+INCLUDES = -I. @RL_INCLUDE@ -I$(srcdir) -I$(BASHINCDIR) -I$(LIBSRC) $(INTL_INC)
+
+GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
+ -Wcast-align -Wstrict-prototypes -Wconversion \
+ -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
+
+GCC_LINT_CFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(GCC_LINT_FLAGS)
+
+#
+# Support libraries
+#
+
+dot = .
+
+LIBSUBDIR = lib
+LIBSRC = $(srcdir)/$(LIBSUBDIR)
+
+LIBBUILD = ${BUILD_DIR}/${LIBSUBDIR}
+
+SUBDIR_INCLUDES = -I. @RL_INCLUDE@ -I$(topdir) -I$(topdir)/$(LIBSUBDIR)
+
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+
+# the bash library
+# the library is a mix of functions that the C library does not provide on
+# some platforms and general shell utility functions
+SH_LIBSRC = $(LIBSRC)/sh
+SH_LIBDIR = $(dot)/${LIBSUBDIR}/sh
+SH_ABSSRC = ${topdir}/${SH_LIBSRC}
+
+SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
+ ${SH_LIBSRC}/getenv.c ${SH_LIBSRC}/oslib.c \
+ ${SH_LIBSRC}/setlinebuf.c \
+ ${SH_LIBSRC}/strcasecmp.c ${SH_LIBSRC}/strerror.c \
+ ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtol.c \
+ ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/vprint.c \
+ ${SH_LIBSRC}/itos.c ${SH_LIBSRC}/rename.c \
+ ${SH_LIBSRC}/zread.c ${SH_LIBSRC}/zwrite.c \
+ ${SH_LIBSRC}/shtty.c ${SH_LIBSRC}/inet_aton.c \
+ ${SH_LIBSRC}/netopen.c ${SH_LIBSRC}/strpbrk.c \
+ ${SH_LIBSRC}/timeval.c ${SH_LIBSRC}/clock.c \
+ ${SH_LIBSRC}/makepath.c ${SH_LIBSRC}/pathcanon.c \
+ ${SH_LIBSRC}/pathphys.c ${SH_LIBSRC}/stringlist.c \
+ ${SH_LIBSRC}/stringvec.c ${SH_LIBSRC}/tmpfile.c \
+ ${SH_LIBSRC}/spell.c ${SH_LIBSRC}/strtrans.c \
+ ${SH_LIBSRC}/strindex.c ${SH_LIBSRC}/shquote.c \
+ ${SH_LIBSRC}/snprintf.c ${SH_LIBSRC}/mailstat.c \
+ ${SH_LIBSRC}/fmtulong.c ${SH_LIBSRC}/fmtullong.c \
+ ${SH_LIBSRC}/strtoll.c ${SH_LIBSRC}/strtoull.c \
+ ${SH_LIBSRC}/strtoimax.c ${SH_LIBSRC}/strtoumax.c \
+ ${SH_LIBSRC}/fmtumax.c ${SH_LIBSRC}/netconn.c \
+ ${SH_LIBSRC}/mktime.c ${SH_LIBSRC}/strftime.c \
+ ${SH_LIBSRC}/memset.c ${SH_LIBSRC}/xstrchr.c \
+ ${SH_LIBSRC}/zcatfd.c ${SH_LIBSRC}/shmatch.c \
+ ${SH_LIBSRC}/strnlen.c ${SH_LIBSRC}/winsize.c
+
+SHLIB_LIB = -lsh
+SHLIB_LIBNAME = libsh.a
+SHLIB_LIBRARY = ${SH_LIBDIR}/${SHLIB_LIBNAME}
+SHLIB_LDFLAGS = -L${SH_LIBDIR}
+SHLIB_DEP = ${SHLIB_LIBRARY}
+
+# we assume for now that readline source is being shipped with bash
+RL_LIBSRC = $(LIBSRC)/readline
+RL_LIBDOC = $(RL_LIBSRC)/doc
+RL_LIBDIR = @RL_LIBDIR@
+RL_ABSSRC = ${topdir}/$(RL_LIBDIR)
+
+RL_INCLUDEDIR = @RL_INCLUDEDIR@
+
+READLINE_LIB = @READLINE_LIB@
+READLINE_LIBRARY = $(RL_LIBDIR)/libreadline.a
+READLINE_LDFLAGS = -L${RL_LIBDIR}
+READLINE_DEP = @READLINE_DEP@
+
+# The source, object and documentation of the GNU Readline library.
+READLINE_SOURCE = $(RL_LIBSRC)/rldefs.h $(RL_LIBSRC)/rlconf.h \
+ $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/tcap.h \
+ $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/keymaps.h \
+ $(RL_LIBSRC)/history.h $(RL_LIBSRC)/histlib.h \
+ $(RL_LIBSRC)/posixstat.h $(RL_LIBSRC)/tilde.h \
+ $(RL_LIBSRC)/rlstdc.h ${RL_LIBSRC}/xmalloc.h \
+ $(RL_LIBSRC)/rlshell.h ${RL_LIBSRC}/rlprivate.h \
+ $(RL_LIBSRC)/funmap.c $(RL_LIBSRC)/emacs_keymap.c \
+ $(RL_LIBSRC)/search.c $(RL_LIBSRC)/vi_keymap.c \
+ $(RL_LIBSRC)/keymaps.c $(RL_LIBSRC)/parens.c \
+ $(RL_LIBSRC)/vi_mode.c $(RL_LIBSRC)/callback.c \
+ $(RL_LIBSRC)/readline.c $(RL_LIBSRC)/tilde.c \
+ $(RL_LIBSRC)/rltty.c $(RL_LIBSRC)/complete.c \
+ $(RL_LIBSRC)/bind.c $(RL_LIBSRC)/isearch.c \
+ $(RL_LIBSRC)/display.c $(RL_LIBSRC)/signals.c \
+ $(RL_LIBSRC)/util.c $(RL_LIBSRC)/kill.c $(RL_LIBSRC)/text.c \
+ $(RL_LIBSRC)/undo.c $(RL_LIBSRC)/macro.c \
+ $(RL_LIBSRC)/terminal.c $(RL_LIBSRC)/nls.c \
+ $(RL_LIBSRC)/input.c $(RL_LIBSRC)/xmalloc.c \
+ $(RL_LIBSRC)/shell.c $(RL_LIBSRC)/savestring.c \
+ $(RL_LIBSRC)/misc.c $(RL_LIBSRC)/mbutil.c $(RL_LIBSRC)/compat.c \
+ $(RL_LIBSRC)/histexpand.c $(RL_LIBSRC)/history.c \
+ $(RL_LIBSRC)/histsearch.c $(RL_LIBSRC)/histfile.c
+
+READLINE_OBJ = $(RL_LIBDIR)/readline.o $(RL_LIBDIR)/funmap.o \
+ $(RL_LIBDIR)/parens.o $(RL_LIBDIR)/search.o \
+ $(RL_LIBDIR)/keymaps.o $(RL_LIBDIR)/xmalloc.o \
+ $(RL_LIBDIR)/rltty.o $(RL_LIBDIR)/complete.o \
+ $(RL_LIBDIR)/bind.o $(RL_LIBDIR)/isearch.o \
+ $(RL_LIBDIR)/display.o $(RL_LIBDIR)/signals.o \
+ $(RL_LIBDIR)/tilde.o $(RL_LIBDIR)/util.o \
+ $(RL_LIBDIR)/kill.o $(RL_LIBDIR)/undo.o $(RL_LIBDIR)/nls.o \
+ $(RL_LIBDIR)/macro.o $(RL_LIBDIR)/input.o \
+ $(RL_LIBDIR)/terminal.o $(RL_LIBDIR)/callback.o \
+ $(RL_LIBDIR)/shell.o $(RL_LIBDIR)/savestring.o \
+ $(RL_LIBDIR)/mbutil.o $(RL_LIBDIR)/compat.o \
+ $(RL_LIBDIR)/history.o $(RL_LIBDIR)/histexpand.o \
+ $(RL_LIBDIR)/histsearch.o $(RL_LIBDIR)/histfile.o
+
+HIST_LIBSRC = $(LIBSRC)/readline
+HIST_LIBDIR = @HIST_LIBDIR@
+HIST_ABSSRC = ${topdir}/$(HIST_LIBDIR)
+
+HISTORY_LIB = @HISTORY_LIB@
+HISTORY_LIBRARY = $(HIST_LIBDIR)/libhistory.a
+HISTORY_LDFLAGS = -L$(HIST_LIBDIR)
+HISTORY_DEP = @HISTORY_DEP@
+
+# The source, object and documentation of the history library.
+HISTORY_SOURCE = $(HIST_LIBSRC)/history.c $(HIST_LIBSRC)/histexpand.c \
+ $(HIST_LIBSRC)/histsearch.c $(HIST_LIBSRC)/histfile.c \
+ $(HIST_LIBSRC)/shell.c \
+ $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/histlib.h
+HISTORY_OBJ = $(HIST_LIBDIR)/history.o $(HIST_LIBDIR)/histexpand.o \
+ $(HIST_LIBDIR)/histsearch.o $(HIST_LIBDIR)/histfile.o \
+ $(HIST_LIBDIR)/shell.o
+
+# You only need termcap (or curses) if you are linking with GNU Readline.
+TERM_LIBSRC = $(LIBSRC)/termcap
+TERM_LIBDIR = $(dot)/$(LIBSUBDIR)/termcap
+TERM_ABSSRC = ${topdir}/$(TERM_LIBDIR)
+
+TERMCAP_LIB = @TERMCAP_LIB@
+TERMCAP_LIBRARY = $(TERM_LIBDIR)/libtermcap.a
+TERMCAP_LDFLAGS = -L$(TERM_LIBDIR)
+TERMCAP_DEP = @TERMCAP_DEP@
+
+TERMCAP_SOURCE = $(TERM_LIBSRC)/termcap.c $(TERM_LIBSRC)/tparam.c
+TERMCAP_OBJ = $(TERM_LIBDIR)/termcap.o $(TERM_LIBDIR)/tparam.o
+
+GLOB_LIBSRC = $(LIBSRC)/glob
+GLOB_LIBDIR = $(dot)/$(LIBSUBDIR)/glob
+GLOB_ABSSRC = ${topdir}/$(GLOB_LIBDIR)
+
+GLOB_LIB = -lglob
+GLOB_LIBRARY = $(GLOB_LIBDIR)/libglob.a
+GLOB_LDFLAGS = -L$(GLOB_LIBDIR)
+GLOB_DEP = $(GLOB_LIBRARY)
+
+GLOB_SOURCE = $(GLOB_LIBSRC)/glob.c $(GLOB_LIBSRC)/strmatch.c \
+ $(GLOB_LIBSRC)/smatch.c $(GLOB_LIBSRC)/xmbsrtowcs.c \
+ $(GLOB_LIBSRC)/glob_loop.c $(GLOB_LIBSRC)/sm_loop.c \
+ $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+GLOB_OBJ = $(GLOB_LIBDIR)/glob.o $(GLOB_LIBDIR)/strmatch.o \
+ $(GLOB_LIBDIR)/smatch.o $(GLOB_LIBDIR)/xmbsrtowcs.o
+
+# The source, object and documentation for the GNU Tilde library.
+TILDE_LIBSRC = $(LIBSRC)/tilde
+TILDE_LIBDIR = $(dot)/$(LIBSUBDIR)/tilde
+TILDE_ABSSRC = ${topdir}/$(TILDE_LIBDIR)
+
+TILDE_LIB = @TILDE_LIB@
+TILDE_LIBRARY = $(TILDE_LIBDIR)/libtilde.a
+TILDE_LDFLAGS = -L$(TILDE_LIBDIR)
+TILDE_DEP = $(TILDE_LIBRARY)
+
+TILDE_SOURCE = $(TILDE_LIBSRC)/tilde.c $(TILDE_LIBSRC)/tilde.h
+TILDE_OBJ = $(TILDE_LIBDIR)/tilde.o
+
+# libintl
+INTL_LIBSRC = $(LIBSRC)/intl
+INTL_LIBDIR = $(dot)/$(LIBSUBDIR)/intl
+INTL_ABSSRC = ${topdir}/$(INTL_LIB)
+INTL_BUILDDIR = ${LIBBUILD}/intl
+
+INTL_LIB = @LIBINTL@
+INTL_LIBRARY = $(INTL_LIBDIR)/libintl.a
+INTL_DEP = @INTL_DEP@
+INTL_INC = @INTL_INC@
+
+LIBINTL_H = @LIBINTL_H@
+
+# tests
+LIBINTL = @LIBINTL@
+LTLIBINTL = @LTLIBINTL@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+
+# Our malloc.
+MALLOC_TARGET = @MALLOC_TARGET@
+
+# set to alloca.o if we are using the C alloca in lib/malloc
+ALLOCA = @ALLOCA@
+
+ALLOC_LIBSRC = $(LIBSRC)/malloc
+ALLOC_LIBDIR = $(dot)/$(LIBSUBDIR)/malloc
+ALLOC_ABSSRC = ${topdir}/$(ALLOC_LIBDIR)
+
+MALLOC_SRC = @MALLOC_SRC@
+MALLOC_OTHERSRC = ${ALLOC_LIBSRC}/trace.c ${ALLOC_LIBSRC}/stats.c \
+ ${ALLOC_LIBSRC}/table.c ${ALLOC_LIBSRC}/watch.c
+MALLOC_SOURCE = ${ALLOC_LIBSRC}/${MALLOC_SRC} ${MALLOC_OTHERSRC}
+MALLOC_CFLAGS = -DRCHECK -Dbotch=programming_error ${MALLOC_DEBUG}
+
+MALLOC_LIB = @MALLOC_LIB@
+MALLOC_LIBRARY = @MALLOC_LIBRARY@
+MALLOC_LDFLAGS = @MALLOC_LDFLAGS@
+MALLOC_DEP = @MALLOC_DEP@
+
+ALLOC_HEADERS = $(ALLOC_LIBSRC)/getpagesize.h $(ALLOC_LIBSRC)/shmalloc.h \
+ $(ALLOC_LIBSRC)/imalloc.h $(ALLOC_LIBSRC)/mstats.h \
+ $(ALLOC_LIBSRC)/table.h $(ALLOC_LIBSRC)/watch.h
+
+$(MALLOC_LIBRARY): ${MALLOC_SOURCE} ${ALLOC_HEADERS} config.h
+ @(cd $(ALLOC_LIBDIR) && \
+ $(MAKE) $(MFLAGS) \
+ MALLOC_CFLAGS="$(MALLOC_CFLAGS)" ${MALLOC_TARGET} ) || exit 1
+
+BASHINCDIR = ${srcdir}/include
+BASHINCFILES = $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \
+ $(BASHINCDIR)/filecntl.h $(BASHINCDIR)/posixdir.h \
+ $(BASHINCDIR)/memalloc.h $(BASHINCDIR)/stdc.h \
+ $(BASHINCDIR)/posixjmp.h $(BASHINCDIR)/posixwait.h \
+ $(BASHINCDIR)/posixtime.h $(BASHINCDIR)/systimes.h \
+ $(BASHINCDIR)/unionwait.h $(BASHINCDIR)/maxpath.h \
+ $(BASHINCDIR)/shtty.h $(BASHINCDIR)/typemax.h \
+ $(BASHINCDIR)/ocache.h
+
+LIBRARIES = $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) $(GLOB_LIB) \
+ $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LOCAL_LIBS)
+
+LIBDEP = $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_DEP) $(GLOB_DEP) \
+ $(TILDE_DEP) $(MALLOC_DEP)
+
+LIBRARY_LDFLAGS = $(READLINE_LDFLAGS) $(HISTORY_LDFLAGS) $(GLOB_LDFLAGS) \
+ $(TILDE_LDFLAGS) $(MALLOC_LDFLAGS) $(SHLIB_LDFLAGS)
+
+#
+# The shell itself
+#
+
+# The main source code for the Bourne Again SHell.
+CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \
+ dispose_cmd.c execute_cmd.c variables.c $(GLOBC) version.c \
+ expr.c copy_cmd.c flags.c subst.c hashcmd.c hashlib.c mailcheck.c \
+ test.c trap.c alias.c jobs.c nojobs.c $(ALLOC_FILES) braces.c \
+ input.c bashhist.c array.c arrayfunc.c sig.c pathexp.c \
+ unwind_prot.c siglist.c bashline.c bracecomp.c error.c \
+ list.c stringlib.c locale.c findcmd.c redir.c \
+ pcomplete.c pcomplib.c syntax.c xmalloc.c
+
+HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \
+ general.h variables.h config.h $(ALLOC_HEADERS) alias.h \
+ quit.h unwind_prot.h syntax.h ${GRAM_H} \
+ command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \
+ subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \
+ array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \
+ execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h \
+ $(BASHINCFILES)
+
+SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS)
+
+# header files chosen based on running of configure
+SIGNAMES_H = @SIGNAMES_H@
+
+# object files chosen based on running of configure
+JOBS_O = @JOBS_O@
+SIGLIST_O = @SIGLIST_O@
+
+# Matching object files.
+OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
+ dispose_cmd.o execute_cmd.o variables.o copy_cmd.o error.o \
+ expr.o flags.o $(JOBS_O) subst.o hashcmd.o hashlib.o mailcheck.o \
+ 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
+
+# Where the source code of the shell builtins resides.
+BUILTIN_SRCDIR=$(srcdir)/builtins
+DEFSRC=$(BUILTIN_SRCDIR)
+BUILTIN_ABSSRC=${topdir}/builtins
+DEFDIR = $(dot)/builtins
+DEBUGGER_DIR = $(dot)/debugger
+
+BUILTIN_DEFS = $(DEFSRC)/alias.def $(DEFSRC)/bind.def $(DEFSRC)/break.def \
+ $(DEFSRC)/builtin.def $(DEFSRC)/cd.def $(DEFSRC)/colon.def \
+ $(DEFSRC)/command.def ${DEFSRC}/complete.def \
+ $(DEFSRC)/caller.def $(DEFSRC)/declare.def \
+ $(DEFSRC)/echo.def $(DEFSRC)/enable.def $(DEFSRC)/eval.def \
+ $(DEFSRC)/exec.def $(DEFSRC)/exit.def $(DEFSRC)/fc.def \
+ $(DEFSRC)/fg_bg.def $(DEFSRC)/hash.def $(DEFSRC)/help.def \
+ $(DEFSRC)/history.def $(DEFSRC)/jobs.def $(DEFSRC)/kill.def \
+ $(DEFSRC)/let.def $(DEFSRC)/read.def $(DEFSRC)/return.def \
+ $(DEFSRC)/set.def $(DEFSRC)/setattr.def $(DEFSRC)/shift.def \
+ $(DEFSRC)/source.def $(DEFSRC)/suspend.def $(DEFSRC)/test.def \
+ $(DEFSRC)/times.def $(DEFSRC)/trap.def $(DEFSRC)/type.def \
+ $(DEFSRC)/ulimit.def $(DEFSRC)/umask.def $(DEFSRC)/wait.def \
+ $(DEFSRC)/getopts.def $(DEFSRC)/reserved.def \
+ $(DEFSRC)/pushd.def $(DEFSRC)/shopt.def $(DEFSRC)/printf.def
+BUILTIN_C_SRC = $(DEFSRC)/mkbuiltins.c $(DEFSRC)/common.c \
+ $(DEFSRC)/evalstring.c $(DEFSRC)/evalfile.c \
+ $(DEFSRC)/bashgetopt.c $(GETOPT_SOURCE)
+BUILTIN_C_OBJ = $(DEFDIR)/common.o $(DEFDIR)/evalstring.o \
+ $(DEFDIR)/evalfile.o $(DEFDIR)/bashgetopt.o
+BUILTIN_OBJS = $(DEFDIR)/alias.o $(DEFDIR)/bind.o $(DEFDIR)/break.o \
+ $(DEFDIR)/builtin.o $(DEFDIR)/cd.o $(DEFDIR)/colon.o \
+ $(DEFDIR)/command.o $(DEFDIR)/caller.o $(DEFDIR)/declare.o \
+ $(DEFDIR)/echo.o $(DEFDIR)/enable.o $(DEFDIR)/eval.o \
+ $(DEFDIR)/exec.o $(DEFDIR)/exit.o $(DEFDIR)/fc.o \
+ $(DEFDIR)/fg_bg.o $(DEFDIR)/hash.o $(DEFDIR)/help.o \
+ $(DEFDIR)/history.o $(DEFDIR)/jobs.o $(DEFDIR)/kill.o \
+ $(DEFDIR)/let.o $(DEFDIR)/pushd.o $(DEFDIR)/read.o \
+ $(DEFDIR)/return.o $(DEFDIR)/shopt.o $(DEFDIR)/printf.o \
+ $(DEFDIR)/set.o $(DEFDIR)/setattr.o $(DEFDIR)/shift.o \
+ $(DEFDIR)/source.o $(DEFDIR)/suspend.o $(DEFDIR)/test.o \
+ $(DEFDIR)/times.o $(DEFDIR)/trap.o $(DEFDIR)/type.o \
+ $(DEFDIR)/ulimit.o $(DEFDIR)/umask.o $(DEFDIR)/wait.o \
+ $(DEFDIR)/getopts.o $(BUILTIN_C_OBJ)
+GETOPT_SOURCE = $(DEFSRC)/getopt.c $(DEFSRC)/getopt.h
+PSIZE_SOURCE = $(DEFSRC)/psize.sh $(DEFSRC)/psize.c
+
+BUILTINS_LIBRARY = $(DEFDIR)/libbuiltins.a
+BUILTINS_LIB = -lbuiltins
+BUILTINS_LDFLAGS = -L$(DEFDIR)
+BUILTINS_DEP = $(BUILTINS_LIBRARY)
+
+# Documentation for the shell.
+DOCSRC = $(srcdir)/doc
+DOCDIR = $(dot)/doc
+
+# Translations and other i18n support files
+PO_SRC = $(srcdir)/po/
+PO_DIR = $(dot)/po/
+
+SIGNAMES_SUPPORT = $(SUPPORT_SRC)mksignames.c
+
+SUPPORT_SRC = $(srcdir)/support/
+SDIR = $(dot)/support/
+
+TESTS_SUPPORT = recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT)
+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
+CREATED_CONFIGURE = config.h config.cache config.status config.log \
+ stamp-h po/POTFILES
+CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \
+ lib/readline/Makefile lib/glob/Makefile \
+ lib/sh/Makefile lib/tilde/Makefile lib/malloc/Makefile \
+ lib/termcap/Makefile examples/loadables/Makefile \
+ examples/loadables/perl/Makefile support/Makefile \
+ lib/intl/Makefile po/Makefile po/Makefile.in
+
+# Keep GNU Make from exporting the entire environment for small machines.
+.NOEXPORT:
+
+.made: $(Program) bashbug
+ @echo "$(Program) last made for a $(Machine) running $(OS)" >.made
+
+$(Program): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP)
+ $(RM) $@
+ $(PURIFY) $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) -o $(Program) $(OBJECTS) $(LIBS)
+ ls -l $(Program)
+ -$(SIZE) $(Program)
+
+.build: $(SOURCES) config.h Makefile version.h $(VERSPROG)
+ @echo
+ @echo " ***********************************************************"
+ @echo " * *"
+ @echo " * `$(BUILD_DIR)/$(VERSPROG) -l`"
+ @echo " * *"
+ @echo " ***********************************************************"
+ @echo
+
+bashbug: $(SUPPORT_SRC)bashbug.sh config.h Makefile $(VERSPROG)
+ @sed -e "s%!MACHINE!%$(Machine)%" -e "s%!OS!%$(OS)%" \
+ -e "s%!CFLAGS!%$(CCFLAGS)%" -e "s%!CC!%$(CC)%" \
+ -e "s%!RELEASE!%$(Version)%" -e "s%!PATCHLEVEL!%$(PatchLevel)%" \
+ -e "s%!MACHTYPE!%$(MACHTYPE)%" -e "s%!RELSTATUS!%$(RELSTATUS)%" \
+ $(SUPPORT_SRC)bashbug.sh > $@
+ @chmod a+rx bashbug
+
+strip: $(Program) .made
+ strip $(Program)
+ ls -l $(Program)
+ -$(SIZE) $(Program)
+
+lint:
+ ${MAKE} ${MFLAGS} CFLAGS='${GCC_LINT_FLAGS}' .made
+
+version.h: $(SOURCES) config.h Makefile
+ $(SHELL) $(SUPPORT_SRC)mkversion.sh -b -S ${topdir} -s $(RELSTATUS) -d $(Version) -o newversion.h \
+ && 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 ${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
+
+# old rules
+GRAM_H = parser-built
+y.tab.o: y.tab.c ${GRAM_H} command.h ${BASHINCDIR}/stdc.h input.h
+${GRAM_H}: y.tab.h
+ @-if test -f y.tab.h ; then \
+ cmp -s $@ y.tab.h 2>/dev/null || cp -p y.tab.h $@; \
+ fi
+y.tab.c y.tab.h: parse.y
+# -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
+ $(YACC) -d $(srcdir)/parse.y
+ touch parser-built
+# -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; else cp -p y.tab.h ${GRAM_H}; fi
+
+# experimental new rules - work with GNU make but not BSD (or OSF) make
+#y.tab.o: y.tab.c y.tab.h
+#y.tab.c y.tab.h: parse.y command.h ${BASHINCDIR}/stdc.h input.h
+# -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
+# $(YACC) -d $(srcdir)/parse.y
+# -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; fi
+
+$(READLINE_LIBRARY): config.h $(READLINE_SOURCE)
+ @echo making $@ in ${RL_LIBDIR}
+ @( { test "${RL_LIBDIR}" = "${libdir}" && exit 0; } || \
+ cd ${RL_LIBDIR} && $(MAKE) $(MFLAGS) libreadline.a) || exit 1
+
+$(HISTORY_LIBRARY): config.h $(HISTORY_SOURCE)
+ @echo making $@ in ${HIST_LIBDIR}
+ @( { test "${HIST_LIBDIR}" = "${libdir}" && exit 0; } || \
+ cd ${HIST_LIBDIR} && $(MAKE) $(MFLAGS) libhistory.a) || exit 1
+
+$(GLOB_LIBRARY): config.h $(GLOB_SOURCE)
+ @echo making $@ in ${GLOB_LIBDIR}
+ @(cd ${GLOB_LIBDIR} && \
+ $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libglob.a) || exit 1
+
+$(TILDE_LIBRARY): config.h $(TILDE_SOURCE)
+ @echo making $@ in ${TILDE_LIBDIR}
+ @(cd ${TILDE_LIBDIR} && \
+ $(MAKE) $(MFLAGS) libtilde.a) || exit 1
+
+$(TERMCAP_LIBRARY): config.h ${TERMCAP_SOURCE}
+ @echo making $@ in ${TERM_LIBDIR}
+ @(cd ${TERM_LIBDIR} && \
+ $(MAKE) $(MFLAGS) libtermcap.a) || exit 1
+
+$(SHLIB_LIBRARY): config.h ${SHLIB_SOURCE}
+ @echo making $@ in ${SH_LIBDIR}
+ @(cd ${SH_LIBDIR} && \
+ $(MAKE) $(MFLAGS) DEBUG=${DEBUG} ${SHLIB_LIBNAME}) || exit 1
+
+${INTL_LIBRARY}: config.h ${INTL_LIBDIR}/Makefile
+ @echo making $@ in ${INTL_LIBDIR}
+ @(cd ${INTL_LIBDIR} && \
+ $(MAKE) $(MFLAGS) all) || exit 1
+
+${LIBINTL_H}: ${INTL_LIBRARY}
+
+mksignames$(EXEEXT): $(SUPPORT_SRC)mksignames.c
+ $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)mksignames.c ${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 ${LIBS_FOR_BUILD}
+
+# make a list of signals for the local system -- this is done when we're
+# *not* cross-compiling
+lsignames.h: mksignames$(EXEEXT)
+ $(RM) $@
+ ./mksignames$(EXEEXT) $@
+
+# copy the correct signames header file to signames.h
+signames.h: $(SIGNAMES_H)
+ -if cmp -s $(SIGNAMES_H) $@ ; then :; else $(RM) $@ ; $(CP) $(SIGNAMES_H) $@ ; fi
+
+syntax.c: mksyntax${EXEEXT} $(srcdir)/syntax.h
+ $(RM) $@
+ ./mksyntax$(EXEEXT) -o $@
+
+$(BUILTINS_LIBRARY): $(BUILTIN_DEFS) $(BUILTIN_C_SRC) config.h ${BASHINCDIR}/memalloc.h version.h
+ @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libbuiltins.a ) || exit 1
+
+# these require special rules to circumvent make builtin rules
+${DEFDIR}/common.o: $(BUILTIN_SRCDIR)/common.c
+ @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} common.o) || exit 1
+
+${DEFDIR}/bashgetopt.o: $(BUILTIN_SRCDIR)/bashgetopt.c
+ @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} bashgetopt.o) || exit 1
+
+${DEFDIR}/builtext.h: $(BUILTIN_DEFS)
+ @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) builtext.h ) || exit 1
+
+# For the justification of the following Makefile rules, see node
+# `Automatic Remaking' in GNU Autoconf documentation.
+
+Makefile makefile: config.status $(srcdir)/Makefile.in
+ CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
+
+pathnames.h: config.status $(srcdir)/Makefile.in
+ CONFIG_HEADERS= $(SHELL) ./config.status
+
+Makefiles makefiles: config.status $(srcdir)/Makefile.in
+ @for mf in $(CREATED_MAKEFILES); do \
+ CONFIG_FILES=$$mf CONFIG_HEADERS= $(SHELL) ./config.status ; \
+ done
+
+config.h: stamp-h
+
+stamp-h: config.status $(srcdir)/config.h.in $(srcdir)/config-top.h $(srcdir)/config-bot.h
+ CONFIG_FILES= CONFIG_HEADERS=config.h $(SHELL) ./config.status
+
+config.status: $(srcdir)/configure
+ $(SHELL) ./config.status --recheck
+
+# comment out for distribution
+$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4 $(srcdir)/config.h.in
+ cd $(srcdir) && autoconf
+
+# for chet
+reconfig: force
+ sh $(srcdir)/configure -C
+
+#newversion: mkversion
+# $(RM) .build
+# ./mkversion -dir $(srcdir) -dist
+# mv -f newversion.h version.h
+# $(MAKE) -f $(srcdir)/Makefile $(MFLAGS) srcdir=$(srcdir)
+
+doc documentation: force
+ @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) )
+
+info dvi ps: force
+ @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) CFLAGS='$(CCFLAGS)' $@ )
+
+force:
+
+tags: $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+ etags $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+
+TAGS: $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+ ctags -x $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE) > $@
+
+# Targets that actually do things not part of the build
+
+installdirs:
+ @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(bindir)
+ @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(man1dir)
+ @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(infodir)
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+install: .made installdirs
+ $(INSTALL_PROGRAM) $(INSTALLMODE) $(Program) $(DESTDIR)$(bindir)/$(Program)
+ $(INSTALL_SCRIPT) $(INSTALLMODE2) bashbug $(DESTDIR)$(bindir)/bashbug
+ -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
+ man1dir=$(man1dir) man1ext=$(man1ext) \
+ man3dir=$(man3dir) man3ext=$(man3ext) \
+ infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+ -( cd $(DEFDIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+install-strip:
+ $(MAKE) $(MFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
+ prefix=${prefix} exec_prefix=${exec_prefix} \
+ DESTDIR=$(DESTDIR) install
+
+uninstall: .made
+ $(RM) $(DESTDIR)$(bindir)/$(Program) $(DESTDIR)$(bindir)/bashbug
+ -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
+ man1dir=$(man1dir) man1ext=$(man1ext) \
+ man3dir=$(man3dir) man3ext=$(man3ext) \
+ infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+.PHONY: basic-clean clean realclean maintainer-clean distclean mostlyclean maybe-clean
+
+LIB_SUBDIRS = ${RL_LIBDIR} ${HIST_LIBDIR} ${TERM_LIBDIR} ${GLOB_LIBDIR} \
+ ${INTL_LIBDIR} ${TILDE_LIBDIR} ${ALLOC_LIBDIR} ${SH_LIBDIR}
+
+basic-clean:
+ $(RM) $(OBJECTS) $(Program) bashbug
+ $(RM) .build .made version.h
+
+clean: basic-clean
+ ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+ ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+ -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+ -for libdir in ${LIB_SUBDIRS}; do \
+ (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+ done
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+ $(RM) $(CREATED_SUPPORT)
+
+mostlyclean: basic-clean
+ ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+ ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+ -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+ -for libdir in ${LIB_SUBDIRS}; do \
+ (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+ done
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+distclean: basic-clean maybe-clean
+ ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+ ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+ -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+ -for libdir in ${LIB_SUBDIRS}; do \
+ (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+ done
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+ $(RM) $(CREATED_CONFIGURE) tags TAGS
+ $(RM) $(CREATED_SUPPORT) Makefile $(CREATED_MAKEFILES) pathnames.h
+
+maintainer-clean: basic-clean
+ @echo This command is intended for maintainers to use.
+ @echo It deletes files that may require special tools to rebuild.
+ $(RM) y.tab.c y.tab.h parser-built tags TAGS
+ ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+ ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+ ( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+ -for libdir in ${LIB_SUBDIRS}; do \
+ (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+ done
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+ $(RM) $(CREATED_CONFIGURE) $(CREATED_MAKEFILES)
+ $(RM) $(CREATED_SUPPORT) Makefile pathnames.h
+
+maybe-clean:
+ -if test "X$(topdir)" != "X$(BUILD_DIR)" ; then \
+ $(RM) parser-built y.tab.c y.tab.h ; \
+ fi
+
+recho$(EXEEXT): $(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 ${LIBS_FOR_BUILD}
+
+printenv$(EXEEXT): $(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
+ @cp $(TESTS_SUPPORT) tests
+ @( cd $(srcdir)/tests && \
+ PATH=$(BUILD_DIR)/tests:$$PATH THIS_SH=$(THIS_SH) $(SHELL) ${TESTSCRIPT} )
+
+symlinks:
+ $(SHELL) $(SUPPORT_SRC)fixlinks -s $(srcdir)
+
+dist: force
+ @echo Bash distributions are created using $(srcdir)/support/mkdist.
+ @echo Here is a sample of the necessary commands:
+ @echo $(Program) $(srcdir)/support/mkdist -m $(srcdir)/MANIFEST -s $(srcdir) -r ${PACKAGE} $(PACKAGE_VERSION)
+ @echo tar cf $(PACKAGE)-${PACKAGE_VERSION}.tar ${PACKAGE}-$(PACKAGE_VERSION)
+ @echo gzip $(PACKAGE)-$(PACKAGE_VERSION).tar
+
+depend: depends
+
+depends: force
+ $(Program) $(SUPPORT_SRC)mkdep -c ${CC} -- ${CCFLAGS} ${CSOURCES}
+
+#### PRIVATE TARGETS ####
+hashtest: hashlib.c
+ $(CC) -DTEST_HASHING $(CCFLAGS) -o $@ $(srcdir)/hashlib.c
+
+############################ DEPENDENCIES ###############################
+
+# Files that depend on the definitions in config-top.h, which are not meant
+# to be changed
+shell.o: config-top.h
+input.o: config-top.h
+y.tab.o: config-top.h
+jobs.o: config-top.h
+nojobs.o: config-top.h
+execute_cmd.o: config-top.h
+variables.o: config-top.h
+builtins/command.o: config-top.h
+builtins/common.o: config-top.h
+builtins/break.o: config-top.h
+builtins/echo.o: config-top.h
+builtins/evalstring.o: config-top.h
+builtins/exit.o: config-top.h
+builtins/kill.o: config-top.h
+
+# shell basics
+copy_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+copy_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+copy_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+copy_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+dispose_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h
+dispose_cmd.o: error.h general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+dispose_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+dispose_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: ${BASHINCDIR}/ocache.h
+error.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h flags.h ${BASHINCDIR}/stdc.h error.h
+error.o: command.h general.h xmalloc.h externs.h input.h bashhist.h
+error.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+error.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+error.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+error.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+error.o: input.h execute_cmd.h
+eval.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h trap.h flags.h ${DEFSRC}/common.h
+eval.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+eval.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+eval.o: input.h execute_cmd.h
+execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+execute_cmd.o: ${BASHINCDIR}/memalloc.h ${GRAM_H} flags.h builtins.h jobs.h quit.h siglist.h
+execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h
+execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h
+execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h
+expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+expr.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+expr.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+expr.o: ${BASHINCDIR}/chartypes.h
+findcmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h
+findcmd.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h
+findcmd.o: ${BASHINCDIR}/stdc.h error.h general.h xmalloc.h variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
+findcmd.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h
+findcmd.o: flags.h hashlib.h pathexp.h hashcmd.h
+findcmd.o: ${BASHINCDIR}/chartypes.h
+flags.o: config.h flags.h
+flags.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+flags.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+flags.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+flags.o: make_cmd.h subst.h sig.h pathnames.h externs.h bashhist.h
+general.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+general.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+general.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+general.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+general.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+general.o: ${BASHINCDIR}/maxpath.h ${BASHINCDIR}/posixtime.h
+general.o: ${BASHINCDIR}/chartypes.h
+hashcmd.o: config.h ${BASHINCDIR}/posixstat.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+hashcmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+hashcmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashcmd.h
+hashcmd.o: execute_cmd.h findcmd.h ${BASHINCDIR}/stdc.h hashlib.h
+hashlib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+hashlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+hashlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+hashlib.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+hashlib.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+input.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+input.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h input.h error.h externs.h
+list.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+list.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+list.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+list.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+locale.o: config.h bashtypes.h bashintl.h ${LIBINTL_H} bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+locale.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+locale.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+locale.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+locale.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+locale.o: ${BASHINCDIR}/chartypes.h
+mailcheck.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+mailcheck.o: ${BASHINCDIR}/posixtime.h
+mailcheck.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+mailcheck.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+mailcheck.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+mailcheck.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+mailcheck.o: execute_cmd.h mailcheck.h
+make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
+make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
+make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
+make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h
+make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/ocache.h
+y.tab.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h
+y.tab.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+y.tab.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+y.tab.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+y.tab.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h
+y.tab.o: trap.h flags.h parser.h input.h mailcheck.h $(DEFSRC)/common.h
+y.tab.o: $(DEFDIR)/builtext.h bashline.h bashhist.h jobs.h siglist.h alias.h
+pathexp.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+pathexp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+pathexp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+pathexp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+pathexp.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+pathexp.o: pathexp.h flags.h
+pathexp.o: $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+pathexp.o: ${BASHINCDIR}/shmbutil.h
+print_cmd.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+print_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+print_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+print_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+print_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+print_cmd.o: ${GRAM_H} $(DEFSRC)/common.h
+redir.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
+redir.o: ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+redir.o: general.h xmalloc.h variables.h arrayfunc.h conftypes.h array.h hashlib.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
+redir.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h
+redir.o: flags.h execute_cmd.h redir.h input.h
+shell.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
+shell.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+shell.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+shell.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+shell.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+shell.o: flags.h trap.h mailcheck.h builtins.h $(DEFSRC)/common.h
+shell.o: jobs.h siglist.h input.h execute_cmd.h findcmd.h bashhist.h
+shell.o: ${GLOB_LIBSRC}/strmatch.h ${BASHINCDIR}/posixtime.h
+sig.o: config.h bashtypes.h
+sig.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+sig.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+sig.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+sig.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+sig.o: jobs.h siglist.h trap.h $(DEFSRC)/common.h bashline.h bashhist.h
+siglist.o: config.h bashtypes.h siglist.h trap.h
+stringlib.o: bashtypes.h ${BASHINCDIR}/chartypes.h
+stringlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+stringlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+stringlib.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+stringlib.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+stringlib.o: ${GLOB_LIBSRC}/glob.h ${GLOB_LIBSRC}/strmatch.h
+subst.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/posixstat.h
+subst.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+subst.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+subst.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+subst.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+subst.o: flags.h jobs.h siglist.h execute_cmd.h ${BASHINCDIR}/filecntl.h trap.h pathexp.h
+subst.o: mailcheck.h input.h $(DEFSRC)/getopt.h $(DEFSRC)/common.h
+subst.o: bashline.h bashhist.h ${GLOB_LIBSRC}/strmatch.h
+subst.o: ${BASHINCDIR}/chartypes.h
+subst.o: ${BASHINCDIR}/shmbutil.h
+test.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+test.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+test.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+test.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+test.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h
+test.o: ${DEFSRC}/common.h
+trap.o: config.h bashtypes.h trap.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+trap.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+trap.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+trap.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+trap.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+trap.o: signames.h $(DEFSRC)/common.h
+trap.o: ${DEFDIR}/builtext.h
+unwind_prot.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
+unwind_prot.o: general.h xmalloc.h unwind_prot.h quit.h sig.h
+variables.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+variables.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+variables.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+variables.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+variables.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+variables.o: flags.h execute_cmd.h mailcheck.h input.h $(DEFSRC)/common.h
+variables.o: findcmd.h bashhist.h hashcmd.h pathexp.h
+variables.o: pcomplete.h ${BASHINCDIR}/chartypes.h
+variables.o: ${BASHINCDIR}/posixtime.h
+version.o: conftypes.h patchlevel.h version.h
+xmalloc.o: config.h bashtypes.h ${BASHINCDIR}/ansi_stdlib.h error.h
+
+# job control
+
+jobs.o: config.h bashtypes.h trap.h ${BASHINCDIR}/filecntl.h input.h ${BASHINCDIR}/shtty.h
+jobs.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+jobs.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+jobs.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+jobs.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+jobs.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+jobs.o: jobs.h flags.h $(DEFSRC)/common.h $(DEFDIR)/builtext.h
+jobs.o: ${BASHINCDIR}/posixwait.h ${BASHINCDIR}/unionwait.h
+jobs.o: ${BASHINCDIR}/posixtime.h
+nojobs.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+nojobs.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h jobs.h quit.h siglist.h externs.h
+nojobs.o: sig.h error.h ${BASHINCDIR}/shtty.h input.h
+
+# shell features that may be compiled in
+
+array.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+array.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+array.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+array.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+array.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+array.o: $(DEFSRC)/common.h
+arrayfunc.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+arrayfunc.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+arrayfunc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+arrayfunc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+arrayfunc.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+arrayfunc.o: $(DEFSRC)/common.h
+arrayfunc.o: ${BASHINCDIR}/shmbutil.h
+braces.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+braces.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+braces.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+braces.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+braces.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+braces.o: ${BASHINCDIR}/shmbutil.h
+alias.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
+alias.o: general.h xmalloc.h bashtypes.h externs.h alias.h
+alias.o: pcomplete.h
+alias.o: ${BASHINCDIR}/chartypes.h
+
+pcomplib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h bashtypes.h
+pcomplib.o: ${BASHINCDIR}/stdc.h hashlib.h pcomplete.h shell.h syntax.h
+pcomplib.o: bashjmp.h command.h general.h xmalloc.h error.h variables.h arrayfunc.h conftypes.h quit.h
+pcomplib.o: unwind_prot.h dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h
+pcomplib.o: externs.h ${BASHINCDIR}/maxpath.h
+
+pcomplete.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h bashtypes.h
+pcomplete.o: ${BASHINCDIR}/stdc.h hashlib.h pcomplete.h shell.h syntax.h
+pcomplete.o: bashjmp.h command.h general.h xmalloc.h error.h variables.h arrayfunc.h conftypes.h quit.h
+pcomplete.o: unwind_prot.h dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h
+pcomplete.o: externs.h ${BASHINCDIR}/maxpath.h execute_cmd.h
+
+# library support files
+
+bashhist.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/posixstat.h
+bashhist.o: ${BASHINCDIR}/filecntl.h
+bashhist.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bashhist.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bashhist.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bashhist.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+bashhist.o: flags.h input.h parser.h pathexp.h $(DEFSRC)/common.h bashline.h
+bashhist.o: $(GLOB_LIBSRC)/strmatch.h
+bashline.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+bashline.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bashline.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bashline.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bashline.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+bashline.o: builtins.h bashhist.h bashline.h execute_cmd.h findcmd.h pathexp.h
+bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h
+bashline.o: pcomplete.h ${BASHINCDIR}/chartypes.h input.h
+bracecomp.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+bracecomp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bracecomp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bracecomp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bracecomp.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+bracecomp.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h hashlib.h builtins.h general.h xmalloc.h
+bracecomp.o: quit.h alias.h config.h variables.h arrayfunc.h conftypes.h
+bracecomp.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+
+# library dependencies
+
+bashline.o: $(RL_LIBSRC)/rlconf.h
+bashline.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/rlstdc.h
+bashline.o: $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/readline.h
+bracecomp.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+bracecomp.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+y.tab.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+y.tab.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+subst.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+subst.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+
+shell.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+subst.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+bashline.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+bashhist.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+y.tab.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+
+execute_cmd.o: $(TILDE_LIBSRC)/tilde.h
+general.o: $(TILDE_LIBSRC)/tilde.h
+mailcheck.o: $(TILDE_LIBSRC)/tilde.h
+shell.o: $(TILDE_LIBSRC)/tilde.h
+subst.o: $(TILDE_LIBSRC)/tilde.h
+variables.o: $(TILDE_LIBSRC)/tilde.h
+
+# libintl dependencies
+arrayfunc.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+bashhist.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+bashline.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+braces.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+error.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+eval.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+execute_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+expr.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+general.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+input.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+jobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+mailcheck.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+make_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+nojobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+parse.y: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pcomplete.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pcomplib.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+print_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+redir.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+shell.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+sig.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+siglist.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+subst.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+test.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+trap.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+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
+
+# XXX - dependencies checked through here
+
+# builtin c sources
+builtins/bashgetopt.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/bashgetopt.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/bashgetopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/bashgetopt.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+builtins/bashgetopt.o: $(DEFSRC)/common.h
+builtins/bashgetopt.o: ${BASHINCDIR}/chartypes.h
+builtins/common.o: bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/common.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h
+builtins/common.o: ${BASHINCDIR}/memalloc.h variables.h arrayfunc.h conftypes.h input.h siglist.h
+builtins/common.o: quit.h unwind_prot.h ${BASHINCDIR}/maxpath.h jobs.h builtins.h
+builtins/common.o: dispose_cmd.h make_cmd.h subst.h externs.h bashhist.h
+builtins/common.o: execute_cmd.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h pathnames.h
+builtins/common.o: ${DEFDIR}/builtext.h
+builtins/common.o: ${BASHINCDIR}/chartypes.h
+builtins/evalfile.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/evalfile.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/evalfile.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/evalfile.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+builtins/evalfile.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+builtins/evalfile.o: bashhist.h $(DEFSRC)/common.h
+builtins/evalstring.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/evalstring.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h siglist.h
+builtins/evalstring.o: ${BASHINCDIR}/memalloc.h variables.h arrayfunc.h conftypes.h input.h
+builtins/evalstring.o: quit.h unwind_prot.h ${BASHINCDIR}/maxpath.h jobs.h builtins.h
+builtins/evalstring.o: dispose_cmd.h make_cmd.h subst.h externs.h
+builtins/evalstring.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+builtins/evalstring.o: bashhist.h $(DEFSRC)/common.h
+builtins/getopt.o: config.h ${BASHINCDIR}/memalloc.h
+builtins/getopt.o: shell.h syntax.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/getopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/getopt.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+builtins/getopt.o: $(DEFSRC)/getopt.h
+builtins/mkbuiltins.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+builtins/mkbuiltins.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+
+# builtin def files
+builtins/alias.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/alias.o: quit.h $(DEFSRC)/common.h
+builtins/alias.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h ${BASHINCDIR}/stdc.h unwind_prot.h
+builtins/alias.o: dispose_cmd.h make_cmd.h subst.h externs.h variables.h arrayfunc.h conftypes.h
+builtins/bind.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/bind.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/bind.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/bind.o: $(DEFSRC)/bashgetopt.h
+builtins/break.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/break.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/break.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/builtin.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/builtin.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/builtin.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/builtin.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/caller.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/caller.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/caller.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/caller.o: $(DEFSRC)/common.h quit.h
+builtins/caller.o: ${BASHINCDIR}/chartypes.h bashtypes.h
+builtins/caller.o: ${DEFDIR}/builtext.h
+builtins/cd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/cd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/cd.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/cd.o: $(DEFSRC)/common.h quit.h
+builtins/command.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/command.o: quit.h $(DEFSRC)/bashgetopt.h
+builtins/command.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/command.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/declare.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/declare.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/declare.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/declare.o: $(DEFSRC)/bashgetopt.h
+builtins/echo.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/echo.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/echo.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/enable.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/enable.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/enable.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/enable.o: pcomplete.h
+builtins/eval.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/eval.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/eval.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/exec.o: bashtypes.h
+builtins/exec.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/exec.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/exec.o: dispose_cmd.h make_cmd.h subst.h externs.h execute_cmd.h
+builtins/exec.o: findcmd.h flags.h quit.h $(DEFSRC)/common.h ${BASHINCDIR}/stdc.h
+builtins/exit.o: bashtypes.h
+builtins/exit.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/exit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/exit.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/fc.o: bashtypes.h ${BASHINCDIR}/posixstat.h
+builtins/fc.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h builtins.h command.h ${BASHINCDIR}/stdc.h
+builtins/fc.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/fc.o: flags.h unwind_prot.h variables.h arrayfunc.h conftypes.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h
+builtins/fc.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h quit.h
+builtins/fc.o: $(DEFSRC)/bashgetopt.h bashhist.h
+builtins/fc.o: ${BASHINCDIR}/chartypes.h
+builtins/fg_bg.o: bashtypes.h $(DEFSRC)/bashgetopt.h
+builtins/fg_bg.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/fg_bg.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/fg_bg.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/getopts.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/getopts.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/getopts.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/hash.o: bashtypes.h
+builtins/hash.o: builtins.h command.h findcmd.h ${BASHINCDIR}/stdc.h $(DEFSRC)/common.h
+builtins/hash.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/hash.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/help.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/help.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/help.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/help.o: $(GLOB_LIBSRC)/glob.h
+builtins/history.o: bashtypes.h
+builtins/history.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/history.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/history.o: ${BASHINCDIR}/filecntl.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h
+builtins/history.o: bashhist.h variables.h arrayfunc.h conftypes.h
+builtins/inlib.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/inlib.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/inlib.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/jobs.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/jobs.o: quit.h $(DEFSRC)/bashgetopt.h
+builtins/jobs.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/jobs.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/kill.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/kill.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/kill.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h trap.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/let.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/let.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/let.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/printf.o: config.h ${BASHINCDIR}/memalloc.h bashjmp.h command.h error.h
+builtins/printf.o: general.h xmalloc.h quit.h dispose_cmd.h make_cmd.h subst.h
+builtins/printf.o: externs.h sig.h pathnames.h shell.h syntax.h unwind_prot.h
+builtins/printf.o: variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/stdc.h $(DEFSRC)/bashgetopt.h
+builtins/printf.o: ${BASHINCDIR}/chartypes.h
+builtins/pushd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/pushd.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/pushd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/pushd.o: $(DEFSRC)/common.h
+builtins/read.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/read.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/read.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/return.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/return.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/return.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/set.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/set.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/set.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h flags.h
+builtins/setattr.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/setattr.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/setattr.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/setattr.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shift.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/shift.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shift.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/shift.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shopt.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h
+builtins/shopt.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h
+builtins/shopt.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h unwind_prot.h variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/maxpath.h
+builtins/shopt.o: $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/source.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/source.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/source.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/source.o: findcmd.h $(DEFSRC)/bashgetopt.h flags.h trap.h
+builtins/suspend.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/suspend.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/suspend.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/test.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/test.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/test.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/test.o: test.h
+builtins/times.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/times.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/times.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/trap.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/trap.o: quit.h $(DEFSRC)/common.h
+builtins/trap.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/trap.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/type.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/type.o: quit.h $(DEFSRC)/common.h findcmd.h
+builtins/type.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/type.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/ulimit.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/ulimit.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/ulimit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/umask.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/umask.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/umask.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/umask.o: ${BASHINCDIR}/chartypes.h
+builtins/wait.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/wait.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/wait.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/wait.o: ${BASHINCDIR}/chartypes.h
+
+builtins/complete.o: config.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h
+builtins/complete.o: unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/complete.o: bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/complete.o: builtins.h
+builtins/complete.o: pcomplete.h
+builtins/complete.o: ${DEFSRC}/common.h ${DEFSRC}/bashgetopt.h
+
+# libintl dependencies
+builtins/bind.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/break.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/caller.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/cd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/common.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/complete.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/declare.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/enable.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/evalfile.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/exec.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/exit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/fc.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/fg_bg.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/getopt.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/hash.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/help.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/history.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/inlib.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/jobs.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/kill.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/let.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/mkbuiltins.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/printf.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/pushd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/read.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/return.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/set.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/setattr.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/shift.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/shopt.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/source.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/suspend.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/type.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/ulimit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/umask.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+
+# builtin library dependencies
+builtins/bind.o: $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/readline.h
+builtins/bind.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/rlstdc.h
+
+builtins/bind.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+builtins/fc.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+builtins/history.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+
+builtins/common.o: $(TILDE_LIBSRC)/tilde.h
+builtins/cd.o: $(TILDE_LIBSRC)/tilde.h
+
+builtins/alias.o: $(DEFSRC)/alias.def
+builtins/bind.o: $(DEFSRC)/bind.def
+builtins/break.o: $(DEFSRC)/break.def
+builtins/builtin.o: $(DEFSRC)/builtin.def
+builtins/caller.o: $(DEFSRC)/caller.def
+builtins/cd.o: $(DEFSRC)/cd.def
+builtins/colon.o: $(DEFSRC)/colon.def
+builtins/command.o: $(DEFSRC)/command.def
+builtins/complete.o: $(DEFSRC)/complete.def
+builtins/declare.o: $(DEFSRC)/declare.def
+builtins/echo.o: $(DEFSRC)/echo.def
+builtins/enable.o: $(DEFSRC)/enable.def
+builtins/eval.o: $(DEFSRC)/eval.def
+builtins/exec.o: $(DEFSRC)/exec.def
+builtins/exit.o: $(DEFSRC)/exit.def
+builtins/fc.o: $(DEFSRC)/fc.def
+builtins/fg_bg.o: $(DEFSRC)/fg_bg.def
+builtins/getopts.o: $(DEFSRC)/getopts.def
+builtins/hash.o: $(DEFSRC)/hash.def
+builtins/help.o: $(DEFSRC)/help.def
+builtins/history.o: $(DEFSRC)/history.def
+builtins/inlib.o: $(DEFSRC)/inlib.def
+builtins/jobs.o: $(DEFSRC)/jobs.def
+builtins/kill.o: $(DEFSRC)/kill.def
+builtins/let.o: $(DEFSRC)/let.def
+builtins/pushd.o: $(DEFSRC)/pushd.def
+builtins/read.o: $(DEFSRC)/read.def
+builtins/reserved.o: $(DEFSRC)/reserved.def
+builtins/return.o: $(DEFSRC)/return.def
+builtins/set.o: $(DEFSRC)/set.def
+builtins/setattr.o: $(DEFSRC)/setattr.def
+builtins/shift.o: $(DEFSRC)/shift.def
+builtins/shopt.o: $(DEFSRC)/shopt.def
+builtins/source.o: $(DEFSRC)/source.def
+builtins/suspend.o: $(DEFSRC)/suspend.def
+builtins/test.o: $(DEFSRC)/test.def
+builtins/times.o: $(DEFSRC)/times.def
+builtins/trap.o: $(DEFSRC)/trap.def
+builtins/type.o: $(DEFSRC)/type.def
+builtins/ulimit.o: $(DEFSRC)/ulimit.def
+builtins/umask.o: $(DEFSRC)/umask.def
+builtins/wait.o: $(DEFSRC)/wait.def
diff --git a/Makefile.in~ b/Makefile.in~
new file mode 100644
index 00000000..bac74e62
--- /dev/null
+++ b/Makefile.in~
@@ -0,0 +1,1455 @@
+# Makefile for bash-3.1, version 2.159
+#
+# Copyright (C) 1996-2005 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.
+
+# Make sure the first target in the makefile is the right one
+all: .made
+
+PACKAGE = @PACKAGE_NAME@
+VERSION = @PACKAGE_VERSION@
+
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+
+# Include some boilerplate Gnu makefile definitions.
+prefix = @prefix@
+
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+libdir = @libdir@
+infodir = @infodir@
+includedir = @includedir@
+datadir = @datadir@
+localedir = $(datadir)/locale
+
+mandir = @mandir@
+manpfx = man
+
+man1ext = .1
+man1dir = $(mandir)/$(manpfx)1
+man3ext = .3
+man3dir = $(mandir)/$(manpfx)3
+
+htmldir = @htmldir@
+
+# Support an alternate destination root directory for package building
+DESTDIR =
+
+topdir = @top_srcdir@
+BUILD_DIR = @BUILD_DIR@
+top_builddir = @BUILD_DIR@
+srcdir = @srcdir@
+VPATH = .:@srcdir@
+
+@SET_MAKE@
+CC = @CC@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+YACC = @YACC@
+SHELL = @MAKE_SHELL@
+CP = cp
+RM = rm -f
+AR = @AR@
+ARFLAGS = @ARFLAGS@
+RANLIB = @RANLIB@
+SIZE = @SIZE@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALLMODE= -m 0755
+INSTALLMODE2 = -m 0555
+
+TESTSCRIPT = @TESTSCRIPT@
+
+#If you have purify, and want to use it, uncomment this definition or
+# run the make as `make PURIFY=purify'
+# or run configure with the --with-purify argument.
+PURIFY = @PURIFY@
+
+# Here is a rule for making .o files from .c files that does not
+# force the type of the machine (like -M_MACHINE) into the flags.
+.c.o:
+ $(RM) $@
+ $(CC) $(CCFLAGS) -c $<
+
+EXEEXT = @EXEEXT@
+OBJEXT = @OBJEXT@
+
+# The name of this program and some version information.
+VERSPROG = bashversion$(EXEEXT)
+VERSOBJ = bashversion.$(OBJEXT)
+
+Program = bash$(EXEEXT)
+Version = @BASHVERS@
+PatchLevel = `$(BUILD_DIR)/$(VERSPROG) -p`
+RELSTATUS = @RELSTATUS@
+
+Machine = @host_cpu@
+OS = @host_os@
+VENDOR = @host_vendor@
+MACHTYPE = @host@
+
+# comment out for release
+DEBUG = @DEBUG@
+MALLOC_DEBUG = @MALLOC_DEBUG@
+
+THIS_SH = $(BUILD_DIR)/$(Program)
+
+# PROFILE_FLAGS is either -pg, to generate profiling info for use
+# with gprof, or nothing (the default).
+PROFILE_FLAGS= @PROFILE_FLAGS@
+
+CFLAGS = @CFLAGS@
+CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ @CROSS_COMPILE@
+CPPFLAGS = @CPPFLAGS@
+CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
+LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG} ${MALLOC_DEBUG}
+DEFS = @DEFS@
+LOCAL_DEFS = @LOCAL_DEFS@
+
+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@
+
+SYSTEM_FLAGS = -DPROGRAM='"$(Program)"' -DCONF_HOSTTYPE='"$(Machine)"' -DCONF_OSTYPE='"$(OS)"' -DCONF_MACHTYPE='"$(MACHTYPE)"' -DCONF_VENDOR='"$(VENDOR)"' $(LOCALE_DEFS)
+
+BASE_CCFLAGS = $(PROFILE_FLAGS) $(SYSTEM_FLAGS) $(LOCAL_DEFS) \
+ $(DEFS) $(LOCAL_CFLAGS) $(INCLUDES)
+
+CCFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(CFLAGS)
+
+CCFLAGS_FOR_BUILD = $(BASE_CCFLAGS) $(CPPFLAGS_FOR_BUILD) $(CFLAGS_FOR_BUILD)
+
+LDFLAGS = @LDFLAGS@ $(STATIC_LD) $(LOCAL_LDFLAGS) $(PROFILE_FLAGS) $(CFLAGS)
+LDFLAGS_FOR_BUILD = $(LDFLAGS)
+
+INCLUDES = -I. @RL_INCLUDE@ -I$(srcdir) -I$(BASHINCDIR) -I$(LIBSRC) $(INTL_INC)
+
+GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
+ -Wcast-align -Wstrict-prototypes -Wconversion \
+ -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
+
+GCC_LINT_CFLAGS = $(BASE_CCFLAGS) $(CPPFLAGS) $(GCC_LINT_FLAGS)
+
+#
+# Support libraries
+#
+
+dot = .
+
+LIBSUBDIR = lib
+LIBSRC = $(srcdir)/$(LIBSUBDIR)
+
+LIBBUILD = ${BUILD_DIR}/${LIBSUBDIR}
+
+SUBDIR_INCLUDES = -I. @RL_INCLUDE@ -I$(topdir) -I$(topdir)/$(LIBSUBDIR)
+
+BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
+USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
+
+# the bash library
+# the library is a mix of functions that the C library does not provide on
+# some platforms and general shell utility functions
+SH_LIBSRC = $(LIBSRC)/sh
+SH_LIBDIR = $(dot)/${LIBSUBDIR}/sh
+SH_ABSSRC = ${topdir}/${SH_LIBSRC}
+
+SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
+ ${SH_LIBSRC}/getenv.c ${SH_LIBSRC}/oslib.c \
+ ${SH_LIBSRC}/setlinebuf.c \
+ ${SH_LIBSRC}/strcasecmp.c ${SH_LIBSRC}/strerror.c \
+ ${SH_LIBSRC}/strtod.c ${SH_LIBSRC}/strtol.c \
+ ${SH_LIBSRC}/strtoul.c ${SH_LIBSRC}/vprint.c \
+ ${SH_LIBSRC}/itos.c ${SH_LIBSRC}/rename.c \
+ ${SH_LIBSRC}/zread.c ${SH_LIBSRC}/zwrite.c \
+ ${SH_LIBSRC}/shtty.c ${SH_LIBSRC}/inet_aton.c \
+ ${SH_LIBSRC}/netopen.c ${SH_LIBSRC}/strpbrk.c \
+ ${SH_LIBSRC}/timeval.c ${SH_LIBSRC}/clock.c \
+ ${SH_LIBSRC}/makepath.c ${SH_LIBSRC}/pathcanon.c \
+ ${SH_LIBSRC}/pathphys.c ${SH_LIBSRC}/stringlist.c \
+ ${SH_LIBSRC}/stringvec.c ${SH_LIBSRC}/tmpfile.c \
+ ${SH_LIBSRC}/spell.c ${SH_LIBSRC}/strtrans.c \
+ ${SH_LIBSRC}/strindex.c ${SH_LIBSRC}/shquote.c \
+ ${SH_LIBSRC}/snprintf.c ${SH_LIBSRC}/mailstat.c \
+ ${SH_LIBSRC}/fmtulong.c ${SH_LIBSRC}/fmtullong.c \
+ ${SH_LIBSRC}/strtoll.c ${SH_LIBSRC}/strtoull.c \
+ ${SH_LIBSRC}/strtoimax.c ${SH_LIBSRC}/strtoumax.c \
+ ${SH_LIBSRC}/fmtumax.c ${SH_LIBSRC}/netconn.c \
+ ${SH_LIBSRC}/mktime.c ${SH_LIBSRC}/strftime.c \
+ ${SH_LIBSRC}/memset.c ${SH_LIBSRC}/xstrchr.c \
+ ${SH_LIBSRC}/zcatfd.c ${SH_LIBSRC}/shmatch.c \
+ ${SH_LIBSRC}/strnlen.c ${SH_LIBSRC}/winsize.c
+
+SHLIB_LIB = -lsh
+SHLIB_LIBNAME = libsh.a
+SHLIB_LIBRARY = ${SH_LIBDIR}/${SHLIB_LIBNAME}
+SHLIB_LDFLAGS = -L${SH_LIBDIR}
+SHLIB_DEP = ${SHLIB_LIBRARY}
+
+# we assume for now that readline source is being shipped with bash
+RL_LIBSRC = $(LIBSRC)/readline
+RL_LIBDOC = $(RL_LIBSRC)/doc
+RL_LIBDIR = @RL_LIBDIR@
+RL_ABSSRC = ${topdir}/$(RL_LIBDIR)
+
+RL_INCLUDEDIR = @RL_INCLUDEDIR@
+
+READLINE_LIB = @READLINE_LIB@
+READLINE_LIBRARY = $(RL_LIBDIR)/libreadline.a
+READLINE_LDFLAGS = -L${RL_LIBDIR}
+READLINE_DEP = @READLINE_DEP@
+
+# The source, object and documentation of the GNU Readline library.
+READLINE_SOURCE = $(RL_LIBSRC)/rldefs.h $(RL_LIBSRC)/rlconf.h \
+ $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/tcap.h \
+ $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/keymaps.h \
+ $(RL_LIBSRC)/history.h $(RL_LIBSRC)/histlib.h \
+ $(RL_LIBSRC)/posixstat.h $(RL_LIBSRC)/tilde.h \
+ $(RL_LIBSRC)/rlstdc.h ${RL_LIBSRC}/xmalloc.h \
+ $(RL_LIBSRC)/rlshell.h ${RL_LIBSRC}/rlprivate.h \
+ $(RL_LIBSRC)/funmap.c $(RL_LIBSRC)/emacs_keymap.c \
+ $(RL_LIBSRC)/search.c $(RL_LIBSRC)/vi_keymap.c \
+ $(RL_LIBSRC)/keymaps.c $(RL_LIBSRC)/parens.c \
+ $(RL_LIBSRC)/vi_mode.c $(RL_LIBSRC)/callback.c \
+ $(RL_LIBSRC)/readline.c $(RL_LIBSRC)/tilde.c \
+ $(RL_LIBSRC)/rltty.c $(RL_LIBSRC)/complete.c \
+ $(RL_LIBSRC)/bind.c $(RL_LIBSRC)/isearch.c \
+ $(RL_LIBSRC)/display.c $(RL_LIBSRC)/signals.c \
+ $(RL_LIBSRC)/util.c $(RL_LIBSRC)/kill.c $(RL_LIBSRC)/text.c \
+ $(RL_LIBSRC)/undo.c $(RL_LIBSRC)/macro.c \
+ $(RL_LIBSRC)/terminal.c $(RL_LIBSRC)/nls.c \
+ $(RL_LIBSRC)/input.c $(RL_LIBSRC)/xmalloc.c \
+ $(RL_LIBSRC)/shell.c $(RL_LIBSRC)/savestring.c \
+ $(RL_LIBSRC)/misc.c $(RL_LIBSRC)/mbutil.c $(RL_LIBSRC)/compat.c \
+ $(RL_LIBSRC)/histexpand.c $(RL_LIBSRC)/history.c \
+ $(RL_LIBSRC)/histsearch.c $(RL_LIBSRC)/histfile.c
+
+READLINE_OBJ = $(RL_LIBDIR)/readline.o $(RL_LIBDIR)/funmap.o \
+ $(RL_LIBDIR)/parens.o $(RL_LIBDIR)/search.o \
+ $(RL_LIBDIR)/keymaps.o $(RL_LIBDIR)/xmalloc.o \
+ $(RL_LIBDIR)/rltty.o $(RL_LIBDIR)/complete.o \
+ $(RL_LIBDIR)/bind.o $(RL_LIBDIR)/isearch.o \
+ $(RL_LIBDIR)/display.o $(RL_LIBDIR)/signals.o \
+ $(RL_LIBDIR)/tilde.o $(RL_LIBDIR)/util.o \
+ $(RL_LIBDIR)/kill.o $(RL_LIBDIR)/undo.o $(RL_LIBDIR)/nls.o \
+ $(RL_LIBDIR)/macro.o $(RL_LIBDIR)/input.o \
+ $(RL_LIBDIR)/terminal.o $(RL_LIBDIR)/callback.o \
+ $(RL_LIBDIR)/shell.o $(RL_LIBDIR)/savestring.o \
+ $(RL_LIBDIR)/mbutil.o $(RL_LIBDIR)/compat.o \
+ $(RL_LIBDIR)/history.o $(RL_LIBDIR)/histexpand.o \
+ $(RL_LIBDIR)/histsearch.o $(RL_LIBDIR)/histfile.o
+
+HIST_LIBSRC = $(LIBSRC)/readline
+HIST_LIBDIR = @HIST_LIBDIR@
+HIST_ABSSRC = ${topdir}/$(HIST_LIBDIR)
+
+HISTORY_LIB = @HISTORY_LIB@
+HISTORY_LIBRARY = $(HIST_LIBDIR)/libhistory.a
+HISTORY_LDFLAGS = -L$(HIST_LIBDIR)
+HISTORY_DEP = @HISTORY_DEP@
+
+# The source, object and documentation of the history library.
+HISTORY_SOURCE = $(HIST_LIBSRC)/history.c $(HIST_LIBSRC)/histexpand.c \
+ $(HIST_LIBSRC)/histsearch.c $(HIST_LIBSRC)/histfile.c \
+ $(HIST_LIBSRC)/shell.c \
+ $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/histlib.h
+HISTORY_OBJ = $(HIST_LIBDIR)/history.o $(HIST_LIBDIR)/histexpand.o \
+ $(HIST_LIBDIR)/histsearch.o $(HIST_LIBDIR)/histfile.o \
+ $(HIST_LIBDIR)/shell.o
+
+# You only need termcap (or curses) if you are linking with GNU Readline.
+TERM_LIBSRC = $(LIBSRC)/termcap
+TERM_LIBDIR = $(dot)/$(LIBSUBDIR)/termcap
+TERM_ABSSRC = ${topdir}/$(TERM_LIBDIR)
+
+TERMCAP_LIB = @TERMCAP_LIB@
+TERMCAP_LIBRARY = $(TERM_LIBDIR)/libtermcap.a
+TERMCAP_LDFLAGS = -L$(TERM_LIBDIR)
+TERMCAP_DEP = @TERMCAP_DEP@
+
+TERMCAP_SOURCE = $(TERM_LIBSRC)/termcap.c $(TERM_LIBSRC)/tparam.c
+TERMCAP_OBJ = $(TERM_LIBDIR)/termcap.o $(TERM_LIBDIR)/tparam.o
+
+GLOB_LIBSRC = $(LIBSRC)/glob
+GLOB_LIBDIR = $(dot)/$(LIBSUBDIR)/glob
+GLOB_ABSSRC = ${topdir}/$(GLOB_LIBDIR)
+
+GLOB_LIB = -lglob
+GLOB_LIBRARY = $(GLOB_LIBDIR)/libglob.a
+GLOB_LDFLAGS = -L$(GLOB_LIBDIR)
+GLOB_DEP = $(GLOB_LIBRARY)
+
+GLOB_SOURCE = $(GLOB_LIBSRC)/glob.c $(GLOB_LIBSRC)/strmatch.c \
+ $(GLOB_LIBSRC)/smatch.c $(GLOB_LIBSRC)/xmbsrtowcs.c \
+ $(GLOB_LIBSRC)/glob_loop.c $(GLOB_LIBSRC)/sm_loop.c \
+ $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+GLOB_OBJ = $(GLOB_LIBDIR)/glob.o $(GLOB_LIBDIR)/strmatch.o \
+ $(GLOB_LIBDIR)/smatch.o $(GLOB_LIBDIR)/xmbsrtowcs.o
+
+# The source, object and documentation for the GNU Tilde library.
+TILDE_LIBSRC = $(LIBSRC)/tilde
+TILDE_LIBDIR = $(dot)/$(LIBSUBDIR)/tilde
+TILDE_ABSSRC = ${topdir}/$(TILDE_LIBDIR)
+
+TILDE_LIB = @TILDE_LIB@
+TILDE_LIBRARY = $(TILDE_LIBDIR)/libtilde.a
+TILDE_LDFLAGS = -L$(TILDE_LIBDIR)
+TILDE_DEP = $(TILDE_LIBRARY)
+
+TILDE_SOURCE = $(TILDE_LIBSRC)/tilde.c $(TILDE_LIBSRC)/tilde.h
+TILDE_OBJ = $(TILDE_LIBDIR)/tilde.o
+
+# libintl
+INTL_LIBSRC = $(LIBSRC)/intl
+INTL_LIBDIR = $(dot)/$(LIBSUBDIR)/intl
+INTL_ABSSRC = ${topdir}/$(INTL_LIB)
+INTL_BUILDDIR = ${LIBBUILD}/intl
+
+INTL_LIB = @LIBINTL@
+INTL_LIBRARY = $(INTL_LIBDIR)/libintl.a
+INTL_DEP = @INTL_DEP@
+INTL_INC = @INTL_INC@
+
+LIBINTL_H = @LIBINTL_H@
+
+# tests
+LIBINTL = @LIBINTL@
+LTLIBINTL = @LTLIBINTL@
+INTLLIBS = @INTLLIBS@
+INTLOBJS = @INTLOBJS@
+
+# Our malloc.
+MALLOC_TARGET = @MALLOC_TARGET@
+
+# set to alloca.o if we are using the C alloca in lib/malloc
+ALLOCA = @ALLOCA@
+
+ALLOC_LIBSRC = $(LIBSRC)/malloc
+ALLOC_LIBDIR = $(dot)/$(LIBSUBDIR)/malloc
+ALLOC_ABSSRC = ${topdir}/$(ALLOC_LIBDIR)
+
+MALLOC_SRC = @MALLOC_SRC@
+MALLOC_OTHERSRC = ${ALLOC_LIBSRC}/trace.c ${ALLOC_LIBSRC}/stats.c \
+ ${ALLOC_LIBSRC}/table.c ${ALLOC_LIBSRC}/watch.c
+MALLOC_SOURCE = ${ALLOC_LIBSRC}/${MALLOC_SRC} ${MALLOC_OTHERSRC}
+MALLOC_CFLAGS = -DRCHECK -Dbotch=programming_error ${MALLOC_DEBUG}
+
+MALLOC_LIB = @MALLOC_LIB@
+MALLOC_LIBRARY = @MALLOC_LIBRARY@
+MALLOC_LDFLAGS = @MALLOC_LDFLAGS@
+MALLOC_DEP = @MALLOC_DEP@
+
+ALLOC_HEADERS = $(ALLOC_LIBSRC)/getpagesize.h $(ALLOC_LIBSRC)/shmalloc.h \
+ $(ALLOC_LIBSRC)/imalloc.h $(ALLOC_LIBSRC)/mstats.h \
+ $(ALLOC_LIBSRC)/table.h $(ALLOC_LIBSRC)/watch.h
+
+$(MALLOC_LIBRARY): ${MALLOC_SOURCE} ${ALLOC_HEADERS} config.h
+ @(cd $(ALLOC_LIBDIR) && \
+ $(MAKE) $(MFLAGS) \
+ MALLOC_CFLAGS="$(MALLOC_CFLAGS)" ${MALLOC_TARGET} ) || exit 1
+
+BASHINCDIR = ${srcdir}/include
+BASHINCFILES = $(BASHINCDIR)/posixstat.h $(BASHINCDIR)/ansi_stdlib.h \
+ $(BASHINCDIR)/filecntl.h $(BASHINCDIR)/posixdir.h \
+ $(BASHINCDIR)/memalloc.h $(BASHINCDIR)/stdc.h \
+ $(BASHINCDIR)/posixjmp.h $(BASHINCDIR)/posixwait.h \
+ $(BASHINCDIR)/posixtime.h $(BASHINCDIR)/systimes.h \
+ $(BASHINCDIR)/unionwait.h $(BASHINCDIR)/maxpath.h \
+ $(BASHINCDIR)/shtty.h $(BASHINCDIR)/typemax.h \
+ $(BASHINCDIR)/ocache.h
+
+LIBRARIES = $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) $(GLOB_LIB) \
+ $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LOCAL_LIBS)
+
+LIBDEP = $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_DEP) $(GLOB_DEP) \
+ $(TILDE_DEP) $(MALLOC_DEP)
+
+LIBRARY_LDFLAGS = $(READLINE_LDFLAGS) $(HISTORY_LDFLAGS) $(GLOB_LDFLAGS) \
+ $(TILDE_LDFLAGS) $(MALLOC_LDFLAGS) $(SHLIB_LDFLAGS)
+
+#
+# The shell itself
+#
+
+# The main source code for the Bourne Again SHell.
+CSOURCES = shell.c eval.c parse.y general.c make_cmd.c print_cmd.c y.tab.c \
+ dispose_cmd.c execute_cmd.c variables.c $(GLOBC) version.c \
+ expr.c copy_cmd.c flags.c subst.c hashcmd.c hashlib.c mailcheck.c \
+ test.c trap.c alias.c jobs.c nojobs.c $(ALLOC_FILES) braces.c \
+ input.c bashhist.c array.c arrayfunc.c sig.c pathexp.c \
+ unwind_prot.c siglist.c bashline.c bracecomp.c error.c \
+ list.c stringlib.c locale.c findcmd.c redir.c \
+ pcomplete.c pcomplib.c syntax.c xmalloc.c
+
+HSOURCES = shell.h flags.h trap.h hashcmd.h hashlib.h jobs.h builtins.h \
+ general.h variables.h config.h $(ALLOC_HEADERS) alias.h \
+ quit.h unwind_prot.h syntax.h ${GRAM_H} \
+ command.h input.h error.h bashansi.h dispose_cmd.h make_cmd.h \
+ subst.h externs.h siglist.h bashhist.h bashline.h bashtypes.h \
+ array.h arrayfunc.h sig.h mailcheck.h bashintl.h bashjmp.h \
+ execute_cmd.h parser.h pathexp.h pathnames.h pcomplete.h \
+ $(BASHINCFILES)
+
+SOURCES = $(CSOURCES) $(HSOURCES) $(BUILTIN_DEFS)
+
+# header files chosen based on running of configure
+SIGNAMES_H = @SIGNAMES_H@
+
+# object files chosen based on running of configure
+JOBS_O = @JOBS_O@
+SIGLIST_O = @SIGLIST_O@
+
+# Matching object files.
+OBJECTS = shell.o eval.o y.tab.o general.o make_cmd.o print_cmd.o $(GLOBO) \
+ dispose_cmd.o execute_cmd.o variables.o copy_cmd.o error.o \
+ expr.o flags.o $(JOBS_O) subst.o hashcmd.o hashlib.o mailcheck.o \
+ 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
+
+# Where the source code of the shell builtins resides.
+BUILTIN_SRCDIR=$(srcdir)/builtins
+DEFSRC=$(BUILTIN_SRCDIR)
+BUILTIN_ABSSRC=${topdir}/builtins
+DEFDIR = $(dot)/builtins
+DEBUGGER_DIR = $(dot)/debugger
+
+BUILTIN_DEFS = $(DEFSRC)/alias.def $(DEFSRC)/bind.def $(DEFSRC)/break.def \
+ $(DEFSRC)/builtin.def $(DEFSRC)/cd.def $(DEFSRC)/colon.def \
+ $(DEFSRC)/command.def ${DEFSRC}/complete.def \
+ $(DEFSRC)/caller.def $(DEFSRC)/declare.def \
+ $(DEFSRC)/echo.def $(DEFSRC)/enable.def $(DEFSRC)/eval.def \
+ $(DEFSRC)/exec.def $(DEFSRC)/exit.def $(DEFSRC)/fc.def \
+ $(DEFSRC)/fg_bg.def $(DEFSRC)/hash.def $(DEFSRC)/help.def \
+ $(DEFSRC)/history.def $(DEFSRC)/jobs.def $(DEFSRC)/kill.def \
+ $(DEFSRC)/let.def $(DEFSRC)/read.def $(DEFSRC)/return.def \
+ $(DEFSRC)/set.def $(DEFSRC)/setattr.def $(DEFSRC)/shift.def \
+ $(DEFSRC)/source.def $(DEFSRC)/suspend.def $(DEFSRC)/test.def \
+ $(DEFSRC)/times.def $(DEFSRC)/trap.def $(DEFSRC)/type.def \
+ $(DEFSRC)/ulimit.def $(DEFSRC)/umask.def $(DEFSRC)/wait.def \
+ $(DEFSRC)/getopts.def $(DEFSRC)/reserved.def \
+ $(DEFSRC)/pushd.def $(DEFSRC)/shopt.def $(DEFSRC)/printf.def
+BUILTIN_C_SRC = $(DEFSRC)/mkbuiltins.c $(DEFSRC)/common.c \
+ $(DEFSRC)/evalstring.c $(DEFSRC)/evalfile.c \
+ $(DEFSRC)/bashgetopt.c $(GETOPT_SOURCE)
+BUILTIN_C_OBJ = $(DEFDIR)/common.o $(DEFDIR)/evalstring.o \
+ $(DEFDIR)/evalfile.o $(DEFDIR)/bashgetopt.o
+BUILTIN_OBJS = $(DEFDIR)/alias.o $(DEFDIR)/bind.o $(DEFDIR)/break.o \
+ $(DEFDIR)/builtin.o $(DEFDIR)/cd.o $(DEFDIR)/colon.o \
+ $(DEFDIR)/command.o $(DEFDIR)/caller.o $(DEFDIR)/declare.o \
+ $(DEFDIR)/echo.o $(DEFDIR)/enable.o $(DEFDIR)/eval.o \
+ $(DEFDIR)/exec.o $(DEFDIR)/exit.o $(DEFDIR)/fc.o \
+ $(DEFDIR)/fg_bg.o $(DEFDIR)/hash.o $(DEFDIR)/help.o \
+ $(DEFDIR)/history.o $(DEFDIR)/jobs.o $(DEFDIR)/kill.o \
+ $(DEFDIR)/let.o $(DEFDIR)/pushd.o $(DEFDIR)/read.o \
+ $(DEFDIR)/return.o $(DEFDIR)/shopt.o $(DEFDIR)/printf.o \
+ $(DEFDIR)/set.o $(DEFDIR)/setattr.o $(DEFDIR)/shift.o \
+ $(DEFDIR)/source.o $(DEFDIR)/suspend.o $(DEFDIR)/test.o \
+ $(DEFDIR)/times.o $(DEFDIR)/trap.o $(DEFDIR)/type.o \
+ $(DEFDIR)/ulimit.o $(DEFDIR)/umask.o $(DEFDIR)/wait.o \
+ $(DEFDIR)/getopts.o $(BUILTIN_C_OBJ)
+GETOPT_SOURCE = $(DEFSRC)/getopt.c $(DEFSRC)/getopt.h
+PSIZE_SOURCE = $(DEFSRC)/psize.sh $(DEFSRC)/psize.c
+
+BUILTINS_LIBRARY = $(DEFDIR)/libbuiltins.a
+BUILTINS_LIB = -lbuiltins
+BUILTINS_LDFLAGS = -L$(DEFDIR)
+BUILTINS_DEP = $(BUILTINS_LIBRARY)
+
+# Documentation for the shell.
+DOCSRC = $(srcdir)/doc
+DOCDIR = $(dot)/doc
+
+# Translations and other i18n support files
+PO_SRC = $(srcdir)/po/
+PO_DIR = $(dot)/po/
+
+SIGNAMES_SUPPORT = $(SUPPORT_SRC)mksignames.c
+
+SUPPORT_SRC = $(srcdir)/support/
+SDIR = $(dot)/support/
+
+TESTS_SUPPORT = recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT)
+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 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 \
+ lib/readline/Makefile lib/glob/Makefile \
+ lib/sh/Makefile lib/tilde/Makefile lib/malloc/Makefile \
+ lib/termcap/Makefile examples/loadables/Makefile \
+ examples/loadables/perl/Makefile support/Makefile \
+ lib/intl/Makefile po/Makefile po/Makefile.in
+
+# Keep GNU Make from exporting the entire environment for small machines.
+.NOEXPORT:
+
+.made: $(Program) bashbug
+ @echo "$(Program) last made for a $(Machine) running $(OS)" >.made
+
+$(Program): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP)
+ $(RM) $@
+ $(PURIFY) $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) -o $(Program) $(OBJECTS) $(LIBS)
+ ls -l $(Program)
+ -$(SIZE) $(Program)
+
+.build: $(SOURCES) config.h Makefile version.h $(VERSPROG)
+ @echo
+ @echo " ***********************************************************"
+ @echo " * *"
+ @echo " * `$(BUILD_DIR)/$(VERSPROG) -l`"
+ @echo " * *"
+ @echo " ***********************************************************"
+ @echo
+
+bashbug: $(SUPPORT_SRC)bashbug.sh config.h Makefile $(VERSPROG)
+ @sed -e "s%!MACHINE!%$(Machine)%" -e "s%!OS!%$(OS)%" \
+ -e "s%!CFLAGS!%$(CCFLAGS)%" -e "s%!CC!%$(CC)%" \
+ -e "s%!RELEASE!%$(Version)%" -e "s%!PATCHLEVEL!%$(PatchLevel)%" \
+ -e "s%!MACHTYPE!%$(MACHTYPE)%" -e "s%!RELSTATUS!%$(RELSTATUS)%" \
+ $(SUPPORT_SRC)bashbug.sh > $@
+ @chmod a+rx bashbug
+
+strip: $(Program) .made
+ strip $(Program)
+ ls -l $(Program)
+ -$(SIZE) $(Program)
+
+lint:
+ ${MAKE} ${MFLAGS} CFLAGS='${GCC_LINT_FLAGS}' .made
+
+version.h: $(SOURCES) config.h Makefile
+ $(SHELL) $(SUPPORT_SRC)mkversion.sh -b -S ${topdir} -s $(RELSTATUS) -d $(Version) -o newversion.h \
+ && 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 ${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
+
+# old rules
+GRAM_H = parser-built
+y.tab.o: y.tab.c ${GRAM_H} command.h ${BASHINCDIR}/stdc.h input.h
+${GRAM_H}: y.tab.h
+ @-if test -f y.tab.h ; then \
+ cmp -s $@ y.tab.h 2>/dev/null || cp -p y.tab.h $@; \
+ fi
+y.tab.c y.tab.h: parse.y
+# -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
+ $(YACC) -d $(srcdir)/parse.y
+ touch parser-built
+# -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; else cp -p y.tab.h ${GRAM_H}; fi
+
+# experimental new rules - work with GNU make but not BSD (or OSF) make
+#y.tab.o: y.tab.c y.tab.h
+#y.tab.c y.tab.h: parse.y command.h ${BASHINCDIR}/stdc.h input.h
+# -if test -f y.tab.h; then mv -f y.tab.h old-y.tab.h; fi
+# $(YACC) -d $(srcdir)/parse.y
+# -if cmp -s old-y.tab.h y.tab.h; then mv old-y.tab.h y.tab.h; fi
+
+$(READLINE_LIBRARY): config.h $(READLINE_SOURCE)
+ @echo making $@ in ${RL_LIBDIR}
+ @( { test "${RL_LIBDIR}" = "${libdir}" && exit 0; } || \
+ cd ${RL_LIBDIR} && $(MAKE) $(MFLAGS) libreadline.a) || exit 1
+
+$(HISTORY_LIBRARY): config.h $(HISTORY_SOURCE)
+ @echo making $@ in ${HIST_LIBDIR}
+ @( { test "${HIST_LIBDIR}" = "${libdir}" && exit 0; } || \
+ cd ${HIST_LIBDIR} && $(MAKE) $(MFLAGS) libhistory.a) || exit 1
+
+$(GLOB_LIBRARY): config.h $(GLOB_SOURCE)
+ @echo making $@ in ${GLOB_LIBDIR}
+ @(cd ${GLOB_LIBDIR} && \
+ $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libglob.a) || exit 1
+
+$(TILDE_LIBRARY): config.h $(TILDE_SOURCE)
+ @echo making $@ in ${TILDE_LIBDIR}
+ @(cd ${TILDE_LIBDIR} && \
+ $(MAKE) $(MFLAGS) libtilde.a) || exit 1
+
+$(TERMCAP_LIBRARY): config.h ${TERMCAP_SOURCE}
+ @echo making $@ in ${TERM_LIBDIR}
+ @(cd ${TERM_LIBDIR} && \
+ $(MAKE) $(MFLAGS) libtermcap.a) || exit 1
+
+$(SHLIB_LIBRARY): config.h ${SHLIB_SOURCE}
+ @echo making $@ in ${SH_LIBDIR}
+ @(cd ${SH_LIBDIR} && \
+ $(MAKE) $(MFLAGS) DEBUG=${DEBUG} ${SHLIB_LIBNAME}) || exit 1
+
+${INTL_LIBRARY}: config.h ${INTL_LIBDIR}/Makefile
+ @echo making $@ in ${INTL_LIBDIR}
+ @(cd ${INTL_LIBDIR} && \
+ $(MAKE) $(MFLAGS) all) || exit 1
+
+${LIBINTL_H}: ${INTL_LIBRARY}
+
+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
+ $(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
+lsignames.h: mksignames$(EXEEXT)
+ $(RM) $@
+ ./mksignames$(EXEEXT) $@
+
+# copy the correct signames header file to signames.h
+signames.h: $(SIGNAMES_H)
+ -if cmp -s $(SIGNAMES_H) $@ ; then :; else $(RM) $@ ; $(CP) $(SIGNAMES_H) $@ ; fi
+
+syntax.c: mksyntax${EXEEXT} $(srcdir)/syntax.h
+ $(RM) $@
+ ./mksyntax$(EXEEXT) -o $@
+
+$(BUILTINS_LIBRARY): $(BUILTIN_DEFS) $(BUILTIN_C_SRC) config.h ${BASHINCDIR}/memalloc.h version.h
+ @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} libbuiltins.a ) || exit 1
+
+# these require special rules to circumvent make builtin rules
+${DEFDIR}/common.o: $(BUILTIN_SRCDIR)/common.c
+ @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} common.o) || exit 1
+
+${DEFDIR}/bashgetopt.o: $(BUILTIN_SRCDIR)/bashgetopt.c
+ @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) DEBUG=${DEBUG} bashgetopt.o) || exit 1
+
+${DEFDIR}/builtext.h: $(BUILTIN_DEFS)
+ @(cd $(DEFDIR) && $(MAKE) $(MFLAGS) builtext.h ) || exit 1
+
+# For the justification of the following Makefile rules, see node
+# `Automatic Remaking' in GNU Autoconf documentation.
+
+Makefile makefile: config.status $(srcdir)/Makefile.in
+ CONFIG_FILES=Makefile CONFIG_HEADERS= $(SHELL) ./config.status
+
+pathnames.h: config.status $(srcdir)/Makefile.in
+ CONFIG_HEADERS= $(SHELL) ./config.status
+
+Makefiles makefiles: config.status $(srcdir)/Makefile.in
+ @for mf in $(CREATED_MAKEFILES); do \
+ CONFIG_FILES=$$mf CONFIG_HEADERS= $(SHELL) ./config.status ; \
+ done
+
+config.h: stamp-h
+
+stamp-h: config.status $(srcdir)/config.h.in $(srcdir)/config-top.h $(srcdir)/config-bot.h
+ CONFIG_FILES= CONFIG_HEADERS=config.h $(SHELL) ./config.status
+
+config.status: $(srcdir)/configure
+ $(SHELL) ./config.status --recheck
+
+# comment out for distribution
+$(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4 $(srcdir)/config.h.in
+ cd $(srcdir) && autoconf
+
+# for chet
+reconfig: force
+ sh $(srcdir)/configure -C
+
+#newversion: mkversion
+# $(RM) .build
+# ./mkversion -dir $(srcdir) -dist
+# mv -f newversion.h version.h
+# $(MAKE) -f $(srcdir)/Makefile $(MFLAGS) srcdir=$(srcdir)
+
+doc documentation: force
+ @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) )
+
+info dvi ps: force
+ @(cd $(DOCDIR) ; $(MAKE) $(MFLAGS) CFLAGS='$(CCFLAGS)' $@ )
+
+force:
+
+tags: $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+ etags $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+
+TAGS: $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE)
+ ctags -x $(SOURCES) $(BUILTIN_C_SRC) $(LIBRARY_SOURCE) > $@
+
+# Targets that actually do things not part of the build
+
+installdirs:
+ @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(bindir)
+ @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(man1dir)
+ @${SHELL} $(SUPPORT_SRC)mkinstalldirs $(DESTDIR)$(infodir)
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+install: .made installdirs
+ $(INSTALL_PROGRAM) $(INSTALLMODE) $(Program) $(DESTDIR)$(bindir)/$(Program)
+ $(INSTALL_SCRIPT) $(INSTALLMODE2) bashbug $(DESTDIR)$(bindir)/bashbug
+ -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
+ man1dir=$(man1dir) man1ext=$(man1ext) \
+ man3dir=$(man3dir) man3ext=$(man3ext) \
+ infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+ -( cd $(DEFDIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+install-strip:
+ $(MAKE) $(MFLAGS) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' \
+ prefix=${prefix} exec_prefix=${exec_prefix} \
+ DESTDIR=$(DESTDIR) install
+
+uninstall: .made
+ $(RM) $(DESTDIR)$(bindir)/$(Program) $(DESTDIR)$(bindir)/bashbug
+ -( cd $(DOCDIR) ; $(MAKE) $(MFLAGS) \
+ man1dir=$(man1dir) man1ext=$(man1ext) \
+ man3dir=$(man3dir) man3ext=$(man3ext) \
+ infodir=$(infodir) htmldir=$(htmldir) DESTDIR=$(DESTDIR) $@ )
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+.PHONY: basic-clean clean realclean maintainer-clean distclean mostlyclean maybe-clean
+
+LIB_SUBDIRS = ${RL_LIBDIR} ${HIST_LIBDIR} ${TERM_LIBDIR} ${GLOB_LIBDIR} \
+ ${INTL_LIBDIR} ${TILDE_LIBDIR} ${ALLOC_LIBDIR} ${SH_LIBDIR}
+
+basic-clean:
+ $(RM) $(OBJECTS) $(Program) bashbug
+ $(RM) .build .made version.h
+
+clean: basic-clean
+ ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+ ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+ -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+ -for libdir in ${LIB_SUBDIRS}; do \
+ (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+ done
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+ $(RM) $(CREATED_SUPPORT)
+
+mostlyclean: basic-clean
+ ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+ ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+ -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+ -for libdir in ${LIB_SUBDIRS}; do \
+ (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+ done
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+
+distclean: basic-clean maybe-clean
+ ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+ ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+ -( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+ -for libdir in ${LIB_SUBDIRS}; do \
+ (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+ done
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+ $(RM) $(CREATED_CONFIGURE) tags TAGS
+ $(RM) $(CREATED_SUPPORT) Makefile $(CREATED_MAKEFILES) pathnames.h
+
+maintainer-clean: basic-clean
+ @echo This command is intended for maintainers to use.
+ @echo It deletes files that may require special tools to rebuild.
+ $(RM) y.tab.c y.tab.h parser-built tags TAGS
+ ( cd $(DOCDIR) && $(MAKE) $(MFLAGS) $@ )
+ ( cd builtins && $(MAKE) $(MFLAGS) $@ )
+ ( cd $(SDIR) && $(MAKE) $(MFLAGS) $@ )
+ -for libdir in ${LIB_SUBDIRS}; do \
+ (cd $$libdir && test -f Makefile && $(MAKE) $(MFLAGS) $@) ;\
+ done
+ -( cd $(PO_DIR) ; $(MAKE) $(MFLAGS) DESTDIR=$(DESTDIR) $@ )
+ $(RM) $(CREATED_CONFIGURE) $(CREATED_MAKEFILES)
+ $(RM) $(CREATED_SUPPORT) Makefile pathnames.h
+
+maybe-clean:
+ -if test "X$(topdir)" != "X$(BUILD_DIR)" ; then \
+ $(RM) parser-built y.tab.c y.tab.h ; \
+ fi
+
+recho$(EXEEXT): $(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 ${LIBS_FOR_BUILD}
+
+printenv$(EXEEXT): $(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
+ @cp $(TESTS_SUPPORT) tests
+ @( cd $(srcdir)/tests && \
+ PATH=$(BUILD_DIR)/tests:$$PATH THIS_SH=$(THIS_SH) $(SHELL) ${TESTSCRIPT} )
+
+symlinks:
+ $(SHELL) $(SUPPORT_SRC)fixlinks -s $(srcdir)
+
+dist: force
+ @echo Bash distributions are created using $(srcdir)/support/mkdist.
+ @echo Here is a sample of the necessary commands:
+ @echo $(Program) $(srcdir)/support/mkdist -m $(srcdir)/MANIFEST -s $(srcdir) -r ${PACKAGE} $(PACKAGE_VERSION)
+ @echo tar cf $(PACKAGE)-${PACKAGE_VERSION}.tar ${PACKAGE}-$(PACKAGE_VERSION)
+ @echo gzip $(PACKAGE)-$(PACKAGE_VERSION).tar
+
+depend: depends
+
+depends: force
+ $(Program) $(SUPPORT_SRC)mkdep -c ${CC} -- ${CCFLAGS} ${CSOURCES}
+
+#### PRIVATE TARGETS ####
+hashtest: hashlib.c
+ $(CC) -DTEST_HASHING $(CCFLAGS) -o $@ $(srcdir)/hashlib.c
+
+############################ DEPENDENCIES ###############################
+
+# Files that depend on the definitions in config-top.h, which are not meant
+# to be changed
+shell.o: config-top.h
+input.o: config-top.h
+y.tab.o: config-top.h
+jobs.o: config-top.h
+nojobs.o: config-top.h
+execute_cmd.o: config-top.h
+variables.o: config-top.h
+builtins/command.o: config-top.h
+builtins/common.o: config-top.h
+builtins/break.o: config-top.h
+builtins/echo.o: config-top.h
+builtins/evalstring.o: config-top.h
+builtins/exit.o: config-top.h
+builtins/kill.o: config-top.h
+
+# shell basics
+copy_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+copy_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+copy_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+copy_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+dispose_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h
+dispose_cmd.o: error.h general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+dispose_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+dispose_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+dispose_cmd.o: ${BASHINCDIR}/ocache.h
+error.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h flags.h ${BASHINCDIR}/stdc.h error.h
+error.o: command.h general.h xmalloc.h externs.h input.h bashhist.h
+error.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+error.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+error.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+error.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+error.o: input.h execute_cmd.h
+eval.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h trap.h flags.h ${DEFSRC}/common.h
+eval.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+eval.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+eval.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+eval.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+eval.o: input.h execute_cmd.h
+execute_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+execute_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+execute_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+execute_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+execute_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+execute_cmd.o: ${BASHINCDIR}/memalloc.h ${GRAM_H} flags.h builtins.h jobs.h quit.h siglist.h
+execute_cmd.o: execute_cmd.h findcmd.h redir.h trap.h test.h pathexp.h
+execute_cmd.o: $(DEFSRC)/common.h ${DEFDIR}/builtext.h ${GLOB_LIBSRC}/strmatch.h
+execute_cmd.o: ${BASHINCDIR}/posixtime.h ${BASHINCDIR}/chartypes.h
+expr.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+expr.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+expr.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+expr.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+expr.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+expr.o: ${BASHINCDIR}/chartypes.h
+findcmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h
+findcmd.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h
+findcmd.o: ${BASHINCDIR}/stdc.h error.h general.h xmalloc.h variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
+findcmd.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h
+findcmd.o: flags.h hashlib.h pathexp.h hashcmd.h
+findcmd.o: ${BASHINCDIR}/chartypes.h
+flags.o: config.h flags.h
+flags.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+flags.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+flags.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+flags.o: make_cmd.h subst.h sig.h pathnames.h externs.h bashhist.h
+general.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+general.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+general.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+general.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+general.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+general.o: ${BASHINCDIR}/maxpath.h ${BASHINCDIR}/posixtime.h
+general.o: ${BASHINCDIR}/chartypes.h
+hashcmd.o: config.h ${BASHINCDIR}/posixstat.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+hashcmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+hashcmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashcmd.h
+hashcmd.o: execute_cmd.h findcmd.h ${BASHINCDIR}/stdc.h hashlib.h
+hashlib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+hashlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+hashlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+hashlib.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+hashlib.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+input.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+input.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h input.h error.h externs.h
+list.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+list.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+list.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+list.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+locale.o: config.h bashtypes.h bashintl.h ${LIBINTL_H} bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+locale.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+locale.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+locale.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+locale.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+locale.o: ${BASHINCDIR}/chartypes.h
+mailcheck.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+mailcheck.o: ${BASHINCDIR}/posixtime.h
+mailcheck.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+mailcheck.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+mailcheck.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+mailcheck.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+mailcheck.o: execute_cmd.h mailcheck.h
+make_cmd.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashansi.h
+make_cmd.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h flags.h make_cmd.h
+make_cmd.o: variables.h arrayfunc.h conftypes.h array.h hashlib.h subst.h input.h externs.h
+make_cmd.o: jobs.h quit.h siglist.h syntax.h dispose_cmd.h
+make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/ocache.h
+y.tab.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/memalloc.h
+y.tab.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+y.tab.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+y.tab.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+y.tab.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h
+y.tab.o: trap.h flags.h parser.h input.h mailcheck.h $(DEFSRC)/common.h
+y.tab.o: $(DEFDIR)/builtext.h bashline.h bashhist.h jobs.h siglist.h alias.h
+pathexp.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+pathexp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+pathexp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+pathexp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+pathexp.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+pathexp.o: pathexp.h flags.h
+pathexp.o: $(GLOB_LIBSRC)/glob.h $(GLOB_LIBSRC)/strmatch.h
+pathexp.o: ${BASHINCDIR}/shmbutil.h
+print_cmd.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+print_cmd.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+print_cmd.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+print_cmd.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+print_cmd.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+print_cmd.o: ${GRAM_H} $(DEFSRC)/common.h
+redir.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
+redir.o: ${BASHINCDIR}/memalloc.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+redir.o: general.h xmalloc.h variables.h arrayfunc.h conftypes.h array.h hashlib.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h
+redir.o: dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h externs.h
+redir.o: flags.h execute_cmd.h redir.h input.h
+shell.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/filecntl.h
+shell.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+shell.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+shell.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+shell.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+shell.o: flags.h trap.h mailcheck.h builtins.h $(DEFSRC)/common.h
+shell.o: jobs.h siglist.h input.h execute_cmd.h findcmd.h bashhist.h
+shell.o: ${GLOB_LIBSRC}/strmatch.h ${BASHINCDIR}/posixtime.h
+sig.o: config.h bashtypes.h
+sig.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+sig.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+sig.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+sig.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+sig.o: jobs.h siglist.h trap.h $(DEFSRC)/common.h bashline.h bashhist.h
+siglist.o: config.h bashtypes.h siglist.h trap.h
+stringlib.o: bashtypes.h ${BASHINCDIR}/chartypes.h
+stringlib.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+stringlib.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+stringlib.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+stringlib.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+stringlib.o: ${GLOB_LIBSRC}/glob.h ${GLOB_LIBSRC}/strmatch.h
+subst.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/posixstat.h
+subst.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+subst.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+subst.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+subst.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+subst.o: flags.h jobs.h siglist.h execute_cmd.h ${BASHINCDIR}/filecntl.h trap.h pathexp.h
+subst.o: mailcheck.h input.h $(DEFSRC)/getopt.h $(DEFSRC)/common.h
+subst.o: bashline.h bashhist.h ${GLOB_LIBSRC}/strmatch.h
+subst.o: ${BASHINCDIR}/chartypes.h
+subst.o: ${BASHINCDIR}/shmbutil.h
+test.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+test.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+test.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+test.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+test.o: make_cmd.h subst.h sig.h pathnames.h externs.h test.h
+test.o: ${DEFSRC}/common.h
+trap.o: config.h bashtypes.h trap.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+trap.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+trap.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+trap.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+trap.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+trap.o: signames.h $(DEFSRC)/common.h
+trap.o: ${DEFDIR}/builtext.h
+unwind_prot.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
+unwind_prot.o: general.h xmalloc.h unwind_prot.h quit.h sig.h
+variables.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+variables.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+variables.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+variables.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+variables.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+variables.o: flags.h execute_cmd.h mailcheck.h input.h $(DEFSRC)/common.h
+variables.o: findcmd.h bashhist.h hashcmd.h pathexp.h
+variables.o: pcomplete.h ${BASHINCDIR}/chartypes.h
+variables.o: ${BASHINCDIR}/posixtime.h
+version.o: conftypes.h patchlevel.h version.h
+xmalloc.o: config.h bashtypes.h ${BASHINCDIR}/ansi_stdlib.h error.h
+
+# job control
+
+jobs.o: config.h bashtypes.h trap.h ${BASHINCDIR}/filecntl.h input.h ${BASHINCDIR}/shtty.h
+jobs.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+jobs.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+jobs.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+jobs.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+jobs.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+jobs.o: jobs.h flags.h $(DEFSRC)/common.h $(DEFDIR)/builtext.h
+jobs.o: ${BASHINCDIR}/posixwait.h ${BASHINCDIR}/unionwait.h
+jobs.o: ${BASHINCDIR}/posixtime.h
+nojobs.o: config.h bashtypes.h ${BASHINCDIR}/filecntl.h bashjmp.h ${BASHINCDIR}/posixjmp.h
+nojobs.o: command.h ${BASHINCDIR}/stdc.h general.h xmalloc.h jobs.h quit.h siglist.h externs.h
+nojobs.o: sig.h error.h ${BASHINCDIR}/shtty.h input.h
+
+# shell features that may be compiled in
+
+array.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+array.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+array.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+array.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+array.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+array.o: $(DEFSRC)/common.h
+arrayfunc.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+arrayfunc.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+arrayfunc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+arrayfunc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+arrayfunc.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+arrayfunc.o: $(DEFSRC)/common.h
+arrayfunc.o: ${BASHINCDIR}/shmbutil.h
+braces.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+braces.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+braces.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+braces.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+braces.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+braces.o: ${BASHINCDIR}/shmbutil.h
+alias.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h command.h ${BASHINCDIR}/stdc.h
+alias.o: general.h xmalloc.h bashtypes.h externs.h alias.h
+alias.o: pcomplete.h
+alias.o: ${BASHINCDIR}/chartypes.h
+
+pcomplib.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h bashtypes.h
+pcomplib.o: ${BASHINCDIR}/stdc.h hashlib.h pcomplete.h shell.h syntax.h
+pcomplib.o: bashjmp.h command.h general.h xmalloc.h error.h variables.h arrayfunc.h conftypes.h quit.h
+pcomplib.o: unwind_prot.h dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h
+pcomplib.o: externs.h ${BASHINCDIR}/maxpath.h
+
+pcomplete.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h bashtypes.h
+pcomplete.o: ${BASHINCDIR}/stdc.h hashlib.h pcomplete.h shell.h syntax.h
+pcomplete.o: bashjmp.h command.h general.h xmalloc.h error.h variables.h arrayfunc.h conftypes.h quit.h
+pcomplete.o: unwind_prot.h dispose_cmd.h make_cmd.h subst.h sig.h pathnames.h
+pcomplete.o: externs.h ${BASHINCDIR}/maxpath.h execute_cmd.h
+
+# library support files
+
+bashhist.o: config.h bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/posixstat.h
+bashhist.o: ${BASHINCDIR}/filecntl.h
+bashhist.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bashhist.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bashhist.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bashhist.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+bashhist.o: flags.h input.h parser.h pathexp.h $(DEFSRC)/common.h bashline.h
+bashhist.o: $(GLOB_LIBSRC)/strmatch.h
+bashline.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+bashline.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bashline.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bashline.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bashline.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+bashline.o: builtins.h bashhist.h bashline.h execute_cmd.h findcmd.h pathexp.h
+bashline.o: $(DEFSRC)/common.h $(GLOB_LIBSRC)/glob.h alias.h
+bashline.o: pcomplete.h ${BASHINCDIR}/chartypes.h input.h
+bracecomp.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+bracecomp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h command.h ${BASHINCDIR}/stdc.h error.h
+bracecomp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h array.h hashlib.h
+bracecomp.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+bracecomp.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+bracecomp.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h hashlib.h builtins.h general.h xmalloc.h
+bracecomp.o: quit.h alias.h config.h variables.h arrayfunc.h conftypes.h
+bracecomp.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+
+# library dependencies
+
+bashline.o: $(RL_LIBSRC)/rlconf.h
+bashline.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/rlstdc.h
+bashline.o: $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/readline.h
+bracecomp.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+bracecomp.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+y.tab.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+y.tab.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+subst.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/chardefs.h
+subst.o: $(RL_LIBSRC)/readline.h $(RL_LIBSRC)/rlstdc.h
+
+shell.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+subst.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+bashline.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+bashhist.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+y.tab.o: $(HIST_LIBSRC)/history.h $(HIST_LIBSRC)/rlstdc.h
+
+execute_cmd.o: $(TILDE_LIBSRC)/tilde.h
+general.o: $(TILDE_LIBSRC)/tilde.h
+mailcheck.o: $(TILDE_LIBSRC)/tilde.h
+shell.o: $(TILDE_LIBSRC)/tilde.h
+subst.o: $(TILDE_LIBSRC)/tilde.h
+variables.o: $(TILDE_LIBSRC)/tilde.h
+
+# libintl dependencies
+arrayfunc.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+bashhist.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+bashline.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+braces.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+error.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+eval.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+execute_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+expr.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+general.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+input.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+jobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+mailcheck.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+make_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+nojobs.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+parse.y: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pcomplete.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+pcomplib.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+print_cmd.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+redir.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+shell.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+sig.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+siglist.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+subst.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+test.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+trap.o: bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+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
+builtins/bashgetopt.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/bashgetopt.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/bashgetopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/bashgetopt.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+builtins/bashgetopt.o: $(DEFSRC)/common.h
+builtins/bashgetopt.o: ${BASHINCDIR}/chartypes.h
+builtins/common.o: bashtypes.h ${BASHINCDIR}/posixstat.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/common.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h
+builtins/common.o: ${BASHINCDIR}/memalloc.h variables.h arrayfunc.h conftypes.h input.h siglist.h
+builtins/common.o: quit.h unwind_prot.h ${BASHINCDIR}/maxpath.h jobs.h builtins.h
+builtins/common.o: dispose_cmd.h make_cmd.h subst.h externs.h bashhist.h
+builtins/common.o: execute_cmd.h ${BASHINCDIR}/stdc.h general.h xmalloc.h error.h pathnames.h
+builtins/common.o: ${DEFDIR}/builtext.h
+builtins/common.o: ${BASHINCDIR}/chartypes.h
+builtins/evalfile.o: bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/evalfile.o: shell.h syntax.h config.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/evalfile.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/evalfile.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+builtins/evalfile.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+builtins/evalfile.o: bashhist.h $(DEFSRC)/common.h
+builtins/evalstring.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/evalstring.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h siglist.h
+builtins/evalstring.o: ${BASHINCDIR}/memalloc.h variables.h arrayfunc.h conftypes.h input.h
+builtins/evalstring.o: quit.h unwind_prot.h ${BASHINCDIR}/maxpath.h jobs.h builtins.h
+builtins/evalstring.o: dispose_cmd.h make_cmd.h subst.h externs.h
+builtins/evalstring.o: jobs.h builtins.h flags.h input.h execute_cmd.h
+builtins/evalstring.o: bashhist.h $(DEFSRC)/common.h
+builtins/getopt.o: config.h ${BASHINCDIR}/memalloc.h
+builtins/getopt.o: shell.h syntax.h bashjmp.h command.h general.h xmalloc.h error.h
+builtins/getopt.o: variables.h arrayfunc.h conftypes.h quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
+builtins/getopt.o: make_cmd.h subst.h sig.h pathnames.h externs.h
+builtins/getopt.o: $(DEFSRC)/getopt.h
+builtins/mkbuiltins.o: config.h bashtypes.h ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
+builtins/mkbuiltins.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+
+# builtin def files
+builtins/alias.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/alias.o: quit.h $(DEFSRC)/common.h
+builtins/alias.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h command.h ${BASHINCDIR}/stdc.h unwind_prot.h
+builtins/alias.o: dispose_cmd.h make_cmd.h subst.h externs.h variables.h arrayfunc.h conftypes.h
+builtins/bind.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/bind.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/bind.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/bind.o: $(DEFSRC)/bashgetopt.h
+builtins/break.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/break.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/break.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/builtin.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/builtin.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/builtin.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/builtin.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/caller.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/caller.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/caller.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/caller.o: $(DEFSRC)/common.h quit.h
+builtins/caller.o: ${BASHINCDIR}/chartypes.h bashtypes.h
+builtins/caller.o: ${DEFDIR}/builtext.h
+builtins/cd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/cd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/cd.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/cd.o: $(DEFSRC)/common.h quit.h
+builtins/command.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/command.o: quit.h $(DEFSRC)/bashgetopt.h
+builtins/command.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/command.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/declare.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/declare.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/declare.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/declare.o: $(DEFSRC)/bashgetopt.h
+builtins/echo.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/echo.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/echo.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/enable.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/enable.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/enable.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/enable.o: pcomplete.h
+builtins/eval.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/eval.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/eval.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/exec.o: bashtypes.h
+builtins/exec.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/exec.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/exec.o: dispose_cmd.h make_cmd.h subst.h externs.h execute_cmd.h
+builtins/exec.o: findcmd.h flags.h quit.h $(DEFSRC)/common.h ${BASHINCDIR}/stdc.h
+builtins/exit.o: bashtypes.h
+builtins/exit.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/exit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/exit.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/fc.o: bashtypes.h ${BASHINCDIR}/posixstat.h
+builtins/fc.o: bashansi.h ${BASHINCDIR}/ansi_stdlib.h builtins.h command.h ${BASHINCDIR}/stdc.h
+builtins/fc.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/fc.o: flags.h unwind_prot.h variables.h arrayfunc.h conftypes.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h
+builtins/fc.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h quit.h
+builtins/fc.o: $(DEFSRC)/bashgetopt.h bashhist.h
+builtins/fc.o: ${BASHINCDIR}/chartypes.h
+builtins/fg_bg.o: bashtypes.h $(DEFSRC)/bashgetopt.h
+builtins/fg_bg.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/fg_bg.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/fg_bg.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/getopts.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/getopts.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/getopts.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/hash.o: bashtypes.h
+builtins/hash.o: builtins.h command.h findcmd.h ${BASHINCDIR}/stdc.h $(DEFSRC)/common.h
+builtins/hash.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/hash.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/help.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/help.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/help.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/help.o: $(GLOB_LIBSRC)/glob.h
+builtins/history.o: bashtypes.h
+builtins/history.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/history.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/history.o: ${BASHINCDIR}/filecntl.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h
+builtins/history.o: bashhist.h variables.h arrayfunc.h conftypes.h
+builtins/inlib.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/inlib.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h quit.h
+builtins/inlib.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/jobs.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/jobs.o: quit.h $(DEFSRC)/bashgetopt.h
+builtins/jobs.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/jobs.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/kill.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/kill.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/kill.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h trap.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/let.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/let.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/let.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/printf.o: config.h ${BASHINCDIR}/memalloc.h bashjmp.h command.h error.h
+builtins/printf.o: general.h xmalloc.h quit.h dispose_cmd.h make_cmd.h subst.h
+builtins/printf.o: externs.h sig.h pathnames.h shell.h syntax.h unwind_prot.h
+builtins/printf.o: variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/stdc.h $(DEFSRC)/bashgetopt.h
+builtins/printf.o: ${BASHINCDIR}/chartypes.h
+builtins/pushd.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/pushd.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/pushd.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/pushd.o: $(DEFSRC)/common.h
+builtins/read.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/read.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/read.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/return.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/return.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/return.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/set.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/set.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/set.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h flags.h
+builtins/setattr.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/setattr.o: quit.h $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/setattr.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/setattr.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shift.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/shift.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shift.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/shift.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/shopt.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h
+builtins/shopt.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h
+builtins/shopt.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h unwind_prot.h variables.h arrayfunc.h conftypes.h ${BASHINCDIR}/maxpath.h
+builtins/shopt.o: $(DEFSRC)/common.h $(DEFSRC)/bashgetopt.h
+builtins/source.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/source.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/source.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/source.o: findcmd.h $(DEFSRC)/bashgetopt.h flags.h trap.h
+builtins/suspend.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/suspend.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/suspend.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/test.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/test.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/test.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/test.o: test.h
+builtins/times.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/times.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/times.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/trap.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/trap.o: quit.h $(DEFSRC)/common.h
+builtins/trap.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/trap.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/type.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/type.o: quit.h $(DEFSRC)/common.h findcmd.h
+builtins/type.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/type.o: dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/ulimit.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/ulimit.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/ulimit.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/umask.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/umask.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/umask.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/umask.o: ${BASHINCDIR}/chartypes.h
+builtins/wait.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
+builtins/wait.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
+builtins/wait.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/wait.o: ${BASHINCDIR}/chartypes.h
+
+builtins/complete.o: config.h shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h
+builtins/complete.o: unwind_prot.h variables.h arrayfunc.h conftypes.h
+builtins/complete.o: bashtypes.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
+builtins/complete.o: builtins.h
+builtins/complete.o: pcomplete.h
+builtins/complete.o: ${DEFSRC}/common.h ${DEFSRC}/bashgetopt.h
+
+# libintl dependencies
+builtins/bind.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/break.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/caller.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/cd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/common.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/complete.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/declare.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/enable.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/evalfile.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/exec.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/exit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/fc.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/fg_bg.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/getopt.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/hash.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/help.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/history.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/inlib.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/jobs.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/kill.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/let.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/mkbuiltins.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/printf.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/pushd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/read.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/return.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/set.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/setattr.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/shift.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/shopt.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/source.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/suspend.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/type.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/ulimit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+builtins/umask.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+
+# builtin library dependencies
+builtins/bind.o: $(RL_LIBSRC)/chardefs.h $(RL_LIBSRC)/readline.h
+builtins/bind.o: $(RL_LIBSRC)/keymaps.h $(RL_LIBSRC)/rlstdc.h
+
+builtins/bind.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+builtins/fc.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+builtins/history.o: $(HIST_LIBSRC)/history.h $(RL_LIBSRC)/rlstdc.h
+
+builtins/common.o: $(TILDE_LIBSRC)/tilde.h
+builtins/cd.o: $(TILDE_LIBSRC)/tilde.h
+
+builtins/alias.o: $(DEFSRC)/alias.def
+builtins/bind.o: $(DEFSRC)/bind.def
+builtins/break.o: $(DEFSRC)/break.def
+builtins/builtin.o: $(DEFSRC)/builtin.def
+builtins/caller.o: $(DEFSRC)/caller.def
+builtins/cd.o: $(DEFSRC)/cd.def
+builtins/colon.o: $(DEFSRC)/colon.def
+builtins/command.o: $(DEFSRC)/command.def
+builtins/complete.o: $(DEFSRC)/complete.def
+builtins/declare.o: $(DEFSRC)/declare.def
+builtins/echo.o: $(DEFSRC)/echo.def
+builtins/enable.o: $(DEFSRC)/enable.def
+builtins/eval.o: $(DEFSRC)/eval.def
+builtins/exec.o: $(DEFSRC)/exec.def
+builtins/exit.o: $(DEFSRC)/exit.def
+builtins/fc.o: $(DEFSRC)/fc.def
+builtins/fg_bg.o: $(DEFSRC)/fg_bg.def
+builtins/getopts.o: $(DEFSRC)/getopts.def
+builtins/hash.o: $(DEFSRC)/hash.def
+builtins/help.o: $(DEFSRC)/help.def
+builtins/history.o: $(DEFSRC)/history.def
+builtins/inlib.o: $(DEFSRC)/inlib.def
+builtins/jobs.o: $(DEFSRC)/jobs.def
+builtins/kill.o: $(DEFSRC)/kill.def
+builtins/let.o: $(DEFSRC)/let.def
+builtins/pushd.o: $(DEFSRC)/pushd.def
+builtins/read.o: $(DEFSRC)/read.def
+builtins/reserved.o: $(DEFSRC)/reserved.def
+builtins/return.o: $(DEFSRC)/return.def
+builtins/set.o: $(DEFSRC)/set.def
+builtins/setattr.o: $(DEFSRC)/setattr.def
+builtins/shift.o: $(DEFSRC)/shift.def
+builtins/shopt.o: $(DEFSRC)/shopt.def
+builtins/source.o: $(DEFSRC)/source.def
+builtins/suspend.o: $(DEFSRC)/suspend.def
+builtins/test.o: $(DEFSRC)/test.def
+builtins/times.o: $(DEFSRC)/times.def
+builtins/trap.o: $(DEFSRC)/trap.def
+builtins/type.o: $(DEFSRC)/type.def
+builtins/ulimit.o: $(DEFSRC)/ulimit.def
+builtins/umask.o: $(DEFSRC)/umask.def
+builtins/wait.o: $(DEFSRC)/wait.def
diff --git a/aclocal.m4 b/aclocal.m4
index d21972c5..b9539591 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -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])
diff --git a/aclocal.m4~ b/aclocal.m4~
new file mode 100644
index 00000000..d21972c5
--- /dev/null
+++ b/aclocal.m4~
@@ -0,0 +1,3962 @@
+dnl
+dnl Bash specific tests
+dnl
+dnl Some derived from PDKSH 5.1.3 autoconf tests
+dnl
+
+AC_DEFUN(BASH_C_LONG_LONG,
+[AC_CACHE_CHECK(for long long, ac_cv_c_long_long,
+[if test "$GCC" = yes; then
+ ac_cv_c_long_long=yes
+else
+AC_TRY_RUN([
+int
+main()
+{
+long long foo = 0;
+exit(sizeof(long long) < sizeof(long));
+}
+], ac_cv_c_long_long=yes, ac_cv_c_long_long=no)
+fi])
+if test $ac_cv_c_long_long = yes; then
+ AC_DEFINE(HAVE_LONG_LONG, 1, [Define if the `long long' type works.])
+fi
+])
+
+dnl
+dnl This is very similar to AC_C_LONG_DOUBLE, with the fix for IRIX
+dnl (< changed to <=) added.
+dnl
+AC_DEFUN(BASH_C_LONG_DOUBLE,
+[AC_CACHE_CHECK(for long double, ac_cv_c_long_double,
+[if test "$GCC" = yes; then
+ ac_cv_c_long_double=yes
+else
+AC_TRY_RUN([
+int
+main()
+{
+ /* The Stardent Vistra knows sizeof(long double), but does not
+ support it. */
+ long double foo = 0.0;
+ /* On Ultrix 4.3 cc, long double is 4 and double is 8. */
+ /* On IRIX 5.3, the compiler converts long double to double with a warning,
+ but compiles this successfully. */
+ exit(sizeof(long double) <= sizeof(double));
+}
+], ac_cv_c_long_double=yes, ac_cv_c_long_double=no)
+fi])
+if test $ac_cv_c_long_double = yes; then
+ AC_DEFINE(HAVE_LONG_DOUBLE, 1, [Define if the `long double' type works.])
+fi
+])
+
+dnl
+dnl Check for <inttypes.h>. This is separated out so that it can be
+dnl AC_REQUIREd.
+dnl
+dnl BASH_HEADER_INTTYPES
+AC_DEFUN(BASH_HEADER_INTTYPES,
+[
+ AC_CHECK_HEADERS(inttypes.h)
+])
+
+dnl
+dnl check for typedef'd symbols in header files, but allow the caller to
+dnl specify the include files to be checked in addition to the default
+dnl
+dnl BASH_CHECK_TYPE(TYPE, HEADERS, DEFAULT[, VALUE-IF-FOUND])
+AC_DEFUN(BASH_CHECK_TYPE,
+[
+AC_REQUIRE([AC_HEADER_STDC])dnl
+AC_REQUIRE([BASH_HEADER_INTTYPES])
+AC_MSG_CHECKING(for $1)
+AC_CACHE_VAL(bash_cv_type_$1,
+[AC_EGREP_CPP($1, [#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#if HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+$2
+], bash_cv_type_$1=yes, bash_cv_type_$1=no)])
+AC_MSG_RESULT($bash_cv_type_$1)
+ifelse($#, 4, [if test $bash_cv_type_$1 = yes; then
+ AC_DEFINE($4)
+ fi])
+if test $bash_cv_type_$1 = no; then
+ AC_DEFINE_UNQUOTED($1, $3)
+fi
+])
+
+dnl
+dnl BASH_CHECK_DECL(FUNC)
+dnl
+dnl Check for a declaration of FUNC in stdlib.h and inttypes.h like
+dnl AC_CHECK_DECL
+dnl
+AC_DEFUN(BASH_CHECK_DECL,
+[
+AC_REQUIRE([AC_HEADER_STDC])
+AC_REQUIRE([BASH_HEADER_INTTYPES])
+AC_CACHE_CHECK([for declaration of $1], bash_cv_decl_$1,
+[AC_TRY_LINK(
+[
+#if STDC_HEADERS
+# include <stdlib.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+],
+[return !$1;],
+bash_cv_decl_$1=yes, bash_cv_decl_$1=no)])
+bash_tr_func=HAVE_DECL_`echo $1 | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
+if test $bash_cv_decl_$1 = yes; then
+ AC_DEFINE_UNQUOTED($bash_tr_func, 1)
+else
+ AC_DEFINE_UNQUOTED($bash_tr_func, 0)
+fi
+])
+
+AC_DEFUN(BASH_DECL_PRINTF,
+[AC_MSG_CHECKING(for declaration of printf in <stdio.h>)
+AC_CACHE_VAL(bash_cv_printf_declared,
+[AC_TRY_RUN([
+#include <stdio.h>
+#ifdef __STDC__
+typedef int (*_bashfunc)(const char *, ...);
+#else
+typedef int (*_bashfunc)();
+#endif
+main()
+{
+_bashfunc pf;
+pf = (_bashfunc) printf;
+exit(pf == 0);
+}
+], bash_cv_printf_declared=yes, bash_cv_printf_declared=no,
+ [AC_MSG_WARN(cannot check printf declaration if cross compiling -- defaulting to yes)
+ bash_cv_printf_declared=yes]
+)])
+AC_MSG_RESULT($bash_cv_printf_declared)
+if test $bash_cv_printf_declared = yes; then
+AC_DEFINE(PRINTF_DECLARED)
+fi
+])
+
+AC_DEFUN(BASH_DECL_SBRK,
+[AC_MSG_CHECKING(for declaration of sbrk in <unistd.h>)
+AC_CACHE_VAL(bash_cv_sbrk_declared,
+[AC_EGREP_HEADER(sbrk, unistd.h,
+ bash_cv_sbrk_declared=yes, bash_cv_sbrk_declared=no)])
+AC_MSG_RESULT($bash_cv_sbrk_declared)
+if test $bash_cv_sbrk_declared = yes; then
+AC_DEFINE(SBRK_DECLARED)
+fi
+])
+
+dnl
+dnl Check for sys_siglist[] or _sys_siglist[]
+dnl
+AC_DEFUN(BASH_DECL_UNDER_SYS_SIGLIST,
+[AC_MSG_CHECKING([for _sys_siglist in signal.h or unistd.h])
+AC_CACHE_VAL(bash_cv_decl_under_sys_siglist,
+[AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif], [ char *msg = _sys_siglist[2]; ],
+ bash_cv_decl_under_sys_siglist=yes, bash_cv_decl_under_sys_siglist=no,
+ [AC_MSG_WARN(cannot check for _sys_siglist[] if cross compiling -- defaulting to no)])])dnl
+AC_MSG_RESULT($bash_cv_decl_under_sys_siglist)
+if test $bash_cv_decl_under_sys_siglist = yes; then
+AC_DEFINE(UNDER_SYS_SIGLIST_DECLARED)
+fi
+])
+
+AC_DEFUN(BASH_UNDER_SYS_SIGLIST,
+[AC_REQUIRE([BASH_DECL_UNDER_SYS_SIGLIST])
+AC_MSG_CHECKING([for _sys_siglist in system C library])
+AC_CACHE_VAL(bash_cv_under_sys_siglist,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifndef UNDER_SYS_SIGLIST_DECLARED
+extern char *_sys_siglist[];
+#endif
+main()
+{
+char *msg = (char *)_sys_siglist[2];
+exit(msg == 0);
+}],
+ bash_cv_under_sys_siglist=yes, bash_cv_under_sys_siglist=no,
+ [AC_MSG_WARN(cannot check for _sys_siglist[] if cross compiling -- defaulting to no)
+ bash_cv_under_sys_siglist=no])])
+AC_MSG_RESULT($bash_cv_under_sys_siglist)
+if test $bash_cv_under_sys_siglist = yes; then
+AC_DEFINE(HAVE_UNDER_SYS_SIGLIST)
+fi
+])
+
+AC_DEFUN(BASH_SYS_SIGLIST,
+[AC_REQUIRE([AC_DECL_SYS_SIGLIST])
+AC_MSG_CHECKING([for sys_siglist in system C library])
+AC_CACHE_VAL(bash_cv_sys_siglist,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifndef SYS_SIGLIST_DECLARED
+extern char *sys_siglist[];
+#endif
+main()
+{
+char *msg = sys_siglist[2];
+exit(msg == 0);
+}],
+ bash_cv_sys_siglist=yes, bash_cv_sys_siglist=no,
+ [AC_MSG_WARN(cannot check for sys_siglist if cross compiling -- defaulting to no)
+ bash_cv_sys_siglist=no])])
+AC_MSG_RESULT($bash_cv_sys_siglist)
+if test $bash_cv_sys_siglist = yes; then
+AC_DEFINE(HAVE_SYS_SIGLIST)
+fi
+])
+
+dnl Check for the various permutations of sys_siglist and make sure we
+dnl compile in siglist.o if they're not defined
+AC_DEFUN(BASH_CHECK_SYS_SIGLIST, [
+AC_REQUIRE([BASH_SYS_SIGLIST])
+AC_REQUIRE([BASH_DECL_UNDER_SYS_SIGLIST])
+AC_REQUIRE([BASH_FUNC_STRSIGNAL])
+if test "$bash_cv_sys_siglist" = no && test "$bash_cv_under_sys_siglist" = no && test "$bash_cv_have_strsignal" = no; then
+ SIGLIST_O=siglist.o
+else
+ SIGLIST_O=
+fi
+AC_SUBST([SIGLIST_O])
+])
+
+dnl Check for sys_errlist[] and sys_nerr, check for declaration
+AC_DEFUN(BASH_SYS_ERRLIST,
+[AC_MSG_CHECKING([for sys_errlist and sys_nerr])
+AC_CACHE_VAL(bash_cv_sys_errlist,
+[AC_TRY_LINK([#include <errno.h>],
+[extern char *sys_errlist[];
+ extern int sys_nerr;
+ char *msg = sys_errlist[sys_nerr - 1];],
+ bash_cv_sys_errlist=yes, bash_cv_sys_errlist=no)])dnl
+AC_MSG_RESULT($bash_cv_sys_errlist)
+if test $bash_cv_sys_errlist = yes; then
+AC_DEFINE(HAVE_SYS_ERRLIST)
+fi
+])
+
+dnl
+dnl Check if dup2() does not clear the close on exec flag
+dnl
+AC_DEFUN(BASH_FUNC_DUP2_CLOEXEC_CHECK,
+[AC_MSG_CHECKING(if dup2 fails to clear the close-on-exec flag)
+AC_CACHE_VAL(bash_cv_dup2_broken,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <fcntl.h>
+main()
+{
+ int fd1, fd2, fl;
+ fd1 = open("/dev/null", 2);
+ if (fcntl(fd1, 2, 1) < 0)
+ exit(1);
+ fd2 = dup2(fd1, 1);
+ if (fd2 < 0)
+ exit(2);
+ fl = fcntl(fd2, 1, 0);
+ /* fl will be 1 if dup2 did not reset the close-on-exec flag. */
+ exit(fl != 1);
+}
+], bash_cv_dup2_broken=yes, bash_cv_dup2_broken=no,
+ [AC_MSG_WARN(cannot check dup2 if cross compiling -- defaulting to no)
+ bash_cv_dup2_broken=no])
+])
+AC_MSG_RESULT($bash_cv_dup2_broken)
+if test $bash_cv_dup2_broken = yes; then
+AC_DEFINE(DUP2_BROKEN)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_STRSIGNAL,
+[AC_MSG_CHECKING([for the existence of strsignal])
+AC_CACHE_VAL(bash_cv_have_strsignal,
+[AC_TRY_LINK([#include <sys/types.h>
+#include <signal.h>],
+[char *s = (char *)strsignal(2);],
+ bash_cv_have_strsignal=yes, bash_cv_have_strsignal=no)])
+AC_MSG_RESULT($bash_cv_have_strsignal)
+if test $bash_cv_have_strsignal = yes; then
+AC_DEFINE(HAVE_STRSIGNAL)
+fi
+])
+
+dnl Check to see if opendir will open non-directories (not a nice thing)
+AC_DEFUN(BASH_FUNC_OPENDIR_CHECK,
+[AC_REQUIRE([AC_HEADER_DIRENT])dnl
+AC_MSG_CHECKING(if opendir() opens non-directories)
+AC_CACHE_VAL(bash_cv_opendir_not_robust,
+[AC_TRY_RUN([
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#else
+# define dirent direct
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif /* SYSNDIR */
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif /* SYSDIR */
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif /* HAVE_DIRENT_H */
+main()
+{
+DIR *dir;
+int fd, err;
+err = mkdir("/tmp/bash-aclocal", 0700);
+if (err < 0) {
+ perror("mkdir");
+ exit(1);
+}
+unlink("/tmp/bash-aclocal/not_a_directory");
+fd = open("/tmp/bash-aclocal/not_a_directory", O_WRONLY|O_CREAT|O_EXCL, 0666);
+write(fd, "\n", 1);
+close(fd);
+dir = opendir("/tmp/bash-aclocal/not_a_directory");
+unlink("/tmp/bash-aclocal/not_a_directory");
+rmdir("/tmp/bash-aclocal");
+exit (dir == 0);
+}], bash_cv_opendir_not_robust=yes,bash_cv_opendir_not_robust=no,
+ [AC_MSG_WARN(cannot check opendir if cross compiling -- defaulting to no)
+ bash_cv_opendir_not_robust=no]
+)])
+AC_MSG_RESULT($bash_cv_opendir_not_robust)
+if test $bash_cv_opendir_not_robust = yes; then
+AC_DEFINE(OPENDIR_NOT_ROBUST)
+fi
+])
+
+dnl
+AC_DEFUN(BASH_TYPE_SIGHANDLER,
+[AC_MSG_CHECKING([whether signal handlers are of type void])
+AC_CACHE_VAL(bash_cv_void_sighandler,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C"
+#endif
+void (*signal ()) ();],
+[int i;], bash_cv_void_sighandler=yes, bash_cv_void_sighandler=no)])dnl
+AC_MSG_RESULT($bash_cv_void_sighandler)
+if test $bash_cv_void_sighandler = yes; then
+AC_DEFINE(VOID_SIGHANDLER)
+fi
+])
+
+dnl
+dnl A signed 16-bit integer quantity
+dnl
+AC_DEFUN(BASH_TYPE_BITS16_T,
+[
+if test "$ac_cv_sizeof_short" = 2; then
+ AC_CHECK_TYPE(bits16_t, short)
+elif test "$ac_cv_sizeof_char" = 2; then
+ AC_CHECK_TYPE(bits16_t, char)
+else
+ AC_CHECK_TYPE(bits16_t, short)
+fi
+])
+
+dnl
+dnl An unsigned 16-bit integer quantity
+dnl
+AC_DEFUN(BASH_TYPE_U_BITS16_T,
+[
+if test "$ac_cv_sizeof_short" = 2; then
+ AC_CHECK_TYPE(u_bits16_t, unsigned short)
+elif test "$ac_cv_sizeof_char" = 2; then
+ AC_CHECK_TYPE(u_bits16_t, unsigned char)
+else
+ AC_CHECK_TYPE(u_bits16_t, unsigned short)
+fi
+])
+
+dnl
+dnl A signed 32-bit integer quantity
+dnl
+AC_DEFUN(BASH_TYPE_BITS32_T,
+[
+if test "$ac_cv_sizeof_int" = 4; then
+ AC_CHECK_TYPE(bits32_t, int)
+elif test "$ac_cv_sizeof_long" = 4; then
+ AC_CHECK_TYPE(bits32_t, long)
+else
+ AC_CHECK_TYPE(bits32_t, int)
+fi
+])
+
+dnl
+dnl An unsigned 32-bit integer quantity
+dnl
+AC_DEFUN(BASH_TYPE_U_BITS32_T,
+[
+if test "$ac_cv_sizeof_int" = 4; then
+ AC_CHECK_TYPE(u_bits32_t, unsigned int)
+elif test "$ac_cv_sizeof_long" = 4; then
+ AC_CHECK_TYPE(u_bits32_t, unsigned long)
+else
+ AC_CHECK_TYPE(u_bits32_t, unsigned int)
+fi
+])
+
+AC_DEFUN(BASH_TYPE_PTRDIFF_T,
+[
+if test "$ac_cv_sizeof_int" = "$ac_cv_sizeof_char_p"; then
+ AC_CHECK_TYPE(ptrdiff_t, int)
+elif test "$ac_cv_sizeof_long" = "$ac_cv_sizeof_char_p"; then
+ AC_CHECK_TYPE(ptrdiff_t, long)
+elif test "$ac_cv_type_long_long" = yes && test "$ac_cv_sizeof_long_long" = "$ac_cv_sizeof_char_p"; then
+ AC_CHECK_TYPE(ptrdiff_t, [long long])
+else
+ AC_CHECK_TYPE(ptrdiff_t, int)
+fi
+])
+
+dnl
+dnl A signed 64-bit quantity
+dnl
+AC_DEFUN(BASH_TYPE_BITS64_T,
+[
+if test "$ac_cv_sizeof_char_p" = 8; then
+ AC_CHECK_TYPE(bits64_t, char *)
+elif test "$ac_cv_sizeof_double" = 8; then
+ AC_CHECK_TYPE(bits64_t, double)
+elif test -n "$ac_cv_type_long_long" && test "$ac_cv_sizeof_long_long" = 8; then
+ AC_CHECK_TYPE(bits64_t, [long long])
+elif test "$ac_cv_sizeof_long" = 8; then
+ AC_CHECK_TYPE(bits64_t, long)
+else
+ AC_CHECK_TYPE(bits64_t, double)
+fi
+])
+
+AC_DEFUN(BASH_TYPE_LONG_LONG,
+[
+AC_CACHE_CHECK([for long long], bash_cv_type_long_long,
+[AC_TRY_LINK([
+long long ll = 1; int i = 63;],
+[
+long long llm = (long long) -1;
+return ll << i | ll >> i | llm / ll | llm % ll;
+], bash_cv_type_long_long='long long', bash_cv_type_long_long='long')])
+if test "$bash_cv_type_long_long" = 'long long'; then
+ AC_DEFINE(HAVE_LONG_LONG, 1)
+fi
+])
+
+AC_DEFUN(BASH_TYPE_UNSIGNED_LONG_LONG,
+[
+AC_CACHE_CHECK([for unsigned long long], bash_cv_type_unsigned_long_long,
+[AC_TRY_LINK([
+unsigned long long ull = 1; int i = 63;],
+[
+unsigned long long ullmax = (unsigned long long) -1;
+return ull << i | ull >> i | ullmax / ull | ullmax % ull;
+], bash_cv_type_unsigned_long_long='unsigned long long',
+ bash_cv_type_unsigned_long_long='unsigned long')])
+if test "$bash_cv_type_unsigned_long_long" = 'unsigned long long'; then
+ AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1)
+fi
+])
+
+dnl
+dnl Type of struct rlimit fields: some systems (OSF/1, NetBSD, RISC/os 5.0)
+dnl have a rlim_t, others (4.4BSD based systems) use quad_t, others use
+dnl long and still others use int (HP-UX 9.01, SunOS 4.1.3). To simplify
+dnl matters, this just checks for rlim_t, quad_t, or long.
+dnl
+AC_DEFUN(BASH_TYPE_RLIMIT,
+[AC_MSG_CHECKING(for size and type of struct rlimit fields)
+AC_CACHE_VAL(bash_cv_type_rlimit,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/resource.h>],
+[rlim_t xxx;], bash_cv_type_rlimit=rlim_t,[
+AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+main()
+{
+#ifdef HAVE_QUAD_T
+ struct rlimit rl;
+ if (sizeof(rl.rlim_cur) == sizeof(quad_t))
+ exit(0);
+#endif
+ exit(1);
+}], bash_cv_type_rlimit=quad_t, bash_cv_type_rlimit=long,
+ [AC_MSG_WARN(cannot check quad_t if cross compiling -- defaulting to long)
+ bash_cv_type_rlimit=long])])
+])
+AC_MSG_RESULT($bash_cv_type_rlimit)
+if test $bash_cv_type_rlimit = quad_t; then
+AC_DEFINE(RLIMTYPE, quad_t)
+elif test $bash_cv_type_rlimit = rlim_t; then
+AC_DEFINE(RLIMTYPE, rlim_t)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_LSTAT,
+[dnl Cannot use AC_CHECK_FUNCS(lstat) because Linux defines lstat() as an
+dnl inline function in <sys/stat.h>.
+AC_CACHE_CHECK([for lstat], bash_cv_func_lstat,
+[AC_TRY_LINK([
+#include <sys/types.h>
+#include <sys/stat.h>
+],[ lstat(".",(struct stat *)0); ],
+bash_cv_func_lstat=yes, bash_cv_func_lstat=no)])
+if test $bash_cv_func_lstat = yes; then
+ AC_DEFINE(HAVE_LSTAT)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_INET_ATON,
+[
+AC_CACHE_CHECK([for inet_aton], bash_cv_func_inet_aton,
+[AC_TRY_LINK([
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+struct in_addr ap;], [ inet_aton("127.0.0.1", &ap); ],
+bash_cv_func_inet_aton=yes, bash_cv_func_inet_aton=no)])
+if test $bash_cv_func_inet_aton = yes; then
+ AC_DEFINE(HAVE_INET_ATON)
+else
+ AC_LIBOBJ(inet_aton)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_GETENV,
+[AC_MSG_CHECKING(to see if getenv can be redefined)
+AC_CACHE_VAL(bash_cv_getenv_redef,
+[AC_TRY_RUN([
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#ifndef __STDC__
+# ifndef const
+# define const
+# endif
+#endif
+char *
+getenv (name)
+#if defined (__linux__) || defined (__bsdi__) || defined (convex)
+ const char *name;
+#else
+ char const *name;
+#endif /* !__linux__ && !__bsdi__ && !convex */
+{
+return "42";
+}
+main()
+{
+char *s;
+/* The next allows this program to run, but does not allow bash to link
+ when it redefines getenv. I'm not really interested in figuring out
+ why not. */
+#if defined (NeXT)
+exit(1);
+#endif
+s = getenv("ABCDE");
+exit(s == 0); /* force optimizer to leave getenv in */
+}
+], bash_cv_getenv_redef=yes, bash_cv_getenv_redef=no,
+ [AC_MSG_WARN(cannot check getenv redefinition if cross compiling -- defaulting to yes)
+ bash_cv_getenv_redef=yes]
+)])
+AC_MSG_RESULT($bash_cv_getenv_redef)
+if test $bash_cv_getenv_redef = yes; then
+AC_DEFINE(CAN_REDEFINE_GETENV)
+fi
+])
+
+# We should check for putenv before calling this
+AC_DEFUN(BASH_FUNC_STD_PUTENV,
+[
+AC_REQUIRE([AC_HEADER_STDC])
+AC_REQUIRE([AC_C_PROTOTYPES])
+AC_CACHE_CHECK([for standard-conformant putenv declaration], bash_cv_std_putenv,
+[AC_TRY_LINK([
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifndef __STDC__
+# ifndef const
+# define const
+# endif
+#endif
+#ifdef PROTOTYPES
+extern int putenv (char *);
+#else
+extern int putenv ();
+#endif
+],
+[return (putenv == 0);],
+bash_cv_std_putenv=yes, bash_cv_std_putenv=no
+)])
+if test $bash_cv_std_putenv = yes; then
+AC_DEFINE(HAVE_STD_PUTENV)
+fi
+])
+
+# We should check for unsetenv before calling this
+AC_DEFUN(BASH_FUNC_STD_UNSETENV,
+[
+AC_REQUIRE([AC_HEADER_STDC])
+AC_REQUIRE([AC_C_PROTOTYPES])
+AC_CACHE_CHECK([for standard-conformant unsetenv declaration], bash_cv_std_unsetenv,
+[AC_TRY_LINK([
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#ifndef __STDC__
+# ifndef const
+# define const
+# endif
+#endif
+#ifdef PROTOTYPES
+extern int unsetenv (const char *);
+#else
+extern int unsetenv ();
+#endif
+],
+[return (unsetenv == 0);],
+bash_cv_std_unsetenv=yes, bash_cv_std_unsetenv=no
+)])
+if test $bash_cv_std_unsetenv = yes; then
+AC_DEFINE(HAVE_STD_UNSETENV)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_ULIMIT_MAXFDS,
+[AC_MSG_CHECKING(whether ulimit can substitute for getdtablesize)
+AC_CACHE_VAL(bash_cv_ulimit_maxfds,
+[AC_TRY_RUN([
+main()
+{
+long maxfds = ulimit(4, 0L);
+exit (maxfds == -1L);
+}
+], bash_cv_ulimit_maxfds=yes, bash_cv_ulimit_maxfds=no,
+ [AC_MSG_WARN(cannot check ulimit if cross compiling -- defaulting to no)
+ bash_cv_ulimit_maxfds=no]
+)])
+AC_MSG_RESULT($bash_cv_ulimit_maxfds)
+if test $bash_cv_ulimit_maxfds = yes; then
+AC_DEFINE(ULIMIT_MAXFDS)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_GETCWD,
+[AC_MSG_CHECKING([if getcwd() will dynamically allocate memory])
+AC_CACHE_VAL(bash_cv_getcwd_malloc,
+[AC_TRY_RUN([
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+main()
+{
+ char *xpwd;
+ xpwd = getcwd(0, 0);
+ exit (xpwd == 0);
+}
+], bash_cv_getcwd_malloc=yes, bash_cv_getcwd_malloc=no,
+ [AC_MSG_WARN(cannot check whether getcwd allocates memory when cross-compiling -- defaulting to no)
+ bash_cv_getcwd_malloc=no]
+)])
+AC_MSG_RESULT($bash_cv_getcwd_malloc)
+if test $bash_cv_getcwd_malloc = no; then
+AC_DEFINE(GETCWD_BROKEN)
+AC_LIBOBJ(getcwd)
+fi
+])
+
+dnl
+dnl This needs BASH_CHECK_SOCKLIB, but since that's not called on every
+dnl system, we can't use AC_PREREQ
+dnl
+AC_DEFUN(BASH_FUNC_GETHOSTBYNAME,
+[if test "X$bash_cv_have_gethostbyname" = "X"; then
+_bash_needmsg=yes
+else
+AC_MSG_CHECKING(for gethostbyname in socket library)
+_bash_needmsg=
+fi
+AC_CACHE_VAL(bash_cv_have_gethostbyname,
+[AC_TRY_LINK([#include <netdb.h>],
+[ struct hostent *hp;
+ hp = gethostbyname("localhost");
+], bash_cv_have_gethostbyname=yes, bash_cv_have_gethostbyname=no)]
+)
+if test "X$_bash_needmsg" = Xyes; then
+ AC_MSG_CHECKING(for gethostbyname in socket library)
+fi
+AC_MSG_RESULT($bash_cv_have_gethostbyname)
+if test "$bash_cv_have_gethostbyname" = yes; then
+AC_DEFINE(HAVE_GETHOSTBYNAME)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_FNMATCH_EXTMATCH,
+[AC_MSG_CHECKING(if fnmatch does extended pattern matching with FNM_EXTMATCH)
+AC_CACHE_VAL(bash_cv_fnm_extmatch,
+[AC_TRY_RUN([
+#include <fnmatch.h>
+
+main()
+{
+#ifdef FNM_EXTMATCH
+ exit (0);
+#else
+ exit (1);
+#endif
+}
+], bash_cv_fnm_extmatch=yes, bash_cv_fnm_extmatch=no,
+ [AC_MSG_WARN(cannot check FNM_EXTMATCH if cross compiling -- defaulting to no)
+ bash_cv_fnm_extmatch=no])
+])
+AC_MSG_RESULT($bash_cv_fnm_extmatch)
+if test $bash_cv_fnm_extmatch = yes; then
+AC_DEFINE(HAVE_LIBC_FNM_EXTMATCH)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_POSIX_SETJMP,
+[AC_REQUIRE([BASH_SYS_SIGNAL_VINTAGE])
+AC_MSG_CHECKING(for presence of POSIX-style sigsetjmp/siglongjmp)
+AC_CACHE_VAL(bash_cv_func_sigsetjmp,
+[AC_TRY_RUN([
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+#include <signal.h>
+#include <setjmp.h>
+
+main()
+{
+#if !defined (_POSIX_VERSION) || !defined (HAVE_POSIX_SIGNALS)
+exit (1);
+#else
+
+int code;
+sigset_t set, oset;
+sigjmp_buf xx;
+
+/* get the mask */
+sigemptyset(&set);
+sigemptyset(&oset);
+sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &set);
+sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &oset);
+
+/* save it */
+code = sigsetjmp(xx, 1);
+if (code)
+ exit(0); /* could get sigmask and compare to oset here. */
+
+/* change it */
+sigaddset(&set, SIGINT);
+sigprocmask(SIG_BLOCK, &set, (sigset_t *)NULL);
+
+/* and siglongjmp */
+siglongjmp(xx, 10);
+exit(1);
+#endif
+}], bash_cv_func_sigsetjmp=present, bash_cv_func_sigsetjmp=missing,
+ [AC_MSG_WARN(cannot check for sigsetjmp/siglongjmp if cross-compiling -- defaulting to missing)
+ bash_cv_func_sigsetjmp=missing]
+)])
+AC_MSG_RESULT($bash_cv_func_sigsetjmp)
+if test $bash_cv_func_sigsetjmp = present; then
+AC_DEFINE(HAVE_POSIX_SIGSETJMP)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_STRCOLL,
+[
+AC_MSG_CHECKING(whether or not strcoll and strcmp differ)
+AC_CACHE_VAL(bash_cv_func_strcoll_broken,
+[AC_TRY_RUN([
+#include <stdio.h>
+#if defined (HAVE_LOCALE_H)
+#include <locale.h>
+#endif
+
+main(c, v)
+int c;
+char *v[];
+{
+ int r1, r2;
+ char *deflocale, *defcoll;
+
+#ifdef HAVE_SETLOCALE
+ deflocale = setlocale(LC_ALL, "");
+ defcoll = setlocale(LC_COLLATE, "");
+#endif
+
+#ifdef HAVE_STRCOLL
+ /* These two values are taken from tests/glob-test. */
+ r1 = strcoll("abd", "aXd");
+#else
+ r1 = 0;
+#endif
+ r2 = strcmp("abd", "aXd");
+
+ /* These two should both be greater than 0. It is permissible for
+ a system to return different values, as long as the sign is the
+ same. */
+
+ /* Exit with 1 (failure) if these two values are both > 0, since
+ this tests whether strcoll(3) is broken with respect to strcmp(3)
+ in the default locale. */
+ exit (r1 > 0 && r2 > 0);
+}
+], bash_cv_func_strcoll_broken=yes, bash_cv_func_strcoll_broken=no,
+ [AC_MSG_WARN(cannot check strcoll if cross compiling -- defaulting to no)
+ bash_cv_func_strcoll_broken=no]
+)])
+AC_MSG_RESULT($bash_cv_func_strcoll_broken)
+if test $bash_cv_func_strcoll_broken = yes; then
+AC_DEFINE(STRCOLL_BROKEN)
+fi
+])
+
+AC_DEFUN(BASH_FUNC_PRINTF_A_FORMAT,
+[AC_MSG_CHECKING([for printf floating point output in hex notation])
+AC_CACHE_VAL(bash_cv_printf_a_format,
+[AC_TRY_RUN([
+#include <stdio.h>
+#include <string.h>
+
+int
+main()
+{
+ double y = 0.0;
+ char abuf[1024];
+
+ sprintf(abuf, "%A", y);
+ exit(strchr(abuf, 'P') == (char *)0);
+}
+], bash_cv_printf_a_format=yes, bash_cv_printf_a_format=no,
+ [AC_MSG_WARN(cannot check printf if cross compiling -- defaulting to no)
+ bash_cv_printf_a_format=no]
+)])
+AC_MSG_RESULT($bash_cv_printf_a_format)
+if test $bash_cv_printf_a_format = yes; then
+AC_DEFINE(HAVE_PRINTF_A_FORMAT)
+fi
+])
+
+AC_DEFUN(BASH_STRUCT_TERMIOS_LDISC,
+[
+AC_CHECK_MEMBER(struct termios.c_line, AC_DEFINE(TERMIOS_LDISC), ,[
+#include <sys/types.h>
+#include <termios.h>
+])
+])
+
+AC_DEFUN(BASH_STRUCT_TERMIO_LDISC,
+[
+AC_CHECK_MEMBER(struct termio.c_line, AC_DEFINE(TERMIO_LDISC), ,[
+#include <sys/types.h>
+#include <termio.h>
+])
+])
+
+dnl
+dnl Like AC_STRUCT_ST_BLOCKS, but doesn't muck with LIBOBJS
+dnl
+dnl sets bash_cv_struct_stat_st_blocks
+dnl
+dnl unused for now; we'll see how AC_CHECK_MEMBERS works
+dnl
+AC_DEFUN(BASH_STRUCT_ST_BLOCKS,
+[
+AC_MSG_CHECKING([for struct stat.st_blocks])
+AC_CACHE_VAL(bash_cv_struct_stat_st_blocks,
+[AC_TRY_COMPILE(
+[
+#include <sys/types.h>
+#include <sys/stat.h>
+],
+[
+main()
+{
+static struct stat a;
+if (a.st_blocks) return 0;
+return 0;
+}
+], bash_cv_struct_stat_st_blocks=yes, bash_cv_struct_stat_st_blocks=no)
+])
+AC_MSG_RESULT($bash_cv_struct_stat_st_blocks)
+if test "$bash_cv_struct_stat_st_blocks" = "yes"; then
+AC_DEFINE(HAVE_STRUCT_STAT_ST_BLOCKS)
+fi
+])
+
+AC_DEFUN(BASH_CHECK_LIB_TERMCAP,
+[
+if test "X$bash_cv_termcap_lib" = "X"; then
+_bash_needmsg=yes
+else
+AC_MSG_CHECKING(which library has the termcap functions)
+_bash_needmsg=
+fi
+AC_CACHE_VAL(bash_cv_termcap_lib,
+[AC_CHECK_FUNC(tgetent, bash_cv_termcap_lib=libc,
+ [AC_CHECK_LIB(termcap, tgetent, bash_cv_termcap_lib=libtermcap,
+ [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
+ [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
+ [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
+ bash_cv_termcap_lib=gnutermcap)])])])])])
+if test "X$_bash_needmsg" = "Xyes"; then
+AC_MSG_CHECKING(which library has the termcap functions)
+fi
+AC_MSG_RESULT(using $bash_cv_termcap_lib)
+if test $bash_cv_termcap_lib = gnutermcap && test -z "$prefer_curses"; then
+LDFLAGS="$LDFLAGS -L./lib/termcap"
+TERMCAP_LIB="./lib/termcap/libtermcap.a"
+TERMCAP_DEP="./lib/termcap/libtermcap.a"
+elif test $bash_cv_termcap_lib = libtermcap && test -z "$prefer_curses"; then
+TERMCAP_LIB=-ltermcap
+TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libtinfo; then
+TERMCAP_LIB=-ltinfo
+TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libncurses; then
+TERMCAP_LIB=-lncurses
+TERMCAP_DEP=
+elif test $bash_cv_termcap_lib = libc; then
+TERMCAP_LIB=
+TERMCAP_DEP=
+else
+TERMCAP_LIB=-lcurses
+TERMCAP_DEP=
+fi
+])
+
+dnl
+dnl Check for the presence of getpeername in libsocket.
+dnl If libsocket is present, check for libnsl and add it to LIBS if
+dnl it's there, since most systems with libsocket require linking
+dnl with libnsl as well. This should only be called if getpeername
+dnl was not found in libc.
+dnl
+dnl NOTE: IF WE FIND GETPEERNAME, WE ASSUME THAT WE HAVE BIND/CONNECT
+dnl AS WELL
+dnl
+AC_DEFUN(BASH_CHECK_LIB_SOCKET,
+[
+if test "X$bash_cv_have_socklib" = "X"; then
+_bash_needmsg=
+else
+AC_MSG_CHECKING(for socket library)
+_bash_needmsg=yes
+fi
+AC_CACHE_VAL(bash_cv_have_socklib,
+[AC_CHECK_LIB(socket, getpeername,
+ bash_cv_have_socklib=yes, bash_cv_have_socklib=no, -lnsl)])
+if test "X$_bash_needmsg" = Xyes; then
+ AC_MSG_RESULT($bash_cv_have_socklib)
+ _bash_needmsg=
+fi
+if test $bash_cv_have_socklib = yes; then
+ # check for libnsl, add it to LIBS if present
+ if test "X$bash_cv_have_libnsl" = "X"; then
+ _bash_needmsg=
+ else
+ AC_MSG_CHECKING(for libnsl)
+ _bash_needmsg=yes
+ fi
+ AC_CACHE_VAL(bash_cv_have_libnsl,
+ [AC_CHECK_LIB(nsl, t_open,
+ bash_cv_have_libnsl=yes, bash_cv_have_libnsl=no)])
+ if test "X$_bash_needmsg" = Xyes; then
+ AC_MSG_RESULT($bash_cv_have_libnsl)
+ _bash_needmsg=
+ fi
+ if test $bash_cv_have_libnsl = yes; then
+ LIBS="-lsocket -lnsl $LIBS"
+ else
+ LIBS="-lsocket $LIBS"
+ fi
+ AC_DEFINE(HAVE_LIBSOCKET)
+ AC_DEFINE(HAVE_GETPEERNAME)
+fi
+])
+
+AC_DEFUN(BASH_STRUCT_DIRENT_D_INO,
+[AC_REQUIRE([AC_HEADER_DIRENT])
+AC_MSG_CHECKING(for struct dirent.d_ino)
+AC_CACHE_VAL(bash_cv_dirent_has_dino,
+[AC_TRY_COMPILE([
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#else
+# define dirent direct
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif /* SYSNDIR */
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif /* SYSDIR */
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif /* HAVE_DIRENT_H */
+],[
+struct dirent d; int z; z = d.d_ino;
+], bash_cv_dirent_has_dino=yes, bash_cv_dirent_has_dino=no)])
+AC_MSG_RESULT($bash_cv_dirent_has_dino)
+if test $bash_cv_dirent_has_dino = yes; then
+AC_DEFINE(HAVE_STRUCT_DIRENT_D_INO)
+fi
+])
+
+AC_DEFUN(BASH_STRUCT_DIRENT_D_FILENO,
+[AC_REQUIRE([AC_HEADER_DIRENT])
+AC_MSG_CHECKING(for struct dirent.d_fileno)
+AC_CACHE_VAL(bash_cv_dirent_has_d_fileno,
+[AC_TRY_COMPILE([
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#else
+# define dirent direct
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif /* SYSNDIR */
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif /* SYSDIR */
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif /* HAVE_DIRENT_H */
+],[
+struct dirent d; int z; z = d.d_fileno;
+], bash_cv_dirent_has_d_fileno=yes, bash_cv_dirent_has_d_fileno=no)])
+AC_MSG_RESULT($bash_cv_dirent_has_d_fileno)
+if test $bash_cv_dirent_has_d_fileno = yes; then
+AC_DEFINE(HAVE_STRUCT_DIRENT_D_FILENO)
+fi
+])
+
+AC_DEFUN(BASH_STRUCT_DIRENT_D_NAMLEN,
+[AC_REQUIRE([AC_HEADER_DIRENT])
+AC_MSG_CHECKING(for struct dirent.d_namlen)
+AC_CACHE_VAL(bash_cv_dirent_has_d_namlen,
+[AC_TRY_COMPILE([
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#else
+# define dirent direct
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif /* SYSNDIR */
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif /* SYSDIR */
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif /* HAVE_DIRENT_H */
+],[
+struct dirent d; int z; z = d.d_namlen;
+], bash_cv_dirent_has_d_namlen=yes, bash_cv_dirent_has_d_namlen=no)])
+AC_MSG_RESULT($bash_cv_dirent_has_d_namlen)
+if test $bash_cv_dirent_has_d_namlen = yes; then
+AC_DEFINE(HAVE_STRUCT_DIRENT_D_NAMLEN)
+fi
+])
+
+AC_DEFUN(BASH_STRUCT_TIMEVAL,
+[AC_MSG_CHECKING(for struct timeval in sys/time.h and time.h)
+AC_CACHE_VAL(bash_cv_struct_timeval,
+[
+AC_EGREP_HEADER(struct timeval, sys/time.h,
+ bash_cv_struct_timeval=yes,
+ AC_EGREP_HEADER(struct timeval, time.h,
+ bash_cv_struct_timeval=yes,
+ bash_cv_struct_timeval=no))
+])
+AC_MSG_RESULT($bash_cv_struct_timeval)
+if test $bash_cv_struct_timeval = yes; then
+ AC_DEFINE(HAVE_TIMEVAL)
+fi
+])
+
+AC_DEFUN(BASH_STRUCT_TIMEZONE,
+[AC_MSG_CHECKING(for struct timezone in sys/time.h and time.h)
+AC_CACHE_VAL(bash_cv_struct_timezone,
+[
+AC_EGREP_HEADER(struct timezone, sys/time.h,
+ bash_cv_struct_timezone=yes,
+ AC_EGREP_HEADER(struct timezone, time.h,
+ bash_cv_struct_timezone=yes,
+ bash_cv_struct_timezone=no))
+])
+AC_MSG_RESULT($bash_cv_struct_timezone)
+if test $bash_cv_struct_timezone = yes; then
+ AC_DEFINE(HAVE_STRUCT_TIMEZONE)
+fi
+])
+
+AC_DEFUN(BASH_STRUCT_WINSIZE,
+[AC_MSG_CHECKING(for struct winsize in sys/ioctl.h and termios.h)
+AC_CACHE_VAL(bash_cv_struct_winsize_header,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/ioctl.h>], [struct winsize x;],
+ bash_cv_struct_winsize_header=ioctl_h,
+ [AC_TRY_COMPILE([#include <sys/types.h>
+#include <termios.h>], [struct winsize x;],
+ bash_cv_struct_winsize_header=termios_h, bash_cv_struct_winsize_header=other)
+])])
+if test $bash_cv_struct_winsize_header = ioctl_h; then
+ AC_MSG_RESULT(sys/ioctl.h)
+ AC_DEFINE(STRUCT_WINSIZE_IN_SYS_IOCTL)
+elif test $bash_cv_struct_winsize_header = termios_h; then
+ AC_MSG_RESULT(termios.h)
+ AC_DEFINE(STRUCT_WINSIZE_IN_TERMIOS)
+else
+ AC_MSG_RESULT(not found)
+fi
+])
+
+dnl Check type of signal routines (posix, 4.2bsd, 4.1bsd or v7)
+AC_DEFUN(BASH_SYS_SIGNAL_VINTAGE,
+[AC_REQUIRE([AC_TYPE_SIGNAL])
+AC_MSG_CHECKING(for type of signal functions)
+AC_CACHE_VAL(bash_cv_signal_vintage,
+[
+ AC_TRY_LINK([#include <signal.h>],[
+ sigset_t ss;
+ struct sigaction sa;
+ sigemptyset(&ss); sigsuspend(&ss);
+ sigaction(SIGINT, &sa, (struct sigaction *) 0);
+ sigprocmask(SIG_BLOCK, &ss, (sigset_t *) 0);
+ ], bash_cv_signal_vintage=posix,
+ [
+ AC_TRY_LINK([#include <signal.h>], [
+ int mask = sigmask(SIGINT);
+ sigsetmask(mask); sigblock(mask); sigpause(mask);
+ ], bash_cv_signal_vintage=4.2bsd,
+ [
+ AC_TRY_LINK([
+ #include <signal.h>
+ RETSIGTYPE foo() { }], [
+ int mask = sigmask(SIGINT);
+ sigset(SIGINT, foo); sigrelse(SIGINT);
+ sighold(SIGINT); sigpause(SIGINT);
+ ], bash_cv_signal_vintage=svr3, bash_cv_signal_vintage=v7
+ )]
+ )]
+)
+])
+AC_MSG_RESULT($bash_cv_signal_vintage)
+if test "$bash_cv_signal_vintage" = posix; then
+AC_DEFINE(HAVE_POSIX_SIGNALS)
+elif test "$bash_cv_signal_vintage" = "4.2bsd"; then
+AC_DEFINE(HAVE_BSD_SIGNALS)
+elif test "$bash_cv_signal_vintage" = svr3; then
+AC_DEFINE(HAVE_USG_SIGHOLD)
+fi
+])
+
+dnl Check if the pgrp of setpgrp() can't be the pid of a zombie process.
+AC_DEFUN(BASH_SYS_PGRP_SYNC,
+[AC_REQUIRE([AC_FUNC_GETPGRP])
+AC_MSG_CHECKING(whether pgrps need synchronization)
+AC_CACHE_VAL(bash_cv_pgrp_pipe,
+[AC_TRY_RUN([
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+main()
+{
+# ifdef GETPGRP_VOID
+# define getpgID() getpgrp()
+# else
+# define getpgID() getpgrp(0)
+# define setpgid(x,y) setpgrp(x,y)
+# endif
+ int pid1, pid2, fds[2];
+ int status;
+ char ok;
+
+ switch (pid1 = fork()) {
+ case -1:
+ exit(1);
+ case 0:
+ setpgid(0, getpid());
+ exit(0);
+ }
+ setpgid(pid1, pid1);
+
+ sleep(2); /* let first child die */
+
+ if (pipe(fds) < 0)
+ exit(2);
+
+ switch (pid2 = fork()) {
+ case -1:
+ exit(3);
+ case 0:
+ setpgid(0, pid1);
+ ok = getpgID() == pid1;
+ write(fds[1], &ok, 1);
+ exit(0);
+ }
+ setpgid(pid2, pid1);
+
+ close(fds[1]);
+ if (read(fds[0], &ok, 1) != 1)
+ exit(4);
+ wait(&status);
+ wait(&status);
+ exit(ok ? 0 : 5);
+}
+], bash_cv_pgrp_pipe=no,bash_cv_pgrp_pipe=yes,
+ [AC_MSG_WARN(cannot check pgrp synchronization if cross compiling -- defaulting to no)
+ bash_cv_pgrp_pipe=no])
+])
+AC_MSG_RESULT($bash_cv_pgrp_pipe)
+if test $bash_cv_pgrp_pipe = yes; then
+AC_DEFINE(PGRP_PIPE)
+fi
+])
+
+AC_DEFUN(BASH_SYS_REINSTALL_SIGHANDLERS,
+[AC_REQUIRE([AC_TYPE_SIGNAL])
+AC_REQUIRE([BASH_SYS_SIGNAL_VINTAGE])
+AC_MSG_CHECKING([if signal handlers must be reinstalled when invoked])
+AC_CACHE_VAL(bash_cv_must_reinstall_sighandlers,
+[AC_TRY_RUN([
+#include <signal.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+typedef RETSIGTYPE sigfunc();
+
+int nsigint;
+
+#ifdef HAVE_POSIX_SIGNALS
+sigfunc *
+set_signal_handler(sig, handler)
+ int sig;
+ sigfunc *handler;
+{
+ struct sigaction act, oact;
+ act.sa_handler = handler;
+ act.sa_flags = 0;
+ sigemptyset (&act.sa_mask);
+ sigemptyset (&oact.sa_mask);
+ sigaction (sig, &act, &oact);
+ return (oact.sa_handler);
+}
+#else
+#define set_signal_handler(s, h) signal(s, h)
+#endif
+
+RETSIGTYPE
+sigint(s)
+int s;
+{
+ nsigint++;
+}
+
+main()
+{
+ nsigint = 0;
+ set_signal_handler(SIGINT, sigint);
+ kill((int)getpid(), SIGINT);
+ kill((int)getpid(), SIGINT);
+ exit(nsigint != 2);
+}
+], bash_cv_must_reinstall_sighandlers=no, bash_cv_must_reinstall_sighandlers=yes,
+ [AC_MSG_WARN(cannot check signal handling if cross compiling -- defaulting to no)
+ bash_cv_must_reinstall_sighandlers=no]
+)])
+AC_MSG_RESULT($bash_cv_must_reinstall_sighandlers)
+if test $bash_cv_must_reinstall_sighandlers = yes; then
+AC_DEFINE(MUST_REINSTALL_SIGHANDLERS)
+fi
+])
+
+dnl check that some necessary job control definitions are present
+AC_DEFUN(BASH_SYS_JOB_CONTROL_MISSING,
+[AC_REQUIRE([BASH_SYS_SIGNAL_VINTAGE])
+AC_MSG_CHECKING(for presence of necessary job control definitions)
+AC_CACHE_VAL(bash_cv_job_control_missing,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <signal.h>
+
+/* Add more tests in here as appropriate. */
+main()
+{
+/* signal type */
+#if !defined (HAVE_POSIX_SIGNALS) && !defined (HAVE_BSD_SIGNALS)
+exit(1);
+#endif
+
+/* signals and tty control. */
+#if !defined (SIGTSTP) || !defined (SIGSTOP) || !defined (SIGCONT)
+exit (1);
+#endif
+
+/* process control */
+#if !defined (WNOHANG) || !defined (WUNTRACED)
+exit(1);
+#endif
+
+/* Posix systems have tcgetpgrp and waitpid. */
+#if defined (_POSIX_VERSION) && !defined (HAVE_TCGETPGRP)
+exit(1);
+#endif
+
+#if defined (_POSIX_VERSION) && !defined (HAVE_WAITPID)
+exit(1);
+#endif
+
+/* Other systems have TIOCSPGRP/TIOCGPRGP and wait3. */
+#if !defined (_POSIX_VERSION) && !defined (HAVE_WAIT3)
+exit(1);
+#endif
+
+exit(0);
+}], bash_cv_job_control_missing=present, bash_cv_job_control_missing=missing,
+ [AC_MSG_WARN(cannot check job control if cross-compiling -- defaulting to missing)
+ bash_cv_job_control_missing=missing]
+)])
+AC_MSG_RESULT($bash_cv_job_control_missing)
+if test $bash_cv_job_control_missing = missing; then
+AC_DEFINE(JOB_CONTROL_MISSING)
+fi
+])
+
+dnl check whether named pipes are present
+dnl this requires a previous check for mkfifo, but that is awkward to specify
+AC_DEFUN(BASH_SYS_NAMED_PIPES,
+[AC_MSG_CHECKING(for presence of named pipes)
+AC_CACHE_VAL(bash_cv_sys_named_pipes,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Add more tests in here as appropriate. */
+main()
+{
+int fd, err;
+
+#if defined (HAVE_MKFIFO)
+exit (0);
+#endif
+
+#if !defined (S_IFIFO) && (defined (_POSIX_VERSION) && !defined (S_ISFIFO))
+exit (1);
+#endif
+
+#if defined (NeXT)
+exit (1);
+#endif
+err = mkdir("/tmp/bash-aclocal", 0700);
+if (err < 0) {
+ perror ("mkdir");
+ exit(1);
+}
+fd = mknod ("/tmp/bash-aclocal/sh-np-autoconf", 0666 | S_IFIFO, 0);
+if (fd == -1) {
+ rmdir ("/tmp/bash-aclocal");
+ exit (1);
+}
+close(fd);
+unlink ("/tmp/bash-aclocal/sh-np-autoconf");
+rmdir ("/tmp/bash-aclocal");
+exit(0);
+}], bash_cv_sys_named_pipes=present, bash_cv_sys_named_pipes=missing,
+ [AC_MSG_WARN(cannot check for named pipes if cross-compiling -- defaulting to missing)
+ bash_cv_sys_named_pipes=missing]
+)])
+AC_MSG_RESULT($bash_cv_sys_named_pipes)
+if test $bash_cv_sys_named_pipes = missing; then
+AC_DEFINE(NAMED_PIPES_MISSING)
+fi
+])
+
+AC_DEFUN(BASH_SYS_DEFAULT_MAIL_DIR,
+[AC_MSG_CHECKING(for default mail directory)
+AC_CACHE_VAL(bash_cv_mail_dir,
+[if test -d /var/mail; then
+ bash_cv_mail_dir=/var/mail
+ elif test -d /var/spool/mail; then
+ bash_cv_mail_dir=/var/spool/mail
+ elif test -d /usr/mail; then
+ bash_cv_mail_dir=/usr/mail
+ elif test -d /usr/spool/mail; then
+ bash_cv_mail_dir=/usr/spool/mail
+ else
+ bash_cv_mail_dir=unknown
+ fi
+])
+AC_MSG_RESULT($bash_cv_mail_dir)
+AC_DEFINE_UNQUOTED(DEFAULT_MAIL_DIRECTORY, "$bash_cv_mail_dir")
+])
+
+AC_DEFUN(BASH_HAVE_TIOCGWINSZ,
+[AC_MSG_CHECKING(for TIOCGWINSZ in sys/ioctl.h)
+AC_CACHE_VAL(bash_cv_tiocgwinsz_in_ioctl,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/ioctl.h>], [int x = TIOCGWINSZ;],
+ bash_cv_tiocgwinsz_in_ioctl=yes,bash_cv_tiocgwinsz_in_ioctl=no)])
+AC_MSG_RESULT($bash_cv_tiocgwinsz_in_ioctl)
+if test $bash_cv_tiocgwinsz_in_ioctl = yes; then
+AC_DEFINE(GWINSZ_IN_SYS_IOCTL)
+fi
+])
+
+AC_DEFUN(BASH_HAVE_TIOCSTAT,
+[AC_MSG_CHECKING(for TIOCSTAT in sys/ioctl.h)
+AC_CACHE_VAL(bash_cv_tiocstat_in_ioctl,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/ioctl.h>], [int x = TIOCSTAT;],
+ bash_cv_tiocstat_in_ioctl=yes,bash_cv_tiocstat_in_ioctl=no)])
+AC_MSG_RESULT($bash_cv_tiocstat_in_ioctl)
+if test $bash_cv_tiocstat_in_ioctl = yes; then
+AC_DEFINE(TIOCSTAT_IN_SYS_IOCTL)
+fi
+])
+
+AC_DEFUN(BASH_HAVE_FIONREAD,
+[AC_MSG_CHECKING(for FIONREAD in sys/ioctl.h)
+AC_CACHE_VAL(bash_cv_fionread_in_ioctl,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/ioctl.h>], [int x = FIONREAD;],
+ bash_cv_fionread_in_ioctl=yes,bash_cv_fionread_in_ioctl=no)])
+AC_MSG_RESULT($bash_cv_fionread_in_ioctl)
+if test $bash_cv_fionread_in_ioctl = yes; then
+AC_DEFINE(FIONREAD_IN_SYS_IOCTL)
+fi
+])
+
+dnl
+dnl See if speed_t is declared in <sys/types.h>. Some versions of linux
+dnl require a definition of speed_t each time <termcap.h> is included,
+dnl but you can only get speed_t if you include <termios.h> (on some
+dnl versions) or <sys/types.h> (on others).
+dnl
+AC_DEFUN(BASH_CHECK_SPEED_T,
+[AC_MSG_CHECKING(for speed_t in sys/types.h)
+AC_CACHE_VAL(bash_cv_speed_t_in_sys_types,
+[AC_TRY_COMPILE([#include <sys/types.h>], [speed_t x;],
+ bash_cv_speed_t_in_sys_types=yes,bash_cv_speed_t_in_sys_types=no)])
+AC_MSG_RESULT($bash_cv_speed_t_in_sys_types)
+if test $bash_cv_speed_t_in_sys_types = yes; then
+AC_DEFINE(SPEED_T_IN_SYS_TYPES)
+fi
+])
+
+AC_DEFUN(BASH_CHECK_GETPW_FUNCS,
+[AC_MSG_CHECKING(whether getpw functions are declared in pwd.h)
+AC_CACHE_VAL(bash_cv_getpw_declared,
+[AC_EGREP_CPP(getpwuid,
+[
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <pwd.h>
+],
+bash_cv_getpw_declared=yes,bash_cv_getpw_declared=no)])
+AC_MSG_RESULT($bash_cv_getpw_declared)
+if test $bash_cv_getpw_declared = yes; then
+AC_DEFINE(HAVE_GETPW_DECLS)
+fi
+])
+
+AC_DEFUN(BASH_CHECK_DEV_FD,
+[AC_MSG_CHECKING(whether /dev/fd is available)
+AC_CACHE_VAL(bash_cv_dev_fd,
+[if test -d /dev/fd && test -r /dev/fd/0 < /dev/null; then
+# check for systems like FreeBSD 5 that only provide /dev/fd/[012]
+ exec 3<&0
+ if test -r /dev/fd/3; then
+ bash_cv_dev_fd=standard
+ else
+ bash_cv_dev_fd=absent
+ fi
+ exec 3<&-
+ elif test -d /proc/self/fd && test -r /proc/self/fd/0 < /dev/null; then
+ bash_cv_dev_fd=whacky
+ else
+ bash_cv_dev_fd=absent
+ fi
+])
+AC_MSG_RESULT($bash_cv_dev_fd)
+if test $bash_cv_dev_fd = "standard"; then
+ AC_DEFINE(HAVE_DEV_FD)
+ AC_DEFINE(DEV_FD_PREFIX, "/dev/fd/")
+elif test $bash_cv_dev_fd = "whacky"; then
+ AC_DEFINE(HAVE_DEV_FD)
+ AC_DEFINE(DEV_FD_PREFIX, "/proc/self/fd/")
+fi
+])
+
+AC_DEFUN(BASH_CHECK_DEV_STDIN,
+[AC_MSG_CHECKING(whether /dev/stdin stdout stderr are available)
+AC_CACHE_VAL(bash_cv_dev_stdin,
+[if test -d /dev/fd && test -r /dev/stdin < /dev/null; then
+ bash_cv_dev_stdin=present
+ elif test -d /proc/self/fd && test -r /dev/stdin < /dev/null; then
+ bash_cv_dev_stdin=present
+ else
+ bash_cv_dev_stdin=absent
+ fi
+])
+AC_MSG_RESULT($bash_cv_dev_stdin)
+if test $bash_cv_dev_stdin = "present"; then
+ AC_DEFINE(HAVE_DEV_STDIN)
+fi
+])
+
+dnl
+dnl Check if HPUX needs _KERNEL defined for RLIMIT_* definitions
+dnl
+AC_DEFUN(BASH_CHECK_KERNEL_RLIMIT,
+[AC_MSG_CHECKING([whether $host_os needs _KERNEL for RLIMIT defines])
+AC_CACHE_VAL(bash_cv_kernel_rlimit,
+[AC_TRY_COMPILE([
+#include <sys/types.h>
+#include <sys/resource.h>
+],
+[
+ int f;
+ f = RLIMIT_DATA;
+], bash_cv_kernel_rlimit=no,
+[AC_TRY_COMPILE([
+#include <sys/types.h>
+#define _KERNEL
+#include <sys/resource.h>
+#undef _KERNEL
+],
+[
+ int f;
+ f = RLIMIT_DATA;
+], bash_cv_kernel_rlimit=yes, bash_cv_kernel_rlimit=no)]
+)])
+AC_MSG_RESULT($bash_cv_kernel_rlimit)
+if test $bash_cv_kernel_rlimit = yes; then
+AC_DEFINE(RLIMIT_NEEDS_KERNEL)
+fi
+])
+
+dnl
+dnl Check for 64-bit off_t -- used for malloc alignment
+dnl
+dnl C does not allow duplicate case labels, so the compile will fail if
+dnl sizeof(off_t) is > 4.
+dnl
+AC_DEFUN(BASH_CHECK_OFF_T_64,
+[AC_CACHE_CHECK(for 64-bit off_t, bash_cv_off_t_64,
+AC_TRY_COMPILE([
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <sys/types.h>
+],[
+switch (0) case 0: case (sizeof (off_t) <= 4):;
+], bash_cv_off_t_64=no, bash_cv_off_t_64=yes))
+if test $bash_cv_off_t_64 = yes; then
+ AC_DEFINE(HAVE_OFF_T_64)
+fi])
+
+AC_DEFUN(BASH_CHECK_RTSIGS,
+[AC_MSG_CHECKING(for unusable real-time signals due to large values)
+AC_CACHE_VAL(bash_cv_unusable_rtsigs,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <signal.h>
+
+#ifndef NSIG
+# define NSIG 64
+#endif
+
+main ()
+{
+ int n_sigs = 2 * NSIG;
+#ifdef SIGRTMIN
+ int rtmin = SIGRTMIN;
+#else
+ int rtmin = 0;
+#endif
+
+ exit(rtmin < n_sigs);
+}], bash_cv_unusable_rtsigs=yes, bash_cv_unusable_rtsigs=no,
+ [AC_MSG_WARN(cannot check real-time signals if cross compiling -- defaulting to yes)
+ bash_cv_unusable_rtsigs=yes]
+)])
+AC_MSG_RESULT($bash_cv_unusable_rtsigs)
+if test $bash_cv_unusable_rtsigs = yes; then
+AC_DEFINE(UNUSABLE_RT_SIGNALS)
+fi
+])
+
+dnl
+dnl check for availability of multibyte characters and functions
+dnl
+dnl geez, I wish I didn't have to check for all of this stuff separately
+dnl
+AC_DEFUN(BASH_CHECK_MULTIBYTE,
+[
+AC_CHECK_HEADERS(wctype.h)
+AC_CHECK_HEADERS(wchar.h)
+AC_CHECK_HEADERS(langinfo.h)
+
+AC_CHECK_FUNC(mbsrtowcs, AC_DEFINE(HAVE_MBSRTOWCS))
+AC_CHECK_FUNC(mbrtowc, AC_DEFINE(HAVE_MBRTOWC))
+AC_CHECK_FUNC(mbrlen, AC_DEFINE(HAVE_MBRLEN))
+AC_CHECK_FUNC(wctomb, AC_DEFINE(HAVE_WCTOMB))
+AC_CHECK_FUNC(wcwidth, AC_DEFINE(HAVE_WCWIDTH))
+AC_CHECK_FUNC(wcsdup, AC_DEFINE(HAVE_WCSDUP))
+AC_CHECK_FUNC(wctype, AC_DEFINE(HAVE_WCTYPE))
+
+AC_CACHE_CHECK([for mbstate_t], bash_cv_have_mbstate_t,
+[AC_TRY_COMPILE([
+#include <wchar.h>], [
+ mbstate_t ps;
+ mbstate_t *psp;
+ psp = (mbstate_t *)0;
+], bash_cv_have_mbstate_t=yes, bash_cv_have_mbstate_t=no)])
+if test $bash_cv_have_mbstate_t = yes; then
+ AC_DEFINE(HAVE_MBSTATE_T)
+fi
+
+AC_CACHE_CHECK([for nl_langinfo and CODESET], bash_cv_langinfo_codeset,
+[AC_TRY_LINK(
+[#include <langinfo.h>],
+[char* cs = nl_langinfo(CODESET);],
+bash_cv_langinfo_codeset=yes, bash_cv_langinfo_codeset=no)])
+if test $bash_cv_langinfo_codeset = yes; then
+ AC_DEFINE(HAVE_LANGINFO_CODESET)
+fi
+
+])
+
+dnl need: prefix exec_prefix libdir includedir CC TERMCAP_LIB
+dnl require:
+dnl AC_PROG_CC
+dnl BASH_CHECK_LIB_TERMCAP
+
+AC_DEFUN(RL_LIB_READLINE_VERSION,
+[
+AC_REQUIRE([BASH_CHECK_LIB_TERMCAP])
+
+AC_MSG_CHECKING([version of installed readline library])
+
+# What a pain in the ass this is.
+
+# save cpp and ld options
+_save_CFLAGS="$CFLAGS"
+_save_LDFLAGS="$LDFLAGS"
+_save_LIBS="$LIBS"
+
+# Don't set ac_cv_rl_prefix if the caller has already assigned a value. This
+# allows the caller to do something like $_rl_prefix=$withval if the user
+# specifies --with-installed-readline=PREFIX as an argument to configure
+
+if test -z "$ac_cv_rl_prefix"; then
+test "x$prefix" = xNONE && ac_cv_rl_prefix=$ac_default_prefix || ac_cv_rl_prefix=${prefix}
+fi
+
+eval ac_cv_rl_includedir=${ac_cv_rl_prefix}/include
+eval ac_cv_rl_libdir=${ac_cv_rl_prefix}/lib
+
+LIBS="$LIBS -lreadline ${TERMCAP_LIB}"
+CFLAGS="$CFLAGS -I${ac_cv_rl_includedir}"
+LDFLAGS="$LDFLAGS -L${ac_cv_rl_libdir}"
+
+AC_CACHE_VAL(ac_cv_rl_version,
+[AC_TRY_RUN([
+#include <stdio.h>
+#include <readline/readline.h>
+
+extern int rl_gnu_readline_p;
+
+main()
+{
+ FILE *fp;
+ fp = fopen("conftest.rlv", "w");
+ if (fp == 0)
+ exit(1);
+ if (rl_gnu_readline_p != 1)
+ fprintf(fp, "0.0\n");
+ else
+ fprintf(fp, "%s\n", rl_library_version ? rl_library_version : "0.0");
+ fclose(fp);
+ exit(0);
+}
+],
+ac_cv_rl_version=`cat conftest.rlv`,
+ac_cv_rl_version='0.0',
+ac_cv_rl_version='4.2')])
+
+CFLAGS="$_save_CFLAGS"
+LDFLAGS="$_save_LDFLAGS"
+LIBS="$_save_LIBS"
+
+RL_MAJOR=0
+RL_MINOR=0
+
+# (
+case "$ac_cv_rl_version" in
+2*|3*|4*|5*|6*|7*|8*|9*)
+ RL_MAJOR=`echo $ac_cv_rl_version | sed 's:\..*$::'`
+ RL_MINOR=`echo $ac_cv_rl_version | sed -e 's:^.*\.::' -e 's:[[a-zA-Z]]*$::'`
+ ;;
+esac
+
+# (((
+case $RL_MAJOR in
+[[0-9][0-9]]) _RL_MAJOR=$RL_MAJOR ;;
+[[0-9]]) _RL_MAJOR=0$RL_MAJOR ;;
+*) _RL_MAJOR=00 ;;
+esac
+
+# (((
+case $RL_MINOR in
+[[0-9][0-9]]) _RL_MINOR=$RL_MINOR ;;
+[[0-9]]) _RL_MINOR=0$RL_MINOR ;;
+*) _RL_MINOR=00 ;;
+esac
+
+RL_VERSION="0x${_RL_MAJOR}${_RL_MINOR}"
+
+# Readline versions greater than 4.2 have these defines in readline.h
+
+if test $ac_cv_rl_version = '0.0' ; then
+ AC_MSG_WARN([Could not test version of installed readline library.])
+elif test $RL_MAJOR -gt 4 || { test $RL_MAJOR = 4 && test $RL_MINOR -gt 2 ; } ; then
+ # set these for use by the caller
+ RL_PREFIX=$ac_cv_rl_prefix
+ RL_LIBDIR=$ac_cv_rl_libdir
+ RL_INCLUDEDIR=$ac_cv_rl_includedir
+ AC_MSG_RESULT($ac_cv_rl_version)
+else
+
+AC_DEFINE_UNQUOTED(RL_READLINE_VERSION, $RL_VERSION, [encoded version of the installed readline library])
+AC_DEFINE_UNQUOTED(RL_VERSION_MAJOR, $RL_MAJOR, [major version of installed readline library])
+AC_DEFINE_UNQUOTED(RL_VERSION_MINOR, $RL_MINOR, [minor version of installed readline library])
+
+AC_SUBST(RL_VERSION)
+AC_SUBST(RL_MAJOR)
+AC_SUBST(RL_MINOR)
+
+# set these for use by the caller
+RL_PREFIX=$ac_cv_rl_prefix
+RL_LIBDIR=$ac_cv_rl_libdir
+RL_INCLUDEDIR=$ac_cv_rl_includedir
+
+AC_MSG_RESULT($ac_cv_rl_version)
+
+fi
+])
+
+AC_DEFUN(BASH_FUNC_CTYPE_NONASCII,
+[
+AC_MSG_CHECKING(whether the ctype macros accept non-ascii characters)
+AC_CACHE_VAL(bash_cv_func_ctype_nonascii,
+[AC_TRY_RUN([
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+#include <stdio.h>
+#include <ctype.h>
+
+main(c, v)
+int c;
+char *v[];
+{
+ char *deflocale;
+ unsigned char x;
+ int r1, r2;
+
+#ifdef HAVE_SETLOCALE
+ /* We take a shot here. If that locale is not known, try the
+ system default. We try this one because '\342' (226) is
+ known to be a printable character in that locale. */
+ deflocale = setlocale(LC_ALL, "en_US.ISO8859-1");
+ if (deflocale == 0)
+ deflocale = setlocale(LC_ALL, "");
+#endif
+
+ x = '\342';
+ r1 = isprint(x);
+ x -= 128;
+ r2 = isprint(x);
+ exit (r1 == 0 || r2 == 0);
+}
+], bash_cv_func_ctype_nonascii=yes, bash_cv_func_ctype_nonascii=no,
+ [AC_MSG_WARN(cannot check ctype macros if cross compiling -- defaulting to no)
+ bash_cv_func_ctype_nonascii=no]
+)])
+AC_MSG_RESULT($bash_cv_func_ctype_nonascii)
+if test $bash_cv_func_ctype_nonascii = yes; then
+AC_DEFINE(CTYPE_NON_ASCII)
+fi
+])
+
+AC_DEFUN(BASH_CHECK_WCONTINUED,
+[
+AC_MSG_CHECKING(whether WCONTINUED flag to waitpid is unavailable or available but broken)
+AC_CACHE_VAL(bash_cv_wcontinued_broken,
+[AC_TRY_RUN([
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef errno
+extern int errno;
+#endif
+main()
+{
+ int x;
+
+ x = waitpid(-1, (int *)0, WNOHANG|WCONTINUED);
+ if (x == -1 && errno == EINVAL)
+ exit (1);
+ else
+ exit (0);
+}
+], bash_cv_wcontinued_broken=no,bash_cv_wcontinued_broken=yes,
+ [AC_MSG_WARN(cannot check WCONTINUED if cross compiling -- defaulting to no)
+ bash_cv_wcontinued_broken=no]
+)])
+AC_MSG_RESULT($bash_cv_wcontinued_broken)
+if test $bash_cv_wcontinued_broken = yes; then
+AC_DEFINE(WCONTINUED_BROKEN)
+fi
+])
+
+dnl
+dnl tests added for bashdb
+dnl
+
+
+AC_DEFUN([AM_PATH_LISPDIR],
+ [AC_ARG_WITH(lispdir, AC_HELP_STRING([--with-lispdir], [override the default lisp directory]),
+ [ lispdir="$withval"
+ AC_MSG_CHECKING([where .elc files should go])
+ AC_MSG_RESULT([$lispdir])],
+ [
+ # If set to t, that means we are running in a shell under Emacs.
+ # If you have an Emacs named "t", then use the full path.
+ test x"$EMACS" = xt && EMACS=
+ AC_CHECK_PROGS(EMACS, emacs xemacs, no)
+ if test $EMACS != "no"; then
+ if test x${lispdir+set} != xset; then
+ AC_CACHE_CHECK([where .elc files should go], [am_cv_lispdir], [dnl
+ am_cv_lispdir=`$EMACS -batch -q -eval '(while load-path (princ (concat (car load-path) "\n")) (setq load-path (cdr load-path)))' | sed -n -e 's,/$,,' -e '/.*\/lib\/\(x\?emacs\/site-lisp\)$/{s,,${libdir}/\1,;p;q;}' -e '/.*\/share\/\(x\?emacs\/site-lisp\)$/{s,,${datadir}/\1,;p;q;}'`
+ if test -z "$am_cv_lispdir"; then
+ am_cv_lispdir='${datadir}/emacs/site-lisp'
+ fi
+ ])
+ lispdir="$am_cv_lispdir"
+ fi
+ fi
+ ])
+ AC_SUBST(lispdir)
+])
+
+dnl
+dnl tests added for gettext
+dnl
+# codeset.m4 serial AM1 (gettext-0.10.40)
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_LANGINFO_CODESET],
+[
+ AC_CACHE_CHECK([for nl_langinfo and CODESET], am_cv_langinfo_codeset,
+ [AC_TRY_LINK([#include <langinfo.h>],
+ [char* cs = nl_langinfo(CODESET);],
+ am_cv_langinfo_codeset=yes,
+ am_cv_langinfo_codeset=no)
+ ])
+ if test $am_cv_langinfo_codeset = yes; then
+ AC_DEFINE(HAVE_LANGINFO_CODESET, 1,
+ [Define if you have <langinfo.h> and nl_langinfo(CODESET).])
+ fi
+])
+# gettext.m4 serial 20 (gettext-0.12)
+dnl Copyright (C) 1995-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
+dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
+
+dnl Macro to add for using GNU gettext.
+
+dnl Usage: AM_GNU_GETTEXT([INTLSYMBOL], [NEEDSYMBOL], [INTLDIR]).
+dnl INTLSYMBOL can be one of 'external', 'no-libtool', 'use-libtool'. The
+dnl default (if it is not specified or empty) is 'no-libtool'.
+dnl INTLSYMBOL should be 'external' for packages with no intl directory,
+dnl and 'no-libtool' or 'use-libtool' for packages with an intl directory.
+dnl If INTLSYMBOL is 'use-libtool', then a libtool library
+dnl $(top_builddir)/intl/libintl.la will be created (shared and/or static,
+dnl depending on --{enable,disable}-{shared,static} and on the presence of
+dnl AM-DISABLE-SHARED). If INTLSYMBOL is 'no-libtool', a static library
+dnl $(top_builddir)/intl/libintl.a will be created.
+dnl If NEEDSYMBOL is specified and is 'need-ngettext', then GNU gettext
+dnl implementations (in libc or libintl) without the ngettext() function
+dnl will be ignored. If NEEDSYMBOL is specified and is
+dnl 'need-formatstring-macros', then GNU gettext implementations that don't
+dnl support the ISO C 99 <inttypes.h> formatstring macros will be ignored.
+dnl INTLDIR is used to find the intl libraries. If empty,
+dnl the value `$(top_builddir)/intl/' is used.
+dnl
+dnl The result of the configuration is one of three cases:
+dnl 1) GNU gettext, as included in the intl subdirectory, will be compiled
+dnl and used.
+dnl Catalog format: GNU --> install in $(datadir)
+dnl Catalog extension: .mo after installation, .gmo in source tree
+dnl 2) GNU gettext has been found in the system's C library.
+dnl Catalog format: GNU --> install in $(datadir)
+dnl Catalog extension: .mo after installation, .gmo in source tree
+dnl 3) No internationalization, always use English msgid.
+dnl Catalog format: none
+dnl Catalog extension: none
+dnl If INTLSYMBOL is 'external', only cases 2 and 3 can occur.
+dnl The use of .gmo is historical (it was needed to avoid overwriting the
+dnl GNU format catalogs when building on a platform with an X/Open gettext),
+dnl but we keep it in order not to force irrelevant filename changes on the
+dnl maintainers.
+dnl
+AC_DEFUN([AM_GNU_GETTEXT],
+[
+ dnl Argument checking.
+ ifelse([$1], [], , [ifelse([$1], [external], , [ifelse([$1], [no-libtool], , [ifelse([$1], [use-libtool], ,
+ [errprint([ERROR: invalid first argument to AM_GNU_GETTEXT
+])])])])])
+ ifelse([$2], [], , [ifelse([$2], [need-ngettext], , [ifelse([$2], [need-formatstring-macros], ,
+ [errprint([ERROR: invalid second argument to AM_GNU_GETTEXT
+])])])])
+ define(gt_included_intl, ifelse([$1], [external], [no], [yes]))
+ define(gt_libtool_suffix_prefix, ifelse([$1], [use-libtool], [l], []))
+
+ AC_REQUIRE([AM_PO_SUBDIRS])dnl
+ ifelse(gt_included_intl, yes, [
+ AC_REQUIRE([AM_INTL_SUBDIR])dnl
+ ])
+
+ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+
+ dnl Sometimes libintl requires libiconv, so first search for libiconv.
+ dnl Ideally we would do this search only after the
+ dnl if test "$USE_NLS" = "yes"; then
+ dnl if test "$gt_cv_func_gnugettext_libc" != "yes"; then
+ dnl tests. But if configure.in invokes AM_ICONV after AM_GNU_GETTEXT
+ dnl the configure script would need to contain the same shell code
+ dnl again, outside any 'if'. There are two solutions:
+ dnl - Invoke AM_ICONV_LINKFLAGS_BODY here, outside any 'if'.
+ dnl - Control the expansions in more detail using AC_PROVIDE_IFELSE.
+ dnl Since AC_PROVIDE_IFELSE is only in autoconf >= 2.52 and not
+ dnl documented, we avoid it.
+ ifelse(gt_included_intl, yes, , [
+ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+ ])
+
+ dnl Set USE_NLS.
+ AM_NLS
+
+ ifelse(gt_included_intl, yes, [
+ BUILD_INCLUDED_LIBINTL=no
+ USE_INCLUDED_LIBINTL=no
+ ])
+ LIBINTL=
+ LTLIBINTL=
+ POSUB=
+
+ dnl If we use NLS figure out what method
+ if test "$USE_NLS" = "yes"; then
+ gt_use_preinstalled_gnugettext=no
+ ifelse(gt_included_intl, yes, [
+ AC_MSG_CHECKING([whether included gettext is requested])
+ AC_ARG_WITH(included-gettext,
+ [ --with-included-gettext use the GNU gettext library included here],
+ nls_cv_force_use_gnu_gettext=$withval,
+ nls_cv_force_use_gnu_gettext=no)
+ AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
+
+ nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
+ if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
+ ])
+ dnl User does not insist on using GNU NLS library. Figure out what
+ dnl to use. If GNU gettext is available we use this. Else we have
+ dnl to fall back to GNU NLS library.
+
+ dnl Add a version number to the cache macros.
+ define([gt_api_version], ifelse([$2], [need-formatstring-macros], 3, ifelse([$2], [need-ngettext], 2, 1)))
+ define([gt_cv_func_gnugettext_libc], [gt_cv_func_gnugettext]gt_api_version[_libc])
+ define([gt_cv_func_gnugettext_libintl], [gt_cv_func_gnugettext]gt_api_version[_libintl])
+
+ AC_CACHE_CHECK([for GNU gettext in libc], gt_cv_func_gnugettext_libc,
+ [AC_TRY_LINK([#include <libintl.h>
+]ifelse([$2], [need-formatstring-macros],
+[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
+#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1)
+#endif
+changequote(,)dnl
+typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1];
+changequote([,])dnl
+], [])[extern int _nl_msg_cat_cntr;
+extern int *_nl_domain_bindings;],
+ [bindtextdomain ("", "");
+return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_domain_bindings],
+ gt_cv_func_gnugettext_libc=yes,
+ gt_cv_func_gnugettext_libc=no)])
+
+ if test "$gt_cv_func_gnugettext_libc" != "yes"; then
+ dnl Sometimes libintl requires libiconv, so first search for libiconv.
+ ifelse(gt_included_intl, yes, , [
+ AM_ICONV_LINK
+ ])
+ dnl Search for libintl and define LIBINTL, LTLIBINTL and INCINTL
+ dnl accordingly. Don't use AC_LIB_LINKFLAGS_BODY([intl],[iconv])
+ dnl because that would add "-liconv" to LIBINTL and LTLIBINTL
+ dnl even if libiconv doesn't exist.
+ AC_LIB_LINKFLAGS_BODY([intl])
+ AC_CACHE_CHECK([for GNU gettext in libintl],
+ gt_cv_func_gnugettext_libintl,
+ [gt_save_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $INCINTL"
+ gt_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBINTL"
+ dnl Now see whether libintl exists and does not depend on libiconv.
+ AC_TRY_LINK([#include <libintl.h>
+]ifelse([$2], [need-formatstring-macros],
+[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
+#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1)
+#endif
+changequote(,)dnl
+typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1];
+changequote([,])dnl
+], [])[extern int _nl_msg_cat_cntr;
+extern
+#ifdef __cplusplus
+"C"
+#endif
+const char *_nl_expand_alias ();],
+ [bindtextdomain ("", "");
+return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias (0)],
+ gt_cv_func_gnugettext_libintl=yes,
+ gt_cv_func_gnugettext_libintl=no)
+ dnl Now see whether libintl exists and depends on libiconv.
+ if test "$gt_cv_func_gnugettext_libintl" != yes && test -n "$LIBICONV"; then
+ LIBS="$LIBS $LIBICONV"
+ AC_TRY_LINK([#include <libintl.h>
+]ifelse([$2], [need-formatstring-macros],
+[#ifndef __GNU_GETTEXT_SUPPORTED_REVISION
+#define __GNU_GETTEXT_SUPPORTED_REVISION(major) ((major) == 0 ? 0 : -1)
+#endif
+changequote(,)dnl
+typedef int array [2 * (__GNU_GETTEXT_SUPPORTED_REVISION(0) >= 1) - 1];
+changequote([,])dnl
+], [])[extern int _nl_msg_cat_cntr;
+extern
+#ifdef __cplusplus
+"C"
+#endif
+const char *_nl_expand_alias ();],
+ [bindtextdomain ("", "");
+return (int) gettext ("")]ifelse([$2], [need-ngettext], [ + (int) ngettext ("", "", 0)], [])[ + _nl_msg_cat_cntr + *_nl_expand_alias (0)],
+ [LIBINTL="$LIBINTL $LIBICONV"
+ LTLIBINTL="$LTLIBINTL $LTLIBICONV"
+ gt_cv_func_gnugettext_libintl=yes
+ ])
+ fi
+ CPPFLAGS="$gt_save_CPPFLAGS"
+ LIBS="$gt_save_LIBS"])
+ fi
+
+ dnl If an already present or preinstalled GNU gettext() is found,
+ dnl use it. But if this macro is used in GNU gettext, and GNU
+ dnl gettext is already preinstalled in libintl, we update this
+ dnl libintl. (Cf. the install rule in intl/Makefile.in.)
+ if test "$gt_cv_func_gnugettext_libc" = "yes" \
+ || { test "$gt_cv_func_gnugettext_libintl" = "yes" \
+ && test "$PACKAGE" != gettext-runtime \
+ && test "$PACKAGE" != gettext-tools; }; then
+ gt_use_preinstalled_gnugettext=yes
+ else
+ dnl Reset the values set by searching for libintl.
+ LIBINTL=
+ LTLIBINTL=
+ INCINTL=
+ fi
+
+ ifelse(gt_included_intl, yes, [
+ if test "$gt_use_preinstalled_gnugettext" != "yes"; then
+ dnl GNU gettext is not found in the C library.
+ dnl Fall back on included GNU gettext library.
+ nls_cv_use_gnu_gettext=yes
+ fi
+ fi
+
+ if test "$nls_cv_use_gnu_gettext" = "yes"; then
+ dnl Mark actions used to generate GNU NLS library.
+ BUILD_INCLUDED_LIBINTL=yes
+ USE_INCLUDED_LIBINTL=yes
+ LIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LIBICONV"
+ LTLIBINTL="ifelse([$3],[],\${top_builddir}/intl,[$3])/libintl.[]gt_libtool_suffix_prefix[]a $LTLIBICONV"
+ LIBS=`echo " $LIBS " | sed -e 's/ -lintl / /' -e 's/^ //' -e 's/ $//'`
+ fi
+
+ if test "$gt_use_preinstalled_gnugettext" = "yes" \
+ || test "$nls_cv_use_gnu_gettext" = "yes"; then
+ dnl Mark actions to use GNU gettext tools.
+ CATOBJEXT=.gmo
+ fi
+ ])
+
+ if test "$gt_use_preinstalled_gnugettext" = "yes" \
+ || test "$nls_cv_use_gnu_gettext" = "yes"; then
+ AC_DEFINE(ENABLE_NLS, 1,
+ [Define to 1 if translation of program messages to the user's native language
+ is requested.])
+ else
+ USE_NLS=no
+ fi
+ fi
+
+ AC_MSG_CHECKING([whether to use NLS])
+ AC_MSG_RESULT([$USE_NLS])
+ if test "$USE_NLS" = "yes"; then
+ AC_MSG_CHECKING([where the gettext function comes from])
+ if test "$gt_use_preinstalled_gnugettext" = "yes"; then
+ if test "$gt_cv_func_gnugettext_libintl" = "yes"; then
+ gt_source="external libintl"
+ else
+ gt_source="libc"
+ fi
+ else
+ gt_source="included intl directory"
+ fi
+ AC_MSG_RESULT([$gt_source])
+ fi
+
+ if test "$USE_NLS" = "yes"; then
+
+ if test "$gt_use_preinstalled_gnugettext" = "yes"; then
+ if test "$gt_cv_func_gnugettext_libintl" = "yes"; then
+ AC_MSG_CHECKING([how to link with libintl])
+ AC_MSG_RESULT([$LIBINTL])
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCINTL])
+ fi
+
+ dnl For backward compatibility. Some packages may be using this.
+ AC_DEFINE(HAVE_GETTEXT, 1,
+ [Define if the GNU gettext() function is already present or preinstalled.])
+ AC_DEFINE(HAVE_DCGETTEXT, 1,
+ [Define if the GNU dcgettext() function is already present or preinstalled.])
+ fi
+
+ dnl We need to process the po/ directory.
+ POSUB=po
+ fi
+
+ ifelse(gt_included_intl, yes, [
+ dnl If this is used in GNU gettext we have to set BUILD_INCLUDED_LIBINTL
+ dnl to 'yes' because some of the testsuite requires it.
+ if test "$PACKAGE" = gettext-runtime || test "$PACKAGE" = gettext-tools; then
+ BUILD_INCLUDED_LIBINTL=yes
+ fi
+
+ dnl Make all variables we use known to autoconf.
+ AC_SUBST(BUILD_INCLUDED_LIBINTL)
+ AC_SUBST(USE_INCLUDED_LIBINTL)
+ AC_SUBST(CATOBJEXT)
+
+ dnl For backward compatibility. Some configure.ins may be using this.
+ nls_cv_header_intl=
+ nls_cv_header_libgt=
+
+ dnl For backward compatibility. Some Makefiles may be using this.
+ DATADIRNAME=share
+ AC_SUBST(DATADIRNAME)
+
+ dnl For backward compatibility. Some Makefiles may be using this.
+ INSTOBJEXT=.mo
+ AC_SUBST(INSTOBJEXT)
+
+ dnl For backward compatibility. Some Makefiles may be using this.
+ GENCAT=gencat
+ AC_SUBST(GENCAT)
+
+ dnl For backward compatibility. Some Makefiles may be using this.
+ if test "$USE_INCLUDED_LIBINTL" = yes; then
+ INTLOBJS="\$(GETTOBJS)"
+ fi
+ AC_SUBST(INTLOBJS)
+
+ dnl Enable libtool support if the surrounding package wishes it.
+ INTL_LIBTOOL_SUFFIX_PREFIX=gt_libtool_suffix_prefix
+ AC_SUBST(INTL_LIBTOOL_SUFFIX_PREFIX)
+ ])
+
+ dnl For backward compatibility. Some Makefiles may be using this.
+ INTLLIBS="$LIBINTL"
+ AC_SUBST(INTLLIBS)
+
+ dnl Make all documented variables known to autoconf.
+ AC_SUBST(LIBINTL)
+ AC_SUBST(LTLIBINTL)
+ AC_SUBST(POSUB)
+])
+
+
+dnl Checks for all prerequisites of the intl subdirectory,
+dnl except for INTL_LIBTOOL_SUFFIX_PREFIX (and possibly LIBTOOL), INTLOBJS,
+dnl USE_INCLUDED_LIBINTL, BUILD_INCLUDED_LIBINTL.
+AC_DEFUN([AM_INTL_SUBDIR],
+[
+ AC_REQUIRE([AC_PROG_INSTALL])dnl
+ AC_REQUIRE([AM_MKINSTALLDIRS])dnl
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_CANONICAL_HOST])dnl
+ AC_REQUIRE([AC_PROG_RANLIB])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+ AC_REQUIRE([AC_C_CONST])dnl
+ AC_REQUIRE([AC_C_INLINE])dnl
+ AC_REQUIRE([AC_TYPE_OFF_T])dnl
+ AC_REQUIRE([AC_TYPE_SIZE_T])dnl
+ AC_REQUIRE([AC_FUNC_ALLOCA])dnl
+ AC_REQUIRE([AC_FUNC_MMAP])dnl
+ AC_REQUIRE([jm_GLIBC21])dnl
+ AC_REQUIRE([gt_INTDIV0])dnl
+ AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])dnl
+ AC_REQUIRE([gt_HEADER_INTTYPES_H])dnl
+ AC_REQUIRE([gt_INTTYPES_PRI])dnl
+
+ AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \
+stdlib.h string.h unistd.h sys/param.h])
+ AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \
+geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \
+strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next \
+__fsetlocking])
+
+ AM_ICONV
+ AM_LANGINFO_CODESET
+ if test $ac_cv_header_locale_h = yes; then
+ AM_LC_MESSAGES
+ fi
+
+ dnl intl/plural.c is generated from intl/plural.y. It requires bison,
+ dnl because plural.y uses bison specific features. It requires at least
+ dnl bison-1.26 because earlier versions generate a plural.c that doesn't
+ dnl compile.
+ dnl bison is only needed for the maintainer (who touches plural.y). But in
+ dnl order to avoid separate Makefiles or --enable-maintainer-mode, we put
+ dnl the rule in general Makefile. Now, some people carelessly touch the
+ dnl files or have a broken "make" program, hence the plural.c rule will
+ dnl sometimes fire. To avoid an error, defines BISON to ":" if it is not
+ dnl present or too old.
+ AC_CHECK_PROGS([INTLBISON], [bison])
+ if test -z "$INTLBISON"; then
+ ac_verc_fail=yes
+ else
+ dnl Found it, now check the version.
+ AC_MSG_CHECKING([version of bison])
+changequote(<<,>>)dnl
+ ac_prog_version=`$INTLBISON --version 2>&1 | sed -n 's/^.*GNU Bison.* \([0-9]*\.[0-9.]*\).*$/\1/p'`
+ case $ac_prog_version in
+ '') ac_prog_version="v. ?.??, bad"; ac_verc_fail=yes;;
+ 1.2[6-9]* | 1.[3-9][0-9]* | [2-9].*)
+changequote([,])dnl
+ ac_prog_version="$ac_prog_version, ok"; ac_verc_fail=no;;
+ *) ac_prog_version="$ac_prog_version, bad"; ac_verc_fail=yes;;
+ esac
+ AC_MSG_RESULT([$ac_prog_version])
+ fi
+ if test $ac_verc_fail = yes; then
+ INTLBISON=:
+ fi
+])
+
+
+dnl Usage: AM_GNU_GETTEXT_VERSION([gettext-version])
+AC_DEFUN([AM_GNU_GETTEXT_VERSION], [])
+# glibc21.m4 serial 2 (fileutils-4.1.3, gettext-0.10.40)
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+# Test for the GNU C Library, version 2.1 or newer.
+# From Bruno Haible.
+
+AC_DEFUN([jm_GLIBC21],
+ [
+ AC_CACHE_CHECK(whether we are using the GNU C Library 2.1 or newer,
+ ac_cv_gnu_library_2_1,
+ [AC_EGREP_CPP([Lucky GNU user],
+ [
+#include <features.h>
+#ifdef __GNU_LIBRARY__
+ #if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) || (__GLIBC__ > 2)
+ Lucky GNU user
+ #endif
+#endif
+ ],
+ ac_cv_gnu_library_2_1=yes,
+ ac_cv_gnu_library_2_1=no)
+ ]
+ )
+ AC_SUBST(GLIBC21)
+ GLIBC21="$ac_cv_gnu_library_2_1"
+ ]
+)
+# iconv.m4 serial AM4 (gettext-0.11.3)
+dnl Copyright (C) 2000-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
+[
+ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+
+ dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([iconv])
+])
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+ dnl those with the standalone portable GNU libiconv installed).
+
+ dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+ dnl accordingly.
+ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+
+ dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed libiconv and not disabled its use
+ dnl via --without-libiconv-prefix, he wants to use it. The first
+ dnl AC_TRY_LINK will then fail, the second AC_TRY_LINK will succeed.
+ am_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+ AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
+ am_cv_func_iconv="no, consider installing GNU libiconv"
+ am_cv_lib_iconv=no
+ AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+ [iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);],
+ am_cv_func_iconv=yes)
+ if test "$am_cv_func_iconv" != yes; then
+ am_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBICONV"
+ AC_TRY_LINK([#include <stdlib.h>
+#include <iconv.h>],
+ [iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);],
+ am_cv_lib_iconv=yes
+ am_cv_func_iconv=yes)
+ LIBS="$am_save_LIBS"
+ fi
+ ])
+ if test "$am_cv_func_iconv" = yes; then
+ AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
+ fi
+ if test "$am_cv_lib_iconv" = yes; then
+ AC_MSG_CHECKING([how to link with libiconv])
+ AC_MSG_RESULT([$LIBICONV])
+ else
+ dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+ dnl either.
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBICONV=
+ LTLIBICONV=
+ fi
+ AC_SUBST(LIBICONV)
+ AC_SUBST(LTLIBICONV)
+])
+
+AC_DEFUN([AM_ICONV],
+[
+ AM_ICONV_LINK
+ if test "$am_cv_func_iconv" = yes; then
+ AC_MSG_CHECKING([for iconv declaration])
+ AC_CACHE_VAL(am_cv_proto_iconv, [
+ AC_TRY_COMPILE([
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
+ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+ am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+ AC_MSG_RESULT([$]{ac_t:-
+ }[$]am_cv_proto_iconv)
+ AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
+ [Define as const if the declaration of iconv() needs const.])
+ fi
+])
+# intdiv0.m4 serial 1 (gettext-0.11.3)
+dnl Copyright (C) 2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([gt_INTDIV0],
+[
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+ AC_CACHE_CHECK([whether integer division by zero raises SIGFPE],
+ gt_cv_int_divbyzero_sigfpe,
+ [
+ AC_TRY_RUN([
+#include <stdlib.h>
+#include <signal.h>
+
+static void
+#ifdef __cplusplus
+sigfpe_handler (int sig)
+#else
+sigfpe_handler (sig) int sig;
+#endif
+{
+ /* Exit with code 0 if SIGFPE, with code 1 if any other signal. */
+ exit (sig != SIGFPE);
+}
+
+int x = 1;
+int y = 0;
+int z;
+int nan;
+
+int main ()
+{
+ signal (SIGFPE, sigfpe_handler);
+/* IRIX and AIX (when "xlc -qcheck" is used) yield signal SIGTRAP. */
+#if (defined (__sgi) || defined (_AIX)) && defined (SIGTRAP)
+ signal (SIGTRAP, sigfpe_handler);
+#endif
+/* Linux/SPARC yields signal SIGILL. */
+#if defined (__sparc__) && defined (__linux__)
+ signal (SIGILL, sigfpe_handler);
+#endif
+
+ z = x / y;
+ nan = y / y;
+ exit (1);
+}
+], gt_cv_int_divbyzero_sigfpe=yes, gt_cv_int_divbyzero_sigfpe=no,
+ [
+ # Guess based on the CPU.
+ case "$host_cpu" in
+ alpha* | i[34567]86 | m68k | s390*)
+ gt_cv_int_divbyzero_sigfpe="guessing yes";;
+ *)
+ gt_cv_int_divbyzero_sigfpe="guessing no";;
+ esac
+ ])
+ ])
+ case "$gt_cv_int_divbyzero_sigfpe" in
+ *yes) value=1;;
+ *) value=0;;
+ esac
+ AC_DEFINE_UNQUOTED(INTDIV0_RAISES_SIGFPE, $value,
+ [Define if integer division by zero raises signal SIGFPE.])
+])
+# inttypes.m4 serial 1 (gettext-0.11.4)
+dnl Copyright (C) 1997-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Paul Eggert.
+
+# Define HAVE_INTTYPES_H if <inttypes.h> exists and doesn't clash with
+# <sys/types.h>.
+
+AC_DEFUN([gt_HEADER_INTTYPES_H],
+[
+ AC_CACHE_CHECK([for inttypes.h], gt_cv_header_inttypes_h,
+ [
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <inttypes.h>],
+ [], gt_cv_header_inttypes_h=yes, gt_cv_header_inttypes_h=no)
+ ])
+ if test $gt_cv_header_inttypes_h = yes; then
+ AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1,
+ [Define if <inttypes.h> exists and doesn't clash with <sys/types.h>.])
+ fi
+])
+# inttypes_h.m4 serial 5 (gettext-0.12)
+dnl Copyright (C) 1997-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Paul Eggert.
+
+# Define HAVE_INTTYPES_H_WITH_UINTMAX if <inttypes.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([jm_AC_HEADER_INTTYPES_H],
+[
+ AC_CACHE_CHECK([for inttypes.h], jm_ac_cv_header_inttypes_h,
+ [AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <inttypes.h>],
+ [uintmax_t i = (uintmax_t) -1;],
+ jm_ac_cv_header_inttypes_h=yes,
+ jm_ac_cv_header_inttypes_h=no)])
+ if test $jm_ac_cv_header_inttypes_h = yes; then
+ AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H_WITH_UINTMAX, 1,
+ [Define if <inttypes.h> exists, doesn't clash with <sys/types.h>,
+ and declares uintmax_t. ])
+ fi
+])
+# inttypes-pri.m4 serial 1 (gettext-0.11.4)
+dnl Copyright (C) 1997-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+# Define PRI_MACROS_BROKEN if <inttypes.h> exists and defines the PRI*
+# macros to non-string values. This is the case on AIX 4.3.3.
+
+AC_DEFUN([gt_INTTYPES_PRI],
+[
+ AC_REQUIRE([gt_HEADER_INTTYPES_H])
+ if test $gt_cv_header_inttypes_h = yes; then
+ AC_CACHE_CHECK([whether the inttypes.h PRIxNN macros are broken],
+ gt_cv_inttypes_pri_broken,
+ [
+ AC_TRY_COMPILE([#include <inttypes.h>
+#ifdef PRId32
+char *p = PRId32;
+#endif
+], [], gt_cv_inttypes_pri_broken=no, gt_cv_inttypes_pri_broken=yes)
+ ])
+ fi
+ if test "$gt_cv_inttypes_pri_broken" = yes; then
+ AC_DEFINE_UNQUOTED(PRI_MACROS_BROKEN, 1,
+ [Define if <inttypes.h> exists and defines unusable PRI* macros.])
+ fi
+])
+# isc-posix.m4 serial 2 (gettext-0.11.2)
+dnl Copyright (C) 1995-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+# This file is not needed with autoconf-2.53 and newer. Remove it in 2005.
+
+# This test replaces the one in autoconf.
+# Currently this macro should have the same name as the autoconf macro
+# because gettext's gettext.m4 (distributed in the automake package)
+# still uses it. Otherwise, the use in gettext.m4 makes autoheader
+# give these diagnostics:
+# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX
+# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX
+
+undefine([AC_ISC_POSIX])
+
+AC_DEFUN([AC_ISC_POSIX],
+ [
+ dnl This test replaces the obsolescent AC_ISC_POSIX kludge.
+ AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"])
+ ]
+)
+# lcmessage.m4 serial 3 (gettext-0.11.3)
+dnl Copyright (C) 1995-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+# Check whether LC_MESSAGES is available in <locale.h>.
+
+AC_DEFUN([AM_LC_MESSAGES],
+[
+ AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
+ [AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
+ am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
+ if test $am_cv_val_LC_MESSAGES = yes; then
+ AC_DEFINE(HAVE_LC_MESSAGES, 1,
+ [Define if your <locale.h> file defines LC_MESSAGES.])
+ fi
+])
+# lib-ld.m4 serial 2 (gettext-0.12)
+dnl Copyright (C) 1996-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
+dnl with libtool.m4.
+
+dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+ acl_cv_prog_gnu_ld=yes
+else
+ acl_cv_prog_gnu_ld=no
+fi])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-1.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_ARG_WITH(gnu-ld,
+[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by GCC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]* | [A-Za-z]:[\\/]*)]
+ [re_direlt='/[^/][^/]*/\.\./']
+ # Canonicalize the path of ld
+ ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+ while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(acl_cv_path_LD,
+[if test -z "$LD"; then
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+ for ac_dir in $PATH; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some GNU ld's only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ if "$acl_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+ test "$with_gnu_ld" != no && break
+ else
+ test "$with_gnu_ld" != yes && break
+ fi
+ fi
+ done
+ IFS="$ac_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT($LD)
+else
+ AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
+# lib-link.m4 serial 4 (gettext-0.12)
+dnl Copyright (C) 2001-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ define([Name],[translit([$1],[./-], [___])])
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+ ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+ ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+ ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+ ])
+ LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+ LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+ INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+ dnl results of this search when this library appears as a dependency.
+ HAVE_LIB[]NAME=yes
+ undefine([Name])
+ undefine([NAME])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. If found, it
+dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
+dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ define([Name],[translit([$1],[./-], [___])])
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+
+ dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+ dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed lib[]Name and not disabled its use
+ dnl via --without-lib[]Name-prefix, he wants to use it.
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+ AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+ ac_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIB[]NAME"
+ AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
+ LIBS="$ac_save_LIBS"
+ ])
+ if test "$ac_cv_lib[]Name" = yes; then
+ HAVE_LIB[]NAME=yes
+ AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
+ AC_MSG_CHECKING([how to link with lib[]$1])
+ AC_MSG_RESULT([$LIB[]NAME])
+ else
+ HAVE_LIB[]NAME=no
+ dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+ dnl $INC[]NAME either.
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIB[]NAME=
+ LTLIB[]NAME=
+ fi
+ AC_SUBST([HAVE_LIB]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ undefine([Name])
+ undefine([NAME])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl libext, shlibext, hardcode_libdir_flag_spec, hardcode_libdir_separator,
+dnl hardcode_direct, hardcode_minus_L.
+AC_DEFUN([AC_LIB_RPATH],
+[
+ AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
+ AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
+ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+ AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+ ])
+ wl="$acl_cv_wl"
+ libext="$acl_cv_libext"
+ shlibext="$acl_cv_shlibext"
+ hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ hardcode_direct="$acl_cv_hardcode_direct"
+ hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ dnl Determine whether the user wants rpath handling at all.
+ AC_ARG_ENABLE(rpath,
+ [ --disable-rpath do not hardcode runtime library paths],
+ :, enable_rpath=yes)
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+ define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_LIB_ARG_WITH([lib$1-prefix],
+[ --with-lib$1-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib
+ --without-lib$1-prefix don't search for lib$1 in includedir and libdir],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/lib"
+ fi
+ fi
+])
+ dnl Search the library and its dependencies in $additional_libdir and
+ dnl $LDFLAGS. Using breadth-first-seach.
+ LIB[]NAME=
+ LTLIB[]NAME=
+ INC[]NAME=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='$1 $2'
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+ dnl or AC_LIB_HAVE_LINKFLAGS call.
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+ else
+ dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+ dnl that this library doesn't exist. So just drop it.
+ :
+ fi
+ else
+ dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+ dnl and the already constructed $LIBNAME/$LTLIBNAME.
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ if test $use_additional = yes; then
+ if test -n "$shlibext" && test -f "$additional_libdir/lib$name.$shlibext"; then
+ found_dir="$additional_libdir"
+ found_so="$additional_libdir/lib$name.$shlibext"
+ if test -f "$additional_libdir/lib$name.la"; then
+ found_la="$additional_libdir/lib$name.la"
+ fi
+ else
+ if test -f "$additional_libdir/lib$name.$libext"; then
+ found_dir="$additional_libdir"
+ found_a="$additional_libdir/lib$name.$libext"
+ if test -f "$additional_libdir/lib$name.la"; then
+ found_la="$additional_libdir/lib$name.la"
+ fi
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ if test -n "$shlibext" && test -f "$dir/lib$name.$shlibext"; then
+ found_dir="$dir"
+ found_so="$dir/lib$name.$shlibext"
+ if test -f "$dir/lib$name.la"; then
+ found_la="$dir/lib$name.la"
+ fi
+ else
+ if test -f "$dir/lib$name.$libext"; then
+ found_dir="$dir"
+ found_a="$dir/lib$name.$libext"
+ if test -f "$dir/lib$name.la"; then
+ found_la="$dir/lib$name.la"
+ fi
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ dnl Found the library.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ dnl Linking with a shared library. We attempt to hardcode its
+ dnl directory into the executable's runpath, unless it's the
+ dnl standard /usr/lib.
+ if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/lib"; then
+ dnl No hardcoding is needed.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ dnl The hardcoding into $LIBNAME is system dependent.
+ if test "$hardcode_direct" = yes; then
+ dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+ dnl resulting binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ if test -n "$hardcode_libdir_flag_spec" && test "$hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ dnl Rely on "-L$found_dir".
+ dnl But don't add it if it's already contained in the LDFLAGS
+ dnl or the already constructed $LIBNAME
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+ fi
+ if test "$hardcode_minus_L" != no; then
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl We cannot use $hardcode_runpath_var and LD_RUN_PATH
+ dnl here, because this doesn't fit in flags passed to the
+ dnl compiler. So give up. No hardcoding. This affects only
+ dnl very old systems.
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ dnl Linking with a static library.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+ else
+ dnl We shouldn't come here, but anyway it's good to have a
+ dnl fallback.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+ fi
+ fi
+ dnl Assume the include files are nearby.
+ additional_includedir=
+ case "$found_dir" in
+ */lib | */lib/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e 's,/lib/*$,,'`
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ dnl Potentially add $additional_includedir to $INCNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 3. if it's already present in $CPPFLAGS or the already
+ dnl constructed $INCNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INC[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $INCNAME.
+ INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ dnl Look for dependencies.
+ if test -n "$found_la"; then
+ dnl Read the .la file. It defines the variables
+ dnl dlname, library_names, old_library, dependency_libs, current,
+ dnl age, revision, installed, dlopen, dlpreopen, libdir.
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ dnl We use only dependency_libs.
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 3. if it's already present in $LDFLAGS or the already
+ dnl constructed $LIBNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/lib"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/lib"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LIBNAME.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LTLIBNAME.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ dnl Handle this in the next round.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ dnl Handle this in the next round. Throw away the .la's
+ dnl directory; it is already contained in a preceding -L
+ dnl option.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ dnl Most likely an immediate library name.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ dnl Didn't find the library; assume it is in the system directories
+ dnl known to the linker and runtime loader. (All the system
+ dnl directories known to the linker should also be known to the
+ dnl runtime loader, otherwise the system is severely misconfigured.)
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user must
+ dnl pass all path elements in one option. We can arrange that for a
+ dnl single library, but not when more than one $LIBNAMEs are used.
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$hardcode_libdir_separator}$found_dir"
+ done
+ dnl Note: hardcode_libdir_flag_spec uses $libdir and $wl.
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ dnl When using libtool, the option that works for both libraries and
+ dnl executables is -R. The -R options are cumulative.
+ for found_dir in $ltrpathdirs; do
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+ done
+ fi
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+ for element in [$2]; do
+ haveit=
+ for x in $[$1]; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ [$1]="${[$1]}${[$1]:+ }$element"
+ fi
+ done
+])
+# lib-prefix.m4 serial 2 (gettext-0.12)
+dnl Copyright (C) 2001-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
+dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
+dnl require excessive bracketing.
+ifdef([AC_HELP_STRING],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+ AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_LIB_ARG_WITH([lib-prefix],
+[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+ --without-lib-prefix don't search for libraries in includedir and libdir],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/lib"
+ fi
+ fi
+])
+ if test $use_additional = yes; then
+ dnl Potentially add $additional_includedir to $CPPFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's already present in $CPPFLAGS,
+ dnl 3. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ for x in $CPPFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $CPPFLAGS.
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ dnl Potentially add $additional_libdir to $LDFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's already present in $LDFLAGS,
+ dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/lib"; then
+ haveit=
+ for x in $LDFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_libdir" = "X/usr/local/lib"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LDFLAGS.
+ LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+ dnl Unfortunately, prefix and exec_prefix get only finally determined
+ dnl at the end of configure.
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ $1
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+])
+# nls.m4 serial 1 (gettext-0.12)
+dnl Copyright (C) 1995-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
+dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
+
+AC_DEFUN([AM_NLS],
+[
+ AC_MSG_CHECKING([whether NLS is requested])
+ dnl Default is enabled NLS
+ AC_ARG_ENABLE(nls,
+ [ --disable-nls do not use Native Language Support],
+ USE_NLS=$enableval, USE_NLS=yes)
+ AC_MSG_RESULT($USE_NLS)
+ AC_SUBST(USE_NLS)
+])
+
+AC_DEFUN([AM_MKINSTALLDIRS],
+[
+ dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
+ dnl find the mkinstalldirs script in another subdir but $(top_srcdir).
+ dnl Try to locate it.
+ MKINSTALLDIRS=
+ if test -n "$ac_aux_dir"; then
+ case "$ac_aux_dir" in
+ /*) MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" ;;
+ *) MKINSTALLDIRS="\$(top_builddir)/$ac_aux_dir/mkinstalldirs" ;;
+ esac
+ fi
+ if test -z "$MKINSTALLDIRS"; then
+ MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
+ fi
+ AC_SUBST(MKINSTALLDIRS)
+])
+# po.m4 serial 1 (gettext-0.12)
+dnl Copyright (C) 1995-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
+dnl Bruno Haible <haible@clisp.cons.org>, 2000-2003.
+
+dnl Checks for all prerequisites of the po subdirectory.
+AC_DEFUN([AM_PO_SUBDIRS],
+[
+ AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+ AC_REQUIRE([AC_PROG_INSTALL])dnl
+ AC_REQUIRE([AM_MKINSTALLDIRS])dnl
+ AC_REQUIRE([AM_NLS])dnl
+
+ dnl Perform the following tests also if --disable-nls has been given,
+ dnl because they are needed for "make dist" to work.
+
+ dnl Search for GNU msgfmt in the PATH.
+ dnl The first test excludes Solaris msgfmt and early GNU msgfmt versions.
+ dnl The second test excludes FreeBSD msgfmt.
+ AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
+ [$ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 &&
+ (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
+ :)
+ AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
+
+ dnl Search for GNU xgettext 0.12 or newer in the PATH.
+ dnl The first test excludes Solaris xgettext and early GNU xgettext versions.
+ dnl The second test excludes FreeBSD xgettext.
+ AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
+ [$ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 &&
+ (if $ac_dir/$ac_word --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi)],
+ :)
+ dnl Remove leftover from FreeBSD xgettext call.
+ rm -f messages.po
+
+ dnl Search for GNU msgmerge 0.11 or newer in the PATH.
+ AM_PATH_PROG_WITH_TEST(MSGMERGE, msgmerge,
+ [$ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1], :)
+
+ dnl This could go away some day; the PATH_PROG_WITH_TEST already does it.
+ dnl Test whether we really found GNU msgfmt.
+ if test "$GMSGFMT" != ":"; then
+ dnl If it is no GNU msgfmt we define it as : so that the
+ dnl Makefiles still can work.
+ if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 &&
+ (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then
+ : ;
+ else
+ GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'`
+ AC_MSG_RESULT(
+ [found $GMSGFMT program is not GNU msgfmt; ignore it])
+ GMSGFMT=":"
+ fi
+ fi
+
+ dnl This could go away some day; the PATH_PROG_WITH_TEST already does it.
+ dnl Test whether we really found GNU xgettext.
+ if test "$XGETTEXT" != ":"; then
+ dnl If it is no GNU xgettext we define it as : so that the
+ dnl Makefiles still can work.
+ if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null >/dev/null 2>&1 &&
+ (if $XGETTEXT --omit-header --copyright-holder= --msgid-bugs-address= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then
+ : ;
+ else
+ AC_MSG_RESULT(
+ [found xgettext program is not GNU xgettext; ignore it])
+ XGETTEXT=":"
+ fi
+ dnl Remove leftover from FreeBSD xgettext call.
+ rm -f messages.po
+ fi
+
+ AC_OUTPUT_COMMANDS([
+ for ac_file in $CONFIG_FILES; do
+ # Support "outfile[:infile[:infile...]]"
+ case "$ac_file" in
+ *:*) ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ esac
+ # PO directories have a Makefile.in generated from Makefile.in.in.
+ case "$ac_file" in */Makefile.in)
+ # Adjust a relative srcdir.
+ ac_dir=`echo "$ac_file"|sed 's%/[^/][^/]*$%%'`
+ ac_dir_suffix="/`echo "$ac_dir"|sed 's%^\./%%'`"
+ ac_dots=`echo "$ac_dir_suffix"|sed 's%/[^/]*%../%g'`
+ # In autoconf-2.13 it is called $ac_given_srcdir.
+ # In autoconf-2.50 it is called $srcdir.
+ test -n "$ac_given_srcdir" || ac_given_srcdir="$srcdir"
+ case "$ac_given_srcdir" in
+ .) top_srcdir=`echo $ac_dots|sed 's%/$%%'` ;;
+ /*) top_srcdir="$ac_given_srcdir" ;;
+ *) top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+ if test -f "$ac_given_srcdir/$ac_dir/POTFILES.in"; then
+ rm -f "$ac_dir/POTFILES"
+ test -n "$as_me" && echo "$as_me: creating $ac_dir/POTFILES" || echo "creating $ac_dir/POTFILES"
+ cat "$ac_given_srcdir/$ac_dir/POTFILES.in" | sed -e "/^#/d" -e "/^[ ]*\$/d" -e "s,.*, $top_srcdir/& \\\\," | sed -e "\$s/\(.*\) \\\\/\1/" > "$ac_dir/POTFILES"
+ POMAKEFILEDEPS="POTFILES.in"
+ # ALL_LINGUAS, POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES depend
+ # on $ac_dir but don't depend on user-specified configuration
+ # parameters.
+ if test -f "$ac_given_srcdir/$ac_dir/LINGUAS"; then
+ # The LINGUAS file contains the set of available languages.
+ if test -n "$OBSOLETE_ALL_LINGUAS"; then
+ test -n "$as_me" && echo "$as_me: setting ALL_LINGUAS in configure.in is obsolete" || echo "setting ALL_LINGUAS in configure.in is obsolete"
+ fi
+ ALL_LINGUAS_=`sed -e "/^#/d" "$ac_given_srcdir/$ac_dir/LINGUAS"`
+ # Hide the ALL_LINGUAS assigment from automake.
+ eval 'ALL_LINGUAS''=$ALL_LINGUAS_'
+ POMAKEFILEDEPS="$POMAKEFILEDEPS LINGUAS"
+ else
+ # The set of available languages was given in configure.in.
+ eval 'ALL_LINGUAS''=$OBSOLETE_ALL_LINGUAS'
+ fi
+ case "$ac_given_srcdir" in
+ .) srcdirpre= ;;
+ *) srcdirpre='$(srcdir)/' ;;
+ esac
+ POFILES=
+ GMOFILES=
+ UPDATEPOFILES=
+ DUMMYPOFILES=
+ for lang in $ALL_LINGUAS; do
+ POFILES="$POFILES $srcdirpre$lang.po"
+ GMOFILES="$GMOFILES $srcdirpre$lang.gmo"
+ UPDATEPOFILES="$UPDATEPOFILES $lang.po-update"
+ DUMMYPOFILES="$DUMMYPOFILES $lang.nop"
+ done
+ # CATALOGS depends on both $ac_dir and the user's LINGUAS
+ # environment variable.
+ INST_LINGUAS=
+ if test -n "$ALL_LINGUAS"; then
+ for presentlang in $ALL_LINGUAS; do
+ useit=no
+ if test "%UNSET%" != "$LINGUAS"; then
+ desiredlanguages="$LINGUAS"
+ else
+ desiredlanguages="$ALL_LINGUAS"
+ fi
+ for desiredlang in $desiredlanguages; do
+ # Use the presentlang catalog if desiredlang is
+ # a. equal to presentlang, or
+ # b. a variant of presentlang (because in this case,
+ # presentlang can be used as a fallback for messages
+ # which are not translated in the desiredlang catalog).
+ case "$desiredlang" in
+ "$presentlang"*) useit=yes;;
+ esac
+ done
+ if test $useit = yes; then
+ INST_LINGUAS="$INST_LINGUAS $presentlang"
+ fi
+ done
+ fi
+ CATALOGS=
+ if test -n "$INST_LINGUAS"; then
+ for lang in $INST_LINGUAS; do
+ CATALOGS="$CATALOGS $lang.gmo"
+ done
+ fi
+ test -n "$as_me" && echo "$as_me: creating $ac_dir/Makefile" || echo "creating $ac_dir/Makefile"
+ sed -e "/^POTFILES =/r $ac_dir/POTFILES" -e "/^# Makevars/r $ac_given_srcdir/$ac_dir/Makevars" -e "s|@POFILES@|$POFILES|g" -e "s|@GMOFILES@|$GMOFILES|g" -e "s|@UPDATEPOFILES@|$UPDATEPOFILES|g" -e "s|@DUMMYPOFILES@|$DUMMYPOFILES|g" -e "s|@CATALOGS@|$CATALOGS|g" -e "s|@POMAKEFILEDEPS@|$POMAKEFILEDEPS|g" "$ac_dir/Makefile.in" > "$ac_dir/Makefile"
+ for f in "$ac_given_srcdir/$ac_dir"/Rules-*; do
+ if test -f "$f"; then
+ case "$f" in
+ *.orig | *.bak | *~) ;;
+ *) cat "$f" >> "$ac_dir/Makefile" ;;
+ esac
+ fi
+ done
+ fi
+ ;;
+ esac
+ done],
+ [# Capture the value of obsolete ALL_LINGUAS because we need it to compute
+ # POFILES, GMOFILES, UPDATEPOFILES, DUMMYPOFILES, CATALOGS. But hide it
+ # from automake.
+ eval 'OBSOLETE_ALL_LINGUAS''="$ALL_LINGUAS"'
+ # Capture the value of LINGUAS because we need it to compute CATALOGS.
+ LINGUAS="${LINGUAS-%UNSET%}"
+ ])
+])
+# progtest.m4 serial 3 (gettext-0.12)
+dnl Copyright (C) 1996-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+# Search path for a program which passes the given test.
+
+dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
+dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN([AM_PATH_PROG_WITH_TEST],
+[
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+# Find out how to test for executable files. Don't use a zero-byte file,
+# as systems may use methods other than mode bits to determine executability.
+cat >conf$$.file <<_ASEOF
+#! /bin/sh
+exit 0
+_ASEOF
+chmod +x conf$$.file
+if test -x conf$$.file >/dev/null 2>&1; then
+ ac_executable_p="test -x"
+else
+ ac_executable_p="test -f"
+fi
+rm -f conf$$.file
+
+# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+ [[\\/]]* | ?:[[\\/]]*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+ ;;
+ *)
+ ac_save_IFS="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in ifelse([$5], , $PATH, [$5]); do
+ IFS="$ac_save_IFS"
+ test -z "$ac_dir" && ac_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $ac_executable_p "$ac_dir/$ac_word$ac_exec_ext"; then
+ if [$3]; then
+ ac_cv_path_$1="$ac_dir/$ac_word$ac_exec_ext"
+ break 2
+ fi
+ fi
+ done
+ done
+ IFS="$ac_save_IFS"
+dnl If no 4th arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
+])dnl
+ ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then
+ AC_MSG_RESULT([$]$1)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+# stdint_h.m4 serial 3 (gettext-0.12)
+dnl Copyright (C) 1997-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Paul Eggert.
+
+# Define HAVE_STDINT_H_WITH_UINTMAX if <stdint.h> exists,
+# doesn't clash with <sys/types.h>, and declares uintmax_t.
+
+AC_DEFUN([jm_AC_HEADER_STDINT_H],
+[
+ AC_CACHE_CHECK([for stdint.h], jm_ac_cv_header_stdint_h,
+ [AC_TRY_COMPILE(
+ [#include <sys/types.h>
+#include <stdint.h>],
+ [uintmax_t i = (uintmax_t) -1;],
+ jm_ac_cv_header_stdint_h=yes,
+ jm_ac_cv_header_stdint_h=no)])
+ if test $jm_ac_cv_header_stdint_h = yes; then
+ AC_DEFINE_UNQUOTED(HAVE_STDINT_H_WITH_UINTMAX, 1,
+ [Define if <stdint.h> exists, doesn't clash with <sys/types.h>,
+ and declares uintmax_t. ])
+ fi
+])
+# uintmax_t.m4 serial 7 (gettext-0.12)
+dnl Copyright (C) 1997-2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Paul Eggert.
+
+AC_PREREQ(2.13)
+
+# Define uintmax_t to 'unsigned long' or 'unsigned long long'
+# if it is not already defined in <stdint.h> or <inttypes.h>.
+
+AC_DEFUN([jm_AC_TYPE_UINTMAX_T],
+[
+ AC_REQUIRE([jm_AC_HEADER_INTTYPES_H])
+ AC_REQUIRE([jm_AC_HEADER_STDINT_H])
+ if test $jm_ac_cv_header_inttypes_h = no && test $jm_ac_cv_header_stdint_h = no; then
+ AC_REQUIRE([jm_AC_TYPE_UNSIGNED_LONG_LONG])
+ test $ac_cv_type_unsigned_long_long = yes \
+ && ac_type='unsigned long long' \
+ || ac_type='unsigned long'
+ AC_DEFINE_UNQUOTED(uintmax_t, $ac_type,
+ [Define to unsigned long or unsigned long long
+ if <stdint.h> and <inttypes.h> don't define.])
+ else
+ AC_DEFINE(HAVE_UINTMAX_T, 1,
+ [Define if you have the 'uintmax_t' type in <stdint.h> or <inttypes.h>.])
+ fi
+])
+# ulonglong.m4 serial 2 (fileutils-4.0.32, gettext-0.10.40)
+dnl Copyright (C) 1999-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl From Paul Eggert.
+
+AC_DEFUN([jm_AC_TYPE_UNSIGNED_LONG_LONG],
+[
+ AC_CACHE_CHECK([for unsigned long long], ac_cv_type_unsigned_long_long,
+ [AC_TRY_LINK([unsigned long long ull = 1; int i = 63;],
+ [unsigned long long ullmax = (unsigned long long) -1;
+ return ull << i | ull >> i | ullmax / ull | ullmax % ull;],
+ ac_cv_type_unsigned_long_long=yes,
+ ac_cv_type_unsigned_long_long=no)])
+ if test $ac_cv_type_unsigned_long_long = yes; then
+ AC_DEFINE(HAVE_UNSIGNED_LONG_LONG, 1,
+ [Define if you have the unsigned long long type.])
+ fi
+])
diff --git a/arrayfunc.c b/arrayfunc.c
index 3bdd54f5..1353b2d9 100644
--- a/arrayfunc.c
+++ b/arrayfunc.c
@@ -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);
diff --git a/arrayfunc.c~ b/arrayfunc.c~
new file mode 100644
index 00000000..7d903563
--- /dev/null
+++ b/arrayfunc.c~
@@ -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 */
diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0
index 5e3141af..bc91a845 100644
--- a/autom4te.cache/output.0
+++ b/autom4te.cache/output.0
@@ -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
diff --git a/autom4te.cache/traces.0 b/autom4te.cache/traces.0
index aa0ecd3e..db36d1ed 100644
--- a/autom4te.cache/traces.0
+++ b/autom4te.cache/traces.0
@@ -290,824 +290,819 @@ m4trace:configure.in:371: -1- AH_OUTPUT([_LARGE_FILES], [/* Define for large fil
#undef _LARGE_FILES])
m4trace:configure.in:407: -1- AC_SUBST([CROSS_COMPILE])
m4trace:configure.in:409: -1- AC_SUBST([SIGNAMES_H])
-m4trace:configure.in:418: -1- AC_SUBST([CC_FOR_BUILD])
-m4trace:configure.in:441: -1- _m4_warn([obsolete], [The macro `ac_cv_prog_gcc' is obsolete.
+m4trace:configure.in:410: -1- AC_SUBST([SIGNAMES_O])
+m4trace:configure.in:419: -1- AC_SUBST([CC_FOR_BUILD])
+m4trace:configure.in:442: -1- _m4_warn([obsolete], [The macro `ac_cv_prog_gcc' is obsolete.
You should run autoupdate.], [autoconf/c.m4:440: ac_cv_prog_gcc is expanded from...
-configure.in:441: the top level])
-m4trace:configure.in:460: -1- AC_SUBST([CFLAGS])
-m4trace:configure.in:461: -1- AC_SUBST([CPPFLAGS])
-m4trace:configure.in:462: -1- AC_SUBST([LDFLAGS])
-m4trace:configure.in:463: -1- AC_SUBST([STATIC_LD])
-m4trace:configure.in:465: -1- AC_SUBST([CFLAGS_FOR_BUILD])
-m4trace:configure.in:466: -1- AC_SUBST([CPPFLAGS_FOR_BUILD])
-m4trace:configure.in:467: -1- AC_SUBST([LDFLAGS_FOR_BUILD])
-m4trace:configure.in:469: -1- AC_PROG_GCC_TRADITIONAL
-m4trace:configure.in:481: -1- AC_CHECK_LIB([termcap], [tgetent], [bash_cv_termcap_lib=libtermcap], [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
+configure.in:442: the top level])
+m4trace:configure.in:461: -1- AC_SUBST([CFLAGS])
+m4trace:configure.in:462: -1- AC_SUBST([CPPFLAGS])
+m4trace:configure.in:463: -1- AC_SUBST([LDFLAGS])
+m4trace:configure.in:464: -1- AC_SUBST([STATIC_LD])
+m4trace:configure.in:466: -1- AC_SUBST([CFLAGS_FOR_BUILD])
+m4trace:configure.in:467: -1- AC_SUBST([CPPFLAGS_FOR_BUILD])
+m4trace:configure.in:468: -1- AC_SUBST([LDFLAGS_FOR_BUILD])
+m4trace:configure.in:470: -1- AC_PROG_GCC_TRADITIONAL
+m4trace:configure.in:482: -1- AC_CHECK_LIB([termcap], [tgetent], [bash_cv_termcap_lib=libtermcap], [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
[AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
[AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
bash_cv_termcap_lib=gnutermcap)])])])
-m4trace:configure.in:481: -1- AC_CHECK_LIB([tinfo], [tgetent], [bash_cv_termcap_lib=libtinfo], [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
+m4trace:configure.in:482: -1- AC_CHECK_LIB([tinfo], [tgetent], [bash_cv_termcap_lib=libtinfo], [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
[AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
bash_cv_termcap_lib=gnutermcap)])])
-m4trace:configure.in:481: -1- AC_CHECK_LIB([curses], [tgetent], [bash_cv_termcap_lib=libcurses], [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
+m4trace:configure.in:482: -1- AC_CHECK_LIB([curses], [tgetent], [bash_cv_termcap_lib=libcurses], [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
bash_cv_termcap_lib=gnutermcap)])
-m4trace:configure.in:481: -1- AC_CHECK_LIB([ncurses], [tgetent], [bash_cv_termcap_lib=libncurses], [bash_cv_termcap_lib=gnutermcap])
-m4trace:configure.in:481: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+m4trace:configure.in:482: -1- AC_CHECK_LIB([ncurses], [tgetent], [bash_cv_termcap_lib=libncurses], [bash_cv_termcap_lib=gnutermcap])
+m4trace:configure.in:482: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1825: RL_LIB_READLINE_VERSION is expanded from...
-configure.in:481: the top level])
-m4trace:configure.in:481: -1- AC_DEFINE_TRACE_LITERAL([RL_READLINE_VERSION])
-m4trace:configure.in:481: -1- AH_OUTPUT([RL_READLINE_VERSION], [/* encoded version of the installed readline library */
+configure.in:482: the top level])
+m4trace:configure.in:482: -1- AC_DEFINE_TRACE_LITERAL([RL_READLINE_VERSION])
+m4trace:configure.in:482: -1- AH_OUTPUT([RL_READLINE_VERSION], [/* encoded version of the installed readline library */
#undef RL_READLINE_VERSION])
-m4trace:configure.in:481: -1- AC_DEFINE_TRACE_LITERAL([RL_VERSION_MAJOR])
-m4trace:configure.in:481: -1- AH_OUTPUT([RL_VERSION_MAJOR], [/* major version of installed readline library */
+m4trace:configure.in:482: -1- AC_DEFINE_TRACE_LITERAL([RL_VERSION_MAJOR])
+m4trace:configure.in:482: -1- AH_OUTPUT([RL_VERSION_MAJOR], [/* major version of installed readline library */
#undef RL_VERSION_MAJOR])
-m4trace:configure.in:481: -1- AC_DEFINE_TRACE_LITERAL([RL_VERSION_MINOR])
-m4trace:configure.in:481: -1- AH_OUTPUT([RL_VERSION_MINOR], [/* minor version of installed readline library */
+m4trace:configure.in:482: -1- AC_DEFINE_TRACE_LITERAL([RL_VERSION_MINOR])
+m4trace:configure.in:482: -1- AH_OUTPUT([RL_VERSION_MINOR], [/* minor version of installed readline library */
#undef RL_VERSION_MINOR])
-m4trace:configure.in:481: -1- AC_SUBST([RL_VERSION])
-m4trace:configure.in:481: -1- AC_SUBST([RL_MAJOR])
-m4trace:configure.in:481: -1- AC_SUBST([RL_MINOR])
-m4trace:configure.in:494: -1- AC_DEFINE_TRACE_LITERAL([READLINE])
-m4trace:configure.in:529: -1- AC_DEFINE_TRACE_LITERAL([HISTORY])
-m4trace:configure.in:532: -1- AC_DEFINE_TRACE_LITERAL([BANG_HISTORY])
-m4trace:configure.in:562: -1- AC_SUBST([READLINE_LIB])
-m4trace:configure.in:563: -1- AC_SUBST([READLINE_DEP])
-m4trace:configure.in:564: -1- AC_SUBST([RL_LIBDIR])
-m4trace:configure.in:565: -1- AC_SUBST([RL_INCLUDEDIR])
-m4trace:configure.in:566: -1- AC_SUBST([RL_INCLUDE])
-m4trace:configure.in:567: -1- AC_SUBST([HISTORY_LIB])
-m4trace:configure.in:568: -1- AC_SUBST([HISTORY_DEP])
-m4trace:configure.in:569: -1- AC_SUBST([HIST_LIBDIR])
-m4trace:configure.in:570: -1- AC_SUBST([TILDE_LIB])
-m4trace:configure.in:575: -1- AC_PROG_INSTALL
-m4trace:configure.in:575: -1- AC_SUBST([INSTALL_PROGRAM])
-m4trace:configure.in:575: -1- AC_SUBST([INSTALL_SCRIPT])
-m4trace:configure.in:575: -1- AC_SUBST([INSTALL_DATA])
-m4trace:configure.in:576: -1- AC_SUBST([AR])
-m4trace:configure.in:580: -1- AC_PROG_RANLIB
-m4trace:configure.in:580: -1- AC_SUBST([RANLIB])
-m4trace:configure.in:580: -1- AC_SUBST([ac_ct_RANLIB])
-m4trace:configure.in:581: -1- AC_PROG_YACC
-m4trace:configure.in:581: -1- AC_SUBST([YACC])
-m4trace:configure.in:582: -1- AC_PROG_MAKE_SET
-m4trace:configure.in:582: -1- AC_SUBST([SET_MAKE])
-m4trace:configure.in:588: -1- AC_SUBST([MAKE_SHELL])
-m4trace:configure.in:610: -1- AC_SUBST([SIZE])
-m4trace:configure.in:613: -1- AC_DEFINE_TRACE_LITERAL([_GNU_SOURCE])
-m4trace:configure.in:616: -1- AC_C_CONST
-m4trace:configure.in:616: -1- AC_DEFINE_TRACE_LITERAL([const])
-m4trace:configure.in:616: -1- AH_OUTPUT([const], [/* Define to empty if `const\' does not conform to ANSI C. */
+m4trace:configure.in:482: -1- AC_SUBST([RL_VERSION])
+m4trace:configure.in:482: -1- AC_SUBST([RL_MAJOR])
+m4trace:configure.in:482: -1- AC_SUBST([RL_MINOR])
+m4trace:configure.in:495: -1- AC_DEFINE_TRACE_LITERAL([READLINE])
+m4trace:configure.in:530: -1- AC_DEFINE_TRACE_LITERAL([HISTORY])
+m4trace:configure.in:533: -1- AC_DEFINE_TRACE_LITERAL([BANG_HISTORY])
+m4trace:configure.in:563: -1- AC_SUBST([READLINE_LIB])
+m4trace:configure.in:564: -1- AC_SUBST([READLINE_DEP])
+m4trace:configure.in:565: -1- AC_SUBST([RL_LIBDIR])
+m4trace:configure.in:566: -1- AC_SUBST([RL_INCLUDEDIR])
+m4trace:configure.in:567: -1- AC_SUBST([RL_INCLUDE])
+m4trace:configure.in:568: -1- AC_SUBST([HISTORY_LIB])
+m4trace:configure.in:569: -1- AC_SUBST([HISTORY_DEP])
+m4trace:configure.in:570: -1- AC_SUBST([HIST_LIBDIR])
+m4trace:configure.in:571: -1- AC_SUBST([TILDE_LIB])
+m4trace:configure.in:576: -1- AC_PROG_INSTALL
+m4trace:configure.in:576: -1- AC_SUBST([INSTALL_PROGRAM])
+m4trace:configure.in:576: -1- AC_SUBST([INSTALL_SCRIPT])
+m4trace:configure.in:576: -1- AC_SUBST([INSTALL_DATA])
+m4trace:configure.in:577: -1- AC_SUBST([AR])
+m4trace:configure.in:581: -1- AC_PROG_RANLIB
+m4trace:configure.in:581: -1- AC_SUBST([RANLIB])
+m4trace:configure.in:581: -1- AC_SUBST([ac_ct_RANLIB])
+m4trace:configure.in:582: -1- AC_PROG_YACC
+m4trace:configure.in:582: -1- AC_SUBST([YACC])
+m4trace:configure.in:583: -1- AC_PROG_MAKE_SET
+m4trace:configure.in:583: -1- AC_SUBST([SET_MAKE])
+m4trace:configure.in:589: -1- AC_SUBST([MAKE_SHELL])
+m4trace:configure.in:611: -1- AC_SUBST([SIZE])
+m4trace:configure.in:614: -1- AC_DEFINE_TRACE_LITERAL([_GNU_SOURCE])
+m4trace:configure.in:617: -1- AC_C_CONST
+m4trace:configure.in:617: -1- AC_DEFINE_TRACE_LITERAL([const])
+m4trace:configure.in:617: -1- AH_OUTPUT([const], [/* Define to empty if `const\' does not conform to ANSI C. */
#undef const])
-m4trace:configure.in:617: -1- AC_C_INLINE
-m4trace:configure.in:617: -1- AH_OUTPUT([inline], [/* Define to `__inline__\' or `__inline\' if that\'s what the C compiler
+m4trace:configure.in:618: -1- AC_C_INLINE
+m4trace:configure.in:618: -1- AH_OUTPUT([inline], [/* Define to `__inline__\' or `__inline\' if that\'s what the C compiler
calls it, or to nothing if \'inline\' is not supported under any name. */
#ifndef __cplusplus
#undef inline
#endif])
-m4trace:configure.in:618: -1- AC_DEFINE_TRACE_LITERAL([WORDS_BIGENDIAN])
-m4trace:configure.in:618: -1- AH_OUTPUT([WORDS_BIGENDIAN], [/* Define to 1 if your processor stores words with the most significant byte
+m4trace:configure.in:619: -1- AC_DEFINE_TRACE_LITERAL([WORDS_BIGENDIAN])
+m4trace:configure.in:619: -1- AH_OUTPUT([WORDS_BIGENDIAN], [/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
#undef WORDS_BIGENDIAN])
-m4trace:configure.in:619: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRINGIZE])
-m4trace:configure.in:619: -1- AH_OUTPUT([HAVE_STRINGIZE], [/* Define to 1 if cpp supports the ANSI @%:@ stringizing operator. */
+m4trace:configure.in:620: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRINGIZE])
+m4trace:configure.in:620: -1- AH_OUTPUT([HAVE_STRINGIZE], [/* Define to 1 if cpp supports the ANSI @%:@ stringizing operator. */
#undef HAVE_STRINGIZE])
-m4trace:configure.in:620: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LONG_DOUBLE])
-m4trace:configure.in:620: -1- AH_OUTPUT([HAVE_LONG_DOUBLE], [/* Define to 1 if long double works and has more range or precision than
+m4trace:configure.in:621: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LONG_DOUBLE])
+m4trace:configure.in:621: -1- AH_OUTPUT([HAVE_LONG_DOUBLE], [/* Define to 1 if long double works and has more range or precision than
double. */
#undef HAVE_LONG_DOUBLE])
-m4trace:configure.in:621: -1- AC_DEFINE_TRACE_LITERAL([PROTOTYPES])
-m4trace:configure.in:621: -1- AH_OUTPUT([PROTOTYPES], [/* Define to 1 if the C compiler supports function prototypes. */
+m4trace:configure.in:622: -1- AC_DEFINE_TRACE_LITERAL([PROTOTYPES])
+m4trace:configure.in:622: -1- AH_OUTPUT([PROTOTYPES], [/* Define to 1 if the C compiler supports function prototypes. */
#undef PROTOTYPES])
-m4trace:configure.in:621: -1- AC_DEFINE_TRACE_LITERAL([__PROTOTYPES])
-m4trace:configure.in:621: -1- AH_OUTPUT([__PROTOTYPES], [/* Define like PROTOTYPES; this can be used by system headers. */
+m4trace:configure.in:622: -1- AC_DEFINE_TRACE_LITERAL([__PROTOTYPES])
+m4trace:configure.in:622: -1- AH_OUTPUT([__PROTOTYPES], [/* Define like PROTOTYPES; this can be used by system headers. */
#undef __PROTOTYPES])
-m4trace:configure.in:622: -1- AH_OUTPUT([__CHAR_UNSIGNED__], [/* Define to 1 if type `char\' is unsigned and you are not using gcc. */
+m4trace:configure.in:623: -1- AH_OUTPUT([__CHAR_UNSIGNED__], [/* Define to 1 if type `char\' is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
# undef __CHAR_UNSIGNED__
#endif])
-m4trace:configure.in:622: -1- AC_DEFINE_TRACE_LITERAL([__CHAR_UNSIGNED__])
-m4trace:configure.in:625: -1- AM_GNU_GETTEXT([no-libtool], [need-ngettext], [lib/intl])
-m4trace:configure.in:625: -1- AC_SUBST([MKINSTALLDIRS])
-m4trace:configure.in:625: -1- AC_SUBST([USE_NLS])
-m4trace:configure.in:625: -1- AC_SUBST([MSGFMT])
-m4trace:configure.in:625: -1- AC_SUBST([GMSGFMT], [$ac_cv_path_GMSGFMT])
-m4trace:configure.in:625: -1- AC_SUBST([XGETTEXT])
-m4trace:configure.in:625: -1- AC_SUBST([MSGMERGE])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_OUTPUT_COMMANDS' is obsolete.
+m4trace:configure.in:623: -1- AC_DEFINE_TRACE_LITERAL([__CHAR_UNSIGNED__])
+m4trace:configure.in:626: -1- AM_GNU_GETTEXT([no-libtool], [need-ngettext], [lib/intl])
+m4trace:configure.in:626: -1- AC_SUBST([MKINSTALLDIRS])
+m4trace:configure.in:626: -1- AC_SUBST([USE_NLS])
+m4trace:configure.in:626: -1- AC_SUBST([MSGFMT])
+m4trace:configure.in:626: -1- AC_SUBST([GMSGFMT], [$ac_cv_path_GMSGFMT])
+m4trace:configure.in:626: -1- AC_SUBST([XGETTEXT])
+m4trace:configure.in:626: -1- AC_SUBST([MSGMERGE])
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_OUTPUT_COMMANDS' is obsolete.
You should run autoupdate.], [autoconf/status.m4:318: AC_OUTPUT_COMMANDS is expanded from...
aclocal.m4:3788: AM_PO_SUBDIRS is expanded from...
-configure.in:625: AM_PO_SUBDIRS is required by...
+configure.in:626: AM_PO_SUBDIRS is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -3- _m4_warn([obsolete], [The macro `_AC_OUTPUT_COMMANDS_CNT' is obsolete.
+configure.in:626: the top level])
+m4trace:configure.in:626: -3- _m4_warn([obsolete], [The macro `_AC_OUTPUT_COMMANDS_CNT' is obsolete.
You should run autoupdate.], [autoconf/status.m4:321: _AC_OUTPUT_COMMANDS_CNT is expanded from...
autoconf/status.m4:318: AC_OUTPUT_COMMANDS is expanded from...
aclocal.m4:3788: AM_PO_SUBDIRS is expanded from...
-configure.in:625: AM_PO_SUBDIRS is required by...
+configure.in:626: AM_PO_SUBDIRS is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_TYPE_OFF_T
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([off_t])
-m4trace:configure.in:625: -1- AH_OUTPUT([off_t], [/* Define to `long\' if <sys/types.h> does not define. */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_TYPE_OFF_T
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([off_t])
+m4trace:configure.in:626: -1- AH_OUTPUT([off_t], [/* Define to `long\' if <sys/types.h> does not define. */
#undef off_t])
-m4trace:configure.in:625: -1- AC_TYPE_SIZE_T
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([size_t])
-m4trace:configure.in:625: -1- AH_OUTPUT([size_t], [/* Define to `unsigned\' if <sys/types.h> does not define. */
+m4trace:configure.in:626: -1- AC_TYPE_SIZE_T
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([size_t])
+m4trace:configure.in:626: -1- AH_OUTPUT([size_t], [/* Define to `unsigned\' if <sys/types.h> does not define. */
#undef size_t])
-m4trace:configure.in:625: -1- AC_FUNC_ALLOCA
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_ALLOCA_H], [/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+m4trace:configure.in:626: -1- AC_FUNC_ALLOCA
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA_H])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_ALLOCA_H], [/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#undef HAVE_ALLOCA_H])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_ALLOCA], [/* Define to 1 if you have `alloca\', as a function or macro. */
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_ALLOCA], [/* Define to 1 if you have `alloca\', as a function or macro. */
#undef HAVE_ALLOCA])
-m4trace:configure.in:625: -1- AC_LIBSOURCE([alloca.c])
-m4trace:configure.in:625: -1- AC_SUBST([ALLOCA], [alloca.$ac_objext])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([C_ALLOCA])
-m4trace:configure.in:625: -1- AH_OUTPUT([C_ALLOCA], [/* Define to 1 if using `alloca.c\'. */
+m4trace:configure.in:626: -1- AC_LIBSOURCE([alloca.c])
+m4trace:configure.in:626: -1- AC_SUBST([ALLOCA], [alloca.$ac_objext])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([C_ALLOCA])
+m4trace:configure.in:626: -1- AH_OUTPUT([C_ALLOCA], [/* Define to 1 if using `alloca.c\'. */
#undef C_ALLOCA])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([CRAY_STACKSEG_END])
-m4trace:configure.in:625: -1- AH_OUTPUT([CRAY_STACKSEG_END], [/* Define to one of `_getb67\', `GETB67\', `getb67\' for Cray-2 and Cray-YMP
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([CRAY_STACKSEG_END])
+m4trace:configure.in:626: -1- AH_OUTPUT([CRAY_STACKSEG_END], [/* Define to one of `_getb67\', `GETB67\', `getb67\' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c\' support on those systems.
*/
#undef CRAY_STACKSEG_END])
-m4trace:configure.in:625: -1- AH_OUTPUT([STACK_DIRECTION], [/* If using the C implementation of alloca, define if you know the
+m4trace:configure.in:626: -1- AH_OUTPUT([STACK_DIRECTION], [/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
@%:@undef STACK_DIRECTION])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([STACK_DIRECTION])
-m4trace:configure.in:625: -1- AC_FUNC_MMAP
-m4trace:configure.in:625: -1- AC_CHECK_HEADERS([stdlib.h unistd.h])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([STACK_DIRECTION])
+m4trace:configure.in:626: -1- AC_FUNC_MMAP
+m4trace:configure.in:626: -1- AC_CHECK_HEADERS([stdlib.h unistd.h])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H])
-m4trace:configure.in:625: -1- AC_CHECK_FUNCS([getpagesize])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_GETPAGESIZE], [/* Define to 1 if you have the `getpagesize\' function. */
+m4trace:configure.in:626: -1- AC_CHECK_FUNCS([getpagesize])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_GETPAGESIZE], [/* Define to 1 if you have the `getpagesize\' function. */
#undef HAVE_GETPAGESIZE])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MMAP])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_MMAP], [/* Define to 1 if you have a working `mmap\' system call. */
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MMAP])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_MMAP], [/* Define to 1 if you have a working `mmap\' system call. */
#undef HAVE_MMAP])
-m4trace:configure.in:625: -1- AC_SUBST([GLIBC21])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+m4trace:configure.in:626: -1- AC_SUBST([GLIBC21])
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2581: gt_INTDIV0 is expanded from...
-configure.in:625: gt_INTDIV0 is required by...
+configure.in:626: gt_INTDIV0 is required by...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([INTDIV0_RAISES_SIGFPE])
-m4trace:configure.in:625: -1- AH_OUTPUT([INTDIV0_RAISES_SIGFPE], [/* Define if integer division by zero raises signal SIGFPE. */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([INTDIV0_RAISES_SIGFPE])
+m4trace:configure.in:626: -1- AH_OUTPUT([INTDIV0_RAISES_SIGFPE], [/* Define if integer division by zero raises signal SIGFPE. */
#undef INTDIV0_RAISES_SIGFPE])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2636: jm_AC_HEADER_INTTYPES_H is expanded from...
-configure.in:625: jm_AC_HEADER_INTTYPES_H is required by...
+configure.in:626: jm_AC_HEADER_INTTYPES_H is required by...
aclocal.m4:3939: jm_AC_TYPE_UINTMAX_T is expanded from...
-configure.in:625: jm_AC_TYPE_UINTMAX_T is required by...
+configure.in:626: jm_AC_TYPE_UINTMAX_T is required by...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_INTTYPES_H_WITH_UINTMAX])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_INTTYPES_H_WITH_UINTMAX], [/* Define if <inttypes.h> exists, doesn\'t clash with <sys/types.h>, and
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_INTTYPES_H_WITH_UINTMAX])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_INTTYPES_H_WITH_UINTMAX], [/* Define if <inttypes.h> exists, doesn\'t clash with <sys/types.h>, and
declares uintmax_t. */
#undef HAVE_INTTYPES_H_WITH_UINTMAX])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:3907: jm_AC_HEADER_STDINT_H is expanded from...
-configure.in:625: jm_AC_HEADER_STDINT_H is required by...
+configure.in:626: jm_AC_HEADER_STDINT_H is required by...
aclocal.m4:3939: jm_AC_TYPE_UINTMAX_T is expanded from...
-configure.in:625: jm_AC_TYPE_UINTMAX_T is required by...
+configure.in:626: jm_AC_TYPE_UINTMAX_T is required by...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STDINT_H_WITH_UINTMAX])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STDINT_H_WITH_UINTMAX], [/* Define if <stdint.h> exists, doesn\'t clash with <sys/types.h>, and declares
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STDINT_H_WITH_UINTMAX])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STDINT_H_WITH_UINTMAX], [/* Define if <stdint.h> exists, doesn\'t clash with <sys/types.h>, and declares
uintmax_t. */
#undef HAVE_STDINT_H_WITH_UINTMAX])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:3962: jm_AC_TYPE_UNSIGNED_LONG_LONG is expanded from...
-configure.in:625: jm_AC_TYPE_UNSIGNED_LONG_LONG is required by...
+configure.in:626: jm_AC_TYPE_UNSIGNED_LONG_LONG is required by...
aclocal.m4:3939: jm_AC_TYPE_UINTMAX_T is expanded from...
-configure.in:625: jm_AC_TYPE_UINTMAX_T is required by...
+configure.in:626: jm_AC_TYPE_UINTMAX_T is required by...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_UNSIGNED_LONG_LONG])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_UNSIGNED_LONG_LONG], [/* Define if you have the unsigned long long type. */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_UNSIGNED_LONG_LONG])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_UNSIGNED_LONG_LONG], [/* Define if you have the unsigned long long type. */
#undef HAVE_UNSIGNED_LONG_LONG])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([uintmax_t])
-m4trace:configure.in:625: -1- AH_OUTPUT([uintmax_t], [/* Define to unsigned long or unsigned long long if <stdint.h> and
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([uintmax_t])
+m4trace:configure.in:626: -1- AH_OUTPUT([uintmax_t], [/* Define to unsigned long or unsigned long long if <stdint.h> and
<inttypes.h> don\'t define. */
#undef uintmax_t])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_UINTMAX_T])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_UINTMAX_T], [/* Define if you have the \'uintmax_t\' type in <stdint.h> or <inttypes.h>. */
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_UINTMAX_T])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_UINTMAX_T], [/* Define if you have the \'uintmax_t\' type in <stdint.h> or <inttypes.h>. */
#undef HAVE_UINTMAX_T])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2608: gt_HEADER_INTTYPES_H is expanded from...
-configure.in:625: gt_HEADER_INTTYPES_H is required by...
+configure.in:626: gt_HEADER_INTTYPES_H is required by...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_INTTYPES_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define if <inttypes.h> exists and doesn\'t clash with <sys/types.h>. */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_INTTYPES_H])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define if <inttypes.h> exists and doesn\'t clash with <sys/types.h>. */
#undef HAVE_INTTYPES_H])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2668: gt_INTTYPES_PRI is expanded from...
-configure.in:625: gt_INTTYPES_PRI is required by...
+configure.in:626: gt_INTTYPES_PRI is required by...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([PRI_MACROS_BROKEN])
-m4trace:configure.in:625: -1- AH_OUTPUT([PRI_MACROS_BROKEN], [/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([PRI_MACROS_BROKEN])
+m4trace:configure.in:626: -1- AH_OUTPUT([PRI_MACROS_BROKEN], [/* Define if <inttypes.h> exists and defines unusable PRI* macros. */
#undef PRI_MACROS_BROKEN])
-m4trace:configure.in:625: -1- AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \
+m4trace:configure.in:626: -1- AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h stddef.h \
stdlib.h string.h unistd.h sys/param.h])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_ARGZ_H], [/* Define to 1 if you have the <argz.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_ARGZ_H], [/* Define to 1 if you have the <argz.h> header file. */
#undef HAVE_ARGZ_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_LIMITS_H], [/* Define to 1 if you have the <limits.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_LIMITS_H], [/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_LOCALE_H], [/* Define to 1 if you have the <locale.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_LOCALE_H], [/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_NL_TYPES_H], [/* Define to 1 if you have the <nl_types.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_NL_TYPES_H], [/* Define to 1 if you have the <nl_types.h> header file. */
#undef HAVE_NL_TYPES_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_MALLOC_H], [/* Define to 1 if you have the <malloc.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_MALLOC_H], [/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_SYS_PARAM_H], [/* Define to 1 if you have the <sys/param.h> header file. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_SYS_PARAM_H], [/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H])
-m4trace:configure.in:625: -1- AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \
+m4trace:configure.in:626: -1- AC_CHECK_FUNCS([feof_unlocked fgets_unlocked getc_unlocked getcwd getegid \
geteuid getgid getuid mempcpy munmap putenv setenv setlocale stpcpy \
strcasecmp strdup strtoul tsearch __argz_count __argz_stringify __argz_next \
__fsetlocking])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_FEOF_UNLOCKED], [/* Define to 1 if you have the `feof_unlocked\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_FEOF_UNLOCKED], [/* Define to 1 if you have the `feof_unlocked\' function. */
#undef HAVE_FEOF_UNLOCKED])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_FGETS_UNLOCKED], [/* Define to 1 if you have the `fgets_unlocked\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_FGETS_UNLOCKED], [/* Define to 1 if you have the `fgets_unlocked\' function. */
#undef HAVE_FGETS_UNLOCKED])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_GETC_UNLOCKED], [/* Define to 1 if you have the `getc_unlocked\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_GETC_UNLOCKED], [/* Define to 1 if you have the `getc_unlocked\' function. */
#undef HAVE_GETC_UNLOCKED])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you have the `getcwd\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you have the `getcwd\' function. */
#undef HAVE_GETCWD])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_GETEGID], [/* Define to 1 if you have the `getegid\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_GETEGID], [/* Define to 1 if you have the `getegid\' function. */
#undef HAVE_GETEGID])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_GETEUID], [/* Define to 1 if you have the `geteuid\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_GETEUID], [/* Define to 1 if you have the `geteuid\' function. */
#undef HAVE_GETEUID])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_GETGID], [/* Define to 1 if you have the `getgid\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_GETGID], [/* Define to 1 if you have the `getgid\' function. */
#undef HAVE_GETGID])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_GETUID], [/* Define to 1 if you have the `getuid\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_GETUID], [/* Define to 1 if you have the `getuid\' function. */
#undef HAVE_GETUID])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_MEMPCPY], [/* Define to 1 if you have the `mempcpy\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_MEMPCPY], [/* Define to 1 if you have the `mempcpy\' function. */
#undef HAVE_MEMPCPY])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_MUNMAP], [/* Define to 1 if you have the `munmap\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_MUNMAP], [/* Define to 1 if you have the `munmap\' function. */
#undef HAVE_MUNMAP])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_PUTENV], [/* Define to 1 if you have the `putenv\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_PUTENV], [/* Define to 1 if you have the `putenv\' function. */
#undef HAVE_PUTENV])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_SETENV], [/* Define to 1 if you have the `setenv\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_SETENV], [/* Define to 1 if you have the `setenv\' function. */
#undef HAVE_SETENV])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_SETLOCALE], [/* Define to 1 if you have the `setlocale\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_SETLOCALE], [/* Define to 1 if you have the `setlocale\' function. */
#undef HAVE_SETLOCALE])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STPCPY], [/* Define to 1 if you have the `stpcpy\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STPCPY], [/* Define to 1 if you have the `stpcpy\' function. */
#undef HAVE_STPCPY])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STRCASECMP], [/* Define to 1 if you have the `strcasecmp\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STRCASECMP], [/* Define to 1 if you have the `strcasecmp\' function. */
#undef HAVE_STRCASECMP])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STRDUP], [/* Define to 1 if you have the `strdup\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STRDUP], [/* Define to 1 if you have the `strdup\' function. */
#undef HAVE_STRDUP])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_STRTOUL], [/* Define to 1 if you have the `strtoul\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_STRTOUL], [/* Define to 1 if you have the `strtoul\' function. */
#undef HAVE_STRTOUL])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_TSEARCH], [/* Define to 1 if you have the `tsearch\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_TSEARCH], [/* Define to 1 if you have the `tsearch\' function. */
#undef HAVE_TSEARCH])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE___ARGZ_COUNT], [/* Define to 1 if you have the `__argz_count\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE___ARGZ_COUNT], [/* Define to 1 if you have the `__argz_count\' function. */
#undef HAVE___ARGZ_COUNT])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE___ARGZ_STRINGIFY], [/* Define to 1 if you have the `__argz_stringify\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE___ARGZ_STRINGIFY], [/* Define to 1 if you have the `__argz_stringify\' function. */
#undef HAVE___ARGZ_STRINGIFY])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE___ARGZ_NEXT], [/* Define to 1 if you have the `__argz_next\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE___ARGZ_NEXT], [/* Define to 1 if you have the `__argz_next\' function. */
#undef HAVE___ARGZ_NEXT])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE___FSETLOCKING], [/* Define to 1 if you have the `__fsetlocking\' function. */
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE___FSETLOCKING], [/* Define to 1 if you have the `__fsetlocking\' function. */
#undef HAVE___FSETLOCKING])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2481: AM_ICONV_LINK is expanded from...
aclocal.m4:2509: AM_ICONV is expanded from...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2481: AM_ICONV_LINK is expanded from...
aclocal.m4:2509: AM_ICONV is expanded from...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ICONV])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_ICONV], [/* Define if you have the iconv() function. */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ICONV])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_ICONV], [/* Define if you have the iconv() function. */
#undef HAVE_ICONV])
-m4trace:configure.in:625: -1- AC_SUBST([LIBICONV])
-m4trace:configure.in:625: -1- AC_SUBST([LTLIBICONV])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:626: -1- AC_SUBST([LIBICONV])
+m4trace:configure.in:626: -1- AC_SUBST([LTLIBICONV])
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:2509: AM_ICONV is expanded from...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([ICONV_CONST])
-m4trace:configure.in:625: -1- AH_OUTPUT([ICONV_CONST], [/* Define as const if the declaration of iconv() needs const. */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([ICONV_CONST])
+m4trace:configure.in:626: -1- AH_OUTPUT([ICONV_CONST], [/* Define as const if the declaration of iconv() needs const. */
#undef ICONV_CONST])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:1959: AM_LANGINFO_CODESET is expanded from...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LANGINFO_CODESET])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_LANGINFO_CODESET], [/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LANGINFO_CODESET])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_LANGINFO_CODESET], [/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#undef HAVE_LANGINFO_CODESET])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2726: AM_LC_MESSAGES is expanded from...
aclocal.m4:2370: AM_INTL_SUBDIR is expanded from...
-configure.in:625: AM_INTL_SUBDIR is required by...
+configure.in:626: AM_INTL_SUBDIR is required by...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LC_MESSAGES])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_LC_MESSAGES], [/* Define if your <locale.h> file defines LC_MESSAGES. */
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LC_MESSAGES])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_LC_MESSAGES], [/* Define if your <locale.h> file defines LC_MESSAGES. */
#undef HAVE_LC_MESSAGES])
-m4trace:configure.in:625: -1- AC_SUBST([INTLBISON])
-m4trace:configure.in:625: -1- AC_SUBST([USE_NLS])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:626: -1- AC_SUBST([INTLBISON])
+m4trace:configure.in:626: -1- AC_SUBST([USE_NLS])
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:2300: AM_GNU_GETTEXT is expanded from...
-configure.in:625: the top level])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([ENABLE_NLS])
-m4trace:configure.in:625: -1- AH_OUTPUT([ENABLE_NLS], [/* Define to 1 if translation of program messages to the user\'s native
+configure.in:626: the top level])
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([ENABLE_NLS])
+m4trace:configure.in:626: -1- AH_OUTPUT([ENABLE_NLS], [/* Define to 1 if translation of program messages to the user\'s native
language is requested. */
#undef ENABLE_NLS])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETTEXT])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_GETTEXT], [/* Define if the GNU gettext() function is already present or preinstalled. */
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETTEXT])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_GETTEXT], [/* Define if the GNU gettext() function is already present or preinstalled. */
#undef HAVE_GETTEXT])
-m4trace:configure.in:625: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DCGETTEXT])
-m4trace:configure.in:625: -1- AH_OUTPUT([HAVE_DCGETTEXT], [/* Define if the GNU dcgettext() function is already present or preinstalled.
+m4trace:configure.in:626: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DCGETTEXT])
+m4trace:configure.in:626: -1- AH_OUTPUT([HAVE_DCGETTEXT], [/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
#undef HAVE_DCGETTEXT])
-m4trace:configure.in:625: -1- AC_SUBST([BUILD_INCLUDED_LIBINTL])
-m4trace:configure.in:625: -1- AC_SUBST([USE_INCLUDED_LIBINTL])
-m4trace:configure.in:625: -1- AC_SUBST([CATOBJEXT])
-m4trace:configure.in:625: -1- AC_SUBST([DATADIRNAME])
-m4trace:configure.in:625: -1- AC_SUBST([INSTOBJEXT])
-m4trace:configure.in:625: -1- AC_SUBST([GENCAT])
-m4trace:configure.in:625: -1- AC_SUBST([INTLOBJS])
-m4trace:configure.in:625: -1- AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX])
-m4trace:configure.in:625: -1- AC_SUBST([INTLLIBS])
-m4trace:configure.in:625: -1- AC_SUBST([LIBINTL])
-m4trace:configure.in:625: -1- AC_SUBST([LTLIBINTL])
-m4trace:configure.in:625: -1- AC_SUBST([POSUB])
-m4trace:configure.in:628: -1- AC_HEADER_DIRENT
-m4trace:configure.in:628: -1- AH_OUTPUT([HAVE_DIRENT_H], [/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR\'.
+m4trace:configure.in:626: -1- AC_SUBST([BUILD_INCLUDED_LIBINTL])
+m4trace:configure.in:626: -1- AC_SUBST([USE_INCLUDED_LIBINTL])
+m4trace:configure.in:626: -1- AC_SUBST([CATOBJEXT])
+m4trace:configure.in:626: -1- AC_SUBST([DATADIRNAME])
+m4trace:configure.in:626: -1- AC_SUBST([INSTOBJEXT])
+m4trace:configure.in:626: -1- AC_SUBST([GENCAT])
+m4trace:configure.in:626: -1- AC_SUBST([INTLOBJS])
+m4trace:configure.in:626: -1- AC_SUBST([INTL_LIBTOOL_SUFFIX_PREFIX])
+m4trace:configure.in:626: -1- AC_SUBST([INTLLIBS])
+m4trace:configure.in:626: -1- AC_SUBST([LIBINTL])
+m4trace:configure.in:626: -1- AC_SUBST([LTLIBINTL])
+m4trace:configure.in:626: -1- AC_SUBST([POSUB])
+m4trace:configure.in:629: -1- AC_HEADER_DIRENT
+m4trace:configure.in:629: -1- AH_OUTPUT([HAVE_DIRENT_H], [/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR\'.
*/
#undef HAVE_DIRENT_H])
-m4trace:configure.in:628: -1- AH_OUTPUT([HAVE_SYS_NDIR_H], [/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR\'.
+m4trace:configure.in:629: -1- AH_OUTPUT([HAVE_SYS_NDIR_H], [/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR\'.
*/
#undef HAVE_SYS_NDIR_H])
-m4trace:configure.in:628: -1- AH_OUTPUT([HAVE_SYS_DIR_H], [/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR\'.
+m4trace:configure.in:629: -1- AH_OUTPUT([HAVE_SYS_DIR_H], [/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR\'.
*/
#undef HAVE_SYS_DIR_H])
-m4trace:configure.in:628: -1- AH_OUTPUT([HAVE_NDIR_H], [/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR\'. */
+m4trace:configure.in:629: -1- AH_OUTPUT([HAVE_NDIR_H], [/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR\'. */
#undef HAVE_NDIR_H])
-m4trace:configure.in:629: -1- AC_HEADER_TIME
-m4trace:configure.in:629: -1- AC_DEFINE_TRACE_LITERAL([TIME_WITH_SYS_TIME])
-m4trace:configure.in:629: -1- AH_OUTPUT([TIME_WITH_SYS_TIME], [/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+m4trace:configure.in:630: -1- AC_HEADER_TIME
+m4trace:configure.in:630: -1- AC_DEFINE_TRACE_LITERAL([TIME_WITH_SYS_TIME])
+m4trace:configure.in:630: -1- AH_OUTPUT([TIME_WITH_SYS_TIME], [/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME])
-m4trace:configure.in:631: -1- AC_CHECK_HEADERS([inttypes.h])
-m4trace:configure.in:631: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
+m4trace:configure.in:632: -1- AC_CHECK_HEADERS([inttypes.h])
+m4trace:configure.in:632: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H])
-m4trace:configure.in:635: -1- AC_CHECK_HEADERS([unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \
+m4trace:configure.in:636: -1- AC_CHECK_HEADERS([unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \
memory.h locale.h termcap.h termio.h termios.h dlfcn.h \
stddef.h stdint.h netdb.h pwd.h grp.h strings.h regex.h])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_STDARG_H], [/* Define to 1 if you have the <stdarg.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_STDARG_H], [/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_VARARGS_H], [/* Define to 1 if you have the <varargs.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_VARARGS_H], [/* Define to 1 if you have the <varargs.h> header file. */
#undef HAVE_VARARGS_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_LIMITS_H], [/* Define to 1 if you have the <limits.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_LIMITS_H], [/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the <memory.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_LOCALE_H], [/* Define to 1 if you have the <locale.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_LOCALE_H], [/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_TERMCAP_H], [/* Define to 1 if you have the <termcap.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_TERMCAP_H], [/* Define to 1 if you have the <termcap.h> header file. */
#undef HAVE_TERMCAP_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_TERMIO_H], [/* Define to 1 if you have the <termio.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_TERMIO_H], [/* Define to 1 if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_TERMIOS_H], [/* Define to 1 if you have the <termios.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_TERMIOS_H], [/* Define to 1 if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_DLFCN_H], [/* Define to 1 if you have the <dlfcn.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_DLFCN_H], [/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_NETDB_H], [/* Define to 1 if you have the <netdb.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_NETDB_H], [/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_PWD_H], [/* Define to 1 if you have the <pwd.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_PWD_H], [/* Define to 1 if you have the <pwd.h> header file. */
#undef HAVE_PWD_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_GRP_H], [/* Define to 1 if you have the <grp.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_GRP_H], [/* Define to 1 if you have the <grp.h> header file. */
#undef HAVE_GRP_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the <strings.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H])
-m4trace:configure.in:635: -1- AH_OUTPUT([HAVE_REGEX_H], [/* Define to 1 if you have the <regex.h> header file. */
+m4trace:configure.in:636: -1- AH_OUTPUT([HAVE_REGEX_H], [/* Define to 1 if you have the <regex.h> header file. */
#undef HAVE_REGEX_H])
-m4trace:configure.in:638: -1- AC_CHECK_HEADERS([sys/pte.h sys/stream.h sys/select.h sys/file.h \
+m4trace:configure.in:639: -1- AC_CHECK_HEADERS([sys/pte.h sys/stream.h sys/select.h sys/file.h \
sys/resource.h sys/param.h sys/socket.h sys/stat.h \
sys/time.h sys/times.h sys/types.h sys/wait.h])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_PTE_H], [/* Define to 1 if you have the <sys/pte.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_PTE_H], [/* Define to 1 if you have the <sys/pte.h> header file. */
#undef HAVE_SYS_PTE_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_STREAM_H], [/* Define to 1 if you have the <sys/stream.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_STREAM_H], [/* Define to 1 if you have the <sys/stream.h> header file. */
#undef HAVE_SYS_STREAM_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_SELECT_H], [/* Define to 1 if you have the <sys/select.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_SELECT_H], [/* Define to 1 if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_FILE_H], [/* Define to 1 if you have the <sys/file.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_FILE_H], [/* Define to 1 if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_RESOURCE_H], [/* Define to 1 if you have the <sys/resource.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_RESOURCE_H], [/* Define to 1 if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_PARAM_H], [/* Define to 1 if you have the <sys/param.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_PARAM_H], [/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_SOCKET_H], [/* Define to 1 if you have the <sys/socket.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_SOCKET_H], [/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the <sys/stat.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_TIME_H], [/* Define to 1 if you have the <sys/time.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_TIME_H], [/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_TIMES_H], [/* Define to 1 if you have the <sys/times.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_TIMES_H], [/* Define to 1 if you have the <sys/times.h> header file. */
#undef HAVE_SYS_TIMES_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the <sys/types.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H])
-m4trace:configure.in:638: -1- AH_OUTPUT([HAVE_SYS_WAIT_H], [/* Define to 1 if you have the <sys/wait.h> header file. */
+m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_SYS_WAIT_H], [/* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H])
-m4trace:configure.in:639: -1- AC_CHECK_HEADERS([netinet/in.h arpa/inet.h])
-m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_NETINET_IN_H], [/* Define to 1 if you have the <netinet/in.h> header file. */
+m4trace:configure.in:640: -1- AC_CHECK_HEADERS([netinet/in.h arpa/inet.h])
+m4trace:configure.in:640: -1- AH_OUTPUT([HAVE_NETINET_IN_H], [/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H])
-m4trace:configure.in:639: -1- AH_OUTPUT([HAVE_ARPA_INET_H], [/* Define to 1 if you have the <arpa/inet.h> header file. */
+m4trace:configure.in:640: -1- AH_OUTPUT([HAVE_ARPA_INET_H], [/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H])
-m4trace:configure.in:650: -1- AC_FUNC_ALLOCA
-m4trace:configure.in:650: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA_H])
-m4trace:configure.in:650: -1- AH_OUTPUT([HAVE_ALLOCA_H], [/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+m4trace:configure.in:651: -1- AC_FUNC_ALLOCA
+m4trace:configure.in:651: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA_H])
+m4trace:configure.in:651: -1- AH_OUTPUT([HAVE_ALLOCA_H], [/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#undef HAVE_ALLOCA_H])
-m4trace:configure.in:650: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA])
-m4trace:configure.in:650: -1- AH_OUTPUT([HAVE_ALLOCA], [/* Define to 1 if you have `alloca\', as a function or macro. */
+m4trace:configure.in:651: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA])
+m4trace:configure.in:651: -1- AH_OUTPUT([HAVE_ALLOCA], [/* Define to 1 if you have `alloca\', as a function or macro. */
#undef HAVE_ALLOCA])
-m4trace:configure.in:650: -1- AC_LIBSOURCE([alloca.c])
-m4trace:configure.in:650: -1- AC_SUBST([ALLOCA], [alloca.$ac_objext])
-m4trace:configure.in:650: -1- AC_DEFINE_TRACE_LITERAL([C_ALLOCA])
-m4trace:configure.in:650: -1- AH_OUTPUT([C_ALLOCA], [/* Define to 1 if using `alloca.c\'. */
+m4trace:configure.in:651: -1- AC_LIBSOURCE([alloca.c])
+m4trace:configure.in:651: -1- AC_SUBST([ALLOCA], [alloca.$ac_objext])
+m4trace:configure.in:651: -1- AC_DEFINE_TRACE_LITERAL([C_ALLOCA])
+m4trace:configure.in:651: -1- AH_OUTPUT([C_ALLOCA], [/* Define to 1 if using `alloca.c\'. */
#undef C_ALLOCA])
-m4trace:configure.in:650: -1- AC_DEFINE_TRACE_LITERAL([CRAY_STACKSEG_END])
-m4trace:configure.in:650: -1- AH_OUTPUT([CRAY_STACKSEG_END], [/* Define to one of `_getb67\', `GETB67\', `getb67\' for Cray-2 and Cray-YMP
+m4trace:configure.in:651: -1- AC_DEFINE_TRACE_LITERAL([CRAY_STACKSEG_END])
+m4trace:configure.in:651: -1- AH_OUTPUT([CRAY_STACKSEG_END], [/* Define to one of `_getb67\', `GETB67\', `getb67\' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c\' support on those systems.
*/
#undef CRAY_STACKSEG_END])
-m4trace:configure.in:650: -1- AH_OUTPUT([STACK_DIRECTION], [/* If using the C implementation of alloca, define if you know the
+m4trace:configure.in:651: -1- AH_OUTPUT([STACK_DIRECTION], [/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
@%:@undef STACK_DIRECTION])
-m4trace:configure.in:650: -1- AC_DEFINE_TRACE_LITERAL([STACK_DIRECTION])
-m4trace:configure.in:651: -1- AC_FUNC_GETPGRP
-m4trace:configure.in:651: -1- AC_DEFINE_TRACE_LITERAL([GETPGRP_VOID])
-m4trace:configure.in:651: -1- AH_OUTPUT([GETPGRP_VOID], [/* Define to 1 if the `getpgrp\' function requires zero arguments. */
+m4trace:configure.in:651: -1- AC_DEFINE_TRACE_LITERAL([STACK_DIRECTION])
+m4trace:configure.in:652: -1- AC_FUNC_GETPGRP
+m4trace:configure.in:652: -1- AC_DEFINE_TRACE_LITERAL([GETPGRP_VOID])
+m4trace:configure.in:652: -1- AH_OUTPUT([GETPGRP_VOID], [/* Define to 1 if the `getpgrp\' function requires zero arguments. */
#undef GETPGRP_VOID])
-m4trace:configure.in:652: -1- AC_FUNC_SETVBUF_REVERSED
-m4trace:configure.in:652: -1- AC_DEFINE_TRACE_LITERAL([SETVBUF_REVERSED])
-m4trace:configure.in:652: -1- AH_OUTPUT([SETVBUF_REVERSED], [/* Define to 1 if the `setvbuf\' function takes the buffering type as its
+m4trace:configure.in:653: -1- AC_FUNC_SETVBUF_REVERSED
+m4trace:configure.in:653: -1- AC_DEFINE_TRACE_LITERAL([SETVBUF_REVERSED])
+m4trace:configure.in:653: -1- AH_OUTPUT([SETVBUF_REVERSED], [/* Define to 1 if the `setvbuf\' function takes the buffering type as its
second argument and the buffer pointer as the third, as on System V before
release 3. */
#undef SETVBUF_REVERSED])
-m4trace:configure.in:653: -1- AC_FUNC_VPRINTF
-m4trace:configure.in:653: -1- AC_CHECK_FUNCS([vprintf], [
+m4trace:configure.in:654: -1- AC_FUNC_VPRINTF
+m4trace:configure.in:654: -1- AC_CHECK_FUNCS([vprintf], [
AC_CHECK_FUNC(_doprnt,
[AC_DEFINE(HAVE_DOPRNT, 1,
[Define to 1 if you don't have `vprintf' but do have
`_doprnt.'])])])
-m4trace:configure.in:653: -1- AH_OUTPUT([HAVE_VPRINTF], [/* Define to 1 if you have the `vprintf\' function. */
+m4trace:configure.in:654: -1- AH_OUTPUT([HAVE_VPRINTF], [/* Define to 1 if you have the `vprintf\' function. */
#undef HAVE_VPRINTF])
-m4trace:configure.in:653: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DOPRNT])
-m4trace:configure.in:653: -1- AH_OUTPUT([HAVE_DOPRNT], [/* Define to 1 if you don\'t have `vprintf\' but do have `_doprnt.\' */
+m4trace:configure.in:654: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DOPRNT])
+m4trace:configure.in:654: -1- AH_OUTPUT([HAVE_DOPRNT], [/* Define to 1 if you don\'t have `vprintf\' but do have `_doprnt.\' */
#undef HAVE_DOPRNT])
-m4trace:configure.in:654: -1- AC_FUNC_STRCOLL
-m4trace:configure.in:654: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRCOLL])
-m4trace:configure.in:654: -1- AH_OUTPUT([HAVE_STRCOLL], [/* Define to 1 if you have the `strcoll\' function and it is properly defined.
+m4trace:configure.in:655: -1- AC_FUNC_STRCOLL
+m4trace:configure.in:655: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRCOLL])
+m4trace:configure.in:655: -1- AH_OUTPUT([HAVE_STRCOLL], [/* Define to 1 if you have the `strcoll\' function and it is properly defined.
*/
#undef HAVE_STRCOLL])
-m4trace:configure.in:675: -1- AC_DEFINE_TRACE_LITERAL([HAVE_VPRINTF])
-m4trace:configure.in:680: -1- AC_LIBSOURCE([vprint.c])
-m4trace:configure.in:680: -1- AC_SUBST([LIB@&t@OBJS])
-m4trace:configure.in:684: -1- AC_TYPE_SIGNAL
-m4trace:configure.in:684: -1- AC_DEFINE_TRACE_LITERAL([RETSIGTYPE])
-m4trace:configure.in:684: -1- AH_OUTPUT([RETSIGTYPE], [/* Define as the return type of signal handlers (`int\' or `void\'). */
+m4trace:configure.in:676: -1- AC_DEFINE_TRACE_LITERAL([HAVE_VPRINTF])
+m4trace:configure.in:681: -1- AC_LIBSOURCE([vprint.c])
+m4trace:configure.in:681: -1- AC_SUBST([LIB@&t@OBJS])
+m4trace:configure.in:685: -1- AC_TYPE_SIGNAL
+m4trace:configure.in:685: -1- AC_DEFINE_TRACE_LITERAL([RETSIGTYPE])
+m4trace:configure.in:685: -1- AH_OUTPUT([RETSIGTYPE], [/* Define as the return type of signal handlers (`int\' or `void\'). */
#undef RETSIGTYPE])
-m4trace:configure.in:687: -2- AC_DEFINE_TRACE_LITERAL([HAVE_SETOSTYPE])
-m4trace:configure.in:688: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WAIT3])
-m4trace:configure.in:689: -2- AC_DEFINE_TRACE_LITERAL([HAVE_ISINF_IN_LIBC])
-m4trace:configure.in:692: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MKFIFO])
-m4trace:configure.in:692: -2- AC_DEFINE_TRACE_LITERAL([MKFIFO_MISSING])
-m4trace:configure.in:698: -1- AC_CHECK_FUNCS([dup2 fcntl getdtablesize getgroups gethostname getpagesize \
+m4trace:configure.in:688: -2- AC_DEFINE_TRACE_LITERAL([HAVE_SETOSTYPE])
+m4trace:configure.in:689: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WAIT3])
+m4trace:configure.in:690: -2- AC_DEFINE_TRACE_LITERAL([HAVE_ISINF_IN_LIBC])
+m4trace:configure.in:693: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MKFIFO])
+m4trace:configure.in:693: -2- AC_DEFINE_TRACE_LITERAL([MKFIFO_MISSING])
+m4trace:configure.in:699: -1- AC_CHECK_FUNCS([dup2 fcntl getdtablesize getgroups gethostname getpagesize \
getpeername getrlimit getrusage gettimeofday kill killpg \
lstat readlink sbrk select setdtablesize tcgetpgrp uname \
ulimit waitpid])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_DUP2], [/* Define to 1 if you have the `dup2\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_DUP2], [/* Define to 1 if you have the `dup2\' function. */
#undef HAVE_DUP2])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_FCNTL], [/* Define to 1 if you have the `fcntl\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_FCNTL], [/* Define to 1 if you have the `fcntl\' function. */
#undef HAVE_FCNTL])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_GETDTABLESIZE], [/* Define to 1 if you have the `getdtablesize\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_GETDTABLESIZE], [/* Define to 1 if you have the `getdtablesize\' function. */
#undef HAVE_GETDTABLESIZE])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_GETGROUPS], [/* Define to 1 if you have the `getgroups\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_GETGROUPS], [/* Define to 1 if you have the `getgroups\' function. */
#undef HAVE_GETGROUPS])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_GETHOSTNAME], [/* Define to 1 if you have the `gethostname\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_GETHOSTNAME], [/* Define to 1 if you have the `gethostname\' function. */
#undef HAVE_GETHOSTNAME])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_GETPAGESIZE], [/* Define to 1 if you have the `getpagesize\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_GETPAGESIZE], [/* Define to 1 if you have the `getpagesize\' function. */
#undef HAVE_GETPAGESIZE])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_GETPEERNAME], [/* Define to 1 if you have the `getpeername\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_GETPEERNAME], [/* Define to 1 if you have the `getpeername\' function. */
#undef HAVE_GETPEERNAME])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_GETRLIMIT], [/* Define to 1 if you have the `getrlimit\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_GETRLIMIT], [/* Define to 1 if you have the `getrlimit\' function. */
#undef HAVE_GETRLIMIT])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_GETRUSAGE], [/* Define to 1 if you have the `getrusage\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_GETRUSAGE], [/* Define to 1 if you have the `getrusage\' function. */
#undef HAVE_GETRUSAGE])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_GETTIMEOFDAY], [/* Define to 1 if you have the `gettimeofday\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_GETTIMEOFDAY], [/* Define to 1 if you have the `gettimeofday\' function. */
#undef HAVE_GETTIMEOFDAY])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_KILL], [/* Define to 1 if you have the `kill\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_KILL], [/* Define to 1 if you have the `kill\' function. */
#undef HAVE_KILL])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_KILLPG], [/* Define to 1 if you have the `killpg\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_KILLPG], [/* Define to 1 if you have the `killpg\' function. */
#undef HAVE_KILLPG])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_LSTAT], [/* Define to 1 if you have the `lstat\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_LSTAT], [/* Define to 1 if you have the `lstat\' function. */
#undef HAVE_LSTAT])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_READLINK], [/* Define to 1 if you have the `readlink\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_READLINK], [/* Define to 1 if you have the `readlink\' function. */
#undef HAVE_READLINK])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_SBRK], [/* Define to 1 if you have the `sbrk\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_SBRK], [/* Define to 1 if you have the `sbrk\' function. */
#undef HAVE_SBRK])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_SELECT], [/* Define to 1 if you have the `select\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_SELECT], [/* Define to 1 if you have the `select\' function. */
#undef HAVE_SELECT])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_SETDTABLESIZE], [/* Define to 1 if you have the `setdtablesize\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_SETDTABLESIZE], [/* Define to 1 if you have the `setdtablesize\' function. */
#undef HAVE_SETDTABLESIZE])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_TCGETPGRP], [/* Define to 1 if you have the `tcgetpgrp\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_TCGETPGRP], [/* Define to 1 if you have the `tcgetpgrp\' function. */
#undef HAVE_TCGETPGRP])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_UNAME], [/* Define to 1 if you have the `uname\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_UNAME], [/* Define to 1 if you have the `uname\' function. */
#undef HAVE_UNAME])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_ULIMIT], [/* Define to 1 if you have the `ulimit\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_ULIMIT], [/* Define to 1 if you have the `ulimit\' function. */
#undef HAVE_ULIMIT])
-m4trace:configure.in:698: -1- AH_OUTPUT([HAVE_WAITPID], [/* Define to 1 if you have the `waitpid\' function. */
+m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_WAITPID], [/* Define to 1 if you have the `waitpid\' function. */
#undef HAVE_WAITPID])
-m4trace:configure.in:699: -1- AC_LIBSOURCE([rename.c])
-m4trace:configure.in:699: -1- AC_CHECK_FUNCS([rename], [], [_AC_LIBOBJ($ac_func)])
-m4trace:configure.in:699: -1- AH_OUTPUT([HAVE_RENAME], [/* Define to 1 if you have the `rename\' function. */
+m4trace:configure.in:700: -1- AC_LIBSOURCE([rename.c])
+m4trace:configure.in:700: -1- AC_CHECK_FUNCS([rename], [], [_AC_LIBOBJ($ac_func)])
+m4trace:configure.in:700: -1- AH_OUTPUT([HAVE_RENAME], [/* Define to 1 if you have the `rename\' function. */
#undef HAVE_RENAME])
-m4trace:configure.in:699: -1- AC_SUBST([LIB@&t@OBJS])
-m4trace:configure.in:706: -1- AC_CHECK_FUNCS([bcopy bzero confstr fnmatch \
+m4trace:configure.in:700: -1- AC_SUBST([LIB@&t@OBJS])
+m4trace:configure.in:707: -1- AC_CHECK_FUNCS([bcopy bzero confstr fnmatch \
getaddrinfo gethostbyname getservbyname getservent inet_aton \
memmove pathconf putenv raise regcomp regexec \
setenv setlinebuf setlocale setvbuf siginterrupt strchr \
sysconf tcgetattr times ttyname tzset unsetenv])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_BCOPY], [/* Define to 1 if you have the `bcopy\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_BCOPY], [/* Define to 1 if you have the `bcopy\' function. */
#undef HAVE_BCOPY])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_BZERO], [/* Define to 1 if you have the `bzero\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_BZERO], [/* Define to 1 if you have the `bzero\' function. */
#undef HAVE_BZERO])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_CONFSTR], [/* Define to 1 if you have the `confstr\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_CONFSTR], [/* Define to 1 if you have the `confstr\' function. */
#undef HAVE_CONFSTR])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_FNMATCH], [/* Define to 1 if you have the `fnmatch\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_FNMATCH], [/* Define to 1 if you have the `fnmatch\' function. */
#undef HAVE_FNMATCH])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_GETADDRINFO], [/* Define to 1 if you have the `getaddrinfo\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_GETADDRINFO], [/* Define to 1 if you have the `getaddrinfo\' function. */
#undef HAVE_GETADDRINFO])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_GETHOSTBYNAME], [/* Define to 1 if you have the `gethostbyname\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_GETHOSTBYNAME], [/* Define to 1 if you have the `gethostbyname\' function. */
#undef HAVE_GETHOSTBYNAME])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_GETSERVBYNAME], [/* Define to 1 if you have the `getservbyname\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_GETSERVBYNAME], [/* Define to 1 if you have the `getservbyname\' function. */
#undef HAVE_GETSERVBYNAME])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_GETSERVENT], [/* Define to 1 if you have the `getservent\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_GETSERVENT], [/* Define to 1 if you have the `getservent\' function. */
#undef HAVE_GETSERVENT])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_INET_ATON], [/* Define to 1 if you have the `inet_aton\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_INET_ATON], [/* Define to 1 if you have the `inet_aton\' function. */
#undef HAVE_INET_ATON])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_MEMMOVE], [/* Define to 1 if you have the `memmove\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_MEMMOVE], [/* Define to 1 if you have the `memmove\' function. */
#undef HAVE_MEMMOVE])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_PATHCONF], [/* Define to 1 if you have the `pathconf\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_PATHCONF], [/* Define to 1 if you have the `pathconf\' function. */
#undef HAVE_PATHCONF])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_PUTENV], [/* Define to 1 if you have the `putenv\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_PUTENV], [/* Define to 1 if you have the `putenv\' function. */
#undef HAVE_PUTENV])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_RAISE], [/* Define to 1 if you have the `raise\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_RAISE], [/* Define to 1 if you have the `raise\' function. */
#undef HAVE_RAISE])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_REGCOMP], [/* Define to 1 if you have the `regcomp\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_REGCOMP], [/* Define to 1 if you have the `regcomp\' function. */
#undef HAVE_REGCOMP])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_REGEXEC], [/* Define to 1 if you have the `regexec\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_REGEXEC], [/* Define to 1 if you have the `regexec\' function. */
#undef HAVE_REGEXEC])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_SETENV], [/* Define to 1 if you have the `setenv\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_SETENV], [/* Define to 1 if you have the `setenv\' function. */
#undef HAVE_SETENV])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_SETLINEBUF], [/* Define to 1 if you have the `setlinebuf\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_SETLINEBUF], [/* Define to 1 if you have the `setlinebuf\' function. */
#undef HAVE_SETLINEBUF])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_SETLOCALE], [/* Define to 1 if you have the `setlocale\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_SETLOCALE], [/* Define to 1 if you have the `setlocale\' function. */
#undef HAVE_SETLOCALE])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_SETVBUF], [/* Define to 1 if you have the `setvbuf\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_SETVBUF], [/* Define to 1 if you have the `setvbuf\' function. */
#undef HAVE_SETVBUF])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_SIGINTERRUPT], [/* Define to 1 if you have the `siginterrupt\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_SIGINTERRUPT], [/* Define to 1 if you have the `siginterrupt\' function. */
#undef HAVE_SIGINTERRUPT])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_STRCHR], [/* Define to 1 if you have the `strchr\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_STRCHR], [/* Define to 1 if you have the `strchr\' function. */
#undef HAVE_STRCHR])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_SYSCONF], [/* Define to 1 if you have the `sysconf\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_SYSCONF], [/* Define to 1 if you have the `sysconf\' function. */
#undef HAVE_SYSCONF])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_TCGETATTR], [/* Define to 1 if you have the `tcgetattr\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_TCGETATTR], [/* Define to 1 if you have the `tcgetattr\' function. */
#undef HAVE_TCGETATTR])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_TIMES], [/* Define to 1 if you have the `times\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_TIMES], [/* Define to 1 if you have the `times\' function. */
#undef HAVE_TIMES])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_TTYNAME], [/* Define to 1 if you have the `ttyname\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_TTYNAME], [/* Define to 1 if you have the `ttyname\' function. */
#undef HAVE_TTYNAME])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_TZSET], [/* Define to 1 if you have the `tzset\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_TZSET], [/* Define to 1 if you have the `tzset\' function. */
#undef HAVE_TZSET])
-m4trace:configure.in:706: -1- AH_OUTPUT([HAVE_UNSETENV], [/* Define to 1 if you have the `unsetenv\' function. */
+m4trace:configure.in:707: -1- AH_OUTPUT([HAVE_UNSETENV], [/* Define to 1 if you have the `unsetenv\' function. */
#undef HAVE_UNSETENV])
-m4trace:configure.in:708: -1- AC_CHECK_FUNCS([vsnprintf snprintf vasprintf asprintf])
-m4trace:configure.in:708: -1- AH_OUTPUT([HAVE_VSNPRINTF], [/* Define to 1 if you have the `vsnprintf\' function. */
+m4trace:configure.in:709: -1- AC_CHECK_FUNCS([vsnprintf snprintf vasprintf asprintf])
+m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_VSNPRINTF], [/* Define to 1 if you have the `vsnprintf\' function. */
#undef HAVE_VSNPRINTF])
-m4trace:configure.in:708: -1- AH_OUTPUT([HAVE_SNPRINTF], [/* Define to 1 if you have the `snprintf\' function. */
+m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_SNPRINTF], [/* Define to 1 if you have the `snprintf\' function. */
#undef HAVE_SNPRINTF])
-m4trace:configure.in:708: -1- AH_OUTPUT([HAVE_VASPRINTF], [/* Define to 1 if you have the `vasprintf\' function. */
+m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_VASPRINTF], [/* Define to 1 if you have the `vasprintf\' function. */
#undef HAVE_VASPRINTF])
-m4trace:configure.in:708: -1- AH_OUTPUT([HAVE_ASPRINTF], [/* Define to 1 if you have the `asprintf\' function. */
+m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_ASPRINTF], [/* Define to 1 if you have the `asprintf\' function. */
#undef HAVE_ASPRINTF])
-m4trace:configure.in:709: -1- AC_CHECK_FUNCS([isascii isblank isgraph isprint isspace isxdigit])
-m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_ISASCII], [/* Define to 1 if you have the `isascii\' function. */
+m4trace:configure.in:710: -1- AC_CHECK_FUNCS([isascii isblank isgraph isprint isspace isxdigit])
+m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_ISASCII], [/* Define to 1 if you have the `isascii\' function. */
#undef HAVE_ISASCII])
-m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_ISBLANK], [/* Define to 1 if you have the `isblank\' function. */
+m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_ISBLANK], [/* Define to 1 if you have the `isblank\' function. */
#undef HAVE_ISBLANK])
-m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_ISGRAPH], [/* Define to 1 if you have the `isgraph\' function. */
+m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_ISGRAPH], [/* Define to 1 if you have the `isgraph\' function. */
#undef HAVE_ISGRAPH])
-m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_ISPRINT], [/* Define to 1 if you have the `isprint\' function. */
+m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_ISPRINT], [/* Define to 1 if you have the `isprint\' function. */
#undef HAVE_ISPRINT])
-m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_ISSPACE], [/* Define to 1 if you have the `isspace\' function. */
+m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_ISSPACE], [/* Define to 1 if you have the `isspace\' function. */
#undef HAVE_ISSPACE])
-m4trace:configure.in:709: -1- AH_OUTPUT([HAVE_ISXDIGIT], [/* Define to 1 if you have the `isxdigit\' function. */
+m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_ISXDIGIT], [/* Define to 1 if you have the `isxdigit\' function. */
#undef HAVE_ISXDIGIT])
-m4trace:configure.in:710: -1- AC_CHECK_FUNCS([getpwent getpwnam getpwuid])
-m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_GETPWENT], [/* Define to 1 if you have the `getpwent\' function. */
+m4trace:configure.in:711: -1- AC_CHECK_FUNCS([getpwent getpwnam getpwuid])
+m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_GETPWENT], [/* Define to 1 if you have the `getpwent\' function. */
#undef HAVE_GETPWENT])
-m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_GETPWNAM], [/* Define to 1 if you have the `getpwnam\' function. */
+m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_GETPWNAM], [/* Define to 1 if you have the `getpwnam\' function. */
#undef HAVE_GETPWNAM])
-m4trace:configure.in:710: -1- AH_OUTPUT([HAVE_GETPWUID], [/* Define to 1 if you have the `getpwuid\' function. */
+m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_GETPWUID], [/* Define to 1 if you have the `getpwuid\' function. */
#undef HAVE_GETPWUID])
-m4trace:configure.in:711: -1- AC_LIBSOURCE([getcwd.c])
-m4trace:configure.in:711: -1- AC_LIBSOURCE([memset.c])
-m4trace:configure.in:711: -1- AC_LIBSOURCE([strcasecmp.c])
-m4trace:configure.in:711: -1- AC_LIBSOURCE([strerror.c])
-m4trace:configure.in:711: -1- AC_LIBSOURCE([strftime.c])
-m4trace:configure.in:711: -1- AC_LIBSOURCE([strnlen.c])
-m4trace:configure.in:711: -1- AC_LIBSOURCE([strpbrk.c])
-m4trace:configure.in:711: -1- AC_LIBSOURCE([strstr.c])
-m4trace:configure.in:711: -1- AC_CHECK_FUNCS([getcwd memset strcasecmp strerror strftime strnlen strpbrk strstr], [], [_AC_LIBOBJ($ac_func)])
-m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you have the `getcwd\' function. */
+m4trace:configure.in:712: -1- AC_LIBSOURCE([getcwd.c])
+m4trace:configure.in:712: -1- AC_LIBSOURCE([memset.c])
+m4trace:configure.in:712: -1- AC_LIBSOURCE([strcasecmp.c])
+m4trace:configure.in:712: -1- AC_LIBSOURCE([strerror.c])
+m4trace:configure.in:712: -1- AC_LIBSOURCE([strftime.c])
+m4trace:configure.in:712: -1- AC_LIBSOURCE([strnlen.c])
+m4trace:configure.in:712: -1- AC_LIBSOURCE([strpbrk.c])
+m4trace:configure.in:712: -1- AC_LIBSOURCE([strstr.c])
+m4trace:configure.in:712: -1- AC_CHECK_FUNCS([getcwd memset strcasecmp strerror strftime strnlen strpbrk strstr], [], [_AC_LIBOBJ($ac_func)])
+m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you have the `getcwd\' function. */
#undef HAVE_GETCWD])
-m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_MEMSET], [/* Define to 1 if you have the `memset\' function. */
+m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_MEMSET], [/* Define to 1 if you have the `memset\' function. */
#undef HAVE_MEMSET])
-m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_STRCASECMP], [/* Define to 1 if you have the `strcasecmp\' function. */
+m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRCASECMP], [/* Define to 1 if you have the `strcasecmp\' function. */
#undef HAVE_STRCASECMP])
-m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_STRERROR], [/* Define to 1 if you have the `strerror\' function. */
+m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRERROR], [/* Define to 1 if you have the `strerror\' function. */
#undef HAVE_STRERROR])
-m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_STRFTIME], [/* Define to 1 if you have the `strftime\' function. */
+m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRFTIME], [/* Define to 1 if you have the `strftime\' function. */
#undef HAVE_STRFTIME])
-m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_STRNLEN], [/* Define to 1 if you have the `strnlen\' function. */
+m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRNLEN], [/* Define to 1 if you have the `strnlen\' function. */
#undef HAVE_STRNLEN])
-m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_STRPBRK], [/* Define to 1 if you have the `strpbrk\' function. */
+m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRPBRK], [/* Define to 1 if you have the `strpbrk\' function. */
#undef HAVE_STRPBRK])
-m4trace:configure.in:711: -1- AH_OUTPUT([HAVE_STRSTR], [/* Define to 1 if you have the `strstr\' function. */
+m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRSTR], [/* Define to 1 if you have the `strstr\' function. */
#undef HAVE_STRSTR])
-m4trace:configure.in:711: -1- AC_SUBST([LIB@&t@OBJS])
-m4trace:configure.in:712: -1- AC_LIBSOURCE([strtod.c])
-m4trace:configure.in:712: -1- AC_LIBSOURCE([strtol.c])
-m4trace:configure.in:712: -1- AC_LIBSOURCE([strtoul.c])
-m4trace:configure.in:712: -1- AC_LIBSOURCE([strtoll.c])
-m4trace:configure.in:712: -1- AC_LIBSOURCE([strtoull.c])
-m4trace:configure.in:712: -1- AC_LIBSOURCE([strtoimax.c])
-m4trace:configure.in:712: -1- AC_LIBSOURCE([strtoumax.c])
-m4trace:configure.in:712: -1- AC_CHECK_FUNCS([strtod strtol strtoul strtoll strtoull strtoimax strtoumax], [], [_AC_LIBOBJ($ac_func)])
-m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRTOD], [/* Define to 1 if you have the `strtod\' function. */
+m4trace:configure.in:712: -1- AC_SUBST([LIB@&t@OBJS])
+m4trace:configure.in:713: -1- AC_LIBSOURCE([strtod.c])
+m4trace:configure.in:713: -1- AC_LIBSOURCE([strtol.c])
+m4trace:configure.in:713: -1- AC_LIBSOURCE([strtoul.c])
+m4trace:configure.in:713: -1- AC_LIBSOURCE([strtoll.c])
+m4trace:configure.in:713: -1- AC_LIBSOURCE([strtoull.c])
+m4trace:configure.in:713: -1- AC_LIBSOURCE([strtoimax.c])
+m4trace:configure.in:713: -1- AC_LIBSOURCE([strtoumax.c])
+m4trace:configure.in:713: -1- AC_CHECK_FUNCS([strtod strtol strtoul strtoll strtoull strtoimax strtoumax], [], [_AC_LIBOBJ($ac_func)])
+m4trace:configure.in:713: -1- AH_OUTPUT([HAVE_STRTOD], [/* Define to 1 if you have the `strtod\' function. */
#undef HAVE_STRTOD])
-m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRTOL], [/* Define to 1 if you have the `strtol\' function. */
+m4trace:configure.in:713: -1- AH_OUTPUT([HAVE_STRTOL], [/* Define to 1 if you have the `strtol\' function. */
#undef HAVE_STRTOL])
-m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRTOUL], [/* Define to 1 if you have the `strtoul\' function. */
+m4trace:configure.in:713: -1- AH_OUTPUT([HAVE_STRTOUL], [/* Define to 1 if you have the `strtoul\' function. */
#undef HAVE_STRTOUL])
-m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRTOLL], [/* Define to 1 if you have the `strtoll\' function. */
+m4trace:configure.in:713: -1- AH_OUTPUT([HAVE_STRTOLL], [/* Define to 1 if you have the `strtoll\' function. */
#undef HAVE_STRTOLL])
-m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRTOULL], [/* Define to 1 if you have the `strtoull\' function. */
+m4trace:configure.in:713: -1- AH_OUTPUT([HAVE_STRTOULL], [/* Define to 1 if you have the `strtoull\' function. */
#undef HAVE_STRTOULL])
-m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRTOIMAX], [/* Define to 1 if you have the `strtoimax\' function. */
+m4trace:configure.in:713: -1- AH_OUTPUT([HAVE_STRTOIMAX], [/* Define to 1 if you have the `strtoimax\' function. */
#undef HAVE_STRTOIMAX])
-m4trace:configure.in:712: -1- AH_OUTPUT([HAVE_STRTOUMAX], [/* Define to 1 if you have the `strtoumax\' function. */
+m4trace:configure.in:713: -1- AH_OUTPUT([HAVE_STRTOUMAX], [/* Define to 1 if you have the `strtoumax\' function. */
#undef HAVE_STRTOUMAX])
-m4trace:configure.in:712: -1- AC_SUBST([LIB@&t@OBJS])
-m4trace:configure.in:714: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_CONFSTR])
-m4trace:configure.in:714: -1- AH_OUTPUT([HAVE_DECL_CONFSTR], [/* Define to 1 if you have the declaration of `confstr\', and to 0 if you
+m4trace:configure.in:713: -1- AC_SUBST([LIB@&t@OBJS])
+m4trace:configure.in:715: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_CONFSTR])
+m4trace:configure.in:715: -1- AH_OUTPUT([HAVE_DECL_CONFSTR], [/* Define to 1 if you have the declaration of `confstr\', and to 0 if you
don\'t. */
#undef HAVE_DECL_CONFSTR])
-m4trace:configure.in:714: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_CONFSTR])
-m4trace:configure.in:715: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_PRINTF])
-m4trace:configure.in:715: -1- AH_OUTPUT([HAVE_DECL_PRINTF], [/* Define to 1 if you have the declaration of `printf\', and to 0 if you don\'t.
+m4trace:configure.in:715: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_CONFSTR])
+m4trace:configure.in:716: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_PRINTF])
+m4trace:configure.in:716: -1- AH_OUTPUT([HAVE_DECL_PRINTF], [/* Define to 1 if you have the declaration of `printf\', and to 0 if you don\'t.
*/
#undef HAVE_DECL_PRINTF])
-m4trace:configure.in:715: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_PRINTF])
-m4trace:configure.in:716: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_SBRK])
-m4trace:configure.in:716: -1- AH_OUTPUT([HAVE_DECL_SBRK], [/* Define to 1 if you have the declaration of `sbrk\', and to 0 if you don\'t.
+m4trace:configure.in:716: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_PRINTF])
+m4trace:configure.in:717: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_SBRK])
+m4trace:configure.in:717: -1- AH_OUTPUT([HAVE_DECL_SBRK], [/* Define to 1 if you have the declaration of `sbrk\', and to 0 if you don\'t.
*/
#undef HAVE_DECL_SBRK])
-m4trace:configure.in:716: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_SBRK])
-m4trace:configure.in:717: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRCPY])
-m4trace:configure.in:717: -1- AH_OUTPUT([HAVE_DECL_STRCPY], [/* Define to 1 if you have the declaration of `strcpy\', and to 0 if you don\'t.
+m4trace:configure.in:717: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_SBRK])
+m4trace:configure.in:718: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRCPY])
+m4trace:configure.in:718: -1- AH_OUTPUT([HAVE_DECL_STRCPY], [/* Define to 1 if you have the declaration of `strcpy\', and to 0 if you don\'t.
*/
#undef HAVE_DECL_STRCPY])
-m4trace:configure.in:717: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRCPY])
-m4trace:configure.in:718: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRSIGNAL])
-m4trace:configure.in:718: -1- AH_OUTPUT([HAVE_DECL_STRSIGNAL], [/* Define to 1 if you have the declaration of `strsignal\', and to 0 if you
+m4trace:configure.in:718: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRCPY])
+m4trace:configure.in:719: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRSIGNAL])
+m4trace:configure.in:719: -1- AH_OUTPUT([HAVE_DECL_STRSIGNAL], [/* Define to 1 if you have the declaration of `strsignal\', and to 0 if you
don\'t. */
#undef HAVE_DECL_STRSIGNAL])
-m4trace:configure.in:718: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRSIGNAL])
-m4trace:configure.in:735: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRTOLD])
-m4trace:configure.in:735: -1- AH_OUTPUT([HAVE_DECL_STRTOLD], [/* Define to 1 if you have the declaration of `strtold\', and to 0 if you
+m4trace:configure.in:719: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRSIGNAL])
+m4trace:configure.in:736: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRTOLD])
+m4trace:configure.in:736: -1- AH_OUTPUT([HAVE_DECL_STRTOLD], [/* Define to 1 if you have the declaration of `strtold\', and to 0 if you
don\'t. */
#undef HAVE_DECL_STRTOLD])
-m4trace:configure.in:735: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:736: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:2352: AC_CHECK_DECL is expanded from...
autoconf/general.m4:2372: AC_CHECK_DECLS is expanded from...
-configure.in:735: the top level])
-m4trace:configure.in:735: -1- AC_DEFINE_TRACE_LITERAL([STRTOLD_BROKEN])
-m4trace:configure.in:735: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRTOLD])
-m4trace:configure.in:738: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
-You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
-autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
-aclocal.m4:122: BASH_CHECK_DECL is expanded from...
-configure.in:738: the top level])
+configure.in:736: the top level])
+m4trace:configure.in:736: -1- AC_DEFINE_TRACE_LITERAL([STRTOLD_BROKEN])
+m4trace:configure.in:736: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_STRTOLD])
m4trace:configure.in:739: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
@@ -1138,364 +1133,370 @@ autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:122: BASH_CHECK_DECL is expanded from...
configure.in:743: the top level])
-m4trace:configure.in:745: -1- AC_FUNC_MKTIME
-m4trace:configure.in:745: -1- AC_CHECK_HEADERS([stdlib.h sys/time.h unistd.h])
-m4trace:configure.in:745: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+m4trace:configure.in:744: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
+autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
+autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
+aclocal.m4:122: BASH_CHECK_DECL is expanded from...
+configure.in:744: the top level])
+m4trace:configure.in:746: -1- AC_FUNC_MKTIME
+m4trace:configure.in:746: -1- AC_CHECK_HEADERS([stdlib.h sys/time.h unistd.h])
+m4trace:configure.in:746: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H])
-m4trace:configure.in:745: -1- AH_OUTPUT([HAVE_SYS_TIME_H], [/* Define to 1 if you have the <sys/time.h> header file. */
+m4trace:configure.in:746: -1- AH_OUTPUT([HAVE_SYS_TIME_H], [/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H])
-m4trace:configure.in:745: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
+m4trace:configure.in:746: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H])
-m4trace:configure.in:745: -1- AC_CHECK_FUNCS([alarm])
-m4trace:configure.in:745: -1- AH_OUTPUT([HAVE_ALARM], [/* Define to 1 if you have the `alarm\' function. */
+m4trace:configure.in:746: -1- AC_CHECK_FUNCS([alarm])
+m4trace:configure.in:746: -1- AH_OUTPUT([HAVE_ALARM], [/* Define to 1 if you have the `alarm\' function. */
#undef HAVE_ALARM])
-m4trace:configure.in:745: -1- AC_LIBSOURCE([mktime.c])
-m4trace:configure.in:745: -1- AC_SUBST([LIB@&t@OBJS])
-m4trace:configure.in:752: -1- AC_CHECK_HEADERS([argz.h errno.h fcntl.h malloc.h stdio_ext.h])
-m4trace:configure.in:752: -1- AH_OUTPUT([HAVE_ARGZ_H], [/* Define to 1 if you have the <argz.h> header file. */
+m4trace:configure.in:746: -1- AC_LIBSOURCE([mktime.c])
+m4trace:configure.in:746: -1- AC_SUBST([LIB@&t@OBJS])
+m4trace:configure.in:753: -1- AC_CHECK_HEADERS([argz.h errno.h fcntl.h malloc.h stdio_ext.h])
+m4trace:configure.in:753: -1- AH_OUTPUT([HAVE_ARGZ_H], [/* Define to 1 if you have the <argz.h> header file. */
#undef HAVE_ARGZ_H])
-m4trace:configure.in:752: -1- AH_OUTPUT([HAVE_ERRNO_H], [/* Define to 1 if you have the <errno.h> header file. */
+m4trace:configure.in:753: -1- AH_OUTPUT([HAVE_ERRNO_H], [/* Define to 1 if you have the <errno.h> header file. */
#undef HAVE_ERRNO_H])
-m4trace:configure.in:752: -1- AH_OUTPUT([HAVE_FCNTL_H], [/* Define to 1 if you have the <fcntl.h> header file. */
+m4trace:configure.in:753: -1- AH_OUTPUT([HAVE_FCNTL_H], [/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H])
-m4trace:configure.in:752: -1- AH_OUTPUT([HAVE_MALLOC_H], [/* Define to 1 if you have the <malloc.h> header file. */
+m4trace:configure.in:753: -1- AH_OUTPUT([HAVE_MALLOC_H], [/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H])
-m4trace:configure.in:752: -1- AH_OUTPUT([HAVE_STDIO_EXT_H], [/* Define to 1 if you have the <stdio_ext.h> header file. */
+m4trace:configure.in:753: -1- AH_OUTPUT([HAVE_STDIO_EXT_H], [/* Define to 1 if you have the <stdio_ext.h> header file. */
#undef HAVE_STDIO_EXT_H])
-m4trace:configure.in:755: -1- AC_FUNC_MMAP
-m4trace:configure.in:755: -1- AC_CHECK_HEADERS([stdlib.h unistd.h])
-m4trace:configure.in:755: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+m4trace:configure.in:756: -1- AC_FUNC_MMAP
+m4trace:configure.in:756: -1- AC_CHECK_HEADERS([stdlib.h unistd.h])
+m4trace:configure.in:756: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H])
-m4trace:configure.in:755: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
+m4trace:configure.in:756: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H])
-m4trace:configure.in:755: -1- AC_CHECK_FUNCS([getpagesize])
-m4trace:configure.in:755: -1- AH_OUTPUT([HAVE_GETPAGESIZE], [/* Define to 1 if you have the `getpagesize\' function. */
+m4trace:configure.in:756: -1- AC_CHECK_FUNCS([getpagesize])
+m4trace:configure.in:756: -1- AH_OUTPUT([HAVE_GETPAGESIZE], [/* Define to 1 if you have the `getpagesize\' function. */
#undef HAVE_GETPAGESIZE])
-m4trace:configure.in:755: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MMAP])
-m4trace:configure.in:755: -1- AH_OUTPUT([HAVE_MMAP], [/* Define to 1 if you have a working `mmap\' system call. */
+m4trace:configure.in:756: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MMAP])
+m4trace:configure.in:756: -1- AH_OUTPUT([HAVE_MMAP], [/* Define to 1 if you have a working `mmap\' system call. */
#undef HAVE_MMAP])
-m4trace:configure.in:757: -1- AC_CHECK_FUNCS([__argz_count __argz_next __argz_stringify dcgettext mempcpy \
+m4trace:configure.in:758: -1- AC_CHECK_FUNCS([__argz_count __argz_next __argz_stringify dcgettext mempcpy \
munmap stpcpy strcspn strdup])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE___ARGZ_COUNT], [/* Define to 1 if you have the `__argz_count\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE___ARGZ_COUNT], [/* Define to 1 if you have the `__argz_count\' function. */
#undef HAVE___ARGZ_COUNT])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE___ARGZ_NEXT], [/* Define to 1 if you have the `__argz_next\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE___ARGZ_NEXT], [/* Define to 1 if you have the `__argz_next\' function. */
#undef HAVE___ARGZ_NEXT])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE___ARGZ_STRINGIFY], [/* Define to 1 if you have the `__argz_stringify\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE___ARGZ_STRINGIFY], [/* Define to 1 if you have the `__argz_stringify\' function. */
#undef HAVE___ARGZ_STRINGIFY])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE_DCGETTEXT], [/* Define to 1 if you have the `dcgettext\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE_DCGETTEXT], [/* Define to 1 if you have the `dcgettext\' function. */
#undef HAVE_DCGETTEXT])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE_MEMPCPY], [/* Define to 1 if you have the `mempcpy\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE_MEMPCPY], [/* Define to 1 if you have the `mempcpy\' function. */
#undef HAVE_MEMPCPY])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE_MUNMAP], [/* Define to 1 if you have the `munmap\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE_MUNMAP], [/* Define to 1 if you have the `munmap\' function. */
#undef HAVE_MUNMAP])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE_STPCPY], [/* Define to 1 if you have the `stpcpy\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE_STPCPY], [/* Define to 1 if you have the `stpcpy\' function. */
#undef HAVE_STPCPY])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE_STRCSPN], [/* Define to 1 if you have the `strcspn\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE_STRCSPN], [/* Define to 1 if you have the `strcspn\' function. */
#undef HAVE_STRCSPN])
-m4trace:configure.in:757: -1- AH_OUTPUT([HAVE_STRDUP], [/* Define to 1 if you have the `strdup\' function. */
+m4trace:configure.in:758: -1- AH_OUTPUT([HAVE_STRDUP], [/* Define to 1 if you have the `strdup\' function. */
#undef HAVE_STRDUP])
-m4trace:configure.in:765: -1- AC_SUBST([INTL_DEP])
-m4trace:configure.in:766: -1- AC_SUBST([INTL_INC])
-m4trace:configure.in:767: -1- AC_SUBST([LIBINTL_H])
-m4trace:configure.in:773: -1- AC_CHECK_HEADERS([wctype.h])
-m4trace:configure.in:773: -1- AH_OUTPUT([HAVE_WCTYPE_H], [/* Define to 1 if you have the <wctype.h> header file. */
+m4trace:configure.in:766: -1- AC_SUBST([INTL_DEP])
+m4trace:configure.in:767: -1- AC_SUBST([INTL_INC])
+m4trace:configure.in:768: -1- AC_SUBST([LIBINTL_H])
+m4trace:configure.in:774: -1- AC_CHECK_HEADERS([wctype.h])
+m4trace:configure.in:774: -1- AH_OUTPUT([HAVE_WCTYPE_H], [/* Define to 1 if you have the <wctype.h> header file. */
#undef HAVE_WCTYPE_H])
-m4trace:configure.in:773: -1- AC_CHECK_HEADERS([wchar.h])
-m4trace:configure.in:773: -1- AH_OUTPUT([HAVE_WCHAR_H], [/* Define to 1 if you have the <wchar.h> header file. */
+m4trace:configure.in:774: -1- AC_CHECK_HEADERS([wchar.h])
+m4trace:configure.in:774: -1- AH_OUTPUT([HAVE_WCHAR_H], [/* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H])
-m4trace:configure.in:773: -1- AC_CHECK_HEADERS([langinfo.h])
-m4trace:configure.in:773: -1- AH_OUTPUT([HAVE_LANGINFO_H], [/* Define to 1 if you have the <langinfo.h> header file. */
+m4trace:configure.in:774: -1- AC_CHECK_HEADERS([langinfo.h])
+m4trace:configure.in:774: -1- AH_OUTPUT([HAVE_LANGINFO_H], [/* Define to 1 if you have the <langinfo.h> header file. */
#undef HAVE_LANGINFO_H])
-m4trace:configure.in:773: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MBSRTOWCS])
-m4trace:configure.in:773: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MBRTOWC])
-m4trace:configure.in:773: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MBRLEN])
-m4trace:configure.in:773: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WCTOMB])
-m4trace:configure.in:773: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WCWIDTH])
-m4trace:configure.in:773: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WCSDUP])
-m4trace:configure.in:773: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WCTYPE])
-m4trace:configure.in:773: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:774: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MBSRTOWCS])
+m4trace:configure.in:774: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MBRTOWC])
+m4trace:configure.in:774: -2- AC_DEFINE_TRACE_LITERAL([HAVE_MBRLEN])
+m4trace:configure.in:774: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WCTOMB])
+m4trace:configure.in:774: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WCWIDTH])
+m4trace:configure.in:774: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WCSDUP])
+m4trace:configure.in:774: -2- AC_DEFINE_TRACE_LITERAL([HAVE_WCTYPE])
+m4trace:configure.in:774: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:1706: BASH_CHECK_MULTIBYTE is expanded from...
-configure.in:773: the top level])
-m4trace:configure.in:773: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MBSTATE_T])
-m4trace:configure.in:773: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:774: the top level])
+m4trace:configure.in:774: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MBSTATE_T])
+m4trace:configure.in:774: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:1706: BASH_CHECK_MULTIBYTE is expanded from...
-configure.in:773: the top level])
-m4trace:configure.in:773: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LANGINFO_CODESET])
-m4trace:configure.in:777: -1- AC_CHECK_LIB([dl], [dlopen])
-m4trace:configure.in:777: -1- AH_OUTPUT([HAVE_LIBDL], [/* Define to 1 if you have the `dl\' library (-ldl). */
+configure.in:774: the top level])
+m4trace:configure.in:774: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LANGINFO_CODESET])
+m4trace:configure.in:778: -1- AC_CHECK_LIB([dl], [dlopen])
+m4trace:configure.in:778: -1- AH_OUTPUT([HAVE_LIBDL], [/* Define to 1 if you have the `dl\' library (-ldl). */
#undef HAVE_LIBDL])
-m4trace:configure.in:777: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBDL])
-m4trace:configure.in:778: -1- AC_CHECK_FUNCS([dlopen dlclose dlsym])
-m4trace:configure.in:778: -1- AH_OUTPUT([HAVE_DLOPEN], [/* Define to 1 if you have the `dlopen\' function. */
+m4trace:configure.in:778: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBDL])
+m4trace:configure.in:779: -1- AC_CHECK_FUNCS([dlopen dlclose dlsym])
+m4trace:configure.in:779: -1- AH_OUTPUT([HAVE_DLOPEN], [/* Define to 1 if you have the `dlopen\' function. */
#undef HAVE_DLOPEN])
-m4trace:configure.in:778: -1- AH_OUTPUT([HAVE_DLCLOSE], [/* Define to 1 if you have the `dlclose\' function. */
+m4trace:configure.in:779: -1- AH_OUTPUT([HAVE_DLCLOSE], [/* Define to 1 if you have the `dlclose\' function. */
#undef HAVE_DLCLOSE])
-m4trace:configure.in:778: -1- AH_OUTPUT([HAVE_DLSYM], [/* Define to 1 if you have the `dlsym\' function. */
+m4trace:configure.in:779: -1- AH_OUTPUT([HAVE_DLSYM], [/* Define to 1 if you have the `dlsym\' function. */
#undef HAVE_DLSYM])
-m4trace:configure.in:782: -1- AC_DECL_SYS_SIGLIST
-m4trace:configure.in:782: -1- _m4_warn([obsolete], [The macro `AC_DECL_SYS_SIGLIST' is obsolete.
+m4trace:configure.in:783: -1- AC_DECL_SYS_SIGLIST
+m4trace:configure.in:783: -1- _m4_warn([obsolete], [The macro `AC_DECL_SYS_SIGLIST' is obsolete.
You should run autoupdate.], [autoconf/specific.m4:70: AC_DECL_SYS_SIGLIST is expanded from...
-configure.in:782: the top level])
-m4trace:configure.in:782: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_SYS_SIGLIST])
-m4trace:configure.in:782: -1- AH_OUTPUT([HAVE_DECL_SYS_SIGLIST], [/* Define to 1 if you have the declaration of `sys_siglist\', and to 0 if you
+configure.in:783: the top level])
+m4trace:configure.in:783: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_SYS_SIGLIST])
+m4trace:configure.in:783: -1- AH_OUTPUT([HAVE_DECL_SYS_SIGLIST], [/* Define to 1 if you have the declaration of `sys_siglist\', and to 0 if you
don\'t. */
#undef HAVE_DECL_SYS_SIGLIST])
-m4trace:configure.in:782: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_SYS_SIGLIST])
-m4trace:configure.in:786: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:783: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DECL_SYS_SIGLIST])
+m4trace:configure.in:787: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:562: BASH_FUNC_INET_ATON is expanded from...
-configure.in:786: the top level])
-m4trace:configure.in:786: -1- AC_DEFINE_TRACE_LITERAL([HAVE_INET_ATON])
-m4trace:configure.in:786: -1- AC_LIBSOURCE([inet_aton.c])
-m4trace:configure.in:786: -1- AC_SUBST([LIB@&t@OBJS])
-m4trace:configure.in:792: -1- AC_CHECK_LIB([sun], [getpwent])
-m4trace:configure.in:792: -1- AH_OUTPUT([HAVE_LIBSUN], [/* Define to 1 if you have the `sun\' library (-lsun). */
+configure.in:787: the top level])
+m4trace:configure.in:787: -1- AC_DEFINE_TRACE_LITERAL([HAVE_INET_ATON])
+m4trace:configure.in:787: -1- AC_LIBSOURCE([inet_aton.c])
+m4trace:configure.in:787: -1- AC_SUBST([LIB@&t@OBJS])
+m4trace:configure.in:793: -1- AC_CHECK_LIB([sun], [getpwent])
+m4trace:configure.in:793: -1- AH_OUTPUT([HAVE_LIBSUN], [/* Define to 1 if you have the `sun\' library (-lsun). */
#undef HAVE_LIBSUN])
-m4trace:configure.in:792: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBSUN])
-m4trace:configure.in:797: -1- AC_CHECK_LIB([socket], [getpeername], [bash_cv_have_socklib=yes], [bash_cv_have_socklib=no], [-lnsl])
-m4trace:configure.in:797: -1- AC_CHECK_LIB([nsl], [t_open], [bash_cv_have_libnsl=yes], [bash_cv_have_libnsl=no])
-m4trace:configure.in:797: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBSOCKET])
-m4trace:configure.in:797: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETPEERNAME])
-m4trace:configure.in:801: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:793: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBSUN])
+m4trace:configure.in:798: -1- AC_CHECK_LIB([socket], [getpeername], [bash_cv_have_socklib=yes], [bash_cv_have_socklib=no], [-lnsl])
+m4trace:configure.in:798: -1- AC_CHECK_LIB([nsl], [t_open], [bash_cv_have_libnsl=yes], [bash_cv_have_libnsl=no])
+m4trace:configure.in:798: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBSOCKET])
+m4trace:configure.in:798: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETPEERNAME])
+m4trace:configure.in:802: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:737: BASH_FUNC_GETHOSTBYNAME is expanded from...
-configure.in:801: the top level])
-m4trace:configure.in:801: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETHOSTBYNAME])
-m4trace:configure.in:805: -1- AC_TYPE_UID_T
-m4trace:configure.in:805: -1- AC_DEFINE_TRACE_LITERAL([uid_t])
-m4trace:configure.in:805: -1- AH_OUTPUT([uid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
+configure.in:802: the top level])
+m4trace:configure.in:802: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETHOSTBYNAME])
+m4trace:configure.in:806: -1- AC_TYPE_UID_T
+m4trace:configure.in:806: -1- AC_DEFINE_TRACE_LITERAL([uid_t])
+m4trace:configure.in:806: -1- AH_OUTPUT([uid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
#undef uid_t])
-m4trace:configure.in:805: -1- AC_DEFINE_TRACE_LITERAL([gid_t])
-m4trace:configure.in:805: -1- AH_OUTPUT([gid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
+m4trace:configure.in:806: -1- AC_DEFINE_TRACE_LITERAL([gid_t])
+m4trace:configure.in:806: -1- AH_OUTPUT([gid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
#undef gid_t])
-m4trace:configure.in:805: -1- AC_DEFINE_TRACE_LITERAL([GETGROUPS_T])
-m4trace:configure.in:805: -1- AH_OUTPUT([GETGROUPS_T], [/* Define to the type of elements in the array set by `getgroups\'. Usually
+m4trace:configure.in:806: -1- AC_DEFINE_TRACE_LITERAL([GETGROUPS_T])
+m4trace:configure.in:806: -1- AH_OUTPUT([GETGROUPS_T], [/* Define to the type of elements in the array set by `getgroups\'. Usually
this is either `int\' or `gid_t\'. */
#undef GETGROUPS_T])
-m4trace:configure.in:806: -1- AC_TYPE_OFF_T
-m4trace:configure.in:806: -1- AC_DEFINE_TRACE_LITERAL([off_t])
-m4trace:configure.in:806: -1- AH_OUTPUT([off_t], [/* Define to `long\' if <sys/types.h> does not define. */
+m4trace:configure.in:807: -1- AC_TYPE_OFF_T
+m4trace:configure.in:807: -1- AC_DEFINE_TRACE_LITERAL([off_t])
+m4trace:configure.in:807: -1- AH_OUTPUT([off_t], [/* Define to `long\' if <sys/types.h> does not define. */
#undef off_t])
-m4trace:configure.in:807: -1- AC_TYPE_MODE_T
-m4trace:configure.in:807: -1- AC_DEFINE_TRACE_LITERAL([mode_t])
-m4trace:configure.in:807: -1- AH_OUTPUT([mode_t], [/* Define to `int\' if <sys/types.h> does not define. */
+m4trace:configure.in:808: -1- AC_TYPE_MODE_T
+m4trace:configure.in:808: -1- AC_DEFINE_TRACE_LITERAL([mode_t])
+m4trace:configure.in:808: -1- AH_OUTPUT([mode_t], [/* Define to `int\' if <sys/types.h> does not define. */
#undef mode_t])
-m4trace:configure.in:808: -1- AC_TYPE_UID_T
-m4trace:configure.in:808: -1- AC_DEFINE_TRACE_LITERAL([uid_t])
-m4trace:configure.in:808: -1- AH_OUTPUT([uid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
+m4trace:configure.in:809: -1- AC_TYPE_UID_T
+m4trace:configure.in:809: -1- AC_DEFINE_TRACE_LITERAL([uid_t])
+m4trace:configure.in:809: -1- AH_OUTPUT([uid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
#undef uid_t])
-m4trace:configure.in:808: -1- AC_DEFINE_TRACE_LITERAL([gid_t])
-m4trace:configure.in:808: -1- AH_OUTPUT([gid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
+m4trace:configure.in:809: -1- AC_DEFINE_TRACE_LITERAL([gid_t])
+m4trace:configure.in:809: -1- AH_OUTPUT([gid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
#undef gid_t])
-m4trace:configure.in:809: -1- AC_TYPE_PID_T
-m4trace:configure.in:809: -1- AC_DEFINE_TRACE_LITERAL([pid_t])
-m4trace:configure.in:809: -1- AH_OUTPUT([pid_t], [/* Define to `int\' if <sys/types.h> does not define. */
+m4trace:configure.in:810: -1- AC_TYPE_PID_T
+m4trace:configure.in:810: -1- AC_DEFINE_TRACE_LITERAL([pid_t])
+m4trace:configure.in:810: -1- AH_OUTPUT([pid_t], [/* Define to `int\' if <sys/types.h> does not define. */
#undef pid_t])
-m4trace:configure.in:810: -1- AC_TYPE_SIZE_T
-m4trace:configure.in:810: -1- AC_DEFINE_TRACE_LITERAL([size_t])
-m4trace:configure.in:810: -1- AH_OUTPUT([size_t], [/* Define to `unsigned\' if <sys/types.h> does not define. */
+m4trace:configure.in:811: -1- AC_TYPE_SIZE_T
+m4trace:configure.in:811: -1- AC_DEFINE_TRACE_LITERAL([size_t])
+m4trace:configure.in:811: -1- AH_OUTPUT([size_t], [/* Define to `unsigned\' if <sys/types.h> does not define. */
#undef size_t])
-m4trace:configure.in:811: -1- AC_DEFINE_TRACE_LITERAL([ssize_t])
-m4trace:configure.in:811: -1- AH_OUTPUT([ssize_t], [/* Define to `int\' if <sys/types.h> does not define. */
+m4trace:configure.in:812: -1- AC_DEFINE_TRACE_LITERAL([ssize_t])
+m4trace:configure.in:812: -1- AH_OUTPUT([ssize_t], [/* Define to `int\' if <sys/types.h> does not define. */
#undef ssize_t])
-m4trace:configure.in:812: -1- AC_DEFINE_TRACE_LITERAL([time_t])
-m4trace:configure.in:812: -1- AH_OUTPUT([time_t], [/* Define to `long\' if <sys/types.h> does not define. */
+m4trace:configure.in:813: -1- AC_DEFINE_TRACE_LITERAL([time_t])
+m4trace:configure.in:813: -1- AH_OUTPUT([time_t], [/* Define to `long\' if <sys/types.h> does not define. */
#undef time_t])
-m4trace:configure.in:814: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:815: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:481: BASH_TYPE_LONG_LONG is expanded from...
-configure.in:814: the top level])
-m4trace:configure.in:814: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LONG_LONG])
-m4trace:configure.in:815: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:815: the top level])
+m4trace:configure.in:815: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LONG_LONG])
+m4trace:configure.in:816: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:496: BASH_TYPE_UNSIGNED_LONG_LONG is expanded from...
-configure.in:815: the top level])
-m4trace:configure.in:815: -1- AC_DEFINE_TRACE_LITERAL([HAVE_UNSIGNED_LONG_LONG])
-m4trace:configure.in:817: -1- AC_TYPE_SIGNAL
-m4trace:configure.in:817: -1- AC_DEFINE_TRACE_LITERAL([RETSIGTYPE])
-m4trace:configure.in:817: -1- AH_OUTPUT([RETSIGTYPE], [/* Define as the return type of signal handlers (`int\' or `void\'). */
+configure.in:816: the top level])
+m4trace:configure.in:816: -1- AC_DEFINE_TRACE_LITERAL([HAVE_UNSIGNED_LONG_LONG])
+m4trace:configure.in:818: -1- AC_TYPE_SIGNAL
+m4trace:configure.in:818: -1- AC_DEFINE_TRACE_LITERAL([RETSIGTYPE])
+m4trace:configure.in:818: -1- AH_OUTPUT([RETSIGTYPE], [/* Define as the return type of signal handlers (`int\' or `void\'). */
#undef RETSIGTYPE])
-m4trace:configure.in:819: -1- _m4_warn([cross], [AC_RUN_IFELSE called without default to allow cross compiling], [autoconf/general.m4:2281: AC_RUN_IFELSE is expanded from...
-autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
-autoconf/types.m4:405: AC_CHECK_SIZEOF is expanded from...
-configure.in:819: the top level])
-m4trace:configure.in:819: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_CHAR])
-m4trace:configure.in:819: -1- AH_OUTPUT([SIZEOF_CHAR], [/* The size of a `char\', as computed by sizeof. */
-#undef SIZEOF_CHAR])
m4trace:configure.in:820: -1- _m4_warn([cross], [AC_RUN_IFELSE called without default to allow cross compiling], [autoconf/general.m4:2281: AC_RUN_IFELSE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
autoconf/types.m4:405: AC_CHECK_SIZEOF is expanded from...
configure.in:820: the top level])
-m4trace:configure.in:820: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_SHORT])
-m4trace:configure.in:820: -1- AH_OUTPUT([SIZEOF_SHORT], [/* The size of a `short\', as computed by sizeof. */
-#undef SIZEOF_SHORT])
+m4trace:configure.in:820: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_CHAR])
+m4trace:configure.in:820: -1- AH_OUTPUT([SIZEOF_CHAR], [/* The size of a `char\', as computed by sizeof. */
+#undef SIZEOF_CHAR])
m4trace:configure.in:821: -1- _m4_warn([cross], [AC_RUN_IFELSE called without default to allow cross compiling], [autoconf/general.m4:2281: AC_RUN_IFELSE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
autoconf/types.m4:405: AC_CHECK_SIZEOF is expanded from...
configure.in:821: the top level])
-m4trace:configure.in:821: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_INT])
-m4trace:configure.in:821: -1- AH_OUTPUT([SIZEOF_INT], [/* The size of a `int\', as computed by sizeof. */
-#undef SIZEOF_INT])
+m4trace:configure.in:821: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_SHORT])
+m4trace:configure.in:821: -1- AH_OUTPUT([SIZEOF_SHORT], [/* The size of a `short\', as computed by sizeof. */
+#undef SIZEOF_SHORT])
m4trace:configure.in:822: -1- _m4_warn([cross], [AC_RUN_IFELSE called without default to allow cross compiling], [autoconf/general.m4:2281: AC_RUN_IFELSE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
autoconf/types.m4:405: AC_CHECK_SIZEOF is expanded from...
configure.in:822: the top level])
-m4trace:configure.in:822: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_LONG])
-m4trace:configure.in:822: -1- AH_OUTPUT([SIZEOF_LONG], [/* The size of a `long\', as computed by sizeof. */
-#undef SIZEOF_LONG])
+m4trace:configure.in:822: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_INT])
+m4trace:configure.in:822: -1- AH_OUTPUT([SIZEOF_INT], [/* The size of a `int\', as computed by sizeof. */
+#undef SIZEOF_INT])
m4trace:configure.in:823: -1- _m4_warn([cross], [AC_RUN_IFELSE called without default to allow cross compiling], [autoconf/general.m4:2281: AC_RUN_IFELSE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
autoconf/types.m4:405: AC_CHECK_SIZEOF is expanded from...
configure.in:823: the top level])
-m4trace:configure.in:823: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_CHAR_P])
-m4trace:configure.in:823: -1- AH_OUTPUT([SIZEOF_CHAR_P], [/* The size of a `char *\', as computed by sizeof. */
-#undef SIZEOF_CHAR_P])
+m4trace:configure.in:823: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_LONG])
+m4trace:configure.in:823: -1- AH_OUTPUT([SIZEOF_LONG], [/* The size of a `long\', as computed by sizeof. */
+#undef SIZEOF_LONG])
m4trace:configure.in:824: -1- _m4_warn([cross], [AC_RUN_IFELSE called without default to allow cross compiling], [autoconf/general.m4:2281: AC_RUN_IFELSE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
autoconf/types.m4:405: AC_CHECK_SIZEOF is expanded from...
configure.in:824: the top level])
-m4trace:configure.in:824: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_DOUBLE])
-m4trace:configure.in:824: -1- AH_OUTPUT([SIZEOF_DOUBLE], [/* The size of a `double\', as computed by sizeof. */
-#undef SIZEOF_DOUBLE])
+m4trace:configure.in:824: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_CHAR_P])
+m4trace:configure.in:824: -1- AH_OUTPUT([SIZEOF_CHAR_P], [/* The size of a `char *\', as computed by sizeof. */
+#undef SIZEOF_CHAR_P])
m4trace:configure.in:825: -1- _m4_warn([cross], [AC_RUN_IFELSE called without default to allow cross compiling], [autoconf/general.m4:2281: AC_RUN_IFELSE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
autoconf/types.m4:405: AC_CHECK_SIZEOF is expanded from...
configure.in:825: the top level])
-m4trace:configure.in:825: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_LONG_LONG])
-m4trace:configure.in:825: -1- AH_OUTPUT([SIZEOF_LONG_LONG], [/* The size of a `long long\', as computed by sizeof. */
+m4trace:configure.in:825: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_DOUBLE])
+m4trace:configure.in:825: -1- AH_OUTPUT([SIZEOF_DOUBLE], [/* The size of a `double\', as computed by sizeof. */
+#undef SIZEOF_DOUBLE])
+m4trace:configure.in:826: -1- _m4_warn([cross], [AC_RUN_IFELSE called without default to allow cross compiling], [autoconf/general.m4:2281: AC_RUN_IFELSE is expanded from...
+autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
+autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
+autoconf/types.m4:405: AC_CHECK_SIZEOF is expanded from...
+configure.in:826: the top level])
+m4trace:configure.in:826: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_LONG_LONG])
+m4trace:configure.in:826: -1- AH_OUTPUT([SIZEOF_LONG_LONG], [/* The size of a `long long\', as computed by sizeof. */
#undef SIZEOF_LONG_LONG])
-m4trace:configure.in:827: -1- AC_DEFINE_TRACE_LITERAL([u_int])
-m4trace:configure.in:827: -1- AH_OUTPUT([u_int], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
+m4trace:configure.in:828: -1- AC_DEFINE_TRACE_LITERAL([u_int])
+m4trace:configure.in:828: -1- AH_OUTPUT([u_int], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
#undef u_int])
-m4trace:configure.in:828: -1- AC_DEFINE_TRACE_LITERAL([u_long])
-m4trace:configure.in:828: -1- AH_OUTPUT([u_long], [/* Define to `unsigned long\' if <sys/types.h> does not define. */
+m4trace:configure.in:829: -1- AC_DEFINE_TRACE_LITERAL([u_long])
+m4trace:configure.in:829: -1- AH_OUTPUT([u_long], [/* Define to `unsigned long\' if <sys/types.h> does not define. */
#undef u_long])
-m4trace:configure.in:830: -1- AC_DEFINE_TRACE_LITERAL([bits16_t])
-m4trace:configure.in:830: -1- AH_OUTPUT([bits16_t], [/* Define to `short\' if <sys/types.h> does not define. */
+m4trace:configure.in:831: -1- AC_DEFINE_TRACE_LITERAL([bits16_t])
+m4trace:configure.in:831: -1- AH_OUTPUT([bits16_t], [/* Define to `short\' if <sys/types.h> does not define. */
#undef bits16_t])
-m4trace:configure.in:830: -1- AC_DEFINE_TRACE_LITERAL([bits16_t])
-m4trace:configure.in:830: -1- AH_OUTPUT([bits16_t], [/* Define to `char\' if <sys/types.h> does not define. */
+m4trace:configure.in:831: -1- AC_DEFINE_TRACE_LITERAL([bits16_t])
+m4trace:configure.in:831: -1- AH_OUTPUT([bits16_t], [/* Define to `char\' if <sys/types.h> does not define. */
#undef bits16_t])
-m4trace:configure.in:830: -1- AC_DEFINE_TRACE_LITERAL([bits16_t])
-m4trace:configure.in:830: -1- AH_OUTPUT([bits16_t], [/* Define to `short\' if <sys/types.h> does not define. */
+m4trace:configure.in:831: -1- AC_DEFINE_TRACE_LITERAL([bits16_t])
+m4trace:configure.in:831: -1- AH_OUTPUT([bits16_t], [/* Define to `short\' if <sys/types.h> does not define. */
#undef bits16_t])
-m4trace:configure.in:831: -1- AC_DEFINE_TRACE_LITERAL([u_bits16_t])
-m4trace:configure.in:831: -1- AH_OUTPUT([u_bits16_t], [/* Define to `unsigned short\' if <sys/types.h> does not define. */
+m4trace:configure.in:832: -1- AC_DEFINE_TRACE_LITERAL([u_bits16_t])
+m4trace:configure.in:832: -1- AH_OUTPUT([u_bits16_t], [/* Define to `unsigned short\' if <sys/types.h> does not define. */
#undef u_bits16_t])
-m4trace:configure.in:831: -1- AC_DEFINE_TRACE_LITERAL([u_bits16_t])
-m4trace:configure.in:831: -1- AH_OUTPUT([u_bits16_t], [/* Define to `unsigned char\' if <sys/types.h> does not define. */
+m4trace:configure.in:832: -1- AC_DEFINE_TRACE_LITERAL([u_bits16_t])
+m4trace:configure.in:832: -1- AH_OUTPUT([u_bits16_t], [/* Define to `unsigned char\' if <sys/types.h> does not define. */
#undef u_bits16_t])
-m4trace:configure.in:831: -1- AC_DEFINE_TRACE_LITERAL([u_bits16_t])
-m4trace:configure.in:831: -1- AH_OUTPUT([u_bits16_t], [/* Define to `unsigned short\' if <sys/types.h> does not define. */
+m4trace:configure.in:832: -1- AC_DEFINE_TRACE_LITERAL([u_bits16_t])
+m4trace:configure.in:832: -1- AH_OUTPUT([u_bits16_t], [/* Define to `unsigned short\' if <sys/types.h> does not define. */
#undef u_bits16_t])
-m4trace:configure.in:832: -1- AC_DEFINE_TRACE_LITERAL([bits32_t])
-m4trace:configure.in:832: -1- AH_OUTPUT([bits32_t], [/* Define to `int\' if <sys/types.h> does not define. */
+m4trace:configure.in:833: -1- AC_DEFINE_TRACE_LITERAL([bits32_t])
+m4trace:configure.in:833: -1- AH_OUTPUT([bits32_t], [/* Define to `int\' if <sys/types.h> does not define. */
#undef bits32_t])
-m4trace:configure.in:832: -1- AC_DEFINE_TRACE_LITERAL([bits32_t])
-m4trace:configure.in:832: -1- AH_OUTPUT([bits32_t], [/* Define to `long\' if <sys/types.h> does not define. */
+m4trace:configure.in:833: -1- AC_DEFINE_TRACE_LITERAL([bits32_t])
+m4trace:configure.in:833: -1- AH_OUTPUT([bits32_t], [/* Define to `long\' if <sys/types.h> does not define. */
#undef bits32_t])
-m4trace:configure.in:832: -1- AC_DEFINE_TRACE_LITERAL([bits32_t])
-m4trace:configure.in:832: -1- AH_OUTPUT([bits32_t], [/* Define to `int\' if <sys/types.h> does not define. */
+m4trace:configure.in:833: -1- AC_DEFINE_TRACE_LITERAL([bits32_t])
+m4trace:configure.in:833: -1- AH_OUTPUT([bits32_t], [/* Define to `int\' if <sys/types.h> does not define. */
#undef bits32_t])
-m4trace:configure.in:833: -1- AC_DEFINE_TRACE_LITERAL([u_bits32_t])
-m4trace:configure.in:833: -1- AH_OUTPUT([u_bits32_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
+m4trace:configure.in:834: -1- AC_DEFINE_TRACE_LITERAL([u_bits32_t])
+m4trace:configure.in:834: -1- AH_OUTPUT([u_bits32_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
#undef u_bits32_t])
-m4trace:configure.in:833: -1- AC_DEFINE_TRACE_LITERAL([u_bits32_t])
-m4trace:configure.in:833: -1- AH_OUTPUT([u_bits32_t], [/* Define to `unsigned long\' if <sys/types.h> does not define. */
+m4trace:configure.in:834: -1- AC_DEFINE_TRACE_LITERAL([u_bits32_t])
+m4trace:configure.in:834: -1- AH_OUTPUT([u_bits32_t], [/* Define to `unsigned long\' if <sys/types.h> does not define. */
#undef u_bits32_t])
-m4trace:configure.in:833: -1- AC_DEFINE_TRACE_LITERAL([u_bits32_t])
-m4trace:configure.in:833: -1- AH_OUTPUT([u_bits32_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
+m4trace:configure.in:834: -1- AC_DEFINE_TRACE_LITERAL([u_bits32_t])
+m4trace:configure.in:834: -1- AH_OUTPUT([u_bits32_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
#undef u_bits32_t])
-m4trace:configure.in:834: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
-m4trace:configure.in:834: -1- AH_OUTPUT([bits64_t], [/* Define to `char *\' if <sys/types.h> does not define. */
+m4trace:configure.in:835: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
+m4trace:configure.in:835: -1- AH_OUTPUT([bits64_t], [/* Define to `char *\' if <sys/types.h> does not define. */
#undef bits64_t])
-m4trace:configure.in:834: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
-m4trace:configure.in:834: -1- AH_OUTPUT([bits64_t], [/* Define to `double\' if <sys/types.h> does not define. */
+m4trace:configure.in:835: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
+m4trace:configure.in:835: -1- AH_OUTPUT([bits64_t], [/* Define to `double\' if <sys/types.h> does not define. */
#undef bits64_t])
-m4trace:configure.in:834: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
-m4trace:configure.in:834: -1- AH_OUTPUT([bits64_t], [/* Define to `long long\' if <sys/types.h> does not define. */
+m4trace:configure.in:835: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
+m4trace:configure.in:835: -1- AH_OUTPUT([bits64_t], [/* Define to `long long\' if <sys/types.h> does not define. */
#undef bits64_t])
-m4trace:configure.in:834: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
-m4trace:configure.in:834: -1- AH_OUTPUT([bits64_t], [/* Define to `long\' if <sys/types.h> does not define. */
+m4trace:configure.in:835: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
+m4trace:configure.in:835: -1- AH_OUTPUT([bits64_t], [/* Define to `long\' if <sys/types.h> does not define. */
#undef bits64_t])
-m4trace:configure.in:834: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
-m4trace:configure.in:834: -1- AH_OUTPUT([bits64_t], [/* Define to `double\' if <sys/types.h> does not define. */
+m4trace:configure.in:835: -1- AC_DEFINE_TRACE_LITERAL([bits64_t])
+m4trace:configure.in:835: -1- AH_OUTPUT([bits64_t], [/* Define to `double\' if <sys/types.h> does not define. */
#undef bits64_t])
-m4trace:configure.in:836: -1- AC_DEFINE_TRACE_LITERAL([ptrdiff_t])
-m4trace:configure.in:836: -1- AH_OUTPUT([ptrdiff_t], [/* Define to `int\' if <sys/types.h> does not define. */
+m4trace:configure.in:837: -1- AC_DEFINE_TRACE_LITERAL([ptrdiff_t])
+m4trace:configure.in:837: -1- AH_OUTPUT([ptrdiff_t], [/* Define to `int\' if <sys/types.h> does not define. */
#undef ptrdiff_t])
-m4trace:configure.in:836: -1- AC_DEFINE_TRACE_LITERAL([ptrdiff_t])
-m4trace:configure.in:836: -1- AH_OUTPUT([ptrdiff_t], [/* Define to `long\' if <sys/types.h> does not define. */
+m4trace:configure.in:837: -1- AC_DEFINE_TRACE_LITERAL([ptrdiff_t])
+m4trace:configure.in:837: -1- AH_OUTPUT([ptrdiff_t], [/* Define to `long\' if <sys/types.h> does not define. */
#undef ptrdiff_t])
-m4trace:configure.in:836: -1- AC_DEFINE_TRACE_LITERAL([ptrdiff_t])
-m4trace:configure.in:836: -1- AH_OUTPUT([ptrdiff_t], [/* Define to `long long\' if <sys/types.h> does not define. */
+m4trace:configure.in:837: -1- AC_DEFINE_TRACE_LITERAL([ptrdiff_t])
+m4trace:configure.in:837: -1- AH_OUTPUT([ptrdiff_t], [/* Define to `long long\' if <sys/types.h> does not define. */
#undef ptrdiff_t])
-m4trace:configure.in:836: -1- AC_DEFINE_TRACE_LITERAL([ptrdiff_t])
-m4trace:configure.in:836: -1- AH_OUTPUT([ptrdiff_t], [/* Define to `int\' if <sys/types.h> does not define. */
+m4trace:configure.in:837: -1- AC_DEFINE_TRACE_LITERAL([ptrdiff_t])
+m4trace:configure.in:837: -1- AH_OUTPUT([ptrdiff_t], [/* Define to `int\' if <sys/types.h> does not define. */
#undef ptrdiff_t])
-m4trace:configure.in:839: -1- AC_HEADER_STAT
-m4trace:configure.in:839: -1- AC_DEFINE_TRACE_LITERAL([STAT_MACROS_BROKEN])
-m4trace:configure.in:839: -1- AH_OUTPUT([STAT_MACROS_BROKEN], [/* Define to 1 if the `S_IS*\' macros in <sys/stat.h> do not work properly. */
+m4trace:configure.in:840: -1- AC_HEADER_STAT
+m4trace:configure.in:840: -1- AC_DEFINE_TRACE_LITERAL([STAT_MACROS_BROKEN])
+m4trace:configure.in:840: -1- AH_OUTPUT([STAT_MACROS_BROKEN], [/* Define to 1 if the `S_IS*\' macros in <sys/stat.h> do not work properly. */
#undef STAT_MACROS_BROKEN])
-m4trace:configure.in:844: -1- AC_DEFINE_TRACE_LITERAL([HAVE_HASH_BANG_EXEC])
-m4trace:configure.in:849: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:845: -1- AC_DEFINE_TRACE_LITERAL([HAVE_HASH_BANG_EXEC])
+m4trace:configure.in:850: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:546: BASH_FUNC_LSTAT is expanded from...
-configure.in:849: the top level])
-m4trace:configure.in:849: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LSTAT])
-m4trace:configure.in:853: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:850: the top level])
+m4trace:configure.in:850: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LSTAT])
+m4trace:configure.in:854: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1869: BASH_FUNC_CTYPE_NONASCII is expanded from...
-configure.in:853: the top level])
-m4trace:configure.in:853: -1- AC_DEFINE_TRACE_LITERAL([CTYPE_NON_ASCII])
-m4trace:configure.in:854: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:854: the top level])
+m4trace:configure.in:854: -1- AC_DEFINE_TRACE_LITERAL([CTYPE_NON_ASCII])
+m4trace:configure.in:855: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:294: BASH_FUNC_DUP2_CLOEXEC_CHECK is expanded from...
-configure.in:854: the top level])
-m4trace:configure.in:854: -1- AC_DEFINE_TRACE_LITERAL([DUP2_BROKEN])
-m4trace:configure.in:855: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:855: the top level])
+m4trace:configure.in:855: -1- AC_DEFINE_TRACE_LITERAL([DUP2_BROKEN])
+m4trace:configure.in:856: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1280: BASH_SYS_PGRP_SYNC is expanded from...
-configure.in:855: the top level])
-m4trace:configure.in:855: -1- AC_DEFINE_TRACE_LITERAL([PGRP_PIPE])
-m4trace:configure.in:856: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:856: the top level])
+m4trace:configure.in:856: -1- AC_DEFINE_TRACE_LITERAL([PGRP_PIPE])
+m4trace:configure.in:857: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1217: BASH_SYS_SIGNAL_VINTAGE is expanded from...
-configure.in:856: the top level])
-m4trace:configure.in:856: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:857: the top level])
+m4trace:configure.in:857: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:2215: AC_LINK_IFELSE is expanded from...
autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1217: BASH_SYS_SIGNAL_VINTAGE is expanded from...
-configure.in:856: the top level])
-m4trace:configure.in:856: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:857: the top level])
+m4trace:configure.in:857: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:2215: AC_LINK_IFELSE is expanded from...
autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
@@ -1503,311 +1504,311 @@ autoconf/general.m4:2215: AC_LINK_IFELSE is expanded from...
autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1217: BASH_SYS_SIGNAL_VINTAGE is expanded from...
-configure.in:856: the top level])
-m4trace:configure.in:856: -1- AC_DEFINE_TRACE_LITERAL([HAVE_POSIX_SIGNALS])
-m4trace:configure.in:856: -1- AC_DEFINE_TRACE_LITERAL([HAVE_BSD_SIGNALS])
-m4trace:configure.in:856: -1- AC_DEFINE_TRACE_LITERAL([HAVE_USG_SIGHOLD])
-m4trace:configure.in:859: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:857: the top level])
+m4trace:configure.in:857: -1- AC_DEFINE_TRACE_LITERAL([HAVE_POSIX_SIGNALS])
+m4trace:configure.in:857: -1- AC_DEFINE_TRACE_LITERAL([HAVE_BSD_SIGNALS])
+m4trace:configure.in:857: -1- AC_DEFINE_TRACE_LITERAL([HAVE_USG_SIGHOLD])
+m4trace:configure.in:860: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:262: BASH_SYS_ERRLIST is expanded from...
-configure.in:859: the top level])
-m4trace:configure.in:859: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SYS_ERRLIST])
-m4trace:configure.in:860: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:860: the top level])
+m4trace:configure.in:860: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SYS_ERRLIST])
+m4trace:configure.in:861: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:233: BASH_SYS_SIGLIST is expanded from...
-configure.in:860: the top level])
-m4trace:configure.in:860: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SYS_SIGLIST])
-m4trace:configure.in:861: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+configure.in:861: the top level])
+m4trace:configure.in:861: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SYS_SIGLIST])
+m4trace:configure.in:862: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:179: BASH_DECL_UNDER_SYS_SIGLIST is expanded from...
-configure.in:861: BASH_DECL_UNDER_SYS_SIGLIST is required by...
+configure.in:862: BASH_DECL_UNDER_SYS_SIGLIST is required by...
aclocal.m4:206: BASH_UNDER_SYS_SIGLIST is expanded from...
-configure.in:861: the top level])
-m4trace:configure.in:861: -1- AC_DEFINE_TRACE_LITERAL([UNDER_SYS_SIGLIST_DECLARED])
-m4trace:configure.in:861: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:862: the top level])
+m4trace:configure.in:862: -1- AC_DEFINE_TRACE_LITERAL([UNDER_SYS_SIGLIST_DECLARED])
+m4trace:configure.in:862: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:206: BASH_UNDER_SYS_SIGLIST is expanded from...
-configure.in:861: the top level])
-m4trace:configure.in:861: -1- AC_DEFINE_TRACE_LITERAL([HAVE_UNDER_SYS_SIGLIST])
-m4trace:configure.in:864: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+configure.in:862: the top level])
+m4trace:configure.in:862: -1- AC_DEFINE_TRACE_LITERAL([HAVE_UNDER_SYS_SIGLIST])
+m4trace:configure.in:865: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:380: BASH_TYPE_SIGHANDLER is expanded from...
-configure.in:864: the top level])
-m4trace:configure.in:864: -1- AC_DEFINE_TRACE_LITERAL([VOID_SIGHANDLER])
-m4trace:configure.in:865: -1- AC_DEFINE_TRACE_LITERAL([clock_t])
-m4trace:configure.in:866: -1- AC_DEFINE_TRACE_LITERAL([sigset_t])
-m4trace:configure.in:867: -1- AC_DEFINE_TRACE_LITERAL([HAVE_QUAD_T])
-m4trace:configure.in:867: -1- AC_DEFINE_TRACE_LITERAL([quad_t])
-m4trace:configure.in:868: -1- AC_DEFINE_TRACE_LITERAL([intmax_t])
-m4trace:configure.in:869: -1- AC_DEFINE_TRACE_LITERAL([uintmax_t])
-m4trace:configure.in:871: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SOCKLEN_T])
-m4trace:configure.in:871: -1- AC_DEFINE_TRACE_LITERAL([socklen_t])
-m4trace:configure.in:873: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+configure.in:865: the top level])
+m4trace:configure.in:865: -1- AC_DEFINE_TRACE_LITERAL([VOID_SIGHANDLER])
+m4trace:configure.in:866: -1- AC_DEFINE_TRACE_LITERAL([clock_t])
+m4trace:configure.in:867: -1- AC_DEFINE_TRACE_LITERAL([sigset_t])
+m4trace:configure.in:868: -1- AC_DEFINE_TRACE_LITERAL([HAVE_QUAD_T])
+m4trace:configure.in:868: -1- AC_DEFINE_TRACE_LITERAL([quad_t])
+m4trace:configure.in:869: -1- AC_DEFINE_TRACE_LITERAL([intmax_t])
+m4trace:configure.in:870: -1- AC_DEFINE_TRACE_LITERAL([uintmax_t])
+m4trace:configure.in:872: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SOCKLEN_T])
+m4trace:configure.in:872: -1- AC_DEFINE_TRACE_LITERAL([socklen_t])
+m4trace:configure.in:874: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:532: BASH_TYPE_RLIMIT is expanded from...
-configure.in:873: the top level])
-m4trace:configure.in:873: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:874: the top level])
+m4trace:configure.in:874: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:2173: AC_COMPILE_IFELSE is expanded from...
autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:532: BASH_TYPE_RLIMIT is expanded from...
-configure.in:873: the top level])
-m4trace:configure.in:873: -1- AC_DEFINE_TRACE_LITERAL([RLIMTYPE])
-m4trace:configure.in:873: -1- AC_DEFINE_TRACE_LITERAL([RLIMTYPE])
-m4trace:configure.in:876: -2- AC_DEFINE_TRACE_LITERAL([TERMIOS_LDISC])
-m4trace:configure.in:877: -2- AC_DEFINE_TRACE_LITERAL([TERMIO_LDISC])
-m4trace:configure.in:878: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
-You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
-autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-aclocal.m4:1058: BASH_STRUCT_DIRENT_D_INO is expanded from...
-configure.in:878: the top level])
-m4trace:configure.in:878: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_DIRENT_D_INO])
+configure.in:874: the top level])
+m4trace:configure.in:874: -1- AC_DEFINE_TRACE_LITERAL([RLIMTYPE])
+m4trace:configure.in:874: -1- AC_DEFINE_TRACE_LITERAL([RLIMTYPE])
+m4trace:configure.in:877: -2- AC_DEFINE_TRACE_LITERAL([TERMIOS_LDISC])
+m4trace:configure.in:878: -2- AC_DEFINE_TRACE_LITERAL([TERMIO_LDISC])
m4trace:configure.in:879: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-aclocal.m4:1091: BASH_STRUCT_DIRENT_D_FILENO is expanded from...
+aclocal.m4:1058: BASH_STRUCT_DIRENT_D_INO is expanded from...
configure.in:879: the top level])
-m4trace:configure.in:879: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_DIRENT_D_FILENO])
+m4trace:configure.in:879: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_DIRENT_D_INO])
m4trace:configure.in:880: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-aclocal.m4:1124: BASH_STRUCT_DIRENT_D_NAMLEN is expanded from...
+aclocal.m4:1091: BASH_STRUCT_DIRENT_D_FILENO is expanded from...
configure.in:880: the top level])
-m4trace:configure.in:880: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_DIRENT_D_NAMLEN])
+m4trace:configure.in:880: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_DIRENT_D_FILENO])
m4trace:configure.in:881: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-aclocal.m4:1177: BASH_STRUCT_WINSIZE is expanded from...
+aclocal.m4:1124: BASH_STRUCT_DIRENT_D_NAMLEN is expanded from...
configure.in:881: the top level])
-m4trace:configure.in:881: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:881: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_DIRENT_D_NAMLEN])
+m4trace:configure.in:882: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
+autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
+aclocal.m4:1177: BASH_STRUCT_WINSIZE is expanded from...
+configure.in:882: the top level])
+m4trace:configure.in:882: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:2173: AC_COMPILE_IFELSE is expanded from...
autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1177: BASH_STRUCT_WINSIZE is expanded from...
-configure.in:881: the top level])
-m4trace:configure.in:881: -1- AC_DEFINE_TRACE_LITERAL([STRUCT_WINSIZE_IN_SYS_IOCTL])
-m4trace:configure.in:881: -1- AC_DEFINE_TRACE_LITERAL([STRUCT_WINSIZE_IN_TERMIOS])
-m4trace:configure.in:882: -1- AC_DEFINE_TRACE_LITERAL([HAVE_TIMEVAL])
-m4trace:configure.in:883: -1- AC_CHECK_MEMBERS([struct stat.st_blocks])
-m4trace:configure.in:883: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_STAT_ST_BLOCKS])
-m4trace:configure.in:883: -1- AH_OUTPUT([HAVE_STRUCT_STAT_ST_BLOCKS], [/* Define to 1 if `st_blocks\' is member of `struct stat\'. */
+configure.in:882: the top level])
+m4trace:configure.in:882: -1- AC_DEFINE_TRACE_LITERAL([STRUCT_WINSIZE_IN_SYS_IOCTL])
+m4trace:configure.in:882: -1- AC_DEFINE_TRACE_LITERAL([STRUCT_WINSIZE_IN_TERMIOS])
+m4trace:configure.in:883: -1- AC_DEFINE_TRACE_LITERAL([HAVE_TIMEVAL])
+m4trace:configure.in:884: -1- AC_CHECK_MEMBERS([struct stat.st_blocks])
+m4trace:configure.in:884: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_STAT_ST_BLOCKS])
+m4trace:configure.in:884: -1- AH_OUTPUT([HAVE_STRUCT_STAT_ST_BLOCKS], [/* Define to 1 if `st_blocks\' is member of `struct stat\'. */
#undef HAVE_STRUCT_STAT_ST_BLOCKS])
-m4trace:configure.in:884: -1- AC_STRUCT_TM
-m4trace:configure.in:884: -1- AC_DEFINE_TRACE_LITERAL([TM_IN_SYS_TIME])
-m4trace:configure.in:884: -1- AH_OUTPUT([TM_IN_SYS_TIME], [/* Define to 1 if your <sys/time.h> declares `struct tm\'. */
+m4trace:configure.in:885: -1- AC_STRUCT_TM
+m4trace:configure.in:885: -1- AC_DEFINE_TRACE_LITERAL([TM_IN_SYS_TIME])
+m4trace:configure.in:885: -1- AH_OUTPUT([TM_IN_SYS_TIME], [/* Define to 1 if your <sys/time.h> declares `struct tm\'. */
#undef TM_IN_SYS_TIME])
-m4trace:configure.in:885: -1- AC_STRUCT_TIMEZONE
-m4trace:configure.in:885: -1- AC_CHECK_MEMBERS([struct tm.tm_zone], [], [], [#include <sys/types.h>
+m4trace:configure.in:886: -1- AC_STRUCT_TIMEZONE
+m4trace:configure.in:886: -1- AC_CHECK_MEMBERS([struct tm.tm_zone], [], [], [#include <sys/types.h>
#include <$ac_cv_struct_tm>
])
-m4trace:configure.in:885: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_TM_TM_ZONE])
-m4trace:configure.in:885: -1- AH_OUTPUT([HAVE_STRUCT_TM_TM_ZONE], [/* Define to 1 if `tm_zone\' is member of `struct tm\'. */
+m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_TM_TM_ZONE])
+m4trace:configure.in:886: -1- AH_OUTPUT([HAVE_STRUCT_TM_TM_ZONE], [/* Define to 1 if `tm_zone\' is member of `struct tm\'. */
#undef HAVE_STRUCT_TM_TM_ZONE])
-m4trace:configure.in:885: -1- AC_DEFINE_TRACE_LITERAL([HAVE_TM_ZONE])
-m4trace:configure.in:885: -1- AH_OUTPUT([HAVE_TM_ZONE], [/* Define to 1 if your `struct tm\' has `tm_zone\'. Deprecated, use
+m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([HAVE_TM_ZONE])
+m4trace:configure.in:886: -1- AH_OUTPUT([HAVE_TM_ZONE], [/* Define to 1 if your `struct tm\' has `tm_zone\'. Deprecated, use
`HAVE_STRUCT_TM_TM_ZONE\' instead. */
#undef HAVE_TM_ZONE])
-m4trace:configure.in:885: -1- AC_DEFINE_TRACE_LITERAL([HAVE_TZNAME])
-m4trace:configure.in:885: -1- AH_OUTPUT([HAVE_TZNAME], [/* Define to 1 if you don\'t have `tm_zone\' but do have the external array
+m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([HAVE_TZNAME])
+m4trace:configure.in:886: -1- AH_OUTPUT([HAVE_TZNAME], [/* Define to 1 if you don\'t have `tm_zone\' but do have the external array
`tzname\'. */
#undef HAVE_TZNAME])
-m4trace:configure.in:886: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_TIMEZONE])
-m4trace:configure.in:889: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+m4trace:configure.in:887: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRUCT_TIMEZONE])
+m4trace:configure.in:890: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:307: BASH_FUNC_STRSIGNAL is expanded from...
-configure.in:889: the top level])
-m4trace:configure.in:889: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRSIGNAL])
-m4trace:configure.in:890: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
-You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
-autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-aclocal.m4:360: BASH_FUNC_OPENDIR_CHECK is expanded from...
configure.in:890: the top level])
-m4trace:configure.in:890: -1- AC_DEFINE_TRACE_LITERAL([OPENDIR_NOT_ROBUST])
+m4trace:configure.in:890: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STRSIGNAL])
m4trace:configure.in:891: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-aclocal.m4:685: BASH_FUNC_ULIMIT_MAXFDS is expanded from...
+aclocal.m4:360: BASH_FUNC_OPENDIR_CHECK is expanded from...
configure.in:891: the top level])
-m4trace:configure.in:891: -1- AC_DEFINE_TRACE_LITERAL([ULIMIT_MAXFDS])
+m4trace:configure.in:891: -1- AC_DEFINE_TRACE_LITERAL([OPENDIR_NOT_ROBUST])
m4trace:configure.in:892: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
-aclocal.m4:606: BASH_FUNC_GETENV is expanded from...
+aclocal.m4:685: BASH_FUNC_ULIMIT_MAXFDS is expanded from...
configure.in:892: the top level])
-m4trace:configure.in:892: -1- AC_DEFINE_TRACE_LITERAL([CAN_REDEFINE_GETENV])
-m4trace:configure.in:894: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+m4trace:configure.in:892: -1- AC_DEFINE_TRACE_LITERAL([ULIMIT_MAXFDS])
+m4trace:configure.in:893: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
+autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
+aclocal.m4:606: BASH_FUNC_GETENV is expanded from...
+configure.in:893: the top level])
+m4trace:configure.in:893: -1- AC_DEFINE_TRACE_LITERAL([CAN_REDEFINE_GETENV])
+m4trace:configure.in:895: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:711: BASH_FUNC_GETCWD is expanded from...
-configure.in:894: the top level])
-m4trace:configure.in:894: -1- AC_DEFINE_TRACE_LITERAL([GETCWD_BROKEN])
-m4trace:configure.in:894: -1- AC_LIBSOURCE([getcwd.c])
-m4trace:configure.in:894: -1- AC_SUBST([LIB@&t@OBJS])
-m4trace:configure.in:896: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:895: the top level])
+m4trace:configure.in:895: -1- AC_DEFINE_TRACE_LITERAL([GETCWD_BROKEN])
+m4trace:configure.in:895: -1- AC_LIBSOURCE([getcwd.c])
+m4trace:configure.in:895: -1- AC_SUBST([LIB@&t@OBJS])
+m4trace:configure.in:897: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:812: BASH_FUNC_POSIX_SETJMP is expanded from...
-configure.in:896: the top level])
-m4trace:configure.in:896: -1- AC_DEFINE_TRACE_LITERAL([HAVE_POSIX_SIGSETJMP])
-m4trace:configure.in:897: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:897: the top level])
+m4trace:configure.in:897: -1- AC_DEFINE_TRACE_LITERAL([HAVE_POSIX_SIGSETJMP])
+m4trace:configure.in:898: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:861: BASH_FUNC_STRCOLL is expanded from...
-configure.in:897: the top level])
-m4trace:configure.in:897: -1- AC_DEFINE_TRACE_LITERAL([STRCOLL_BROKEN])
-m4trace:configure.in:903: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:898: the top level])
+m4trace:configure.in:898: -1- AC_DEFINE_TRACE_LITERAL([STRCOLL_BROKEN])
+m4trace:configure.in:904: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:636: BASH_FUNC_STD_PUTENV is expanded from...
-configure.in:903: the top level])
-m4trace:configure.in:903: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STD_PUTENV])
-m4trace:configure.in:905: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STD_PUTENV])
-m4trace:configure.in:908: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
+configure.in:904: the top level])
+m4trace:configure.in:904: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STD_PUTENV])
+m4trace:configure.in:906: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STD_PUTENV])
+m4trace:configure.in:909: -1- _m4_warn([obsolete], [The macro `AC_TRY_LINK' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2223: AC_TRY_LINK is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
autoconf/general.m4:1808: AC_CACHE_CHECK is expanded from...
aclocal.m4:666: BASH_FUNC_STD_UNSETENV is expanded from...
-configure.in:908: the top level])
-m4trace:configure.in:908: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STD_UNSETENV])
-m4trace:configure.in:910: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STD_UNSETENV])
-m4trace:configure.in:913: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:909: the top level])
+m4trace:configure.in:909: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STD_UNSETENV])
+m4trace:configure.in:911: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STD_UNSETENV])
+m4trace:configure.in:914: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:887: BASH_FUNC_PRINTF_A_FORMAT is expanded from...
-configure.in:913: the top level])
-m4trace:configure.in:913: -1- AC_DEFINE_TRACE_LITERAL([HAVE_PRINTF_A_FORMAT])
-m4trace:configure.in:916: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:914: the top level])
+m4trace:configure.in:914: -1- AC_DEFINE_TRACE_LITERAL([HAVE_PRINTF_A_FORMAT])
+m4trace:configure.in:917: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1338: BASH_SYS_REINSTALL_SIGHANDLERS is expanded from...
-configure.in:916: the top level])
-m4trace:configure.in:916: -1- AC_DEFINE_TRACE_LITERAL([MUST_REINSTALL_SIGHANDLERS])
-m4trace:configure.in:917: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:917: the top level])
+m4trace:configure.in:917: -1- AC_DEFINE_TRACE_LITERAL([MUST_REINSTALL_SIGHANDLERS])
+m4trace:configure.in:918: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1396: BASH_SYS_JOB_CONTROL_MISSING is expanded from...
-configure.in:917: the top level])
-m4trace:configure.in:917: -1- AC_DEFINE_TRACE_LITERAL([JOB_CONTROL_MISSING])
-m4trace:configure.in:918: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:918: the top level])
+m4trace:configure.in:918: -1- AC_DEFINE_TRACE_LITERAL([JOB_CONTROL_MISSING])
+m4trace:configure.in:919: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1448: BASH_SYS_NAMED_PIPES is expanded from...
-configure.in:918: the top level])
-m4trace:configure.in:918: -1- AC_DEFINE_TRACE_LITERAL([NAMED_PIPES_MISSING])
-m4trace:configure.in:921: -1- AC_DEFINE_TRACE_LITERAL([GWINSZ_IN_SYS_IOCTL])
-m4trace:configure.in:921: -1- AH_OUTPUT([GWINSZ_IN_SYS_IOCTL], [/* Define to 1 if `TIOCGWINSZ\' requires <sys/ioctl.h>. */
+configure.in:919: the top level])
+m4trace:configure.in:919: -1- AC_DEFINE_TRACE_LITERAL([NAMED_PIPES_MISSING])
+m4trace:configure.in:922: -1- AC_DEFINE_TRACE_LITERAL([GWINSZ_IN_SYS_IOCTL])
+m4trace:configure.in:922: -1- AH_OUTPUT([GWINSZ_IN_SYS_IOCTL], [/* Define to 1 if `TIOCGWINSZ\' requires <sys/ioctl.h>. */
#undef GWINSZ_IN_SYS_IOCTL])
-m4trace:configure.in:922: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+m4trace:configure.in:923: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1491: BASH_HAVE_TIOCSTAT is expanded from...
-configure.in:922: the top level])
-m4trace:configure.in:922: -1- AC_DEFINE_TRACE_LITERAL([TIOCSTAT_IN_SYS_IOCTL])
-m4trace:configure.in:923: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+configure.in:923: the top level])
+m4trace:configure.in:923: -1- AC_DEFINE_TRACE_LITERAL([TIOCSTAT_IN_SYS_IOCTL])
+m4trace:configure.in:924: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1503: BASH_HAVE_FIONREAD is expanded from...
-configure.in:923: the top level])
-m4trace:configure.in:923: -1- AC_DEFINE_TRACE_LITERAL([FIONREAD_IN_SYS_IOCTL])
-m4trace:configure.in:925: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:924: the top level])
+m4trace:configure.in:924: -1- AC_DEFINE_TRACE_LITERAL([FIONREAD_IN_SYS_IOCTL])
+m4trace:configure.in:926: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1902: BASH_CHECK_WCONTINUED is expanded from...
-configure.in:925: the top level])
-m4trace:configure.in:925: -1- AC_DEFINE_TRACE_LITERAL([WCONTINUED_BROKEN])
-m4trace:configure.in:928: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+configure.in:926: the top level])
+m4trace:configure.in:926: -1- AC_DEFINE_TRACE_LITERAL([WCONTINUED_BROKEN])
+m4trace:configure.in:929: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1520: BASH_CHECK_SPEED_T is expanded from...
-configure.in:928: the top level])
-m4trace:configure.in:928: -1- AC_DEFINE_TRACE_LITERAL([SPEED_T_IN_SYS_TYPES])
-m4trace:configure.in:929: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETPW_DECLS])
-m4trace:configure.in:930: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
+configure.in:929: the top level])
+m4trace:configure.in:929: -1- AC_DEFINE_TRACE_LITERAL([SPEED_T_IN_SYS_TYPES])
+m4trace:configure.in:930: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GETPW_DECLS])
+m4trace:configure.in:931: -1- _m4_warn([obsolete], [The macro `AC_TRY_RUN' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2289: AC_TRY_RUN is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1665: BASH_CHECK_RTSIGS is expanded from...
-configure.in:930: the top level])
-m4trace:configure.in:930: -1- AC_DEFINE_TRACE_LITERAL([UNUSABLE_RT_SIGNALS])
-m4trace:configure.in:931: -1- AC_SUBST([SIGLIST_O])
-m4trace:configure.in:935: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+configure.in:931: the top level])
+m4trace:configure.in:931: -1- AC_DEFINE_TRACE_LITERAL([UNUSABLE_RT_SIGNALS])
+m4trace:configure.in:932: -1- AC_SUBST([SIGLIST_O])
+m4trace:configure.in:936: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1614: BASH_CHECK_KERNEL_RLIMIT is expanded from...
-configure.in:935: the top level])
-m4trace:configure.in:935: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
+configure.in:936: the top level])
+m4trace:configure.in:936: -1- _m4_warn([obsolete], [The macro `AC_TRY_COMPILE' is obsolete.
You should run autoupdate.], [autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:2173: AC_COMPILE_IFELSE is expanded from...
autoconf/general.m4:2180: AC_TRY_COMPILE is expanded from...
autoconf/general.m4:1799: AC_CACHE_VAL is expanded from...
aclocal.m4:1614: BASH_CHECK_KERNEL_RLIMIT is expanded from...
-configure.in:935: the top level])
-m4trace:configure.in:935: -1- AC_DEFINE_TRACE_LITERAL([RLIMIT_NEEDS_KERNEL])
-m4trace:configure.in:943: -1- AC_CHECK_LIB([termcap], [tgetent], [bash_cv_termcap_lib=libtermcap], [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
+configure.in:936: the top level])
+m4trace:configure.in:936: -1- AC_DEFINE_TRACE_LITERAL([RLIMIT_NEEDS_KERNEL])
+m4trace:configure.in:944: -1- AC_CHECK_LIB([termcap], [tgetent], [bash_cv_termcap_lib=libtermcap], [AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
[AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
[AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
bash_cv_termcap_lib=gnutermcap)])])])
-m4trace:configure.in:943: -1- AC_CHECK_LIB([tinfo], [tgetent], [bash_cv_termcap_lib=libtinfo], [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
+m4trace:configure.in:944: -1- AC_CHECK_LIB([tinfo], [tgetent], [bash_cv_termcap_lib=libtinfo], [AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
[AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
bash_cv_termcap_lib=gnutermcap)])])
-m4trace:configure.in:943: -1- AC_CHECK_LIB([curses], [tgetent], [bash_cv_termcap_lib=libcurses], [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
+m4trace:configure.in:944: -1- AC_CHECK_LIB([curses], [tgetent], [bash_cv_termcap_lib=libcurses], [AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
bash_cv_termcap_lib=gnutermcap)])
-m4trace:configure.in:943: -1- AC_CHECK_LIB([ncurses], [tgetent], [bash_cv_termcap_lib=libncurses], [bash_cv_termcap_lib=gnutermcap])
-m4trace:configure.in:945: -1- AC_SUBST([TERMCAP_LIB])
-m4trace:configure.in:946: -1- AC_SUBST([TERMCAP_DEP])
-m4trace:configure.in:948: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_FD])
-m4trace:configure.in:948: -1- AC_DEFINE_TRACE_LITERAL([DEV_FD_PREFIX])
-m4trace:configure.in:948: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_FD])
-m4trace:configure.in:948: -1- AC_DEFINE_TRACE_LITERAL([DEV_FD_PREFIX])
-m4trace:configure.in:949: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_STDIN])
-m4trace:configure.in:950: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_MAIL_DIRECTORY])
-m4trace:configure.in:957: -1- AC_DEFINE_TRACE_LITERAL([JOB_CONTROL])
-m4trace:configure.in:963: -1- AC_SUBST([JOBS_O])
-m4trace:configure.in:976: -1- AC_DEFINE_TRACE_LITERAL([SVR4_2])
-m4trace:configure.in:977: -1- AC_DEFINE_TRACE_LITERAL([SVR4])
+m4trace:configure.in:944: -1- AC_CHECK_LIB([ncurses], [tgetent], [bash_cv_termcap_lib=libncurses], [bash_cv_termcap_lib=gnutermcap])
+m4trace:configure.in:946: -1- AC_SUBST([TERMCAP_LIB])
+m4trace:configure.in:947: -1- AC_SUBST([TERMCAP_DEP])
+m4trace:configure.in:949: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_FD])
+m4trace:configure.in:949: -1- AC_DEFINE_TRACE_LITERAL([DEV_FD_PREFIX])
+m4trace:configure.in:949: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_FD])
+m4trace:configure.in:949: -1- AC_DEFINE_TRACE_LITERAL([DEV_FD_PREFIX])
+m4trace:configure.in:950: -1- AC_DEFINE_TRACE_LITERAL([HAVE_DEV_STDIN])
+m4trace:configure.in:951: -1- AC_DEFINE_TRACE_LITERAL([DEFAULT_MAIL_DIRECTORY])
+m4trace:configure.in:958: -1- AC_DEFINE_TRACE_LITERAL([JOB_CONTROL])
+m4trace:configure.in:964: -1- AC_SUBST([JOBS_O])
+m4trace:configure.in:977: -1- AC_DEFINE_TRACE_LITERAL([SVR4_2])
m4trace:configure.in:978: -1- AC_DEFINE_TRACE_LITERAL([SVR4])
-m4trace:configure.in:979: -1- AC_DEFINE_TRACE_LITERAL([SVR5])
-m4trace:configure.in:994: -1- AC_DEFINE_TRACE_LITERAL([PGRP_PIPE])
-m4trace:configure.in:1041: -1- AC_SUBST([SHOBJ_CC])
-m4trace:configure.in:1042: -1- AC_SUBST([SHOBJ_CFLAGS])
-m4trace:configure.in:1043: -1- AC_SUBST([SHOBJ_LD])
-m4trace:configure.in:1044: -1- AC_SUBST([SHOBJ_LDFLAGS])
-m4trace:configure.in:1045: -1- AC_SUBST([SHOBJ_XLDFLAGS])
-m4trace:configure.in:1046: -1- AC_SUBST([SHOBJ_LIBS])
-m4trace:configure.in:1047: -1- AC_SUBST([SHOBJ_STATUS])
-m4trace:configure.in:1072: -1- AC_SUBST([PROFILE_FLAGS])
-m4trace:configure.in:1074: -1- AC_SUBST([incdir])
-m4trace:configure.in:1075: -1- AC_SUBST([BUILD_DIR])
-m4trace:configure.in:1077: -1- AC_SUBST([YACC])
-m4trace:configure.in:1078: -1- AC_SUBST([AR])
-m4trace:configure.in:1079: -1- AC_SUBST([ARFLAGS])
-m4trace:configure.in:1081: -1- AC_SUBST([BASHVERS])
-m4trace:configure.in:1082: -1- AC_SUBST([RELSTATUS])
-m4trace:configure.in:1083: -1- AC_SUBST([DEBUG])
-m4trace:configure.in:1084: -1- AC_SUBST([MALLOC_DEBUG])
-m4trace:configure.in:1086: -1- AC_SUBST([host_cpu])
-m4trace:configure.in:1087: -1- AC_SUBST([host_vendor])
-m4trace:configure.in:1088: -1- AC_SUBST([host_os])
-m4trace:configure.in:1090: -1- AC_SUBST([LOCAL_LIBS])
-m4trace:configure.in:1091: -1- AC_SUBST([LOCAL_CFLAGS])
-m4trace:configure.in:1092: -1- AC_SUBST([LOCAL_LDFLAGS])
-m4trace:configure.in:1093: -1- AC_SUBST([LOCAL_DEFS])
-m4trace:configure.in:1107: -1- AC_CONFIG_FILES([Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \
+m4trace:configure.in:979: -1- AC_DEFINE_TRACE_LITERAL([SVR4])
+m4trace:configure.in:980: -1- AC_DEFINE_TRACE_LITERAL([SVR5])
+m4trace:configure.in:995: -1- AC_DEFINE_TRACE_LITERAL([PGRP_PIPE])
+m4trace:configure.in:1042: -1- AC_SUBST([SHOBJ_CC])
+m4trace:configure.in:1043: -1- AC_SUBST([SHOBJ_CFLAGS])
+m4trace:configure.in:1044: -1- AC_SUBST([SHOBJ_LD])
+m4trace:configure.in:1045: -1- AC_SUBST([SHOBJ_LDFLAGS])
+m4trace:configure.in:1046: -1- AC_SUBST([SHOBJ_XLDFLAGS])
+m4trace:configure.in:1047: -1- AC_SUBST([SHOBJ_LIBS])
+m4trace:configure.in:1048: -1- AC_SUBST([SHOBJ_STATUS])
+m4trace:configure.in:1073: -1- AC_SUBST([PROFILE_FLAGS])
+m4trace:configure.in:1075: -1- AC_SUBST([incdir])
+m4trace:configure.in:1076: -1- AC_SUBST([BUILD_DIR])
+m4trace:configure.in:1078: -1- AC_SUBST([YACC])
+m4trace:configure.in:1079: -1- AC_SUBST([AR])
+m4trace:configure.in:1080: -1- AC_SUBST([ARFLAGS])
+m4trace:configure.in:1082: -1- AC_SUBST([BASHVERS])
+m4trace:configure.in:1083: -1- AC_SUBST([RELSTATUS])
+m4trace:configure.in:1084: -1- AC_SUBST([DEBUG])
+m4trace:configure.in:1085: -1- AC_SUBST([MALLOC_DEBUG])
+m4trace:configure.in:1087: -1- AC_SUBST([host_cpu])
+m4trace:configure.in:1088: -1- AC_SUBST([host_vendor])
+m4trace:configure.in:1089: -1- AC_SUBST([host_os])
+m4trace:configure.in:1091: -1- AC_SUBST([LOCAL_LIBS])
+m4trace:configure.in:1092: -1- AC_SUBST([LOCAL_CFLAGS])
+m4trace:configure.in:1093: -1- AC_SUBST([LOCAL_LDFLAGS])
+m4trace:configure.in:1094: -1- AC_SUBST([LOCAL_DEFS])
+m4trace:configure.in:1108: -1- AC_CONFIG_FILES([Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \
lib/intl/Makefile \
lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile \
lib/tilde/Makefile doc/Makefile support/Makefile po/Makefile.in \
examples/loadables/Makefile examples/loadables/perl/Makefile \
pathnames.h])
-m4trace:configure.in:1107: -1- _m4_warn([obsolete], [AC_OUTPUT should be used without arguments.
+m4trace:configure.in:1108: -1- _m4_warn([obsolete], [AC_OUTPUT should be used without arguments.
You should run autoupdate.], [])
-m4trace:configure.in:1107: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
-m4trace:configure.in:1107: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
+m4trace:configure.in:1108: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
+m4trace:configure.in:1108: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
diff --git a/bashhist.c b/bashhist.c
index 5d2b8174..6468a538 100644
--- a/bashhist.c
+++ b/bashhist.c
@@ -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");
diff --git a/bashhist.c~ b/bashhist.c~
new file mode 100644
index 00000000..5d2b8174
--- /dev/null
+++ b/bashhist.c~
@@ -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 */
diff --git a/builtins/mkbuiltins.c b/builtins/mkbuiltins.c
index 94953e6c..632e42e7 100644
--- a/builtins/mkbuiltins.c
+++ b/builtins/mkbuiltins.c
@@ -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
diff --git a/builtins/mkbuiltins.c~ b/builtins/mkbuiltins.c~
new file mode 100644
index 00000000..632e42e7
--- /dev/null
+++ b/builtins/mkbuiltins.c~
@@ -0,0 +1,1566 @@
+/* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
+ a single source file called builtins.def. */
+
+/* Copyright (C) 1987-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. */
+
+/* #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
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#ifndef _MINIX
+# include "../bashtypes.h"
+# if defined (HAVE_SYS_FILE_H)
+# include <sys/file.h>
+# endif
+#endif
+
+#include "posixstat.h"
+#include "filecntl.h"
+
+#include "../bashansi.h"
+#include <stdio.h>
+#include <errno.h>
+
+#include "stdc.h"
+
+#define DOCFILE "builtins.texi"
+
+#ifndef errno
+extern int errno;
+#endif
+
+static char *xmalloc (), *xrealloc ();
+
+#if !defined (__STDC__) && !defined (strcpy)
+extern char *strcpy ();
+#endif /* !__STDC__ && !strcpy */
+
+#define savestring(x) strcpy (xmalloc (1 + strlen (x)), (x))
+#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
+
+/* Flag values that builtins can have. */
+#define BUILTIN_FLAG_SPECIAL 0x01
+#define BUILTIN_FLAG_ASSIGNMENT 0x02
+
+#define BASE_INDENT 4
+
+/* If this stream descriptor is non-zero, then write
+ texinfo documentation to it. */
+FILE *documentation_file = (FILE *)NULL;
+
+/* Non-zero means to only produce documentation. */
+int only_documentation = 0;
+
+/* Non-zero means to not do any productions. */
+int inhibit_production = 0;
+
+/* Non-zero means to produce separate help files for each builtin, named by
+ the builtin name, in `./helpfiles'. */
+int separate_helpfiles = 0;
+
+/* Non-zero means to create single C strings for each `longdoc', with
+ embedded newlines, for ease of translation. */
+int single_longdoc_strings = 1;
+
+/* The name of a directory into which the separate external help files will
+ eventually be installed. */
+char *helpfile_directory;
+
+/* The name of a directory to precede the filename when reporting
+ errors. */
+char *error_directory = (char *)NULL;
+
+/* The name of the structure file. */
+char *struct_filename = (char *)NULL;
+
+/* The name of the external declaration file. */
+char *extern_filename = (char *)NULL;
+
+/* Here is a structure for manipulating arrays of data. */
+typedef struct {
+ int size; /* Number of slots allocated to array. */
+ int sindex; /* Current location in array. */
+ int width; /* Size of each element. */
+ int growth_rate; /* How fast to grow. */
+ char **array; /* The array itself. */
+} ARRAY;
+
+/* Here is a structure defining a single BUILTIN. */
+typedef struct {
+ char *name; /* The name of this builtin. */
+ char *function; /* The name of the function to call. */
+ char *shortdoc; /* The short documentation for this builtin. */
+ char *docname; /* Possible name for documentation string. */
+ ARRAY *longdoc; /* The long documentation for this builtin. */
+ ARRAY *dependencies; /* Null terminated array of #define names. */
+ int flags; /* Flags for this builtin. */
+} BUILTIN_DESC;
+
+/* Here is a structure which defines a DEF file. */
+typedef struct {
+ char *filename; /* The name of the input def file. */
+ ARRAY *lines; /* The contents of the file. */
+ int line_number; /* The current line number. */
+ char *production; /* The name of the production file. */
+ FILE *output; /* Open file stream for PRODUCTION. */
+ ARRAY *builtins; /* Null terminated array of BUILTIN_DESC *. */
+} DEF_FILE;
+
+/* The array of all builtins encountered during execution of this code. */
+ARRAY *saved_builtins = (ARRAY *)NULL;
+
+/* The Posix.2 so-called `special' builtins. */
+char *special_builtins[] =
+{
+ ":", ".", "source", "break", "continue", "eval", "exec", "exit",
+ "export", "readonly", "return", "set", "shift", "times", "trap", "unset",
+ (char *)NULL
+};
+
+/* The builtin commands that take assignment statements as arguments. */
+char *assignment_builtins[] =
+{
+ "alias", "declare", "export", "local", "readonly", "typeset",
+ (char *)NULL
+};
+
+/* Forward declarations. */
+static int is_special_builtin ();
+static int is_assignment_builtin ();
+
+#if !defined (HAVE_RENAME)
+static int rename ();
+#endif
+
+void extract_info ();
+
+void file_error ();
+void line_error ();
+
+void write_file_headers ();
+void write_file_footers ();
+void write_ifdefs ();
+void write_endifs ();
+void write_documentation ();
+void write_longdocs ();
+void write_builtins ();
+
+int write_helpfiles ();
+
+void free_defs ();
+void add_documentation ();
+
+void must_be_building ();
+void remove_trailing_whitespace ();
+
+#define document_name(b) ((b)->docname ? (b)->docname : (b)->name)
+
+
+/* For each file mentioned on the command line, process it and
+ write the information to STRUCTFILE and EXTERNFILE, while
+ creating the production file if neccessary. */
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int arg_index = 1;
+ FILE *structfile, *externfile;
+ char *documentation_filename, *temp_struct_filename;
+
+ structfile = externfile = (FILE *)NULL;
+ documentation_filename = DOCFILE;
+ temp_struct_filename = (char *)NULL;
+
+ while (arg_index < argc && argv[arg_index][0] == '-')
+ {
+ char *arg = argv[arg_index++];
+
+ if (strcmp (arg, "-externfile") == 0)
+ extern_filename = argv[arg_index++];
+ else if (strcmp (arg, "-structfile") == 0)
+ struct_filename = argv[arg_index++];
+ else if (strcmp (arg, "-noproduction") == 0)
+ inhibit_production = 1;
+ else if (strcmp (arg, "-document") == 0)
+ documentation_file = fopen (documentation_filename, "w");
+ else if (strcmp (arg, "-D") == 0)
+ {
+ int len;
+
+ if (error_directory)
+ free (error_directory);
+
+ error_directory = xmalloc (2 + strlen (argv[arg_index]));
+ strcpy (error_directory, argv[arg_index]);
+ len = strlen (error_directory);
+
+ if (len && error_directory[len - 1] != '/')
+ strcat (error_directory, "/");
+
+ arg_index++;
+ }
+ else if (strcmp (arg, "-documentonly") == 0)
+ {
+ only_documentation = 1;
+ documentation_file = fopen (documentation_filename, "w");
+ }
+ else if (strcmp (arg, "-H") == 0)
+ {
+ separate_helpfiles = 1;
+ helpfile_directory = argv[arg_index++];
+ }
+ else if (strcmp (arg, "-S") == 0)
+ single_longdoc_strings = 0;
+ else
+ {
+ fprintf (stderr, "%s: Unknown flag %s.\n", argv[0], arg);
+ exit (2);
+ }
+ }
+
+ /* If there are no files to process, just quit now. */
+ if (arg_index == argc)
+ exit (0);
+
+ if (!only_documentation)
+ {
+ /* Open the files. */
+ if (struct_filename)
+ {
+ temp_struct_filename = xmalloc (15);
+ sprintf (temp_struct_filename, "mk-%ld", (long) getpid ());
+ structfile = fopen (temp_struct_filename, "w");
+
+ if (!structfile)
+ file_error (temp_struct_filename);
+ }
+
+ if (extern_filename)
+ {
+ externfile = fopen (extern_filename, "w");
+
+ if (!externfile)
+ file_error (extern_filename);
+ }
+
+ /* Write out the headers. */
+ write_file_headers (structfile, externfile);
+ }
+
+ if (documentation_file)
+ {
+ fprintf (documentation_file, "@c Table of builtins created with %s.\n",
+ argv[0]);
+ fprintf (documentation_file, "@ftable @asis\n");
+ }
+
+ /* Process the .def files. */
+ while (arg_index < argc)
+ {
+ register char *arg;
+
+ arg = argv[arg_index++];
+
+ extract_info (arg, structfile, externfile);
+ }
+
+ /* Close the files. */
+ if (!only_documentation)
+ {
+ /* Write the footers. */
+ write_file_footers (structfile, externfile);
+
+ if (structfile)
+ {
+ write_longdocs (structfile, saved_builtins);
+ fclose (structfile);
+ rename (temp_struct_filename, struct_filename);
+ }
+
+ if (externfile)
+ fclose (externfile);
+ }
+
+ if (separate_helpfiles)
+ {
+ write_helpfiles (saved_builtins);
+ }
+
+ if (documentation_file)
+ {
+ fprintf (documentation_file, "@end ftable\n");
+ fclose (documentation_file);
+ }
+
+ exit (0);
+}
+
+/* **************************************************************** */
+/* */
+/* Array Functions and Manipulators */
+/* */
+/* **************************************************************** */
+
+/* Make a new array, and return a pointer to it. The array will
+ contain elements of size WIDTH, and is initialized to no elements. */
+ARRAY *
+array_create (width)
+ int width;
+{
+ ARRAY *array;
+
+ array = (ARRAY *)xmalloc (sizeof (ARRAY));
+ array->size = 0;
+ array->sindex = 0;
+ array->width = width;
+
+ /* Default to increasing size in units of 20. */
+ array->growth_rate = 20;
+
+ array->array = (char **)NULL;
+
+ return (array);
+}
+
+/* Copy the array of strings in ARRAY. */
+ARRAY *
+copy_string_array (array)
+ ARRAY *array;
+{
+ register int i;
+ ARRAY *copy;
+
+ if (!array)
+ return (ARRAY *)NULL;
+
+ copy = array_create (sizeof (char *));
+
+ copy->size = array->size;
+ copy->sindex = array->sindex;
+ copy->width = array->width;
+
+ copy->array = (char **)xmalloc ((1 + array->sindex) * sizeof (char *));
+
+ for (i = 0; i < array->sindex; i++)
+ copy->array[i] = savestring (array->array[i]);
+
+ copy->array[i] = (char *)NULL;
+
+ return (copy);
+}
+
+/* Add ELEMENT to ARRAY, growing the array if neccessary. */
+void
+array_add (element, array)
+ char *element;
+ ARRAY *array;
+{
+ if (array->sindex + 2 > array->size)
+ array->array = (char **)xrealloc
+ (array->array, (array->size += array->growth_rate) * array->width);
+
+ array->array[array->sindex++] = element;
+ array->array[array->sindex] = (char *)NULL;
+}
+
+/* Free an allocated array and data pointer. */
+void
+array_free (array)
+ ARRAY *array;
+{
+ if (array->array)
+ free (array->array);
+
+ free (array);
+}
+
+/* **************************************************************** */
+/* */
+/* Processing a DEF File */
+/* */
+/* **************************************************************** */
+
+/* The definition of a function. */
+typedef int Function ();
+typedef int mk_handler_func_t __P((char *, DEF_FILE *, char *));
+
+/* Structure handles processor directives. */
+typedef struct {
+ char *directive;
+ mk_handler_func_t *function;
+} HANDLER_ENTRY;
+
+extern int builtin_handler __P((char *, DEF_FILE *, char *));
+extern int function_handler __P((char *, DEF_FILE *, char *));
+extern int short_doc_handler __P((char *, DEF_FILE *, char *));
+extern int comment_handler __P((char *, DEF_FILE *, char *));
+extern int depends_on_handler __P((char *, DEF_FILE *, char *));
+extern int produces_handler __P((char *, DEF_FILE *, char *));
+extern int end_handler __P((char *, DEF_FILE *, char *));
+extern int docname_handler __P((char *, DEF_FILE *, char *));
+
+HANDLER_ENTRY handlers[] = {
+ { "BUILTIN", builtin_handler },
+ { "DOCNAME", docname_handler },
+ { "FUNCTION", function_handler },
+ { "SHORT_DOC", short_doc_handler },
+ { "$", comment_handler },
+ { "COMMENT", comment_handler },
+ { "DEPENDS_ON", depends_on_handler },
+ { "PRODUCES", produces_handler },
+ { "END", end_handler },
+ { (char *)NULL, (mk_handler_func_t *)NULL }
+};
+
+/* Return the entry in the table of handlers for NAME. */
+HANDLER_ENTRY *
+find_directive (directive)
+ char *directive;
+{
+ register int i;
+
+ for (i = 0; handlers[i].directive; i++)
+ if (strcmp (handlers[i].directive, directive) == 0)
+ return (&handlers[i]);
+
+ return ((HANDLER_ENTRY *)NULL);
+}
+
+/* Non-zero indicates that a $BUILTIN has been seen, but not
+ the corresponding $END. */
+static int building_builtin = 0;
+
+/* Non-zero means to output cpp line and file information before
+ printing the current line to the production file. */
+int output_cpp_line_info = 0;
+
+/* The main function of this program. Read FILENAME and act on what is
+ found. Lines not starting with a dollar sign are copied to the
+ $PRODUCES target, if one is present. Lines starting with a dollar sign
+ are directives to this program, specifying the name of the builtin, the
+ function to call, the short documentation and the long documentation
+ strings. FILENAME can contain multiple $BUILTINs, but only one $PRODUCES
+ target. After the file has been processed, write out the names of
+ builtins found in each $BUILTIN. Plain text found before the $PRODUCES
+ is ignored, as is "$$ comment text". */
+void
+extract_info (filename, structfile, externfile)
+ char *filename;
+ FILE *structfile, *externfile;
+{
+ register int i;
+ DEF_FILE *defs;
+ struct stat finfo;
+ size_t file_size;
+ char *buffer, *line;
+ int fd, nr;
+
+ if (stat (filename, &finfo) == -1)
+ file_error (filename);
+
+ fd = open (filename, O_RDONLY, 0666);
+
+ if (fd == -1)
+ file_error (filename);
+
+ file_size = (size_t)finfo.st_size;
+ buffer = xmalloc (1 + file_size);
+
+ if ((nr = read (fd, buffer, file_size)) < 0)
+ file_error (filename);
+
+ /* This is needed on WIN32, and does not hurt on Unix. */
+ if (nr < file_size)
+ file_size = nr;
+
+ close (fd);
+
+ if (nr == 0)
+ {
+ fprintf (stderr, "mkbuiltins: %s: skipping zero-length file\n", filename);
+ return;
+ }
+
+ /* Create and fill in the initial structure describing this file. */
+ defs = (DEF_FILE *)xmalloc (sizeof (DEF_FILE));
+ defs->filename = filename;
+ defs->lines = array_create (sizeof (char *));
+ defs->line_number = 0;
+ defs->production = (char *)NULL;
+ defs->output = (FILE *)NULL;
+ defs->builtins = (ARRAY *)NULL;
+
+ /* Build the array of lines. */
+ i = 0;
+ while (i < file_size)
+ {
+ array_add (&buffer[i], defs->lines);
+
+ while (buffer[i] != '\n' && i < file_size)
+ i++;
+ buffer[i++] = '\0';
+ }
+
+ /* Begin processing the input file. We don't write any output
+ until we have a file to write output to. */
+ output_cpp_line_info = 1;
+
+ /* Process each line in the array. */
+ for (i = 0; line = defs->lines->array[i]; i++)
+ {
+ defs->line_number = i;
+
+ if (*line == '$')
+ {
+ register int j;
+ char *directive;
+ HANDLER_ENTRY *handler;
+
+ /* Isolate the directive. */
+ for (j = 0; line[j] && !whitespace (line[j]); j++);
+
+ directive = xmalloc (j);
+ strncpy (directive, line + 1, j - 1);
+ directive[j -1] = '\0';
+
+ /* Get the function handler and call it. */
+ handler = find_directive (directive);
+
+ if (!handler)
+ {
+ line_error (defs, "Unknown directive `%s'", directive);
+ free (directive);
+ continue;
+ }
+ else
+ {
+ /* Advance to the first non-whitespace character. */
+ while (whitespace (line[j]))
+ j++;
+
+ /* Call the directive handler with the FILE, and ARGS. */
+ (*(handler->function)) (directive, defs, line + j);
+ }
+ free (directive);
+ }
+ else
+ {
+ if (building_builtin)
+ add_documentation (defs, line);
+ else if (defs->output)
+ {
+ if (output_cpp_line_info)
+ {
+ /* If we're handed an absolute pathname, don't prepend
+ the directory name. */
+ if (defs->filename[0] == '/')
+ fprintf (defs->output, "#line %d \"%s\"\n",
+ defs->line_number + 1, defs->filename);
+ else
+ fprintf (defs->output, "#line %d \"%s%s\"\n",
+ defs->line_number + 1,
+ error_directory ? error_directory : "./",
+ defs->filename);
+ output_cpp_line_info = 0;
+ }
+
+ fprintf (defs->output, "%s\n", line);
+ }
+ }
+ }
+
+ /* Close the production file. */
+ if (defs->output)
+ fclose (defs->output);
+
+ /* The file has been processed. Write the accumulated builtins to
+ the builtins.c file, and write the extern definitions to the
+ builtext.h file. */
+ write_builtins (defs, structfile, externfile);
+
+ free (buffer);
+ free_defs (defs);
+}
+
+#define free_safely(x) if (x) free (x)
+
+static void
+free_builtin (builtin)
+ BUILTIN_DESC *builtin;
+{
+ register int i;
+
+ free_safely (builtin->name);
+ free_safely (builtin->function);
+ free_safely (builtin->shortdoc);
+ free_safely (builtin->docname);
+
+ if (builtin->longdoc)
+ array_free (builtin->longdoc);
+
+ if (builtin->dependencies)
+ {
+ for (i = 0; builtin->dependencies->array[i]; i++)
+ free (builtin->dependencies->array[i]);
+ array_free (builtin->dependencies);
+ }
+}
+
+/* Free all of the memory allocated to a DEF_FILE. */
+void
+free_defs (defs)
+ DEF_FILE *defs;
+{
+ register int i;
+ register BUILTIN_DESC *builtin;
+
+ if (defs->production)
+ free (defs->production);
+
+ if (defs->lines)
+ array_free (defs->lines);
+
+ if (defs->builtins)
+ {
+ for (i = 0; builtin = (BUILTIN_DESC *)defs->builtins->array[i]; i++)
+ {
+ free_builtin (builtin);
+ free (builtin);
+ }
+ array_free (defs->builtins);
+ }
+ free (defs);
+}
+
+/* **************************************************************** */
+/* */
+/* The Handler Functions Themselves */
+/* */
+/* **************************************************************** */
+
+/* Strip surrounding whitespace from STRING, and
+ return a pointer to the start of it. */
+char *
+strip_whitespace (string)
+ char *string;
+{
+ while (whitespace (*string))
+ string++;
+
+ remove_trailing_whitespace (string);
+ return (string);
+}
+
+/* Remove only the trailing whitespace from STRING. */
+void
+remove_trailing_whitespace (string)
+ char *string;
+{
+ register int i;
+
+ i = strlen (string) - 1;
+
+ while (i > 0 && whitespace (string[i]))
+ i--;
+
+ string[++i] = '\0';
+}
+
+/* Ensure that there is a argument in STRING and return it.
+ FOR_WHOM is the name of the directive which needs the argument.
+ DEFS is the DEF_FILE in which the directive is found.
+ If there is no argument, produce an error. */
+char *
+get_arg (for_whom, defs, string)
+ char *for_whom, *string;
+ DEF_FILE *defs;
+{
+ char *new;
+
+ new = strip_whitespace (string);
+
+ if (!*new)
+ line_error (defs, "%s requires an argument", for_whom);
+
+ return (savestring (new));
+}
+
+/* Error if not building a builtin. */
+void
+must_be_building (directive, defs)
+ char *directive;
+ DEF_FILE *defs;
+{
+ if (!building_builtin)
+ line_error (defs, "%s must be inside of a $BUILTIN block", directive);
+}
+
+/* Return the current builtin. */
+BUILTIN_DESC *
+current_builtin (directive, defs)
+ char *directive;
+ DEF_FILE *defs;
+{
+ must_be_building (directive, defs);
+ if (defs->builtins)
+ return ((BUILTIN_DESC *)defs->builtins->array[defs->builtins->sindex - 1]);
+ else
+ return ((BUILTIN_DESC *)NULL);
+}
+
+/* Add LINE to the long documentation for the current builtin.
+ Ignore blank lines until the first non-blank line has been seen. */
+void
+add_documentation (defs, line)
+ DEF_FILE *defs;
+ char *line;
+{
+ register BUILTIN_DESC *builtin;
+
+ builtin = current_builtin ("(implied LONGDOC)", defs);
+
+ remove_trailing_whitespace (line);
+
+ if (!*line && !builtin->longdoc)
+ return;
+
+ if (!builtin->longdoc)
+ builtin->longdoc = array_create (sizeof (char *));
+
+ array_add (line, builtin->longdoc);
+}
+
+/* How to handle the $BUILTIN directive. */
+int
+builtin_handler (self, defs, arg)
+ char *self;
+ DEF_FILE *defs;
+ char *arg;
+{
+ BUILTIN_DESC *new;
+ char *name;
+
+ /* If we are already building a builtin, we cannot start a new one. */
+ if (building_builtin)
+ {
+ line_error (defs, "%s found before $END", self);
+ return (-1);
+ }
+
+ output_cpp_line_info++;
+
+ /* Get the name of this builtin, and stick it in the array. */
+ name = get_arg (self, defs, arg);
+
+ /* If this is the first builtin, create the array to hold them. */
+ if (!defs->builtins)
+ defs->builtins = array_create (sizeof (BUILTIN_DESC *));
+
+ new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
+ new->name = name;
+ new->function = (char *)NULL;
+ new->shortdoc = (char *)NULL;
+ new->docname = (char *)NULL;
+ new->longdoc = (ARRAY *)NULL;
+ new->dependencies = (ARRAY *)NULL;
+ new->flags = 0;
+
+ if (is_special_builtin (name))
+ new->flags |= BUILTIN_FLAG_SPECIAL;
+ if (is_assignment_builtin (name))
+ new->flags |= BUILTIN_FLAG_ASSIGNMENT;
+
+ array_add ((char *)new, defs->builtins);
+ building_builtin = 1;
+
+ return (0);
+}
+
+/* How to handle the $FUNCTION directive. */
+int
+function_handler (self, defs, arg)
+ char *self;
+ DEF_FILE *defs;
+ char *arg;
+{
+ register BUILTIN_DESC *builtin;
+
+ builtin = current_builtin (self, defs);
+
+ if (builtin == 0)
+ {
+ line_error (defs, "syntax error: no current builtin for $FUNCTION directive");
+ exit (1);
+ }
+ if (builtin->function)
+ line_error (defs, "%s already has a function (%s)",
+ builtin->name, builtin->function);
+ else
+ builtin->function = get_arg (self, defs, arg);
+
+ return (0);
+}
+
+/* How to handle the $DOCNAME directive. */
+int
+docname_handler (self, defs, arg)
+ char *self;
+ DEF_FILE *defs;
+ char *arg;
+{
+ register BUILTIN_DESC *builtin;
+
+ builtin = current_builtin (self, defs);
+
+ if (builtin->docname)
+ line_error (defs, "%s already had a docname (%s)",
+ builtin->name, builtin->docname);
+ else
+ builtin->docname = get_arg (self, defs, arg);
+
+ return (0);
+}
+
+/* How to handle the $SHORT_DOC directive. */
+int
+short_doc_handler (self, defs, arg)
+ char *self;
+ DEF_FILE *defs;
+ char *arg;
+{
+ register BUILTIN_DESC *builtin;
+
+ builtin = current_builtin (self, defs);
+
+ if (builtin->shortdoc)
+ line_error (defs, "%s already has short documentation (%s)",
+ builtin->name, builtin->shortdoc);
+ else
+ builtin->shortdoc = get_arg (self, defs, arg);
+
+ return (0);
+}
+
+/* How to handle the $COMMENT directive. */
+int
+comment_handler (self, defs, arg)
+ char *self;
+ DEF_FILE *defs;
+ char *arg;
+{
+ return (0);
+}
+
+/* How to handle the $DEPENDS_ON directive. */
+int
+depends_on_handler (self, defs, arg)
+ char *self;
+ DEF_FILE *defs;
+ char *arg;
+{
+ register BUILTIN_DESC *builtin;
+ char *dependent;
+
+ builtin = current_builtin (self, defs);
+ dependent = get_arg (self, defs, arg);
+
+ if (!builtin->dependencies)
+ builtin->dependencies = array_create (sizeof (char *));
+
+ array_add (dependent, builtin->dependencies);
+
+ return (0);
+}
+
+/* How to handle the $PRODUCES directive. */
+int
+produces_handler (self, defs, arg)
+ char *self;
+ DEF_FILE *defs;
+ char *arg;
+{
+ /* If just hacking documentation, don't change any of the production
+ files. */
+ if (only_documentation)
+ return (0);
+
+ output_cpp_line_info++;
+
+ if (defs->production)
+ line_error (defs, "%s already has a %s definition", defs->filename, self);
+ else
+ {
+ defs->production = get_arg (self, defs, arg);
+
+ if (inhibit_production)
+ return (0);
+
+ defs->output = fopen (defs->production, "w");
+
+ if (!defs->output)
+ file_error (defs->production);
+
+ fprintf (defs->output, "/* %s, created from %s. */\n",
+ defs->production, defs->filename);
+ }
+ return (0);
+}
+
+/* How to handle the $END directive. */
+int
+end_handler (self, defs, arg)
+ char *self;
+ DEF_FILE *defs;
+ char *arg;
+{
+ must_be_building (self, defs);
+ building_builtin = 0;
+ return (0);
+}
+
+/* **************************************************************** */
+/* */
+/* Error Handling Functions */
+/* */
+/* **************************************************************** */
+
+/* Produce an error for DEFS with FORMAT and ARGS. */
+void
+line_error (defs, format, arg1, arg2)
+ DEF_FILE *defs;
+ char *format, *arg1, *arg2;
+{
+ if (defs->filename[0] != '/')
+ fprintf (stderr, "%s", error_directory ? error_directory : "./");
+ fprintf (stderr, "%s:%d:", defs->filename, defs->line_number + 1);
+ fprintf (stderr, format, arg1, arg2);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+}
+
+/* Print error message for FILENAME. */
+void
+file_error (filename)
+ char *filename;
+{
+ perror (filename);
+ exit (2);
+}
+
+/* **************************************************************** */
+/* */
+/* xmalloc and xrealloc () */
+/* */
+/* **************************************************************** */
+
+static void memory_error_and_abort ();
+
+static char *
+xmalloc (bytes)
+ int bytes;
+{
+ char *temp = (char *)malloc (bytes);
+
+ if (!temp)
+ memory_error_and_abort ();
+ return (temp);
+}
+
+static char *
+xrealloc (pointer, bytes)
+ char *pointer;
+ int bytes;
+{
+ char *temp;
+
+ if (!pointer)
+ temp = (char *)malloc (bytes);
+ else
+ temp = (char *)realloc (pointer, bytes);
+
+ if (!temp)
+ memory_error_and_abort ();
+
+ return (temp);
+}
+
+static void
+memory_error_and_abort ()
+{
+ fprintf (stderr, "mkbuiltins: out of virtual memory\n");
+ abort ();
+}
+
+/* **************************************************************** */
+/* */
+/* Creating the Struct and Extern Files */
+/* */
+/* **************************************************************** */
+
+/* Return a pointer to a newly allocated builtin which is
+ an exact copy of BUILTIN. */
+BUILTIN_DESC *
+copy_builtin (builtin)
+ BUILTIN_DESC *builtin;
+{
+ BUILTIN_DESC *new;
+
+ new = (BUILTIN_DESC *)xmalloc (sizeof (BUILTIN_DESC));
+
+ new->name = savestring (builtin->name);
+ new->shortdoc = savestring (builtin->shortdoc);
+ new->longdoc = copy_string_array (builtin->longdoc);
+ new->dependencies = copy_string_array (builtin->dependencies);
+
+ new->function =
+ builtin->function ? savestring (builtin->function) : (char *)NULL;
+ new->docname =
+ builtin->docname ? savestring (builtin->docname) : (char *)NULL;
+
+ return (new);
+}
+
+/* How to save away a builtin. */
+void
+save_builtin (builtin)
+ BUILTIN_DESC *builtin;
+{
+ BUILTIN_DESC *newbuiltin;
+
+ newbuiltin = copy_builtin (builtin);
+
+ /* If this is the first builtin to be saved, create the array
+ to hold it. */
+ if (!saved_builtins)
+ saved_builtins = array_create (sizeof (BUILTIN_DESC *));
+
+ array_add ((char *)newbuiltin, saved_builtins);
+}
+
+/* Flags that mean something to write_documentation (). */
+#define STRING_ARRAY 0x01
+#define TEXINFO 0x02
+#define PLAINTEXT 0x04
+#define HELPFILE 0x08
+
+char *structfile_header[] = {
+ "/* builtins.c -- the built in shell commands. */",
+ "",
+ "/* This file is manufactured by ./mkbuiltins, and should not be",
+ " edited by hand. See the source to mkbuiltins for details. */",
+ "",
+ "/* Copyright (C) 1987-2002 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. */",
+ "",
+ "/* The list of shell builtins. Each element is name, function, flags,",
+ " long-doc, short-doc. The long-doc field contains a pointer to an array",
+ " of help lines. The function takes a WORD_LIST *; the first word in the",
+ " list is the first arg to the command. The list has already had word",
+ " expansion performed.",
+ "",
+ " Functions which need to look at only the simple commands (e.g.",
+ " the enable_builtin ()), should ignore entries where",
+ " (array[i].function == (sh_builtin_func_t *)NULL). Such entries are for",
+ " the list of shell reserved control structures, like `if' and `while'.",
+ " The end of the list is denoted with a NULL name field. */",
+ "",
+ "#include \"../builtins.h\"",
+ (char *)NULL
+ };
+
+char *structfile_footer[] = {
+ " { (char *)0x0, (sh_builtin_func_t *)0x0, 0, (char **)0x0, (char *)0x0 }",
+ "};",
+ "",
+ "struct builtin *shell_builtins = static_shell_builtins;",
+ "struct builtin *current_builtin;",
+ "",
+ "int num_shell_builtins =",
+ "\tsizeof (static_shell_builtins) / sizeof (struct builtin) - 1;",
+ (char *)NULL
+};
+
+/* Write out any neccessary opening information for
+ STRUCTFILE and EXTERNFILE. */
+void
+write_file_headers (structfile, externfile)
+ FILE *structfile, *externfile;
+{
+ register int i;
+
+ if (structfile)
+ {
+ for (i = 0; structfile_header[i]; i++)
+ fprintf (structfile, "%s\n", structfile_header[i]);
+
+ fprintf (structfile, "#include \"%s\"\n",
+ extern_filename ? extern_filename : "builtext.h");
+
+ fprintf (structfile, "#include \"bashintl.h\"\n");
+
+ fprintf (structfile, "\nstruct builtin static_shell_builtins[] = {\n");
+ }
+
+ if (externfile)
+ fprintf (externfile,
+ "/* %s - The list of builtins found in libbuiltins.a. */\n",
+ extern_filename ? extern_filename : "builtext.h");
+}
+
+/* Write out any necessary closing information for
+ STRUCTFILE and EXTERNFILE. */
+void
+write_file_footers (structfile, externfile)
+ FILE *structfile, *externfile;
+{
+ register int i;
+
+ /* Write out the footers. */
+ if (structfile)
+ {
+ for (i = 0; structfile_footer[i]; i++)
+ fprintf (structfile, "%s\n", structfile_footer[i]);
+ }
+}
+
+/* Write out the information accumulated in DEFS to
+ STRUCTFILE and EXTERNFILE. */
+void
+write_builtins (defs, structfile, externfile)
+ DEF_FILE *defs;
+ FILE *structfile, *externfile;
+{
+ register int i;
+
+ /* Write out the information. */
+ if (defs->builtins)
+ {
+ register BUILTIN_DESC *builtin;
+
+ for (i = 0; i < defs->builtins->sindex; i++)
+ {
+ builtin = (BUILTIN_DESC *)defs->builtins->array[i];
+
+ /* Write out any #ifdefs that may be there. */
+ if (!only_documentation)
+ {
+ if (builtin->dependencies)
+ {
+ write_ifdefs (externfile, builtin->dependencies->array);
+ write_ifdefs (structfile, builtin->dependencies->array);
+ }
+
+ /* Write the extern definition. */
+ if (externfile)
+ {
+ if (builtin->function)
+ fprintf (externfile, "extern int %s __P((WORD_LIST *));\n",
+ builtin->function);
+
+ fprintf (externfile, "extern char * const %s_doc[];\n",
+ document_name (builtin));
+ }
+
+ /* Write the structure definition. */
+ if (structfile)
+ {
+ fprintf (structfile, " { \"%s\", ", builtin->name);
+
+ if (builtin->function)
+ fprintf (structfile, "%s, ", builtin->function);
+ else
+ fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
+
+ fprintf (structfile, "%s%s%s, %s_doc,\n",
+ "BUILTIN_ENABLED | STATIC_BUILTIN",
+ (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
+ (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
+ document_name (builtin));
+
+ fprintf
+ (structfile, " \"%s\", (char *)NULL },\n",
+ builtin->shortdoc ? builtin->shortdoc : builtin->name);
+
+ }
+
+ if (structfile || separate_helpfiles)
+ /* Save away this builtin for later writing of the
+ long documentation strings. */
+ save_builtin (builtin);
+
+ /* Write out the matching #endif, if neccessary. */
+ if (builtin->dependencies)
+ {
+ if (externfile)
+ write_endifs (externfile, builtin->dependencies->array);
+
+ if (structfile)
+ write_endifs (structfile, builtin->dependencies->array);
+ }
+ }
+
+ if (documentation_file)
+ {
+ fprintf (documentation_file, "@item %s\n", builtin->name);
+ write_documentation
+ (documentation_file, builtin->longdoc->array, 0, TEXINFO);
+ }
+ }
+ }
+}
+
+/* Write out the long documentation strings in BUILTINS to STREAM. */
+void
+write_longdocs (stream, builtins)
+ FILE *stream;
+ ARRAY *builtins;
+{
+ register int i;
+ register BUILTIN_DESC *builtin;
+ char *dname;
+ char *sarray[2];
+
+ for (i = 0; i < builtins->sindex; i++)
+ {
+ builtin = (BUILTIN_DESC *)builtins->array[i];
+
+ if (builtin->dependencies)
+ write_ifdefs (stream, builtin->dependencies->array);
+
+ /* Write the long documentation strings. */
+ dname = document_name (builtin);
+ fprintf (stream, "char * const %s_doc[] =", dname);
+
+ if (separate_helpfiles)
+ {
+ int l = strlen (helpfile_directory) + strlen (dname) + 1;
+ sarray[0] = (char *)xmalloc (l + 1);
+ sprintf (sarray[0], "%s/%s", helpfile_directory, dname);
+ sarray[1] = (char *)NULL;
+ write_documentation (stream, sarray, 0, STRING_ARRAY|HELPFILE);
+ free (sarray[0]);
+ }
+ else
+ write_documentation (stream, builtin->longdoc->array, 0, STRING_ARRAY);
+
+ if (builtin->dependencies)
+ write_endifs (stream, builtin->dependencies->array);
+
+ }
+}
+
+/* Write an #ifdef string saying what needs to be defined (or not defined)
+ in order to allow compilation of the code that will follow.
+ STREAM is the stream to write the information to,
+ DEFINES is a null terminated array of define names.
+ If a define is preceded by an `!', then the sense of the test is
+ reversed. */
+void
+write_ifdefs (stream, defines)
+ FILE *stream;
+ char **defines;
+{
+ register int i;
+
+ if (!stream)
+ return;
+
+ fprintf (stream, "#if ");
+
+ for (i = 0; defines[i]; i++)
+ {
+ char *def = defines[i];
+
+ if (*def == '!')
+ fprintf (stream, "!defined (%s)", def + 1);
+ else
+ fprintf (stream, "defined (%s)", def);
+
+ if (defines[i + 1])
+ fprintf (stream, " && ");
+ }
+ fprintf (stream, "\n");
+}
+
+/* Write an #endif string saying what defines controlled the compilation
+ of the immediately preceding code.
+ STREAM is the stream to write the information to.
+ DEFINES is a null terminated array of define names. */
+void
+write_endifs (stream, defines)
+ FILE *stream;
+ char **defines;
+{
+ register int i;
+
+ if (!stream)
+ return;
+
+ fprintf (stream, "#endif /* ");
+
+ for (i = 0; defines[i]; i++)
+ {
+ fprintf (stream, "%s", defines[i]);
+
+ if (defines[i + 1])
+ fprintf (stream, " && ");
+ }
+
+ fprintf (stream, " */\n");
+}
+
+/* Write DOCUMENTATION to STREAM, perhaps surrounding it with double-quotes
+ and quoting special characters in the string. Handle special things for
+ internationalization (gettext) and the single-string vs. multiple-strings
+ issues. */
+void
+write_documentation (stream, documentation, indentation, flags)
+ FILE *stream;
+ char **documentation;
+ int indentation, flags;
+{
+ register int i, j;
+ register char *line;
+ int string_array, texinfo, base_indent, last_cpp, filename_p;
+
+ if (!stream)
+ return;
+
+ string_array = flags & STRING_ARRAY;
+ filename_p = flags & HELPFILE;
+
+ if (string_array)
+ {
+ fprintf (stream, " {\n#if defined (HELP_BUILTIN)\n"); /* } */
+ if (single_longdoc_strings)
+ {
+ if (filename_p == 0)
+ fprintf (stream, "N_(\" "); /* the empty string translates specially. */
+ else
+ fprintf (stream, "\"");
+ }
+ }
+
+ base_indent = (string_array && single_longdoc_strings && filename_p == 0) ? BASE_INDENT : 0;
+
+ for (i = last_cpp = 0, texinfo = (flags & TEXINFO); line = documentation[i]; i++)
+ {
+ /* Allow #ifdef's to be written out verbatim, but don't put them into
+ separate help files. */
+ if (*line == '#')
+ {
+ if (string_array && filename_p == 0 && single_longdoc_strings == 0)
+ fprintf (stream, "%s\n", line);
+ last_cpp = 1;
+ continue;
+ }
+ else
+ last_cpp = 0;
+
+ /* prefix with N_( for gettext */
+ if (string_array && single_longdoc_strings == 0)
+ {
+ if (filename_p == 0)
+ fprintf (stream, " N_(\" "); /* the empty string translates specially. */
+ else
+ fprintf (stream, " \"");
+ }
+
+ if (indentation)
+ for (j = 0; j < indentation; j++)
+ fprintf (stream, " ");
+
+ /* Don't indent the first line, because of how the help builtin works. */
+ if (i == 0)
+ indentation += base_indent;
+
+ if (string_array)
+ {
+ for (j = 0; line[j]; j++)
+ {
+ switch (line[j])
+ {
+ case '\\':
+ case '"':
+ fprintf (stream, "\\%c", line[j]);
+ break;
+
+ default:
+ fprintf (stream, "%c", line[j]);
+ }
+ }
+
+ /* closing right paren for gettext */
+ if (single_longdoc_strings == 0)
+ {
+ if (filename_p == 0)
+ fprintf (stream, "\"),\n");
+ else
+ fprintf (stream, "\",\n");
+ }
+ else if (documentation[i+1])
+ /* don't add extra newline after last line */
+ fprintf (stream, "\\n\\\n");
+ }
+ else if (texinfo)
+ {
+ for (j = 0; line[j]; j++)
+ {
+ switch (line[j])
+ {
+ case '@':
+ case '{':
+ case '}':
+ fprintf (stream, "@%c", line[j]);
+ break;
+
+ default:
+ fprintf (stream, "%c", line[j]);
+ }
+ }
+ fprintf (stream, "\n");
+ }
+ else
+ fprintf (stream, "%s\n", line);
+ }
+
+ /* closing right paren for gettext */
+ if (string_array && single_longdoc_strings)
+ {
+ if (filename_p == 0)
+ fprintf (stream, "\"),\n");
+ else
+ fprintf (stream, "\",\n");
+ }
+
+ if (string_array)
+ fprintf (stream, "#endif /* HELP_BUILTIN */\n (char *)NULL\n};\n");
+}
+
+int
+write_helpfiles (builtins)
+ ARRAY *builtins;
+{
+ char *helpfile, *bname;
+ FILE *helpfp;
+ int i, hdlen;
+ BUILTIN_DESC *builtin;
+
+ i = mkdir ("helpfiles", 0777);
+ if (i < 0 && errno != EEXIST)
+ {
+ fprintf (stderr, "write_helpfiles: helpfiles: cannot create directory\n");
+ return -1;
+ }
+
+ hdlen = strlen ("helpfiles/");
+ for (i = 0; i < builtins->sindex; i++)
+ {
+ builtin = (BUILTIN_DESC *)builtins->array[i];
+
+ bname = document_name (builtin);
+ helpfile = (char *)xmalloc (hdlen + strlen (bname) + 1);
+ sprintf (helpfile, "helpfiles/%s", bname);
+
+ helpfp = fopen (helpfile, "w");
+ if (helpfp == 0)
+ {
+ fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
+ free (helpfile);
+ continue;
+ }
+
+ write_documentation (helpfp, builtin->longdoc->array, 4, PLAINTEXT);
+
+ fflush (helpfp);
+ fclose (helpfp);
+ free (helpfile);
+ }
+ return 0;
+}
+
+static int
+_find_in_table (name, name_table)
+ char *name, *name_table[];
+{
+ register int i;
+
+ for (i = 0; name_table[i]; i++)
+ if (strcmp (name, name_table[i]) == 0)
+ return 1;
+ return 0;
+}
+
+static int
+is_special_builtin (name)
+ char *name;
+{
+ return (_find_in_table (name, special_builtins));
+}
+
+static int
+is_assignment_builtin (name)
+ char *name;
+{
+ return (_find_in_table (name, assignment_builtins));
+}
+
+#if !defined (HAVE_RENAME)
+static int
+rename (from, to)
+ char *from, *to;
+{
+ unlink (to);
+ if (link (from, to) < 0)
+ return (-1);
+ unlink (from);
+ return (0);
+}
+#endif /* !HAVE_RENAME */
diff --git a/builtins/read.def b/builtins/read.def
index e40cd6dd..646ab61e 100644
--- a/builtins/read.def
+++ b/builtins/read.def
@@ -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);
diff --git a/builtins/read.def~ b/builtins/read.def~
index 914ebd7d..29ddf8ae 100644
--- a/builtins/read.def~
+++ b/builtins/read.def~
@@ -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);
diff --git a/builtins/ulimit.def b/builtins/ulimit.def
index c8e87f13..17898699 100644
--- a/builtins/ulimit.def
+++ b/builtins/ulimit.def
@@ -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
@@ -202,6 +204,9 @@ static RESOURCE_LIMITS limits[] = {
#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
{ 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL },
@@ -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
diff --git a/builtins/ulimit.def~ b/builtins/ulimit.def~
index 8cfcd4fd..17898699 100644
--- a/builtins/ulimit.def~
+++ b/builtins/ulimit.def~
@@ -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
@@ -202,6 +204,9 @@ static RESOURCE_LIMITS limits[] = {
#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
{ 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL },
@@ -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
diff --git a/command.h b/command.h
index a5bac0b6..75e4990d 100644
--- a/command.h
+++ b/command.h
@@ -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 &' */
diff --git a/command.h~ b/command.h~
new file mode 100644
index 00000000..a5bac0b6
--- /dev/null
+++ b/command.h~
@@ -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_ */
diff --git a/configure b/configure
index 9c920c77..76f0f467 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/configure.in b/configure.in
index da395f97..71331664 100644
--- a/configure.in
+++ b/configure.in
@@ -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
diff --git a/configure.in~ b/configure.in~
new file mode 100644
index 00000000..411b801e
--- /dev/null
+++ b/configure.in~
@@ -0,0 +1,1112 @@
+dnl
+dnl Configure script for bash-3.2
+dnl
+dnl report bugs to chet@po.cwru.edu
+dnl
+dnl Process this file with autoconf to produce a configure script.
+
+# Copyright (C) 1987-2005 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-1307, USA.
+
+AC_REVISION([for Bash 3.2, version 3.186])dnl
+
+define(bashvers, 3.2)
+define(relstatus, devel)
+
+AC_INIT(bash, bashvers-relstatus, bug-bash@gnu.org)
+
+dnl make sure we are using a recent autoconf version
+AC_PREREQ(2.50)
+
+AC_CONFIG_SRCDIR(shell.h)
+dnl where to find install.sh, config.sub, and config.guess
+AC_CONFIG_AUX_DIR(./support)
+AC_CONFIG_HEADERS(config.h)
+
+dnl checks for version info
+BASHVERS=bashvers
+RELSTATUS=relstatus
+
+dnl defaults for debug settings
+case "$RELSTATUS" in
+alp*|bet*|dev*|rc*) DEBUG='-DDEBUG' MALLOC_DEBUG='-DMALLOC_DEBUG' ;;
+*) DEBUG= MALLOC_DEBUG= ;;
+esac
+
+dnl canonicalize the host and os so we can do some tricky things before
+dnl parsing options
+AC_CANONICAL_HOST
+
+dnl configure defaults
+opt_bash_malloc=yes
+opt_purify=no
+opt_purecov=no
+opt_afs=no
+opt_curses=no
+opt_with_installed_readline=no
+
+#htmldir=
+
+dnl some systems should be configured without the bash malloc by default
+dnl and some need a special compiler or loader
+dnl look in the NOTES file for more
+case "${host_cpu}-${host_os}" in
+alpha*-*) opt_bash_malloc=no ;; # alpha running osf/1 or linux
+*[[Cc]]ray*-*) opt_bash_malloc=no ;; # Crays
+*-osf1*) opt_bash_malloc=no ;; # other osf/1 machines
+sparc-svr4*) opt_bash_malloc=no ;; # sparc SVR4, SVR4.2
+sparc-netbsd*) opt_bash_malloc=no ;; # needs 8-byte alignment
+mips-irix6*) opt_bash_malloc=no ;; # needs 8-byte alignment
+m68k-sysv) opt_bash_malloc=no ;; # fixes file descriptor leak in closedir
+sparc-linux*) opt_bash_malloc=no ;; # sparc running linux; requires ELF
+#*-freebsd*-gnu) opt_bash_malloc=no ;; # there's some undetermined problem here
+#*-freebsd*) opt_bash_malloc=no ;; # they claim it's better; I disagree
+*-openbsd*) opt_bash_malloc=no ;; # they claim it needs eight-bit alignment
+*-aix*) opt_bash_malloc=no ;; # AIX machines
+*-nextstep*) opt_bash_malloc=no ;; # NeXT machines running NeXTstep
+*-macos*) opt_bash_malloc=no ;; # Apple MacOS X
+*-rhapsody*) opt_bash_malloc=no ;; # Apple Rhapsody (MacOS X)
+*-darwin*) opt_bash_malloc=no ;; # Apple Darwin (MacOS X)
+*-dgux*) opt_bash_malloc=no ;; # DG/UX machines
+*-qnx*) opt_bash_malloc=no ;; # QNX 4.2, QNX 6.x
+*-machten4) opt_bash_malloc=no ;; # MachTen 4.x
+*-bsdi2.1|*-bsdi3.?) opt_bash_malloc=no ; : ${CC:=shlicc2} ;; # for loadable builtins
+*-beos*) opt_bash_malloc=no ;; # they say it's suitable
+*-cygwin*) opt_bash_malloc=no ;; # Cygnus's CYGWIN environment
+*-opennt*|*-interix*) opt_bash_malloc=no ;; # Interix, now owned by Microsoft
+esac
+
+# memory scrambling on free()
+case "${host_os}" in
+sco3.2v5*|sco3.2v4*) opt_memscramble=no ;;
+*) opt_memscramble=yes ;;
+esac
+
+dnl
+dnl macros for the bash debugger
+dnl
+AM_PATH_LISPDIR
+AC_ARG_VAR(DEBUGGER_START_FILE, [location of bash debugger initialization file])
+
+dnl arguments to configure
+dnl packages
+AC_ARG_WITH(afs, AC_HELP_STRING([--with-afs], [if you are running AFS]), opt_afs=$withval)
+AC_ARG_WITH(bash-malloc, AC_HELP_STRING([--with-bash-malloc], [use the Bash version of malloc]), opt_bash_malloc=$withval)
+AC_ARG_WITH(curses, AC_HELP_STRING([--with-curses], [use the curses library instead of the termcap library]), opt_curses=$withval)
+AC_ARG_WITH(gnu-malloc, AC_HELP_STRING([--with-gnu-malloc], [synonym for --with-bash-malloc]), opt_bash_malloc=$withval)
+AC_ARG_WITH(installed-readline, AC_HELP_STRING([--with-installed-readline], [use a version of the readline library that is already installed]), opt_with_installed_readline=$withval)
+AC_ARG_WITH(purecov, AC_HELP_STRING([--with-purecov], [configure to postprocess with pure coverage]), opt_purecov=$withval)
+AC_ARG_WITH(purify, AC_HELP_STRING([--with-purify], [configure to postprocess with purify]), opt_purify=$withval)
+
+if test "$opt_bash_malloc" = yes; then
+ MALLOC_TARGET=malloc
+ MALLOC_SRC=malloc.c
+
+ MALLOC_LIB='-lmalloc'
+ MALLOC_LIBRARY='$(ALLOC_LIBDIR)/libmalloc.a'
+ MALLOC_LDFLAGS='-L$(ALLOC_LIBDIR)'
+ MALLOC_DEP='$(MALLOC_LIBRARY)'
+
+ AC_DEFINE(USING_BASH_MALLOC)
+else
+ MALLOC_LIB=
+ MALLOC_LIBRARY=
+ MALLOC_LDFLAGS=
+ MALLOC_DEP=
+fi
+
+if test "$opt_purify" = yes; then
+ PURIFY="purify "
+ AC_DEFINE(DISABLE_MALLOC_WRAPPERS)
+else
+ PURIFY=
+fi
+
+if test "$opt_purecov" = yes; then
+ PURIFY="${PURIFY}purecov"
+fi
+
+if test "$opt_afs" = yes; then
+ AC_DEFINE(AFS)
+fi
+
+if test "$opt_curses" = yes; then
+ prefer_curses=yes
+fi
+
+if test -z "${DEBUGGER_START_FILE}"; then
+ DEBUGGER_START_FILE=${ac_default_prefix}/lib/bashdb/bashdb-main.inc
+fi
+
+dnl optional shell features in config.h.in
+opt_minimal_config=no
+
+opt_job_control=yes
+opt_alias=yes
+opt_readline=yes
+opt_history=yes
+opt_bang_history=yes
+opt_dirstack=yes
+opt_restricted=yes
+opt_process_subst=yes
+opt_prompt_decoding=yes
+opt_select=yes
+opt_help=yes
+opt_array_variables=yes
+opt_dparen_arith=yes
+opt_extended_glob=yes
+opt_brace_expansion=yes
+opt_disabled_builtins=no
+opt_command_timing=yes
+opt_xpg_echo=no
+opt_strict_posix=no
+opt_cond_command=yes
+opt_cond_regexp=yes
+opt_arith_for_command=yes
+opt_net_redirs=yes
+opt_progcomp=yes
+opt_separate_help=no
+opt_multibyte=yes
+opt_debugger=yes
+opt_single_longdoc_strings=yes
+
+dnl options that affect how bash is compiled and linked
+opt_static_link=no
+opt_profiling=no
+
+dnl argument parsing for optional features
+AC_ARG_ENABLE(minimal-config, AC_HELP_STRING([--enable-minimal-config], [a minimal sh-like configuration]), opt_minimal_config=$enableval)
+
+dnl a minimal configuration turns everything off, but features can be
+dnl added individually
+if test $opt_minimal_config = yes; then
+ opt_job_control=no opt_alias=no opt_readline=no
+ opt_history=no opt_bang_history=no opt_dirstack=no
+ opt_restricted=no opt_process_subst=no opt_prompt_decoding=no
+ opt_select=no opt_help=no opt_array_variables=no opt_dparen_arith=no
+ opt_brace_expansion=no opt_disabled_builtins=no opt_command_timing=no
+ opt_extended_glob=no opt_cond_command=no opt_arith_for_command=no
+ opt_net_redirs=no opt_progcomp=no opt_separate_help=no
+ opt_multibyte=yes opt_cond_regexp=no
+fi
+
+AC_ARG_ENABLE(alias, AC_HELP_STRING([--enable-alias], [enable shell aliases]), opt_alias=$enableval)
+AC_ARG_ENABLE(arith-for-command, AC_HELP_STRING([--enable-arith-for-command], [enable arithmetic for command]), opt_arith_for_command=$enableval)
+AC_ARG_ENABLE(array-variables, AC_HELP_STRING([--enable-array-variables], [include shell array variables]), opt_array_variables=$enableval)
+AC_ARG_ENABLE(bang-history, AC_HELP_STRING([--enable-bang-history], [turn on csh-style history substitution]), opt_bang_history=$enableval)
+AC_ARG_ENABLE(brace-expansion, AC_HELP_STRING([--enable-brace-expansion], [include brace expansion]), opt_brace_expansion=$enableval)
+AC_ARG_ENABLE(command-timing, AC_HELP_STRING([--enable-command-timing], [enable the time reserved word and command timing]), opt_command_timing=$enableval)
+AC_ARG_ENABLE(cond-command, AC_HELP_STRING([--enable-cond-command], [enable the conditional command]), opt_cond_command=$enableval)
+AC_ARG_ENABLE(cond-regexp, AC_HELP_STRING([--enable-cond-regexp], [enable extgended regular expression matching in conditional commands]), opt_cond_regexp=$enableval)
+AC_ARG_ENABLE(debugger, AC_HELP_STRING([--enable-debugger], [enable support for bash debugger]), opt_debugger=$enableval)
+AC_ARG_ENABLE(directory-stack, AC_HELP_STRING([--enable-directory-stack], [enable builtins pushd/popd/dirs]), opt_dirstack=$enableval)
+AC_ARG_ENABLE(disabled-builtins, AC_HELP_STRING([--enable-disabled-builtins], [allow disabled builtins to still be invoked]), opt_disabled_builtins=$enableval)
+AC_ARG_ENABLE(dparen-arithmetic, AC_HELP_STRING([--enable-dparen-arithmetic], [include ((...)) command]), opt_dparen_arith=$enableval)
+AC_ARG_ENABLE(extended-glob, AC_HELP_STRING([--enable-extended-glob], [include ksh-style extended pattern matching]), opt_extended_glob=$enableval)
+AC_ARG_ENABLE(help-builtin, AC_HELP_STRING([--enable-help-builtin], [include the help builtin]), opt_help=$enableval)
+AC_ARG_ENABLE(history, AC_HELP_STRING([--enable-history], [turn on command history]), opt_history=$enableval)
+AC_ARG_ENABLE(job-control, AC_HELP_STRING([--enable-job-control], [enable job control features]), opt_job_control=$enableval)
+AC_ARG_ENABLE(multibyte, AC_HELP_STRING([--enable-multibyte], [enable multibyte characters if OS supports them]), opt_multibyte=$enableval)
+AC_ARG_ENABLE(net-redirections, AC_HELP_STRING([--enable-net-redirections], [enable /dev/tcp/host/port redirection]), opt_net_redirs=$enableval)
+AC_ARG_ENABLE(process-substitution, AC_HELP_STRING([--enable-process-substitution], [enable process substitution]), opt_process_subst=$enableval)
+AC_ARG_ENABLE(progcomp, AC_HELP_STRING([--enable-progcomp], [enable programmable completion and the complete builtin]), opt_progcomp=$enableval)
+AC_ARG_ENABLE(prompt-string-decoding, AC_HELP_STRING([--enable-prompt-string-decoding], [turn on escape character decoding in prompts]), opt_prompt_decoding=$enableval)
+AC_ARG_ENABLE(readline, AC_HELP_STRING([--enable-readline], [turn on command line editing]), opt_readline=$enableval)
+AC_ARG_ENABLE(restricted, AC_HELP_STRING([--enable-restricted], [enable a restricted shell]), opt_restricted=$enableval)
+AC_ARG_ENABLE(select, AC_HELP_STRING([--enable-select], [include select command]), opt_select=$enableval)
+AC_ARG_ENABLE(separate-helpfiles, AC_HELP_STRING([--enable-separate-helpfiles], [use external files for help builtin documentation]), opt_separate_help=$enableval)
+AC_ARG_ENABLE(single-help-strings, AC_HELP_STRING([--enable-single-help-strings], [store help documentation as a single string to ease translation]), opt_single_longdoc_strings=$enableval)
+AC_ARG_ENABLE(strict-posix-default, AC_HELP_STRING([--enable-strict-posix-default], [configure bash to be posix-conformant by default]), opt_strict_posix=$enableval)
+AC_ARG_ENABLE(usg-echo-default, AC_HELP_STRING([--enable-usg-echo-default], [a synonym for --enable-xpg-echo-default]), opt_xpg_echo=$enableval)
+AC_ARG_ENABLE(xpg-echo-default, AC_HELP_STRING([--enable-xpg-echo-default], [make the echo builtin expand escape sequences by default]), opt_xpg_echo=$enableval)
+
+dnl options that alter how bash is compiled and linked
+AC_ARG_ENABLE(mem-scramble, AC_HELP_STRING([--enable-mem-scramble], [scramble memory on calls to malloc and free]), opt_memscramble=$enableval)
+AC_ARG_ENABLE(profiling, AC_HELP_STRING([--enable-profiling], [allow profiling with gprof]), opt_profiling=$enableval)
+AC_ARG_ENABLE(static-link, AC_HELP_STRING([--enable-static-link], [link bash statically, for use as a root shell]), opt_static_link=$enableval)
+
+dnl opt_job_control is handled later, after BASH_JOB_CONTROL_MISSING runs
+
+dnl opt_readline and opt_history are handled later, because AC_PROG_CC needs
+dnl to be run before we can check the version of an already-installed readline
+dnl library
+
+if test $opt_alias = yes; then
+AC_DEFINE(ALIAS)
+fi
+if test $opt_dirstack = yes; then
+AC_DEFINE(PUSHD_AND_POPD)
+fi
+if test $opt_restricted = yes; then
+AC_DEFINE(RESTRICTED_SHELL)
+fi
+if test $opt_process_subst = yes; then
+AC_DEFINE(PROCESS_SUBSTITUTION)
+fi
+if test $opt_prompt_decoding = yes; then
+AC_DEFINE(PROMPT_STRING_DECODE)
+fi
+if test $opt_select = yes; then
+AC_DEFINE(SELECT_COMMAND)
+fi
+if test $opt_help = yes; then
+AC_DEFINE(HELP_BUILTIN)
+fi
+if test $opt_array_variables = yes; then
+AC_DEFINE(ARRAY_VARS)
+fi
+if test $opt_dparen_arith = yes; then
+AC_DEFINE(DPAREN_ARITHMETIC)
+fi
+if test $opt_brace_expansion = yes; then
+AC_DEFINE(BRACE_EXPANSION)
+fi
+if test $opt_disabled_builtins = yes; then
+AC_DEFINE(DISABLED_BUILTINS)
+fi
+if test $opt_command_timing = yes; then
+AC_DEFINE(COMMAND_TIMING)
+fi
+if test $opt_xpg_echo = yes ; then
+AC_DEFINE(DEFAULT_ECHO_TO_XPG)
+fi
+if test $opt_strict_posix = yes; then
+AC_DEFINE(STRICT_POSIX)
+fi
+if test $opt_extended_glob = yes ; then
+AC_DEFINE(EXTENDED_GLOB)
+fi
+if test $opt_cond_command = yes ; then
+AC_DEFINE(COND_COMMAND)
+fi
+if test $opt_cond_regexp = yes ; then
+AC_DEFINE(COND_REGEXP)
+fi
+if test $opt_arith_for_command = yes; then
+AC_DEFINE(ARITH_FOR_COMMAND)
+fi
+if test $opt_net_redirs = yes; then
+AC_DEFINE(NETWORK_REDIRECTIONS)
+fi
+if test $opt_progcomp = yes; then
+AC_DEFINE(PROGRAMMABLE_COMPLETION)
+fi
+if test $opt_multibyte = no; then
+AC_DEFINE(NO_MULTIBYTE_SUPPORT)
+fi
+if test $opt_debugger = yes; then
+AC_DEFINE(DEBUGGER)
+fi
+
+if test $opt_memscramble = yes; then
+AC_DEFINE(MEMSCRAMBLE)
+fi
+
+if test "$opt_minimal_config" = yes; then
+ TESTSCRIPT=run-minimal
+else
+ TESTSCRIPT=run-all
+fi
+
+HELPDIR= HELPDIRDEFINE= HELPINSTALL=
+if test "$opt_separate_help" != no; then
+ if test "$opt_separate_help" = "yes" ; then
+ HELPDIR='${datadir}/bash'
+ else
+ HELPDIR=$opt_separate_help
+ fi
+ HELPDIRDEFINE='-H ${HELPDIR}'
+ HELPINSTALL='install-help'
+fi
+HELPSTRINGS=
+if test "$opt_single_longdoc_strings" != "yes"; then
+ HELPSTRINGS='-S'
+fi
+
+dnl now substitute in the values generated by arguments
+AC_SUBST(TESTSCRIPT)
+AC_SUBST(PURIFY)
+AC_SUBST(MALLOC_TARGET)
+AC_SUBST(MALLOC_SRC)
+
+AC_SUBST(MALLOC_LIB)
+AC_SUBST(MALLOC_LIBRARY)
+AC_SUBST(MALLOC_LDFLAGS)
+AC_SUBST(MALLOC_DEP)
+
+AC_SUBST(htmldir)
+
+AC_SUBST(HELPDIR)
+AC_SUBST(HELPDIRDEFINE)
+AC_SUBST(HELPINSTALL)
+AC_SUBST(HELPSTRINGS)
+
+echo ""
+echo "Beginning configuration for bash-$BASHVERS-$RELSTATUS for ${host_cpu}-${host_vendor}-${host_os}"
+echo ""
+
+dnl compilation checks
+dnl AC_PROG_CC sets $cross_compiling to `yes' if cross-compiling for a
+dnl different environment
+AC_PROG_CC
+
+dnl test for Unix variants
+AC_ISC_POSIX
+AC_MINIX
+
+AC_SYS_LARGEFILE
+
+dnl BEGIN changes for cross-building (currently cygwin, minGW, and
+dnl (obsolete) BeOS)
+
+cross_compiling=yes
+
+SIGNAMES_O=
+SIGNAMES_H=lsignames.h
+
+dnl load up the cross-building cache file -- add more cases and cache
+dnl files as necessary
+
+dnl Note that host and target machine are the same, and different than the
+dnl build machine.
+dnl Set SIGNAMES_H based on whether or not we're cross-compiling.
+
+if test "x$cross_compiling" = "xyes"; then
+ case "${host}" in
+ *-cygwin*)
+ cross_cache=${srcdir}/cross-build/cygwin32.cache
+ ;;
+ *-mingw*)
+ cross_cache=${srcdir}/cross-build/cygwin32.cache
+ ;;
+ i[[3456]]86-*-beos*)
+ cross_cache=${srcdir}/cross-build/x86-beos.cache
+ ;;
+ *) echo "configure: cross-compiling for $host is not supported" >&2
+ ;;
+ esac
+ if test -n "${cross_cache}" && test -r "${cross_cache}"; then
+ echo "loading cross-build cache file ${cross_cache}"
+ . ${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)
+
+cross_compiling=no
+
+if test -z "$CC_FOR_BUILD"; then
+ if test "x$cross_compiling" = "xno"; then
+ CC_FOR_BUILD='$(CC)'
+ else
+ CC_FOR_BUILD=gcc
+ fi
+fi
+AC_SUBST(CC_FOR_BUILD)
+
+dnl END changes for cross-building
+
+dnl We want these before the checks, so the checks can modify their values.
+test -z "$CFLAGS" && CFLAGS=-g auto_cflags=1
+
+dnl If we're using gcc and the user hasn't specified CFLAGS, add -O2 to CFLAGS.
+test -n "$GCC" && test -n "$auto_cflags" && CFLAGS="$CFLAGS -O2"
+
+dnl handle options that alter how bash is compiled and linked
+dnl these must come after the test for cc/gcc
+if test "$opt_profiling" = "yes"; then
+ PROFILE_FLAGS=-pg
+ case "$host_os" in
+ solaris2*) ;;
+ *) opt_static_link=yes ;;
+ esac
+ DEBUG= MALLOC_DEBUG=
+fi
+
+if test "$opt_static_link" = yes; then
+ # if we're using gcc, add `-static' to LDFLAGS, except on Solaris >= 2
+ if test -n "$GCC" || test "$ac_cv_prog_gcc" = "yes"; then
+ STATIC_LD="-static"
+ case "$host_os" in
+ solaris2*) ;;
+ *) LDFLAGS="$LDFLAGS -static" ;; # XXX experimental
+ esac
+ fi
+fi
+
+if test "X$cross_compiling" = "Xno"; then
+ CPPFLAGS_FOR_BUILD=${CPPFLAGS_FOR_BUILD-"$CPPFLAGS"}
+ LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-'$(LDFLAGS)'}
+else
+ CPPFLAGS_FOR_BUILD=${CPPFLAGS_FOR_BUILD-""}
+ LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-""}
+fi
+
+test -z "$CFLAGS_FOR_BUILD" && CFLAGS_FOR_BUILD="-g"
+
+AC_SUBST(CFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
+AC_SUBST(STATIC_LD)
+
+AC_SUBST(CFLAGS_FOR_BUILD)
+AC_SUBST(CPPFLAGS_FOR_BUILD)
+AC_SUBST(LDFLAGS_FOR_BUILD)
+
+AC_PROG_GCC_TRADITIONAL
+
+dnl BEGIN READLINE and HISTORY LIBRARY SECTION
+dnl prepare to allow bash to be linked against an already-installed readline
+
+dnl first test that the readline version is new enough to link bash against
+if test "$opt_readline" = yes && test "$opt_with_installed_readline" != "no"
+then
+ # If the user specified --with-installed-readline=PREFIX and PREFIX
+ # is not `yes', set ac_cv_rl_prefix to PREFIX
+ test $opt_with_installed_readline != "yes" && ac_cv_rl_prefix=$opt_with_installed_readline
+
+ RL_LIB_READLINE_VERSION
+
+ case "$ac_cv_rl_version" in
+ 5*|6*|7*|8*|9*) ;;
+ *) opt_with_installed_readline=no
+ AC_MSG_WARN(installed readline library is too old to be linked with bash)
+ AC_MSG_WARN(using private bash version)
+ ;;
+ esac
+fi
+
+TILDE_LIB=-ltilde
+if test $opt_readline = yes; then
+ AC_DEFINE(READLINE)
+ if test "$opt_with_installed_readline" != "no" ; then
+ case "$opt_with_installed_readline" in
+ yes) RL_INCLUDE= ;;
+ *) case "$RL_INCLUDEDIR" in
+ /usr/include) ;;
+ *) RL_INCLUDE='-I${RL_INCLUDEDIR}' ;;
+ esac
+ ;;
+ esac
+ READLINE_DEP=
+ READLINE_LIB=-lreadline
+ # section for OS versions that don't allow unresolved symbols
+ # to be compiled into dynamic libraries.
+ case "$host_os" in
+ cygwin*) TILDE_LIB= ;;
+ esac
+ else
+ RL_LIBDIR='$(dot)/$(LIBSUBDIR)/readline'
+ READLINE_DEP='$(READLINE_LIBRARY)'
+ # section for OS versions that ship an older/broken version of
+ # readline as a standard dynamic library and don't allow a
+ # static version specified as -llibname to override the
+ # dynamic version
+ case "${host_os}" in
+ darwin8*) READLINE_LIB='${READLINE_LIBRARY}' ;;
+ *) READLINE_LIB=-lreadline ;;
+ esac
+ fi
+else
+ RL_LIBDIR='$(dot)/$(LIBSUBDIR)/readline'
+ READLINE_LIB= READLINE_DEP=
+fi
+if test $opt_history = yes || test $opt_bang_history = yes; then
+ if test $opt_history = yes; then
+ AC_DEFINE(HISTORY)
+ fi
+ if test $opt_bang_history = yes; then
+ AC_DEFINE(BANG_HISTORY)
+ fi
+ if test "$opt_with_installed_readline" != "no"; then
+ HIST_LIBDIR=$RL_LIBDIR
+ HISTORY_DEP=
+ HISTORY_LIB=-lhistory
+ case "$opt_with_installed_readline" in
+ yes) RL_INCLUDE= ;;
+ *) case "$RL_INCLUDEDIR" in
+ /usr/include) ;;
+ *) RL_INCLUDE='-I${RL_INCLUDEDIR}' ;;
+ esac
+ ;;
+ esac
+ else
+ HIST_LIBDIR='$(dot)/$(LIBSUBDIR)/readline'
+ HISTORY_DEP='$(HISTORY_LIBRARY)'
+ # section for OS versions that ship an older version of
+ # readline as a standard dynamic library and don't allow a
+ # static version specified as -llibname to override the
+ # dynamic version
+ case "${host_os}" in
+ darwin8*) HISTORY_LIB='${HISTORY_LIBRARY}' ;;
+ *) HISTORY_LIB=-lhistory ;;
+ esac
+ fi
+else
+ HIST_LIBDIR='$(dot)/$(LIBSUBDIR)/readline'
+ HISTORY_LIB= HISTORY_DEP=
+fi
+AC_SUBST(READLINE_LIB)
+AC_SUBST(READLINE_DEP)
+AC_SUBST(RL_LIBDIR)
+AC_SUBST(RL_INCLUDEDIR)
+AC_SUBST(RL_INCLUDE)
+AC_SUBST(HISTORY_LIB)
+AC_SUBST(HISTORY_DEP)
+AC_SUBST(HIST_LIBDIR)
+AC_SUBST(TILDE_LIB)
+
+dnl END READLINE and HISTORY LIBRARY SECTION
+
+dnl programs needed by the build and install process
+AC_PROG_INSTALL
+AC_CHECK_PROG(AR, ar, , ar)
+dnl Set default for ARFLAGS, since autoconf does not have a macro for it.
+dnl This allows people to set it when running configure or make
+test -n "$ARFLAGS" || ARFLAGS="cr"
+AC_PROG_RANLIB
+AC_PROG_YACC
+AC_PROG_MAKE_SET
+
+case "$host_os" in
+opennt*|interix*) MAKE_SHELL="$INTERIX_ROOT/bin/sh" ;;
+*) MAKE_SHELL=/bin/sh ;;
+esac
+AC_SUBST(MAKE_SHELL)
+
+dnl this is similar to the expanded AC_PROG_RANLIB
+if test x$SIZE = x; then
+ if test x$ac_tool_prefix = x; then
+ SIZE=size
+ else
+ SIZE=${ac_tool_prefix}size
+ save_IFS=$IFS ; IFS=:
+ size_found=0
+ for dir in $PATH; do
+ if test -x $dir/$SIZE ; then
+ size_found=1
+ break
+ fi
+ done
+ if test $size_found -eq 0; then
+ SIZE=:
+ fi
+ IFS=$save_IFS
+ fi
+fi
+AC_SUBST(SIZE)
+
+dnl Turn on any extensions available in the GNU C library.
+AC_DEFINE(_GNU_SOURCE, 1)
+
+dnl C compiler characteristics
+AC_C_CONST
+AC_C_INLINE
+AC_C_BIGENDIAN
+AC_C_STRINGIZE
+AC_C_LONG_DOUBLE
+AC_C_PROTOTYPES
+AC_C_CHAR_UNSIGNED
+
+dnl initialize GNU gettext
+AM_GNU_GETTEXT([no-libtool], [need-ngettext], [lib/intl])
+
+dnl header files
+AC_HEADER_DIRENT
+AC_HEADER_TIME
+
+BASH_HEADER_INTTYPES
+
+AC_CHECK_HEADERS(unistd.h stdlib.h stdarg.h varargs.h limits.h string.h \
+ memory.h locale.h termcap.h termio.h termios.h dlfcn.h \
+ stddef.h stdint.h netdb.h pwd.h grp.h strings.h regex.h)
+AC_CHECK_HEADERS(sys/pte.h sys/stream.h sys/select.h sys/file.h \
+ sys/resource.h sys/param.h sys/socket.h sys/stat.h \
+ sys/time.h sys/times.h sys/types.h sys/wait.h)
+AC_CHECK_HEADERS(netinet/in.h arpa/inet.h)
+
+dnl sys/ptem.h requires definitions from sys/stream.h on systems where it
+dnl exists
+AC_CHECK_HEADER(sys/ptem.h, , ,[[
+#if HAVE_SYS_STREAM_H
+# include <sys/stream.h>
+#endif
+]])
+
+dnl special checks for libc functions
+AC_FUNC_ALLOCA
+AC_FUNC_GETPGRP
+AC_FUNC_SETVBUF_REVERSED
+AC_FUNC_VPRINTF
+AC_FUNC_STRCOLL
+
+dnl if we're not using the bash malloc but require the C alloca, set things
+dnl up to build a libmalloc.a containing only alloca.o
+
+if test "$ac_cv_func_alloca_works" = "no" && test "$opt_bash_malloc" = "no"; then
+ MALLOC_TARGET=alloca
+ MALLOC_SRC=alloca.c
+
+ MALLOC_LIB='-lmalloc'
+ MALLOC_LIBRARY='$(ALLOC_LIBDIR)/libmalloc.a'
+ MALLOC_LDFLAGS='-L$(ALLOC_LIBDIR)'
+ MALLOC_DEP='$(MALLOC_LIBRARY)'
+fi
+
+dnl if vprintf is not in libc, see if it's defined in stdio.h
+if test "$ac_cv_func_vprintf" = no; then
+ AC_MSG_CHECKING(for declaration of vprintf in stdio.h)
+ AC_EGREP_HEADER([[int[ ]*vprintf[^a-zA-Z0-9]]],stdio.h,ac_cv_func_vprintf=yes)
+ AC_MSG_RESULT($ac_cv_func_vprintf)
+ if test $ac_cv_func_vprintf = yes; then
+ AC_DEFINE(HAVE_VPRINTF)
+ fi
+fi
+
+if test "$ac_cv_func_vprintf" = no && test "$ac_cv_func__doprnt" = "yes"; then
+ AC_LIBOBJ(vprint)
+fi
+
+dnl signal stuff
+AC_TYPE_SIGNAL
+
+dnl checks for certain version-specific system calls and libc functions
+AC_CHECK_FUNC(__setostype, AC_DEFINE(HAVE_SETOSTYPE))
+AC_CHECK_FUNC(wait3, AC_DEFINE(HAVE_WAIT3))
+AC_CHECK_FUNC(isinf, AC_DEFINE(HAVE_ISINF_IN_LIBC))
+
+dnl checks for missing libc functions
+AC_CHECK_FUNC(mkfifo,AC_DEFINE(HAVE_MKFIFO),AC_DEFINE(MKFIFO_MISSING))
+
+dnl checks for system calls
+AC_CHECK_FUNCS(dup2 fcntl getdtablesize getgroups gethostname getpagesize \
+ getpeername getrlimit getrusage gettimeofday kill killpg \
+ lstat readlink sbrk select setdtablesize tcgetpgrp uname \
+ ulimit waitpid)
+AC_REPLACE_FUNCS(rename)
+
+dnl checks for c library functions
+AC_CHECK_FUNCS(bcopy bzero confstr fnmatch \
+ getaddrinfo gethostbyname getservbyname getservent inet_aton \
+ memmove pathconf putenv raise regcomp regexec \
+ setenv setlinebuf setlocale setvbuf siginterrupt strchr \
+ sysconf tcgetattr times ttyname tzset unsetenv)
+
+AC_CHECK_FUNCS(vsnprintf snprintf vasprintf asprintf)
+AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit)
+AC_CHECK_FUNCS(getpwent getpwnam getpwuid)
+AC_REPLACE_FUNCS(getcwd memset strcasecmp strerror strftime strnlen strpbrk strstr)
+AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax)
+
+AC_CHECK_DECLS([confstr])
+AC_CHECK_DECLS([printf])
+AC_CHECK_DECLS([sbrk])
+AC_CHECK_DECLS([strcpy])
+AC_CHECK_DECLS([strsignal])
+
+dnl Extra test to detect the horribly broken HP/UX 11.00 strtold(3)
+AC_CHECK_DECLS([strtold], [
+ AC_MSG_CHECKING([for broken strtold])
+ AC_CACHE_VAL(bash_cv_strtold_broken,
+ [AC_TRY_COMPILE(
+ [#include <stdlib.h>],
+ [int main() { long double r; char *foo, bar; r = strtold(foo, &bar);}],
+ bash_cv_strtold_broken=no, bash_cv_strtold_broken=yes,
+ [AC_MSG_WARN(cannot check for broken strtold if cross-compiling, defaulting to no)])
+ ]
+ )
+ AC_MSG_RESULT($bash_cv_strtold_broken)
+ if test "$bash_cv_strtold_broken" = "yes" ; then
+ AC_DEFINE(STRTOLD_BROKEN)
+ fi
+])
+
+
+BASH_CHECK_DECL(strtoimax)
+BASH_CHECK_DECL(strtol)
+BASH_CHECK_DECL(strtoll)
+BASH_CHECK_DECL(strtoul)
+BASH_CHECK_DECL(strtoull)
+BASH_CHECK_DECL(strtoumax)
+
+AC_FUNC_MKTIME
+
+dnl
+dnl Checks for lib/intl and related code (uses some of the output from
+dnl AM_GNU_GETTEXT)
+dnl
+
+AC_CHECK_HEADERS([argz.h errno.h fcntl.h malloc.h stdio_ext.h])
+
+dnl AC_FUNC_MALLOC
+AC_FUNC_MMAP
+AC_CHECK_FUNCS([__argz_count __argz_next __argz_stringify dcgettext mempcpy \
+ munmap stpcpy strcspn strdup])
+
+INTL_DEP= INTL_INC= LIBINTL_H=
+if test "x$USE_INCLUDED_LIBINTL" = "xyes"; then
+ INTL_DEP='${INTL_LIBDIR}/libintl.a'
+ INTL_INC='-I${INTL_LIBSRC} -I${INTL_BUILDDIR}'
+ LIBINTL_H='${INTL_BUILDDIR}/libintl.h'
+fi
+AC_SUBST(INTL_DEP)
+AC_SUBST(INTL_INC)
+AC_SUBST(LIBINTL_H)
+
+dnl
+dnl End of checks needed by files in lib/intl
+dnl
+
+BASH_CHECK_MULTIBYTE
+
+dnl checks for the dynamic loading library functions in libc and libdl
+if test "$opt_static_link" != yes; then
+AC_CHECK_LIB(dl, dlopen)
+AC_CHECK_FUNCS(dlopen dlclose dlsym)
+fi
+
+dnl this defines SYS_SIGLIST_DECLARED
+AC_DECL_SYS_SIGLIST
+
+dnl network functions -- check for inet_aton again
+if test "$ac_cv_func_inet_aton" != 'yes'; then
+BASH_FUNC_INET_ATON
+fi
+
+dnl libraries
+dnl this is reportedly no longer necessary for irix[56].?
+case "$host_os" in
+irix4*) AC_CHECK_LIB(sun, getpwent) ;;
+esac
+
+dnl check for getpeername in the socket library only if it's not in libc
+if test "$ac_cv_func_getpeername" = no; then
+ BASH_CHECK_LIB_SOCKET
+fi
+dnl check for gethostbyname in socket libraries if it's not in libc
+if test "$ac_cv_func_gethostbyname" = no; then
+ BASH_FUNC_GETHOSTBYNAME
+fi
+
+dnl system types
+AC_TYPE_GETGROUPS
+AC_TYPE_OFF_T
+AC_TYPE_MODE_T
+AC_TYPE_UID_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_CHECK_TYPE(ssize_t, int)
+AC_CHECK_TYPE(time_t, long)
+
+BASH_TYPE_LONG_LONG
+BASH_TYPE_UNSIGNED_LONG_LONG
+
+AC_TYPE_SIGNAL
+
+AC_CHECK_SIZEOF(char, 1)
+AC_CHECK_SIZEOF(short, 2)
+AC_CHECK_SIZEOF(int, 4)
+AC_CHECK_SIZEOF(long, 4)
+AC_CHECK_SIZEOF(char *, 4)
+AC_CHECK_SIZEOF(double, 8)
+AC_CHECK_SIZEOF([long long], 8)
+
+AC_CHECK_TYPE(u_int, [unsigned int])
+AC_CHECK_TYPE(u_long, [unsigned long])
+
+BASH_TYPE_BITS16_T
+BASH_TYPE_U_BITS16_T
+BASH_TYPE_BITS32_T
+BASH_TYPE_U_BITS32_T
+BASH_TYPE_BITS64_T
+
+BASH_TYPE_PTRDIFF_T
+
+dnl structures
+AC_HEADER_STAT
+
+dnl system services
+AC_SYS_INTERPRETER
+if test $ac_cv_sys_interpreter = yes; then
+AC_DEFINE(HAVE_HASH_BANG_EXEC)
+fi
+
+dnl Miscellaneous Bash tests
+if test "$ac_cv_func_lstat" = "no"; then
+BASH_FUNC_LSTAT
+fi
+
+dnl behavior of system calls and library functions
+BASH_FUNC_CTYPE_NONASCII
+BASH_FUNC_DUP2_CLOEXEC_CHECK
+BASH_SYS_PGRP_SYNC
+BASH_SYS_SIGNAL_VINTAGE
+
+dnl checking for the presence of certain library symbols
+BASH_SYS_ERRLIST
+BASH_SYS_SIGLIST
+BASH_UNDER_SYS_SIGLIST
+
+dnl various system types
+BASH_TYPE_SIGHANDLER
+BASH_CHECK_TYPE(clock_t, [#include <sys/times.h>], long)
+BASH_CHECK_TYPE(sigset_t, [#include <signal.h>], int)
+BASH_CHECK_TYPE(quad_t, , long, HAVE_QUAD_T)
+BASH_CHECK_TYPE(intmax_t, , $bash_cv_type_long_long)
+BASH_CHECK_TYPE(uintmax_t, , $bash_cv_type_unsigned_long_long)
+if test "$ac_cv_header_sys_socket_h" = "yes"; then
+BASH_CHECK_TYPE(socklen_t, [#include <sys/socket.h>], int, HAVE_SOCKLEN_T)
+fi
+BASH_TYPE_RLIMIT
+
+dnl presence and contents of structures used by system calls
+BASH_STRUCT_TERMIOS_LDISC
+BASH_STRUCT_TERMIO_LDISC
+BASH_STRUCT_DIRENT_D_INO
+BASH_STRUCT_DIRENT_D_FILENO
+BASH_STRUCT_DIRENT_D_NAMLEN
+BASH_STRUCT_WINSIZE
+BASH_STRUCT_TIMEVAL
+AC_CHECK_MEMBERS([struct stat.st_blocks])
+AC_STRUCT_TM
+AC_STRUCT_TIMEZONE
+BASH_STRUCT_TIMEZONE
+
+dnl presence and behavior of C library functions
+BASH_FUNC_STRSIGNAL
+BASH_FUNC_OPENDIR_CHECK
+BASH_FUNC_ULIMIT_MAXFDS
+BASH_FUNC_GETENV
+if test "$ac_cv_func_getcwd" = "yes"; then
+BASH_FUNC_GETCWD
+fi
+BASH_FUNC_POSIX_SETJMP
+BASH_FUNC_STRCOLL
+
+dnl If putenv or unsetenv is not present, set the right define so the
+dnl prototype and declaration in lib/sh/getenv.c will be standard-conformant
+
+if test "$ac_cv_func_putenv" = "yes"; then
+BASH_FUNC_STD_PUTENV
+else
+AC_DEFINE(HAVE_STD_PUTENV)
+fi
+if test "$ac_cv_func_unsetenv" = "yes"; then
+BASH_FUNC_STD_UNSETENV
+else
+AC_DEFINE(HAVE_STD_UNSETENV)
+fi
+
+BASH_FUNC_PRINTF_A_FORMAT
+
+dnl presence and behavior of OS functions
+BASH_SYS_REINSTALL_SIGHANDLERS
+BASH_SYS_JOB_CONTROL_MISSING
+BASH_SYS_NAMED_PIPES
+
+dnl presence of certain CPP defines
+AC_HEADER_TIOCGWINSZ
+BASH_HAVE_TIOCSTAT
+BASH_HAVE_FIONREAD
+
+BASH_CHECK_WCONTINUED
+
+dnl miscellaneous
+BASH_CHECK_SPEED_T
+BASH_CHECK_GETPW_FUNCS
+BASH_CHECK_RTSIGS
+BASH_CHECK_SYS_SIGLIST
+
+dnl special checks
+case "$host_os" in
+hpux*) BASH_CHECK_KERNEL_RLIMIT ;;
+esac
+
+if test "$opt_readline" = yes; then
+dnl yuck
+case "$host_os" in
+aix*) prefer_curses=yes ;;
+esac
+BASH_CHECK_LIB_TERMCAP
+fi
+AC_SUBST(TERMCAP_LIB)
+AC_SUBST(TERMCAP_DEP)
+
+BASH_CHECK_DEV_FD
+BASH_CHECK_DEV_STDIN
+BASH_SYS_DEFAULT_MAIL_DIR
+
+if test "$bash_cv_job_control_missing" = missing; then
+ opt_job_control=no
+fi
+
+if test "$opt_job_control" = yes; then
+AC_DEFINE(JOB_CONTROL)
+JOBS_O=jobs.o
+else
+JOBS_O=nojobs.o
+fi
+
+AC_SUBST(JOBS_O)
+
+dnl Defines that we want to propagate to the Makefiles in subdirectories,
+dnl like glob and readline
+
+LOCAL_DEFS=-DSHELL
+
+dnl use this section to possibly define more cpp variables, specify local
+dnl libraries, and specify any additional local cc flags
+dnl
+dnl this should really go away someday
+
+case "${host_os}" in
+sysv4.2*) AC_DEFINE(SVR4_2)
+ AC_DEFINE(SVR4) ;;
+sysv4*) AC_DEFINE(SVR4) ;;
+sysv5*) AC_DEFINE(SVR5) ;;
+hpux9*) LOCAL_CFLAGS="-DHPUX9 -DHPUX" ;;
+hpux*) LOCAL_CFLAGS=-DHPUX ;;
+dgux*) LOCAL_CFLAGS=-D_DGUX_SOURCE; LOCAL_LIBS=-ldgc ;;
+isc*) LOCAL_CFLAGS=-Disc386 ;;
+rhapsody*) LOCAL_CFLAGS=-DRHAPSODY ;;
+darwin*) LOCAL_CFLAGS=-DMACOSX ;;
+sco3.2v5*) LOCAL_CFLAGS="-b elf -DWAITPID_BROKEN -DPATH_MAX=1024" ;;
+sco3.2v4*) LOCAL_CFLAGS="-DMUST_UNBLOCK_CHLD -DPATH_MAX=1024" ;;
+sco3.2*) LOCAL_CFLAGS=-DMUST_UNBLOCK_CHLD ;;
+sunos4*) LOCAL_CFLAGS=-DSunOS4 ;;
+solaris2.5*) LOCAL_CFLAGS=-DSunOS5 ;;
+lynxos*) LOCAL_CFLAGS=-DRECYCLES_PIDS ;;
+linux*) LOCAL_LDFLAGS=-rdynamic # allow dynamic loading
+ case "`uname -r`" in
+ 2.[[456789]]*|3*) AC_DEFINE(PGRP_PIPE) ;;
+ esac ;;
+*qnx6*) LOCAL_CFLAGS="-Dqnx -Dqnx6" LOCAL_LIBS="-lncurses" ;;
+*qnx*) LOCAL_CFLAGS="-Dqnx -F -3s" LOCAL_LDFLAGS="-3s" LOCAL_LIBS="-lunix -lncurses" ;;
+powerux*) LOCAL_LIBS="-lgen" ;;
+cygwin*) LOCAL_CFLAGS=-DRECYCLES_PIDS ;;
+opennt*|interix*) LOCAL_CFLAGS="-DNO_MAIN_ENV_ARG -DBROKEN_DIRENT_D_INO -D_POSIX_SOURCE" ;;
+esac
+
+dnl Stanza for OS/compiler pair-specific flags
+case "${host_os}-${CC}" in
+aix4.2*-*gcc*) LOCAL_LDFLAGS="-Xlinker -bexpall -Xlinker -brtl" ;;
+aix4.2*) LOCAL_LDFLAGS="-bexpall -brtl" ;;
+bsdi4*-*gcc*) LOCAL_LDFLAGS="-rdynamic" ;; # allow dynamic loading, like Linux
+esac
+
+dnl FreeBSD-3.x can have either a.out or ELF
+case "${host_os}" in
+freebsd[[3-9]]*)
+ if test -x /usr/bin/objformat && test "`/usr/bin/objformat`" = "elf" ; then
+ LOCAL_LDFLAGS=-rdynamic # allow dynamic loading
+ fi ;;
+freebsdelf*) LOCAL_LDFLAGS=-rdynamic ;; # allow dynamic loading
+dragonfly*) LOCAL_LDFLAGS=-rdynamic ;; # allow dynamic loading
+esac
+
+case "$host_cpu" in
+*cray*) LOCAL_CFLAGS="-DCRAY" ;; # shell var so config.h can use it
+esac
+
+case "$host_cpu-$host_os" in
+ibmrt-*bsd4*) LOCAL_CFLAGS="-ma -U__STDC__" ;;
+esac
+
+case "$host_cpu-$host_vendor-$host_os" in
+m88k-motorola-sysv3) LOCAL_CFLAGS=-DWAITPID_BROKEN ;;
+mips-pyramid-sysv4) LOCAL_CFLAGS=-Xa ;;
+esac
+
+#
+# Shared object configuration section. These values are generated by
+# ${srcdir}/support/shobj-conf
+#
+if test "$ac_cv_func_dlopen" = "yes" && test -f ${srcdir}/support/shobj-conf
+then
+ AC_MSG_CHECKING(shared object configuration for loadable builtins)
+ eval `${CONFIG_SHELL-/bin/sh} ${srcdir}/support/shobj-conf -C "${CC}" -c "${host_cpu}" -o "${host_os}" -v "${host_vendor}"`
+ AC_SUBST(SHOBJ_CC)
+ AC_SUBST(SHOBJ_CFLAGS)
+ AC_SUBST(SHOBJ_LD)
+ AC_SUBST(SHOBJ_LDFLAGS)
+ AC_SUBST(SHOBJ_XLDFLAGS)
+ AC_SUBST(SHOBJ_LIBS)
+ AC_SUBST(SHOBJ_STATUS)
+ AC_MSG_RESULT($SHOBJ_STATUS)
+fi
+
+# try to create a directory tree if the source is elsewhere
+# this should be packaged into a script accessible via ${srcdir}/support
+case "$srcdir" in
+.) ;;
+*) for d in doc tests support lib examples; do # dirs
+ test -d $d || mkdir $d
+ done
+ for ld in readline glob tilde malloc sh termcap; do # libdirs
+ test -d lib/$ld || mkdir lib/$ld
+ done
+ test -d examples/loadables || mkdir examples/loadables # loadable builtins
+ test -d examples/loadables/perl || mkdir examples/loadables/perl
+ ;;
+esac
+
+BUILD_DIR=`pwd`
+case "$BUILD_DIR" in
+*\ *) BUILD_DIR=`echo "$BUILD_DIR" | sed 's: :\\\\ :g'` ;;
+*) ;;
+esac
+
+AC_SUBST(PROFILE_FLAGS)
+
+AC_SUBST(incdir)
+AC_SUBST(BUILD_DIR)
+
+AC_SUBST(YACC)
+AC_SUBST(AR)
+AC_SUBST(ARFLAGS)
+
+AC_SUBST(BASHVERS)
+AC_SUBST(RELSTATUS)
+AC_SUBST(DEBUG)
+AC_SUBST(MALLOC_DEBUG)
+
+AC_SUBST(host_cpu)
+AC_SUBST(host_vendor)
+AC_SUBST(host_os)
+
+AC_SUBST(LOCAL_LIBS)
+AC_SUBST(LOCAL_CFLAGS)
+AC_SUBST(LOCAL_LDFLAGS)
+AC_SUBST(LOCAL_DEFS)
+
+#AC_SUBST(ALLOCA_SOURCE)
+#AC_SUBST(ALLOCA_OBJECT)
+
+AC_OUTPUT([Makefile builtins/Makefile lib/readline/Makefile lib/glob/Makefile \
+ lib/intl/Makefile \
+ lib/malloc/Makefile lib/sh/Makefile lib/termcap/Makefile \
+ lib/tilde/Makefile doc/Makefile support/Makefile po/Makefile.in \
+ examples/loadables/Makefile examples/loadables/perl/Makefile \
+ pathnames.h],
+[
+# Makefile uses this timestamp file to record whether config.h is up to date.
+echo timestamp > stamp-h
+])
diff --git a/dd~ b/dd~
new file mode 100644
index 00000000..9f4e2d00
--- /dev/null
+++ b/dd~
@@ -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;
diff --git a/doc/FAQ b/doc/FAQ
index 2d48fff2..71702653 100644
--- a/doc/FAQ
+++ b/doc/FAQ
@@ -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.
diff --git a/doc/FAQ~ b/doc/FAQ~
new file mode 100644
index 00000000..0fa10b5b
--- /dev/null
+++ b/doc/FAQ~
@@ -0,0 +1,1803 @@
+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
+interpreter with advanced features for both interactive use and shell
+programming.
+
+Another good source of basic information about shells is the collection
+of FAQ articles periodically posted to comp.unix.shell.
+
+Questions and comments concerning this document should be sent to
+chet@po.cwru.edu.
+
+This document is available for anonymous FTP with the URL
+
+ftp://ftp.cwru.edu/pub/bash/FAQ
+
+The Bash home page is http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html
+
+----------
+Contents:
+
+Section A: The Basics
+
+A1) What is it?
+A2) What's the latest version?
+A3) Where can I get it?
+A4) On what machines will bash run?
+A5) Will bash run on operating systems other than Unix?
+A6) How can I build bash with gcc?
+A7) How can I make bash my login shell?
+A8) I just changed my login shell to bash, and now I can't FTP into my
+ machine. Why not?
+A9) What's the `POSIX Shell and Utilities standard'?
+A10) What is the bash `posix mode'?
+
+Section B: The latest version
+
+B1) What's new in version 3.1?
+B2) Are there any user-visible incompatibilities between bash-3.1 and
+ bash-2.05b?
+
+Section C: Differences from other Unix shells
+
+C1) How does bash differ from sh, the Bourne shell?
+C2) How does bash differ from the Korn shell, version ksh88?
+C3) Which new features in ksh-93 are not in bash, and which are?
+
+Section D: Why does bash do some things differently than other Unix shells?
+
+D1) Why does bash run a different version of `command' than
+ `which command' says it will?
+D2) Why doesn't bash treat brace expansions exactly like csh?
+D3) Why doesn't bash have csh variable modifiers?
+D4) How can I make my csh aliases work when I convert to bash?
+D5) How can I pipe standard output and standard error from one command to
+ another, like csh does with `|&'?
+D6) Now that I've converted from ksh to bash, are there equivalents to
+ ksh features like autoloaded functions and the `whence' command?
+
+Section E: Why does bash do certain things the way it does?
+
+E1) Why is the bash builtin `test' slightly different from /bin/test?
+E2) Why does bash sometimes say `Broken pipe'?
+E3) When I have terminal escape sequences in my prompt, why does bash
+ wrap lines at the wrong column?
+E4) If I pipe the output of a command into `read variable', why doesn't
+ the output show up in $variable when the read command finishes?
+E5) I have a bunch of shell scripts that use backslash-escaped characters
+ in arguments to `echo'. Bash doesn't interpret these characters. Why
+ not, and how can I make it understand them?
+E6) Why doesn't a while or for loop get suspended when I type ^Z?
+E7) What about empty for loops in Makefiles?
+E8) Why does the arithmetic evaluation code complain about `08'?
+E9) Why does the pattern matching expression [A-Z]* match files beginning
+ with every letter except `z'?
+E10) Why does `cd //' leave $PWD as `//'?
+E11) If I resize my xterm while another program is running, why doesn't bash
+ notice the change?
+E12) Why don't negative offsets in substring expansion work like I expect?
+
+Section F: Things to watch out for on certain Unix versions
+
+F1) Why can't I use command line editing in my `cmdtool'?
+F2) I built bash on Solaris 2. Why do globbing expansions and filename
+ completion chop off the first few characters of each filename?
+F3) Why does bash dump core after I interrupt username completion or
+ `~user' tilde expansion on a machine running NIS?
+F4) I'm running SVR4.2. Why is the line erased every time I type `@'?
+F5) Why does bash report syntax errors when my C News scripts use a
+ redirection before a subshell command?
+F6) Why can't I use vi-mode editing on Red Hat Linux 6.1?
+F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on
+ HP/UX 11.x?
+
+Section G: How can I get bash to do certain common things?
+
+G1) How can I get bash to read and display eight-bit characters?
+G2) How do I write a function `x' to replace builtin command `x', but
+ still invoke the command from within the function?
+G3) How can I find the value of a shell variable whose name is the value
+ of another shell variable?
+G4) How can I make the bash `time' reserved word print timing output that
+ looks like the output from my system's /usr/bin/time?
+G5) How do I get the current directory into my prompt?
+G6) How can I rename "*.foo" to "*.bar"?
+G7) How can I translate a filename from uppercase to lowercase?
+G8) How can I write a filename expansion (globbing) pattern that will match
+ all files in the current directory except "." and ".."?
+
+Section H: Where do I go from here?
+
+H1) How do I report bugs in bash, and where should I look for fixes and
+ advice?
+H2) What kind of bash documentation is there?
+H3) What's coming in future versions?
+H4) What's on the bash `wish list'?
+H5) When will the next release appear?
+
+----------
+Section A: The Basics
+
+A1) What is it?
+
+Bash is a Unix command interpreter (shell). It is an implementation of
+the Posix 1003.2 shell standard, and resembles the Korn and System V
+shells.
+
+Bash contains a number of enhancements over those shells, both
+for interactive use and shell programming. Features geared
+toward interactive use include command line editing, command
+history, job control, aliases, and prompt expansion. Programming
+features include additional variable expansions, shell
+arithmetic, and a number of variables and options to control
+shell behavior.
+
+Bash was originally written by Brian Fox of the Free Software
+Foundation. The current developer and maintainer is Chet Ramey
+of Case Western Reserve University.
+
+A2) What's the latest version?
+
+The latest version is 3.1, first made available on 09 December, 2005.
+
+A3) Where can I get it?
+
+Bash is the GNU project's shell, and so is available from the
+master GNU archive site, ftp.gnu.org, and its mirrors. The
+latest version is also available for FTP from ftp.cwru.edu.
+The following URLs tell how to get version 3.1:
+
+ftp://ftp.gnu.org/pub/gnu/bash/bash-3.1.tar.gz
+ftp://ftp.cwru.edu/pub/bash/bash-3.1.tar.gz
+
+Formatted versions of the documentation are available with the URLs:
+
+ftp://ftp.gnu.org/pub/gnu/bash/bash-doc-3.1.tar.gz
+ftp://ftp.cwru.edu/pub/bash/bash-doc-3.1.tar.gz
+
+Any patches for the current version are available with the URL:
+
+ftp://ftp.cwru.edu/pub/bash/bash-3.1-patches/
+
+A4) On what machines will bash run?
+
+Bash has been ported to nearly every version of Unix. All you
+should have to do to build it on a machine for which a port
+exists is to type `configure' and then `make'. The build process
+will attempt to discover the version of Unix you have and tailor
+itself accordingly, using a script created by GNU autoconf.
+
+More information appears in the file `INSTALL' in the distribution.
+
+The Bash web page (http://cnswww.cns.cwru.edu/~chet/bash/bashtop.html)
+explains how to obtain binary versions of bash for most of the major
+commercial Unix systems.
+
+A5) Will bash run on operating systems other than Unix?
+
+Configuration specifics for Unix-like systems such as QNX and
+LynxOS are included in the distribution. Bash-2.05 and later
+versions should compile and run on Minix 2.0 (patches were
+contributed), but I don't believe anyone has built bash-2.x on
+earlier Minix versions yet.
+
+Bash has been ported to versions of Windows implementing the Win32
+programming interface. This includes Windows 95 and Windows NT.
+The port was done by Cygnus Solutions (now part of Red Hat) as part
+of their CYGWIN project. For more information about the project, see
+http://www.cygwin.com/.
+
+Cygnus originally ported bash-1.14.7, and that port was part of their
+early GNU-Win32 (the original name) releases. Cygnus has also done
+ports of bash-2.05b and bash-3.0 to the CYGWIN environment, and both
+are available as part of their current release. Bash-3.1 is currently
+being tested and should be available soon.
+
+Bash-2.05b and later versions should require no local Cygnus changes to
+build and run under CYGWIN.
+
+DJ Delorie has a port of bash-2.x which runs under MS-DOS, as part
+of the DJGPP project. For more information on the project, see
+
+http://www.delorie.com/djgpp/
+
+I have been told that the original DJGPP port was done by Daisuke Aoyama.
+
+Mark Elbrecht <snowball3@bigfoot.com> has sent me notice that bash-2.04
+is available for DJGPP V2. The files are available as:
+
+ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204b.zip binary
+ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204d.zip documentation
+ftp://ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2gnu/bsh204s.zip source
+
+Mark began to work with bash-2.05, but I don't know the current status.
+
+Bash-3.0 compiles and runs with no modifications under Microsoft's Services
+for Unix (SFU), once known as Interix. I do not anticipate any problems
+with building bash-3.1.
+
+A6) How can I build bash with gcc?
+
+Bash configures to use gcc by default if it is available. Read the
+file INSTALL in the distribution for more information.
+
+A7) How can I make bash my login shell?
+
+Some machines let you use `chsh' to change your login shell. Other
+systems use `passwd -s' or `passwd -e'. If one of these works for
+you, that's all you need. Note that many systems require the full
+pathname to a shell to appear in /etc/shells before you can make it
+your login shell. For this, you may need the assistance of your
+friendly local system administrator.
+
+If you cannot do this, you can still use bash as your login shell, but
+you need to perform some tricks. The basic idea is to add a command
+to your login shell's startup file to replace your login shell with
+bash.
+
+For example, if your login shell is csh or tcsh, and you have installed
+bash in /usr/gnu/bin/bash, add the following line to ~/.login:
+
+ if ( -f /usr/gnu/bin/bash ) exec /usr/gnu/bin/bash --login
+
+(the `--login' tells bash that it is a login shell).
+
+It's not a good idea to put this command into ~/.cshrc, because every
+csh you run without the `-f' option, even ones started to run csh scripts,
+reads that file. If you must put the command in ~/.cshrc, use something
+like
+
+ if ( $?prompt ) exec /usr/gnu/bin/bash --login
+
+to ensure that bash is exec'd only when the csh is interactive.
+
+If your login shell is sh or ksh, you have to do two things.
+
+First, create an empty file in your home directory named `.bash_profile'.
+The existence of this file will prevent the exec'd bash from trying to
+read ~/.profile, and re-execing itself over and over again. ~/.bash_profile
+is the first file bash tries to read initialization commands from when
+it is invoked as a login shell.
+
+Next, add a line similar to the above to ~/.profile:
+
+ [ -f /usr/gnu/bin/bash ] && [ -x /usr/gnu/bin/bash ] && \
+ exec /usr/gnu/bin/bash --login
+
+This will cause login shells to replace themselves with bash running as
+a login shell. Once you have this working, you can copy your initialization
+code from ~/.profile to ~/.bash_profile.
+
+I have received word that the recipe supplied above is insufficient for
+machines running CDE. CDE has a maze of twisty little startup files, all
+slightly different.
+
+If you cannot change your login shell in the password file to bash, you
+will have to (apparently) live with CDE using the shell in the password
+file to run its startup scripts. If you have changed your shell to bash,
+there is code in the CDE startup files (on Solaris, at least) that attempts
+to do the right thing. It is, however, often broken, and may require that
+you use the $BASH_ENV trick described below.
+
+`dtterm' claims to use $SHELL as the default program to start, so if you
+can change $SHELL in the CDE startup files, you should be able to use bash
+in your terminal windows.
+
+Setting DTSOURCEPROFILE in ~/.dtprofile will cause the `Xsession' program
+to read your login shell's startup files. You may be able to use bash for
+the rest of the CDE programs by setting SHELL to bash in ~/.dtprofile as
+well, but I have not tried this.
+
+You can use the above `exec' recipe to start bash when not logging in with
+CDE by testing the value of the DT variable:
+
+ if [ -n "$DT" ]; then
+ [ -f /usr/gnu/bin/bash ] && exec /usr/gnu/bin/bash --login
+ fi
+
+If CDE starts its shells non-interactively during login, the login shell
+startup files (~/.profile, ~/.bash_profile) will not be sourced at login.
+To get around this problem, append a line similar to the following to your
+~/.dtprofile:
+
+ BASH_ENV=${HOME}/.bash_profile ; export BASH_ENV
+
+and add the following line to the beginning of ~/.bash_profile:
+
+ unset BASH_ENV
+
+A8) I just changed my login shell to bash, and now I can't FTP into my
+ machine. Why not?
+
+You must add the full pathname to bash to the file /etc/shells. As
+noted in the answer to the previous question, many systems require
+this before you can make bash your login shell.
+
+Most versions of ftpd use this file to prohibit `special' users
+such as `uucp' and `news' from using FTP.
+
+A9) What's the `POSIX Shell and Utilities standard'?
+
+POSIX is a name originally coined by Richard Stallman for a
+family of open system standards based on UNIX. There are a
+number of aspects of UNIX under consideration for
+standardization, from the basic system services at the system
+call and C library level to applications and tools to system
+administration and management. Each area of standardization is
+assigned to a working group in the 1003 series.
+
+The POSIX Shell and Utilities standard was originally developed by
+IEEE Working Group 1003.2 (POSIX.2). Today it has been merged with
+the original 1003.1 Working Group and is maintained by the Austin
+Group (a joint working group of the IEEE, The Open Group and
+ISO/IEC SC22/WG15). Today the Shell and Utilities are a volume
+within the set of documents that make up IEEE Std 1003.1-2001, and
+thus now the former POSIX.2 (from 1992) is now part of the current
+POSIX.1 standard (POSIX 1003.1-2001).
+
+The Shell and Utilities volume concentrates on the command
+interpreter interface and utility programs commonly executed from
+the command line or by other programs. The standard is freely
+available on the web at http://www.UNIX-systems.org/version3/ .
+Work continues at the Austin Group on maintenance issues; see
+http://www.opengroup.org/austin/ to join the discussions.
+
+Bash is concerned with the aspects of the shell's behavior defined
+by the POSIX Shell and Utilities volume. The shell command
+language has of course been standardized, including the basic flow
+control and program execution constructs, I/O redirection and
+pipelining, argument handling, variable expansion, and quoting.
+
+The `special' builtins, which must be implemented as part of the
+shell to provide the desired functionality, are specified as
+being part of the shell; examples of these are `eval' and
+`export'. Other utilities appear in the sections of POSIX not
+devoted to the shell which are commonly (and in some cases must
+be) implemented as builtin commands, such as `read' and `test'.
+POSIX also specifies aspects of the shell's interactive
+behavior as part of the UPE, including job control and command
+line editing. Only vi-style line editing commands have been
+standardized; emacs editing commands were left out due to
+objections.
+
+The latest version of the POSIX Shell and Utilities standard is
+available (now updated to the 2004 Edition) as part of the Single
+UNIX Specification Version 3 at
+
+http://www.UNIX-systems.org/version3/
+
+A10) What is the bash `posix mode'?
+
+Although bash is an implementation of the POSIX shell
+specification, there are areas where the bash default behavior
+differs from that spec. The bash `posix mode' changes the bash
+behavior in these areas so that it obeys the spec more closely.
+
+Posix mode is entered by starting bash with the --posix or
+'-o posix' option or executing `set -o posix' after bash is running.
+
+The specific aspects of bash which change when posix mode is
+active are listed in the file POSIX in the bash distribution.
+They are also listed in a section in the Bash Reference Manual
+(from which that file is generated).
+
+Section B: The latest version
+
+B1) What's new in version 3.1?
+
+Bash-3.1 is the first maintenance release of the third major release of
+bash. It contains the following significant new features (see the manual
+page for complete descriptions and the CHANGES and NEWS files in the
+bash-3.1 distribution).
+
+o Bash-3.1 may now be configured and built in a mode that enforces strict
+ POSIX compliance.
+
+o The `+=' assignment operator, which appends to the value of a string or
+ array variable, has been implemented.
+
+o It is now possible to ignore case when matching in contexts other than
+ filename generation using the new `nocasematch' shell option.
+
+A short feature history dating from Bash-2.0:
+
+Bash-3.0 contained the following new features:
+
+o Features to support the bash debugger have been implemented, and there
+ is a new `extdebug' option to turn the non-default options on
+
+o HISTCONTROL is now a colon-separated list of options and has been
+ extended with a new `erasedups' option that will result in only one
+ copy of a command being kept in the history list
+
+o Brace expansion has been extended with a new {x..y} form, producing
+ sequences of digits or characters
+
+o Timestamps are now kept with history entries, with an option to save
+ and restore them from the history file; there is a new HISTTIMEFORMAT
+ variable describing how to display the timestamps when listing history
+ entries
+
+o The `[[' command can now perform extended regular expression (egrep-like)
+ matching, with matched subexpressions placed in the BASH_REMATCH array
+ variable
+
+o A new `pipefail' option causes a pipeline to return a failure status if
+ any command in it fails
+
+o The `jobs', `kill', and `wait' builtins now accept job control notation
+ in their arguments even if job control is not enabled
+
+o The `gettext' package and libintl have been integrated, and the shell
+ messages may be translated into other languages
+
+Bash-2.05b introduced the following new features:
+
+o support for multibyte characters has been added to both bash and readline
+
+o the DEBUG trap is now run *before* simple commands, ((...)) commands,
+ [[...]] conditional commands, and for ((...)) loops
+
+o the shell now performs arithmetic in the largest integer size the machine
+ supports (intmax_t)
+
+o there is a new \D{...} prompt expansion; passes the `...' to strftime(3)
+ and inserts the result into the expanded prompt
+
+o there is a new `here-string' redirection operator: <<< word
+
+o when displaying variables, function attributes and definitions are shown
+ separately, allowing them to be re-used as input (attempting to re-use
+ the old output would result in syntax errors).
+
+o `read' has a new `-u fd' option to read from a specified file descriptor
+
+o the bash debugger in examples/bashdb has been modified to work with the
+ new DEBUG trap semantics, the command set has been made more gdb-like,
+ and the changes to $LINENO make debugging functions work better
+
+o the expansion of $LINENO inside a shell function is only relative to the
+ function start if the shell is interactive -- if the shell is running a
+ script, $LINENO expands to the line number in the script. This is as
+ POSIX-2001 requires
+
+Bash-2.05a introduced the following new features:
+
+o The `printf' builtin has undergone major work
+
+o There is a new read-only `shopt' option: login_shell, which is set by
+ login shells and unset otherwise
+
+o New `\A' prompt string escape sequence; expanding to time in 24-hour
+ HH:MM format
+
+o New `-A group/-g' option to complete and compgen; goes group name
+ completion
+
+o New [+-]O invocation option to set and unset `shopt' options at startup
+
+o ksh-like `ERR' trap
+
+o `for' loops now allow empty word lists after the `in' reserved word
+
+o new `hard' and `soft' arguments for the `ulimit' builtin
+
+o Readline can be configured to place the user at the same point on the line
+ when retrieving commands from the history list
+
+o Readline can be configured to skip `hidden' files (filenames with a leading
+ `.' on Unix) when performing completion
+
+Bash-2.05 introduced the following new features:
+
+o This version has once again reverted to using locales and strcoll(3) when
+ processing pattern matching bracket expressions, as POSIX requires.
+o Added a new `--init-file' invocation argument as a synonym for `--rcfile',
+ per the new GNU coding standards.
+o The /dev/tcp and /dev/udp redirections now accept service names as well as
+ port numbers.
+o `complete' and `compgen' now take a `-o value' option, which controls some
+ of the aspects of that compspec. Valid values are:
+
+ default - perform bash default completion if programmable
+ completion produces no matches
+ dirnames - perform directory name completion if programmable
+ completion produces no matches
+ filenames - tell readline that the compspec produces filenames,
+ so it can do things like append slashes to
+ directory names and suppress trailing spaces
+o A new loadable builtin, realpath, which canonicalizes and expands symlinks
+ in pathname arguments.
+o When `set' is called without options, it prints function defintions in a
+ way that allows them to be reused as input. This affects `declare' and
+ `declare -p' as well. This only happens when the shell is not in POSIX
+ mode, since POSIX.2 forbids this behavior.
+
+Bash-2.04 introduced the following new features:
+
+o Programmable word completion with the new `complete' and `compgen' builtins;
+ examples are provided in examples/complete/complete-examples
+o `history' has a new `-d' option to delete a history entry
+o `bind' has a new `-x' option to bind key sequences to shell commands
+o The prompt expansion code has new `\j' and `\l' escape sequences
+o The `no_empty_cmd_completion' shell option, if enabled, inhibits
+ command completion when TAB is typed on an empty line
+o `help' has a new `-s' option to print a usage synopsis
+o New arithmetic operators: var++, var--, ++var, --var, expr1,expr2 (comma)
+o New ksh93-style arithmetic for command:
+ for ((expr1 ; expr2; expr3 )); do list; done
+o `read' has new options: `-t', `-n', `-d', `-s'
+o The redirection code handles several filenames specially: /dev/fd/N,
+ /dev/stdin, /dev/stdout, /dev/stderr
+o The redirection code now recognizes /dev/tcp/HOST/PORT and
+ /dev/udp/HOST/PORT and tries to open a TCP or UDP socket, respectively,
+ to the specified port on the specified host
+o The ${!prefix*} expansion has been implemented
+o A new FUNCNAME variable, which expands to the name of a currently-executing
+ function
+o The GROUPS variable is no longer readonly
+o A new shopt `xpg_echo' variable, to control the behavior of echo with
+ respect to backslash-escape sequences at runtime
+o The NON_INTERACTIVE_LOGIN_SHELLS #define has returned
+
+The version of Readline released with Bash-2.04, Readline-4.1, had several
+new features as well:
+
+o Parentheses matching is always compiled into readline, and controllable
+ with the new `blink-matching-paren' variable
+o The history-search-forward and history-search-backward functions now leave
+ point at the end of the line when the search string is empty, like
+ reverse-search-history, and forward-search-history
+o A new function for applications: rl_on_new_line_with_prompt()
+o New variables for applications: rl_already_prompted, and rl_gnu_readline_p
+
+
+Bash-2.03 had very few new features, in keeping with the convention
+that odd-numbered releases provide mainly bug fixes. A number of new
+features were added to Readline, mostly at the request of the Cygnus
+folks.
+
+A new shopt option, `restricted_shell', so that startup files can test
+ whether or not the shell was started in restricted mode
+Filename generation is now performed on the words between ( and ) in
+ compound array assignments (this is really a bug fix)
+OLDPWD is now auto-exported, as POSIX.2 requires
+ENV and BASH_ENV are read-only variables in a restricted shell
+Bash may now be linked against an already-installed Readline library,
+ as long as the Readline library is version 4 or newer
+All shells begun with the `--login' option will source the login shell
+ startup files, even if the shell is not interactive
+
+There were lots of changes to the version of the Readline library released
+along with Bash-2.03. For a complete list of the changes, read the file
+CHANGES in the Bash-2.03 distribution.
+
+Bash-2.02 contained the following new features:
+
+a new version of malloc (based on the old GNU malloc code in previous
+ bash versions) that is more page-oriented, more conservative
+ with memory usage, does not `orphan' large blocks when they
+ are freed, is usable on 64-bit machines, and has allocation
+ checking turned on unconditionally
+POSIX.2-style globbing character classes ([:alpha:], [:alnum:], etc.)
+POSIX.2-style globbing equivalence classes
+POSIX.2-style globbing collating symbols
+the ksh [[...]] extended conditional command
+the ksh egrep-style extended pattern matching operators
+a new `printf' builtin
+the ksh-like $(<filename) command substitution, which is equivalent to
+ $(cat filename)
+new tilde prefixes that expand to directories from the directory stack
+new `**' arithmetic operator to do exponentiation
+case-insensitive globbing (filename expansion)
+menu completion a la tcsh
+`magic-space' history expansion function like tcsh
+the readline inputrc `language' has a new file inclusion directive ($include)
+
+Bash-2.01 contained only a few new features:
+
+new `GROUPS' builtin array variable containing the user's group list
+new bindable readline commands: history-and-alias-expand-line and
+ alias-expand-line
+
+Bash-2.0 contained extensive changes and new features from bash-1.14.7.
+Here's a short list:
+
+new `time' reserved word to time pipelines, shell builtins, and
+ shell functions
+one-dimensional arrays with a new compound assignment statement,
+ appropriate expansion constructs and modifications to some
+ of the builtins (read, declare, etc.) to use them
+new quoting syntaxes for ANSI-C string expansion and locale-specific
+ string translation
+new expansions to do substring extraction, pattern replacement, and
+ indirect variable expansion
+new builtins: `disown' and `shopt'
+new variables: HISTIGNORE, SHELLOPTS, PIPESTATUS, DIRSTACK, GLOBIGNORE,
+ MACHTYPE, BASH_VERSINFO
+special handling of many unused or redundant variables removed
+ (e.g., $notify, $glob_dot_filenames, $no_exit_on_failed_exec)
+dynamic loading of new builtin commands; many loadable examples provided
+new prompt expansions: \a, \e, \n, \H, \T, \@, \v, \V
+history and aliases available in shell scripts
+new readline variables: enable-keypad, mark-directories, input-meta,
+ visible-stats, disable-completion, comment-begin
+new readline commands to manipulate the mark and operate on the region
+new readline emacs mode commands and bindings for ksh-88 compatibility
+updated and extended builtins
+new DEBUG trap
+expanded (and now documented) restricted shell mode
+
+implementation stuff:
+autoconf-based configuration
+nearly all of the bugs reported since version 1.14 have been fixed
+most builtins converted to use builtin `getopt' for consistency
+most builtins use -p option to display output in a reusable form
+ (for consistency)
+grammar tighter and smaller (66 reduce-reduce conflicts gone)
+lots of code now smaller and faster
+test suite greatly expanded
+
+B2) Are there any user-visible incompatibilities between bash-3.1 and
+ bash-2.05b?
+
+There are a few incompatibilities between version 2.05b and version 3.1.
+They are detailed in the file COMPAT in the bash distribution. That file
+is not meant to be all-encompassing; send mail to bash-maintainers@gnu.org
+if if you find something that's not mentioned there.
+
+Section C: Differences from other Unix shells
+
+C1) How does bash differ from sh, the Bourne shell?
+
+This is a non-comprehensive list of features that differentiate bash
+from the SVR4.2 shell. The bash manual page explains these more
+completely.
+
+Things bash has that sh does not:
+ long invocation options
+ [+-]O invocation option
+ -l invocation option
+ `!' reserved word to invert pipeline return value
+ `time' reserved word to time pipelines and shell builtins
+ the `function' reserved word
+ the `select' compound command and reserved word
+ arithmetic for command: for ((expr1 ; expr2; expr3 )); do list; done
+ new $'...' and $"..." quoting
+ the $(...) form of command substitution
+ the $(<filename) form of command substitution, equivalent to
+ $(cat filename)
+ the ${#param} parameter value length operator
+ the ${!param} indirect parameter expansion operator
+ the ${!param*} prefix expansion operator
+ the ${param:offset[:length]} parameter substring operator
+ the ${param/pat[/string]} parameter pattern substitution operator
+ expansions to perform substring removal (${p%[%]w}, ${p#[#]w})
+ expansion of positional parameters beyond $9 with ${num}
+ variables: BASH, BASH_VERSION, BASH_VERSINFO, UID, EUID, REPLY,
+ TIMEFORMAT, PPID, PWD, OLDPWD, SHLVL, RANDOM, SECONDS,
+ LINENO, HISTCMD, HOSTTYPE, OSTYPE, MACHTYPE, HOSTNAME,
+ ENV, PS3, PS4, DIRSTACK, PIPESTATUS, HISTSIZE, HISTFILE,
+ HISTFILESIZE, HISTCONTROL, HISTIGNORE, GLOBIGNORE, GROUPS,
+ PROMPT_COMMAND, FCEDIT, FIGNORE, IGNOREEOF, INPUTRC,
+ SHELLOPTS, OPTERR, HOSTFILE, TMOUT, FUNCNAME, histchars,
+ auto_resume
+ DEBUG trap
+ ERR trap
+ variable arrays with new compound assignment syntax
+ redirections: <>, &>, >|, <<<, [n]<&word-, [n]>&word-
+ prompt string special char translation and variable expansion
+ auto-export of variables in initial environment
+ command search finds functions before builtins
+ bash return builtin will exit a file sourced with `.'
+ builtins: cd -/-L/-P, exec -l/-c/-a, echo -e/-E, hash -d/-l/-p/-t.
+ export -n/-f/-p/name=value, pwd -L/-P,
+ 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 -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
+ bash restricted shell mode is more extensive
+ bash allows functions and variables with the same name
+ brace expansion
+ tilde expansion
+ arithmetic expansion with $((...)) and `let' builtin
+ the `[[...]]' extended conditional command
+ process substitution
+ aliases and alias/unalias builtins
+ local variables in functions and `local' builtin
+ readline and command-line editing with programmable completion
+ command history and history/fc builtins
+ csh-like history expansion
+ other new bash builtins: bind, command, compgen, complete, builtin,
+ declare/typeset, dirs, enable, fc, help,
+ history, logout, popd, pushd, disown, shopt,
+ printf
+ exported functions
+ filename generation when using output redirection (command >a*)
+ POSIX.2-style globbing character classes
+ POSIX.2-style globbing equivalence classes
+ POSIX.2-style globbing collating symbols
+ egrep-like extended pattern matching operators
+ case-insensitive pattern matching and globbing
+ variable assignments preceding commands affect only that command,
+ even for builtins and functions
+ posix mode and strict posix conformance
+ redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr,
+ /dev/tcp/host/port, /dev/udp/host/port
+ debugger support, including `caller' builtin and new variables
+ RETURN trap
+ the `+=' assignment operator
+
+
+Things sh has that bash does not:
+ uses variable SHACCT to do shell accounting
+ includes `stop' builtin (bash can use alias stop='kill -s STOP')
+ `newgrp' builtin
+ turns on job control if called as `jsh'
+ $TIMEOUT (like bash $TMOUT)
+ `^' is a synonym for `|'
+ new SVR4.2 sh builtins: mldmode, priv
+
+Implementation differences:
+ redirection to/from compound commands causes sh to create a subshell
+ bash does not allow unbalanced quotes; sh silently inserts them at EOF
+ bash does not mess with signal 11
+ sh sets (euid, egid) to (uid, gid) if -p not supplied and uid < 100
+ bash splits only the results of expansions on IFS, using POSIX.2
+ field splitting rules; sh splits all words on IFS
+ sh does not allow MAILCHECK to be unset (?)
+ sh does not allow traps on SIGALRM or SIGCHLD
+ bash allows multiple option arguments when invoked (e.g. -x -v);
+ sh allows only a single option argument (`sh -x -v' attempts
+ to open a file named `-v', and, on SunOS 4.1.4, dumps core.
+ On Solaris 2.4 and earlier versions, sh goes into an infinite
+ loop.)
+ sh exits a script if any builtin fails; bash exits only if one of
+ the POSIX.2 `special' builtins fails
+
+C2) How does bash differ from the Korn shell, version ksh88?
+
+Things bash has or uses that ksh88 does not:
+ long invocation options
+ [-+]O invocation option
+ -l invocation option
+ `!' reserved word
+ arithmetic for command: for ((expr1 ; expr2; expr3 )); do list; done
+ arithmetic in largest machine-supported size (intmax_t)
+ posix mode and posix conformance
+ command hashing
+ tilde expansion for assignment statements that look like $PATH
+ process substitution with named pipes if /dev/fd is not available
+ the ${!param} indirect parameter expansion operator
+ the ${!param*} prefix expansion operator
+ the ${param:offset[:length]} parameter substring operator
+ the ${param/pat[/string]} parameter pattern substitution operator
+ variables: BASH, BASH_VERSION, BASH_VERSINFO, UID, EUID, SHLVL,
+ TIMEFORMAT, HISTCMD, HOSTTYPE, OSTYPE, MACHTYPE,
+ HISTFILESIZE, HISTIGNORE, HISTCONTROL, PROMPT_COMMAND,
+ IGNOREEOF, FIGNORE, INPUTRC, HOSTFILE, DIRSTACK,
+ PIPESTATUS, HOSTNAME, OPTERR, SHELLOPTS, GLOBIGNORE,
+ GROUPS, FUNCNAME, histchars, auto_resume
+ prompt expansion with backslash escapes and command substitution
+ redirection: &> (stdout and stderr), <<<, [n]<&word-, [n]>&word-
+ more extensive and extensible editing and programmable completion
+ builtins: bind, builtin, command, declare, dirs, echo -e/-E, enable,
+ exec -l/-c/-a, fc -s, export -n/-f/-p, hash, help, history,
+ jobs -x/-r/-s, kill -s/-n/-l, local, logout, popd, pushd,
+ read -e/-p/-a/-t/-n/-d/-s, readonly -a/-n/-f/-p,
+ 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 -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
+ POSIX.2-style globbing collating symbols
+ egrep-like extended pattern matching operators
+ case-insensitive pattern matching and globbing
+ `**' arithmetic operator to do exponentiation
+ redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr
+ arrays of unlimited size
+ TMOUT is default timeout for `read' and `select'
+ debugger support, including the `caller' builtin
+ RETURN trap
+ Timestamps in history entries
+ {x..y} brace expansion
+ The `+=' assignment operator
+
+Things ksh88 has or uses that bash does not:
+ tracked aliases (alias -t)
+ variables: ERRNO, FPATH, EDITOR, VISUAL
+ co-processes (|&, >&p, <&p)
+ weirdly-scoped functions
+ typeset +f to list all function names without definitions
+ text of command history kept in a file, not memory
+ builtins: alias -x, cd old new, newgrp, print,
+ read -p/-s/var?prompt, set -A/-o gmacs/
+ -o bgnice/-o markdirs/-o trackall/-o viraw/-s,
+ typeset -H/-L/-R/-Z/-A/-ft/-fu/-fx/-l/-u/-t, whence
+ using environment to pass attributes of exported variables
+ arithmetic evaluation done on arguments to some builtins
+ reads .profile from $PWD when invoked as login shell
+
+Implementation differences:
+ ksh runs last command of a pipeline in parent shell context
+ bash has brace expansion by default (ksh88 compile-time option)
+ bash has fixed startup file for all interactive shells; ksh reads $ENV
+ bash has exported functions
+ bash command search finds functions before builtins
+ bash waits for all commands in pipeline to exit before returning status
+ emacs-mode editing has some slightly different key bindings
+
+C3) Which new features in ksh-93 are not in bash, and which are?
+
+New things in ksh-93 not in bash-3.0:
+ associative arrays
+ floating point arithmetic and variables
+ math library functions
+ ${!name[sub]} name of subscript for associative array
+ `.' is allowed in variable names to create a hierarchical namespace
+ more extensive compound assignment syntax
+ discipline functions
+ `sleep' and `getconf' builtins (bash has loadable versions)
+ typeset -n and `nameref' variables
+ KEYBD trap
+ variables: .sh.edchar, .sh.edmode, .sh.edcol, .sh.edtext, .sh.version,
+ .sh.name, .sh.subscript, .sh.value, .sh.match, HISTEDIT
+ backreferences in pattern matching (\N)
+ `&' operator in pattern lists for matching
+ print -f (bash uses printf)
+ `fc' has been renamed to `hist'
+ `.' can execute shell functions
+ exit statuses between 0 and 255
+ FPATH and PATH mixing
+ getopts -a
+ -I invocation option
+ printf %H, %P, %T, %Z modifiers, output base for %d
+ lexical scoping for local variables in `ksh' functions
+ no scoping for local variables in `POSIX' functions
+
+New things in ksh-93 present in bash-3.0:
+ [n]<&word- and [n]>&word- redirections (combination dup and close)
+ for (( expr1; expr2; expr3 )) ; do list; done - arithmetic for command
+ ?:, ++, --, `expr1 , expr2' arithmetic operators
+ expansions: ${!param}, ${param:offset[:len]}, ${param/pat[/str]},
+ ${!param*}
+ compound array assignment
+ the `!' reserved word
+ loadable builtins -- but ksh uses `builtin' while bash uses `enable'
+ `command', `builtin', `disown' builtins
+ new $'...' and $"..." quoting
+ FIGNORE (but bash uses GLOBIGNORE), HISTCMD
+ set -o notify/-C
+ changes to kill builtin
+ read -A (bash uses read -a)
+ read -t/-d
+ trap -p
+ exec -c/-a
+ `.' restores the positional parameters when it completes
+ POSIX.2 `test'
+ umask -S
+ unalias -a
+ command and arithmetic substitution performed on PS1, PS4, and ENV
+ command name completion
+ ENV processed only for interactive shells
+ set -o pipefail
+ The `+=' assignment operator
+
+Section D: Why does bash do some things differently than other Unix shells?
+
+D1) Why does bash run a different version of `command' than
+ `which command' says it will?
+
+On many systems, `which' is actually a csh script that assumes
+you're running csh. In tcsh, `which' and its cousin `where'
+are builtins. On other Unix systems, `which' is a perl script
+that uses the PATH environment variable.
+
+The csh script version reads the csh startup files from your
+home directory and uses those to determine which `command' will
+be invoked. Since bash doesn't use any of those startup files,
+there's a good chance that your bash environment differs from
+your csh environment. The bash `type' builtin does everything
+`which' does, and will report correct results for the running
+shell. If you're really wedded to the name `which', try adding
+the following function definition to your .bashrc:
+
+ which()
+ {
+ builtin type "$@"
+ }
+
+If you're moving from tcsh and would like to bring `where' along
+as well, use this function:
+
+ where()
+ {
+ builtin type -a "$@"
+ }
+
+D2) Why doesn't bash treat brace expansions exactly like csh?
+
+The only difference between bash and csh brace expansion is that
+bash requires a brace expression to contain at least one unquoted
+comma if it is to be expanded. Any brace-surrounded word not
+containing an unquoted comma is left unchanged by the brace
+expansion code. This affords the greatest degree of sh
+compatibility.
+
+Bash, ksh, zsh, and pd-ksh all implement brace expansion this way.
+
+D3) Why doesn't bash have csh variable modifiers?
+
+Posix has specified a more powerful, albeit somewhat more cryptic,
+mechanism cribbed from ksh, and bash implements it.
+
+${parameter%word}
+ Remove smallest suffix pattern. The WORD is expanded to produce
+ a pattern. It then expands to the value of PARAMETER, with the
+ smallest portion of the suffix matched by the pattern deleted.
+
+ x=file.c
+ echo ${x%.c}.o
+ -->file.o
+
+${parameter%%word}
+
+ Remove largest suffix pattern. The WORD is expanded to produce
+ a pattern. It then expands to the value of PARAMETER, with the
+ largest portion of the suffix matched by the pattern deleted.
+
+ x=posix/src/std
+ echo ${x%%/*}
+ -->posix
+
+${parameter#word}
+ Remove smallest prefix pattern. The WORD is expanded to produce
+ a pattern. It then expands to the value of PARAMETER, with the
+ smallest portion of the prefix matched by the pattern deleted.
+
+ x=$HOME/src/cmd
+ echo ${x#$HOME}
+ -->/src/cmd
+
+${parameter##word}
+ Remove largest prefix pattern. The WORD is expanded to produce
+ a pattern. It then expands to the value of PARAMETER, with the
+ largest portion of the prefix matched by the pattern deleted.
+
+ x=/one/two/three
+ echo ${x##*/}
+ -->three
+
+
+Given
+ a=/a/b/c/d
+ b=b.xxx
+
+ csh bash result
+ --- ---- ------
+ $a:h ${a%/*} /a/b/c
+ $a:t ${a##*/} d
+ $b:r ${b%.*} b
+ $b:e ${b##*.} xxx
+
+
+D4) How can I make my csh aliases work when I convert to bash?
+
+Bash uses a different syntax to support aliases than csh does.
+The details can be found in the documentation. We have provided
+a shell script which does most of the work of conversion for you;
+this script can be found in ./examples/misc/aliasconv.sh. Here is
+how you use it:
+
+Start csh in the normal way for you. (e.g., `csh')
+
+Pipe the output of `alias' through `aliasconv.sh', saving the
+results into `bash_aliases':
+
+ alias | bash aliasconv.sh >bash_aliases
+
+Edit `bash_aliases', carefully reading through any created
+functions. You will need to change the names of some csh specific
+variables to the bash equivalents. The script converts $cwd to
+$PWD, $term to $TERM, $home to $HOME, $user to $USER, and $prompt
+to $PS1. You may also have to add quotes to avoid unwanted
+expansion.
+
+For example, the csh alias:
+
+ alias cd 'cd \!*; echo $cwd'
+
+is converted to the bash function:
+
+ cd () { command cd "$@"; echo $PWD ; }
+
+The only thing that needs to be done is to quote $PWD:
+
+ cd () { command cd "$@"; echo "$PWD" ; }
+
+Merge the edited file into your ~/.bashrc.
+
+There is an additional, more ambitious, script in
+examples/misc/cshtobash that attempts to convert your entire csh
+environment to its bash equivalent. This script can be run as
+simply `cshtobash' to convert your normal interactive
+environment, or as `cshtobash ~/.login' to convert your login
+environment.
+
+D5) How can I pipe standard output and standard error from one command to
+ another, like csh does with `|&'?
+
+Use
+ command 2>&1 | command2
+
+The key is to remember that piping is performed before redirection, so
+file descriptor 1 points to the pipe when it is duplicated onto file
+descriptor 2.
+
+D6) Now that I've converted from ksh to bash, are there equivalents to
+ ksh features like autoloaded functions and the `whence' command?
+
+There are features in ksh-88 and ksh-93 that do not have direct bash
+equivalents. Most, however, can be emulated with very little trouble.
+
+ksh-88 feature Bash equivalent
+-------------- ---------------
+compiled-in aliases set up aliases in .bashrc; some ksh aliases are
+ bash builtins (hash, history, type)
+coprocesses named pipe pairs (one for read, one for write)
+typeset +f declare -F
+cd, print, whence function substitutes in examples/functions/kshenv
+autoloaded functions examples/functions/autoload is the same as typeset -fu
+read var?prompt read -p prompt var
+
+ksh-93 feature Bash equivalent
+-------------- ---------------
+sleep, getconf Bash has loadable versions in examples/loadables
+${.sh.version} $BASH_VERSION
+print -f printf
+hist alias hist=fc
+$HISTEDIT $FCEDIT
+
+Section E: How can I get bash to do certain things, and why does bash do
+ things the way it does?
+
+E1) Why is the bash builtin `test' slightly different from /bin/test?
+
+The specific example used here is [ ! x -o x ], which is false.
+
+Bash's builtin `test' implements the Posix.2 spec, which can be
+summarized as follows (the wording is due to David Korn):
+
+Here is the set of rules for processing test arguments.
+
+ 0 Args: False
+ 1 Arg: True iff argument is not null.
+ 2 Args: If first arg is !, True iff second argument is null.
+ If first argument is unary, then true if unary test is true
+ Otherwise error.
+ 3 Args: If second argument is a binary operator, do binary test of $1 $3
+ If first argument is !, negate two argument test of $2 $3
+ If first argument is `(' and third argument is `)', do the
+ one-argument test of the second argument.
+ Otherwise error.
+ 4 Args: If first argument is !, negate three argument test of $2 $3 $4.
+ Otherwise unspecified
+ 5 or more Args: unspecified. (Historical shells would use their
+ current algorithm).
+
+The operators -a and -o are considered binary operators for the purpose
+of the 3 Arg case.
+
+As you can see, the test becomes (not (x or x)), which is false.
+
+E2) Why does bash sometimes say `Broken pipe'?
+
+If a sequence of commands appears in a pipeline, and one of the
+reading commands finishes before the writer has finished, the
+writer receives a SIGPIPE signal. Many other shells special-case
+SIGPIPE as an exit status in the pipeline and do not report it.
+For example, in:
+
+ ps -aux | head
+
+`head' can finish before `ps' writes all of its output, and ps
+will try to write on a pipe without a reader. In that case, bash
+will print `Broken pipe' to stderr when ps is killed by a
+SIGPIPE.
+
+As of bash-3.1, bash will not report SIGPIPE errors by default. You
+can build a version of bash that will report such errors.
+
+E3) When I have terminal escape sequences in my prompt, why does bash
+ wrap lines at the wrong column?
+
+Readline, the line editing library that bash uses, does not know
+that the terminal escape sequences do not take up space on the
+screen. The redisplay code assumes, unless told otherwise, that
+each character in the prompt is a `printable' character that
+takes up one character position on the screen.
+
+You can use the bash prompt expansion facility (see the PROMPTING
+section in the manual page) to tell readline that sequences of
+characters in the prompt strings take up no screen space.
+
+Use the \[ escape to begin a sequence of non-printing characters,
+and the \] escape to signal the end of such a sequence.
+
+E4) If I pipe the output of a command into `read variable', why doesn't
+ the output show up in $variable when the read command finishes?
+
+This has to do with the parent-child relationship between Unix
+processes. It affects all commands run in pipelines, not just
+simple calls to `read'. For example, piping a command's output
+into a `while' loop that repeatedly calls `read' will result in
+the same behavior.
+
+Each element of a pipeline, even a builtin or shell function,
+runs in a separate process, a child of the shell running the
+pipeline. A subprocess cannot affect its parent's environment.
+When the `read' command sets the variable to the input, that
+variable is set only in the subshell, not the parent shell. When
+the subshell exits, the value of the variable is lost.
+
+Many pipelines that end with `read variable' can be converted
+into command substitutions, which will capture the output of
+a specified command. The output can then be assigned to a
+variable:
+
+ grep ^gnu /usr/lib/news/active | wc -l | read ngroup
+
+can be converted into
+
+ ngroup=$(grep ^gnu /usr/lib/news/active | wc -l)
+
+This does not, unfortunately, work to split the text among
+multiple variables, as read does when given multiple variable
+arguments. If you need to do this, you can either use the
+command substitution above to read the output into a variable
+and chop up the variable using the bash pattern removal
+expansion operators or use some variant of the following
+approach.
+
+Say /usr/local/bin/ipaddr is the following shell script:
+
+#! /bin/sh
+host `hostname` | awk '/address/ {print $NF}'
+
+Instead of using
+
+ /usr/local/bin/ipaddr | read A B C D
+
+to break the local machine's IP address into separate octets, use
+
+ OIFS="$IFS"
+ IFS=.
+ set -- $(/usr/local/bin/ipaddr)
+ IFS="$OIFS"
+ A="$1" B="$2" C="$3" D="$4"
+
+Beware, however, that this will change the shell's positional
+parameters. If you need them, you should save them before doing
+this.
+
+This is the general approach -- in most cases you will not need to
+set $IFS to a different value.
+
+Some other user-supplied alternatives include:
+
+read A B C D << HERE
+ $(IFS=.; echo $(/usr/local/bin/ipaddr))
+HERE
+
+and, where process substitution is available,
+
+read A B C D < <(IFS=.; echo $(/usr/local/bin/ipaddr))
+
+E5) I have a bunch of shell scripts that use backslash-escaped characters
+ in arguments to `echo'. Bash doesn't interpret these characters. Why
+ not, and how can I make it understand them?
+
+This is the behavior of echo on most Unix System V machines.
+
+The bash builtin `echo' is modeled after the 9th Edition
+Research Unix version of `echo'. It does not interpret
+backslash-escaped characters in its argument strings by default;
+it requires the use of the -e option to enable the
+interpretation. The System V echo provides no way to disable the
+special characters; the bash echo has a -E option to disable
+them.
+
+There is a configuration option that will make bash behave like
+the System V echo and interpret things like `\t' by default. Run
+configure with the --enable-xpg-echo-default option to turn this
+on. Be aware that this will cause some of the tests run when you
+type `make tests' to fail.
+
+There is a shell option, `xpg_echo', settable with `shopt', that will
+change the behavior of echo at runtime. Enabling this option turns
+on expansion of backslash-escape sequences.
+
+E6) Why doesn't a while or for loop get suspended when I type ^Z?
+
+This is a consequence of how job control works on Unix. The only
+thing that can be suspended is the process group. This is a single
+command or pipeline of commands that the shell forks and executes.
+
+When you run a while or for loop, the only thing that the shell forks
+and executes are any commands in the while loop test and commands in
+the loop bodies. These, therefore, are the only things that can be
+suspended when you type ^Z.
+
+If you want to be able to stop the entire loop, you need to put it
+within parentheses, which will force the loop into a subshell that
+may be stopped (and subsequently restarted) as a single unit.
+
+E7) What about empty for loops in Makefiles?
+
+It's fairly common to see constructs like this in automatically-generated
+Makefiles:
+
+SUBDIRS = @SUBDIRS@
+
+ ...
+
+subdirs-clean:
+ for d in ${SUBDIRS}; do \
+ ( cd $$d && ${MAKE} ${MFLAGS} clean ) \
+ done
+
+When SUBDIRS is empty, this results in a command like this being passed to
+bash:
+
+ for d in ; do
+ ( cd $d && ${MAKE} ${MFLAGS} clean )
+ done
+
+In versions of bash before bash-2.05a, this was a syntax error. If the
+reserved word `in' was present, a word must follow it before the semicolon
+or newline. The language in the manual page referring to the list of words
+being empty referred to the list after it is expanded. These versions of
+bash required that there be at least one word following the `in' when the
+construct was parsed.
+
+The idiomatic Makefile solution is something like:
+
+SUBDIRS = @SUBDIRS@
+
+subdirs-clean:
+ subdirs=$SUBDIRS ; for d in $$subdirs; do \
+ ( cd $$d && ${MAKE} ${MFLAGS} clean ) \
+ done
+
+The latest updated POSIX standard has changed this: the word list
+is no longer required. Bash versions 2.05a and later accept the
+new syntax.
+
+E8) Why does the arithmetic evaluation code complain about `08'?
+
+The bash arithmetic evaluation code (used for `let', $(()), (()), and in
+other places), interprets a leading `0' in numeric constants as denoting
+an octal number, and a leading `0x' as denoting hexadecimal. This is
+in accordance with the POSIX.2 spec, section 2.9.2.1, which states that
+arithmetic constants should be handled as signed long integers as defined
+by the ANSI/ISO C standard.
+
+The POSIX.2 interpretation committee has confirmed this:
+
+http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-173.html
+
+E9) Why does the pattern matching expression [A-Z]* match files beginning
+ with every letter except `z'?
+
+Bash-2.03, Bash-2.05 and later versions honor the current locale setting
+when processing ranges within pattern matching bracket expressions ([A-Z]).
+This is what POSIX.2 and SUSv3/XPG6 specify.
+
+The behavior of the matcher in bash-2.05 and later versions depends on the
+current LC_COLLATE setting. Setting this variable to `C' or `POSIX' will
+result in the traditional behavior ([A-Z] matches all uppercase ASCII
+characters). Many other locales, including the en_US locale (the default
+on many US versions of Linux) collate the upper and lower case letters like
+this:
+
+ AaBb...Zz
+
+which means that [A-Z] matches every letter except `z'. Others 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). If you have locale(1), you can use it to find
+your current locale information even if you do not have any of the
+LC_ variables set.
+
+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.
+
+E10) Why does `cd //' leave $PWD as `//'?
+
+POSIX.2, in its description of `cd', says that *three* or more leading
+slashes may be replaced with a single slash when canonicalizing the
+current working directory.
+
+This is, I presume, for historical compatibility. Certain versions of
+Unix, and early network file systems, used paths of the form
+//hostname/path to access `path' on server `hostname'.
+
+E11) If I resize my xterm while another program is running, why doesn't bash
+ notice the change?
+
+This is another issue that deals with job control.
+
+The kernel maintains a notion of a current terminal process group. Members
+of this process group (processes whose process group ID is equal to the
+current terminal process group ID) receive terminal-generated signals like
+SIGWINCH. (For more details, see the JOB CONTROL section of the bash
+man page.)
+
+If a terminal is resized, the kernel sends SIGWINCH to each member of
+the terminal's current process group (the `foreground' process group).
+
+When bash is running with job control enabled, each pipeline (which may be
+a single command) is run in its own process group, different from bash's
+process group. This foreground process group receives the SIGWINCH; bash
+does not. Bash has no way of knowing that the terminal has been resized.
+
+There is a `checkwinsize' option, settable with the `shopt' builtin, that
+will cause bash to check the window size and adjust its idea of the
+terminal's dimensions each time a process stops or exits and returns control
+of the terminal to bash. Enable it with `shopt -s checkwinsize'.
+
+E12) Why don't negative offsets in substring expansion work like I expect?
+
+When substring expansion of the form ${param:offset[:length} is used,
+an `offset' that evaluates to a number less than zero counts back from
+the end of the expanded value of $param.
+
+When a negative `offset' begins with a minus sign, however, unexpected things
+can happen. Consider
+
+ a=12345678
+ echo ${a:-4}
+
+intending to print the last four characters of $a. The problem is that
+${param:-word} already has a well-defined meaning: expand to word if the
+expanded value of param is unset or null, and $param otherwise.
+
+To use negative offsets that begin with a minus sign, separate the
+minus sign and the colon with a space.
+
+Section F: Things to watch out for on certain Unix versions
+
+F1) Why can't I use command line editing in my `cmdtool'?
+
+The problem is `cmdtool' and bash fighting over the input. When
+scrolling is enabled in a cmdtool window, cmdtool puts the tty in
+`raw mode' to permit command-line editing using the mouse for
+applications that cannot do it themselves. As a result, bash and
+cmdtool each try to read keyboard input immediately, with neither
+getting enough of it to be useful.
+
+This mode also causes cmdtool to not implement many of the
+terminal functions and control sequences appearing in the
+`sun-cmd' termcap entry. For a more complete explanation, see
+that file examples/suncmd.termcap in the bash distribution.
+
+`xterm' is a better choice, and gets along with bash much more
+smoothly.
+
+If you must use cmdtool, you can use the termcap description in
+examples/suncmd.termcap. Set the TERMCAP variable to the terminal
+description contained in that file, i.e.
+
+TERMCAP='Mu|sun-cmd:am:bs:km:pt:li#34:co#80:cl=^L:ce=\E[K:cd=\E[J:rs=\E[s:'
+
+Then export TERMCAP and start a new cmdtool window from that shell.
+The bash command-line editing should behave better in the new
+cmdtool. If this works, you can put the assignment to TERMCAP
+in your bashrc file.
+
+F2) I built bash on Solaris 2. Why do globbing expansions and filename
+ completion chop off the first few characters of each filename?
+
+This is the consequence of building bash on SunOS 5 and linking
+with the libraries in /usr/ucblib, but using the definitions
+and structures from files in /usr/include.
+
+The actual conflict is between the dirent structure in
+/usr/include/dirent.h and the struct returned by the version of
+`readdir' in libucb.a (a 4.3-BSD style `struct direct').
+
+Make sure you've got /usr/ccs/bin ahead of /usr/ucb in your $PATH
+when configuring and building bash. This will ensure that you
+use /usr/ccs/bin/cc or acc instead of /usr/ucb/cc and that you
+link with libc before libucb.
+
+If you have installed the Sun C compiler, you may also need to
+put /usr/ccs/bin and /opt/SUNWspro/bin into your $PATH before
+/usr/ucb.
+
+F3) Why does bash dump core after I interrupt username completion or
+ `~user' tilde expansion on a machine running NIS?
+
+This is a famous and long-standing bug in the SunOS YP (sorry, NIS)
+client library, which is part of libc.
+
+The YP library code keeps static state -- a pointer into the data
+returned from the server. When YP initializes itself (setpwent),
+it looks at this pointer and calls free on it if it's non-null.
+So far, so good.
+
+If one of the YP functions is interrupted during getpwent (the
+exact function is interpretwithsave()), and returns NULL, the
+pointer is freed without being reset to NULL, and the function
+returns. The next time getpwent is called, it sees that this
+pointer is non-null, calls free, and the bash free() blows up
+because it's being asked to free freed memory.
+
+The traditional Unix mallocs allow memory to be freed multiple
+times; that's probably why this has never been fixed. You can
+run configure with the `--without-gnu-malloc' option to use
+the C library malloc and avoid the problem.
+
+F4) I'm running SVR4.2. Why is the line erased every time I type `@'?
+
+The `@' character is the default `line kill' character in most
+versions of System V, including SVR4.2. You can change this
+character to whatever you want using `stty'. For example, to
+change the line kill character to control-u, type
+
+ stty kill ^U
+
+where the `^' and `U' can be two separate characters.
+
+F5) Why does bash report syntax errors when my C News scripts use a
+ redirection before a subshell command?
+
+The actual command in question is something like
+
+ < file ( command )
+
+According to the grammar given in the POSIX.2 standard, this construct
+is, in fact, a syntax error. Redirections may only precede `simple
+commands'. A subshell construct such as the above is one of the shell's
+`compound commands'. A redirection may only follow a compound command.
+
+This affects the mechanical transformation of commands that use `cat'
+to pipe a file into a command (a favorite Useless-Use-Of-Cat topic on
+comp.unix.shell). While most commands of the form
+
+ cat file | command
+
+can be converted to `< file command', shell control structures such as
+loops and subshells require `command < file'.
+
+The file CWRU/sh-redir-hack in the bash distribution is an
+(unofficial) patch to parse.y that will modify the grammar to
+support this construct. It will not apply with `patch'; you must
+modify parse.y by hand. Note that if you apply this, you must
+recompile with -DREDIRECTION_HACK. This introduces a large
+number of reduce/reduce conflicts into the shell grammar.
+
+F6) Why can't I use vi-mode editing on Red Hat Linux 6.1?
+
+The short answer is that Red Hat screwed up.
+
+The long answer is that they shipped an /etc/inputrc that only works
+for emacs mode editing, and then screwed all the vi users by setting
+INPUTRC to /etc/inputrc in /etc/profile.
+
+The short fix is to do one of the following: remove or rename
+/etc/inputrc, set INPUTRC=~/.inputrc in ~/.bashrc (or .bash_profile,
+but make sure you export it if you do), remove the assignment to
+INPUTRC from /etc/profile, add
+
+ set keymap emacs
+
+to the beginning of /etc/inputrc, or bracket the key bindings in
+/etc/inputrc with these lines
+
+ $if mode=emacs
+ [...]
+ $endif
+
+F7) Why do bash-2.05a and bash-2.05b fail to compile `printf.def' on
+ HP/UX 11.x?
+
+HP/UX's support for long double is imperfect at best.
+
+GCC will support it without problems, but the HP C library functions
+like strtold(3) and printf(3) don't actually work with long doubles.
+HP implemented a `long_double' type as a 4-element array of 32-bit
+ints, and that is what the library functions use. The ANSI C
+`long double' type is a 128-bit floating point scalar.
+
+The easiest fix, until HP fixes things up, is to edit the generated
+config.h and #undef the HAVE_LONG_DOUBLE line. After doing that,
+the compilation should complete successfully.
+
+Section G: How can I get bash to do certain common things?
+
+G1) How can I get bash to read and display eight-bit characters?
+
+This is a process requiring several steps.
+
+First, you must ensure that the `physical' data path is a full eight
+bits. For xterms, for example, the `vt100' resources `eightBitInput'
+and `eightBitOutput' should be set to `true'.
+
+Once you have set up an eight-bit path, you must tell the kernel and
+tty driver to leave the eighth bit of characters alone when processing
+keyboard input. Use `stty' to do this:
+
+ stty cs8 -istrip -parenb
+
+For old BSD-style systems, you can use
+
+ stty pass8
+
+You may also need
+
+ stty even odd
+
+Finally, you need to tell readline that you will be inputting and
+displaying eight-bit characters. You use readline variables to do
+this. These variables can be set in your .inputrc or using the bash
+`bind' builtin. Here's an example using `bind':
+
+ bash$ bind 'set convert-meta off'
+ bash$ bind 'set meta-flag on'
+ bash$ bind 'set output-meta on'
+
+The `set' commands between the single quotes may also be placed
+in ~/.inputrc.
+
+G2) How do I write a function `x' to replace builtin command `x', but
+ still invoke the command from within the function?
+
+This is why the `command' and `builtin' builtins exist. The
+`command' builtin executes the command supplied as its first
+argument, skipping over any function defined with that name. The
+`builtin' builtin executes the builtin command given as its first
+argument directly.
+
+For example, to write a function to replace `cd' that writes the
+hostname and current directory to an xterm title bar, use
+something like the following:
+
+ cd()
+ {
+ builtin cd "$@" && xtitle "$HOST: $PWD"
+ }
+
+This could also be written using `command' instead of `builtin';
+the version above is marginally more efficient.
+
+G3) How can I find the value of a shell variable whose name is the value
+ of another shell variable?
+
+Versions of Bash newer than Bash-2.0 support this directly. You can use
+
+ ${!var}
+
+For example, the following sequence of commands will echo `z':
+
+ var1=var2
+ var2=z
+ echo ${!var1}
+
+For sh compatibility, use the `eval' builtin. The important
+thing to remember is that `eval' expands the arguments you give
+it again, so you need to quote the parts of the arguments that
+you want `eval' to act on.
+
+For example, this expression prints the value of the last positional
+parameter:
+
+ eval echo \"\$\{$#\}\"
+
+The expansion of the quoted portions of this expression will be
+deferred until `eval' runs, while the `$#' will be expanded
+before `eval' is executed. In versions of bash later than bash-2.0,
+
+ echo ${!#}
+
+does the same thing.
+
+This is not the same thing as ksh93 `nameref' variables, though the syntax
+is similar. I may add namerefs in a future bash version.
+
+G4) How can I make the bash `time' reserved word print timing output that
+ looks like the output from my system's /usr/bin/time?
+
+The bash command timing code looks for a variable `TIMEFORMAT' and
+uses its value as a format string to decide how to display the
+timing statistics.
+
+The value of TIMEFORMAT is a string with `%' escapes expanded in a
+fashion similar in spirit to printf(3). The manual page explains
+the meanings of the escape sequences in the format string.
+
+If TIMEFORMAT is not set, bash acts as if the following assignment had
+been performed:
+
+ TIMEFORMAT=$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'
+
+The POSIX.2 default time format (used by `time -p command') is
+
+ TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S'
+
+The BSD /usr/bin/time format can be emulated with:
+
+ TIMEFORMAT=$'\t%1R real\t%1U user\t%1S sys'
+
+The System V /usr/bin/time format can be emulated with:
+
+ TIMEFORMAT=$'\nreal\t%1R\nuser\t%1U\nsys\t%1S'
+
+The ksh format can be emulated with:
+
+ TIMEFORMAT=$'\nreal\t%2lR\nuser\t%2lU\nsys\t%2lS'
+
+G5) How do I get the current directory into my prompt?
+
+Bash provides a number of backslash-escape sequences which are expanded
+when the prompt string (PS1 or PS2) is displayed. The full list is in
+the manual page.
+
+The \w expansion gives the full pathname of the current directory, with
+a tilde (`~') substituted for the current value of $HOME. The \W
+expansion gives the basename of the current directory. To put the full
+pathname of the current directory into the path without any tilde
+subsitution, use $PWD. Here are some examples:
+
+ PS1='\w$ ' # current directory with tilde
+ PS1='\W$ ' # basename of current directory
+ PS1='$PWD$ ' # full pathname of current directory
+
+The single quotes are important in the final example to prevent $PWD from
+being expanded when the assignment to PS1 is performed.
+
+G6) How can I rename "*.foo" to "*.bar"?
+
+Use the pattern removal functionality described in D3. The following `for'
+loop will do the trick:
+
+ for f in *.foo; do
+ mv $f ${f%foo}bar
+ done
+
+G7) How can I translate a filename from uppercase to lowercase?
+
+The script examples/functions/lowercase, originally written by John DuBois,
+will do the trick. The converse is left as an exercise.
+
+G8) How can I write a filename expansion (globbing) pattern that will match
+ all files in the current directory except "." and ".."?
+
+You must have set the `extglob' shell option using `shopt -s extglob' to use
+this:
+
+ echo .!(.|) *
+
+A solution that works without extended globbing is given in the Unix Shell
+FAQ, posted periodically to comp.unix.shell.
+
+Section H: Where do I go from here?
+
+H1) How do I report bugs in bash, and where should I look for fixes and
+ advice?
+
+Use the `bashbug' script to report bugs. It is built and
+installed at the same time as bash. It provides a standard
+template for reporting a problem and automatically includes
+information about your configuration and build environment.
+
+`bashbug' sends its reports to bug-bash@gnu.org, which
+is a large mailing list gatewayed to the usenet newsgroup gnu.bash.bug.
+
+Bug fixes, answers to questions, and announcements of new releases
+are all posted to gnu.bash.bug. Discussions concerning bash features
+and problems also take place there.
+
+To reach the bash maintainers directly, send mail to
+bash-maintainers@gnu.org.
+
+H2) What kind of bash documentation is there?
+
+First, look in the doc directory in the bash distribution. It should
+contain at least the following files:
+
+bash.1 an extensive, thorough Unix-style manual page
+builtins.1 a manual page covering just bash builtin commands
+bashref.texi a reference manual in GNU tex`info format
+bashref.info an info version of the reference manual
+FAQ this file
+article.ms text of an article written for The Linux Journal
+readline.3 a man page describing readline
+
+Postscript, HTML, and ASCII files created from the above source are
+available in the documentation distribution.
+
+There is additional documentation available for anonymous FTP from host
+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
+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
+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.
+
+Rocky Bernstein's bash debugger (support is included with bash-3.0)
+associative arrays
+co-processes, but with a new-style syntax that looks like function declaration
+
+H4) What's on the bash `wish list' for future versions?
+
+These are features that may or may not appear in a future version of bash.
+
+breaking some of the shell functionality into embeddable libraries
+a module system like zsh's, using dynamic loading like builtins
+a bash programmer's guide with a chapter on creating loadable builtins
+a better loadable interface to perl with access to the shell builtins and
+ variables (contributions gratefully accepted)
+ksh93-like `nameref' variables
+ksh93-like `xx.yy' variables (including some of the .sh.* variables) and
+ associated disipline functions
+Some of the new ksh93 pattern matching operators, like backreferencing
+
+H5) When will the next release appear?
+
+The next version will appear sometime in 2006. Never make predictions.
+
+This document is Copyright 1995-2005 by Chester Ramey.
+
+Permission is hereby granted, without written agreement and
+without license or royalty fees, to use, copy, and distribute
+this document for any purpose, provided that the above copyright
+notice appears in all copies of this document and that the
+contents of this document remain unaltered.
diff --git a/doc/bash.1 b/doc/bash.1
index 5ff7a598..9de04a74 100644
--- a/doc/bash.1
+++ b/doc/bash.1
@@ -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
diff --git a/doc/bash.1~ b/doc/bash.1~
index 796c1fc6..84065f2b 100644
--- a/doc/bash.1~
+++ b/doc/bash.1~
@@ -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
diff --git a/doc/bashref.texi b/doc/bashref.texi
index a144572c..de2cfcc3 100644
--- a/doc/bashref.texi
+++ b/doc/bashref.texi
@@ -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
diff --git a/doc/bashref.texi~ b/doc/bashref.texi~
index b25dad91..93d56c81 100644
--- a/doc/bashref.texi~
+++ b/doc/bashref.texi~
@@ -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;
diff --git a/doc/rose94.pdf b/doc/rose94.pdf
index f5ce80d3..1772f543 100644
--- a/doc/rose94.pdf
+++ b/doc/rose94.pdf
Binary files differ
diff --git a/doc/version.texi b/doc/version.texi
index 7c7684d7..6ee00d42 100644
--- a/doc/version.texi
+++ b/doc/version.texi
@@ -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
diff --git a/doc/version.texi~ b/doc/version.texi~
index 2b1db7ec..ab97188c 100644
--- a/doc/version.texi~
+++ b/doc/version.texi~
@@ -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
diff --git a/execute_cmd.c b/execute_cmd.c
index b7a6e7c8..b7b56712 100644
--- a/execute_cmd.c
+++ b/execute_cmd.c
@@ -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
diff --git a/execute_cmd.c~ b/execute_cmd.c~
index 0afb0bd2..b7a6e7c8 100644
--- a/execute_cmd.c~
+++ b/execute_cmd.c~
@@ -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);
diff --git a/expr.c b/expr.c
index 7f9a2f18..418f48d0 100644
--- a/expr.c
+++ b/expr.c
@@ -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;
}
diff --git a/expr.c~ b/expr.c~
new file mode 100644
index 00000000..ed00c845
--- /dev/null
+++ b/expr.c~
@@ -0,0 +1,1348 @@
+/* expr.c -- arithmetic expression evaluation. */
+
+/* Copyright (C) 1990-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. */
+
+/*
+ All arithmetic is done as intmax_t integers with no checking for overflow
+ (though division by 0 is caught and flagged as an error).
+
+ The following operators are handled, grouped into a set of levels in
+ order of decreasing precedence.
+
+ "id++", "id--" [post-increment and post-decrement]
+ "++id", "--id" [pre-increment and pre-decrement]
+ "-", "+" [(unary operators)]
+ "!", "~"
+ "**" [(exponentiation)]
+ "*", "/", "%"
+ "+", "-"
+ "<<", ">>"
+ "<=", ">=", "<", ">"
+ "==", "!="
+ "&"
+ "^"
+ "|"
+ "&&"
+ "||"
+ "expr ? expr : expr"
+ "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|="
+ , [comma]
+
+ (Note that most of these operators have special meaning to bash, and an
+ entire expression should be quoted, e.g. "a=$a+1" or "a=a+1" to ensure
+ that it is passed intact to the evaluator when using `let'. When using
+ the $[] or $(( )) forms, the text between the `[' and `]' or `((' and `))'
+ is treated as if in double quotes.)
+
+ Sub-expressions within parentheses have a precedence level greater than
+ all of the above levels and are evaluated first. Within a single prece-
+ dence group, evaluation is left-to-right, except for the arithmetic
+ assignment operator (`='), which is evaluated right-to-left (as in C).
+
+ The expression evaluator returns the value of the expression (assignment
+ statements have as a value what is returned by the RHS). The `let'
+ builtin, on the other hand, returns 0 if the last expression evaluates to
+ a non-zero, and 1 otherwise.
+
+ Implementation is a recursive-descent parser.
+
+ Chet Ramey
+ chet@ins.CWRU.Edu
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include "bashansi.h"
+
+#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#include "chartypes.h"
+#include "bashintl.h"
+
+#include "shell.h"
+
+/* Because of the $((...)) construct, expressions may include newlines.
+ Here is a macro which accepts newlines, tabs and spaces as whitespace. */
+#define cr_whitespace(c) (whitespace(c) || ((c) == '\n'))
+
+/* Size be which the expression stack grows when neccessary. */
+#define EXPR_STACK_GROW_SIZE 10
+
+/* Maximum amount of recursion allowed. This prevents a non-integer
+ variable such as "num=num+2" from infinitely adding to itself when
+ "let num=num+2" is given. */
+#define MAX_EXPR_RECURSION_LEVEL 1024
+
+/* The Tokens. Singing "The Lion Sleeps Tonight". */
+
+#define EQEQ 1 /* "==" */
+#define NEQ 2 /* "!=" */
+#define LEQ 3 /* "<=" */
+#define GEQ 4 /* ">=" */
+#define STR 5 /* string */
+#define NUM 6 /* number */
+#define LAND 7 /* "&&" Logical AND */
+#define LOR 8 /* "||" Logical OR */
+#define LSH 9 /* "<<" Left SHift */
+#define RSH 10 /* ">>" Right SHift */
+#define OP_ASSIGN 11 /* op= expassign as in Posix.2 */
+#define COND 12 /* exp1 ? exp2 : exp3 */
+#define POWER 13 /* exp1**exp2 */
+#define PREINC 14 /* ++var */
+#define PREDEC 15 /* --var */
+#define POSTINC 16 /* var++ */
+#define POSTDEC 17 /* var-- */
+#define EQ '='
+#define GT '>'
+#define LT '<'
+#define PLUS '+'
+#define MINUS '-'
+#define MUL '*'
+#define DIV '/'
+#define MOD '%'
+#define NOT '!'
+#define LPAR '('
+#define RPAR ')'
+#define BAND '&' /* Bitwise AND */
+#define BOR '|' /* Bitwise OR. */
+#define BXOR '^' /* Bitwise eXclusive OR. */
+#define BNOT '~' /* Bitwise NOT; Two's complement. */
+#define QUES '?'
+#define COL ':'
+#define COMMA ','
+
+/* This should be the function corresponding to the operator with the
+ highest precedence. */
+#define EXP_HIGHEST expcomma
+
+static char *expression; /* The current expression */
+static char *tp; /* token lexical position */
+static char *lasttp; /* pointer to last token position */
+static int curtok; /* the current token */
+static int lasttok; /* the previous token */
+static int assigntok; /* the OP in OP= */
+static char *tokstr; /* current token string */
+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));
+static intmax_t strlong __P((char *));
+static void evalerror __P((char *));
+
+static void pushexp __P((void));
+static void popexp __P((void));
+static void expr_unwind __P((void));
+static void expr_bind_variable __P((char *, char *));
+
+static intmax_t subexpr __P((char *));
+
+static intmax_t expcomma __P((void));
+static intmax_t expassign __P((void));
+static intmax_t expcond __P((void));
+static intmax_t explor __P((void));
+static intmax_t expland __P((void));
+static intmax_t expbor __P((void));
+static intmax_t expbxor __P((void));
+static intmax_t expband __P((void));
+static intmax_t exp5 __P((void));
+static intmax_t exp4 __P((void));
+static intmax_t expshift __P((void));
+static intmax_t exp3 __P((void));
+static intmax_t exp2 __P((void));
+static intmax_t exppower __P((void));
+static intmax_t exp1 __P((void));
+static intmax_t exp0 __P((void));
+
+/* A structure defining a single expression context. */
+typedef struct {
+ int curtok, lasttok;
+ char *expression, *tp, *lasttp;
+ intmax_t tokval;
+ char *tokstr;
+ int noeval;
+} EXPR_CONTEXT;
+
+#ifdef INCLUDE_UNUSED
+/* Not used yet. */
+typedef struct {
+ char *tokstr;
+ intmax_t tokval;
+} LVALUE;
+#endif
+
+/* Global var which contains the stack of expression contexts. */
+static EXPR_CONTEXT **expr_stack;
+static int expr_depth; /* Location in the stack. */
+static int expr_stack_size; /* Number of slots already allocated. */
+
+extern char *this_command_name;
+extern int unbound_vars_is_error;
+
+#if defined (ARRAY_VARS)
+extern char *bash_badsub_errmsg;
+#endif
+
+#define SAVETOK(X) \
+ do { \
+ (X)->curtok = curtok; \
+ (X)->lasttok = lasttok; \
+ (X)->tp = tp; \
+ (X)->lasttp = lasttp; \
+ (X)->tokval = tokval; \
+ (X)->tokstr = tokstr; \
+ (X)->noeval = noeval; \
+ } while (0)
+
+#define RESTORETOK(X) \
+ do { \
+ curtok = (X)->curtok; \
+ lasttok = (X)->lasttok; \
+ tp = (X)->tp; \
+ lasttp = (X)->lasttp; \
+ tokval = (X)->tokval; \
+ tokstr = (X)->tokstr; \
+ noeval = (X)->noeval; \
+ } while (0)
+
+/* Push and save away the contents of the globals describing the
+ current expression context. */
+static void
+pushexp ()
+{
+ EXPR_CONTEXT *context;
+
+ if (expr_depth >= MAX_EXPR_RECURSION_LEVEL)
+ evalerror (_("expression recursion level exceeded"));
+
+ if (expr_depth >= expr_stack_size)
+ {
+ expr_stack_size += EXPR_STACK_GROW_SIZE;
+ expr_stack = (EXPR_CONTEXT **)xrealloc (expr_stack, expr_stack_size * sizeof (EXPR_CONTEXT *));
+ }
+
+ context = (EXPR_CONTEXT *)xmalloc (sizeof (EXPR_CONTEXT));
+
+ context->expression = expression;
+ SAVETOK(context);
+
+ expr_stack[expr_depth++] = context;
+}
+
+/* Pop the the contents of the expression context stack into the
+ globals describing the current expression context. */
+static void
+popexp ()
+{
+ EXPR_CONTEXT *context;
+
+ if (expr_depth == 0)
+ evalerror (_("recursion stack underflow"));
+
+ context = expr_stack[--expr_depth];
+
+ expression = context->expression;
+ RESTORETOK (context);
+
+ free (context);
+}
+
+static void
+expr_unwind ()
+{
+ while (--expr_depth > 0)
+ {
+ if (expr_stack[expr_depth]->tokstr)
+ free (expr_stack[expr_depth]->tokstr);
+
+ if (expr_stack[expr_depth]->expression)
+ free (expr_stack[expr_depth]->expression);
+
+ free (expr_stack[expr_depth]);
+ }
+ free (expr_stack[expr_depth]); /* free the allocated EXPR_CONTEXT */
+}
+
+static void
+expr_bind_variable (lhs, rhs)
+ char *lhs, *rhs;
+{
+ (void)bind_int_variable (lhs, rhs);
+ stupidly_hack_special_variables (lhs);
+}
+
+/* Evaluate EXPR, and return the arithmetic result. If VALIDP is
+ non-null, a zero is stored into the location to which it points
+ if the expression is invalid, non-zero otherwise. If a non-zero
+ value is returned in *VALIDP, the return value of evalexp() may
+ be used.
+
+ The `while' loop after the longjmp is caught relies on the above
+ implementation of pushexp and popexp leaving in expr_stack[0] the
+ values that the variables had when the program started. That is,
+ the first things saved are the initial values of the variables that
+ were assigned at program startup or by the compiler. Therefore, it is
+ safe to let the loop terminate when expr_depth == 0, without freeing up
+ any of the expr_depth[0] stuff. */
+intmax_t
+evalexp (expr, validp)
+ char *expr;
+ int *validp;
+{
+ intmax_t val;
+ int c;
+ procenv_t oevalbuf;
+
+ val = 0;
+
+ FASTCOPY (evalbuf, oevalbuf, sizeof (evalbuf));
+
+ c = setjmp (evalbuf);
+
+ if (c)
+ {
+ FREE (tokstr);
+ FREE (expression);
+ tokstr = expression = (char *)NULL;
+
+ expr_unwind ();
+
+ if (validp)
+ *validp = 0;
+ return (0);
+ }
+
+ val = subexpr (expr);
+
+ if (validp)
+ *validp = 1;
+
+ FASTCOPY (oevalbuf, evalbuf, sizeof (evalbuf));
+
+ return (val);
+}
+
+static intmax_t
+subexpr (expr)
+ char *expr;
+{
+ intmax_t val;
+ char *p;
+
+ for (p = expr; p && *p && cr_whitespace (*p); p++)
+ ;
+
+ if (p == NULL || *p == '\0')
+ return (0);
+
+ pushexp ();
+ curtok = lasttok = 0;
+ expression = savestring (expr);
+ tp = expression;
+
+ tokstr = (char *)NULL;
+ tokval = 0;
+
+ readtok ();
+
+ val = EXP_HIGHEST ();
+
+ if (curtok != 0)
+ evalerror (_("syntax error in expression"));
+
+ FREE (tokstr);
+ FREE (expression);
+
+ popexp ();
+
+ return val;
+}
+
+static intmax_t
+expcomma ()
+{
+ register intmax_t value;
+
+ value = expassign ();
+ while (curtok == COMMA)
+ {
+ readtok ();
+ value = expassign ();
+ }
+
+ return value;
+}
+
+static intmax_t
+expassign ()
+{
+ register intmax_t value;
+ char *lhs, *rhs;
+
+ value = expcond ();
+ if (curtok == EQ || curtok == OP_ASSIGN)
+ {
+ int special, op;
+ intmax_t lvalue;
+
+ special = curtok == OP_ASSIGN;
+
+ if (lasttok != STR)
+ evalerror (_("attempted assignment to non-variable"));
+
+ if (special)
+ {
+ op = assigntok; /* a OP= b */
+ lvalue = value;
+ }
+
+ lhs = savestring (tokstr);
+ readtok ();
+ value = expassign ();
+
+ if (special)
+ {
+ switch (op)
+ {
+ case MUL:
+ lvalue *= value;
+ break;
+ case DIV:
+ if (value == 0)
+ evalerror (_("division by 0"));
+ lvalue /= value;
+ break;
+ case MOD:
+ if (value == 0)
+ evalerror (_("division by 0"));
+ lvalue %= value;
+ break;
+ case PLUS:
+ lvalue += value;
+ break;
+ case MINUS:
+ lvalue -= value;
+ break;
+ case LSH:
+ lvalue <<= value;
+ break;
+ case RSH:
+ lvalue >>= value;
+ break;
+ case BAND:
+ lvalue &= value;
+ break;
+ case BOR:
+ lvalue |= value;
+ break;
+ case BXOR:
+ lvalue ^= value;
+ break;
+ default:
+ free (lhs);
+ evalerror (_("bug: bad expassign token"));
+ break;
+ }
+ value = lvalue;
+ }
+
+ rhs = itos (value);
+ if (noeval == 0)
+ expr_bind_variable (lhs, rhs);
+ free (rhs);
+ free (lhs);
+ FREE (tokstr);
+ tokstr = (char *)NULL; /* For freeing on errors. */
+ }
+ return (value);
+}
+
+/* Conditional expression (expr?expr:expr) */
+static intmax_t
+expcond ()
+{
+ intmax_t cval, val1, val2, rval;
+ int set_noeval;
+
+ set_noeval = 0;
+ rval = cval = explor ();
+ if (curtok == QUES) /* found conditional expr */
+ {
+ readtok ();
+ if (curtok == 0 || curtok == COL)
+ evalerror (_("expression expected"));
+ if (cval == 0)
+ {
+ set_noeval = 1;
+ noeval++;
+ }
+
+ val1 = EXP_HIGHEST ();
+
+ if (set_noeval)
+ noeval--;
+ if (curtok != COL)
+ evalerror (_("`:' expected for conditional expression"));
+ readtok ();
+ if (curtok == 0)
+ evalerror (_("expression expected"));
+ set_noeval = 0;
+ if (cval)
+ {
+ set_noeval = 1;
+ noeval++;
+ }
+ val2 = explor ();
+ if (set_noeval)
+ noeval--;
+ rval = cval ? val1 : val2;
+ lasttok = COND;
+ }
+ return rval;
+}
+
+/* Logical OR. */
+static intmax_t
+explor ()
+{
+ register intmax_t val1, val2;
+ int set_noeval;
+
+ val1 = expland ();
+
+ while (curtok == LOR)
+ {
+ set_noeval = 0;
+ if (val1 != 0)
+ {
+ noeval++;
+ set_noeval = 1;
+ }
+ readtok ();
+ val2 = expland ();
+ if (set_noeval)
+ noeval--;
+ val1 = val1 || val2;
+ lasttok = LOR;
+ }
+
+ return (val1);
+}
+
+/* Logical AND. */
+static intmax_t
+expland ()
+{
+ register intmax_t val1, val2;
+ int set_noeval;
+
+ val1 = expbor ();
+
+ while (curtok == LAND)
+ {
+ set_noeval = 0;
+ if (val1 == 0)
+ {
+ set_noeval = 1;
+ noeval++;
+ }
+ readtok ();
+ val2 = expbor ();
+ if (set_noeval)
+ noeval--;
+ val1 = val1 && val2;
+ lasttok = LAND;
+ }
+
+ return (val1);
+}
+
+/* Bitwise OR. */
+static intmax_t
+expbor ()
+{
+ register intmax_t val1, val2;
+
+ val1 = expbxor ();
+
+ while (curtok == BOR)
+ {
+ readtok ();
+ val2 = expbxor ();
+ val1 = val1 | val2;
+ }
+
+ return (val1);
+}
+
+/* Bitwise XOR. */
+static intmax_t
+expbxor ()
+{
+ register intmax_t val1, val2;
+
+ val1 = expband ();
+
+ while (curtok == BXOR)
+ {
+ readtok ();
+ val2 = expband ();
+ val1 = val1 ^ val2;
+ }
+
+ return (val1);
+}
+
+/* Bitwise AND. */
+static intmax_t
+expband ()
+{
+ register intmax_t val1, val2;
+
+ val1 = exp5 ();
+
+ while (curtok == BAND)
+ {
+ readtok ();
+ val2 = exp5 ();
+ val1 = val1 & val2;
+ }
+
+ return (val1);
+}
+
+static intmax_t
+exp5 ()
+{
+ register intmax_t val1, val2;
+
+ val1 = exp4 ();
+
+ while ((curtok == EQEQ) || (curtok == NEQ))
+ {
+ int op = curtok;
+
+ readtok ();
+ val2 = exp4 ();
+ if (op == EQEQ)
+ val1 = (val1 == val2);
+ else if (op == NEQ)
+ val1 = (val1 != val2);
+ }
+ return (val1);
+}
+
+static intmax_t
+exp4 ()
+{
+ register intmax_t val1, val2;
+
+ val1 = expshift ();
+ while ((curtok == LEQ) ||
+ (curtok == GEQ) ||
+ (curtok == LT) ||
+ (curtok == GT))
+ {
+ int op = curtok;
+
+ readtok ();
+ val2 = expshift ();
+
+ if (op == LEQ)
+ val1 = val1 <= val2;
+ else if (op == GEQ)
+ val1 = val1 >= val2;
+ else if (op == LT)
+ val1 = val1 < val2;
+ else /* (op == GT) */
+ val1 = val1 > val2;
+ }
+ return (val1);
+}
+
+/* Left and right shifts. */
+static intmax_t
+expshift ()
+{
+ register intmax_t val1, val2;
+
+ val1 = exp3 ();
+
+ while ((curtok == LSH) || (curtok == RSH))
+ {
+ int op = curtok;
+
+ readtok ();
+ val2 = exp3 ();
+
+ if (op == LSH)
+ val1 = val1 << val2;
+ else
+ val1 = val1 >> val2;
+ }
+
+ return (val1);
+}
+
+static intmax_t
+exp3 ()
+{
+ register intmax_t val1, val2;
+
+ val1 = exp2 ();
+
+ while ((curtok == PLUS) || (curtok == MINUS))
+ {
+ int op = curtok;
+
+ readtok ();
+ val2 = exp2 ();
+
+ if (op == PLUS)
+ val1 += val2;
+ else if (op == MINUS)
+ val1 -= val2;
+ }
+ return (val1);
+}
+
+static intmax_t
+exp2 ()
+{
+ register intmax_t val1, val2;
+
+ val1 = exppower ();
+
+ while ((curtok == MUL) ||
+ (curtok == DIV) ||
+ (curtok == MOD))
+ {
+ int op = curtok;
+
+ readtok ();
+
+ val2 = exppower ();
+
+ if (((op == DIV) || (op == MOD)) && (val2 == 0))
+ evalerror (_("division by 0"));
+
+ if (op == MUL)
+ val1 *= val2;
+ else if (op == DIV)
+ val1 /= val2;
+ else if (op == MOD)
+ val1 %= val2;
+ }
+ return (val1);
+}
+
+static intmax_t
+exppower ()
+{
+ register intmax_t val1, val2, c;
+
+ val1 = exp1 ();
+ while (curtok == POWER)
+ {
+ readtok ();
+ val2 = exppower (); /* exponentiation is right-associative */
+ if (val2 == 0)
+ return (1);
+ if (val2 < 0)
+ evalerror (_("exponent less than 0"));
+ for (c = 1; val2--; c *= val1)
+ ;
+ val1 = c;
+ }
+ return (val1);
+}
+
+static intmax_t
+exp1 ()
+{
+ register intmax_t val;
+
+ if (curtok == NOT)
+ {
+ readtok ();
+ val = !exp1 ();
+ }
+ else if (curtok == BNOT)
+ {
+ readtok ();
+ val = ~exp1 ();
+ }
+ else
+ val = exp0 ();
+
+ return (val);
+}
+
+static intmax_t
+exp0 ()
+{
+ register intmax_t val = 0, v2;
+ char *vincdec;
+ int stok;
+ EXPR_CONTEXT ec;
+
+ /* XXX - might need additional logic here to decide whether or not
+ pre-increment or pre-decrement is legal at this point. */
+ if (curtok == PREINC || curtok == PREDEC)
+ {
+ stok = lasttok = curtok;
+ readtok ();
+ if (curtok != STR)
+ /* readtok() catches this */
+ evalerror (_("identifier expected after pre-increment or pre-decrement"));
+
+ v2 = tokval + ((stok == PREINC) ? 1 : -1);
+ vincdec = itos (v2);
+ if (noeval == 0)
+ expr_bind_variable (tokstr, vincdec);
+ free (vincdec);
+ val = v2;
+
+ curtok = NUM; /* make sure --x=7 is flagged as an error */
+ readtok ();
+ }
+ else if (curtok == MINUS)
+ {
+ readtok ();
+ val = - exp0 ();
+ }
+ else if (curtok == PLUS)
+ {
+ readtok ();
+ val = exp0 ();
+ }
+ else if (curtok == LPAR)
+ {
+ readtok ();
+ val = EXP_HIGHEST ();
+
+ if (curtok != RPAR) /* ( */
+ evalerror (_("missing `)'"));
+
+ /* Skip over closing paren. */
+ readtok ();
+ }
+ else if ((curtok == NUM) || (curtok == STR))
+ {
+ val = tokval;
+ if (curtok == STR)
+ {
+ SAVETOK (&ec);
+ tokstr = (char *)NULL; /* keep it from being freed */
+ noeval = 1;
+ readtok ();
+ stok = curtok;
+
+ /* post-increment or post-decrement */
+ if (stok == POSTINC || stok == POSTDEC)
+ {
+ /* restore certain portions of EC */
+ tokstr = ec.tokstr;
+ noeval = ec.noeval;
+ lasttok = STR; /* ec.curtok */
+
+ v2 = val + ((stok == POSTINC) ? 1 : -1);
+ vincdec = itos (v2);
+ if (noeval == 0)
+ expr_bind_variable (tokstr, vincdec);
+ free (vincdec);
+ curtok = NUM; /* make sure x++=7 is flagged as an error */
+ }
+ else
+ {
+ if (stok == STR) /* free new tokstr before old one is restored */
+ FREE (tokstr);
+ RESTORETOK (&ec);
+ }
+
+ }
+
+ readtok ();
+ }
+ else
+ evalerror (_("syntax error: operand expected"));
+
+ return (val);
+}
+
+static intmax_t
+expr_streval (tok, e)
+ char *tok;
+ int e;
+{
+ SHELL_VAR *v;
+ char *value;
+ intmax_t tval;
+
+ /* [[[[[ */
+#if defined (ARRAY_VARS)
+ v = (e == ']') ? array_variable_part (tok, (char **)0, (int *)0) : find_variable (tok);
+#else
+ v = find_variable (tok);
+#endif
+
+ if ((v == 0 || invisible_p (v)) && unbound_vars_is_error)
+ {
+#if defined (ARRAY_VARS)
+ value = (e == ']') ? array_variable_name (tok, (char **)0, (int *)0) : tok;
+#else
+ value = tok;
+#endif
+
+ err_unboundvar (value);
+
+#if defined (ARRAY_VARS)
+ if (e == ']')
+ FREE (value); /* array_variable_name returns new memory */
+#endif
+
+ if (interactive_shell)
+ {
+ expr_unwind ();
+ jump_to_top_level (DISCARD);
+ }
+ else
+ jump_to_top_level (FORCE_EOF);
+ }
+
+#if defined (ARRAY_VARS)
+ /* Second argument of 0 to get_array_value means that we don't allow
+ references like array[@]. In this case, get_array_value is just
+ like get_variable_value in that it does not return newly-allocated
+ memory or quote the results. */
+ value = (e == ']') ? get_array_value (tok, 0, (int *)NULL) : get_variable_value (v);
+#else
+ value = get_variable_value (v);
+#endif
+
+ tval = (value && *value) ? subexpr (value) : 0;
+
+ 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
+ string). */
+static void
+readtok ()
+{
+ register char *cp, *xp;
+ register unsigned char c, c1;
+ register int e;
+
+ /* Skip leading whitespace. */
+ cp = tp;
+ c = e = 0;
+ while (cp && (c = *cp) && (cr_whitespace (c)))
+ cp++;
+
+ if (c)
+ cp++;
+
+ lasttp = tp = cp - 1;
+
+ if (c == '\0')
+ {
+ lasttok = curtok;
+ curtok = 0;
+ tp = cp;
+ return;
+ }
+
+ if (legal_variable_starter (c))
+ {
+ /* variable names not preceded with a dollar sign are shell variables. */
+ char *savecp;
+ EXPR_CONTEXT ec;
+ int peektok;
+
+ while (legal_variable_char (c))
+ c = *cp++;
+
+ c = *--cp;
+
+#if defined (ARRAY_VARS)
+ if (c == '[')
+ {
+ e = skipsubscript (cp, 0);
+ if (cp[e] == ']')
+ {
+ cp += e + 1;
+ c = *cp;
+ e = ']';
+ }
+ else
+ evalerror (bash_badsub_errmsg);
+ }
+#endif /* ARRAY_VARS */
+
+ *cp = '\0';
+ FREE (tokstr);
+ tokstr = savestring (tp);
+ *cp = c;
+
+ SAVETOK (&ec);
+ tokstr = (char *)NULL; /* keep it from being freed */
+ tp = savecp = cp;
+ noeval = 1;
+ curtok = STR;
+ readtok ();
+ peektok = curtok;
+ if (peektok == STR) /* free new tokstr before old one is restored */
+ FREE (tokstr);
+ RESTORETOK (&ec);
+ cp = savecp;
+
+ /* The tests for PREINC and PREDEC aren't strictly correct, but they
+ preserve old behavior if a construct like --x=9 is given. */
+ if (lasttok == PREINC || lasttok == PREDEC || peektok != EQ)
+ tokval = expr_streval (tokstr, e);
+ else
+ tokval = 0;
+
+ lasttok = curtok;
+ curtok = STR;
+ }
+ else if (DIGIT(c))
+ {
+ while (ISALNUM (c) || c == '#' || c == '@' || c == '_')
+ c = *cp++;
+
+ c = *--cp;
+ *cp = '\0';
+
+ tokval = strlong (tp);
+ *cp = c;
+ lasttok = curtok;
+ curtok = NUM;
+ }
+ else
+ {
+ c1 = *cp++;
+ if ((c == EQ) && (c1 == EQ))
+ c = EQEQ;
+ else if ((c == NOT) && (c1 == EQ))
+ c = NEQ;
+ else if ((c == GT) && (c1 == EQ))
+ c = GEQ;
+ else if ((c == LT) && (c1 == EQ))
+ c = LEQ;
+ else if ((c == LT) && (c1 == LT))
+ {
+ if (*cp == '=') /* a <<= b */
+ {
+ assigntok = LSH;
+ c = OP_ASSIGN;
+ cp++;
+ }
+ else
+ c = LSH;
+ }
+ else if ((c == GT) && (c1 == GT))
+ {
+ if (*cp == '=')
+ {
+ assigntok = RSH; /* a >>= b */
+ c = OP_ASSIGN;
+ cp++;
+ }
+ else
+ c = RSH;
+ }
+ else if ((c == BAND) && (c1 == BAND))
+ c = LAND;
+ else if ((c == BOR) && (c1 == BOR))
+ c = LOR;
+ else if ((c == '*') && (c1 == '*'))
+ c = POWER;
+ else if ((c == '-' || c == '+') && c1 == c && curtok == STR)
+ c = (c == '-') ? POSTDEC : POSTINC;
+ else if ((c == '-' || c == '+') && c1 == c)
+ {
+ /* Quickly scan forward to see if this is followed by optional
+ whitespace and an identifier. */
+ xp = cp;
+ while (xp && *xp && cr_whitespace (*xp))
+ xp++;
+ if (legal_variable_starter ((unsigned char)*xp))
+ c = (c == '-') ? PREDEC : PREINC;
+ else
+ cp--; /* not preinc or predec, so unget the character */
+ }
+ else if (c1 == EQ && member (c, "*/%+-&^|"))
+ {
+ 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 (_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;
+ }
+ tp = cp;
+}
+
+static void
+evalerror (msg)
+ char *msg;
+{
+ char *name, *t;
+
+ name = this_command_name;
+ for (t = expression; whitespace (*t); t++)
+ ;
+ internal_error ("%s%s%s: %s (error token is \"%s\")",
+ name ? name : "", name ? ": " : "", t,
+ msg, (lasttp && *lasttp) ? lasttp : "");
+ longjmp (evalbuf, 1);
+}
+
+/* Convert a string to an intmax_t integer, with an arbitrary base.
+ 0nnn -> base 8
+ 0[Xx]nn -> base 16
+ Anything else: [base#]number (this is implemented to match ksh93)
+
+ Base may be >=2 and <=64. If base is <= 36, the numbers are drawn
+ from [0-9][a-zA-Z], and lowercase and uppercase letters may be used
+ interchangably. If base is > 36 and <= 64, the numbers are drawn
+ from [0-9][a-z][A-Z]_@ (a = 10, z = 35, A = 36, Z = 61, @ = 62, _ = 63 --
+ you get the picture). */
+
+static intmax_t
+strlong (num)
+ char *num;
+{
+ register char *s;
+ register unsigned char c;
+ int base, foundbase;
+ intmax_t val;
+
+ s = num;
+
+ base = 10;
+ foundbase = 0;
+ if (*s == '0')
+ {
+ s++;
+
+ if (*s == '\0')
+ return 0;
+
+ /* Base 16? */
+ if (*s == 'x' || *s == 'X')
+ {
+ base = 16;
+ s++;
+ }
+ else
+ base = 8;
+ foundbase++;
+ }
+
+ val = 0;
+ for (c = *s++; c; c = *s++)
+ {
+ if (c == '#')
+ {
+ if (foundbase)
+ evalerror (_("invalid number"));
+
+ /* Illegal base specifications raise an evaluation error. */
+ if (val < 2 || val > 64)
+ evalerror (_("invalid arithmetic base"));
+
+ base = val;
+ val = 0;
+ foundbase++;
+ }
+ else if (ISALNUM(c) || (c == '_') || (c == '@'))
+ {
+ if (DIGIT(c))
+ c = TODIGIT(c);
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - ((base <= 36) ? 10 : 36);
+ else if (c == '@')
+ c = 62;
+ else if (c == '_')
+ c = 63;
+
+ if (c >= base)
+ evalerror (_("value too great for base"));
+
+ val = (val * base) + c;
+ }
+ else
+ break;
+ }
+
+ return (val);
+}
+
+#if defined (EXPR_TEST)
+void *
+xmalloc (n)
+ int n;
+{
+ return (malloc (n));
+}
+
+void *
+xrealloc (s, n)
+ char *s;
+ int n;
+{
+ return (realloc (s, n));
+}
+
+SHELL_VAR *find_variable () { return 0;}
+SHELL_VAR *bind_variable () { return 0; }
+
+char *get_string_value () { return 0; }
+
+procenv_t top_level;
+
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ register int i;
+ intmax_t v;
+ int expok;
+
+ if (setjmp (top_level))
+ exit (0);
+
+ for (i = 1; i < argc; i++)
+ {
+ v = evalexp (argv[i], &expok);
+ if (expok == 0)
+ fprintf (stderr, "%s: expression error\n", argv[i]);
+ else
+ printf ("'%s' -> %ld\n", argv[i], v);
+ }
+ exit (0);
+}
+
+int
+builtin_error (format, arg1, arg2, arg3, arg4, arg5)
+ char *format;
+{
+ fprintf (stderr, "expr: ");
+ fprintf (stderr, format, arg1, arg2, arg3, arg4, arg5);
+ fprintf (stderr, "\n");
+ return 0;
+}
+
+char *
+itos (n)
+ intmax_t n;
+{
+ return ("42");
+}
+
+#endif /* EXPR_TEST */
diff --git a/lib/readline/bind.c b/lib/readline/bind.c
index 7559d32f..235f68cd 100644
--- a/lib/readline/bind.c
+++ b/lib/readline/bind.c
@@ -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)
{
diff --git a/lib/readline/bind.c~ b/lib/readline/bind.c~
new file mode 100644
index 00000000..1d94b46d
--- /dev/null
+++ b/lib/readline/bind.c~
@@ -0,0 +1,2286 @@
+/* bind.c -- key binding and startup file support for the readline library. */
+
+/* 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 (__TANDEM)
+# include <floss.h>
+#endif
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#if defined (HAVE_SYS_FILE_H)
+# include <sys/file.h>
+#endif /* HAVE_SYS_FILE_H */
+
+#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 */
+
+#include <errno.h>
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+#include "posixstat.h"
+
+/* System-specific feature definitions and include files. */
+#include "rldefs.h"
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+#if !defined (strchr) && !defined (__STDC__)
+extern char *strchr (), *strrchr ();
+#endif /* !strchr && !__STDC__ */
+
+/* Variables exported by this file. */
+Keymap rl_binding_keymap;
+
+static char *_rl_read_file PARAMS((char *, size_t *));
+static void _rl_init_file_error PARAMS((const char *));
+static int _rl_read_init_file PARAMS((const char *, int));
+static int glean_key_from_name PARAMS((char *));
+static int find_boolean_var PARAMS((const char *));
+
+static char *_rl_get_string_variable_value PARAMS((const char *));
+static int substring_member_of_array PARAMS((char *, const char **));
+
+static int currently_reading_init_file;
+
+/* used only in this file */
+static int _rl_prefer_visible_bell = 1;
+
+/* **************************************************************** */
+/* */
+/* Binding keys */
+/* */
+/* **************************************************************** */
+
+/* rl_add_defun (char *name, rl_command_func_t *function, int key)
+ Add NAME to the list of named functions. Make FUNCTION be the function
+ that gets called. If KEY is not -1, then bind it. */
+int
+rl_add_defun (name, function, key)
+ const char *name;
+ rl_command_func_t *function;
+ int key;
+{
+ if (key != -1)
+ rl_bind_key (key, function);
+ rl_add_funmap_entry (name, function);
+ return 0;
+}
+
+/* Bind KEY to FUNCTION. Returns non-zero if KEY is out of range. */
+int
+rl_bind_key (key, function)
+ int key;
+ rl_command_func_t *function;
+{
+ if (key < 0)
+ return (key);
+
+ if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
+ {
+ if (_rl_keymap[ESC].type == ISKMAP)
+ {
+ Keymap escmap;
+
+ escmap = FUNCTION_TO_KEYMAP (_rl_keymap, ESC);
+ key = UNMETA (key);
+ escmap[key].type = ISFUNC;
+ escmap[key].function = function;
+ return (0);
+ }
+ return (key);
+ }
+
+ _rl_keymap[key].type = ISFUNC;
+ _rl_keymap[key].function = function;
+ rl_binding_keymap = _rl_keymap;
+ return (0);
+}
+
+/* Bind KEY to FUNCTION in MAP. Returns non-zero in case of invalid
+ KEY. */
+int
+rl_bind_key_in_map (key, function, map)
+ int key;
+ rl_command_func_t *function;
+ Keymap map;
+{
+ int result;
+ Keymap oldmap;
+
+ oldmap = _rl_keymap;
+ _rl_keymap = map;
+ result = rl_bind_key (key, function);
+ _rl_keymap = oldmap;
+ return (result);
+}
+
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
+ now, this is always used to attempt to bind the arrow keys, hence the
+ check for rl_vi_movement_mode. */
+int
+rl_bind_key_if_unbound_in_map (key, default_func, kmap)
+ int key;
+ rl_command_func_t *default_func;
+ Keymap kmap;
+{
+ char keyseq[2];
+
+ keyseq[0] = (unsigned char)key;
+ keyseq[1] = '\0';
+ return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap));
+}
+
+int
+rl_bind_key_if_unbound (key, default_func)
+ int key;
+ rl_command_func_t *default_func;
+{
+ char keyseq[2];
+
+ keyseq[0] = (unsigned char)key;
+ keyseq[1] = '\0';
+ return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
+}
+
+/* Make KEY do nothing in the currently selected keymap.
+ Returns non-zero in case of error. */
+int
+rl_unbind_key (key)
+ int key;
+{
+ return (rl_bind_key (key, (rl_command_func_t *)NULL));
+}
+
+/* Make KEY do nothing in MAP.
+ Returns non-zero in case of error. */
+int
+rl_unbind_key_in_map (key, map)
+ int key;
+ Keymap map;
+{
+ return (rl_bind_key_in_map (key, (rl_command_func_t *)NULL, map));
+}
+
+/* Unbind all keys bound to FUNCTION in MAP. */
+int
+rl_unbind_function_in_map (func, map)
+ rl_command_func_t *func;
+ Keymap map;
+{
+ register int i, rval;
+
+ for (i = rval = 0; i < KEYMAP_SIZE; i++)
+ {
+ if (map[i].type == ISFUNC && map[i].function == func)
+ {
+ map[i].function = (rl_command_func_t *)NULL;
+ rval = 1;
+ }
+ }
+ return rval;
+}
+
+int
+rl_unbind_command_in_map (command, map)
+ const char *command;
+ Keymap map;
+{
+ rl_command_func_t *func;
+
+ func = rl_named_function (command);
+ if (func == 0)
+ return 0;
+ return (rl_unbind_function_in_map (func, map));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+ FUNCTION, starting in the current keymap. This makes new
+ keymaps as necessary. */
+int
+rl_bind_keyseq (keyseq, function)
+ const char *keyseq;
+ rl_command_func_t *function;
+{
+ return (rl_generic_bind (ISFUNC, keyseq, (char *)function, _rl_keymap));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+ FUNCTION. This makes new keymaps as necessary. The initial
+ place to do bindings is in MAP. */
+int
+rl_bind_keyseq_in_map (keyseq, function, map)
+ const char *keyseq;
+ rl_command_func_t *function;
+ Keymap map;
+{
+ return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
+}
+
+/* Backwards compatibility; equivalent to rl_bind_keyseq_in_map() */
+int
+rl_set_key (keyseq, function, map)
+ const char *keyseq;
+ rl_command_func_t *function;
+ Keymap map;
+{
+ return (rl_generic_bind (ISFUNC, keyseq, (char *)function, map));
+}
+
+/* Bind key sequence KEYSEQ to DEFAULT_FUNC if KEYSEQ is unbound. Right
+ now, this is always used to attempt to bind the arrow keys, hence the
+ check for rl_vi_movement_mode. */
+int
+rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, kmap)
+ const char *keyseq;
+ rl_command_func_t *default_func;
+ Keymap kmap;
+{
+ rl_command_func_t *func;
+
+ if (keyseq)
+ {
+ func = rl_function_of_keyseq (keyseq, kmap, (int *)NULL);
+#if defined (VI_MODE)
+ if (!func || func == rl_do_lowercase_version || func == rl_vi_movement_mode)
+#else
+ if (!func || func == rl_do_lowercase_version)
+#endif
+ return (rl_bind_keyseq_in_map (keyseq, default_func, kmap));
+ else
+ return 1;
+ }
+ return 0;
+}
+
+int
+rl_bind_keyseq_if_unbound (keyseq, default_func)
+ const char *keyseq;
+ rl_command_func_t *default_func;
+{
+ return (rl_bind_keyseq_if_unbound_in_map (keyseq, default_func, _rl_keymap));
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+ the string of characters MACRO. This makes new keymaps as
+ necessary. The initial place to do bindings is in MAP. */
+int
+rl_macro_bind (keyseq, macro, map)
+ const char *keyseq, *macro;
+ Keymap map;
+{
+ char *macro_keys;
+ int macro_keys_len;
+
+ macro_keys = (char *)xmalloc ((2 * strlen (macro)) + 1);
+
+ if (rl_translate_keyseq (macro, macro_keys, &macro_keys_len))
+ {
+ free (macro_keys);
+ return -1;
+ }
+ rl_generic_bind (ISMACR, keyseq, macro_keys, map);
+ return 0;
+}
+
+/* Bind the key sequence represented by the string KEYSEQ to
+ the arbitrary pointer DATA. TYPE says what kind of data is
+ pointed to by DATA, right now this can be a function (ISFUNC),
+ a macro (ISMACR), or a keymap (ISKMAP). This makes new keymaps
+ as necessary. The initial place to do bindings is in MAP. */
+int
+rl_generic_bind (type, keyseq, data, map)
+ int type;
+ const char *keyseq;
+ char *data;
+ Keymap map;
+{
+ char *keys;
+ int keys_len;
+ register int i;
+ KEYMAP_ENTRY k;
+
+ k.function = 0;
+
+ /* If no keys to bind to, exit right away. */
+ if (keyseq == 0 || *keyseq == 0)
+ {
+ if (type == ISMACR)
+ free (data);
+ return -1;
+ }
+
+ keys = (char *)xmalloc (1 + (2 * strlen (keyseq)));
+
+ /* Translate the ASCII representation of KEYSEQ into an array of
+ characters. Stuff the characters into KEYS, and the length of
+ KEYS into KEYS_LEN. */
+ if (rl_translate_keyseq (keyseq, keys, &keys_len))
+ {
+ free (keys);
+ return -1;
+ }
+
+ /* Bind keys, making new keymaps as necessary. */
+ for (i = 0; i < keys_len; i++)
+ {
+ unsigned char uc = keys[i];
+ int ic;
+
+ ic = uc;
+ if (ic < 0 || ic >= KEYMAP_SIZE)
+ return -1;
+
+ if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
+ {
+ ic = UNMETA (ic);
+ if (map[ESC].type == ISKMAP)
+ map = FUNCTION_TO_KEYMAP (map, ESC);
+ }
+
+ if ((i + 1) < keys_len)
+ {
+ if (map[ic].type != ISKMAP)
+ {
+ /* We allow subsequences of keys. If a keymap is being
+ created that will `shadow' an existing function or macro
+ key binding, we save that keybinding into the ANYOTHERKEY
+ index in the new map. The dispatch code will look there
+ to find the function to execute if the subsequence is not
+ matched. ANYOTHERKEY was chosen to be greater than
+ UCHAR_MAX. */
+ k = map[ic];
+
+ map[ic].type = ISKMAP;
+ map[ic].function = KEYMAP_TO_FUNCTION (rl_make_bare_keymap());
+ }
+ map = FUNCTION_TO_KEYMAP (map, ic);
+ /* The dispatch code will return this function if no matching
+ key sequence is found in the keymap. This (with a little
+ help from the dispatch code in readline.c) allows `a' to be
+ mapped to something, `abc' to be mapped to something else,
+ and the function bound to `a' to be executed when the user
+ types `abx', leaving `bx' in the input queue. */
+ if (k.function && ((k.type == ISFUNC && k.function != rl_do_lowercase_version) || k.type == ISMACR))
+ {
+ map[ANYOTHERKEY] = k;
+ k.function = 0;
+ }
+ }
+ else
+ {
+ if (map[ic].type == ISMACR)
+ free ((char *)map[ic].function);
+ else if (map[ic].type == ISKMAP)
+ {
+ map = FUNCTION_TO_KEYMAP (map, ic);
+ ic = ANYOTHERKEY;
+ }
+
+ map[ic].function = KEYMAP_TO_FUNCTION (data);
+ map[ic].type = type;
+ }
+
+ rl_binding_keymap = map;
+ }
+ free (keys);
+ return 0;
+}
+
+/* Translate the ASCII representation of SEQ, stuffing the values into ARRAY,
+ an array of characters. LEN gets the final length of ARRAY. Return
+ non-zero if there was an error parsing SEQ. */
+int
+rl_translate_keyseq (seq, array, len)
+ const char *seq;
+ char *array;
+ int *len;
+{
+ register int i, c, l, temp;
+
+ for (i = l = 0; c = seq[i]; i++)
+ {
+ if (c == '\\')
+ {
+ c = seq[++i];
+
+ if (c == 0)
+ break;
+
+ /* Handle \C- and \M- prefixes. */
+ if ((c == 'C' || c == 'M') && seq[i + 1] == '-')
+ {
+ /* Handle special case of backwards define. */
+ if (strncmp (&seq[i], "C-\\M-", 5) == 0)
+ {
+ array[l++] = ESC; /* ESC is meta-prefix */
+ i += 5;
+ array[l++] = CTRL (_rl_to_upper (seq[i]));
+ if (seq[i] == '\0')
+ i--;
+ }
+ else if (c == 'M')
+ {
+ i++; /* seq[i] == '-' */
+ /* XXX - should 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]);
+ }
+ }
+ else if (c == 'C')
+ {
+ i += 2;
+ /* Special hack for C-?... */
+ array[l++] = (seq[i] == '?') ? RUBOUT : CTRL (_rl_to_upper (seq[i]));
+ }
+ continue;
+ }
+
+ /* Translate other backslash-escaped characters. These are the
+ same escape sequences that bash's `echo' and `printf' builtins
+ handle, with the addition of \d -> RUBOUT. A backslash
+ preceding a character that is not special is stripped. */
+ switch (c)
+ {
+ case 'a':
+ array[l++] = '\007';
+ break;
+ case 'b':
+ array[l++] = '\b';
+ break;
+ case 'd':
+ array[l++] = RUBOUT; /* readline-specific */
+ break;
+ case 'e':
+ array[l++] = ESC;
+ break;
+ case 'f':
+ array[l++] = '\f';
+ break;
+ case 'n':
+ array[l++] = NEWLINE;
+ break;
+ case 'r':
+ array[l++] = RETURN;
+ break;
+ case 't':
+ array[l++] = TAB;
+ break;
+ case 'v':
+ array[l++] = 0x0B;
+ break;
+ case '\\':
+ array[l++] = '\\';
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ i++;
+ for (temp = 2, c -= '0'; ISOCTAL (seq[i]) && temp--; i++)
+ c = (c * 8) + OCTVALUE (seq[i]);
+ i--; /* auto-increment in for loop */
+ array[l++] = c & largest_char;
+ break;
+ case 'x':
+ i++;
+ for (temp = 2, c = 0; ISXDIGIT ((unsigned char)seq[i]) && temp--; i++)
+ c = (c * 16) + HEXVALUE (seq[i]);
+ if (temp == 2)
+ c = 'x';
+ i--; /* auto-increment in for loop */
+ array[l++] = c & largest_char;
+ break;
+ default: /* backslashes before non-special chars just add the char */
+ array[l++] = c;
+ break; /* the backslash is stripped */
+ }
+ continue;
+ }
+
+ array[l++] = c;
+ }
+
+ *len = l;
+ array[l] = '\0';
+ return (0);
+}
+
+char *
+rl_untranslate_keyseq (seq)
+ int seq;
+{
+ static char kseq[16];
+ int i, c;
+
+ i = 0;
+ c = seq;
+ if (META_CHAR (c))
+ {
+ kseq[i++] = '\\';
+ kseq[i++] = 'M';
+ kseq[i++] = '-';
+ c = UNMETA (c);
+ }
+ else if (CTRL_CHAR (c))
+ {
+ kseq[i++] = '\\';
+ kseq[i++] = 'C';
+ kseq[i++] = '-';
+ c = _rl_to_lower (UNCTRL (c));
+ }
+ else if (c == RUBOUT)
+ {
+ kseq[i++] = '\\';
+ kseq[i++] = 'C';
+ kseq[i++] = '-';
+ c = '?';
+ }
+
+ if (c == ESC)
+ {
+ kseq[i++] = '\\';
+ c = 'e';
+ }
+ else if (c == '\\' || c == '"')
+ {
+ kseq[i++] = '\\';
+ }
+
+ kseq[i++] = (unsigned char) c;
+ kseq[i] = '\0';
+ return kseq;
+}
+
+static char *
+_rl_untranslate_macro_value (seq)
+ char *seq;
+{
+ char *ret, *r, *s;
+ int c;
+
+ r = ret = (char *)xmalloc (7 * strlen (seq) + 1);
+ for (s = seq; *s; s++)
+ {
+ c = *s;
+ if (META_CHAR (c))
+ {
+ *r++ = '\\';
+ *r++ = 'M';
+ *r++ = '-';
+ c = UNMETA (c);
+ }
+ else if (CTRL_CHAR (c) && c != ESC)
+ {
+ *r++ = '\\';
+ *r++ = 'C';
+ *r++ = '-';
+ c = _rl_to_lower (UNCTRL (c));
+ }
+ else if (c == RUBOUT)
+ {
+ *r++ = '\\';
+ *r++ = 'C';
+ *r++ = '-';
+ c = '?';
+ }
+
+ if (c == ESC)
+ {
+ *r++ = '\\';
+ c = 'e';
+ }
+ else if (c == '\\' || c == '"')
+ *r++ = '\\';
+
+ *r++ = (unsigned char)c;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* Return a pointer to the function that STRING represents.
+ If STRING doesn't have a matching function, then a NULL pointer
+ is returned. */
+rl_command_func_t *
+rl_named_function (string)
+ const char *string;
+{
+ register int i;
+
+ rl_initialize_funmap ();
+
+ for (i = 0; funmap[i]; i++)
+ if (_rl_stricmp (funmap[i]->name, string) == 0)
+ return (funmap[i]->function);
+ return ((rl_command_func_t *)NULL);
+}
+
+/* Return the function (or macro) definition which would be invoked via
+ KEYSEQ if executed in MAP. If MAP is NULL, then the current keymap is
+ used. TYPE, if non-NULL, is a pointer to an int which will receive the
+ type of the object pointed to. One of ISFUNC (function), ISKMAP (keymap),
+ or ISMACR (macro). */
+rl_command_func_t *
+rl_function_of_keyseq (keyseq, map, type)
+ const char *keyseq;
+ Keymap map;
+ int *type;
+{
+ register int i;
+
+ if (!map)
+ map = _rl_keymap;
+
+ for (i = 0; keyseq && keyseq[i]; i++)
+ {
+ unsigned char ic = keyseq[i];
+
+ if (META_CHAR (ic) && _rl_convert_meta_chars_to_ascii)
+ {
+ if (map[ESC].type != ISKMAP)
+ {
+ if (type)
+ *type = map[ESC].type;
+
+ return (map[ESC].function);
+ }
+ else
+ {
+ map = FUNCTION_TO_KEYMAP (map, ESC);
+ ic = UNMETA (ic);
+ }
+ }
+
+ if (map[ic].type == ISKMAP)
+ {
+ /* If this is the last key in the key sequence, return the
+ map. */
+ if (!keyseq[i + 1])
+ {
+ if (type)
+ *type = ISKMAP;
+
+ return (map[ic].function);
+ }
+ else
+ map = FUNCTION_TO_KEYMAP (map, ic);
+ }
+ else
+ {
+ if (type)
+ *type = map[ic].type;
+
+ return (map[ic].function);
+ }
+ }
+ return ((rl_command_func_t *) NULL);
+}
+
+/* The last key bindings file read. */
+static char *last_readline_init_file = (char *)NULL;
+
+/* The file we're currently reading key bindings from. */
+static const char *current_readline_init_file;
+static int current_readline_init_include_level;
+static int current_readline_init_lineno;
+
+/* Read FILENAME into a locally-allocated buffer and return the buffer.
+ The size of the buffer is returned in *SIZEP. Returns NULL if any
+ errors were encountered. */
+static char *
+_rl_read_file (filename, sizep)
+ char *filename;
+ size_t *sizep;
+{
+ struct stat finfo;
+ size_t file_size;
+ char *buffer;
+ int i, file;
+
+ if ((stat (filename, &finfo) < 0) || (file = open (filename, O_RDONLY, 0666)) < 0)
+ return ((char *)NULL);
+
+ file_size = (size_t)finfo.st_size;
+
+ /* check for overflow on very large files */
+ if (file_size != finfo.st_size || file_size + 1 < file_size)
+ {
+ if (file >= 0)
+ close (file);
+#if defined (EFBIG)
+ errno = EFBIG;
+#endif
+ return ((char *)NULL);
+ }
+
+ /* Read the file into BUFFER. */
+ buffer = (char *)xmalloc (file_size + 1);
+ i = read (file, buffer, file_size);
+ close (file);
+
+ if (i < 0)
+ {
+ free (buffer);
+ return ((char *)NULL);
+ }
+
+ buffer[i] = '\0';
+ if (sizep)
+ *sizep = i;
+
+ return (buffer);
+}
+
+/* Re-read the current keybindings file. */
+int
+rl_re_read_init_file (count, ignore)
+ int count, ignore;
+{
+ int r;
+ r = rl_read_init_file ((const char *)NULL);
+ rl_set_keymap_from_edit_mode ();
+ return r;
+}
+
+/* Do key bindings from a file. If FILENAME is NULL it defaults
+ to the first non-null filename from this list:
+ 1. the filename used for the previous call
+ 2. the value of the shell variable `INPUTRC'
+ 3. ~/.inputrc
+ If the file existed and could be opened and read, 0 is returned,
+ otherwise errno is returned. */
+int
+rl_read_init_file (filename)
+ const char *filename;
+{
+ /* Default the filename. */
+ if (filename == 0)
+ {
+ filename = last_readline_init_file;
+ if (filename == 0)
+ filename = sh_get_env_value ("INPUTRC");
+ if (filename == 0)
+ filename = DEFAULT_INPUTRC;
+ }
+
+ if (*filename == 0)
+ filename = DEFAULT_INPUTRC;
+
+#if defined (__MSDOS__)
+ if (_rl_read_init_file (filename, 0) == 0)
+ return 0;
+ filename = "~/_inputrc";
+#endif
+ return (_rl_read_init_file (filename, 0));
+}
+
+static int
+_rl_read_init_file (filename, include_level)
+ const char *filename;
+ int include_level;
+{
+ register int i;
+ char *buffer, *openname, *line, *end;
+ size_t file_size;
+
+ current_readline_init_file = filename;
+ current_readline_init_include_level = include_level;
+
+ openname = tilde_expand (filename);
+ buffer = _rl_read_file (openname, &file_size);
+ free (openname);
+
+ if (buffer == 0)
+ return (errno);
+
+ if (include_level == 0 && filename != last_readline_init_file)
+ {
+ FREE (last_readline_init_file);
+ last_readline_init_file = savestring (filename);
+ }
+
+ currently_reading_init_file = 1;
+
+ /* Loop over the lines in the file. Lines that start with `#' are
+ comments; all other lines are commands for readline initialization. */
+ current_readline_init_lineno = 1;
+ line = buffer;
+ end = buffer + file_size;
+ while (line < end)
+ {
+ /* Find the end of this line. */
+ for (i = 0; line + i != end && line[i] != '\n'; i++);
+
+#if defined (__CYGWIN__)
+ /* ``Be liberal in what you accept.'' */
+ if (line[i] == '\n' && line[i-1] == '\r')
+ line[i - 1] = '\0';
+#endif
+
+ /* Mark end of line. */
+ line[i] = '\0';
+
+ /* Skip leading whitespace. */
+ while (*line && whitespace (*line))
+ {
+ line++;
+ i--;
+ }
+
+ /* If the line is not a comment, then parse it. */
+ if (*line && *line != '#')
+ rl_parse_and_bind (line);
+
+ /* Move to the next line. */
+ line += i + 1;
+ current_readline_init_lineno++;
+ }
+
+ free (buffer);
+ currently_reading_init_file = 0;
+ return (0);
+}
+
+static void
+_rl_init_file_error (msg)
+ const char *msg;
+{
+ if (currently_reading_init_file)
+ fprintf (stderr, "readline: %s: line %d: %s\n", current_readline_init_file,
+ current_readline_init_lineno, msg);
+ else
+ fprintf (stderr, "readline: %s\n", msg);
+}
+
+/* **************************************************************** */
+/* */
+/* Parser Directives */
+/* */
+/* **************************************************************** */
+
+typedef int _rl_parser_func_t PARAMS((char *));
+
+/* Things that mean `Control'. */
+const char *_rl_possible_control_prefixes[] = {
+ "Control-", "C-", "CTRL-", (const char *)NULL
+};
+
+const char *_rl_possible_meta_prefixes[] = {
+ "Meta", "M-", (const char *)NULL
+};
+
+/* Conditionals. */
+
+/* Calling programs set this to have their argv[0]. */
+const char *rl_readline_name = "other";
+
+/* Stack of previous values of parsing_conditionalized_out. */
+static unsigned char *if_stack = (unsigned char *)NULL;
+static int if_stack_depth;
+static int if_stack_size;
+
+/* Push _rl_parsing_conditionalized_out, and set parser state based
+ on ARGS. */
+static int
+parser_if (args)
+ char *args;
+{
+ register int i;
+
+ /* Push parser state. */
+ if (if_stack_depth + 1 >= if_stack_size)
+ {
+ if (!if_stack)
+ if_stack = (unsigned char *)xmalloc (if_stack_size = 20);
+ else
+ if_stack = (unsigned char *)xrealloc (if_stack, if_stack_size += 20);
+ }
+ if_stack[if_stack_depth++] = _rl_parsing_conditionalized_out;
+
+ /* If parsing is turned off, then nothing can turn it back on except
+ for finding the matching endif. In that case, return right now. */
+ if (_rl_parsing_conditionalized_out)
+ return 0;
+
+ /* Isolate first argument. */
+ for (i = 0; args[i] && !whitespace (args[i]); i++);
+
+ if (args[i])
+ args[i++] = '\0';
+
+ /* Handle "$if term=foo" and "$if mode=emacs" constructs. If this
+ isn't term=foo, or mode=emacs, then check to see if the first
+ word in ARGS is the same as the value stored in rl_readline_name. */
+ if (rl_terminal_name && _rl_strnicmp (args, "term=", 5) == 0)
+ {
+ char *tem, *tname;
+
+ /* Terminals like "aaa-60" are equivalent to "aaa". */
+ tname = savestring (rl_terminal_name);
+ tem = strchr (tname, '-');
+ if (tem)
+ *tem = '\0';
+
+ /* Test the `long' and `short' forms of the terminal name so that
+ if someone has a `sun-cmd' and does not want to have bindings
+ that will be executed if the terminal is a `sun', they can put
+ `$if term=sun-cmd' into their .inputrc. */
+ _rl_parsing_conditionalized_out = _rl_stricmp (args + 5, tname) &&
+ _rl_stricmp (args + 5, rl_terminal_name);
+ free (tname);
+ }
+#if defined (VI_MODE)
+ else if (_rl_strnicmp (args, "mode=", 5) == 0)
+ {
+ int mode;
+
+ if (_rl_stricmp (args + 5, "emacs") == 0)
+ mode = emacs_mode;
+ else if (_rl_stricmp (args + 5, "vi") == 0)
+ mode = vi_mode;
+ else
+ mode = no_mode;
+
+ _rl_parsing_conditionalized_out = mode != rl_editing_mode;
+ }
+#endif /* VI_MODE */
+ /* Check to see if the first word in ARGS is the same as the
+ value stored in rl_readline_name. */
+ else if (_rl_stricmp (args, rl_readline_name) == 0)
+ _rl_parsing_conditionalized_out = 0;
+ else
+ _rl_parsing_conditionalized_out = 1;
+ return 0;
+}
+
+/* Invert the current parser state if there is anything on the stack. */
+static int
+parser_else (args)
+ char *args;
+{
+ register int i;
+
+ if (if_stack_depth == 0)
+ {
+ _rl_init_file_error ("$else found without matching $if");
+ return 0;
+ }
+
+#if 0
+ /* Check the previous (n - 1) levels of the stack to make sure that
+ we haven't previously turned off parsing. */
+ for (i = 0; i < if_stack_depth - 1; i++)
+#else
+ /* Check the previous (n) levels of the stack to make sure that
+ we haven't previously turned off parsing. */
+ for (i = 0; i < if_stack_depth; i++)
+#endif
+ if (if_stack[i] == 1)
+ return 0;
+
+ /* Invert the state of parsing if at top level. */
+ _rl_parsing_conditionalized_out = !_rl_parsing_conditionalized_out;
+ return 0;
+}
+
+/* Terminate a conditional, popping the value of
+ _rl_parsing_conditionalized_out from the stack. */
+static int
+parser_endif (args)
+ char *args;
+{
+ if (if_stack_depth)
+ _rl_parsing_conditionalized_out = if_stack[--if_stack_depth];
+ else
+ _rl_init_file_error ("$endif without matching $if");
+ return 0;
+}
+
+static int
+parser_include (args)
+ char *args;
+{
+ const char *old_init_file;
+ char *e;
+ int old_line_number, old_include_level, r;
+
+ if (_rl_parsing_conditionalized_out)
+ return (0);
+
+ old_init_file = current_readline_init_file;
+ old_line_number = current_readline_init_lineno;
+ old_include_level = current_readline_init_include_level;
+
+ e = strchr (args, '\n');
+ if (e)
+ *e = '\0';
+ r = _rl_read_init_file ((const char *)args, old_include_level + 1);
+
+ current_readline_init_file = old_init_file;
+ current_readline_init_lineno = old_line_number;
+ current_readline_init_include_level = old_include_level;
+
+ return r;
+}
+
+/* Associate textual names with actual functions. */
+static struct {
+ const char *name;
+ _rl_parser_func_t *function;
+} parser_directives [] = {
+ { "if", parser_if },
+ { "endif", parser_endif },
+ { "else", parser_else },
+ { "include", parser_include },
+ { (char *)0x0, (_rl_parser_func_t *)0x0 }
+};
+
+/* Handle a parser directive. STATEMENT is the line of the directive
+ without any leading `$'. */
+static int
+handle_parser_directive (statement)
+ char *statement;
+{
+ register int i;
+ char *directive, *args;
+
+ /* Isolate the actual directive. */
+
+ /* Skip whitespace. */
+ for (i = 0; whitespace (statement[i]); i++);
+
+ directive = &statement[i];
+
+ for (; statement[i] && !whitespace (statement[i]); i++);
+
+ if (statement[i])
+ statement[i++] = '\0';
+
+ for (; statement[i] && whitespace (statement[i]); i++);
+
+ args = &statement[i];
+
+ /* Lookup the command, and act on it. */
+ for (i = 0; parser_directives[i].name; i++)
+ if (_rl_stricmp (directive, parser_directives[i].name) == 0)
+ {
+ (*parser_directives[i].function) (args);
+ return (0);
+ }
+
+ /* display an error message about the unknown parser directive */
+ _rl_init_file_error ("unknown parser directive");
+ return (1);
+}
+
+/* Read the binding command from STRING and perform it.
+ A key binding command looks like: Keyname: function-name\0,
+ a variable binding command looks like: set variable value.
+ A new-style keybinding looks like "\C-x\C-x": exchange-point-and-mark. */
+int
+rl_parse_and_bind (string)
+ char *string;
+{
+ char *funname, *kname;
+ register int c, i;
+ int key, equivalency;
+
+ while (string && whitespace (*string))
+ string++;
+
+ if (!string || !*string || *string == '#')
+ return 0;
+
+ /* If this is a parser directive, act on it. */
+ if (*string == '$')
+ {
+ handle_parser_directive (&string[1]);
+ return 0;
+ }
+
+ /* If we aren't supposed to be parsing right now, then we're done. */
+ if (_rl_parsing_conditionalized_out)
+ return 0;
+
+ i = 0;
+ /* If this keyname is a complex key expression surrounded by quotes,
+ advance to after the matching close quote. This code allows the
+ backslash to quote characters in the key expression. */
+ if (*string == '"')
+ {
+ int passc = 0;
+
+ for (i = 1; c = string[i]; i++)
+ {
+ if (passc)
+ {
+ passc = 0;
+ continue;
+ }
+
+ if (c == '\\')
+ {
+ passc++;
+ continue;
+ }
+
+ if (c == '"')
+ break;
+ }
+ /* If we didn't find a closing quote, abort the line. */
+ if (string[i] == '\0')
+ {
+ _rl_init_file_error ("no closing `\"' in key binding");
+ return 1;
+ }
+ }
+
+ /* Advance to the colon (:) or whitespace which separates the two objects. */
+ for (; (c = string[i]) && c != ':' && c != ' ' && c != '\t'; i++ );
+
+ equivalency = (c == ':' && string[i + 1] == '=');
+
+ /* Mark the end of the command (or keyname). */
+ if (string[i])
+ string[i++] = '\0';
+
+ /* If doing assignment, skip the '=' sign as well. */
+ if (equivalency)
+ string[i++] = '\0';
+
+ /* If this is a command to set a variable, then do that. */
+ if (_rl_stricmp (string, "set") == 0)
+ {
+ char *var, *value, *e;
+
+ var = string + i;
+ /* Make VAR point to start of variable name. */
+ while (*var && whitespace (*var)) var++;
+
+ /* Make VALUE point to start of value string. */
+ value = var;
+ while (*value && !whitespace (*value)) value++;
+ if (*value)
+ *value++ = '\0';
+ while (*value && whitespace (*value)) value++;
+
+ /* Strip trailing whitespace from values to boolean variables. Temp
+ fix until I get a real quoted-string parser here. */
+ i = find_boolean_var (var);
+ if (i >= 0)
+ {
+ /* remove trailing whitespace */
+ e = value + strlen (value) - 1;
+ while (e >= value && whitespace (*e))
+ e--;
+ e++; /* skip back to whitespace or EOS */
+ if (*e && e >= value)
+ *e = '\0';
+ }
+
+ rl_variable_bind (var, value);
+ return 0;
+ }
+
+ /* Skip any whitespace between keyname and funname. */
+ for (; string[i] && whitespace (string[i]); i++);
+ funname = &string[i];
+
+ /* Now isolate funname.
+ For straight function names just look for whitespace, since
+ that will signify the end of the string. But this could be a
+ macro definition. In that case, the string is quoted, so skip
+ to the matching delimiter. We allow the backslash to quote the
+ delimiter characters in the macro body. */
+ /* This code exists to allow whitespace in macro expansions, which
+ would otherwise be gobbled up by the next `for' loop.*/
+ /* XXX - it may be desirable to allow backslash quoting only if " is
+ the quoted string delimiter, like the shell. */
+ if (*funname == '\'' || *funname == '"')
+ {
+ int delimiter, passc;
+
+ delimiter = string[i++];
+ for (passc = 0; c = string[i]; i++)
+ {
+ if (passc)
+ {
+ passc = 0;
+ continue;
+ }
+
+ if (c == '\\')
+ {
+ passc = 1;
+ continue;
+ }
+
+ if (c == delimiter)
+ break;
+ }
+ if (c)
+ i++;
+ }
+
+ /* Advance to the end of the string. */
+ for (; string[i] && !whitespace (string[i]); i++);
+
+ /* No extra whitespace at the end of the string. */
+ string[i] = '\0';
+
+ /* Handle equivalency bindings here. Make the left-hand side be exactly
+ whatever the right-hand evaluates to, including keymaps. */
+ if (equivalency)
+ {
+ return 0;
+ }
+
+ /* If this is a new-style key-binding, then do the binding with
+ rl_bind_keyseq (). Otherwise, let the older code deal with it. */
+ if (*string == '"')
+ {
+ char *seq;
+ register int j, k, passc;
+
+ seq = (char *)xmalloc (1 + strlen (string));
+ for (j = 1, k = passc = 0; string[j]; j++)
+ {
+ /* Allow backslash to quote characters, but leave them in place.
+ This allows a string to end with a backslash quoting another
+ backslash, or with a backslash quoting a double quote. The
+ backslashes are left in place for rl_translate_keyseq (). */
+ if (passc || (string[j] == '\\'))
+ {
+ seq[k++] = string[j];
+ passc = !passc;
+ continue;
+ }
+
+ if (string[j] == '"')
+ break;
+
+ seq[k++] = string[j];
+ }
+ seq[k] = '\0';
+
+ /* Binding macro? */
+ if (*funname == '\'' || *funname == '"')
+ {
+ j = strlen (funname);
+
+ /* Remove the delimiting quotes from each end of FUNNAME. */
+ if (j && funname[j - 1] == *funname)
+ funname[j - 1] = '\0';
+
+ rl_macro_bind (seq, &funname[1], _rl_keymap);
+ }
+ else
+ rl_bind_keyseq (seq, rl_named_function (funname));
+
+ free (seq);
+ return 0;
+ }
+
+ /* Get the actual character we want to deal with. */
+ kname = strrchr (string, '-');
+ if (!kname)
+ kname = string;
+ else
+ kname++;
+
+ key = glean_key_from_name (kname);
+
+ /* Add in control and meta bits. */
+ if (substring_member_of_array (string, _rl_possible_control_prefixes))
+ key = CTRL (_rl_to_upper (key));
+
+ if (substring_member_of_array (string, _rl_possible_meta_prefixes))
+ key = META (key);
+
+ /* Temporary. Handle old-style keyname with macro-binding. */
+ if (*funname == '\'' || *funname == '"')
+ {
+ char useq[2];
+ int fl = strlen (funname);
+
+ useq[0] = key; useq[1] = '\0';
+ if (fl && funname[fl - 1] == *funname)
+ funname[fl - 1] = '\0';
+
+ rl_macro_bind (useq, &funname[1], _rl_keymap);
+ }
+#if defined (PREFIX_META_HACK)
+ /* Ugly, but working hack to keep prefix-meta around. */
+ else if (_rl_stricmp (funname, "prefix-meta") == 0)
+ {
+ char seq[2];
+
+ seq[0] = key;
+ seq[1] = '\0';
+ rl_generic_bind (ISKMAP, seq, (char *)emacs_meta_keymap, _rl_keymap);
+ }
+#endif /* PREFIX_META_HACK */
+ else
+ rl_bind_key (key, rl_named_function (funname));
+ return 0;
+}
+
+/* Simple structure for boolean readline variables (i.e., those that can
+ have one of two values; either "On" or 1 for truth, or "Off" or 0 for
+ false. */
+
+#define V_SPECIAL 0x1
+
+static struct {
+ const char *name;
+ int *value;
+ int flags;
+} boolean_varlist [] = {
+ { "bind-tty-special-chars", &_rl_bind_stty_chars, 0 },
+ { "blink-matching-paren", &rl_blink_matching_paren, V_SPECIAL },
+ { "byte-oriented", &rl_byte_oriented, 0 },
+ { "completion-ignore-case", &_rl_completion_case_fold, 0 },
+ { "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
+ { "disable-completion", &rl_inhibit_completion, 0 },
+ { "enable-keypad", &_rl_enable_keypad, 0 },
+ { "expand-tilde", &rl_complete_with_tilde_expansion, 0 },
+ { "history-preserve-point", &_rl_history_preserve_point, 0 },
+ { "horizontal-scroll-mode", &_rl_horizontal_scroll_mode, 0 },
+ { "input-meta", &_rl_meta_flag, 0 },
+ { "mark-directories", &_rl_complete_mark_directories, 0 },
+ { "mark-modified-lines", &_rl_mark_modified_lines, 0 },
+ { "mark-symlinked-directories", &_rl_complete_mark_symlink_dirs, 0 },
+ { "match-hidden-files", &_rl_match_hidden_files, 0 },
+ { "meta-flag", &_rl_meta_flag, 0 },
+ { "output-meta", &_rl_output_meta_chars, 0 },
+ { "page-completions", &_rl_page_completions, 0 },
+ { "prefer-visible-bell", &_rl_prefer_visible_bell, V_SPECIAL },
+ { "print-completions-horizontally", &_rl_print_completions_horizontally, 0 },
+ { "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
+ { "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 },
+#if defined (VISIBLE_STATS)
+ { "visible-stats", &rl_visible_stats, 0 },
+#endif /* VISIBLE_STATS */
+ { (char *)NULL, (int *)NULL }
+};
+
+static int
+find_boolean_var (name)
+ const char *name;
+{
+ register int i;
+
+ for (i = 0; boolean_varlist[i].name; i++)
+ if (_rl_stricmp (name, boolean_varlist[i].name) == 0)
+ return i;
+ return -1;
+}
+
+/* Hooks for handling special boolean variables, where a
+ function needs to be called or another variable needs
+ to be changed when they're changed. */
+static void
+hack_special_boolean_var (i)
+ int i;
+{
+ const char *name;
+
+ name = boolean_varlist[i].name;
+
+ if (_rl_stricmp (name, "blink-matching-paren") == 0)
+ _rl_enable_paren_matching (rl_blink_matching_paren);
+ else if (_rl_stricmp (name, "prefer-visible-bell") == 0)
+ {
+ if (_rl_prefer_visible_bell)
+ _rl_bell_preference = VISIBLE_BELL;
+ else
+ _rl_bell_preference = AUDIBLE_BELL;
+ }
+}
+
+typedef int _rl_sv_func_t PARAMS((const char *));
+
+/* These *must* correspond to the array indices for the appropriate
+ string variable. (Though they're not used right now.) */
+#define V_BELLSTYLE 0
+#define V_COMBEGIN 1
+#define V_EDITMODE 2
+#define V_ISRCHTERM 3
+#define V_KEYMAP 4
+
+#define V_STRING 1
+#define V_INT 2
+
+/* Forward declarations */
+static int sv_bell_style PARAMS((const char *));
+static int sv_combegin PARAMS((const char *));
+static int sv_compquery PARAMS((const char *));
+static int sv_editmode PARAMS((const char *));
+static int sv_isrchterm PARAMS((const char *));
+static int sv_keymap PARAMS((const char *));
+
+static struct {
+ const char *name;
+ int flags;
+ _rl_sv_func_t *set_func;
+} string_varlist[] = {
+ { "bell-style", V_STRING, sv_bell_style },
+ { "comment-begin", V_STRING, sv_combegin },
+ { "completion-query-items", V_INT, sv_compquery },
+ { "editing-mode", V_STRING, sv_editmode },
+ { "isearch-terminators", V_STRING, sv_isrchterm },
+ { "keymap", V_STRING, sv_keymap },
+ { (char *)NULL, 0 }
+};
+
+static int
+find_string_var (name)
+ const char *name;
+{
+ register int i;
+
+ for (i = 0; string_varlist[i].name; i++)
+ if (_rl_stricmp (name, string_varlist[i].name) == 0)
+ return i;
+ return -1;
+}
+
+/* A boolean value that can appear in a `set variable' command is true if
+ the value is null or empty, `on' (case-insenstive), or "1". Any other
+ values result in 0 (false). */
+static int
+bool_to_int (value)
+ const char *value;
+{
+ return (value == 0 || *value == '\0' ||
+ (_rl_stricmp (value, "on") == 0) ||
+ (value[0] == '1' && value[1] == '\0'));
+}
+
+char *
+rl_variable_value (name)
+ const char *name;
+{
+ register int i;
+ int v;
+
+ /* Check for simple variables first. */
+ i = find_boolean_var (name);
+ if (i >= 0)
+ return (*boolean_varlist[i].value ? "on" : "off");
+
+ i = find_string_var (name);
+ if (i >= 0)
+ return (_rl_get_string_variable_value (string_varlist[i].name));
+
+ /* Unknown variable names return NULL. */
+ return 0;
+}
+
+int
+rl_variable_bind (name, value)
+ const char *name, *value;
+{
+ register int i;
+ int v;
+
+ /* Check for simple variables first. */
+ i = find_boolean_var (name);
+ if (i >= 0)
+ {
+ *boolean_varlist[i].value = bool_to_int (value);
+ if (boolean_varlist[i].flags & V_SPECIAL)
+ hack_special_boolean_var (i);
+ return 0;
+ }
+
+ i = find_string_var (name);
+
+ /* For the time being, unknown variable names or string names without a
+ handler function are simply ignored. */
+ if (i < 0 || string_varlist[i].set_func == 0)
+ return 0;
+
+ v = (*string_varlist[i].set_func) (value);
+ return v;
+}
+
+static int
+sv_editmode (value)
+ const char *value;
+{
+ if (_rl_strnicmp (value, "vi", 2) == 0)
+ {
+#if defined (VI_MODE)
+ _rl_keymap = vi_insertion_keymap;
+ rl_editing_mode = vi_mode;
+#endif /* VI_MODE */
+ return 0;
+ }
+ else if (_rl_strnicmp (value, "emacs", 5) == 0)
+ {
+ _rl_keymap = emacs_standard_keymap;
+ rl_editing_mode = emacs_mode;
+ return 0;
+ }
+ return 1;
+}
+
+static int
+sv_combegin (value)
+ const char *value;
+{
+ if (value && *value)
+ {
+ FREE (_rl_comment_begin);
+ _rl_comment_begin = savestring (value);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+sv_compquery (value)
+ const char *value;
+{
+ int nval = 100;
+
+ if (value && *value)
+ {
+ nval = atoi (value);
+ if (nval < 0)
+ nval = 0;
+ }
+ rl_completion_query_items = nval;
+ return 0;
+}
+
+static int
+sv_keymap (value)
+ const char *value;
+{
+ Keymap kmap;
+
+ kmap = rl_get_keymap_by_name (value);
+ if (kmap)
+ {
+ rl_set_keymap (kmap);
+ return 0;
+ }
+ return 1;
+}
+
+static int
+sv_bell_style (value)
+ const char *value;
+{
+ if (value == 0 || *value == '\0')
+ _rl_bell_preference = AUDIBLE_BELL;
+ else if (_rl_stricmp (value, "none") == 0 || _rl_stricmp (value, "off") == 0)
+ _rl_bell_preference = NO_BELL;
+ else if (_rl_stricmp (value, "audible") == 0 || _rl_stricmp (value, "on") == 0)
+ _rl_bell_preference = AUDIBLE_BELL;
+ else if (_rl_stricmp (value, "visible") == 0)
+ _rl_bell_preference = VISIBLE_BELL;
+ else
+ return 1;
+ return 0;
+}
+
+static int
+sv_isrchterm (value)
+ const char *value;
+{
+ int beg, end, delim;
+ char *v;
+
+ if (value == 0)
+ return 1;
+
+ /* Isolate the value and translate it into a character string. */
+ v = savestring (value);
+ FREE (_rl_isearch_terminators);
+ if (v[0] == '"' || v[0] == '\'')
+ {
+ delim = v[0];
+ for (beg = end = 1; v[end] && v[end] != delim; end++)
+ ;
+ }
+ else
+ {
+ for (beg = end = 0; whitespace (v[end]) == 0; end++)
+ ;
+ }
+
+ v[end] = '\0';
+
+ /* The value starts at v + beg. Translate it into a character string. */
+ _rl_isearch_terminators = (char *)xmalloc (2 * strlen (v) + 1);
+ rl_translate_keyseq (v + beg, _rl_isearch_terminators, &end);
+ _rl_isearch_terminators[end] = '\0';
+
+ free (v);
+ return 0;
+}
+
+/* Return the character which matches NAME.
+ For example, `Space' returns ' '. */
+
+typedef struct {
+ const char *name;
+ int value;
+} assoc_list;
+
+static assoc_list name_key_alist[] = {
+ { "DEL", 0x7f },
+ { "ESC", '\033' },
+ { "Escape", '\033' },
+ { "LFD", '\n' },
+ { "Newline", '\n' },
+ { "RET", '\r' },
+ { "Return", '\r' },
+ { "Rubout", 0x7f },
+ { "SPC", ' ' },
+ { "Space", ' ' },
+ { "Tab", 0x09 },
+ { (char *)0x0, 0 }
+};
+
+static int
+glean_key_from_name (name)
+ char *name;
+{
+ register int i;
+
+ for (i = 0; name_key_alist[i].name; i++)
+ if (_rl_stricmp (name, name_key_alist[i].name) == 0)
+ return (name_key_alist[i].value);
+
+ return (*(unsigned char *)name); /* XXX was return (*name) */
+}
+
+/* Auxiliary functions to manage keymaps. */
+static struct {
+ const char *name;
+ Keymap map;
+} keymap_names[] = {
+ { "emacs", emacs_standard_keymap },
+ { "emacs-standard", emacs_standard_keymap },
+ { "emacs-meta", emacs_meta_keymap },
+ { "emacs-ctlx", emacs_ctlx_keymap },
+#if defined (VI_MODE)
+ { "vi", vi_movement_keymap },
+ { "vi-move", vi_movement_keymap },
+ { "vi-command", vi_movement_keymap },
+ { "vi-insert", vi_insertion_keymap },
+#endif /* VI_MODE */
+ { (char *)0x0, (Keymap)0x0 }
+};
+
+Keymap
+rl_get_keymap_by_name (name)
+ const char *name;
+{
+ register int i;
+
+ for (i = 0; keymap_names[i].name; i++)
+ if (_rl_stricmp (name, keymap_names[i].name) == 0)
+ return (keymap_names[i].map);
+ return ((Keymap) NULL);
+}
+
+char *
+rl_get_keymap_name (map)
+ Keymap map;
+{
+ register int i;
+ for (i = 0; keymap_names[i].name; i++)
+ if (map == keymap_names[i].map)
+ return ((char *)keymap_names[i].name);
+ return ((char *)NULL);
+}
+
+void
+rl_set_keymap (map)
+ Keymap map;
+{
+ if (map)
+ _rl_keymap = map;
+}
+
+Keymap
+rl_get_keymap ()
+{
+ return (_rl_keymap);
+}
+
+void
+rl_set_keymap_from_edit_mode ()
+{
+ if (rl_editing_mode == emacs_mode)
+ _rl_keymap = emacs_standard_keymap;
+#if defined (VI_MODE)
+ else if (rl_editing_mode == vi_mode)
+ _rl_keymap = vi_insertion_keymap;
+#endif /* VI_MODE */
+}
+
+char *
+rl_get_keymap_name_from_edit_mode ()
+{
+ if (rl_editing_mode == emacs_mode)
+ return "emacs";
+#if defined (VI_MODE)
+ else if (rl_editing_mode == vi_mode)
+ return "vi";
+#endif /* VI_MODE */
+ else
+ return "none";
+}
+
+/* **************************************************************** */
+/* */
+/* Key Binding and Function Information */
+/* */
+/* **************************************************************** */
+
+/* Each of the following functions produces information about the
+ state of keybindings and functions known to Readline. The info
+ is always printed to rl_outstream, and in such a way that it can
+ be read back in (i.e., passed to rl_parse_and_bind ()). */
+
+/* Print the names of functions known to Readline. */
+void
+rl_list_funmap_names ()
+{
+ register int i;
+ const char **funmap_names;
+
+ funmap_names = rl_funmap_names ();
+
+ if (!funmap_names)
+ return;
+
+ for (i = 0; funmap_names[i]; i++)
+ fprintf (rl_outstream, "%s\n", funmap_names[i]);
+
+ free (funmap_names);
+}
+
+static char *
+_rl_get_keyname (key)
+ int key;
+{
+ char *keyname;
+ int i, c;
+
+ keyname = (char *)xmalloc (8);
+
+ c = key;
+ /* Since this is going to be used to write out keysequence-function
+ pairs for possible inclusion in an inputrc file, we don't want to
+ do any special meta processing on KEY. */
+
+#if 1
+ /* XXX - Experimental */
+ /* We might want to do this, but the old version of the code did not. */
+
+ /* If this is an escape character, we don't want to do any more processing.
+ Just add the special ESC key sequence and return. */
+ if (c == ESC)
+ {
+ keyname[0] = '\\';
+ keyname[1] = 'e';
+ keyname[2] = '\0';
+ return keyname;
+ }
+#endif
+
+ /* RUBOUT is translated directly into \C-? */
+ if (key == RUBOUT)
+ {
+ keyname[0] = '\\';
+ keyname[1] = 'C';
+ keyname[2] = '-';
+ keyname[3] = '?';
+ keyname[4] = '\0';
+ return keyname;
+ }
+
+ i = 0;
+ /* Now add special prefixes needed for control characters. This can
+ potentially change C. */
+ if (CTRL_CHAR (c))
+ {
+ keyname[i++] = '\\';
+ keyname[i++] = 'C';
+ keyname[i++] = '-';
+ c = _rl_to_lower (UNCTRL (c));
+ }
+
+ /* XXX experimental code. Turn the characters that are not ASCII or
+ ISO Latin 1 (128 - 159) into octal escape sequences (\200 - \237).
+ This changes C. */
+ if (c >= 128 && c <= 159)
+ {
+ keyname[i++] = '\\';
+ keyname[i++] = '2';
+ c -= 128;
+ keyname[i++] = (c / 8) + '0';
+ c = (c % 8) + '0';
+ }
+
+ /* Now, if the character needs to be quoted with a backslash, do that. */
+ if (c == '\\' || c == '"')
+ keyname[i++] = '\\';
+
+ /* Now add the key, terminate the string, and return it. */
+ keyname[i++] = (char) c;
+ keyname[i] = '\0';
+
+ return keyname;
+}
+
+/* Return a NULL terminated array of strings which represent the key
+ sequences that are used to invoke FUNCTION in MAP. */
+char **
+rl_invoking_keyseqs_in_map (function, map)
+ rl_command_func_t *function;
+ Keymap map;
+{
+ register int key;
+ char **result;
+ int result_index, result_size;
+
+ result = (char **)NULL;
+ result_index = result_size = 0;
+
+ for (key = 0; key < KEYMAP_SIZE; key++)
+ {
+ switch (map[key].type)
+ {
+ case ISMACR:
+ /* Macros match, if, and only if, the pointers are identical.
+ Thus, they are treated exactly like functions in here. */
+ case ISFUNC:
+ /* If the function in the keymap is the one we are looking for,
+ then add the current KEY to the list of invoking keys. */
+ if (map[key].function == function)
+ {
+ char *keyname;
+
+ keyname = _rl_get_keyname (key);
+
+ if (result_index + 2 > result_size)
+ {
+ result_size += 10;
+ result = (char **)xrealloc (result, result_size * sizeof (char *));
+ }
+
+ result[result_index++] = keyname;
+ result[result_index] = (char *)NULL;
+ }
+ break;
+
+ case ISKMAP:
+ {
+ char **seqs;
+ register int i;
+
+ /* Find the list of keyseqs in this map which have FUNCTION as
+ their target. Add the key sequences found to RESULT. */
+ if (map[key].function)
+ seqs =
+ rl_invoking_keyseqs_in_map (function, FUNCTION_TO_KEYMAP (map, key));
+ else
+ break;
+
+ if (seqs == 0)
+ break;
+
+ for (i = 0; seqs[i]; i++)
+ {
+ char *keyname = (char *)xmalloc (6 + strlen (seqs[i]));
+
+ if (key == ESC)
+#if 0
+ sprintf (keyname, "\\e");
+#else
+ /* XXX - experimental */
+ sprintf (keyname, "\\M-");
+#endif
+ else if (CTRL_CHAR (key))
+ sprintf (keyname, "\\C-%c", _rl_to_lower (UNCTRL (key)));
+ else if (key == RUBOUT)
+ sprintf (keyname, "\\C-?");
+ else if (key == '\\' || key == '"')
+ {
+ keyname[0] = '\\';
+ keyname[1] = (char) key;
+ keyname[2] = '\0';
+ }
+ else
+ {
+ keyname[0] = (char) key;
+ keyname[1] = '\0';
+ }
+
+ strcat (keyname, seqs[i]);
+ free (seqs[i]);
+
+ if (result_index + 2 > result_size)
+ {
+ result_size += 10;
+ result = (char **)xrealloc (result, result_size * sizeof (char *));
+ }
+
+ result[result_index++] = keyname;
+ result[result_index] = (char *)NULL;
+ }
+
+ free (seqs);
+ }
+ break;
+ }
+ }
+ return (result);
+}
+
+/* Return a NULL terminated array of strings which represent the key
+ sequences that can be used to invoke FUNCTION using the current keymap. */
+char **
+rl_invoking_keyseqs (function)
+ rl_command_func_t *function;
+{
+ return (rl_invoking_keyseqs_in_map (function, _rl_keymap));
+}
+
+/* Print all of the functions and their bindings to rl_outstream. If
+ PRINT_READABLY is non-zero, then print the output in such a way
+ that it can be read back in. */
+void
+rl_function_dumper (print_readably)
+ int print_readably;
+{
+ register int i;
+ const char **names;
+ const char *name;
+
+ names = rl_funmap_names ();
+
+ fprintf (rl_outstream, "\n");
+
+ for (i = 0; name = names[i]; i++)
+ {
+ rl_command_func_t *function;
+ char **invokers;
+
+ function = rl_named_function (name);
+ invokers = rl_invoking_keyseqs_in_map (function, _rl_keymap);
+
+ if (print_readably)
+ {
+ if (!invokers)
+ fprintf (rl_outstream, "# %s (not bound)\n", name);
+ else
+ {
+ register int j;
+
+ for (j = 0; invokers[j]; j++)
+ {
+ fprintf (rl_outstream, "\"%s\": %s\n",
+ invokers[j], name);
+ free (invokers[j]);
+ }
+
+ free (invokers);
+ }
+ }
+ else
+ {
+ if (!invokers)
+ fprintf (rl_outstream, "%s is not bound to any keys\n",
+ name);
+ else
+ {
+ register int j;
+
+ fprintf (rl_outstream, "%s can be found on ", name);
+
+ for (j = 0; invokers[j] && j < 5; j++)
+ {
+ fprintf (rl_outstream, "\"%s\"%s", invokers[j],
+ invokers[j + 1] ? ", " : ".\n");
+ }
+
+ if (j == 5 && invokers[j])
+ fprintf (rl_outstream, "...\n");
+
+ for (j = 0; invokers[j]; j++)
+ free (invokers[j]);
+
+ free (invokers);
+ }
+ }
+ }
+}
+
+/* Print all of the current functions and their bindings to
+ rl_outstream. If an explicit argument is given, then print
+ the output in such a way that it can be read back in. */
+int
+rl_dump_functions (count, key)
+ int count, key;
+{
+ if (rl_dispatching)
+ fprintf (rl_outstream, "\r\n");
+ rl_function_dumper (rl_explicit_arg);
+ rl_on_new_line ();
+ return (0);
+}
+
+static void
+_rl_macro_dumper_internal (print_readably, map, prefix)
+ int print_readably;
+ Keymap map;
+ char *prefix;
+{
+ register int key;
+ char *keyname, *out;
+ int prefix_len;
+
+ for (key = 0; key < KEYMAP_SIZE; key++)
+ {
+ switch (map[key].type)
+ {
+ case ISMACR:
+ keyname = _rl_get_keyname (key);
+ out = _rl_untranslate_macro_value ((char *)map[key].function);
+
+ if (print_readably)
+ fprintf (rl_outstream, "\"%s%s\": \"%s\"\n", prefix ? prefix : "",
+ keyname,
+ out ? out : "");
+ else
+ fprintf (rl_outstream, "%s%s outputs %s\n", prefix ? prefix : "",
+ keyname,
+ out ? out : "");
+ free (keyname);
+ free (out);
+ break;
+ case ISFUNC:
+ break;
+ case ISKMAP:
+ prefix_len = prefix ? strlen (prefix) : 0;
+ if (key == ESC)
+ {
+ keyname = (char *)xmalloc (3 + prefix_len);
+ if (prefix)
+ strcpy (keyname, prefix);
+ keyname[prefix_len] = '\\';
+ keyname[prefix_len + 1] = 'e';
+ keyname[prefix_len + 2] = '\0';
+ }
+ else
+ {
+ keyname = _rl_get_keyname (key);
+ if (prefix)
+ {
+ out = (char *)xmalloc (strlen (keyname) + prefix_len + 1);
+ strcpy (out, prefix);
+ strcpy (out + prefix_len, keyname);
+ free (keyname);
+ keyname = out;
+ }
+ }
+
+ _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
+ free (keyname);
+ break;
+ }
+ }
+}
+
+void
+rl_macro_dumper (print_readably)
+ int print_readably;
+{
+ _rl_macro_dumper_internal (print_readably, _rl_keymap, (char *)NULL);
+}
+
+int
+rl_dump_macros (count, key)
+ int count, key;
+{
+ if (rl_dispatching)
+ fprintf (rl_outstream, "\r\n");
+ rl_macro_dumper (rl_explicit_arg);
+ rl_on_new_line ();
+ return (0);
+}
+
+static char *
+_rl_get_string_variable_value (name)
+ const char *name;
+{
+ static char numbuf[32];
+ char *ret;
+
+ if (_rl_stricmp (name, "bell-style") == 0)
+ {
+ switch (_rl_bell_preference)
+ {
+ case NO_BELL:
+ return "none";
+ case VISIBLE_BELL:
+ return "visible";
+ case AUDIBLE_BELL:
+ default:
+ return "audible";
+ }
+ }
+ else if (_rl_stricmp (name, "comment-begin") == 0)
+ return (_rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT);
+ else if (_rl_stricmp (name, "completion-query-items") == 0)
+ {
+ sprintf (numbuf, "%d", rl_completion_query_items);
+ return (numbuf);
+ }
+ else if (_rl_stricmp (name, "editing-mode") == 0)
+ return (rl_get_keymap_name_from_edit_mode ());
+ else if (_rl_stricmp (name, "isearch-terminators") == 0)
+ {
+ if (_rl_isearch_terminators == 0)
+ return 0;
+ ret = _rl_untranslate_macro_value (_rl_isearch_terminators);
+ if (ret)
+ {
+ strncpy (numbuf, ret, sizeof (numbuf) - 1);
+ free (ret);
+ numbuf[sizeof(numbuf) - 1] = '\0';
+ }
+ else
+ numbuf[0] = '\0';
+ return numbuf;
+ }
+ else if (_rl_stricmp (name, "keymap") == 0)
+ {
+ ret = rl_get_keymap_name (_rl_keymap);
+ if (ret == 0)
+ ret = rl_get_keymap_name_from_edit_mode ();
+ return (ret ? ret : "none");
+ }
+ else
+ return (0);
+}
+
+void
+rl_variable_dumper (print_readably)
+ int print_readably;
+{
+ int i;
+ char *v;
+
+ for (i = 0; boolean_varlist[i].name; i++)
+ {
+ if (print_readably)
+ fprintf (rl_outstream, "set %s %s\n", boolean_varlist[i].name,
+ *boolean_varlist[i].value ? "on" : "off");
+ else
+ fprintf (rl_outstream, "%s is set to `%s'\n", boolean_varlist[i].name,
+ *boolean_varlist[i].value ? "on" : "off");
+ }
+
+ for (i = 0; string_varlist[i].name; i++)
+ {
+ v = _rl_get_string_variable_value (string_varlist[i].name);
+ if (v == 0) /* _rl_isearch_terminators can be NULL */
+ continue;
+ if (print_readably)
+ fprintf (rl_outstream, "set %s %s\n", string_varlist[i].name, v);
+ else
+ fprintf (rl_outstream, "%s is set to `%s'\n", string_varlist[i].name, v);
+ }
+}
+
+/* Print all of the current variables and their values to
+ rl_outstream. If an explicit argument is given, then print
+ the output in such a way that it can be read back in. */
+int
+rl_dump_variables (count, key)
+ int count, key;
+{
+ if (rl_dispatching)
+ fprintf (rl_outstream, "\r\n");
+ rl_variable_dumper (rl_explicit_arg);
+ rl_on_new_line ();
+ return (0);
+}
+
+/* Return non-zero if any members of ARRAY are a substring in STRING. */
+static int
+substring_member_of_array (string, array)
+ char *string;
+ const char **array;
+{
+ while (*array)
+ {
+ if (_rl_strindex (string, *array))
+ return (1);
+ array++;
+ }
+ return (0);
+}
diff --git a/lib/readline/callback.c b/lib/readline/callback.c
index 9120969c..697066e0 100644
--- a/lib/readline/callback.c
+++ b/lib/readline/callback.c
@@ -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. */
diff --git a/lib/readline/callback.c~ b/lib/readline/callback.c~
new file mode 100644
index 00000000..9120969c
--- /dev/null
+++ b/lib/readline/callback.c~
@@ -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
diff --git a/lib/readline/display.c b/lib/readline/display.c
index 13075137..62d7b01c 100644
--- a/lib/readline/display.c
+++ b/lib/readline/display.c
@@ -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
diff --git a/lib/readline/display.c~ b/lib/readline/display.c~
index b22521bf..e0a4bcf4 100644
--- a/lib/readline/display.c~
+++ b/lib/readline/display.c~
@@ -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;
}
diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c
index d7d8520e..9f67bfc0 100644
--- a/lib/readline/isearch.c
+++ b/lib/readline/isearch.c
@@ -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;
diff --git a/lib/readline/isearch.c~ b/lib/readline/isearch.c~
new file mode 100644
index 00000000..d7d8520e
--- /dev/null
+++ b/lib/readline/isearch.c~
@@ -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
diff --git a/lib/readline/misc.c b/lib/readline/misc.c
index d4558321..94ecb259 100644
--- a/lib/readline/misc.c
+++ b/lib/readline/misc.c
@@ -212,6 +212,8 @@ rl_digit_loop ()
if (r <= 0 || (RL_ISSTATE (RL_STATE_NUMERICARG) == 0))
break;
}
+
+ return r;
}
/* Create a default argument. */
diff --git a/lib/readline/misc.c~ b/lib/readline/misc.c~
new file mode 100644
index 00000000..d4558321
--- /dev/null
+++ b/lib/readline/misc.c~
@@ -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;
+}
diff --git a/lib/readline/rltty.c b/lib/readline/rltty.c
index 9a0326ed..0a570f85 100644
--- a/lib/readline/rltty.c
+++ b/lib/readline/rltty.c
@@ -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);
diff --git a/lib/readline/rltty.c~ b/lib/readline/rltty.c~
new file mode 100644
index 00000000..9a0326ed
--- /dev/null
+++ b/lib/readline/rltty.c~
@@ -0,0 +1,1035 @@
+/* rltty.c -- functions to prepare and restore the terminal for readline's
+ use. */
+
+/* Copyright (C) 1992-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 <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL)
+# include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL */
+
+#include "rltty.h"
+#include "readline.h"
+#include "rlprivate.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
+rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
+
+static void block_sigint PARAMS((void));
+static void release_sigint PARAMS((void));
+
+static void set_winsize PARAMS((int));
+
+/* **************************************************************** */
+/* */
+/* Signal Management */
+/* */
+/* **************************************************************** */
+
+#if defined (HAVE_POSIX_SIGNALS)
+static sigset_t sigint_set, sigint_oset;
+#else /* !HAVE_POSIX_SIGNALS */
+# if defined (HAVE_BSD_SIGNALS)
+static int sigint_oldmask;
+# endif /* HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+static int sigint_blocked;
+
+/* Cause SIGINT to not be delivered until the corresponding call to
+ release_sigint(). */
+static void
+block_sigint ()
+{
+ if (sigint_blocked)
+ return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+ sigemptyset (&sigint_set);
+ sigemptyset (&sigint_oset);
+ sigaddset (&sigint_set, SIGINT);
+ sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
+#else /* !HAVE_POSIX_SIGNALS */
+# if defined (HAVE_BSD_SIGNALS)
+ sigint_oldmask = sigblock (sigmask (SIGINT));
+# else /* !HAVE_BSD_SIGNALS */
+# if defined (HAVE_USG_SIGHOLD)
+ sighold (SIGINT);
+# endif /* HAVE_USG_SIGHOLD */
+# endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ sigint_blocked = 1;
+}
+
+/* Allow SIGINT to be delivered. */
+static void
+release_sigint ()
+{
+ if (sigint_blocked == 0)
+ return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+ sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
+#else
+# if defined (HAVE_BSD_SIGNALS)
+ sigsetmask (sigint_oldmask);
+# else /* !HAVE_BSD_SIGNALS */
+# if defined (HAVE_USG_SIGHOLD)
+ sigrelse (SIGINT);
+# endif /* HAVE_USG_SIGHOLD */
+# endif /* !HAVE_BSD_SIGNALS */
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ sigint_blocked = 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Saving and Restoring the TTY */
+/* */
+/* **************************************************************** */
+
+/* Non-zero means that the terminal is in a prepped state. */
+static int terminal_prepped;
+
+static _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars;
+
+/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
+ and output is suspended. */
+#if defined (__ksr1__)
+static int ksrflow;
+#endif
+
+/* Dummy call to force a backgrounded readline to stop before it tries
+ to get the tty settings. */
+static void
+set_winsize (tty)
+ int tty;
+{
+#if defined (TIOCGWINSZ)
+ struct winsize w;
+
+ if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+ (void) ioctl (tty, TIOCSWINSZ, &w);
+#endif /* TIOCGWINSZ */
+}
+
+#if defined (NO_TTY_DRIVER)
+/* Nothing */
+#elif defined (NEW_TTY_DRIVER)
+
+/* Values for the `flags' field of a struct bsdtty. This tells which
+ elements of the struct bsdtty have been fetched from the system and
+ are valid. */
+#define SGTTY_SET 0x01
+#define LFLAG_SET 0x02
+#define TCHARS_SET 0x04
+#define LTCHARS_SET 0x08
+
+struct bsdtty {
+ struct sgttyb sgttyb; /* Basic BSD tty driver information. */
+ int lflag; /* Local mode flags, like LPASS8. */
+#if defined (TIOCGETC)
+ struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */
+#endif
+#if defined (TIOCGLTC)
+ struct ltchars ltchars; /* 4.2 BSD editing characters */
+#endif
+ int flags; /* Bitmap saying which parts of the struct are valid. */
+};
+
+#define TIOTYPE struct bsdtty
+
+static TIOTYPE otio;
+
+static void save_tty_chars PARAMS((TIOTYPE *));
+static int _get_tty_settings PARAMS((int, TIOTYPE *));
+static int get_tty_settings PARAMS((int, TIOTYPE *));
+static int _set_tty_settings PARAMS((int, TIOTYPE *));
+static int set_tty_settings PARAMS((int, TIOTYPE *));
+
+static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+
+static void
+save_tty_chars (tiop)
+ TIOTYPE *tiop;
+{
+ _rl_last_tty_chars = _rl_tty_chars;
+
+ if (tiop->flags & SGTTY_SET)
+ {
+ _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase;
+ _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill;
+ }
+
+ if (tiop->flags & TCHARS_SET)
+ {
+ _rl_tty_chars.t_intr = tiop->tchars.t_intrc;
+ _rl_tty_chars.t_quit = tiop->tchars.t_quitc;
+ _rl_tty_chars.t_start = tiop->tchars.t_startc;
+ _rl_tty_chars.t_stop = tiop->tchars.t_stopc;
+ _rl_tty_chars.t_eof = tiop->tchars.t_eofc;
+ _rl_tty_chars.t_eol = '\n';
+ _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc;
+ }
+
+ if (tiop->flags & LTCHARS_SET)
+ {
+ _rl_tty_chars.t_susp = tiop->ltchars.t_suspc;
+ _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc;
+ _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc;
+ _rl_tty_chars.t_flush = tiop->ltchars.t_flushc;
+ _rl_tty_chars.t_werase = tiop->ltchars.t_werasc;
+ _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc;
+ }
+
+ _rl_tty_chars.t_status = -1;
+}
+
+static int
+get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ set_winsize (tty);
+
+ tiop->flags = tiop->lflag = 0;
+
+ errno = 0;
+ if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0)
+ return -1;
+ tiop->flags |= SGTTY_SET;
+
+#if defined (TIOCLGET)
+ if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0)
+ tiop->flags |= LFLAG_SET;
+#endif
+
+#if defined (TIOCGETC)
+ if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0)
+ tiop->flags |= TCHARS_SET;
+#endif
+
+#if defined (TIOCGLTC)
+ if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0)
+ tiop->flags |= LTCHARS_SET;
+#endif
+
+ return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ if (tiop->flags & SGTTY_SET)
+ {
+ ioctl (tty, TIOCSETN, &(tiop->sgttyb));
+ tiop->flags &= ~SGTTY_SET;
+ }
+ readline_echoing_p = 1;
+
+#if defined (TIOCLSET)
+ if (tiop->flags & LFLAG_SET)
+ {
+ ioctl (tty, TIOCLSET, &(tiop->lflag));
+ tiop->flags &= ~LFLAG_SET;
+ }
+#endif
+
+#if defined (TIOCSETC)
+ if (tiop->flags & TCHARS_SET)
+ {
+ ioctl (tty, TIOCSETC, &(tiop->tchars));
+ tiop->flags &= ~TCHARS_SET;
+ }
+#endif
+
+#if defined (TIOCSLTC)
+ if (tiop->flags & LTCHARS_SET)
+ {
+ ioctl (tty, TIOCSLTC, &(tiop->ltchars));
+ tiop->flags &= ~LTCHARS_SET;
+ }
+#endif
+
+ return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, oldtio, tiop)
+ int meta_flag;
+ TIOTYPE oldtio, *tiop;
+{
+ readline_echoing_p = (oldtio.sgttyb.sg_flags & ECHO);
+
+ /* Copy the original settings to the structure we're going to use for
+ our settings. */
+ tiop->sgttyb = oldtio.sgttyb;
+ tiop->lflag = oldtio.lflag;
+#if defined (TIOCGETC)
+ tiop->tchars = oldtio.tchars;
+#endif
+#if defined (TIOCGLTC)
+ tiop->ltchars = oldtio.ltchars;
+#endif
+ tiop->flags = oldtio.flags;
+
+ /* First, the basic settings to put us into character-at-a-time, no-echo
+ input mode. */
+ tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
+ tiop->sgttyb.sg_flags |= CBREAK;
+
+ /* If this terminal doesn't care how the 8th bit is used, then we can
+ use it for the meta-key. If only one of even or odd parity is
+ specified, then the terminal is using parity, and we cannot. */
+#if !defined (ANYP)
+# define ANYP (EVENP | ODDP)
+#endif
+ if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) ||
+ ((oldtio.sgttyb.sg_flags & ANYP) == 0))
+ {
+ tiop->sgttyb.sg_flags |= ANYP;
+
+ /* Hack on local mode flags if we can. */
+#if defined (TIOCLGET)
+# if defined (LPASS8)
+ tiop->lflag |= LPASS8;
+# endif /* LPASS8 */
+#endif /* TIOCLGET */
+ }
+
+#if defined (TIOCGETC)
+# if defined (USE_XON_XOFF)
+ /* Get rid of terminal output start and stop characters. */
+ tiop->tchars.t_stopc = -1; /* C-s */
+ tiop->tchars.t_startc = -1; /* C-q */
+
+ /* If there is an XON character, bind it to restart the output. */
+ if (oldtio.tchars.t_startc != -1)
+ rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
+# endif /* USE_XON_XOFF */
+
+ /* If there is an EOF char, bind _rl_eof_char to it. */
+ if (oldtio.tchars.t_eofc != -1)
+ _rl_eof_char = oldtio.tchars.t_eofc;
+
+# if defined (NO_KILL_INTR)
+ /* Get rid of terminal-generated SIGQUIT and SIGINT. */
+ tiop->tchars.t_quitc = -1; /* C-\ */
+ tiop->tchars.t_intrc = -1; /* C-c */
+# endif /* NO_KILL_INTR */
+#endif /* TIOCGETC */
+
+#if defined (TIOCGLTC)
+ /* Make the interrupt keys go away. Just enough to make people happy. */
+ tiop->ltchars.t_dsuspc = -1; /* C-y */
+ tiop->ltchars.t_lnextc = -1; /* C-v */
+#endif /* TIOCGLTC */
+}
+
+#else /* !defined (NEW_TTY_DRIVER) */
+
+#if !defined (VMIN)
+# define VMIN VEOF
+#endif
+
+#if !defined (VTIME)
+# define VTIME VEOL
+#endif
+
+#if defined (TERMIOS_TTY_DRIVER)
+# define TIOTYPE struct termios
+# define DRAIN_OUTPUT(fd) tcdrain (fd)
+# define GETATTR(tty, tiop) (tcgetattr (tty, tiop))
+# ifdef M_UNIX
+# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop))
+# else
+# define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop))
+# endif /* !M_UNIX */
+#else
+# define TIOTYPE struct termio
+# define DRAIN_OUTPUT(fd)
+# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop))
+# define SETATTR(tty, tiop) (ioctl (tty, TCSETAW, tiop))
+#endif /* !TERMIOS_TTY_DRIVER */
+
+static TIOTYPE otio;
+
+static void save_tty_chars PARAMS((TIOTYPE *));
+static int _get_tty_settings PARAMS((int, TIOTYPE *));
+static int get_tty_settings PARAMS((int, TIOTYPE *));
+static int _set_tty_settings PARAMS((int, TIOTYPE *));
+static int set_tty_settings PARAMS((int, TIOTYPE *));
+
+static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
+
+#if defined (FLUSHO)
+# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
+#else
+# define OUTPUT_BEING_FLUSHED(tp) 0
+#endif
+
+static void
+save_tty_chars (tiop)
+ TIOTYPE *tiop;
+{
+ _rl_last_tty_chars = _rl_tty_chars;
+
+ _rl_tty_chars.t_eof = tiop->c_cc[VEOF];
+ _rl_tty_chars.t_eol = tiop->c_cc[VEOL];
+#ifdef VEOL2
+ _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2];
+#endif
+ _rl_tty_chars.t_erase = tiop->c_cc[VERASE];
+#ifdef VWERASE
+ _rl_tty_chars.t_werase = tiop->c_cc[VWERASE];
+#endif
+ _rl_tty_chars.t_kill = tiop->c_cc[VKILL];
+#ifdef VREPRINT
+ _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT];
+#endif
+ _rl_tty_chars.t_intr = tiop->c_cc[VINTR];
+ _rl_tty_chars.t_quit = tiop->c_cc[VQUIT];
+#ifdef VSUSP
+ _rl_tty_chars.t_susp = tiop->c_cc[VSUSP];
+#endif
+#ifdef VDSUSP
+ _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP];
+#endif
+#ifdef VSTART
+ _rl_tty_chars.t_start = tiop->c_cc[VSTART];
+#endif
+#ifdef VSTOP
+ _rl_tty_chars.t_stop = tiop->c_cc[VSTOP];
+#endif
+#ifdef VLNEXT
+ _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT];
+#endif
+#ifdef VDISCARD
+ _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD];
+#endif
+#ifdef VSTATUS
+ _rl_tty_chars.t_status = tiop->c_cc[VSTATUS];
+#endif
+}
+
+#if defined (_AIX) || defined (_AIX41)
+/* Currently this is only used on AIX */
+static void
+rltty_warning (msg)
+ char *msg;
+{
+ fprintf (stderr, "readline: warning: %s\n", msg);
+}
+#endif
+
+#if defined (_AIX)
+void
+setopost(tp)
+TIOTYPE *tp;
+{
+ if ((tp->c_oflag & OPOST) == 0)
+ {
+ rltty_warning ("turning on OPOST for terminal\r");
+ tp->c_oflag |= OPOST|ONLCR;
+ }
+}
+#endif
+
+static int
+_get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ int ioctl_ret;
+
+ while (1)
+ {
+ ioctl_ret = GETATTR (tty, tiop);
+ if (ioctl_ret < 0)
+ {
+ if (errno != EINTR)
+ return -1;
+ else
+ continue;
+ }
+ if (OUTPUT_BEING_FLUSHED (tiop))
+ {
+#if defined (FLUSHO) && defined (_AIX41)
+ rltty_warning ("turning off output flushing");
+ tiop->c_lflag &= ~FLUSHO;
+ break;
+#else
+ continue;
+#endif
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int
+get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ set_winsize (tty);
+
+ errno = 0;
+ if (_get_tty_settings (tty, tiop) < 0)
+ return -1;
+
+#if defined (_AIX)
+ setopost(tiop);
+#endif
+
+ return 0;
+}
+
+static int
+_set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ while (SETATTR (tty, tiop) < 0)
+ {
+ if (errno != EINTR)
+ return -1;
+ errno = 0;
+ }
+ return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ if (_set_tty_settings (tty, tiop) < 0)
+ return -1;
+
+#if 0
+
+#if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ if (ksrflow)
+ {
+ ksrflow = 0;
+ tcflow (tty, TCOON);
+ }
+# else /* !ksr1 */
+ tcflow (tty, TCOON); /* Simulate a ^Q. */
+# endif /* !ksr1 */
+#else
+ ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
+#endif /* !TERMIOS_TTY_DRIVER */
+
+#endif /* 0 */
+
+ return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, oldtio, tiop)
+ int meta_flag;
+ TIOTYPE oldtio, *tiop;
+{
+ readline_echoing_p = (oldtio.c_lflag & ECHO);
+
+ tiop->c_lflag &= ~(ICANON | ECHO);
+
+ if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
+ _rl_eof_char = oldtio.c_cc[VEOF];
+
+#if defined (USE_XON_XOFF)
+#if defined (IXANY)
+ tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
+#else
+ /* `strict' Posix systems do not define IXANY. */
+ tiop->c_iflag &= ~(IXON | IXOFF);
+#endif /* IXANY */
+#endif /* USE_XON_XOFF */
+
+ /* Only turn this off if we are using all 8 bits. */
+ if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
+ tiop->c_iflag &= ~(ISTRIP | INPCK);
+
+ /* Make sure we differentiate between CR and NL on input. */
+ tiop->c_iflag &= ~(ICRNL | INLCR);
+
+#if !defined (HANDLE_SIGNALS)
+ tiop->c_lflag &= ~ISIG;
+#else
+ tiop->c_lflag |= ISIG;
+#endif
+
+ tiop->c_cc[VMIN] = 1;
+ tiop->c_cc[VTIME] = 0;
+
+#if defined (FLUSHO)
+ if (OUTPUT_BEING_FLUSHED (tiop))
+ {
+ tiop->c_lflag &= ~FLUSHO;
+ oldtio.c_lflag &= ~FLUSHO;
+ }
+#endif
+
+ /* Turn off characters that we need on Posix systems with job control,
+ just to be sure. This includes ^Y and ^V. This should not really
+ be necessary. */
+#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
+
+#if defined (VLNEXT)
+ tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+
+#if defined (VDSUSP)
+ tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+
+#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
+}
+#endif /* !NEW_TTY_DRIVER */
+
+/* Put the terminal in CBREAK mode so that we can detect key presses. */
+#if defined (NO_TTY_DRIVER)
+void
+rl_prep_terminal (meta_flag)
+ int meta_flag;
+{
+ readline_echoing_p = 1;
+}
+
+void
+rl_deprep_terminal ()
+{
+}
+
+#else /* ! NO_TTY_DRIVER */
+void
+rl_prep_terminal (meta_flag)
+ int meta_flag;
+{
+ int tty;
+ TIOTYPE tio;
+
+ if (terminal_prepped)
+ return;
+
+ /* Try to keep this function from being INTerrupted. */
+ block_sigint ();
+
+ tty = fileno (rl_instream);
+
+ if (get_tty_settings (tty, &tio) < 0)
+ {
+#if defined (ENOTSUP)
+ /* MacOS X, at least, lies about the value of errno if tcgetattr fails. */
+ if (errno == ENOTTY || errno == ENOTSUP)
+#else
+ if (errno == ENOTTY)
+#endif
+ readline_echoing_p = 1; /* XXX */
+ release_sigint ();
+ return;
+ }
+
+ otio = tio;
+
+ if (_rl_bind_stty_chars)
+ {
+#if defined (VI_MODE)
+ /* If editing in vi mode, make sure we restore the bindings in the
+ insertion keymap no matter what keymap we ended up in. */
+ if (rl_editing_mode == vi_mode)
+ rl_tty_unset_default_bindings (vi_insertion_keymap);
+ else
+#endif
+ rl_tty_unset_default_bindings (_rl_keymap);
+ }
+ save_tty_chars (&otio);
+ RL_SETSTATE(RL_STATE_TTYCSAVED);
+ if (_rl_bind_stty_chars)
+ {
+#if defined (VI_MODE)
+ /* If editing in vi mode, make sure we set the bindings in the
+ insertion keymap no matter what keymap we ended up in. */
+ if (rl_editing_mode == vi_mode)
+ _rl_bind_tty_special_chars (vi_insertion_keymap, tio);
+ else
+#endif
+ _rl_bind_tty_special_chars (_rl_keymap, tio);
+ }
+
+ prepare_terminal_settings (meta_flag, otio, &tio);
+
+ if (set_tty_settings (tty, &tio) < 0)
+ {
+ release_sigint ();
+ return;
+ }
+
+ if (_rl_enable_keypad)
+ _rl_control_keypad (1);
+
+ fflush (rl_outstream);
+ terminal_prepped = 1;
+ RL_SETSTATE(RL_STATE_TERMPREPPED);
+
+ release_sigint ();
+}
+
+/* Restore the terminal's normal settings and modes. */
+void
+rl_deprep_terminal ()
+{
+ int tty;
+
+ if (!terminal_prepped)
+ return;
+
+ /* Try to keep this function from being interrupted. */
+ block_sigint ();
+
+ tty = fileno (rl_instream);
+
+ if (_rl_enable_keypad)
+ _rl_control_keypad (0);
+
+ fflush (rl_outstream);
+
+ if (set_tty_settings (tty, &otio) < 0)
+ {
+ release_sigint ();
+ return;
+ }
+
+ terminal_prepped = 0;
+ RL_UNSETSTATE(RL_STATE_TERMPREPPED);
+
+ release_sigint ();
+}
+#endif /* !NO_TTY_DRIVER */
+
+/* **************************************************************** */
+/* */
+/* Bogus Flow Control */
+/* */
+/* **************************************************************** */
+
+int
+rl_restart_output (count, key)
+ int count, key;
+{
+#if defined (__MINGW32__)
+ return 0;
+#else /* !__MING32__ */
+
+ int fildes = fileno (rl_outstream);
+#if defined (TIOCSTART)
+#if defined (apollo)
+ ioctl (&fildes, TIOCSTART, 0);
+#else
+ ioctl (fildes, TIOCSTART, 0);
+#endif /* apollo */
+
+#else /* !TIOCSTART */
+# if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ if (ksrflow)
+ {
+ ksrflow = 0;
+ tcflow (fildes, TCOON);
+ }
+# else /* !ksr1 */
+ tcflow (fildes, TCOON); /* Simulate a ^Q. */
+# endif /* !ksr1 */
+# else /* !TERMIOS_TTY_DRIVER */
+# if defined (TCXONC)
+ ioctl (fildes, TCXONC, TCOON);
+# endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTART */
+
+ return 0;
+#endif /* !__MINGW32__ */
+}
+
+int
+rl_stop_output (count, key)
+ int count, key;
+{
+#if defined (__MINGW32__)
+ return 0;
+#else
+
+ int fildes = fileno (rl_instream);
+
+#if defined (TIOCSTOP)
+# if defined (apollo)
+ ioctl (&fildes, TIOCSTOP, 0);
+# else
+ ioctl (fildes, TIOCSTOP, 0);
+# endif /* apollo */
+#else /* !TIOCSTOP */
+# if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ ksrflow = 1;
+# endif /* ksr1 */
+ tcflow (fildes, TCOOFF);
+# else
+# if defined (TCXONC)
+ ioctl (fildes, TCXONC, TCOON);
+# endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTOP */
+
+ return 0;
+#endif /* !__MINGW32__ */
+}
+
+/* **************************************************************** */
+/* */
+/* Default Key Bindings */
+/* */
+/* **************************************************************** */
+
+#if !defined (NO_TTY_DRIVER)
+#define SET_SPECIAL(sc, func) set_special_char(kmap, &ttybuff, sc, func)
+#endif
+
+#if defined (NO_TTY_DRIVER)
+
+#define SET_SPECIAL(sc, func)
+#define RESET_SPECIAL(c)
+
+#elif defined (NEW_TTY_DRIVER)
+static void
+set_special_char (kmap, tiop, sc, func)
+ Keymap kmap;
+ TIOTYPE *tiop;
+ int sc;
+ rl_command_func_t *func;
+{
+ if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC)
+ kmap[(unsigned char)sc].function = func;
+}
+
+#define RESET_SPECIAL(c) \
+ if (c != -1 && kmap[(unsigned char)c].type == ISFUNC)
+ kmap[(unsigned char)c].function = rl_insert;
+
+static void
+_rl_bind_tty_special_chars (kmap, ttybuff)
+ Keymap kmap;
+ TIOTYPE ttybuff;
+{
+ if (ttybuff.flags & SGTTY_SET)
+ {
+ SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
+ SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
+ }
+
+# if defined (TIOCGLTC)
+ if (ttybuff.flags & LTCHARS_SET)
+ {
+ SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
+ SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
+ }
+# endif /* TIOCGLTC */
+}
+
+#else /* !NEW_TTY_DRIVER */
+static void
+set_special_char (kmap, tiop, sc, func)
+ Keymap kmap;
+ TIOTYPE *tiop;
+ int sc;
+ rl_command_func_t *func;
+{
+ unsigned char uc;
+
+ uc = tiop->c_cc[sc];
+ if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC)
+ kmap[uc].function = func;
+}
+
+/* used later */
+#define RESET_SPECIAL(uc) \
+ if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
+ kmap[uc].function = rl_insert;
+
+static void
+_rl_bind_tty_special_chars (kmap, ttybuff)
+ Keymap kmap;
+ TIOTYPE ttybuff;
+{
+ SET_SPECIAL (VERASE, rl_rubout);
+ SET_SPECIAL (VKILL, rl_unix_line_discard);
+
+# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+ SET_SPECIAL (VLNEXT, rl_quoted_insert);
+# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+ SET_SPECIAL (VWERASE, rl_unix_word_rubout);
+# endif /* VWERASE && TERMIOS_TTY_DRIVER */
+}
+
+#endif /* !NEW_TTY_DRIVER */
+
+/* Set the system's default editing characters to their readline equivalents
+ in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */
+void
+rltty_set_default_bindings (kmap)
+ Keymap kmap;
+{
+#if !defined (NO_TTY_DRIVER)
+ TIOTYPE ttybuff;
+ int tty;
+ static int called = 0;
+
+ tty = fileno (rl_instream);
+
+ if (get_tty_settings (tty, &ttybuff) == 0)
+ _rl_bind_tty_special_chars (kmap, ttybuff);
+#endif
+}
+
+/* New public way to set the system default editing chars to their readline
+ equivalents. */
+void
+rl_tty_set_default_bindings (kmap)
+ Keymap kmap;
+{
+ rltty_set_default_bindings (kmap);
+}
+
+/* Rebind all of the tty special chars that readline worries about back
+ to self-insert. Call this before saving the current terminal special
+ chars with save_tty_chars(). This only works on POSIX termios or termio
+ systems. */
+void
+rl_tty_unset_default_bindings (kmap)
+ Keymap kmap;
+{
+ /* Don't bother before we've saved the tty special chars at least once. */
+ if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0)
+ return;
+
+ RESET_SPECIAL (_rl_tty_chars.t_erase);
+ RESET_SPECIAL (_rl_tty_chars.t_kill);
+
+# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+ RESET_SPECIAL (_rl_tty_chars.t_lnext);
+# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+ RESET_SPECIAL (_rl_tty_chars.t_werase);
+# endif /* VWERASE && TERMIOS_TTY_DRIVER */
+}
+
+#if defined (HANDLE_SIGNALS)
+
+#if defined (NEW_TTY_DRIVER) || defined (NO_TTY_DRIVER)
+int
+_rl_disable_tty_signals ()
+{
+ return 0;
+}
+
+int
+_rl_restore_tty_signals ()
+{
+ return 0;
+}
+#else
+
+static TIOTYPE sigstty, nosigstty;
+static int tty_sigs_disabled = 0;
+
+int
+_rl_disable_tty_signals ()
+{
+ if (tty_sigs_disabled)
+ return 0;
+
+ if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0)
+ return -1;
+
+ nosigstty = sigstty;
+
+ nosigstty.c_lflag &= ~ISIG;
+ nosigstty.c_iflag &= ~IXON;
+
+ if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0)
+ return (_set_tty_settings (fileno (rl_instream), &sigstty));
+
+ tty_sigs_disabled = 1;
+ return 0;
+}
+
+int
+_rl_restore_tty_signals ()
+{
+ int r;
+
+ if (tty_sigs_disabled == 0)
+ return 0;
+
+ r = _set_tty_settings (fileno (rl_instream), &sigstty);
+
+ if (r == 0)
+ tty_sigs_disabled = 0;
+
+ return r;
+}
+#endif /* !NEW_TTY_DRIVER */
+
+#endif /* HANDLE_SIGNALS */
diff --git a/lib/readline/search.c b/lib/readline/search.c
index 8013916c..d199aa14 100644
--- a/lib/readline/search.c
+++ b/lib/readline/search.c
@@ -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));
diff --git a/lib/readline/search.c~ b/lib/readline/search.c~
new file mode 100644
index 00000000..8013916c
--- /dev/null
+++ b/lib/readline/search.c~
@@ -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));
+}
diff --git a/lib/readline/signals.c b/lib/readline/signals.c
index f344ed83..54f2a642 100644
--- a/lib/readline/signals.c
+++ b/lib/readline/signals.c
@@ -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. */
diff --git a/lib/readline/signals.c~ b/lib/readline/signals.c~
new file mode 100644
index 00000000..be6f41fa
--- /dev/null
+++ b/lib/readline/signals.c~
@@ -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 */
diff --git a/lib/readline/text.c b/lib/readline/text.c
index f8d272cc..6c969a88 100644
--- a/lib/readline/text.c
+++ b/lib/readline/text.c
@@ -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
diff --git a/lib/readline/text.c~ b/lib/readline/text.c~
new file mode 100644
index 00000000..f8d272cc
--- /dev/null
+++ b/lib/readline/text.c~
@@ -0,0 +1,1637 @@
+/* text.c -- text handling commands 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
+
+#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"
+
+#if defined (__EMX__)
+# define INCL_DOSPROCESS
+# include <os2.h>
+#endif /* __EMX__ */
+
+/* Some standard library routines. */
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "rlshell.h"
+#include "xmalloc.h"
+
+/* Forward declarations. */
+static int rl_change_case PARAMS((int, int));
+static int _rl_char_search PARAMS((int, int, int));
+
+#if defined (READLINE_CALLBACKS)
+static int _rl_insert_next_callback PARAMS((_rl_callback_generic_arg *));
+static int _rl_char_search_callback PARAMS((_rl_callback_generic_arg *));
+#endif
+
+/* **************************************************************** */
+/* */
+/* Insert and Delete */
+/* */
+/* **************************************************************** */
+
+/* Insert a string of text into the line at point. This is the only
+ way that you should do insertion. _rl_insert_char () calls this
+ function. Returns the number of characters inserted. */
+int
+rl_insert_text (string)
+ const char *string;
+{
+ register int i, l;
+
+ l = (string && *string) ? strlen (string) : 0;
+ if (l == 0)
+ return 0;
+
+ if (rl_end + l >= rl_line_buffer_len)
+ rl_extend_line_buffer (rl_end + l);
+
+ for (i = rl_end; i >= rl_point; i--)
+ rl_line_buffer[i + l] = rl_line_buffer[i];
+ strncpy (rl_line_buffer + rl_point, string, l);
+
+ /* Remember how to undo this if we aren't undoing something. */
+ if (_rl_doing_an_undo == 0)
+ {
+ /* If possible and desirable, concatenate the undos. */
+ if ((l == 1) &&
+ rl_undo_list &&
+ (rl_undo_list->what == UNDO_INSERT) &&
+ (rl_undo_list->end == rl_point) &&
+ (rl_undo_list->end - rl_undo_list->start < 20))
+ rl_undo_list->end++;
+ else
+ rl_add_undo (UNDO_INSERT, rl_point, rl_point + l, (char *)NULL);
+ }
+ rl_point += l;
+ rl_end += l;
+ rl_line_buffer[rl_end] = '\0';
+ return l;
+}
+
+/* Delete the string between FROM and TO. FROM is inclusive, TO is not.
+ Returns the number of characters deleted. */
+int
+rl_delete_text (from, to)
+ int from, to;
+{
+ register char *text;
+ register int diff, i;
+
+ /* Fix it if the caller is confused. */
+ if (from > to)
+ SWAP (from, to);
+
+ /* fix boundaries */
+ if (to > rl_end)
+ {
+ to = rl_end;
+ if (from > to)
+ from = to;
+ }
+ if (from < 0)
+ from = 0;
+
+ text = rl_copy_text (from, to);
+
+ /* Some versions of strncpy() can't handle overlapping arguments. */
+ diff = to - from;
+ for (i = from; i < rl_end - diff; i++)
+ rl_line_buffer[i] = rl_line_buffer[i + diff];
+
+ /* Remember how to undo this delete. */
+ if (_rl_doing_an_undo == 0)
+ rl_add_undo (UNDO_DELETE, from, to, text);
+ else
+ free (text);
+
+ rl_end -= diff;
+ rl_line_buffer[rl_end] = '\0';
+ return (diff);
+}
+
+/* Fix up point so that it is within the line boundaries after killing
+ text. If FIX_MARK_TOO is non-zero, the mark is forced within line
+ boundaries also. */
+
+#define _RL_FIX_POINT(x) \
+ do { \
+ if (x > rl_end) \
+ x = rl_end; \
+ else if (x < 0) \
+ x = 0; \
+ } while (0)
+
+void
+_rl_fix_point (fix_mark_too)
+ int fix_mark_too;
+{
+ _RL_FIX_POINT (rl_point);
+ if (fix_mark_too)
+ _RL_FIX_POINT (rl_mark);
+}
+#undef _RL_FIX_POINT
+
+/* Replace the contents of the line buffer between START and END with
+ TEXT. The operation is undoable. To replace the entire line in an
+ undoable mode, use _rl_replace_text(text, 0, rl_end); */
+int
+_rl_replace_text (text, start, end)
+ const char *text;
+ int start, end;
+{
+ int n;
+
+ rl_begin_undo_group ();
+ rl_delete_text (start, end + 1);
+ rl_point = start;
+ n = rl_insert_text (text);
+ rl_end_undo_group ();
+
+ return n;
+}
+
+/* Replace the current line buffer contents with TEXT. If CLEAR_UNDO is
+ non-zero, we free the current undo list. */
+void
+rl_replace_line (text, clear_undo)
+ const char *text;
+ int clear_undo;
+{
+ int len;
+
+ len = strlen (text);
+ if (len >= rl_line_buffer_len)
+ rl_extend_line_buffer (len);
+ strcpy (rl_line_buffer, text);
+ rl_end = len;
+
+ if (clear_undo)
+ rl_free_undo_list ();
+
+ _rl_fix_point (1);
+}
+
+/* **************************************************************** */
+/* */
+/* Readline character functions */
+/* */
+/* **************************************************************** */
+
+/* This is not a gap editor, just a stupid line input routine. No hair
+ is involved in writing any of the functions, and none should be. */
+
+/* Note that:
+
+ rl_end is the place in the string that we would place '\0';
+ i.e., it is always safe to place '\0' there.
+
+ rl_point is the place in the string where the cursor is. Sometimes
+ this is the same as rl_end.
+
+ Any command that is called interactively receives two arguments.
+ The first is a count: the numeric arg pased to this command.
+ The second is the key which invoked this command.
+*/
+
+/* **************************************************************** */
+/* */
+/* Movement Commands */
+/* */
+/* **************************************************************** */
+
+/* Note that if you `optimize' the display for these functions, you cannot
+ use said functions in other functions which do not do optimizing display.
+ I.e., you will have to update the data base for rl_redisplay, and you
+ might as well let rl_redisplay do that job. */
+
+/* Move forward COUNT bytes. */
+int
+rl_forward_byte (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_backward_byte (-count, key));
+
+ if (count > 0)
+ {
+ int end = rl_point + count;
+#if defined (VI_MODE)
+ int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
+#else
+ int lend = rl_end;
+#endif
+
+ if (end > lend)
+ {
+ rl_point = lend;
+ rl_ding ();
+ }
+ else
+ rl_point = end;
+ }
+
+ if (rl_end < 0)
+ rl_end = 0;
+
+ return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move forward COUNT characters. */
+int
+rl_forward_char (count, key)
+ int count, key;
+{
+ int point;
+
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ return (rl_forward_byte (count, key));
+
+ if (count < 0)
+ return (rl_backward_char (-count, key));
+
+ if (count > 0)
+ {
+ point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+#if defined (VI_MODE)
+ if (rl_end <= point && rl_editing_mode == vi_mode)
+ point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
+#endif
+
+ if (rl_point == point)
+ rl_ding ();
+
+ rl_point = point;
+
+ if (rl_end < 0)
+ rl_end = 0;
+ }
+
+ return 0;
+}
+#else /* !HANDLE_MULTIBYTE */
+int
+rl_forward_char (count, key)
+ int count, key;
+{
+ return (rl_forward_byte (count, key));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+/* Backwards compatibility. */
+int
+rl_forward (count, key)
+ int count, key;
+{
+ return (rl_forward_char (count, key));
+}
+
+/* Move backward COUNT bytes. */
+int
+rl_backward_byte (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_forward_byte (-count, key));
+
+ if (count > 0)
+ {
+ if (rl_point < count)
+ {
+ rl_point = 0;
+ rl_ding ();
+ }
+ else
+ rl_point -= count;
+ }
+
+ if (rl_point < 0)
+ rl_point = 0;
+
+ return 0;
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Move backward COUNT characters. */
+int
+rl_backward_char (count, key)
+ int count, key;
+{
+ int point;
+
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ return (rl_backward_byte (count, key));
+
+ if (count < 0)
+ return (rl_forward_char (-count, key));
+
+ if (count > 0)
+ {
+ point = rl_point;
+
+ while (count > 0 && point > 0)
+ {
+ point = _rl_find_prev_mbchar (rl_line_buffer, point, MB_FIND_NONZERO);
+ count--;
+ }
+ if (count > 0)
+ {
+ rl_point = 0;
+ rl_ding ();
+ }
+ else
+ rl_point = point;
+ }
+
+ return 0;
+}
+#else
+int
+rl_backward_char (count, key)
+ int count, key;
+{
+ return (rl_backward_byte (count, key));
+}
+#endif
+
+/* Backwards compatibility. */
+int
+rl_backward (count, key)
+ int count, key;
+{
+ return (rl_backward_char (count, key));
+}
+
+/* Move to the beginning of the line. */
+int
+rl_beg_of_line (count, key)
+ int count, key;
+{
+ rl_point = 0;
+ return 0;
+}
+
+/* Move to the end of the line. */
+int
+rl_end_of_line (count, key)
+ int count, key;
+{
+ rl_point = rl_end;
+ return 0;
+}
+
+/* Move forward a word. We do what Emacs does. Handles multibyte chars. */
+int
+rl_forward_word (count, key)
+ int count, key;
+{
+ int c;
+
+ if (count < 0)
+ return (rl_backward_word (-count, key));
+
+ while (count)
+ {
+ if (rl_point == rl_end)
+ return 0;
+
+ /* If we are not in a word, move forward until we are in one.
+ Then, move forward until we hit a non-alphabetic character. */
+ c = _rl_char_value (rl_line_buffer, rl_point);
+
+ if (_rl_walphabetic (c) == 0)
+ {
+ rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+ while (rl_point < rl_end)
+ {
+ c = _rl_char_value (rl_line_buffer, rl_point);
+ if (_rl_walphabetic (c))
+ break;
+ rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+ }
+ }
+
+ if (rl_point == rl_end)
+ return 0;
+
+ rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+ while (rl_point < rl_end)
+ {
+ c = _rl_char_value (rl_line_buffer, rl_point);
+ if (_rl_walphabetic (c) == 0)
+ break;
+ rl_point = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+ }
+
+ --count;
+ }
+
+ return 0;
+}
+
+/* Move backward a word. We do what Emacs does. Handles multibyte chars. */
+int
+rl_backward_word (count, key)
+ int count, key;
+{
+ int c, p;
+
+ if (count < 0)
+ return (rl_forward_word (-count, key));
+
+ while (count)
+ {
+ if (rl_point == 0)
+ return 0;
+
+ /* Like rl_forward_word (), except that we look at the characters
+ just before point. */
+
+ p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ c = _rl_char_value (rl_line_buffer, p);
+
+ if (_rl_walphabetic (c) == 0)
+ {
+ rl_point = p;
+ while (rl_point > 0)
+ {
+ p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ c = _rl_char_value (rl_line_buffer, p);
+ if (_rl_walphabetic (c))
+ break;
+ rl_point = p;
+ }
+ }
+
+ while (rl_point)
+ {
+ p = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ c = _rl_char_value (rl_line_buffer, p);
+ if (_rl_walphabetic (c) == 0)
+ break;
+ else
+ rl_point = p;
+ }
+
+ --count;
+ }
+
+ return 0;
+}
+
+/* Clear the current line. Numeric argument to C-l does this. */
+int
+rl_refresh_line (ignore1, ignore2)
+ int ignore1, ignore2;
+{
+ int curr_line;
+
+ curr_line = _rl_current_display_line ();
+
+ _rl_move_vert (curr_line);
+ _rl_move_cursor_relative (0, rl_line_buffer); /* XXX is this right */
+
+ _rl_clear_to_eol (0); /* arg of 0 means to not use spaces */
+
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return 0;
+}
+
+/* C-l typed to a line without quoting clears the screen, and then reprints
+ the prompt and the current input line. Given a numeric arg, redraw only
+ the current line. */
+int
+rl_clear_screen (count, key)
+ int count, key;
+{
+ if (rl_explicit_arg)
+ {
+ rl_refresh_line (count, key);
+ return 0;
+ }
+
+ _rl_clear_screen (); /* calls termcap function to clear screen */
+ rl_forced_update_display ();
+ rl_display_fixed = 1;
+
+ return 0;
+}
+
+int
+rl_arrow_keys (count, c)
+ int count, c;
+{
+ int ch;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ ch = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ switch (_rl_to_upper (ch))
+ {
+ case 'A':
+ rl_get_previous_history (count, ch);
+ break;
+
+ case 'B':
+ rl_get_next_history (count, ch);
+ break;
+
+ case 'C':
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_forward_char (count, ch);
+ else
+ rl_forward_byte (count, ch);
+ break;
+
+ case 'D':
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_backward_char (count, ch);
+ else
+ rl_backward_byte (count, ch);
+ break;
+
+ default:
+ rl_ding ();
+ }
+
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Text commands */
+/* */
+/* **************************************************************** */
+
+#ifdef HANDLE_MULTIBYTE
+static char pending_bytes[MB_LEN_MAX];
+static int pending_bytes_length = 0;
+static mbstate_t ps = {0};
+#endif
+
+/* Insert the character C at the current location, moving point forward.
+ If C introduces a multibyte sequence, we read the whole sequence and
+ then insert the multibyte char into the line buffer. */
+int
+_rl_insert_char (count, c)
+ int count, c;
+{
+ register int i;
+ char *string;
+#ifdef HANDLE_MULTIBYTE
+ int string_size;
+ char incoming[MB_LEN_MAX + 1];
+ int incoming_length = 0;
+ mbstate_t ps_back;
+ static int stored_count = 0;
+#endif
+
+ if (count <= 0)
+ return 0;
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ {
+ incoming[0] = c;
+ incoming[1] = '\0';
+ incoming_length = 1;
+ }
+ else
+ {
+ wchar_t wc;
+ size_t ret;
+
+ if (stored_count <= 0)
+ stored_count = count;
+ else
+ count = stored_count;
+
+ ps_back = ps;
+ pending_bytes[pending_bytes_length++] = c;
+ ret = mbrtowc (&wc, pending_bytes, pending_bytes_length, &ps);
+
+ if (ret == (size_t)-2)
+ {
+ /* Bytes too short to compose character, try to wait for next byte.
+ Restore the state of the byte sequence, because in this case the
+ effect of mbstate is undefined. */
+ ps = ps_back;
+ return 1;
+ }
+ else if (ret == (size_t)-1)
+ {
+ /* Invalid byte sequence for the current locale. Treat first byte
+ as a single character. */
+ incoming[0] = pending_bytes[0];
+ incoming[1] = '\0';
+ incoming_length = 1;
+ pending_bytes_length--;
+ memmove (pending_bytes, pending_bytes + 1, pending_bytes_length);
+ /* Clear the state of the byte sequence, because in this case the
+ effect of mbstate is undefined. */
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else if (ret == (size_t)0)
+ {
+ incoming[0] = '\0';
+ incoming_length = 0;
+ pending_bytes_length--;
+ /* Clear the state of the byte sequence, because in this case the
+ effect of mbstate is undefined. */
+ memset (&ps, 0, sizeof (mbstate_t));
+ }
+ else
+ {
+ /* We successfully read a single multibyte character. */
+ memcpy (incoming, pending_bytes, pending_bytes_length);
+ incoming[pending_bytes_length] = '\0';
+ incoming_length = pending_bytes_length;
+ pending_bytes_length = 0;
+ }
+ }
+#endif /* HANDLE_MULTIBYTE */
+
+ /* If we can optimize, then do it. But don't let people crash
+ readline because of extra large arguments. */
+ if (count > 1 && count <= 1024)
+ {
+#if defined (HANDLE_MULTIBYTE)
+ string_size = count * incoming_length;
+ string = (char *)xmalloc (1 + string_size);
+
+ i = 0;
+ while (i < string_size)
+ {
+ strncpy (string + i, incoming, incoming_length);
+ i += incoming_length;
+ }
+ incoming_length = 0;
+ stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+ string = (char *)xmalloc (1 + count);
+
+ for (i = 0; i < count; i++)
+ string[i] = c;
+#endif /* !HANDLE_MULTIBYTE */
+
+ string[i] = '\0';
+ rl_insert_text (string);
+ free (string);
+
+ return 0;
+ }
+
+ if (count > 1024)
+ {
+ int decreaser;
+#if defined (HANDLE_MULTIBYTE)
+ string_size = incoming_length * 1024;
+ string = (char *)xmalloc (1 + string_size);
+
+ i = 0;
+ while (i < string_size)
+ {
+ strncpy (string + i, incoming, incoming_length);
+ i += incoming_length;
+ }
+
+ while (count)
+ {
+ decreaser = (count > 1024) ? 1024 : count;
+ string[decreaser*incoming_length] = '\0';
+ rl_insert_text (string);
+ count -= decreaser;
+ }
+
+ free (string);
+ incoming_length = 0;
+ stored_count = 0;
+#else /* !HANDLE_MULTIBYTE */
+ char str[1024+1];
+
+ for (i = 0; i < 1024; i++)
+ str[i] = c;
+
+ while (count)
+ {
+ decreaser = (count > 1024 ? 1024 : count);
+ str[decreaser] = '\0';
+ rl_insert_text (str);
+ count -= decreaser;
+ }
+#endif /* !HANDLE_MULTIBYTE */
+
+ return 0;
+ }
+
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ {
+ /* We are inserting a single character.
+ If there is pending input, then make a string of all of the
+ pending characters that are bound to rl_insert, and insert
+ them all. */
+ if (_rl_any_typein ())
+ _rl_insert_typein (c);
+ else
+ {
+ /* Inserting a single character. */
+ char str[2];
+
+ str[1] = '\0';
+ str[0] = c;
+ rl_insert_text (str);
+ }
+ }
+#if defined (HANDLE_MULTIBYTE)
+ else
+ {
+ rl_insert_text (incoming);
+ stored_count = 0;
+ }
+#endif
+
+ return 0;
+}
+
+/* Overwrite the character at point (or next COUNT characters) with C.
+ If C introduces a multibyte character sequence, read the entire sequence
+ before starting the overwrite loop. */
+int
+_rl_overwrite_char (count, c)
+ int count, c;
+{
+ int i;
+#if defined (HANDLE_MULTIBYTE)
+ char mbkey[MB_LEN_MAX];
+ int k;
+
+ /* Read an entire multibyte character sequence to insert COUNT times. */
+ if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX);
+#endif
+
+ rl_begin_undo_group ();
+
+ for (i = 0; i < count; i++)
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_insert_text (mbkey);
+ else
+#endif
+ _rl_insert_char (1, c);
+
+ if (rl_point < rl_end)
+ rl_delete (1, c);
+ }
+
+ rl_end_undo_group ();
+
+ return 0;
+}
+
+int
+rl_insert (count, c)
+ int count, c;
+{
+ return (rl_insert_mode == RL_IM_INSERT ? _rl_insert_char (count, c)
+ : _rl_overwrite_char (count, c));
+}
+
+/* Insert the next typed character verbatim. */
+static int
+_rl_insert_next (count)
+ int count;
+{
+ int c;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_SIGNALS)
+ if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+ _rl_restore_tty_signals ();
+#endif
+
+ return (_rl_insert_char (count, c));
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_insert_next_callback (data)
+ _rl_callback_generic_arg *data;
+{
+ int count;
+
+ count = data->count;
+
+ /* Deregister function, let rl_callback_read_char deallocate data */
+ _rl_callback_func = 0;
+ _rl_want_redisplay = 1;
+
+ return _rl_insert_next (count);
+}
+#endif
+
+int
+rl_quoted_insert (count, key)
+ int count, key;
+{
+ /* Let's see...should the callback interface futz with signal handling? */
+#if defined (HANDLE_SIGNALS)
+ if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
+ _rl_disable_tty_signals ();
+#endif
+
+#if defined (READLINE_CALLBACKS)
+ if (RL_ISSTATE (RL_STATE_CALLBACK))
+ {
+ _rl_callback_data = _rl_callback_data_alloc (count);
+ _rl_callback_func = _rl_insert_next_callback;
+ return (0);
+ }
+#endif
+
+ return _rl_insert_next (count);
+}
+
+/* Insert a tab character. */
+int
+rl_tab_insert (count, key)
+ int count, key;
+{
+ return (_rl_insert_char (count, '\t'));
+}
+
+/* What to do when a NEWLINE is pressed. We accept the whole line.
+ KEY is the key that invoked this command. I guess it could have
+ meaning in the future. */
+int
+rl_newline (count, key)
+ int count, key;
+{
+ rl_done = 1;
+
+ if (_rl_history_preserve_point)
+ _rl_history_saved_point = (rl_point == rl_end) ? -1 : rl_point;
+
+ RL_SETSTATE(RL_STATE_DONE);
+
+#if defined (VI_MODE)
+ if (rl_editing_mode == vi_mode)
+ {
+ _rl_vi_done_inserting ();
+ if (_rl_vi_textmod_command (_rl_vi_last_command) == 0) /* XXX */
+ _rl_vi_reset_last ();
+ }
+#endif /* VI_MODE */
+
+ /* If we've been asked to erase empty lines, suppress the final update,
+ since _rl_update_final calls rl_crlf(). */
+ if (rl_erase_empty_line && rl_point == 0 && rl_end == 0)
+ return 0;
+
+ if (readline_echoing_p)
+ _rl_update_final ();
+ return 0;
+}
+
+/* What to do for some uppercase characters, like meta characters,
+ and some characters appearing in emacs_ctlx_keymap. This function
+ is just a stub, you bind keys to it and the code in _rl_dispatch ()
+ is special cased. */
+int
+rl_do_lowercase_version (ignore1, ignore2)
+ int ignore1, ignore2;
+{
+ return 0;
+}
+
+/* This is different from what vi does, so the code's not shared. Emacs
+ rubout in overwrite mode has one oddity: it replaces a control
+ character that's displayed as two characters (^X) with two spaces. */
+int
+_rl_overwrite_rubout (count, key)
+ int count, key;
+{
+ int opoint;
+ int i, l;
+
+ if (rl_point == 0)
+ {
+ rl_ding ();
+ return 1;
+ }
+
+ opoint = rl_point;
+
+ /* L == number of spaces to insert */
+ for (i = l = 0; i < count; i++)
+ {
+ rl_backward_char (1, key);
+ l += rl_character_len (rl_line_buffer[rl_point], rl_point); /* not exactly right */
+ }
+
+ rl_begin_undo_group ();
+
+ if (count > 1 || rl_explicit_arg)
+ rl_kill_text (opoint, rl_point);
+ else
+ rl_delete_text (opoint, rl_point);
+
+ /* Emacs puts point at the beginning of the sequence of spaces. */
+ if (rl_point < rl_end)
+ {
+ opoint = rl_point;
+ _rl_insert_char (l, ' ');
+ rl_point = opoint;
+ }
+
+ rl_end_undo_group ();
+
+ return 0;
+}
+
+/* Rubout the character behind point. */
+int
+rl_rubout (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_delete (-count, key));
+
+ if (!rl_point)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (rl_insert_mode == RL_IM_OVERWRITE)
+ return (_rl_overwrite_rubout (count, key));
+
+ return (_rl_rubout_char (count, key));
+}
+
+int
+_rl_rubout_char (count, key)
+ int count, key;
+{
+ int orig_point;
+ unsigned char c;
+
+ /* Duplicated code because this is called from other parts of the library. */
+ if (count < 0)
+ return (rl_delete (-count, key));
+
+ if (rl_point == 0)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ orig_point = rl_point;
+ if (count > 1 || rl_explicit_arg)
+ {
+ rl_backward_char (count, key);
+ rl_kill_text (orig_point, rl_point);
+ }
+ else if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ {
+ c = rl_line_buffer[--rl_point];
+ rl_delete_text (rl_point, orig_point);
+ /* The erase-at-end-of-line hack is of questionable merit now. */
+ if (rl_point == rl_end && ISPRINT (c) && _rl_last_c_pos)
+ {
+ int l;
+ l = rl_character_len (c, rl_point);
+ _rl_erase_at_end_of_line (l);
+ }
+ }
+ else
+ {
+ rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ rl_delete_text (rl_point, orig_point);
+ }
+
+ return 0;
+}
+
+/* Delete the character under the cursor. Given a numeric argument,
+ kill that many characters instead. */
+int
+rl_delete (count, key)
+ int count, key;
+{
+ int xpoint;
+
+ if (count < 0)
+ return (_rl_rubout_char (-count, key));
+
+ if (rl_point == rl_end)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (count > 1 || rl_explicit_arg)
+ {
+ xpoint = rl_point;
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_forward_char (count, key);
+ else
+ rl_forward_byte (count, key);
+
+ rl_kill_text (xpoint, rl_point);
+ rl_point = xpoint;
+ }
+ else
+ {
+ xpoint = MB_NEXTCHAR (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+ rl_delete_text (rl_point, xpoint);
+ }
+ return 0;
+}
+
+/* Delete the character under the cursor, unless the insertion
+ point is at the end of the line, in which case the character
+ behind the cursor is deleted. COUNT is obeyed and may be used
+ to delete forward or backward that many characters. */
+int
+rl_rubout_or_delete (count, key)
+ int count, key;
+{
+ if (rl_end != 0 && rl_point == rl_end)
+ return (_rl_rubout_char (count, key));
+ else
+ return (rl_delete (count, key));
+}
+
+/* Delete all spaces and tabs around point. */
+int
+rl_delete_horizontal_space (count, ignore)
+ int count, ignore;
+{
+ int start = rl_point;
+
+ while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
+ rl_point--;
+
+ start = rl_point;
+
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ if (start != rl_point)
+ {
+ rl_delete_text (start, rl_point);
+ rl_point = start;
+ }
+
+ if (rl_point < 0)
+ rl_point = 0;
+
+ return 0;
+}
+
+/* Like the tcsh editing function delete-char-or-list. The eof character
+ is caught before this is invoked, so this really does the same thing as
+ delete-char-or-list-or-eof, as long as it's bound to the eof character. */
+int
+rl_delete_or_show_completions (count, key)
+ int count, key;
+{
+ if (rl_end != 0 && rl_point == rl_end)
+ return (rl_possible_completions (count, key));
+ else
+ return (rl_delete (count, key));
+}
+
+#ifndef RL_COMMENT_BEGIN_DEFAULT
+#define RL_COMMENT_BEGIN_DEFAULT "#"
+#endif
+
+/* Turn the current line into a comment in shell history.
+ A K*rn shell style function. */
+int
+rl_insert_comment (count, key)
+ int count, key;
+{
+ char *rl_comment_text;
+ int rl_comment_len;
+
+ rl_beg_of_line (1, key);
+ rl_comment_text = _rl_comment_begin ? _rl_comment_begin : RL_COMMENT_BEGIN_DEFAULT;
+
+ if (rl_explicit_arg == 0)
+ rl_insert_text (rl_comment_text);
+ else
+ {
+ rl_comment_len = strlen (rl_comment_text);
+ if (STREQN (rl_comment_text, rl_line_buffer, rl_comment_len))
+ rl_delete_text (rl_point, rl_point + rl_comment_len);
+ else
+ rl_insert_text (rl_comment_text);
+ }
+
+ (*rl_redisplay_function) ();
+ rl_newline (1, '\n');
+
+ return (0);
+}
+
+/* **************************************************************** */
+/* */
+/* Changing Case */
+/* */
+/* **************************************************************** */
+
+/* The three kinds of things that we know how to do. */
+#define UpCase 1
+#define DownCase 2
+#define CapCase 3
+
+/* Uppercase the word at point. */
+int
+rl_upcase_word (count, key)
+ int count, key;
+{
+ return (rl_change_case (count, UpCase));
+}
+
+/* Lowercase the word at point. */
+int
+rl_downcase_word (count, key)
+ int count, key;
+{
+ return (rl_change_case (count, DownCase));
+}
+
+/* Upcase the first letter, downcase the rest. */
+int
+rl_capitalize_word (count, key)
+ int count, key;
+{
+ return (rl_change_case (count, CapCase));
+}
+
+/* The meaty function.
+ Change the case of COUNT words, performing OP on them.
+ OP is one of UpCase, DownCase, or CapCase.
+ If a negative argument is given, leave point where it started,
+ otherwise, leave it where it moves to. */
+static int
+rl_change_case (count, op)
+ int count, op;
+{
+ int start, next, end;
+ int inword, c, nc, nop;
+#if defined (HANDLE_MULTIBYTE)
+ wchar_t wc, nwc;
+ char mb[MB_LEN_MAX+1];
+ int mblen, p;
+ mbstate_t ps;
+#endif
+
+ start = rl_point;
+ rl_forward_word (count, 0);
+ end = rl_point;
+
+ if (op != UpCase && op != DownCase && op != CapCase)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (count < 0)
+ SWAP (start, end);
+
+#if defined (HANDLE_MULTIBYTE)
+ memset (&ps, 0, sizeof (mbstate_t));
+#endif
+
+ /* We are going to modify some text, so let's prepare to undo it. */
+ rl_modifying (start, end);
+
+ inword = 0;
+ while (start < end)
+ {
+ c = _rl_char_value (rl_line_buffer, start);
+ /* This assumes that the upper and lower case versions are the same width. */
+ next = MB_NEXTCHAR (rl_line_buffer, start, 1, MB_FIND_NONZERO);
+
+ if (_rl_walphabetic (c) == 0)
+ {
+ inword = 0;
+ start = next;
+ continue;
+ }
+
+ if (op == CapCase)
+ {
+ nop = inword ? DownCase : UpCase;
+ inword = 1;
+ }
+ else
+ nop = op;
+ if (MB_CUR_MAX == 1 || rl_byte_oriented || isascii (c))
+ {
+ nc = (nop == UpCase) ? _rl_to_upper (c) : _rl_to_lower (c);
+ rl_line_buffer[start] = nc;
+ }
+#if defined (HANDLE_MULTIBYTE)
+ else
+ {
+ mbrtowc (&wc, rl_line_buffer + start, end - start, &ps);
+ nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
+ if (nwc != wc) /* just skip unchanged characters */
+ {
+ mblen = wcrtomb (mb, nwc, &ps);
+ if (mblen > 0)
+ mb[mblen] = '\0';
+ /* Assume the same width */
+ strncpy (rl_line_buffer + start, mb, mblen);
+ }
+ }
+#endif
+
+ start = next;
+ }
+
+ rl_point = end;
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Transposition */
+/* */
+/* **************************************************************** */
+
+/* Transpose the words at point. If point is at the end of the line,
+ transpose the two words before point. */
+int
+rl_transpose_words (count, key)
+ int count, key;
+{
+ char *word1, *word2;
+ int w1_beg, w1_end, w2_beg, w2_end;
+ int orig_point = rl_point;
+
+ if (!count)
+ return 0;
+
+ /* Find the two words. */
+ rl_forward_word (count, key);
+ w2_end = rl_point;
+ rl_backward_word (1, key);
+ w2_beg = rl_point;
+ rl_backward_word (count, key);
+ w1_beg = rl_point;
+ rl_forward_word (1, key);
+ w1_end = rl_point;
+
+ /* Do some check to make sure that there really are two words. */
+ if ((w1_beg == w2_beg) || (w2_beg < w1_end))
+ {
+ rl_ding ();
+ rl_point = orig_point;
+ return -1;
+ }
+
+ /* Get the text of the words. */
+ word1 = rl_copy_text (w1_beg, w1_end);
+ word2 = rl_copy_text (w2_beg, w2_end);
+
+ /* We are about to do many insertions and deletions. Remember them
+ as one operation. */
+ rl_begin_undo_group ();
+
+ /* Do the stuff at word2 first, so that we don't have to worry
+ about word1 moving. */
+ rl_point = w2_beg;
+ rl_delete_text (w2_beg, w2_end);
+ rl_insert_text (word1);
+
+ rl_point = w1_beg;
+ rl_delete_text (w1_beg, w1_end);
+ rl_insert_text (word2);
+
+ /* This is exactly correct since the text before this point has not
+ changed in length. */
+ rl_point = w2_end;
+
+ /* I think that does it. */
+ rl_end_undo_group ();
+ free (word1);
+ free (word2);
+
+ return 0;
+}
+
+/* Transpose the characters at point. If point is at the end of the line,
+ then transpose the characters before point. */
+int
+rl_transpose_chars (count, key)
+ int count, key;
+{
+#if defined (HANDLE_MULTIBYTE)
+ char *dummy;
+ int i;
+#else
+ char dummy[2];
+#endif
+ int char_length, prev_point;
+
+ if (count == 0)
+ return 0;
+
+ if (!rl_point || rl_end < 2)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ rl_begin_undo_group ();
+
+ if (rl_point == rl_end)
+ {
+ rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ count = 1;
+ }
+
+ prev_point = rl_point;
+ rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+
+#if defined (HANDLE_MULTIBYTE)
+ char_length = prev_point - rl_point;
+ dummy = (char *)xmalloc (char_length + 1);
+ for (i = 0; i < char_length; i++)
+ dummy[i] = rl_line_buffer[rl_point + i];
+ dummy[i] = '\0';
+#else
+ dummy[0] = rl_line_buffer[rl_point];
+ dummy[char_length = 1] = '\0';
+#endif
+
+ rl_delete_text (rl_point, rl_point + char_length);
+
+ rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+
+ _rl_fix_point (0);
+ rl_insert_text (dummy);
+ rl_end_undo_group ();
+
+#if defined (HANDLE_MULTIBYTE)
+ free (dummy);
+#endif
+
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Character Searching */
+/* */
+/* **************************************************************** */
+
+int
+#if defined (HANDLE_MULTIBYTE)
+_rl_char_search_internal (count, dir, smbchar, len)
+ int count, dir;
+ char *smbchar;
+ int len;
+#else
+_rl_char_search_internal (count, dir, schar)
+ int count, dir, schar;
+#endif
+{
+ int pos, inc;
+#if defined (HANDLE_MULTIBYTE)
+ int prepos;
+#endif
+
+ pos = rl_point;
+ inc = (dir < 0) ? -1 : 1;
+ while (count)
+ {
+ if ((dir < 0 && pos <= 0) || (dir > 0 && pos >= rl_end))
+ {
+ rl_ding ();
+ return -1;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ pos = (inc > 0) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+ : _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+#else
+ pos += inc;
+#endif
+ do
+ {
+#if defined (HANDLE_MULTIBYTE)
+ if (_rl_is_mbchar_matched (rl_line_buffer, pos, rl_end, smbchar, len))
+#else
+ if (rl_line_buffer[pos] == schar)
+#endif
+ {
+ count--;
+ if (dir < 0)
+ rl_point = (dir == BTO) ? _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)
+ : pos;
+ else
+ rl_point = (dir == FTO) ? _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)
+ : pos;
+ break;
+ }
+#if defined (HANDLE_MULTIBYTE)
+ prepos = pos;
+#endif
+ }
+#if defined (HANDLE_MULTIBYTE)
+ while ((dir < 0) ? (pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY)) != prepos
+ : (pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY)) != prepos);
+#else
+ while ((dir < 0) ? pos-- : ++pos < rl_end);
+#endif
+ }
+ return (0);
+}
+
+/* Search COUNT times for a character read from the current input stream.
+ FDIR is the direction to search if COUNT is non-negative; otherwise
+ the search goes in BDIR. So much is dependent on HANDLE_MULTIBYTE
+ that there are two separate versions of this function. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_char_search (count, fdir, bdir)
+ int count, fdir, bdir;
+{
+ char mbchar[MB_LEN_MAX];
+ int mb_len;
+
+ mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
+
+ if (count < 0)
+ return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
+ else
+ return (_rl_char_search_internal (count, fdir, mbchar, mb_len));
+}
+#else /* !HANDLE_MULTIBYTE */
+static int
+_rl_char_search (count, fdir, bdir)
+ int count, fdir, bdir;
+{
+ int c;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (count < 0)
+ return (_rl_char_search_internal (-count, bdir, c));
+ else
+ return (_rl_char_search_internal (count, fdir, c));
+}
+#endif /* !HANDLE_MULTIBYTE */
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_char_search_callback (data)
+ _rl_callback_generic_arg *data;
+{
+ _rl_callback_func = 0;
+ _rl_want_redisplay = 1;
+
+ return (_rl_char_search (data->count, data->i1, data->i2));
+}
+#endif
+
+int
+rl_char_search (count, key)
+ int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+ if (RL_ISSTATE (RL_STATE_CALLBACK))
+ {
+ _rl_callback_data = _rl_callback_data_alloc (count);
+ _rl_callback_data->i1 = FFIND;
+ _rl_callback_data->i2 = BFIND;
+ _rl_callback_func = _rl_char_search_callback;
+ return (0);
+ }
+#endif
+
+ return (_rl_char_search (count, FFIND, BFIND));
+}
+
+int
+rl_backward_char_search (count, key)
+ int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+ if (RL_ISSTATE (RL_STATE_CALLBACK))
+ {
+ _rl_callback_data = _rl_callback_data_alloc (count);
+ _rl_callback_data->i1 = BFIND;
+ _rl_callback_data->i2 = FFIND;
+ _rl_callback_func = _rl_char_search_callback;
+ return (0);
+ }
+#endif
+
+ return (_rl_char_search (count, BFIND, FFIND));
+}
+
+/* **************************************************************** */
+/* */
+/* The Mark and the Region. */
+/* */
+/* **************************************************************** */
+
+/* Set the mark at POSITION. */
+int
+_rl_set_mark_at_pos (position)
+ int position;
+{
+ if (position > rl_end)
+ return -1;
+
+ rl_mark = position;
+ return 0;
+}
+
+/* A bindable command to set the mark. */
+int
+rl_set_mark (count, key)
+ int count, key;
+{
+ return (_rl_set_mark_at_pos (rl_explicit_arg ? count : rl_point));
+}
+
+/* Exchange the position of mark and point. */
+int
+rl_exchange_point_and_mark (count, key)
+ int count, key;
+{
+ if (rl_mark > rl_end)
+ rl_mark = -1;
+
+ if (rl_mark == -1)
+ {
+ rl_ding ();
+ return -1;
+ }
+ else
+ SWAP (rl_point, rl_mark);
+
+ return 0;
+}
diff --git a/lib/readline/vi_mode.c b/lib/readline/vi_mode.c
index ac5fd744..3914c675 100644
--- a/lib/readline/vi_mode.c
+++ b/lib/readline/vi_mode.c
@@ -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));
diff --git a/lib/readline/vi_mode.c~ b/lib/readline/vi_mode.c~
new file mode 100644
index 00000000..ac5fd744
--- /dev/null
+++ b/lib/readline/vi_mode.c~
@@ -0,0 +1,1717 @@
+/* vi_mode.c -- A vi emulation mode for Bash.
+ Derived from code written by Jeff Sparkes (jsparkes@bnr.ca). */
+
+/* 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
+
+/* **************************************************************** */
+/* */
+/* VI Emulation Mode */
+/* */
+/* **************************************************************** */
+#include "rlconf.h"
+
+#if defined (VI_MODE)
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#if defined (HAVE_STDLIB_H)
+# include <stdlib.h>
+#else
+# include "ansi_stdlib.h"
+#endif /* HAVE_STDLIB_H */
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+/* Some standard library routines. */
+#include "rldefs.h"
+#include "rlmbutil.h"
+
+#include "readline.h"
+#include "history.h"
+
+#include "rlprivate.h"
+#include "xmalloc.h"
+
+#ifndef member
+#define member(c, s) ((c) ? (char *)strchr ((s), (c)) != (char *)NULL : 0)
+#endif
+
+int _rl_vi_last_command = 'i'; /* default `.' puts you in insert mode */
+
+/* Non-zero means enter insertion mode. */
+static int _rl_vi_doing_insert;
+
+/* Command keys which do movement for xxx_to commands. */
+static const char *vi_motion = " hl^$0ftFT;,%wbeWBE|";
+
+/* Keymap used for vi replace characters. Created dynamically since
+ rarely used. */
+static Keymap vi_replace_map;
+
+/* The number of characters inserted in the last replace operation. */
+static int vi_replace_count;
+
+/* If non-zero, we have text inserted after a c[motion] command that put
+ us implicitly into insert mode. Some people want this text to be
+ attached to the command so that it is `redoable' with `.'. */
+static int vi_continued_command;
+static char *vi_insert_buffer;
+static int vi_insert_buffer_size;
+
+static int _rl_vi_last_repeat = 1;
+static int _rl_vi_last_arg_sign = 1;
+static int _rl_vi_last_motion;
+#if defined (HANDLE_MULTIBYTE)
+static char _rl_vi_last_search_mbchar[MB_LEN_MAX];
+static int _rl_vi_last_search_mblen;
+#else
+static int _rl_vi_last_search_char;
+#endif
+static int _rl_vi_last_replacement;
+
+static int _rl_vi_last_key_before_insert;
+
+static int vi_redoing;
+
+/* Text modification commands. These are the `redoable' commands. */
+static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
+
+/* Arrays for the saved marks. */
+static int vi_mark_chars['z' - 'a' + 1];
+
+static void _rl_vi_stuff_insert PARAMS((int));
+static void _rl_vi_save_insert PARAMS((UNDO_LIST *));
+
+static int _rl_vi_arg_dispatch PARAMS((int));
+static int rl_digit_loop1 PARAMS((void));
+
+static int _rl_vi_set_mark PARAMS((void));
+static int _rl_vi_goto_mark PARAMS((void));
+
+static int _rl_vi_callback_getchar PARAMS((char *, int));
+
+#if defined (READLINE_CALLBACKS)
+static int _rl_vi_callback_set_mark PARAMS((_rl_callback_generic_arg *));
+static int _rl_vi_callback_goto_mark PARAMS((_rl_callback_generic_arg *));
+static int _rl_vi_callback_change_char PARAMS((_rl_callback_generic_arg *));
+static int _rl_vi_callback_char_search PARAMS((_rl_callback_generic_arg *));
+#endif
+
+void
+_rl_vi_initialize_line ()
+{
+ register int i;
+
+ for (i = 0; i < sizeof (vi_mark_chars) / sizeof (int); i++)
+ vi_mark_chars[i] = -1;
+
+ RL_UNSETSTATE(RL_STATE_VICMDONCE);
+}
+
+void
+_rl_vi_reset_last ()
+{
+ _rl_vi_last_command = 'i';
+ _rl_vi_last_repeat = 1;
+ _rl_vi_last_arg_sign = 1;
+ _rl_vi_last_motion = 0;
+}
+
+void
+_rl_vi_set_last (key, repeat, sign)
+ int key, repeat, sign;
+{
+ _rl_vi_last_command = key;
+ _rl_vi_last_repeat = repeat;
+ _rl_vi_last_arg_sign = sign;
+}
+
+/* A convenience function that calls _rl_vi_set_last to save the last command
+ information and enters insertion mode. */
+void
+rl_vi_start_inserting (key, repeat, sign)
+ int key, repeat, sign;
+{
+ _rl_vi_set_last (key, repeat, sign);
+ rl_vi_insertion_mode (1, key);
+}
+
+/* Is the command C a VI mode text modification command? */
+int
+_rl_vi_textmod_command (c)
+ int c;
+{
+ return (member (c, vi_textmod));
+}
+
+static void
+_rl_vi_stuff_insert (count)
+ int count;
+{
+ rl_begin_undo_group ();
+ while (count--)
+ rl_insert_text (vi_insert_buffer);
+ rl_end_undo_group ();
+}
+
+/* Bound to `.'. Called from command mode, so we know that we have to
+ redo a text modification command. The default for _rl_vi_last_command
+ puts you back into insert mode. */
+int
+rl_vi_redo (count, c)
+ int count, c;
+{
+ int r;
+
+ if (!rl_explicit_arg)
+ {
+ rl_numeric_arg = _rl_vi_last_repeat;
+ rl_arg_sign = _rl_vi_last_arg_sign;
+ }
+
+ r = 0;
+ vi_redoing = 1;
+ /* If we're redoing an insert with `i', stuff in the inserted text
+ and do not go into insertion mode. */
+ if (_rl_vi_last_command == 'i' && vi_insert_buffer && *vi_insert_buffer)
+ {
+ _rl_vi_stuff_insert (count);
+ /* And back up point over the last character inserted. */
+ if (rl_point > 0)
+ rl_point--;
+ }
+ else
+ r = _rl_dispatch (_rl_vi_last_command, _rl_keymap);
+ vi_redoing = 0;
+
+ return (r);
+}
+
+/* A placeholder for further expansion. */
+int
+rl_vi_undo (count, key)
+ int count, key;
+{
+ return (rl_undo_command (count, key));
+}
+
+/* Yank the nth arg from the previous line into this line at point. */
+int
+rl_vi_yank_arg (count, key)
+ int count, key;
+{
+ /* Readline thinks that the first word on a line is the 0th, while vi
+ thinks the first word on a line is the 1st. Compensate. */
+ if (rl_explicit_arg)
+ rl_yank_nth_arg (count - 1, 0);
+ else
+ rl_yank_nth_arg ('$', 0);
+
+ return (0);
+}
+
+/* With an argument, move back that many history lines, else move to the
+ beginning of history. */
+int
+rl_vi_fetch_history (count, c)
+ int count, c;
+{
+ int wanted;
+
+ /* Giving an argument of n means we want the nth command in the history
+ file. The command number is interpreted the same way that the bash
+ `history' command does it -- that is, giving an argument count of 450
+ to this command would get the command listed as number 450 in the
+ output of `history'. */
+ if (rl_explicit_arg)
+ {
+ wanted = history_base + where_history () - count;
+ if (wanted <= 0)
+ rl_beginning_of_history (0, 0);
+ else
+ rl_get_previous_history (wanted, c);
+ }
+ else
+ rl_beginning_of_history (count, 0);
+ return (0);
+}
+
+/* Search again for the last thing searched for. */
+int
+rl_vi_search_again (count, key)
+ int count, key;
+{
+ switch (key)
+ {
+ case 'n':
+ rl_noninc_reverse_search_again (count, key);
+ break;
+
+ case 'N':
+ rl_noninc_forward_search_again (count, key);
+ break;
+ }
+ return (0);
+}
+
+/* Do a vi style search. */
+int
+rl_vi_search (count, key)
+ int count, key;
+{
+ switch (key)
+ {
+ case '?':
+ _rl_free_saved_history_line ();
+ rl_noninc_forward_search (count, key);
+ break;
+
+ case '/':
+ _rl_free_saved_history_line ();
+ rl_noninc_reverse_search (count, key);
+ break;
+
+ default:
+ rl_ding ();
+ break;
+ }
+ return (0);
+}
+
+/* Completion, from vi's point of view. */
+int
+rl_vi_complete (ignore, key)
+ int ignore, key;
+{
+ if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
+ {
+ if (!whitespace (rl_line_buffer[rl_point + 1]))
+ rl_vi_end_word (1, 'E');
+ rl_point++;
+ }
+
+ if (key == '*')
+ rl_complete_internal ('*'); /* Expansion and replacement. */
+ else if (key == '=')
+ rl_complete_internal ('?'); /* List possible completions. */
+ else if (key == '\\')
+ rl_complete_internal (TAB); /* Standard Readline completion. */
+ else
+ rl_complete (0, key);
+
+ if (key == '*' || key == '\\')
+ rl_vi_start_inserting (key, 1, rl_arg_sign);
+
+ return (0);
+}
+
+/* Tilde expansion for vi mode. */
+int
+rl_vi_tilde_expand (ignore, key)
+ int ignore, key;
+{
+ rl_tilde_expand (0, key);
+ rl_vi_start_inserting (key, 1, rl_arg_sign);
+ return (0);
+}
+
+/* Previous word in vi mode. */
+int
+rl_vi_prev_word (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_vi_next_word (-count, key));
+
+ if (rl_point == 0)
+ {
+ rl_ding ();
+ return (0);
+ }
+
+ if (_rl_uppercase_p (key))
+ rl_vi_bWord (count, key);
+ else
+ rl_vi_bword (count, key);
+
+ return (0);
+}
+
+/* Next word in vi mode. */
+int
+rl_vi_next_word (count, key)
+ int count, key;
+{
+ if (count < 0)
+ return (rl_vi_prev_word (-count, key));
+
+ if (rl_point >= (rl_end - 1))
+ {
+ rl_ding ();
+ return (0);
+ }
+
+ if (_rl_uppercase_p (key))
+ rl_vi_fWord (count, key);
+ else
+ rl_vi_fword (count, key);
+ return (0);
+}
+
+/* Move to the end of the ?next? word. */
+int
+rl_vi_end_word (count, key)
+ int count, key;
+{
+ if (count < 0)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (_rl_uppercase_p (key))
+ rl_vi_eWord (count, key);
+ else
+ rl_vi_eword (count, key);
+ return (0);
+}
+
+/* Move forward a word the way that 'W' does. */
+int
+rl_vi_fWord (count, ignore)
+ int count, ignore;
+{
+ while (count-- && rl_point < (rl_end - 1))
+ {
+ /* Skip until whitespace. */
+ while (!whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+
+ /* Now skip whitespace. */
+ while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+ }
+ return (0);
+}
+
+int
+rl_vi_bWord (count, ignore)
+ int count, ignore;
+{
+ while (count-- && rl_point > 0)
+ {
+ /* If we are at the start of a word, move back to whitespace so
+ we will go back to the start of the previous word. */
+ if (!whitespace (rl_line_buffer[rl_point]) &&
+ whitespace (rl_line_buffer[rl_point - 1]))
+ rl_point--;
+
+ while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+ rl_point--;
+
+ if (rl_point > 0)
+ {
+ while (--rl_point >= 0 && !whitespace (rl_line_buffer[rl_point]));
+ rl_point++;
+ }
+ }
+ return (0);
+}
+
+int
+rl_vi_eWord (count, ignore)
+ int count, ignore;
+{
+ while (count-- && rl_point < (rl_end - 1))
+ {
+ if (!whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ /* Move to the next non-whitespace character (to the start of the
+ next word). */
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ if (rl_point && rl_point < rl_end)
+ {
+ /* Skip whitespace. */
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ /* Skip until whitespace. */
+ while (rl_point < rl_end && !whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ /* Move back to the last character of the word. */
+ rl_point--;
+ }
+ }
+ return (0);
+}
+
+int
+rl_vi_fword (count, ignore)
+ int count, ignore;
+{
+ while (count-- && rl_point < (rl_end - 1))
+ {
+ /* Move to white space (really non-identifer). */
+ if (_rl_isident (rl_line_buffer[rl_point]))
+ {
+ while (_rl_isident (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+ }
+ else /* if (!whitespace (rl_line_buffer[rl_point])) */
+ {
+ while (!_rl_isident (rl_line_buffer[rl_point]) &&
+ !whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+ }
+
+ /* Move past whitespace. */
+ while (whitespace (rl_line_buffer[rl_point]) && rl_point < rl_end)
+ rl_point++;
+ }
+ return (0);
+}
+
+int
+rl_vi_bword (count, ignore)
+ int count, ignore;
+{
+ while (count-- && rl_point > 0)
+ {
+ int last_is_ident;
+
+ /* If we are at the start of a word, move back to whitespace
+ so we will go back to the start of the previous word. */
+ if (!whitespace (rl_line_buffer[rl_point]) &&
+ whitespace (rl_line_buffer[rl_point - 1]))
+ rl_point--;
+
+ /* If this character and the previous character are `opposite', move
+ back so we don't get messed up by the rl_point++ down there in
+ the while loop. Without this code, words like `l;' screw up the
+ function. */
+ last_is_ident = _rl_isident (rl_line_buffer[rl_point - 1]);
+ if ((_rl_isident (rl_line_buffer[rl_point]) && !last_is_ident) ||
+ (!_rl_isident (rl_line_buffer[rl_point]) && last_is_ident))
+ rl_point--;
+
+ while (rl_point > 0 && whitespace (rl_line_buffer[rl_point]))
+ rl_point--;
+
+ if (rl_point > 0)
+ {
+ if (_rl_isident (rl_line_buffer[rl_point]))
+ while (--rl_point >= 0 && _rl_isident (rl_line_buffer[rl_point]));
+ else
+ while (--rl_point >= 0 && !_rl_isident (rl_line_buffer[rl_point]) &&
+ !whitespace (rl_line_buffer[rl_point]));
+ rl_point++;
+ }
+ }
+ return (0);
+}
+
+int
+rl_vi_eword (count, ignore)
+ int count, ignore;
+{
+ while (count-- && rl_point < rl_end - 1)
+ {
+ if (!whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+
+ if (rl_point < rl_end)
+ {
+ if (_rl_isident (rl_line_buffer[rl_point]))
+ while (++rl_point < rl_end && _rl_isident (rl_line_buffer[rl_point]));
+ else
+ while (++rl_point < rl_end && !_rl_isident (rl_line_buffer[rl_point])
+ && !whitespace (rl_line_buffer[rl_point]));
+ }
+ rl_point--;
+ }
+ return (0);
+}
+
+int
+rl_vi_insert_beg (count, key)
+ int count, key;
+{
+ rl_beg_of_line (1, key);
+ rl_vi_insertion_mode (1, key);
+ return (0);
+}
+
+int
+rl_vi_append_mode (count, key)
+ int count, key;
+{
+ if (rl_point < rl_end)
+ {
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ rl_point++;
+ else
+ {
+ int point = rl_point;
+ rl_forward_char (1, key);
+ if (point == rl_point)
+ rl_point = rl_end;
+ }
+ }
+ rl_vi_insertion_mode (1, key);
+ return (0);
+}
+
+int
+rl_vi_append_eol (count, key)
+ int count, key;
+{
+ rl_end_of_line (1, key);
+ rl_vi_append_mode (1, key);
+ return (0);
+}
+
+/* What to do in the case of C-d. */
+int
+rl_vi_eof_maybe (count, c)
+ int count, c;
+{
+ return (rl_newline (1, '\n'));
+}
+
+/* Insertion mode stuff. */
+
+/* Switching from one mode to the other really just involves
+ switching keymaps. */
+int
+rl_vi_insertion_mode (count, key)
+ int count, key;
+{
+ _rl_keymap = vi_insertion_keymap;
+ _rl_vi_last_key_before_insert = key;
+ return (0);
+}
+
+static void
+_rl_vi_save_insert (up)
+ UNDO_LIST *up;
+{
+ int len, start, end;
+
+ if (up == 0)
+ {
+ if (vi_insert_buffer_size >= 1)
+ vi_insert_buffer[0] = '\0';
+ return;
+ }
+
+ start = up->start;
+ end = up->end;
+ len = end - start + 1;
+ if (len >= vi_insert_buffer_size)
+ {
+ vi_insert_buffer_size += (len + 32) - (len % 32);
+ vi_insert_buffer = (char *)xrealloc (vi_insert_buffer, vi_insert_buffer_size);
+ }
+ strncpy (vi_insert_buffer, rl_line_buffer + start, len - 1);
+ vi_insert_buffer[len-1] = '\0';
+}
+
+void
+_rl_vi_done_inserting ()
+{
+ if (_rl_vi_doing_insert)
+ {
+ /* The `C', `s', and `S' commands set this. */
+ rl_end_undo_group ();
+ /* Now, the text between rl_undo_list->next->start and
+ rl_undo_list->next->end is what was inserted while in insert
+ mode. It gets copied to VI_INSERT_BUFFER because it depends
+ on absolute indices into the line which may change (though they
+ probably will not). */
+ _rl_vi_doing_insert = 0;
+ _rl_vi_save_insert (rl_undo_list->next);
+ vi_continued_command = 1;
+ }
+ else
+ {
+ if ((_rl_vi_last_key_before_insert == 'i' || _rl_vi_last_key_before_insert == 'a') && rl_undo_list)
+ _rl_vi_save_insert (rl_undo_list);
+ /* XXX - Other keys probably need to be checked. */
+ else if (_rl_vi_last_key_before_insert == 'C')
+ rl_end_undo_group ();
+ while (_rl_undo_group_level > 0)
+ rl_end_undo_group ();
+ vi_continued_command = 0;
+ }
+}
+
+int
+rl_vi_movement_mode (count, key)
+ int count, key;
+{
+ if (rl_point > 0)
+ rl_backward_char (1, key);
+
+ _rl_keymap = vi_movement_keymap;
+ _rl_vi_done_inserting ();
+
+ /* This is how POSIX.2 says `U' should behave -- everything up until the
+ first time you go into command mode should not be undone. */
+ if (RL_ISSTATE (RL_STATE_VICMDONCE) == 0)
+ rl_free_undo_list ();
+
+ RL_SETSTATE (RL_STATE_VICMDONCE);
+ return (0);
+}
+
+int
+rl_vi_arg_digit (count, c)
+ int count, c;
+{
+ if (c == '0' && rl_numeric_arg == 1 && !rl_explicit_arg)
+ return (rl_beg_of_line (1, c));
+ else
+ return (rl_digit_argument (count, c));
+}
+
+/* Change the case of the next COUNT characters. */
+#if defined (HANDLE_MULTIBYTE)
+static int
+_rl_vi_change_mbchar_case (count)
+ int count;
+{
+ wchar_t wc;
+ char mb[MB_LEN_MAX+1];
+ int mblen, p;
+ mbstate_t ps;
+
+ memset (&ps, 0, sizeof (mbstate_t));
+ if (_rl_adjust_point (rl_line_buffer, rl_point, &ps) > 0)
+ count--;
+ while (count-- && rl_point < rl_end)
+ {
+ mbrtowc (&wc, rl_line_buffer + rl_point, rl_end - rl_point, &ps);
+ if (iswupper (wc))
+ wc = towlower (wc);
+ else if (iswlower (wc))
+ wc = towupper (wc);
+ else
+ {
+ /* Just skip over chars neither upper nor lower case */
+ rl_forward_char (1, 0);
+ continue;
+ }
+
+ /* Vi is kind of strange here. */
+ if (wc)
+ {
+ p = rl_point;
+ mblen = wcrtomb (mb, wc, &ps);
+ if (mblen >= 0)
+ mb[mblen] = '\0';
+ rl_begin_undo_group ();
+ rl_vi_delete (1, 0);
+ if (rl_point < p) /* Did we retreat at EOL? */
+ rl_point++; /* XXX - should we advance more than 1 for mbchar? */
+ rl_insert_text (mb);
+ rl_end_undo_group ();
+ rl_vi_check ();
+ }
+ else
+ rl_forward_char (1, 0);
+ }
+
+ return 0;
+}
+#endif
+
+int
+rl_vi_change_case (count, ignore)
+ int count, ignore;
+{
+ int c, p;
+
+ /* Don't try this on an empty line. */
+ if (rl_point >= rl_end)
+ return (0);
+
+ c = 0;
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ return (_rl_vi_change_mbchar_case (count));
+#endif
+
+ while (count-- && rl_point < rl_end)
+ {
+ if (_rl_uppercase_p (rl_line_buffer[rl_point]))
+ c = _rl_to_lower (rl_line_buffer[rl_point]);
+ else if (_rl_lowercase_p (rl_line_buffer[rl_point]))
+ c = _rl_to_upper (rl_line_buffer[rl_point]);
+ else
+ {
+ /* Just skip over characters neither upper nor lower case. */
+ rl_forward_char (1, c);
+ continue;
+ }
+
+ /* Vi is kind of strange here. */
+ if (c)
+ {
+ p = rl_point;
+ rl_begin_undo_group ();
+ rl_vi_delete (1, c);
+ if (rl_point < p) /* Did we retreat at EOL? */
+ rl_point++;
+ _rl_insert_char (1, c);
+ rl_end_undo_group ();
+ rl_vi_check ();
+ }
+ else
+ rl_forward_char (1, c);
+ }
+ return (0);
+}
+
+int
+rl_vi_put (count, key)
+ int count, key;
+{
+ if (!_rl_uppercase_p (key) && (rl_point + 1 <= rl_end))
+ rl_point = _rl_find_next_mbchar (rl_line_buffer, rl_point, 1, MB_FIND_NONZERO);
+
+ while (count--)
+ rl_yank (1, key);
+
+ rl_backward_char (1, key);
+ return (0);
+}
+
+int
+rl_vi_check ()
+{
+ if (rl_point && rl_point == rl_end)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ else
+ rl_point--;
+ }
+ return (0);
+}
+
+int
+rl_vi_column (count, key)
+ int count, key;
+{
+ if (count > rl_end)
+ rl_end_of_line (1, key);
+ else
+ rl_point = count - 1;
+ return (0);
+}
+
+int
+rl_vi_domove (key, nextkey)
+ int key, *nextkey;
+{
+ int c, save;
+ int old_end;
+
+ rl_mark = rl_point;
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ *nextkey = c;
+
+ if (!member (c, vi_motion))
+ {
+ if (_rl_digit_p (c))
+ {
+ save = rl_numeric_arg;
+ rl_numeric_arg = _rl_digit_value (c);
+ rl_explicit_arg = 1;
+ RL_SETSTATE (RL_STATE_NUMERICARG|RL_STATE_VIMOTION);
+ rl_digit_loop1 ();
+ RL_UNSETSTATE (RL_STATE_VIMOTION);
+ rl_numeric_arg *= save;
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key (); /* real command */
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+ *nextkey = c;
+ }
+ else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
+ {
+ rl_mark = rl_end;
+ rl_beg_of_line (1, c);
+ _rl_vi_last_motion = c;
+ return (0);
+ }
+ else
+ return (-1);
+ }
+
+ _rl_vi_last_motion = c;
+
+ /* Append a blank character temporarily so that the motion routines
+ work right at the end of the line. */
+ old_end = rl_end;
+ rl_line_buffer[rl_end++] = ' ';
+ rl_line_buffer[rl_end] = '\0';
+
+ _rl_dispatch (c, _rl_keymap);
+
+ /* Remove the blank that we added. */
+ rl_end = old_end;
+ rl_line_buffer[rl_end] = '\0';
+ if (rl_point > rl_end)
+ rl_point = rl_end;
+
+ /* No change in position means the command failed. */
+ if (rl_mark == rl_point)
+ return (-1);
+
+ /* rl_vi_f[wW]ord () leaves the cursor on the first character of the next
+ word. If we are not at the end of the line, and we are on a
+ non-whitespace character, move back one (presumably to whitespace). */
+ if ((_rl_to_upper (c) == 'W') && rl_point < rl_end && rl_point > rl_mark &&
+ !whitespace (rl_line_buffer[rl_point]))
+ rl_point--;
+
+ /* If cw or cW, back up to the end of a word, so the behaviour of ce
+ or cE is the actual result. Brute-force, no subtlety. */
+ if (key == 'c' && rl_point >= rl_mark && (_rl_to_upper (c) == 'W'))
+ {
+ /* Don't move farther back than where we started. */
+ while (rl_point > rl_mark && whitespace (rl_line_buffer[rl_point]))
+ rl_point--;
+
+ /* Posix.2 says that if cw or cW moves the cursor towards the end of
+ the line, the character under the cursor should be deleted. */
+ if (rl_point == rl_mark)
+ rl_point++;
+ else
+ {
+ /* Move past the end of the word so that the kill doesn't
+ remove the last letter of the previous word. Only do this
+ if we are not at the end of the line. */
+ if (rl_point >= 0 && rl_point < (rl_end - 1) && !whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+ }
+ }
+
+ if (rl_mark < rl_point)
+ SWAP (rl_point, rl_mark);
+
+ return (0);
+}
+
+/* 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. */
+static int
+_rl_vi_arg_dispatch (c)
+ int c;
+{
+ int key;
+
+ key = c;
+ if (c >= 0 && _rl_keymap[c].type == ISFUNC && _rl_keymap[c].function == rl_universal_argument)
+ {
+ rl_numeric_arg *= 4;
+ return 1;
+ }
+
+ c = UNMETA (c);
+
+ if (_rl_digit_p (c))
+ {
+ if (rl_explicit_arg)
+ rl_numeric_arg = (rl_numeric_arg * 10) + _rl_digit_value (c);
+ else
+ rl_numeric_arg = _rl_digit_value (c);
+ rl_explicit_arg = 1;
+ return 1;
+ }
+ else
+ {
+ rl_clear_message ();
+ rl_stuff_char (key);
+ return 0;
+ }
+}
+
+/* A simplified loop for vi. Don't dispatch key at end.
+ Don't recognize minus sign?
+ Should this do rl_save_prompt/rl_restore_prompt? */
+static int
+rl_digit_loop1 ()
+{
+ int c, r;
+
+ while (1)
+ {
+ if (_rl_arg_overflow ())
+ return 1;
+
+ c = _rl_arg_getchar ();
+
+ r = _rl_vi_arg_dispatch (c);
+ if (r <= 0)
+ break;
+ }
+
+ RL_UNSETSTATE(RL_STATE_NUMERICARG);
+ return (0);
+}
+
+int
+rl_vi_delete_to (count, key)
+ int count, key;
+{
+ int c;
+
+ if (_rl_uppercase_p (key))
+ rl_stuff_char ('$');
+ else if (vi_redoing)
+ rl_stuff_char (_rl_vi_last_motion);
+
+ if (rl_vi_domove (key, &c))
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ /* These are the motion commands that do not require adjusting the
+ mark. */
+ if ((strchr (" l|h^0bB", c) == 0) && (rl_mark < rl_end))
+ rl_mark++;
+
+ rl_kill_text (rl_point, rl_mark);
+ return (0);
+}
+
+int
+rl_vi_change_to (count, key)
+ int count, key;
+{
+ int c, start_pos;
+
+ if (_rl_uppercase_p (key))
+ rl_stuff_char ('$');
+ else if (vi_redoing)
+ rl_stuff_char (_rl_vi_last_motion);
+
+ start_pos = rl_point;
+
+ if (rl_vi_domove (key, &c))
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ /* These are the motion commands that do not require adjusting the
+ mark. c[wW] are handled by special-case code in rl_vi_domove(),
+ and already leave the mark at the correct location. */
+ if ((strchr (" l|hwW^0bB", c) == 0) && (rl_mark < rl_end))
+ rl_mark++;
+
+ /* The cursor never moves with c[wW]. */
+ if ((_rl_to_upper (c) == 'W') && rl_point < start_pos)
+ rl_point = start_pos;
+
+ if (vi_redoing)
+ {
+ if (vi_insert_buffer && *vi_insert_buffer)
+ rl_begin_undo_group ();
+ rl_delete_text (rl_point, rl_mark);
+ if (vi_insert_buffer && *vi_insert_buffer)
+ {
+ rl_insert_text (vi_insert_buffer);
+ rl_end_undo_group ();
+ }
+ }
+ else
+ {
+ rl_begin_undo_group (); /* to make the `u' command work */
+ rl_kill_text (rl_point, rl_mark);
+ /* `C' does not save the text inserted for undoing or redoing. */
+ if (_rl_uppercase_p (key) == 0)
+ _rl_vi_doing_insert = 1;
+ rl_vi_start_inserting (key, rl_numeric_arg, rl_arg_sign);
+ }
+
+ return (0);
+}
+
+int
+rl_vi_yank_to (count, key)
+ int count, key;
+{
+ int c, save;
+
+ save = rl_point;
+ if (_rl_uppercase_p (key))
+ rl_stuff_char ('$');
+
+ if (rl_vi_domove (key, &c))
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ /* These are the motion commands that do not require adjusting the
+ mark. */
+ if ((strchr (" l|h^0%bB", c) == 0) && (rl_mark < rl_end))
+ rl_mark++;
+
+ rl_begin_undo_group ();
+ rl_kill_text (rl_point, rl_mark);
+ rl_end_undo_group ();
+ rl_do_undo ();
+ rl_point = save;
+
+ return (0);
+}
+
+int
+rl_vi_rubout (count, key)
+ int count, key;
+{
+ int p, opoint;
+
+ if (count < 0)
+ return (rl_vi_delete (-count, key));
+
+ if (rl_point == 0)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ opoint = rl_point;
+ if (count > 1 && MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_backward_char (count, key);
+ else if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_point = _rl_find_prev_mbchar (rl_line_buffer, rl_point, MB_FIND_NONZERO);
+ else
+ rl_point -= count;
+
+ if (rl_point < 0)
+ rl_point = 0;
+
+ rl_kill_text (rl_point, opoint);
+
+ return (0);
+}
+
+int
+rl_vi_delete (count, key)
+ int count, key;
+{
+ int end;
+
+ if (count < 0)
+ return (rl_vi_rubout (-count, key));
+
+ if (rl_end == 0)
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ end = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
+ else
+ end = rl_point + count;
+
+ if (end >= rl_end)
+ end = rl_end;
+
+ rl_kill_text (rl_point, end);
+
+ if (rl_point > 0 && rl_point == rl_end)
+ rl_backward_char (1, key);
+
+ return (0);
+}
+
+int
+rl_vi_back_to_indent (count, key)
+ int count, key;
+{
+ rl_beg_of_line (1, key);
+ while (rl_point < rl_end && whitespace (rl_line_buffer[rl_point]))
+ rl_point++;
+ return (0);
+}
+
+int
+rl_vi_first_print (count, key)
+ int count, key;
+{
+ return (rl_vi_back_to_indent (1, key));
+}
+
+static int _rl_cs_dir, _rl_cs_orig_dir;
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_vi_callback_char_search (data)
+ _rl_callback_generic_arg *data;
+{
+#if defined (HANDLE_MULTIBYTE)
+ _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+#else
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ _rl_vi_last_search_char = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+#endif
+
+ _rl_callback_func = 0;
+ _rl_want_redisplay = 1;
+
+#if defined (HANDLE_MULTIBYTE)
+ return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_mbchar, _rl_vi_last_search_mblen));
+#else
+ return (_rl_char_search_internal (data->count, _rl_cs_dir, _rl_vi_last_search_char));
+#endif
+}
+#endif
+
+int
+rl_vi_char_search (count, key)
+ int count, key;
+{
+#if defined (HANDLE_MULTIBYTE)
+ static char *target;
+ static int tlen;
+#else
+ static char target;
+#endif
+
+ if (key == ';' || key == ',')
+ _rl_cs_dir = (key == ';') ? _rl_cs_orig_dir : -_rl_cs_orig_dir;
+ else
+ {
+ switch (key)
+ {
+ case 't':
+ _rl_cs_orig_dir = _rl_cs_dir = FTO;
+ break;
+
+ case 'T':
+ _rl_cs_orig_dir = _rl_cs_dir = BTO;
+ break;
+
+ case 'f':
+ _rl_cs_orig_dir = _rl_cs_dir = FFIND;
+ break;
+
+ case 'F':
+ _rl_cs_orig_dir = _rl_cs_dir = BFIND;
+ break;
+ }
+
+ if (vi_redoing)
+ {
+ /* set target and tlen below */
+ }
+#if defined (READLINE_CALLBACKS)
+ else if (RL_ISSTATE (RL_STATE_CALLBACK))
+ {
+ _rl_callback_data = _rl_callback_data_alloc (count);
+ _rl_callback_data->i1 = _rl_cs_dir;
+ _rl_callback_func = _rl_vi_callback_char_search;
+ return (0);
+ }
+#endif
+ else
+ {
+#if defined (HANDLE_MULTIBYTE)
+ _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
+#else
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ _rl_vi_last_search_char = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+#endif
+ }
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ target = _rl_vi_last_search_mbchar;
+ tlen = _rl_vi_last_search_mblen;
+#else
+ target = _rl_vi_last_search_char;
+#endif
+
+#if defined (HANDLE_MULTIBYTE)
+ return (_rl_char_search_internal (count, _rl_cs_dir, target, tlen));
+#else
+ return (_rl_char_search_internal (count, _rl_cs_dir, target));
+#endif
+}
+
+/* Match brackets */
+int
+rl_vi_match (ignore, key)
+ int ignore, key;
+{
+ int count = 1, brack, pos, tmp, pre;
+
+ pos = rl_point;
+ if ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
+ {
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ {
+ while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0)
+ {
+ pre = rl_point;
+ rl_forward_char (1, key);
+ if (pre == rl_point)
+ break;
+ }
+ }
+ else
+ while ((brack = rl_vi_bracktype (rl_line_buffer[rl_point])) == 0 &&
+ rl_point < rl_end - 1)
+ rl_forward_char (1, key);
+
+ if (brack <= 0)
+ {
+ rl_point = pos;
+ rl_ding ();
+ return -1;
+ }
+ }
+
+ pos = rl_point;
+
+ if (brack < 0)
+ {
+ while (count)
+ {
+ tmp = pos;
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ pos--;
+ else
+ {
+ pos = _rl_find_prev_mbchar (rl_line_buffer, pos, MB_FIND_ANY);
+ if (tmp == pos)
+ pos--;
+ }
+ if (pos >= 0)
+ {
+ int b = rl_vi_bracktype (rl_line_buffer[pos]);
+ if (b == -brack)
+ count--;
+ else if (b == brack)
+ count++;
+ }
+ else
+ {
+ rl_ding ();
+ return -1;
+ }
+ }
+ }
+ else
+ { /* brack > 0 */
+ while (count)
+ {
+ if (MB_CUR_MAX == 1 || rl_byte_oriented)
+ pos++;
+ else
+ pos = _rl_find_next_mbchar (rl_line_buffer, pos, 1, MB_FIND_ANY);
+
+ if (pos < rl_end)
+ {
+ int b = rl_vi_bracktype (rl_line_buffer[pos]);
+ if (b == -brack)
+ count--;
+ else if (b == brack)
+ count++;
+ }
+ else
+ {
+ rl_ding ();
+ return -1;
+ }
+ }
+ }
+ rl_point = pos;
+ return (0);
+}
+
+int
+rl_vi_bracktype (c)
+ int c;
+{
+ switch (c)
+ {
+ case '(': return 1;
+ case ')': return -1;
+ case '[': return 2;
+ case ']': return -2;
+ case '{': return 3;
+ case '}': return -3;
+ default: return 0;
+ }
+}
+
+static int
+_rl_vi_change_char (count, c, mb)
+ int count, c;
+ char *mb;
+{
+ int p;
+
+ if (c == '\033' || c == CTRL ('C'))
+ return -1;
+
+ rl_begin_undo_group ();
+ while (count-- && rl_point < rl_end)
+ {
+ p = rl_point;
+ rl_vi_delete (1, c);
+ if (rl_point < p) /* Did we retreat at EOL? */
+ rl_point++;
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ rl_insert_text (mb);
+ else
+#endif
+ _rl_insert_char (1, c);
+ }
+
+ /* The cursor shall be left on the last character changed. */
+ rl_backward_char (1, c);
+
+ rl_end_undo_group ();
+
+ return (0);
+}
+
+static int
+_rl_vi_callback_getchar (mb, mblen)
+ char *mb;
+ int mblen;
+{
+ int c;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ c = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
+ c = _rl_read_mbstring (c, mb, mblen);
+#endif
+
+ return c;
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_vi_callback_change_char (data)
+ _rl_callback_generic_arg *data;
+{
+ int c;
+ char mb[MB_LEN_MAX];
+
+ _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
+
+ _rl_callback_func = 0;
+ _rl_want_redisplay = 1;
+
+ return (_rl_vi_change_char (data->count, c, mb));
+}
+#endif
+
+int
+rl_vi_change_char (count, key)
+ int count, key;
+{
+ int c;
+ char mb[MB_LEN_MAX];
+
+ if (vi_redoing)
+ {
+ c = _rl_vi_last_replacement;
+ mb[0] = c;
+ mb[1] = '\0';
+ }
+#if defined (READLINE_CALLBACKS)
+ else if (RL_ISSTATE (RL_STATE_CALLBACK))
+ {
+ _rl_callback_data = _rl_callback_data_alloc (count);
+ _rl_callback_func = _rl_vi_callback_change_char;
+ return (0);
+ }
+#endif
+ else
+ _rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
+
+ return (_rl_vi_change_char (count, c, mb));
+}
+
+int
+rl_vi_subst (count, key)
+ int count, key;
+{
+ /* If we are redoing, rl_vi_change_to will stuff the last motion char */
+ if (vi_redoing == 0)
+ rl_stuff_char ((key == 'S') ? 'c' : 'l'); /* `S' == `cc', `s' == `cl' */
+
+ return (rl_vi_change_to (count, 'c'));
+}
+
+int
+rl_vi_overstrike (count, key)
+ int count, key;
+{
+ if (_rl_vi_doing_insert == 0)
+ {
+ _rl_vi_doing_insert = 1;
+ rl_begin_undo_group ();
+ }
+
+ if (count > 0)
+ {
+ _rl_overwrite_char (count, key);
+ vi_replace_count += count;
+ }
+
+ return (0);
+}
+
+int
+rl_vi_overstrike_delete (count, key)
+ int count, key;
+{
+ int i, s;
+
+ for (i = 0; i < count; i++)
+ {
+ if (vi_replace_count == 0)
+ {
+ rl_ding ();
+ break;
+ }
+ s = rl_point;
+
+ if (rl_do_undo ())
+ vi_replace_count--;
+
+ if (rl_point == s)
+ rl_backward_char (1, key);
+ }
+
+ if (vi_replace_count == 0 && _rl_vi_doing_insert)
+ {
+ rl_end_undo_group ();
+ rl_do_undo ();
+ _rl_vi_doing_insert = 0;
+ }
+ return (0);
+}
+
+int
+rl_vi_replace (count, key)
+ int count, key;
+{
+ int i;
+
+ vi_replace_count = 0;
+
+ if (!vi_replace_map)
+ {
+ vi_replace_map = rl_make_bare_keymap ();
+
+ for (i = ' '; i < KEYMAP_SIZE; i++)
+ vi_replace_map[i].function = rl_vi_overstrike;
+
+ vi_replace_map[RUBOUT].function = rl_vi_overstrike_delete;
+ vi_replace_map[ESC].function = rl_vi_movement_mode;
+ vi_replace_map[RETURN].function = rl_newline;
+ vi_replace_map[NEWLINE].function = rl_newline;
+
+ /* If the normal vi insertion keymap has ^H bound to erase, do the
+ same here. Probably should remove the assignment to RUBOUT up
+ there, but I don't think it will make a difference in real life. */
+ if (vi_insertion_keymap[CTRL ('H')].type == ISFUNC &&
+ vi_insertion_keymap[CTRL ('H')].function == rl_rubout)
+ vi_replace_map[CTRL ('H')].function = rl_vi_overstrike_delete;
+
+ }
+ _rl_keymap = vi_replace_map;
+ return (0);
+}
+
+#if 0
+/* Try to complete the word we are standing on or the word that ends with
+ the previous character. A space matches everything. Word delimiters are
+ space and ;. */
+int
+rl_vi_possible_completions()
+{
+ int save_pos = rl_point;
+
+ if (rl_line_buffer[rl_point] != ' ' && rl_line_buffer[rl_point] != ';')
+ {
+ while (rl_point < rl_end && rl_line_buffer[rl_point] != ' ' &&
+ rl_line_buffer[rl_point] != ';')
+ rl_point++;
+ }
+ else if (rl_line_buffer[rl_point - 1] == ';')
+ {
+ rl_ding ();
+ return (0);
+ }
+
+ rl_possible_completions ();
+ rl_point = save_pos;
+
+ return (0);
+}
+#endif
+
+/* Functions to save and restore marks. */
+static int
+_rl_vi_set_mark ()
+{
+ int ch;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ ch = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (ch < 'a' || ch > 'z')
+ {
+ rl_ding ();
+ return -1;
+ }
+ ch -= 'a';
+ vi_mark_chars[ch] = rl_point;
+ return 0;
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_vi_callback_set_mark (data)
+ _rl_callback_generic_arg *data;
+{
+ _rl_callback_func = 0;
+ _rl_want_redisplay = 1;
+
+ return (_rl_vi_set_mark ());
+}
+#endif
+
+int
+rl_vi_set_mark (count, key)
+ int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+ if (RL_ISSTATE (RL_STATE_CALLBACK))
+ {
+ _rl_callback_data = 0;
+ _rl_callback_func = _rl_vi_callback_set_mark;
+ return (0);
+ }
+#endif
+
+ return (_rl_vi_set_mark ());
+}
+
+static int
+_rl_vi_goto_mark ()
+{
+ int ch;
+
+ RL_SETSTATE(RL_STATE_MOREINPUT);
+ ch = rl_read_key ();
+ RL_UNSETSTATE(RL_STATE_MOREINPUT);
+
+ if (ch == '`')
+ {
+ rl_point = rl_mark;
+ return 0;
+ }
+ else if (ch < 'a' || ch > 'z')
+ {
+ rl_ding ();
+ return -1;
+ }
+
+ ch -= 'a';
+ if (vi_mark_chars[ch] == -1)
+ {
+ rl_ding ();
+ return -1;
+ }
+ rl_point = vi_mark_chars[ch];
+ return 0;
+}
+
+#if defined (READLINE_CALLBACKS)
+static int
+_rl_vi_callback_goto_mark (data)
+ _rl_callback_generic_arg *data;
+{
+ _rl_callback_func = 0;
+ _rl_want_redisplay = 1;
+
+ return (_rl_vi_goto_mark ());
+}
+#endif
+
+int
+rl_vi_goto_mark (count, key)
+ int count, key;
+{
+#if defined (READLINE_CALLBACKS)
+ if (RL_ISSTATE (RL_STATE_CALLBACK))
+ {
+ _rl_callback_data = 0;
+ _rl_callback_func = _rl_vi_callback_goto_mark;
+ return (0);
+ }
+#endif
+
+ return (_rl_vi_goto_mark ());
+}
+#endif /* VI_MODE */
diff --git a/parse.y b/parse.y
index b69d3a43..238013fd 100644
--- a/parse.y
+++ b/parse.y
@@ -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 *);
diff --git a/parse.y~ b/parse.y~
index 60165adc..aa26f15b 100644
--- a/parse.y~
+++ b/parse.y~
@@ -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 *);
diff --git a/shell.c b/shell.c
index 6d07c78f..1a4c0017 100644
--- a/shell.c
+++ b/shell.c
@@ -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
diff --git a/shell.c~ b/shell.c~
new file mode 100644
index 00000000..6d07c78f
--- /dev/null
+++ b/shell.c~
@@ -0,0 +1,1793 @@
+/* shell.c -- GNU's idea of the POSIX shell specification. */
+
+/* Copyright (C) 1987-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.
+
+ Birthdate:
+ Sunday, January 10th, 1988.
+ Initial author: Brian Fox
+*/
+#define INSTALL_DEBUG_MODE
+
+#include "config.h"
+
+#include "bashtypes.h"
+#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
+# include <sys/file.h>
+#endif
+#include "posixstat.h"
+#include "posixtime.h"
+#include "bashansi.h"
+#include <stdio.h>
+#include <signal.h>
+#include <errno.h>
+#include "filecntl.h"
+#include <pwd.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include "bashintl.h"
+
+#define NEED_SH_SETLINEBUF_DECL /* used in externs.h */
+
+#include "shell.h"
+#include "flags.h"
+#include "trap.h"
+#include "mailcheck.h"
+#include "builtins.h"
+#include "builtins/common.h"
+
+#if defined (JOB_CONTROL)
+#include "jobs.h"
+#endif /* JOB_CONTROL */
+
+#include "input.h"
+#include "execute_cmd.h"
+#include "findcmd.h"
+
+#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
+# include <malloc/shmalloc.h>
+#endif
+
+#if defined (HISTORY)
+# include "bashhist.h"
+# include <readline/history.h>
+#endif
+
+#include <tilde/tilde.h>
+#include <glob/strmatch.h>
+
+#if defined (__OPENNT)
+# include <opennt/opennt.h>
+#endif
+
+#if !defined (HAVE_GETPW_DECLS)
+extern struct passwd *getpwuid ();
+#endif /* !HAVE_GETPW_DECLS */
+
+#if !defined (errno)
+extern int errno;
+#endif
+
+#if defined (NO_MAIN_ENV_ARG)
+extern char **environ; /* used if no third argument to main() */
+#endif
+
+extern char *dist_version, *release_status;
+extern int patch_level, build_version;
+extern int shell_level;
+extern int subshell_environment;
+extern int last_command_exit_value;
+extern int line_number;
+extern int expand_aliases;
+extern int array_needs_making;
+extern int gnu_error_format;
+extern char *primary_prompt, *secondary_prompt;
+extern char *this_command_name;
+
+/* Non-zero means that this shell has already been run; i.e. you should
+ call shell_reinitialize () if you need to start afresh. */
+int shell_initialized = 0;
+
+COMMAND *global_command = (COMMAND *)NULL;
+
+/* Information about the current user. */
+struct user_info current_user =
+{
+ (uid_t)-1, (uid_t)-1, (gid_t)-1, (gid_t)-1,
+ (char *)NULL, (char *)NULL, (char *)NULL
+};
+
+/* The current host's name. */
+char *current_host_name = (char *)NULL;
+
+/* Non-zero means that this shell is a login shell.
+ Specifically:
+ 0 = not login shell.
+ 1 = login shell from getty (or equivalent fake out)
+ -1 = login shell from "--login" (or -l) flag.
+ -2 = both from getty, and from flag.
+ */
+int login_shell = 0;
+
+/* Non-zero means that at this moment, the shell is interactive. In
+ general, this means that the shell is at this moment reading input
+ from the keyboard. */
+int interactive = 0;
+
+/* Non-zero means that the shell was started as an interactive shell. */
+int interactive_shell = 0;
+
+/* Non-zero means to send a SIGHUP to all jobs when an interactive login
+ shell exits. */
+int hup_on_exit = 0;
+
+/* Tells what state the shell was in when it started:
+ 0 = non-interactive shell script
+ 1 = interactive
+ 2 = -c command
+ 3 = wordexp evaluation
+ This is a superset of the information provided by interactive_shell.
+*/
+int startup_state = 0;
+
+/* Special debugging helper. */
+int debugging_login_shell = 0;
+
+/* The environment that the shell passes to other commands. */
+char **shell_environment;
+
+/* Non-zero when we are executing a top-level command. */
+int executing = 0;
+
+/* The number of commands executed so far. */
+int current_command_number = 1;
+
+/* Non-zero is the recursion depth for commands. */
+int indirection_level = 0;
+
+/* The name of this shell, as taken from argv[0]. */
+char *shell_name = (char *)NULL;
+
+/* time in seconds when the shell was started */
+time_t shell_start_time;
+
+/* Are we running in an emacs shell window? */
+int running_under_emacs;
+
+/* The name of the .(shell)rc file. */
+static char *bashrc_file = "~/.bashrc";
+
+/* Non-zero means to act more like the Bourne shell on startup. */
+static int act_like_sh;
+
+/* Non-zero if this shell is being run by `su'. */
+static int su_shell;
+
+/* Non-zero if we have already expanded and sourced $ENV. */
+static int sourced_env;
+
+/* Is this shell running setuid? */
+static int running_setuid;
+
+/* Values for the long-winded argument names. */
+static int debugging; /* Do debugging things. */
+static int no_rc; /* Don't execute ~/.bashrc */
+static int no_profile; /* Don't execute .profile */
+static int do_version; /* Display interesting version info. */
+static int make_login_shell; /* Make this shell be a `-bash' shell. */
+static int want_initial_help; /* --help option */
+
+int debugging_mode = 0; /* In debugging mode with --debugger */
+int no_line_editing = 0; /* Don't do fancy line editing. */
+int dump_translatable_strings; /* Dump strings in $"...", don't execute. */
+int dump_po_strings; /* Dump strings in $"..." in po format */
+int wordexp_only = 0; /* Do word expansion only */
+int protected_mode = 0; /* No command substitution with --wordexp */
+
+#if defined (STRICT_POSIX)
+int posixly_correct = 1; /* Non-zero means posix.2 superset. */
+#else
+int posixly_correct = 0; /* Non-zero means posix.2 superset. */
+#endif
+
+
+/* Some long-winded argument names. These are obviously new. */
+#define Int 1
+#define Charp 2
+struct {
+ char *name;
+ int type;
+ int *int_value;
+ char **char_value;
+} long_args[] = {
+ { "debug", Int, &debugging, (char **)0x0 },
+#if defined (DEBUGGER)
+ { "debugger", Int, &debugging_mode, (char **)0x0 },
+#endif
+ { "dump-po-strings", Int, &dump_po_strings, (char **)0x0 },
+ { "dump-strings", Int, &dump_translatable_strings, (char **)0x0 },
+ { "help", Int, &want_initial_help, (char **)0x0 },
+ { "init-file", Charp, (int *)0x0, &bashrc_file },
+ { "login", Int, &make_login_shell, (char **)0x0 },
+ { "noediting", Int, &no_line_editing, (char **)0x0 },
+ { "noprofile", Int, &no_profile, (char **)0x0 },
+ { "norc", Int, &no_rc, (char **)0x0 },
+ { "posix", Int, &posixly_correct, (char **)0x0 },
+ { "protected", Int, &protected_mode, (char **)0x0 },
+ { "rcfile", Charp, (int *)0x0, &bashrc_file },
+#if defined (RESTRICTED_SHELL)
+ { "restricted", Int, &restricted, (char **)0x0 },
+#endif
+ { "verbose", Int, &echo_input_at_read, (char **)0x0 },
+ { "version", Int, &do_version, (char **)0x0 },
+ { "wordexp", Int, &wordexp_only, (char **)0x0 },
+ { (char *)0x0, Int, (int *)0x0, (char **)0x0 }
+};
+
+/* These are extern so execute_simple_command can set them, and then
+ longjmp back to main to execute a shell script, instead of calling
+ main () again and resulting in indefinite, possibly fatal, stack
+ growth. */
+procenv_t subshell_top_level;
+int subshell_argc;
+char **subshell_argv;
+char **subshell_envp;
+
+#if defined (BUFFERED_INPUT)
+/* The file descriptor from which the shell is reading input. */
+int default_buffered_input = -1;
+#endif
+
+/* The following two variables are not static so they can show up in $-. */
+int read_from_stdin; /* -s flag supplied */
+int want_pending_command; /* -c flag supplied */
+
+/* This variable is not static so it can be bound to $BASH_EXECUTION_STRING */
+char *command_execution_string; /* argument to -c option */
+
+int malloc_trace_at_exit = 0;
+
+static int shell_reinitialized = 0;
+
+static FILE *default_input;
+
+static STRING_INT_ALIST *shopt_alist;
+static int shopt_ind = 0, shopt_len = 0;
+
+static int parse_long_options __P((char **, int, int));
+static int parse_shell_options __P((char **, int, int));
+static int bind_args __P((char **, int, int, int));
+
+static void start_debugger __P((void));
+
+static void add_shopt_to_alist __P((char *, int));
+static void run_shopt_alist __P((void));
+
+static void execute_env_file __P((char *));
+static void run_startup_files __P((void));
+static int open_shell_script __P((char *));
+static void set_bash_input __P((void));
+static int run_one_command __P((char *));
+static int run_wordexp __P((char *));
+
+static int uidget __P((void));
+
+static void init_interactive __P((void));
+static void init_noninteractive __P((void));
+
+static void set_shell_name __P((char *));
+static void shell_initialize __P((void));
+static void shell_reinitialize __P((void));
+
+static void show_shell_usage __P((FILE *, int));
+
+#ifdef __CYGWIN__
+static void
+_cygwin32_check_tmp ()
+{
+ struct stat sb;
+
+ if (stat ("/tmp", &sb) < 0)
+ internal_warning (_("could not find /tmp, please create!"));
+ else
+ {
+ if (S_ISDIR (sb.st_mode) == 0)
+ internal_warning (_("/tmp must be a valid directory name"));
+ }
+}
+#endif /* __CYGWIN__ */
+
+#if defined (NO_MAIN_ENV_ARG)
+/* systems without third argument to main() */
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+#else /* !NO_MAIN_ENV_ARG */
+int
+main (argc, argv, env)
+ int argc;
+ char **argv, **env;
+#endif /* !NO_MAIN_ENV_ARG */
+{
+ register int i;
+ int code, old_errexit_flag;
+#if defined (RESTRICTED_SHELL)
+ int saverst;
+#endif
+ volatile int locally_skip_execution;
+ volatile int arg_index, top_level_arg_index;
+#ifdef __OPENNT
+ char **env;
+
+ env = environ;
+#endif /* __OPENNT */
+
+ USE_VAR(argc);
+ USE_VAR(argv);
+ USE_VAR(env);
+ USE_VAR(code);
+ USE_VAR(old_errexit_flag);
+#if defined (RESTRICTED_SHELL)
+ USE_VAR(saverst);
+#endif
+
+ /* Catch early SIGINTs. */
+ code = setjmp (top_level);
+ if (code)
+ exit (2);
+
+#if defined (USING_BASH_MALLOC) && defined (DEBUG) && !defined (DISABLE_MALLOC_WRAPPERS)
+# if 1
+ malloc_set_register (1);
+# endif
+#endif
+
+ check_dev_tty ();
+
+#ifdef __CYGWIN__
+ _cygwin32_check_tmp ();
+#endif /* __CYGWIN__ */
+
+ /* Wait forever if we are debugging a login shell. */
+ while (debugging_login_shell) sleep (3);
+
+ set_default_locale ();
+
+ running_setuid = uidget ();
+
+ if (getenv ("POSIXLY_CORRECT") || getenv ("POSIX_PEDANTIC"))
+ posixly_correct = 1;
+
+#if defined (USE_GNU_MALLOC_LIBRARY)
+ mcheck (programming_error, (void (*) ())0);
+#endif /* USE_GNU_MALLOC_LIBRARY */
+
+ if (setjmp (subshell_top_level))
+ {
+ argc = subshell_argc;
+ argv = subshell_argv;
+ env = subshell_envp;
+ sourced_env = 0;
+ }
+
+ shell_reinitialized = 0;
+
+ /* Initialize `local' variables for all `invocations' of main (). */
+ arg_index = 1;
+ if (arg_index > argc)
+ arg_index = argc;
+ command_execution_string = (char *)NULL;
+ want_pending_command = locally_skip_execution = read_from_stdin = 0;
+ default_input = stdin;
+#if defined (BUFFERED_INPUT)
+ default_buffered_input = -1;
+#endif
+
+ /* Fix for the `infinite process creation' bug when running shell scripts
+ from startup files on System V. */
+ login_shell = make_login_shell = 0;
+
+ /* If this shell has already been run, then reinitialize it to a
+ vanilla state. */
+ if (shell_initialized || shell_name)
+ {
+ /* Make sure that we do not infinitely recurse as a login shell. */
+ if (*shell_name == '-')
+ shell_name++;
+
+ shell_reinitialize ();
+ if (setjmp (top_level))
+ exit (2);
+ }
+
+ shell_environment = env;
+ set_shell_name (argv[0]);
+ shell_start_time = NOW; /* NOW now defined in general.h */
+
+ /* Parse argument flags from the input line. */
+
+ /* Find full word arguments first. */
+ arg_index = parse_long_options (argv, arg_index, argc);
+
+ if (want_initial_help)
+ {
+ show_shell_usage (stdout, 1);
+ exit (EXECUTION_SUCCESS);
+ }
+
+ if (do_version)
+ {
+ show_shell_version (1);
+ exit (EXECUTION_SUCCESS);
+ }
+
+ /* All done with full word options; do standard shell option parsing.*/
+ this_command_name = shell_name; /* for error reporting */
+ arg_index = parse_shell_options (argv, arg_index, argc);
+
+ /* If user supplied the "--login" (or -l) flag, then set and invert
+ LOGIN_SHELL. */
+ if (make_login_shell)
+ {
+ login_shell++;
+ login_shell = -login_shell;
+ }
+
+ set_login_shell (login_shell != 0);
+
+ if (dump_po_strings)
+ dump_translatable_strings = 1;
+
+ if (dump_translatable_strings)
+ read_but_dont_execute = 1;
+
+ if (running_setuid && privileged_mode == 0)
+ disable_priv_mode ();
+
+ /* Need to get the argument to a -c option processed in the
+ above loop. The next arg is a command to execute, and the
+ following args are $0...$n respectively. */
+ if (want_pending_command)
+ {
+ command_execution_string = argv[arg_index];
+ if (command_execution_string == 0)
+ {
+ report_error (_("%s: option requires an argument"), "-c");
+ exit (EX_BADUSAGE);
+ }
+ arg_index++;
+ }
+ this_command_name = (char *)NULL;
+
+ cmd_init(); /* initialize the command object caches */
+
+ /* First, let the outside world know about our interactive status.
+ A shell is interactive if the `-i' flag was given, or if all of
+ the following conditions are met:
+ no -c command
+ no arguments remaining or the -s flag given
+ standard input is a terminal
+ standard error is a terminal
+ Refer to Posix.2, the description of the `sh' utility. */
+
+ if (forced_interactive || /* -i flag */
+ (!command_execution_string && /* No -c command and ... */
+ wordexp_only == 0 && /* No --wordexp and ... */
+ ((arg_index == argc) || /* no remaining args or... */
+ read_from_stdin) && /* -s flag with args, and */
+ isatty (fileno (stdin)) && /* Input is a terminal and */
+ isatty (fileno (stderr)))) /* error output is a terminal. */
+ init_interactive ();
+ else
+ init_noninteractive ();
+
+#define CLOSE_FDS_AT_LOGIN
+#if defined (CLOSE_FDS_AT_LOGIN)
+ /*
+ * Some systems have the bad habit of starting login shells with lots of open
+ * file descriptors. For instance, most systems that have picked up the
+ * pre-4.0 Sun YP code leave a file descriptor open each time you call one
+ * of the getpw* functions, and it's set to be open across execs. That
+ * means one for login, one for xterm, one for shelltool, etc.
+ */
+ if (login_shell && interactive_shell)
+ {
+ for (i = 3; i < 20; i++)
+ close (i);
+ }
+#endif /* CLOSE_FDS_AT_LOGIN */
+
+ /* If we're in a strict Posix.2 mode, turn on interactive comments,
+ alias expansion in non-interactive shells, and other Posix.2 things. */
+ if (posixly_correct)
+ {
+ bind_variable ("POSIXLY_CORRECT", "y", 0);
+ sv_strict_posix ("POSIXLY_CORRECT");
+ }
+
+ /* Now we run the shopt_alist and process the options. */
+ if (shopt_alist)
+ run_shopt_alist ();
+
+ /* From here on in, the shell must be a normal functioning shell.
+ Variables from the environment are expected to be set, etc. */
+ shell_initialize ();
+
+ set_default_locale_vars ();
+
+ if (interactive_shell)
+ {
+ char *term, *emacs;
+
+ term = get_string_value ("TERM");
+ no_line_editing |= term && (STREQ (term, "emacs"));
+ emacs = get_string_value ("EMACS");
+ running_under_emacs = emacs ? ((strstr (emacs, "term") != 0) ? 2 : 1) : 0;
+#if 0
+ no_line_editing |= emacs && emacs[0] == 't' && emacs[1] == '\0';
+#else
+ no_line_editing |= emacs && emacs[0] == 't' && emacs[1] == '\0' && STREQ (term, "dumb");
+#endif
+ if (running_under_emacs)
+ gnu_error_format = 1;
+ }
+
+ top_level_arg_index = arg_index;
+ old_errexit_flag = exit_immediately_on_error;
+
+ /* Give this shell a place to longjmp to before executing the
+ startup files. This allows users to press C-c to abort the
+ lengthy startup. */
+ code = setjmp (top_level);
+ if (code)
+ {
+ if (code == EXITPROG || code == ERREXIT)
+ exit_shell (last_command_exit_value);
+ else
+ {
+#if defined (JOB_CONTROL)
+ /* Reset job control, since run_startup_files turned it off. */
+ set_job_control (interactive_shell);
+#endif
+ /* Reset value of `set -e', since it's turned off before running
+ the startup files. */
+ exit_immediately_on_error += old_errexit_flag;
+ locally_skip_execution++;
+ }
+ }
+
+ arg_index = top_level_arg_index;
+
+ /* Execute the start-up scripts. */
+
+ if (interactive_shell == 0)
+ {
+ unbind_variable ("PS1");
+ unbind_variable ("PS2");
+ interactive = 0;
+#if 0
+ /* This has already been done by init_noninteractive */
+ expand_aliases = posixly_correct;
+#endif
+ }
+ else
+ {
+ change_flag ('i', FLAG_ON);
+ interactive = 1;
+ }
+
+#if defined (RESTRICTED_SHELL)
+ /* Set restricted_shell based on whether the basename of $0 indicates that
+ the shell should be restricted or if the `-r' option was supplied at
+ startup. */
+ restricted_shell = shell_is_restricted (shell_name);
+
+ /* If the `-r' option is supplied at invocation, make sure that the shell
+ is not in restricted mode when running the startup files. */
+ saverst = restricted;
+ restricted = 0;
+#endif
+
+ /* The startup files are run with `set -e' temporarily disabled. */
+ if (locally_skip_execution == 0 && running_setuid == 0)
+ {
+ old_errexit_flag = exit_immediately_on_error;
+ exit_immediately_on_error = 0;
+
+ run_startup_files ();
+ exit_immediately_on_error += old_errexit_flag;
+ }
+
+ /* If we are invoked as `sh', turn on Posix mode. */
+ if (act_like_sh)
+ {
+ bind_variable ("POSIXLY_CORRECT", "y", 0);
+ sv_strict_posix ("POSIXLY_CORRECT");
+ }
+
+#if defined (RESTRICTED_SHELL)
+ /* Turn on the restrictions after executing the startup files. This
+ means that `bash -r' or `set -r' invoked from a startup file will
+ turn on the restrictions after the startup files are executed. */
+ restricted = saverst || restricted;
+ if (shell_reinitialized == 0)
+ maybe_make_restricted (shell_name);
+#endif /* RESTRICTED_SHELL */
+
+ if (wordexp_only)
+ {
+ startup_state = 3;
+ last_command_exit_value = run_wordexp (argv[arg_index]);
+ exit_shell (last_command_exit_value);
+ }
+
+ if (command_execution_string)
+ {
+ arg_index = bind_args (argv, arg_index, argc, 0);
+ startup_state = 2;
+
+ if (debugging_mode)
+ start_debugger ();
+
+#if defined (ONESHOT)
+ executing = 1;
+ run_one_command (command_execution_string);
+ exit_shell (last_command_exit_value);
+#else /* ONESHOT */
+ with_input_from_string (command_execution_string, "-c");
+ goto read_and_execute;
+#endif /* !ONESHOT */
+ }
+
+ /* Get possible input filename and set up default_buffered_input or
+ default_input as appropriate. */
+ if (arg_index != argc && read_from_stdin == 0)
+ {
+ open_shell_script (argv[arg_index]);
+ arg_index++;
+ }
+ else if (interactive == 0)
+ /* In this mode, bash is reading a script from stdin, which is a
+ pipe or redirected file. */
+#if defined (BUFFERED_INPUT)
+ default_buffered_input = fileno (stdin); /* == 0 */
+#else
+ setbuf (default_input, (char *)NULL);
+#endif /* !BUFFERED_INPUT */
+
+ set_bash_input ();
+
+ /* Bind remaining args to $1 ... $n */
+ arg_index = bind_args (argv, arg_index, argc, 1);
+
+ if (debugging_mode && locally_skip_execution == 0 && running_setuid == 0)
+ start_debugger ();
+
+ /* Do the things that should be done only for interactive shells. */
+ if (interactive_shell)
+ {
+ /* Set up for checking for presence of mail. */
+ remember_mail_dates ();
+ reset_mail_timer ();
+
+#if defined (HISTORY)
+ /* Initialize the interactive history stuff. */
+ bash_initialize_history ();
+ /* Don't load the history from the history file if we've already
+ saved some lines in this session (e.g., by putting `history -s xx'
+ into one of the startup files). */
+ if (shell_initialized == 0 && history_lines_this_session == 0)
+ load_history ();
+#endif /* HISTORY */
+
+ /* Initialize terminal state for interactive shells after the
+ .bash_profile and .bashrc are interpreted. */
+ get_tty_state ();
+ }
+
+#if !defined (ONESHOT)
+ read_and_execute:
+#endif /* !ONESHOT */
+
+ shell_initialized = 1;
+
+ /* Read commands until exit condition. */
+ reader_loop ();
+ exit_shell (last_command_exit_value);
+}
+
+static int
+parse_long_options (argv, arg_start, arg_end)
+ char **argv;
+ int arg_start, arg_end;
+{
+ int arg_index, longarg, i;
+ char *arg_string;
+
+ arg_index = arg_start;
+ while ((arg_index != arg_end) && (arg_string = argv[arg_index]) &&
+ (*arg_string == '-'))
+ {
+ longarg = 0;
+
+ /* Make --login equivalent to -login. */
+ if (arg_string[1] == '-' && arg_string[2])
+ {
+ longarg = 1;
+ arg_string++;
+ }
+
+ for (i = 0; long_args[i].name; i++)
+ {
+ if (STREQ (arg_string + 1, long_args[i].name))
+ {
+ if (long_args[i].type == Int)
+ *long_args[i].int_value = 1;
+ else if (argv[++arg_index] == 0)
+ {
+ report_error (_("%s: option requires an argument"), long_args[i].name);
+ exit (EX_BADUSAGE);
+ }
+ else
+ *long_args[i].char_value = argv[arg_index];
+
+ break;
+ }
+ }
+ if (long_args[i].name == 0)
+ {
+ if (longarg)
+ {
+ report_error (_("%s: invalid option"), argv[arg_index]);
+ show_shell_usage (stderr, 0);
+ exit (EX_BADUSAGE);
+ }
+ break; /* No such argument. Maybe flag arg. */
+ }
+
+ arg_index++;
+ }
+
+ return (arg_index);
+}
+
+static int
+parse_shell_options (argv, arg_start, arg_end)
+ char **argv;
+ int arg_start, arg_end;
+{
+ int arg_index;
+ int arg_character, on_or_off, next_arg, i;
+ char *o_option, *arg_string;
+
+ arg_index = arg_start;
+ while (arg_index != arg_end && (arg_string = argv[arg_index]) &&
+ (*arg_string == '-' || *arg_string == '+'))
+ {
+ /* There are flag arguments, so parse them. */
+ next_arg = arg_index + 1;
+
+ /* A single `-' signals the end of options. From the 4.3 BSD sh.
+ An option `--' means the same thing; this is the standard
+ getopt(3) meaning. */
+ if (arg_string[0] == '-' &&
+ (arg_string[1] == '\0' ||
+ (arg_string[1] == '-' && arg_string[2] == '\0')))
+ return (next_arg);
+
+ i = 1;
+ on_or_off = arg_string[0];
+ while (arg_character = arg_string[i++])
+ {
+ switch (arg_character)
+ {
+ case 'c':
+ want_pending_command = 1;
+ break;
+
+ case 'l':
+ make_login_shell = 1;
+ break;
+
+ case 's':
+ read_from_stdin = 1;
+ break;
+
+ case 'o':
+ o_option = argv[next_arg];
+ if (o_option == 0)
+ {
+ list_minus_o_opts (-1, (on_or_off == '-') ? 0 : 1);
+ break;
+ }
+ if (set_minus_o_option (on_or_off, o_option) != EXECUTION_SUCCESS)
+ exit (EX_BADUSAGE);
+ next_arg++;
+ break;
+
+ case 'O':
+ /* Since some of these can be overridden by the normal
+ interactive/non-interactive shell initialization or
+ initializing posix mode, we save the options and process
+ them after initialization. */
+ o_option = argv[next_arg];
+ if (o_option == 0)
+ {
+ shopt_listopt (o_option, (on_or_off == '-') ? 0 : 1);
+ break;
+ }
+ add_shopt_to_alist (o_option, on_or_off);
+ next_arg++;
+ break;
+
+ case 'D':
+ dump_translatable_strings = 1;
+ break;
+
+ default:
+ if (change_flag (arg_character, on_or_off) == FLAG_ERROR)
+ {
+ report_error (_("%c%c: invalid option"), on_or_off, arg_character);
+ show_shell_usage (stderr, 0);
+ exit (EX_BADUSAGE);
+ }
+ }
+ }
+ /* Can't do just a simple increment anymore -- what about
+ "bash -abouo emacs ignoreeof -hP"? */
+ arg_index = next_arg;
+ }
+
+ return (arg_index);
+}
+
+/* Exit the shell with status S. */
+void
+exit_shell (s)
+ int s;
+{
+ /* Do trap[0] if defined. Allow it to override the exit status
+ passed to us. */
+ if (signal_is_trapped (0))
+ s = run_exit_trap ();
+
+#if defined (PROCESS_SUBSTITUTION)
+ unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+#if defined (HISTORY)
+ if (interactive_shell)
+ maybe_save_shell_history ();
+#endif /* HISTORY */
+
+#if defined (JOB_CONTROL)
+ /* If the user has run `shopt -s huponexit', hangup all jobs when we exit
+ an interactive login shell. ksh does this unconditionally. */
+ if (interactive_shell && login_shell && hup_on_exit)
+ hangup_all_jobs ();
+
+ /* If this shell is interactive, terminate all stopped jobs and
+ restore the original terminal process group. Don't do this if we're
+ in a subshell and calling exit_shell after, for example, a failed
+ word expansion. */
+ if (subshell_environment == 0)
+ end_job_control ();
+#endif /* JOB_CONTROL */
+
+ /* Always return the exit status of the last command to our parent. */
+ sh_exit (s);
+}
+
+/* A wrapper for exit that (optionally) can do other things, like malloc
+ statistics tracing. */
+void
+sh_exit (s)
+ int s;
+{
+#if defined (MALLOC_DEBUG) && defined (USING_BASH_MALLOC)
+ if (malloc_trace_at_exit)
+ trace_malloc_stats (get_name_for_error (), (char *)NULL);
+#endif
+
+ exit (s);
+}
+
+/* Source the bash startup files. If POSIXLY_CORRECT is non-zero, we obey
+ the Posix.2 startup file rules: $ENV is expanded, and if the file it
+ names exists, that file is sourced. The Posix.2 rules are in effect
+ for interactive shells only. (section 4.56.5.3) */
+
+/* Execute ~/.bashrc for most shells. Never execute it if
+ ACT_LIKE_SH is set, or if NO_RC is set.
+
+ If the executable file "/usr/gnu/src/bash/foo" contains:
+
+ #!/usr/gnu/bin/bash
+ echo hello
+
+ then:
+
+ COMMAND EXECUTE BASHRC
+ --------------------------------
+ bash -c foo NO
+ bash foo NO
+ foo NO
+ rsh machine ls YES (for rsh, which calls `bash -c')
+ rsh machine foo YES (for shell started by rsh) NO (for foo!)
+ echo ls | bash NO
+ login NO
+ bash YES
+*/
+
+static void
+execute_env_file (env_file)
+ char *env_file;
+{
+ char *fn;
+
+ if (env_file && *env_file)
+ {
+ fn = expand_string_unsplit_to_string (env_file, Q_DOUBLE_QUOTES);
+ if (fn && *fn)
+ maybe_execute_file (fn, 1);
+ FREE (fn);
+ }
+}
+
+static void
+run_startup_files ()
+{
+#if defined (JOB_CONTROL)
+ int old_job_control;
+#endif
+ int sourced_login, run_by_ssh;
+
+ /* get the rshd/sshd case out of the way first. */
+ if (interactive_shell == 0 && no_rc == 0 && login_shell == 0 &&
+ act_like_sh == 0 && command_execution_string)
+ {
+#ifdef SSH_SOURCE_BASHRC
+ run_by_ssh = (find_variable ("SSH_CLIENT") != (SHELL_VAR *)0) ||
+ (find_variable ("SSH2_CLIENT") != (SHELL_VAR *)0);
+#else
+ run_by_ssh = 0;
+#endif
+
+ /* If we were run by sshd or we think we were run by rshd, execute
+ ~/.bashrc if we are a top-level shell. */
+ if ((run_by_ssh || isnetconn (fileno (stdin))) && shell_level < 2)
+ {
+#ifdef SYS_BASHRC
+# if defined (__OPENNT)
+ maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);
+# else
+ maybe_execute_file (SYS_BASHRC, 1);
+# endif
+#endif
+ maybe_execute_file (bashrc_file, 1);
+ return;
+ }
+ }
+
+#if defined (JOB_CONTROL)
+ /* Startup files should be run without job control enabled. */
+ old_job_control = interactive_shell ? set_job_control (0) : 0;
+#endif
+
+ sourced_login = 0;
+
+ /* A shell begun with the --login (or -l) flag that is not in posix mode
+ runs the login shell startup files, no matter whether or not it is
+ interactive. If NON_INTERACTIVE_LOGIN_SHELLS is defined, run the
+ startup files if argv[0][0] == '-' as well. */
+#if defined (NON_INTERACTIVE_LOGIN_SHELLS)
+ if (login_shell && posixly_correct == 0)
+#else
+ if (login_shell < 0 && posixly_correct == 0)
+#endif
+ {
+ /* We don't execute .bashrc for login shells. */
+ no_rc++;
+
+ /* Execute /etc/profile and one of the personal login shell
+ initialization files. */
+ if (no_profile == 0)
+ {
+ maybe_execute_file (SYS_PROFILE, 1);
+
+ if (act_like_sh) /* sh */
+ maybe_execute_file ("~/.profile", 1);
+ else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
+ (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
+ maybe_execute_file ("~/.profile", 1);
+ }
+
+ sourced_login = 1;
+ }
+
+ /* A non-interactive shell not named `sh' and not in posix mode reads and
+ executes commands from $BASH_ENV. If `su' starts a shell with `-c cmd'
+ and `-su' as the name of the shell, we want to read the startup files.
+ No other non-interactive shells read any startup files. */
+ if (interactive_shell == 0 && !(su_shell && login_shell))
+ {
+ if (posixly_correct == 0 && act_like_sh == 0 && privileged_mode == 0 &&
+ sourced_env++ == 0)
+ execute_env_file (get_string_value ("BASH_ENV"));
+ return;
+ }
+
+ /* Interactive shell or `-su' shell. */
+ if (posixly_correct == 0) /* bash, sh */
+ {
+ if (login_shell && sourced_login++ == 0)
+ {
+ /* We don't execute .bashrc for login shells. */
+ no_rc++;
+
+ /* Execute /etc/profile and one of the personal login shell
+ initialization files. */
+ if (no_profile == 0)
+ {
+ maybe_execute_file (SYS_PROFILE, 1);
+
+ if (act_like_sh) /* sh */
+ maybe_execute_file ("~/.profile", 1);
+ else if ((maybe_execute_file ("~/.bash_profile", 1) == 0) &&
+ (maybe_execute_file ("~/.bash_login", 1) == 0)) /* bash */
+ maybe_execute_file ("~/.profile", 1);
+ }
+ }
+
+ /* bash */
+ if (act_like_sh == 0 && no_rc == 0)
+ {
+#ifdef SYS_BASHRC
+# if defined (__OPENNT)
+ maybe_execute_file (_prefixInstallPath(SYS_BASHRC, NULL, 0), 1);
+# else
+ maybe_execute_file (SYS_BASHRC, 1);
+# endif
+#endif
+ maybe_execute_file (bashrc_file, 1);
+ }
+ /* sh */
+ else if (act_like_sh && privileged_mode == 0 && sourced_env++ == 0)
+ execute_env_file (get_string_value ("ENV"));
+ }
+ else /* bash --posix, sh --posix */
+ {
+ /* bash and sh */
+ if (interactive_shell && privileged_mode == 0 && sourced_env++ == 0)
+ execute_env_file (get_string_value ("ENV"));
+ }
+
+#if defined (JOB_CONTROL)
+ set_job_control (old_job_control);
+#endif
+}
+
+#if defined (RESTRICTED_SHELL)
+/* Return 1 if the shell should be a restricted one based on NAME or the
+ value of `restricted'. Don't actually do anything, just return a
+ boolean value. */
+int
+shell_is_restricted (name)
+ char *name;
+{
+ char *temp;
+
+ if (restricted)
+ return 1;
+ temp = base_pathname (name);
+ if (*temp == '-')
+ temp++;
+ return (STREQ (temp, RESTRICTED_SHELL_NAME));
+}
+
+/* Perhaps make this shell a `restricted' one, based on NAME. If the
+ basename of NAME is "rbash", then this shell is restricted. The
+ name of the restricted shell is a configurable option, see config.h.
+ In a restricted shell, PATH, SHELL, ENV, and BASH_ENV are read-only
+ and non-unsettable.
+ Do this also if `restricted' is already set to 1; maybe the shell was
+ started with -r. */
+int
+maybe_make_restricted (name)
+ char *name;
+{
+ char *temp;
+
+ temp = base_pathname (name);
+ if (*temp == '-')
+ temp++;
+ if (restricted || (STREQ (temp, RESTRICTED_SHELL_NAME)))
+ {
+ set_var_read_only ("PATH");
+ set_var_read_only ("SHELL");
+ set_var_read_only ("ENV");
+ set_var_read_only ("BASH_ENV");
+ restricted = 1;
+ }
+ return (restricted);
+}
+#endif /* RESTRICTED_SHELL */
+
+/* Fetch the current set of uids and gids and return 1 if we're running
+ setuid or setgid. */
+static int
+uidget ()
+{
+ uid_t u;
+
+ u = getuid ();
+ if (current_user.uid != u)
+ {
+ FREE (current_user.user_name);
+ FREE (current_user.shell);
+ FREE (current_user.home_dir);
+ current_user.user_name = current_user.shell = current_user.home_dir = (char *)NULL;
+ }
+ current_user.uid = u;
+ current_user.gid = getgid ();
+ current_user.euid = geteuid ();
+ current_user.egid = getegid ();
+
+ /* See whether or not we are running setuid or setgid. */
+ return (current_user.uid != current_user.euid) ||
+ (current_user.gid != current_user.egid);
+}
+
+void
+disable_priv_mode ()
+{
+ setuid (current_user.uid);
+ setgid (current_user.gid);
+ current_user.euid = current_user.uid;
+ current_user.egid = current_user.gid;
+}
+
+static int
+run_wordexp (words)
+ char *words;
+{
+ int code, nw, nb;
+ WORD_LIST *wl, *tl, *result;
+
+ code = setjmp (top_level);
+
+ if (code != NOT_JUMPED)
+ {
+ switch (code)
+ {
+ /* Some kind of throw to top_level has occured. */
+ case FORCE_EOF:
+ return last_command_exit_value = 127;
+ case ERREXIT:
+ case EXITPROG:
+ return last_command_exit_value;
+ case DISCARD:
+ return last_command_exit_value = 1;
+ default:
+ command_error ("run_wordexp", CMDERR_BADJUMP, code, 0);
+ }
+ }
+
+ /* Run it through the parser to get a list of words and expand them */
+ if (words && *words)
+ {
+ with_input_from_string (words, "--wordexp");
+ if (parse_command () != 0)
+ return (126);
+ if (global_command == 0)
+ {
+ printf ("0\n0\n");
+ return (0);
+ }
+ if (global_command->type != cm_simple)
+ return (126);
+ wl = global_command->value.Simple->words;
+ if (protected_mode)
+ for (tl = wl; tl; tl = tl->next)
+ tl->word->flags |= W_NOCOMSUB;
+ result = wl ? expand_words_no_vars (wl) : (WORD_LIST *)0;
+ }
+ else
+ result = (WORD_LIST *)0;
+
+ last_command_exit_value = 0;
+
+ if (result == 0)
+ {
+ printf ("0\n0\n");
+ return (0);
+ }
+
+ /* Count up the number of words and bytes, and print them. Don't count
+ the trailing NUL byte. */
+ for (nw = nb = 0, wl = result; wl; wl = wl->next)
+ {
+ nw++;
+ nb += strlen (wl->word->word);
+ }
+ printf ("%u\n%u\n", nw, nb);
+ /* Print each word on a separate line. This will have to be changed when
+ the interface to glibc is completed. */
+ for (wl = result; wl; wl = wl->next)
+ printf ("%s\n", wl->word->word);
+
+ return (0);
+}
+
+#if defined (ONESHOT)
+/* Run one command, given as the argument to the -c option. Tell
+ parse_and_execute not to fork for a simple command. */
+static int
+run_one_command (command)
+ char *command;
+{
+ int code;
+
+ code = setjmp (top_level);
+
+ if (code != NOT_JUMPED)
+ {
+#if defined (PROCESS_SUBSTITUTION)
+ unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+ switch (code)
+ {
+ /* Some kind of throw to top_level has occured. */
+ case FORCE_EOF:
+ return last_command_exit_value = 127;
+ case ERREXIT:
+ case EXITPROG:
+ return last_command_exit_value;
+ case DISCARD:
+ return last_command_exit_value = 1;
+ default:
+ command_error ("run_one_command", CMDERR_BADJUMP, code, 0);
+ }
+ }
+ return (parse_and_execute (savestring (command), "-c", SEVAL_NOHIST));
+}
+#endif /* ONESHOT */
+
+static int
+bind_args (argv, arg_start, arg_end, start_index)
+ char **argv;
+ int arg_start, arg_end, start_index;
+{
+ register int i;
+ WORD_LIST *args;
+
+ for (i = arg_start, args = (WORD_LIST *)NULL; i < arg_end; i++)
+ args = make_word_list (make_word (argv[i]), args);
+ if (args)
+ {
+ args = REVERSE_LIST (args, WORD_LIST *);
+ if (start_index == 0) /* bind to $0...$n for sh -c command */
+ {
+ /* Posix.2 4.56.3 says that the first argument after sh -c command
+ becomes $0, and the rest of the arguments become $1...$n */
+ shell_name = savestring (args->word->word);
+ FREE (dollar_vars[0]);
+ dollar_vars[0] = savestring (args->word->word);
+ remember_args (args->next, 1);
+ push_args (args->next); /* BASH_ARGV and BASH_ARGC */
+ }
+ else /* bind to $1...$n for shell script */
+ {
+ remember_args (args, 1);
+ push_args (args); /* BASH_ARGV and BASH_ARGC */
+ }
+
+ dispose_words (args);
+ }
+
+ return (i);
+}
+
+void
+unbind_args ()
+{
+ remember_args ((WORD_LIST *)NULL, 1);
+ pop_args (); /* Reset BASH_ARGV and BASH_ARGC */
+}
+
+static void
+start_debugger ()
+{
+#if defined (DEBUGGER) && defined (DEBUGGER_START_FILE)
+ int old_errexit;
+
+ old_errexit = exit_immediately_on_error;
+ exit_immediately_on_error = 0;
+
+ maybe_execute_file (DEBUGGER_START_FILE, 1);
+ function_trace_mode = 1;
+
+ exit_immediately_on_error += old_errexit;
+#endif
+}
+
+static int
+open_shell_script (script_name)
+ char *script_name;
+{
+ int fd, e, fd_is_tty;
+ char *filename, *path_filename, *t;
+ char sample[80];
+ int sample_len;
+ struct stat sb;
+#if defined (ARRAY_VARS)
+ SHELL_VAR *funcname_v, *bash_source_v, *bash_lineno_v;
+ ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
+#endif
+
+ filename = savestring (script_name);
+
+ fd = open (filename, O_RDONLY);
+ if ((fd < 0) && (errno == ENOENT) && (absolute_program (filename) == 0))
+ {
+ e = errno;
+ /* If it's not in the current directory, try looking through PATH
+ for it. */
+ path_filename = find_path_file (script_name);
+ if (path_filename)
+ {
+ free (filename);
+ filename = path_filename;
+ fd = open (filename, O_RDONLY);
+ }
+ else
+ errno = e;
+ }
+
+ if (fd < 0)
+ {
+ e = errno;
+ file_error (filename);
+ exit ((e == ENOENT) ? EX_NOTFOUND : EX_NOINPUT);
+ }
+
+ free (dollar_vars[0]);
+ dollar_vars[0] = savestring (script_name);
+
+#if defined (ARRAY_VARS)
+ GET_ARRAY_FROM_VAR ("FUNCNAME", funcname_v, funcname_a);
+ GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
+ GET_ARRAY_FROM_VAR ("BASH_LINENO", bash_lineno_v, bash_lineno_a);
+
+ array_push (bash_source_a, filename);
+ if (bash_lineno_a)
+ {
+ t = itos (executing_line_number ());
+ array_push (bash_lineno_a, t);
+ free (t);
+ }
+ array_push (funcname_a, "main");
+#endif
+
+#ifdef HAVE_DEV_FD
+ fd_is_tty = isatty (fd);
+#else
+ fd_is_tty = 0;
+#endif
+
+ /* Only do this with non-tty file descriptors we can seek on. */
+ if (fd_is_tty == 0 && (lseek (fd, 0L, 1) != -1))
+ {
+ /* Check to see if the `file' in `bash file' is a binary file
+ according to the same tests done by execute_simple_command (),
+ and report an error and exit if it is. */
+ sample_len = read (fd, sample, sizeof (sample));
+ if (sample_len < 0)
+ {
+ e = errno;
+ if ((fstat (fd, &sb) == 0) && S_ISDIR (sb.st_mode))
+ internal_error (_("%s: is a directory"), filename);
+ else
+ {
+ errno = e;
+ file_error (filename);
+ }
+ exit (EX_NOEXEC);
+ }
+ else if (sample_len > 0 && (check_binary_file (sample, sample_len)))
+ {
+ internal_error ("%s: cannot execute binary file", filename);
+ exit (EX_BINARY_FILE);
+ }
+ /* Now rewind the file back to the beginning. */
+ lseek (fd, 0L, 0);
+ }
+
+ /* Open the script. But try to move the file descriptor to a randomly
+ large one, in the hopes that any descriptors used by the script will
+ not match with ours. */
+ fd = move_to_high_fd (fd, 0, -1);
+
+#if defined (__CYGWIN__) && defined (O_TEXT)
+ setmode (fd, O_TEXT);
+#endif
+
+#if defined (BUFFERED_INPUT)
+ default_buffered_input = fd;
+ SET_CLOSE_ON_EXEC (default_buffered_input);
+#else /* !BUFFERED_INPUT */
+ default_input = fdopen (fd, "r");
+
+ if (default_input == 0)
+ {
+ file_error (filename);
+ exit (EX_NOTFOUND);
+ }
+
+ SET_CLOSE_ON_EXEC (fd);
+ if (fileno (default_input) != fd)
+ SET_CLOSE_ON_EXEC (fileno (default_input));
+#endif /* !BUFFERED_INPUT */
+
+ /* Just about the only way for this code to be executed is if something
+ like `bash -i /dev/stdin' is executed. */
+ if (interactive_shell && fd_is_tty)
+ {
+ dup2 (fd, 0);
+ close (fd);
+ fd = 0;
+#if defined (BUFFERED_INPUT)
+ default_buffered_input = 0;
+#else
+ fclose (default_input);
+ default_input = stdin;
+#endif
+ }
+ else if (forced_interactive && fd_is_tty == 0)
+ /* But if a script is called with something like `bash -i scriptname',
+ we need to do a non-interactive setup here, since we didn't do it
+ before. */
+ init_noninteractive ();
+
+ free (filename);
+ return (fd);
+}
+
+/* Initialize the input routines for the parser. */
+static void
+set_bash_input ()
+{
+ /* Make sure the fd from which we are reading input is not in
+ no-delay mode. */
+#if defined (BUFFERED_INPUT)
+ if (interactive == 0)
+ sh_unset_nodelay_mode (default_buffered_input);
+ else
+#endif /* !BUFFERED_INPUT */
+ sh_unset_nodelay_mode (fileno (stdin));
+
+ /* with_input_from_stdin really means `with_input_from_readline' */
+ if (interactive && no_line_editing == 0)
+ with_input_from_stdin ();
+#if defined (BUFFERED_INPUT)
+ else if (interactive == 0)
+ with_input_from_buffered_stream (default_buffered_input, dollar_vars[0]);
+#endif /* BUFFERED_INPUT */
+ else
+ with_input_from_stream (default_input, dollar_vars[0]);
+}
+
+/* Close the current shell script input source and forget about it. This is
+ extern so execute_cmd.c:initialize_subshell() can call it. If CHECK_ZERO
+ is non-zero, we close default_buffered_input even if it's the standard
+ input (fd 0). */
+void
+unset_bash_input (check_zero)
+ int check_zero;
+{
+#if defined (BUFFERED_INPUT)
+ if ((check_zero && default_buffered_input >= 0) ||
+ (check_zero == 0 && default_buffered_input > 0))
+ {
+ close_buffered_fd (default_buffered_input);
+ default_buffered_input = bash_input.location.buffered_fd = -1;
+ }
+#else /* !BUFFERED_INPUT */
+ if (default_input)
+ {
+ fclose (default_input);
+ default_input = (FILE *)NULL;
+ }
+#endif /* !BUFFERED_INPUT */
+}
+
+
+#if !defined (PROGRAM)
+# define PROGRAM "bash"
+#endif
+
+static void
+set_shell_name (argv0)
+ char *argv0;
+{
+ /* Here's a hack. If the name of this shell is "sh", then don't do
+ any startup files; just try to be more like /bin/sh. */
+ shell_name = argv0 ? base_pathname (argv0) : PROGRAM;
+
+ if (*shell_name == '-')
+ {
+ shell_name++;
+ login_shell++;
+ }
+
+ if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
+ act_like_sh++;
+ if (shell_name[0] == 's' && shell_name[1] == 'u' && shell_name[2] == '\0')
+ su_shell++;
+
+ shell_name = argv0 ? argv0 : PROGRAM;
+ FREE (dollar_vars[0]);
+ dollar_vars[0] = savestring (shell_name);
+
+ /* A program may start an interactive shell with
+ "execl ("/bin/bash", "-", NULL)".
+ If so, default the name of this shell to our name. */
+ if (!shell_name || !*shell_name || (shell_name[0] == '-' && !shell_name[1]))
+ shell_name = PROGRAM;
+}
+
+static void
+init_interactive ()
+{
+ interactive_shell = startup_state = interactive = 1;
+ expand_aliases = 1;
+}
+
+static void
+init_noninteractive ()
+{
+#if defined (HISTORY)
+ bash_history_reinit (0);
+#endif /* HISTORY */
+ interactive_shell = startup_state = interactive = 0;
+ expand_aliases = posixly_correct; /* XXX - was 0 not posixly_correct */
+ no_line_editing = 1;
+#if defined (JOB_CONTROL)
+ set_job_control (0);
+#endif /* JOB_CONTROL */
+}
+
+void
+get_current_user_info ()
+{
+ struct passwd *entry;
+
+ /* Don't fetch this more than once. */
+ if (current_user.user_name == 0)
+ {
+ entry = getpwuid (current_user.uid);
+ if (entry)
+ {
+ current_user.user_name = savestring (entry->pw_name);
+ current_user.shell = (entry->pw_shell && entry->pw_shell[0])
+ ? savestring (entry->pw_shell)
+ : savestring ("/bin/sh");
+ current_user.home_dir = savestring (entry->pw_dir);
+ }
+ else
+ {
+ current_user.user_name = _("I have no name!");
+ current_user.user_name = savestring (current_user.user_name);
+ current_user.shell = savestring ("/bin/sh");
+ current_user.home_dir = savestring ("/");
+ }
+ endpwent ();
+ }
+}
+
+/* Do whatever is necessary to initialize the shell.
+ Put new initializations in here. */
+static void
+shell_initialize ()
+{
+ char hostname[256];
+
+ /* Line buffer output for stderr and stdout. */
+ if (shell_initialized == 0)
+ {
+ sh_setlinebuf (stderr);
+ sh_setlinebuf (stdout);
+ }
+
+ /* Sort the array of shell builtins so that the binary search in
+ find_shell_builtin () works correctly. */
+ initialize_shell_builtins ();
+
+ /* Initialize the trap signal handlers before installing our own
+ signal handlers. traps.c:restore_original_signals () is responsible
+ for restoring the original default signal handlers. That function
+ is called when we make a new child. */
+ initialize_traps ();
+ initialize_signals (0);
+
+ /* It's highly unlikely that this will change. */
+ if (current_host_name == 0)
+ {
+ /* Initialize current_host_name. */
+ if (gethostname (hostname, 255) < 0)
+ current_host_name = "??host??";
+ else
+ current_host_name = savestring (hostname);
+ }
+
+ /* Initialize the stuff in current_user that comes from the password
+ file. We don't need to do this right away if the shell is not
+ interactive. */
+ if (interactive_shell)
+ get_current_user_info ();
+
+ /* Initialize our interface to the tilde expander. */
+ tilde_initialize ();
+
+ /* Initialize internal and environment variables. Don't import shell
+ functions from the environment if we are running in privileged or
+ restricted mode or if the shell is running setuid. */
+#if defined (RESTRICTED_SHELL)
+ initialize_shell_variables (shell_environment, privileged_mode||restricted||running_setuid);
+#else
+ initialize_shell_variables (shell_environment, privileged_mode||running_setuid);
+#endif
+
+ /* Initialize the data structures for storing and running jobs. */
+ initialize_job_control (0);
+
+ /* Initialize input streams to null. */
+ initialize_bash_input ();
+
+ initialize_flags ();
+
+ /* Initialize the shell options. Don't import the shell options
+ from the environment variable $SHELLOPTS if we are running in
+ privileged or restricted mode or if the shell is running setuid. */
+#if defined (RESTRICTED_SHELL)
+ initialize_shell_options (privileged_mode||restricted||running_setuid);
+#else
+ initialize_shell_options (privileged_mode||running_setuid);
+#endif
+}
+
+/* Function called by main () when it appears that the shell has already
+ had some initialization performed. This is supposed to reset the world
+ back to a pristine state, as if we had been exec'ed. */
+static void
+shell_reinitialize ()
+{
+ /* The default shell prompts. */
+ primary_prompt = PPROMPT;
+ secondary_prompt = SPROMPT;
+
+ /* Things that get 1. */
+ current_command_number = 1;
+
+ /* We have decided that the ~/.bashrc file should not be executed
+ for the invocation of each shell script. If the variable $ENV
+ (or $BASH_ENV) is set, its value is used as the name of a file
+ to source. */
+ no_rc = no_profile = 1;
+
+ /* Things that get 0. */
+ login_shell = make_login_shell = interactive = executing = 0;
+ debugging = do_version = line_number = last_command_exit_value = 0;
+ forced_interactive = interactive_shell = subshell_environment = 0;
+ expand_aliases = 0;
+
+#if defined (HISTORY)
+ bash_history_reinit (0);
+#endif /* HISTORY */
+
+#if defined (RESTRICTED_SHELL)
+ restricted = 0;
+#endif /* RESTRICTED_SHELL */
+
+ /* Ensure that the default startup file is used. (Except that we don't
+ execute this file for reinitialized shells). */
+ bashrc_file = "~/.bashrc";
+
+ /* Delete all variables and functions. They will be reinitialized when
+ the environment is parsed. */
+ delete_all_contexts (shell_variables);
+ delete_all_variables (shell_functions);
+
+ shell_reinitialized = 1;
+}
+
+static void
+show_shell_usage (fp, extra)
+ FILE *fp;
+ int extra;
+{
+ int i;
+ char *set_opts, *s, *t;
+
+ if (extra)
+ fprintf (fp, "GNU bash, version %s-(%s)\n", shell_version_string (), MACHTYPE);
+ fprintf (fp, _("Usage:\t%s [GNU long option] [option] ...\n\t%s [GNU long option] [option] script-file ...\n"),
+ shell_name, shell_name);
+ fputs (_("GNU long options:\n"), fp);
+ for (i = 0; long_args[i].name; i++)
+ fprintf (fp, "\t--%s\n", long_args[i].name);
+
+ fputs (_("Shell options:\n"), fp);
+ fputs (_("\t-irsD or -c command or -O shopt_option\t\t(invocation only)\n"), fp);
+
+ for (i = 0, set_opts = 0; shell_builtins[i].name; i++)
+ if (STREQ (shell_builtins[i].name, "set"))
+ set_opts = savestring (shell_builtins[i].short_doc);
+ if (set_opts)
+ {
+ s = xstrchr (set_opts, '[');
+ if (s == 0)
+ s = set_opts;
+ while (*++s == '-')
+ ;
+ t = xstrchr (s, ']');
+ if (t)
+ *t = '\0';
+ fprintf (fp, _("\t-%s or -o option\n"), s);
+ free (set_opts);
+ }
+
+ if (extra)
+ {
+ fprintf (fp, _("Type `%s -c \"help set\"' for more information about shell options.\n"), shell_name);
+ fprintf (fp, _("Type `%s -c help' for more information about shell builtin commands.\n"), shell_name);
+ fprintf (fp, _("Use the `bashbug' command to report bugs.\n"));
+ }
+}
+
+static void
+add_shopt_to_alist (opt, on_or_off)
+ char *opt;
+ int on_or_off;
+{
+ if (shopt_ind >= shopt_len)
+ {
+ shopt_len += 8;
+ shopt_alist = (STRING_INT_ALIST *)xrealloc (shopt_alist, shopt_len * sizeof (shopt_alist[0]));
+ }
+ shopt_alist[shopt_ind].word = opt;
+ shopt_alist[shopt_ind].token = on_or_off;
+ shopt_ind++;
+}
+
+static void
+run_shopt_alist ()
+{
+ register int i;
+
+ for (i = 0; i < shopt_ind; i++)
+ if (shopt_setopt (shopt_alist[i].word, (shopt_alist[i].token == '-')) != EXECUTION_SUCCESS)
+ exit (EX_BADUSAGE);
+ free (shopt_alist);
+ shopt_alist = 0;
+ shopt_ind = shopt_len = 0;
+}
diff --git a/subst.c b/subst.c
index 73887ab8..d023294b 100644
--- a/subst.c
+++ b/subst.c
@@ -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;
diff --git a/subst.c.save1 b/subst.c.save1
new file mode 100644
index 00000000..83c9e213
--- /dev/null
+++ b/subst.c.save1
@@ -0,0 +1,8064 @@
+/* subst.c -- The part of the shell that does parameter, command, arithmetic,
+ and globbing substitutions. */
+
+/* ``Have a little faith, there's magic in the night. You ain't a
+ beauty, but, hey, you're alright.'' */
+
+/* Copyright (C) 1987-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"
+
+#include "bashtypes.h"
+#include <stdio.h>
+#include "chartypes.h"
+#include <pwd.h>
+#include <signal.h>
+#include <errno.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include "bashansi.h"
+#include "posixstat.h"
+#include "bashintl.h"
+
+#include "shell.h"
+#include "flags.h"
+#include "jobs.h"
+#include "execute_cmd.h"
+#include "filecntl.h"
+#include "trap.h"
+#include "pathexp.h"
+#include "mailcheck.h"
+
+#include "shmbutil.h"
+
+#include "builtins/getopt.h"
+#include "builtins/common.h"
+
+#include <tilde/tilde.h>
+#include <glob/strmatch.h>
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* The size that strings change by. */
+#define DEFAULT_INITIAL_ARRAY_SIZE 112
+#define DEFAULT_ARRAY_SIZE 128
+
+/* Variable types. */
+#define VT_VARIABLE 0
+#define VT_POSPARMS 1
+#define VT_ARRAYVAR 2
+#define VT_ARRAYMEMBER 3
+
+#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
+
+/* Flags for quoted_strchr */
+#define ST_BACKSL 0x01
+#define ST_CTLESC 0x02
+#define ST_SQUOTE 0x04 /* unused yet */
+#define ST_DQUOTE 0x08 /* unused yet */
+
+/* Flags for the string extraction functions. */
+#define EX_NOALLOC 0x01 /* just skip; don't return substring */
+#define EX_VARNAME 0x02 /* variable name; for string_extract () */
+#define EX_REQMATCH 0x04 /* closing/matching delimiter required */
+
+/* Flags for the `pflags' argument to param_expand() */
+#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
+
+/* These defs make it easier to use the editor. */
+#define LBRACE '{'
+#define RBRACE '}'
+#define LPAREN '('
+#define RPAREN ')'
+
+/* Evaluates to 1 if C is one of the shell's special parameters whose length
+ can be taken, but is also one of the special expansion characters. */
+#define VALID_SPECIAL_LENGTH_PARAM(c) \
+ ((c) == '-' || (c) == '?' || (c) == '#')
+
+/* Evaluates to 1 if C is one of the shell's special parameters for which an
+ indirect variable reference may be made. */
+#define VALID_INDIR_PARAM(c) \
+ ((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
+
+/* Evaluates to 1 if C is one of the OP characters that follows the parameter
+ in ${parameter[:]OPword}. */
+#define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
+
+/* Evaluates to 1 if this is one of the shell's special variables. */
+#define SPECIAL_VAR(name, wi) \
+ ((DIGIT (*name) && all_digits (name)) || \
+ (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
+ (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
+
+/* An expansion function that takes a string and a quoted flag and returns
+ a WORD_LIST *. Used as the type of the third argument to
+ expand_string_if_necessary(). */
+typedef WORD_LIST *EXPFUNC __P((char *, int));
+
+/* Process ID of the last command executed within command substitution. */
+pid_t last_command_subst_pid = NO_PID;
+pid_t current_command_subst_pid = NO_PID;
+
+/* Variables used to keep track of the characters in IFS. */
+SHELL_VAR *ifs_var;
+char *ifs_value;
+unsigned char ifs_cmap[UCHAR_MAX + 1];
+
+#if defined (HANDLE_MULTIBYTE)
+unsigned char ifs_firstc[MB_LEN_MAX];
+size_t ifs_firstc_len;
+#else
+unsigned char ifs_firstc;
+#endif
+
+/* Extern functions and variables from different files. */
+extern int last_command_exit_value, last_command_exit_signal;
+extern int subshell_environment;
+extern int subshell_level;
+extern int eof_encountered;
+extern int return_catch_flag, return_catch_value;
+extern pid_t dollar_dollar_pid;
+extern int posixly_correct;
+extern char *this_command_name;
+extern struct fd_bitmap *current_fds_to_close;
+extern int wordexp_only;
+extern int expanding_redir;
+extern int tempenv_assign_error;
+
+/* Non-zero means to allow unmatched globbed filenames to expand to
+ a null file. */
+int allow_null_glob_expansion;
+
+/* Non-zero means to throw an error when globbing fails to match anything. */
+int fail_glob_expansion;
+
+#if 0
+/* Variables to keep track of which words in an expanded word list (the
+ output of expand_word_list_internal) are the result of globbing
+ expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
+ (CURRENTLY UNUSED). */
+char *glob_argv_flags;
+static int glob_argv_flags_size;
+#endif
+
+static WORD_LIST expand_word_error, expand_word_fatal;
+static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
+static char expand_param_error, expand_param_fatal;
+static char extract_string_error, extract_string_fatal;
+
+/* Tell the expansion functions to not longjmp back to top_level on fatal
+ errors. Enabled when doing completion and prompt string expansion. */
+static int no_longjmp_on_fatal_error = 0;
+
+/* Set by expand_word_unsplit; used to inhibit splitting and re-joining
+ $* on $IFS, primarily when doing assignment statements. */
+static int expand_no_split_dollar_star = 0;
+
+/* Used to hold a list of variable assignments preceding a command. Global
+ so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
+ SIGCHLD trap. */
+WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
+
+/* A WORD_LIST of words to be expanded by expand_word_list_internal,
+ without any leading variable assignments. */
+static WORD_LIST *garglist = (WORD_LIST *)NULL;
+
+static char *quoted_substring __P((char *, int, int));
+static int quoted_strlen __P((char *));
+static char *quoted_strchr __P((char *, int, int));
+
+static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
+static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
+static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
+static WORD_LIST *expand_string_internal __P((char *, int));
+static WORD_LIST *expand_string_leave_quoted __P((char *, int));
+static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
+
+static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
+static char *dequote_escapes __P((char *));
+static char *make_quoted_char __P((int));
+static WORD_LIST *quote_list __P((WORD_LIST *));
+static WORD_LIST *dequote_list __P((WORD_LIST *));
+static char *remove_quoted_escapes __P((char *));
+static char *remove_quoted_nulls __P((char *));
+
+static int unquoted_substring __P((char *, char *));
+static int unquoted_member __P((int, char *));
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
+#endif
+static int do_assignment_internal __P((const WORD_DESC *, int));
+
+static char *string_extract_verbatim __P((char *, size_t, int *, char *));
+static char *string_extract __P((char *, int *, char *, int));
+static char *string_extract_double_quoted __P((char *, int *, int));
+static inline char *string_extract_single_quoted __P((char *, int *));
+static inline int skip_single_quoted __P((char *, size_t, int));
+static int skip_double_quoted __P((char *, size_t, int));
+static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
+static char *extract_dollar_brace_string __P((char *, int *, int, int));
+
+static char *pos_params __P((char *, int, int, int));
+
+static unsigned char *mb_getcharlens __P((char *, int));
+
+static char *remove_upattern __P((char *, char *, int));
+#if defined (HANDLE_MULTIBYTE)
+# if !defined (HAVE_WCSDUP)
+static wchar_t *wcsdup __P((wchar_t *));
+# endif
+static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
+#endif
+static char *remove_pattern __P((char *, char *, int));
+
+static int match_pattern_char __P((char *, char *));
+static int match_upattern __P((char *, char *, int, char **, char **));
+#if defined (HANDLE_MULTIBYTE)
+static int match_pattern_wchar __P((wchar_t *, wchar_t *));
+static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
+#endif
+static int match_pattern __P((char *, char *, int, char **, char **));
+static int getpatspec __P((int, char *));
+static char *getpattern __P((char *, int, int));
+static char *variable_remove_pattern __P((char *, char *, int, int));
+static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
+static char *parameter_list_remove_pattern __P((int, char *, int, int));
+#ifdef ARRAY_VARS
+static char *array_remove_pattern __P((ARRAY *, char *, int, char *, int));
+#endif
+static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
+
+static char *process_substitute __P((char *, int));
+
+static char *read_comsub __P((int, int));
+
+#ifdef ARRAY_VARS
+static arrayind_t array_length_reference __P((char *));
+#endif
+
+static int valid_brace_expansion_word __P((char *, int));
+static int chk_atstar __P((char *, int, int *, int *));
+
+static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
+static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
+static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
+static void parameter_brace_expand_error __P((char *, char *));
+
+static int valid_length_expression __P((char *));
+static intmax_t parameter_brace_expand_length __P((char *));
+
+static char *skiparith __P((char *, int));
+static int verify_substring_values __P((char *, char *, int, intmax_t *, intmax_t *));
+static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
+static char *mb_substring __P((char *, int, int));
+static char *parameter_brace_substring __P((char *, char *, char *, int));
+
+static char *pos_params_pat_subst __P((char *, char *, char *, int));
+
+static char *parameter_brace_patsub __P((char *, char *, char *, int));
+
+static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int *, int *));
+static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
+
+static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
+
+static WORD_LIST *word_list_split __P((WORD_LIST *));
+
+static void exp_jump_to_top_level __P((int));
+
+static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
+static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
+#ifdef BRACE_EXPANSION
+static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
+#endif
+static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
+static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
+
+/* **************************************************************** */
+/* */
+/* Utility Functions */
+/* */
+/* **************************************************************** */
+
+#ifdef INCLUDE_UNUSED
+static char *
+quoted_substring (string, start, end)
+ char *string;
+ int start, end;
+{
+ register int len, l;
+ register char *result, *s, *r;
+
+ len = end - start;
+
+ /* Move to string[start], skipping quoted characters. */
+ for (s = string, l = 0; *s && l < start; )
+ {
+ if (*s == CTLESC)
+ {
+ s++;
+ continue;
+ }
+ l++;
+ if (*s == 0)
+ break;
+ }
+
+ r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
+
+ /* Copy LEN characters, including quote characters. */
+ s = string + l;
+ for (l = 0; l < len; s++)
+ {
+ if (*s == CTLESC)
+ *r++ = *s++;
+ *r++ = *s;
+ l++;
+ if (*s == 0)
+ break;
+ }
+ *r = '\0';
+ return result;
+}
+#endif
+
+#ifdef INCLUDE_UNUSED
+/* Return the length of S, skipping over quoted characters */
+static int
+quoted_strlen (s)
+ char *s;
+{
+ register char *p;
+ int i;
+
+ i = 0;
+ for (p = s; *p; p++)
+ {
+ if (*p == CTLESC)
+ {
+ p++;
+ if (*p == 0)
+ return (i + 1);
+ }
+ i++;
+ }
+
+ return i;
+}
+#endif
+
+/* Find the first occurrence of character C in string S, obeying shell
+ quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
+ characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
+ escaped with CTLESC are skipped. */
+static char *
+quoted_strchr (s, c, flags)
+ char *s;
+ int c, flags;
+{
+ register char *p;
+
+ for (p = s; *p; p++)
+ {
+ if (((flags & ST_BACKSL) && *p == '\\')
+ || ((flags & ST_CTLESC) && *p == CTLESC))
+ {
+ p++;
+ if (*p == '\0')
+ return ((char *)NULL);
+ continue;
+ }
+ else if (*p == c)
+ return p;
+ }
+ return ((char *)NULL);
+}
+
+/* Return 1 if CHARACTER appears in an unquoted portion of
+ STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
+static int
+unquoted_member (character, string)
+ int character;
+ char *string;
+{
+ size_t slen;
+ int sindex, c;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ sindex = 0;
+ while (c = string[sindex])
+ {
+ if (c == character)
+ return (1);
+
+ switch (c)
+ {
+ default:
+ ADVANCE_CHAR (string, slen, sindex);
+ break;
+
+ case '\\':
+ sindex++;
+ if (string[sindex])
+ ADVANCE_CHAR (string, slen, sindex);
+ break;
+
+ case '\'':
+ sindex = skip_single_quoted (string, slen, ++sindex);
+ break;
+
+ case '"':
+ sindex = skip_double_quoted (string, slen, ++sindex);
+ break;
+ }
+ }
+ return (0);
+}
+
+/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
+static int
+unquoted_substring (substr, string)
+ char *substr, *string;
+{
+ size_t slen;
+ int sindex, c, sublen;
+ DECLARE_MBSTATE;
+
+ if (substr == 0 || *substr == '\0')
+ return (0);
+
+ slen = strlen (string);
+ sublen = strlen (substr);
+ for (sindex = 0; c = string[sindex]; )
+ {
+ if (STREQN (string + sindex, substr, sublen))
+ return (1);
+
+ switch (c)
+ {
+ case '\\':
+ sindex++;
+
+ if (string[sindex])
+ ADVANCE_CHAR (string, slen, sindex);
+ break;
+
+ case '\'':
+ sindex = skip_single_quoted (string, slen, ++sindex);
+ break;
+
+ case '"':
+ sindex = skip_double_quoted (string, slen, ++sindex);
+ break;
+
+ default:
+ ADVANCE_CHAR (string, slen, sindex);
+ break;
+ }
+ }
+ return (0);
+}
+
+/* Most of the substitutions must be done in parallel. In order
+ to avoid using tons of unclear goto's, I have some functions
+ for manipulating malloc'ed strings. They all take INDX, a
+ pointer to an integer which is the offset into the string
+ where manipulation is taking place. They also take SIZE, a
+ pointer to an integer which is the current length of the
+ character array for this string. */
+
+/* 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 freeing it.
+ Returns TARGET in case the location has changed. */
+INLINE char *
+sub_append_string (source, target, indx, size)
+ char *source, *target;
+ int *indx, *size;
+{
+ if (source)
+ {
+ int srclen, n;
+
+ srclen = STRLEN (source);
+ if (srclen >= (int)(*size - *indx))
+ {
+ n = srclen + *indx;
+ n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
+ target = (char *)xrealloc (target, (*size = n));
+ }
+
+ FASTCOPY (source, target + *indx, srclen);
+ *indx += srclen;
+ target[*indx] = '\0';
+
+ free (source);
+ }
+ return (target);
+}
+
+#if 0
+/* UNUSED */
+/* Append the textual representation of NUMBER to TARGET.
+ INDX and SIZE are as in SUB_APPEND_STRING. */
+char *
+sub_append_number (number, target, indx, size)
+ intmax_t number;
+ int *indx, *size;
+ char *target;
+{
+ char *temp;
+
+ temp = itos (number);
+ return (sub_append_string (temp, target, indx, size));
+}
+#endif
+
+/* Extract a substring from STRING, starting at SINDEX and ending with
+ one of the characters in CHARLIST. Don't make the ending character
+ part of the string. Leave SINDEX pointing at the ending character.
+ Understand about backslashes in the string. If (flags & EX_VARNAME)
+ is non-zero, and array variables have been compiled into the shell,
+ everything between a `[' and a corresponding `]' is skipped over.
+ If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
+ update SINDEX. If (flags & EX_REQMATCH) is non-zero, the string must
+ contain a closing character from CHARLIST. */
+static char *
+string_extract (string, sindex, charlist, flags)
+ char *string;
+ int *sindex;
+ char *charlist;
+ int flags;
+{
+ register int c, i;
+ int found;
+ size_t slen;
+ char *temp;
+ DECLARE_MBSTATE;
+
+ slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
+ i = *sindex;
+ found = 0;
+ while (c = string[i])
+ {
+ if (c == '\\')
+ {
+ if (string[i + 1])
+ i++;
+ else
+ break;
+ }
+#if defined (ARRAY_VARS)
+ else if ((flags & EX_VARNAME) && c == '[')
+ {
+ int ni;
+ /* If this is an array subscript, skip over it and continue. */
+ ni = skipsubscript (string, i);
+ if (string[ni] == ']')
+ i = ni;
+ }
+#endif
+ else if (MEMBER (c, charlist))
+ {
+ found = 1;
+ break;
+ }
+
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ /* If we had to have a matching delimiter and didn't find one, return an
+ error and let the caller deal with it. */
+ if ((flags & EX_REQMATCH) && found == 0)
+ {
+ *sindex = i;
+ return (&extract_string_error);
+ }
+
+ temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
+ *sindex = i;
+
+ return (temp);
+}
+
+/* Extract the contents of STRING as if it is enclosed in double quotes.
+ SINDEX, when passed in, is the offset of the character immediately
+ following the opening double quote; on exit, SINDEX is left pointing after
+ the closing double quote. If STRIPDQ is non-zero, unquoted double
+ quotes are stripped and the string is terminated by a null byte.
+ Backslashes between the embedded double quotes are processed. If STRIPDQ
+ is zero, an unquoted `"' terminates the string. */
+static char *
+string_extract_double_quoted (string, sindex, stripdq)
+ char *string;
+ int *sindex, stripdq;
+{
+ size_t slen;
+ char *send;
+ int j, i, t;
+ unsigned char c;
+ char *temp, *ret; /* The new string we return. */
+ int pass_next, backquote, si; /* State variables for the machine. */
+ int dquote;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string + *sindex) + *sindex;
+ send = string + slen;
+
+ pass_next = backquote = dquote = 0;
+ temp = (char *)xmalloc (1 + slen - *sindex);
+
+ j = 0;
+ i = *sindex;
+ while (c = string[i])
+ {
+ /* Process a character that was quoted by a backslash. */
+ if (pass_next)
+ {
+ /* Posix.2 sez:
+
+ ``The backslash shall retain its special meaning as an escape
+ character only when followed by one of the characters:
+ $ ` " \ <newline>''.
+
+ If STRIPDQ is zero, we handle the double quotes here and let
+ expand_word_internal handle the rest. If STRIPDQ is non-zero,
+ we have already been through one round of backslash stripping,
+ and want to strip these backslashes only if DQUOTE is non-zero,
+ indicating that we are inside an embedded double-quoted string. */
+
+ /* If we are in an embedded quoted string, then don't strip
+ backslashes before characters for which the backslash
+ retains its special meaning, but remove backslashes in
+ front of other characters. If we are not in an
+ embedded quoted string, don't strip backslashes at all.
+ This mess is necessary because the string was already
+ surrounded by double quotes (and sh has some really weird
+ quoting rules).
+ The returned string will be run through expansion as if
+ it were double-quoted. */
+ if ((stripdq == 0 && c != '"') ||
+ (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
+ temp[j++] = '\\';
+ pass_next = 0;
+
+add_one_character:
+ COPY_CHAR_I (temp, j, string, send, i);
+ continue;
+ }
+
+ /* A backslash protects the next character. The code just above
+ handles preserving the backslash in front of any character but
+ a double quote. */
+ if (c == '\\')
+ {
+ pass_next++;
+ i++;
+ continue;
+ }
+
+ /* Inside backquotes, ``the portion of the quoted string from the
+ initial backquote and the characters up to the next backquote
+ that is not preceded by a backslash, having escape characters
+ removed, defines that command''. */
+ if (backquote)
+ {
+ if (c == '`')
+ backquote = 0;
+ temp[j++] = c;
+ i++;
+ continue;
+ }
+
+ if (c == '`')
+ {
+ temp[j++] = c;
+ backquote++;
+ i++;
+ continue;
+ }
+
+ /* Pass everything between `$(' and the matching `)' or a quoted
+ ${ ... } pair through according to the Posix.2 specification. */
+ if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
+ {
+ int free_ret = 1;
+
+ si = i + 2;
+ if (string[i + 1] == LPAREN)
+ ret = extract_delimited_string (string, &si, "$(", "(", ")", 0); /*)*/
+ else
+ ret = extract_dollar_brace_string (string, &si, 1, 0);
+
+ temp[j++] = '$';
+ temp[j++] = string[i + 1];
+
+ /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
+ is set. */
+ if (ret == 0 && no_longjmp_on_fatal_error)
+ {
+ free_ret = 0;
+ ret = string + i + 2;
+ }
+
+ for (t = 0; ret[t]; t++, j++)
+ temp[j] = ret[t];
+ temp[j] = string[si];
+
+ if (string[si])
+ {
+ j++;
+ i = si + 1;
+ }
+ else
+ i = si;
+
+ if (free_ret)
+ free (ret);
+ continue;
+ }
+
+ /* Add any character but a double quote to the quoted string we're
+ accumulating. */
+ if (c != '"')
+ goto add_one_character;
+
+ /* c == '"' */
+ if (stripdq)
+ {
+ dquote ^= 1;
+ i++;
+ continue;
+ }
+
+ break;
+ }
+ temp[j] = '\0';
+
+ /* Point to after the closing quote. */
+ if (c)
+ i++;
+ *sindex = i;
+
+ return (temp);
+}
+
+/* This should really be another option to string_extract_double_quoted. */
+static int
+skip_double_quoted (string, slen, sind)
+ char *string;
+ size_t slen;
+ int sind;
+{
+ int c, i;
+ char *ret;
+ int pass_next, backquote, si;
+ DECLARE_MBSTATE;
+
+ pass_next = backquote = 0;
+ i = sind;
+ while (c = string[i])
+ {
+ if (pass_next)
+ {
+ pass_next = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '\\')
+ {
+ pass_next++;
+ i++;
+ continue;
+ }
+ else if (backquote)
+ {
+ if (c == '`')
+ backquote = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '`')
+ {
+ backquote++;
+ i++;
+ continue;
+ }
+ else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
+ {
+ si = i + 2;
+ if (string[i + 1] == LPAREN)
+ ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
+ else
+ ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
+
+ i = si + 1;
+ continue;
+ }
+ else if (c != '"')
+ {
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else
+ break;
+ }
+
+ if (c)
+ i++;
+
+ return (i);
+}
+
+/* Extract the contents of STRING as if it is enclosed in single quotes.
+ SINDEX, when passed in, is the offset of the character immediately
+ following the opening single quote; on exit, SINDEX is left pointing after
+ the closing single quote. */
+static inline char *
+string_extract_single_quoted (string, sindex)
+ char *string;
+ int *sindex;
+{
+ register int i;
+ size_t slen;
+ char *t;
+ DECLARE_MBSTATE;
+
+ /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
+ i = *sindex;
+ while (string[i] && string[i] != '\'')
+ ADVANCE_CHAR (string, slen, i);
+
+ t = substring (string, *sindex, i);
+
+ if (string[i])
+ i++;
+ *sindex = i;
+
+ return (t);
+}
+
+static inline int
+skip_single_quoted (string, slen, sind)
+ char *string;
+ size_t slen;
+ int sind;
+{
+ register int c;
+ DECLARE_MBSTATE;
+
+ c = sind;
+ while (string[c] && string[c] != '\'')
+ ADVANCE_CHAR (string, slen, c);
+
+ if (string[c])
+ c++;
+ return c;
+}
+
+/* Just like string_extract, but doesn't hack backslashes or any of
+ that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
+static char *
+string_extract_verbatim (string, slen, sindex, charlist)
+ char *string;
+ size_t slen;
+ int *sindex;
+ char *charlist;
+{
+ register int i = *sindex;
+#if defined (HANDLE_MULTIBYTE)
+ size_t clen;
+ wchar_t *wcharlist;
+#endif
+ int c;
+ char *temp;
+ DECLARE_MBSTATE;
+
+ if (charlist[0] == '\'' && charlist[1] == '\0')
+ {
+ temp = string_extract_single_quoted (string, sindex);
+ --*sindex; /* leave *sindex at separator character */
+ return temp;
+ }
+
+ i = *sindex;
+#if 0
+ /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
+ this only if MB_CUR_MAX > 1. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
+#endif
+#if defined (HANDLE_MULTIBYTE)
+ clen = strlen (charlist);
+ wcharlist = 0;
+#endif
+ while (c = string[i])
+ {
+#if defined (HANDLE_MULTIBYTE)
+ size_t mblength;
+#endif
+ if (c == CTLESC)
+ {
+ i += 2;
+ continue;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ mblength = MBLEN (string + i, slen - i);
+ if (mblength > 1)
+ {
+ wchar_t wc;
+ mblength = mbtowc (&wc, string + i, slen - i);
+ if (MB_INVALIDCH (mblength))
+ {
+ if (MEMBER (c, charlist))
+ break;
+ }
+ else
+ {
+ if (wcharlist == 0)
+ {
+ size_t len;
+ len = mbstowcs (wcharlist, charlist, 0);
+ if (len == -1)
+ len = 0;
+ wcharlist = xmalloc ((sizeof (wchar_t) * len) + 1);
+ mbstowcs (wcharlist, charlist, len);
+ }
+
+ if (wcschr (wcharlist, wc))
+ break;
+ }
+ }
+ else
+#endif
+ if (MEMBER (c, charlist))
+ break;
+
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ FREE (wcharlist);
+#endif
+
+ temp = substring (string, *sindex, i);
+ *sindex = i;
+
+ return (temp);
+}
+
+/* Extract the $( construct in STRING, and return a new string.
+ Start extracting at (SINDEX) as if we had just seen "$(".
+ Make (SINDEX) get the position of the matching ")". ) */
+char *
+extract_command_subst (string, sindex)
+ char *string;
+ int *sindex;
+{
+ return (extract_delimited_string (string, sindex, "$(", "(", ")", 0)); /*)*/
+}
+
+/* Extract the $[ construct in STRING, and return a new string. (])
+ Start extracting at (SINDEX) as if we had just seen "$[".
+ Make (SINDEX) get the position of the matching "]". */
+char *
+extract_arithmetic_subst (string, sindex)
+ char *string;
+ int *sindex;
+{
+ return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
+}
+
+#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 of the matching ")". */ /*))*/
+char *
+extract_process_subst (string, starter, sindex)
+ char *string;
+ char *starter;
+ int *sindex;
+{
+ return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
+}
+#endif /* PROCESS_SUBSTITUTION */
+
+#if defined (ARRAY_VARS)
+/* This can be fooled by unquoted right parens in the passed string. If
+ each caller verifies that the last character in STRING is a right paren,
+ we don't even need to call extract_delimited_string. */
+char *
+extract_array_assignment_list (string, sindex)
+ char *string;
+ int *sindex;
+{
+ int slen;
+ char *ret;
+
+ slen = strlen (string); /* ( */
+ if (string[slen - 1] == ')')
+ {
+ ret = substring (string, *sindex, slen - 1);
+ *sindex = slen - 1;
+ return ret;
+ }
+ return 0;
+}
+#endif
+
+/* Extract and create a new string from the contents of STRING, a
+ character string delimited with OPENER and CLOSER. SINDEX is
+ the address of an int describing the current offset in STRING;
+ it should point to just after the first OPENER found. On exit,
+ SINDEX gets the position of the last character of the matching CLOSER.
+ If OPENER is more than a single character, ALT_OPENER, if non-null,
+ contains a character string that can also match CLOSER and thus
+ needs to be skipped. */
+static char *
+extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
+ char *string;
+ int *sindex;
+ char *opener, *alt_opener, *closer;
+ int flags;
+{
+ int i, c, si;
+ size_t slen;
+ char *t, *result;
+ int pass_character, nesting_level;
+ int len_closer, len_opener, len_alt_opener;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string + *sindex) + *sindex;
+ len_opener = STRLEN (opener);
+ len_alt_opener = STRLEN (alt_opener);
+ len_closer = STRLEN (closer);
+
+ pass_character = 0;
+
+ nesting_level = 1;
+ i = *sindex;
+
+ while (nesting_level)
+ {
+ c = string[i];
+
+ if (c == 0)
+ break;
+
+ if (pass_character) /* previous char was backslash */
+ {
+ pass_character = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+
+ if (c == CTLESC || c == '\\')
+ {
+ pass_character++;
+ i++;
+ continue;
+ }
+
+ /* Process a nested OPENER. */
+ if (STREQN (string + i, opener, len_opener))
+ {
+ si = i + len_opener;
+ t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
+ i = si + 1;
+ continue;
+ }
+
+ /* Process a nested ALT_OPENER */
+ if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
+ {
+ si = i + len_alt_opener;
+ t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
+ i = si + 1;
+ continue;
+ }
+
+ /* If the current substring terminates the delimited string, decrement
+ the nesting level. */
+ if (STREQN (string + i, closer, len_closer))
+ {
+ i += len_closer - 1; /* move to last byte of the closer */
+ nesting_level--;
+ if (nesting_level == 0)
+ break;
+ }
+
+ /* Pass old-style command substitution through verbatim. */
+ if (c == '`')
+ {
+ si = i + 1;
+ t = string_extract (string, &si, "`", flags|EX_NOALLOC);
+ i = si + 1;
+ continue;
+ }
+
+ /* Pass single-quoted and double-quoted strings through verbatim. */
+ if (c == '\'' || c == '"')
+ {
+ si = i + 1;
+ i = (c == '\'') ? skip_single_quoted (string, slen, si)
+ : skip_double_quoted (string, slen, si);
+ continue;
+ }
+
+ /* move past this character, which was not special. */
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ if (c == 0 && nesting_level)
+ {
+ if (no_longjmp_on_fatal_error == 0)
+ {
+ report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
+ last_command_exit_value = EXECUTION_FAILURE;
+ exp_jump_to_top_level (DISCARD);
+ }
+ else
+ {
+ *sindex = i;
+ return (char *)NULL;
+ }
+ }
+
+ si = i - *sindex - len_closer + 1;
+ if (flags & EX_NOALLOC)
+ result = (char *)NULL;
+ else
+ {
+ result = (char *)xmalloc (1 + si);
+ strncpy (result, string + *sindex, si);
+ result[si] = '\0';
+ }
+ *sindex = i;
+
+ return (result);
+}
+
+/* Extract a parameter expansion expression within ${ and } from STRING.
+ Obey the Posix.2 rules for finding the ending `}': count braces while
+ skipping over enclosed quoted strings and command substitutions.
+ SINDEX is the address of an int describing the current offset in STRING;
+ it should point to just after the first `{' found. On exit, SINDEX
+ gets the position of the matching `}'. QUOTED is non-zero if this
+ occurs inside double quotes. */
+/* XXX -- this is very similar to extract_delimited_string -- XXX */
+static char *
+extract_dollar_brace_string (string, sindex, quoted, flags)
+ char *string;
+ int *sindex, quoted, flags;
+{
+ register int i, c;
+ size_t slen;
+ int pass_character, nesting_level, si;
+ char *result, *t;
+ DECLARE_MBSTATE;
+
+ pass_character = 0;
+ nesting_level = 1;
+ slen = strlen (string + *sindex) + *sindex;
+
+ i = *sindex;
+ while (c = string[i])
+ {
+ if (pass_character)
+ {
+ pass_character = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+
+ /* CTLESCs and backslashes quote the next character. */
+ if (c == CTLESC || c == '\\')
+ {
+ pass_character++;
+ i++;
+ continue;
+ }
+
+ if (string[i] == '$' && string[i+1] == LBRACE)
+ {
+ nesting_level++;
+ i += 2;
+ continue;
+ }
+
+ if (c == RBRACE)
+ {
+ nesting_level--;
+ if (nesting_level == 0)
+ break;
+ i++;
+ continue;
+ }
+
+ /* Pass the contents of old-style command substitutions through
+ verbatim. */
+ if (c == '`')
+ {
+ si = i + 1;
+ t = string_extract (string, &si, "`", flags|EX_NOALLOC);
+ i = si + 1;
+ continue;
+ }
+
+ /* Pass the contents of new-style command substitutions and
+ arithmetic substitutions through verbatim. */
+ if (string[i] == '$' && string[i+1] == LPAREN)
+ {
+ si = i + 2;
+ t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC); /*)*/
+ i = si + 1;
+ continue;
+ }
+
+ /* Pass the contents of single-quoted and double-quoted strings
+ through verbatim. */
+ if (c == '\'' || c == '"')
+ {
+ si = i + 1;
+ i = (c == '\'') ? skip_single_quoted (string, slen, si)
+ : skip_double_quoted (string, slen, si);
+ /* skip_XXX_quoted leaves index one past close quote */
+ continue;
+ }
+
+ /* move past this character, which was not special. */
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ if (c == 0 && nesting_level)
+ {
+ if (no_longjmp_on_fatal_error == 0)
+ { /* { */
+ report_error ("bad substitution: no closing `%s' in %s", "}", string);
+ last_command_exit_value = EXECUTION_FAILURE;
+ exp_jump_to_top_level (DISCARD);
+ }
+ else
+ {
+ *sindex = i;
+ return ((char *)NULL);
+ }
+ }
+
+ result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
+ *sindex = i;
+
+ return (result);
+}
+
+/* Remove backslashes which are quoting backquotes from STRING. Modifies
+ STRING, and returns a pointer to it. */
+char *
+de_backslash (string)
+ char *string;
+{
+ register size_t slen;
+ register int i, j, prev_i;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ i = j = 0;
+
+ /* Loop copying string[i] to string[j], i >= j. */
+ while (i < slen)
+ {
+ if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
+ string[i + 1] == '$'))
+ i++;
+ prev_i = i;
+ ADVANCE_CHAR (string, slen, i);
+ if (j < prev_i)
+ do string[j++] = string[prev_i++]; while (prev_i < i);
+ else
+ j = i;
+ }
+ string[j] = '\0';
+
+ return (string);
+}
+
+#if 0
+/*UNUSED*/
+/* Replace instances of \! in a string with !. */
+void
+unquote_bang (string)
+ char *string;
+{
+ register int i, j;
+ register char *temp;
+
+ temp = (char *)xmalloc (1 + strlen (string));
+
+ for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
+ {
+ if (string[i] == '\\' && string[i + 1] == '!')
+ {
+ temp[j] = '!';
+ i++;
+ }
+ }
+ strcpy (string, temp);
+ free (temp);
+}
+#endif
+
+#if defined (READLINE)
+/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
+ an unclosed quoted string), or if the character at EINDEX is quoted
+ by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
+ single and double-quoted string parsing functions should not return an
+ error if there are unclosed quotes or braces. The characters that this
+ recognizes need to be the same as the contents of
+ rl_completer_quote_characters. */
+
+#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
+
+int
+char_is_quoted (string, eindex)
+ char *string;
+ int eindex;
+{
+ int i, pass_next, c;
+ size_t slen;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ no_longjmp_on_fatal_error = 1;
+ i = pass_next = 0;
+ while (i <= eindex)
+ {
+ c = string[i];
+
+ if (pass_next)
+ {
+ pass_next = 0;
+ if (i >= eindex) /* XXX was if (i >= eindex - 1) */
+ CQ_RETURN(1);
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '\\')
+ {
+ pass_next = 1;
+ i++;
+ continue;
+ }
+ else if (c == '\'' || c == '"')
+ {
+ i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
+ : skip_double_quoted (string, slen, ++i);
+ if (i > eindex)
+ CQ_RETURN(1);
+ /* no increment, the skip_xxx functions go one past end */
+ }
+ else
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ CQ_RETURN(0);
+}
+
+int
+unclosed_pair (string, eindex, openstr)
+ char *string;
+ int eindex;
+ char *openstr;
+{
+ int i, pass_next, openc, olen;
+ size_t slen;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ olen = strlen (openstr);
+ i = pass_next = openc = 0;
+ while (i <= eindex)
+ {
+ if (pass_next)
+ {
+ pass_next = 0;
+ if (i >= eindex) /* XXX was if (i >= eindex - 1) */
+ return 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (string[i] == '\\')
+ {
+ pass_next = 1;
+ i++;
+ continue;
+ }
+ else if (STREQN (string + i, openstr, olen))
+ {
+ openc = 1 - openc;
+ i += olen;
+ }
+ else if (string[i] == '\'' || string[i] == '"')
+ {
+ i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
+ : skip_double_quoted (string, slen, i);
+ if (i > eindex)
+ return 0;
+ }
+ else
+ ADVANCE_CHAR (string, slen, i);
+ }
+ return (openc);
+}
+
+/* Skip characters in STRING until we find a character in DELIMS, and return
+ the index of that character. START is the index into string at which we
+ begin. This is similar in spirit to strpbrk, but it returns an index into
+ STRING and takes a starting index. This little piece of code knows quite
+ a lot of shell syntax. It's very similar to skip_double_quoted and other
+ functions of that ilk. */
+int
+skip_to_delim (string, start, delims)
+ char *string;
+ int start;
+ char *delims;
+{
+ int i, pass_next, backq, si, c;
+ size_t slen;
+ char *temp;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string + start) + start;
+ no_longjmp_on_fatal_error = 1;
+ i = start;
+ pass_next = backq = 0;
+ while (c = string[i])
+ {
+ if (pass_next)
+ {
+ pass_next = 0;
+ if (c == 0)
+ CQ_RETURN(i);
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '\\')
+ {
+ pass_next = 1;
+ i++;
+ continue;
+ }
+ else if (backq)
+ {
+ if (c == '`')
+ backq = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '`')
+ {
+ backq = 1;
+ i++;
+ continue;
+ }
+ else if (c == '\'' || c == '"')
+ {
+ i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
+ : skip_double_quoted (string, slen, ++i);
+ /* no increment, the skip functions increment past the closing quote. */
+ }
+ else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
+ {
+ si = i + 2;
+ if (string[si] == '\0')
+ CQ_RETURN(si);
+
+ if (string[i+1] == LPAREN)
+ temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
+ else
+ temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
+ i = si;
+ if (string[i] == '\0') /* don't increment i past EOS in loop */
+ break;
+ i++;
+ continue;
+ }
+ else if (member (c, delims))
+ break;
+ else
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ CQ_RETURN(i);
+}
+
+/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
+ individual words. If DELIMS is NULL, the current value of $IFS is used
+ to split the string, and the function follows the shell field splitting
+ rules. SENTINEL is an index to look for. NWP, if non-NULL,
+ gets the number of words in the returned list. CWP, if non-NULL, gets
+ the index of the word containing SENTINEL. Non-whitespace chars in
+ DELIMS delimit separate fields. */
+WORD_LIST *
+split_at_delims (string, slen, delims, sentinel, nwp, cwp)
+ char *string;
+ int slen;
+ char *delims;
+ int sentinel;
+ int *nwp, *cwp;
+{
+ int ts, te, i, nw, cw, ifs_split;
+ char *token, *d, *d2;
+ WORD_LIST *ret, *tl;
+
+ if (string == 0 || *string == '\0')
+ {
+ if (nwp)
+ *nwp = 0;
+ if (cwp)
+ *cwp = 0;
+ return ((WORD_LIST *)NULL);
+ }
+
+ d = (delims == 0) ? ifs_value : delims;
+ ifs_split = delims == 0;
+
+ /* Make d2 the non-whitespace characters in delims */
+ d2 = 0;
+ if (delims)
+ {
+ size_t slength;
+#if defined (HANDLE_MULTIBYTE)
+ size_t mblength = 1;
+#endif
+ DECLARE_MBSTATE;
+
+ slength = strlen (delims);
+ d2 = (char *)xmalloc (slength + 1);
+ i = ts = 0;
+ while (delims[i])
+ {
+#if defined (HANDLE_MULTIBYTE)
+ mbstate_t state_bak = state;
+ mblength = MBRLEN (delims + i, slength, &state);
+ if (MB_INVALIDCH (mblength))
+ state = state_bak;
+ else if (mblength > 1)
+ {
+ memcpy (d2 + ts, delims + i, mblength);
+ ts += mblength;
+ i += mblength;
+ slength -= mblength;
+ continue;
+ }
+#endif
+ if (whitespace (delims[i]) == 0)
+ d2[ts++] = delims[i];
+
+ i++;
+ slength--;
+ }
+ d2[ts] = '\0';
+ }
+
+ ret = (WORD_LIST *)NULL;
+
+ /* Remove sequences of whitspace characters at the start of the string, as
+ long as those characters are delimiters. */
+ for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
+ ;
+ if (string[i] == '\0')
+ return (ret);
+
+ ts = i;
+ nw = 0;
+ cw = -1;
+ while (1)
+ {
+ te = skip_to_delim (string, ts, d);
+
+ /* If we have a non-whitespace delimiter character, use it to make a
+ separate field. This is just about what $IFS splitting does and
+ is closer to the behavior of the shell parser. */
+ if (ts == te && d2 && member (string[ts], d2))
+ {
+ te = ts + 1;
+ /* If we're using IFS splitting, the non-whitespace delimiter char
+ and any additional IFS whitespace delimits a field. */
+ if (ifs_split)
+ while (member (string[te], d) && spctabnl (string[te]))
+ te++;
+ else
+ while (member (string[te], d2))
+ te++;
+ }
+
+ token = substring (string, ts, te);
+
+ ret = add_string_to_list (token, ret);
+ free (token);
+ nw++;
+
+ if (sentinel >= ts && sentinel <= te)
+ cw = nw;
+
+ /* If the cursor is at whitespace just before word start, set the
+ sentinel word to the current word. */
+ if (cwp && cw == -1 && sentinel == ts-1)
+ cw = nw;
+
+ /* If the cursor is at whitespace between two words, make a new, empty
+ word, add it before (well, after, since the list is in reverse order)
+ the word we just added, and set the current word to that one. */
+ if (cwp && cw == -1 && sentinel < ts)
+ {
+ tl = make_word_list (make_word (""), ret->next);
+ ret->next = tl;
+ cw = nw;
+ nw++;
+ }
+
+ if (string[te] == 0)
+ break;
+
+ i = te;
+ while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
+ i++;
+
+ if (string[i])
+ ts = i;
+ else
+ break;
+ }
+
+ /* Special case for SENTINEL at the end of STRING. If we haven't found
+ the word containing SENTINEL yet, and the index we're looking for is at
+ the end of STRING, add an additional null argument and set the current
+ word pointer to that. */
+ if (cwp && cw == -1 && sentinel >= slen)
+ {
+ if (whitespace (string[sentinel - 1]))
+ {
+ token = "";
+ ret = add_string_to_list (token, ret);
+ nw++;
+ }
+ cw = nw;
+ }
+
+ if (nwp)
+ *nwp = nw;
+ if (cwp)
+ *cwp = cw;
+
+ return (REVERSE_LIST (ret, WORD_LIST *));
+}
+#endif /* READLINE */
+
+#if 0
+/* UNUSED */
+/* Extract the name of the variable to bind to from the assignment string. */
+char *
+assignment_name (string)
+ char *string;
+{
+ int offset;
+ char *temp;
+
+ offset = assignment (string, 0);
+ if (offset == 0)
+ return (char *)NULL;
+ temp = substring (string, 0, offset);
+ return (temp);
+}
+#endif
+
+/* **************************************************************** */
+/* */
+/* Functions to convert strings to WORD_LISTs and vice versa */
+/* */
+/* **************************************************************** */
+
+/* Return a single string of all the words in LIST. SEP is the separator
+ to put between individual elements of LIST in the output string. */
+char *
+string_list_internal (list, sep)
+ WORD_LIST *list;
+ char *sep;
+{
+ register WORD_LIST *t;
+ char *result, *r;
+ int word_len, sep_len, result_size;
+
+ if (list == 0)
+ return ((char *)NULL);
+
+ /* Short-circuit quickly if we don't need to separate anything. */
+ if (list->next == 0)
+ return (savestring (list->word->word));
+
+ /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
+ sep_len = STRLEN (sep);
+ result_size = 0;
+
+ for (t = list; t; t = t->next)
+ {
+ if (t != list)
+ result_size += sep_len;
+ result_size += strlen (t->word->word);
+ }
+
+ r = result = (char *)xmalloc (result_size + 1);
+
+ for (t = list; t; t = t->next)
+ {
+ if (t != list && sep_len)
+ {
+ if (sep_len > 1)
+ {
+ FASTCOPY (sep, r, sep_len);
+ r += sep_len;
+ }
+ else
+ *r++ = sep[0];
+ }
+
+ word_len = strlen (t->word->word);
+ FASTCOPY (t->word->word, r, word_len);
+ r += word_len;
+ }
+
+ *r = '\0';
+ return (result);
+}
+
+/* Return a single string of all the words present in LIST, separating
+ each word with a space. */
+char *
+string_list (list)
+ WORD_LIST *list;
+{
+ return (string_list_internal (list, " "));
+}
+
+/* Return a single string of all the words present in LIST, obeying the
+ quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
+ expansion [of $*] appears within a double quoted string, it expands
+ to a single field with the value of each parameter separated by the
+ first character of the IFS variable, or by a <space> if IFS is unset." */
+char *
+string_list_dollar_star (list)
+ WORD_LIST *list;
+{
+#if defined (HANDLE_MULTIBYTE)
+ char sep[MB_CUR_MAX + 1];
+#else
+ char sep[2];
+#endif
+
+
+#if defined (HANDLE_MULTIBYTE)
+ if (ifs_firstc_len == 1)
+ {
+ sep[0] = ifs_firstc[0];
+ sep[1] = '\0';
+ }
+ else
+ {
+ memcpy (sep, ifs_firstc, ifs_firstc_len);
+ sep[ifs_firstc_len] = '\0';
+ }
+#else
+ sep[0] = ifs_firstc;
+ sep[1] = '\0';
+#endif
+
+ return (string_list_internal (list, sep));
+}
+
+/* Turn $@ into a string. If (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ is non-zero, the $@ appears within double quotes, and we should quote
+ the list before converting it into a string. If IFS is unset, and the
+ word is not quoted, we just need to quote CTLESC and CTLNUL characters
+ in the words in the list, because the default value of $IFS is
+ <space><tab><newline>, IFS characters in the words in the list should
+ also be split. If IFS is null, and the word is not quoted, we need
+ to quote the words in the list to preserve the positional parameters
+ exactly. */
+char *
+string_list_dollar_at (list, quoted)
+ WORD_LIST *list;
+ int quoted;
+{
+ char *ifs, *ret;
+#if defined (HANDLE_MULTIBYTE)
+ char sep[MB_CUR_MAX + 1];
+#else
+ char sep[2];
+#endif
+ WORD_LIST *tlist;
+
+ /* XXX this could just be ifs = ifs_value; */
+ ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
+
+#if defined (HANDLE_MULTIBYTE)
+ if (ifs && *ifs)
+ {
+ if (ifs_firstc_len == 1)
+ {
+ sep[0] = ifs_firstc[0];
+ sep[1] = '\0';
+ }
+ else
+ {
+ memcpy (sep, ifs_firstc, ifs_firstc_len);
+ sep[ifs_firstc_len] = '\0';
+ }
+ }
+ else
+ {
+ sep[0] = ' ';
+ sep[1] = '\0';
+ }
+#else
+ sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
+ sep[1] = '\0';
+#endif
+
+ tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
+ ? quote_list (list)
+ : list_quote_escapes (list);
+ return (string_list_internal (tlist, sep));
+}
+
+/* Return the list of words present in STRING. Separate the string into
+ words at any of the characters found in SEPARATORS. If QUOTED is
+ non-zero then word in the list will have its quoted flag set, otherwise
+ the quoted flag is left as make_word () deemed fit.
+
+ This obeys the P1003.2 word splitting semantics. If `separators' is
+ exactly <space><tab><newline>, then the splitting algorithm is that of
+ the Bourne shell, which treats any sequence of characters from `separators'
+ as a delimiter. If IFS is unset, which results in `separators' being set
+ to "", no splitting occurs. If separators has some other value, the
+ following rules are applied (`IFS white space' means zero or more
+ occurrences of <space>, <tab>, or <newline>, as long as those characters
+ are in `separators'):
+
+ 1) IFS white space is ignored at the start and the end of the
+ string.
+ 2) Each occurrence of a character in `separators' that is not
+ IFS white space, along with any adjacent occurrences of
+ IFS white space delimits a field.
+ 3) Any nonzero-length sequence of IFS white space delimits a field.
+ */
+
+/* BEWARE! list_string strips null arguments. Don't call it twice and
+ expect to have "" preserved! */
+
+/* This performs word splitting and quoted null character removal on
+ STRING. */
+#define issep(c) \
+ (((separators)[0]) ? ((separators)[1] ? isifs(c) \
+ : (c) == (separators)[0]) \
+ : 0)
+
+WORD_LIST *
+list_string (string, separators, quoted)
+ register char *string, *separators;
+ int quoted;
+{
+ WORD_LIST *result;
+ WORD_DESC *t;
+ char *current_word, *s;
+ int sindex, sh_style_split, whitesep;
+ size_t slen;
+
+ if (!string || !*string)
+ return ((WORD_LIST *)NULL);
+
+ sh_style_split = separators && separators[0] == ' ' &&
+ separators[1] == '\t' &&
+ separators[2] == '\n' &&
+ separators[3] == '\0';
+
+ slen = 0;
+ /* Remove sequences of whitespace at the beginning of STRING, as
+ long as those characters appear in IFS. Do not do this if
+ STRING is quoted or if there are no separator characters. */
+ if (!quoted || !separators || !*separators)
+ {
+ for (s = string; *s && spctabnl (*s) && issep (*s); s++);
+
+ if (!*s)
+ return ((WORD_LIST *)NULL);
+
+ string = s;
+ }
+
+ /* OK, now STRING points to a word that does not begin with white space.
+ The splitting algorithm is:
+ extract a word, stopping at a separator
+ skip sequences of spc, tab, or nl as long as they are separators
+ This obeys the field splitting rules in Posix.2. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
+ for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
+ {
+ /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
+ unless multibyte chars are possible. */
+ current_word = string_extract_verbatim (string, slen, &sindex, separators);
+ if (current_word == 0)
+ break;
+
+ /* If we have a quoted empty string, add a quoted null argument. We
+ want to preserve the quoted null character iff this is a quoted
+ empty string; otherwise the quoted null characters are removed
+ below. */
+ if (QUOTED_NULL (current_word))
+ {
+ t = alloc_word_desc ();
+ t->word = make_quoted_char ('\0');
+ t->flags |= W_QUOTED|W_HASQUOTEDNULL;
+ result = make_word_list (t, result);
+ }
+ else if (current_word[0] != '\0')
+ {
+ /* If we have something, then add it regardless. However,
+ perform quoted null character removal on the current word. */
+ remove_quoted_nulls (current_word);
+ result = add_string_to_list (current_word, result);
+ result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
+ if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ result->word->flags |= W_QUOTED;
+ }
+
+ /* If we're not doing sequences of separators in the traditional
+ Bourne shell style, then add a quoted null argument. */
+ else if (!sh_style_split && !spctabnl (string[sindex]))
+ {
+ t = alloc_word_desc ();
+ t->word = make_quoted_char ('\0');
+ t->flags |= W_QUOTED|W_HASQUOTEDNULL;
+ result = make_word_list (t, result);
+ }
+
+ free (current_word);
+
+ /* Note whether or not the separator is IFS whitespace, used later. */
+ whitesep = string[sindex] && spctabnl (string[sindex]);
+
+ /* Move past the current separator character. */
+ if (string[sindex])
+ {
+ DECLARE_MBSTATE;
+ ADVANCE_CHAR (string, slen, sindex);
+ }
+
+ /* Now skip sequences of space, tab, or newline characters if they are
+ in the list of separators. */
+ while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
+ sindex++;
+
+ /* If the first separator was IFS whitespace and the current character
+ is a non-whitespace IFS character, it should be part of the current
+ field delimiter, not a separate delimiter that would result in an
+ empty field. Look at POSIX.2, 3.6.5, (3)(b). */
+ if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
+ {
+ sindex++;
+ /* An IFS character that is not IFS white space, along with any
+ adjacent IFS white space, shall delimit a field. (SUSv3) */
+ while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
+ sindex++;
+ }
+ }
+ return (REVERSE_LIST (result, WORD_LIST *));
+}
+
+/* Parse a single word from STRING, using SEPARATORS to separate fields.
+ ENDPTR is set to the first character after the word. This is used by
+ the `read' builtin. This is never called with SEPARATORS != $IFS;
+ it should be simplified.
+
+ XXX - this function is very similar to list_string; they should be
+ combined - XXX */
+char *
+get_word_from_string (stringp, separators, endptr)
+ char **stringp, *separators, **endptr;
+{
+ register char *s;
+ char *current_word;
+ int sindex, sh_style_split, whitesep;
+ size_t slen;
+
+ if (!stringp || !*stringp || !**stringp)
+ return ((char *)NULL);
+
+ s = *stringp;
+
+ sh_style_split = separators && separators[0] == ' ' &&
+ separators[1] == '\t' &&
+ separators[2] == '\n' &&
+ separators[3] == '\0';
+
+ slen = 0;
+
+ /* Remove sequences of whitespace at the beginning of STRING, as
+ long as those characters appear in IFS. */
+ if (sh_style_split || !separators || !*separators)
+ {
+ for (; *s && spctabnl (*s) && isifs (*s); s++);
+
+ /* If the string is nothing but whitespace, update it and return. */
+ if (!*s)
+ {
+ *stringp = s;
+ if (endptr)
+ *endptr = s;
+ return ((char *)NULL);
+ }
+ }
+
+ /* OK, S points to a word that does not begin with white space.
+ Now extract a word, stopping at a separator, save a pointer to
+ the first character after the word, then skip sequences of spc,
+ tab, or nl as long as they are separators.
+
+ This obeys the field splitting rules in Posix.2. */
+ sindex = 0;
+ /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
+ unless multibyte chars are possible. */
+ slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
+ current_word = string_extract_verbatim (s, slen, &sindex, separators);
+
+ /* Set ENDPTR to the first character after the end of the word. */
+ if (endptr)
+ *endptr = s + sindex;
+
+ /* Note whether or not the separator is IFS whitespace, used later. */
+ whitesep = s[sindex] && spctabnl (s[sindex]);
+
+ /* Move past the current separator character. */
+ if (s[sindex])
+ {
+ DECLARE_MBSTATE;
+ ADVANCE_CHAR (s, slen, sindex);
+ }
+
+ /* Now skip sequences of space, tab, or newline characters if they are
+ in the list of separators. */
+ while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
+ sindex++;
+
+ /* If the first separator was IFS whitespace and the current character is
+ a non-whitespace IFS character, it should be part of the current field
+ delimiter, not a separate delimiter that would result in an empty field.
+ Look at POSIX.2, 3.6.5, (3)(b). */
+ if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
+ {
+ sindex++;
+ /* An IFS character that is not IFS white space, along with any adjacent
+ IFS white space, shall delimit a field. */
+ while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
+ sindex++;
+ }
+
+ /* Update STRING to point to the next field. */
+ *stringp = s + sindex;
+ return (current_word);
+}
+
+/* Remove IFS white space at the end of STRING. Start at the end
+ of the string and walk backwards until the beginning of the string
+ or we find a character that's not IFS white space and not CTLESC.
+ Only let CTLESC escape a white space character if SAW_ESCAPE is
+ non-zero. */
+char *
+strip_trailing_ifs_whitespace (string, separators, saw_escape)
+ char *string, *separators;
+ int saw_escape;
+{
+ char *s;
+
+ s = string + STRLEN (string) - 1;
+ while (s > string && ((spctabnl (*s) && isifs (*s)) ||
+ (saw_escape && *s == CTLESC && spctabnl (s[1]))))
+ s--;
+ *++s = '\0';
+ return string;
+}
+
+#if 0
+/* UNUSED */
+/* Split STRING into words at whitespace. Obeys shell-style quoting with
+ backslashes, single and double quotes. */
+WORD_LIST *
+list_string_with_quotes (string)
+ char *string;
+{
+ WORD_LIST *list;
+ char *token, *s;
+ size_t s_len;
+ int c, i, tokstart, len;
+
+ for (s = string; s && *s && spctabnl (*s); s++)
+ ;
+ if (s == 0 || *s == 0)
+ return ((WORD_LIST *)NULL);
+
+ s_len = strlen (s);
+ tokstart = i = 0;
+ list = (WORD_LIST *)NULL;
+ while (1)
+ {
+ c = s[i];
+ if (c == '\\')
+ {
+ i++;
+ if (s[i])
+ i++;
+ }
+ else if (c == '\'')
+ i = skip_single_quoted (s, s_len, ++i);
+ else if (c == '"')
+ i = skip_double_quoted (s, s_len, ++i);
+ else if (c == 0 || spctabnl (c))
+ {
+ /* We have found the end of a token. Make a word out of it and
+ add it to the word list. */
+ token = substring (s, tokstart, i);
+ list = add_string_to_list (token, list);
+ free (token);
+ while (spctabnl (s[i]))
+ i++;
+ if (s[i])
+ tokstart = i;
+ else
+ break;
+ }
+ else
+ i++; /* normal character */
+ }
+ return (REVERSE_LIST (list, WORD_LIST *));
+}
+#endif
+
+/********************************************************/
+/* */
+/* Functions to perform assignment statements */
+/* */
+/********************************************************/
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *
+do_compound_assignment (name, value, flags)
+ char *name, *value;
+ int flags;
+{
+ SHELL_VAR *v;
+ int off, mklocal;
+
+ mklocal = flags & ASS_MKLOCAL;
+
+ if (mklocal && variable_context)
+ {
+ 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);
+ }
+ else
+ v = assign_array_from_string (name, value, flags);
+
+ return (v);
+}
+#endif
+
+/* 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 parameter expansion, command substitution, and arithmetic
+ expansion on the right-hand side. Perform tilde expansion in any
+ case. Do not perform word splitting on the result of expansion. */
+static int
+do_assignment_internal (word, expand)
+ const WORD_DESC *word;
+ int expand;
+{
+ int offset, tlen, appendop, assign_list, aflags;
+ char *name, *value, *ovalue, *nvalue;
+ SHELL_VAR *entry;
+#if defined (ARRAY_VARS)
+ char *t;
+ int ni;
+#endif
+ const char *string;
+
+ if (word == 0 || word->word == 0)
+ return 0;
+
+ appendop = assign_list = aflags = 0;
+ string = word->word;
+ offset = assignment (string, 0);
+ name = savestring (string);
+ value = (char *)NULL;
+
+ if (name[offset] == '=')
+ {
+ char *temp;
+
+ if (name[offset - 1] == '+')
+ {
+ appendop = 1;
+ name[offset - 1] = '\0';
+ }
+
+ name[offset] = 0; /* might need this set later */
+ temp = name + offset + 1;
+ tlen = STRLEN (temp);
+
+#if defined (ARRAY_VARS)
+# if 0
+ if (expand && temp[0] == LPAREN && temp[tlen-1] == RPAREN)
+#else
+ if (expand && (word->flags & W_COMPASSIGN))
+#endif
+ {
+ assign_list = ni = 1;
+ value = extract_array_assignment_list (temp, &ni);
+ }
+ else
+#endif
+
+ if (expand && temp[0])
+ value = expand_string_if_necessary (temp, 0, expand_string_assignment);
+ else
+ value = savestring (temp);
+ }
+
+ if (value == 0)
+ {
+ value = (char *)xmalloc (1);
+ value[0] = '\0';
+ }
+
+ if (echo_command_at_execute)
+ {
+ if (appendop)
+ name[offset - 1] = '+';
+ xtrace_print_assignment (name, value, assign_list, 1);
+ if (appendop)
+ name[offset - 1] = '\0';
+ }
+
+#define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
+
+ if (appendop)
+ aflags |= ASS_APPEND;
+
+#if defined (ARRAY_VARS)
+ if (t = xstrchr (name, '[')) /*]*/
+ {
+ if (assign_list)
+ {
+ report_error (_("%s: cannot assign list to array member"), name);
+ ASSIGN_RETURN (0);
+ }
+ entry = assign_array_element (name, value, aflags);
+ if (entry == 0)
+ ASSIGN_RETURN (0);
+ }
+ else if (assign_list)
+ {
+ if (word->flags & W_ASSIGNARG)
+ aflags |= ASS_MKLOCAL;
+ entry = do_compound_assignment (name, value, aflags);
+ }
+ else
+#endif /* ARRAY_VARS */
+ entry = bind_variable (name, value, aflags);
+
+ stupidly_hack_special_variables (name);
+
+ if (entry)
+ VUNSETATTR (entry, att_invisible);
+
+ /* Return 1 if the assignment seems to have been performed correctly. */
+ ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
+}
+
+/* Perform the assignment statement in STRING, and expand the
+ right side by doing tilde, command and parameter expansion. */
+int
+do_assignment (string)
+ char *string;
+{
+ WORD_DESC td;
+
+ td.flags = W_ASSIGNMENT;
+ td.word = string;
+
+ return do_assignment_internal (&td, 1);
+}
+
+int
+do_word_assignment (word)
+ WORD_DESC *word;
+{
+ return do_assignment_internal (word, 1);
+}
+
+/* Given STRING, an assignment string, get the value of the right side
+ of the `=', and bind it to the left side. Do not perform any word
+ expansions on the right hand side. */
+int
+do_assignment_no_expand (string)
+ char *string;
+{
+ WORD_DESC td;
+
+ td.flags = W_ASSIGNMENT;
+ td.word = string;
+
+ return (do_assignment_internal (&td, 0));
+}
+
+/***************************************************
+ * *
+ * Functions to manage the positional parameters *
+ * *
+ ***************************************************/
+
+/* Return the word list that corresponds to `$*'. */
+WORD_LIST *
+list_rest_of_args ()
+{
+ register WORD_LIST *list, *args;
+ int i;
+
+ /* Break out of the loop as soon as one of the dollar variables is null. */
+ for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
+ list = make_word_list (make_bare_word (dollar_vars[i]), list);
+
+ for (args = rest_of_args; args; args = args->next)
+ list = make_word_list (make_bare_word (args->word->word), list);
+
+ return (REVERSE_LIST (list, WORD_LIST *));
+}
+
+int
+number_of_args ()
+{
+ register WORD_LIST *list;
+ int n;
+
+ for (n = 0; n < 9 && dollar_vars[n+1]; n++)
+ ;
+ for (list = rest_of_args; list; list = list->next)
+ n++;
+ return n;
+}
+
+/* Return the value of a positional parameter. This handles values > 10. */
+char *
+get_dollar_var_value (ind)
+ intmax_t ind;
+{
+ char *temp;
+ WORD_LIST *p;
+
+ if (ind < 10)
+ temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
+ else /* We want something like ${11} */
+ {
+ ind -= 10;
+ for (p = rest_of_args; p && ind--; p = p->next)
+ ;
+ temp = p ? savestring (p->word->word) : (char *)NULL;
+ }
+ return (temp);
+}
+
+/* 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. */
+char *
+string_rest_of_args (dollar_star)
+ int dollar_star;
+{
+ register WORD_LIST *list;
+ char *string;
+
+ list = list_rest_of_args ();
+ string = dollar_star ? string_list_dollar_star (list) : string_list (list);
+ dispose_words (list);
+ return (string);
+}
+
+/* Return a string containing the positional parameters from START to
+ END, inclusive. If STRING[0] == '*', we obey the rules for $*,
+ which only makes a difference if QUOTED is non-zero. If QUOTED includes
+ Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
+ no quoting chars are added. */
+static char *
+pos_params (string, start, end, quoted)
+ char *string;
+ int start, end, quoted;
+{
+ WORD_LIST *save, *params, *h, *t;
+ char *ret;
+ int i;
+
+ /* see if we can short-circuit. if start == end, we want 0 parameters. */
+ if (start == end)
+ return ((char *)NULL);
+
+ save = params = list_rest_of_args ();
+ if (save == 0)
+ return ((char *)NULL);
+
+ for (i = 1; params && i < start; i++)
+ params = params->next;
+ if (params == 0)
+ return ((char *)NULL);
+ for (h = t = params; params && i < end; i++)
+ {
+ t = params;
+ params = params->next;
+ }
+
+ t->next = (WORD_LIST *)NULL;
+ if (string[0] == '*')
+ {
+ if (quoted & Q_DOUBLE_QUOTES)
+ ret = string_list_dollar_star (quote_list (h));
+ else if (quoted & Q_HERE_DOCUMENT)
+ ret = string_list (quote_list (h));
+ else
+ ret = string_list (h);
+ }
+ else
+ ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
+ if (t != params)
+ t->next = params;
+
+ dispose_words (save);
+ return (ret);
+}
+
+/******************************************************************/
+/* */
+/* Functions to expand strings to strings or WORD_LISTs */
+/* */
+/******************************************************************/
+
+#if defined (PROCESS_SUBSTITUTION)
+#define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
+#else
+#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
+#endif
+
+/* If there are any characters in STRING that require full expansion,
+ then call FUNC to expand STRING; otherwise just perform quote
+ removal if necessary. This returns a new string. */
+static char *
+expand_string_if_necessary (string, quoted, func)
+ char *string;
+ int quoted;
+ EXPFUNC *func;
+{
+ WORD_LIST *list;
+ size_t slen;
+ int i, saw_quote;
+ char *ret;
+ DECLARE_MBSTATE;
+
+ /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
+ i = saw_quote = 0;
+ while (string[i])
+ {
+ if (EXP_CHAR (string[i]))
+ break;
+ else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
+ saw_quote = 1;
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ if (string[i])
+ {
+ list = (*func) (string, quoted);
+ if (list)
+ {
+ ret = string_list (list);
+ dispose_words (list);
+ }
+ else
+ ret = (char *)NULL;
+ }
+ else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ ret = string_quote_removal (string, quoted);
+ else
+ ret = savestring (string);
+
+ return ret;
+}
+
+static inline char *
+expand_string_to_string_internal (string, quoted, func)
+ char *string;
+ int quoted;
+ EXPFUNC *func;
+{
+ WORD_LIST *list;
+ char *ret;
+
+ if (string == 0 || *string == '\0')
+ return ((char *)NULL);
+
+ list = (*func) (string, quoted);
+ if (list)
+ {
+ ret = string_list (list);
+ dispose_words (list);
+ }
+ else
+ ret = (char *)NULL;
+
+ return (ret);
+}
+
+char *
+expand_string_to_string (string, quoted)
+ char *string;
+ int quoted;
+{
+ return (expand_string_to_string_internal (string, quoted, expand_string));
+}
+
+char *
+expand_string_unsplit_to_string (string, quoted)
+ char *string;
+ int quoted;
+{
+ return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
+}
+
+char *
+expand_assignment_string_to_string (string, quoted)
+ char *string;
+ int 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 *
+remove_backslashes (string)
+ char *string;
+{
+ char *r, *ret, *s;
+
+ r = ret = (char *)xmalloc (strlen (string) + 1);
+ for (s = string; s && *s; )
+ {
+ if (*s == '\\')
+ s++;
+ if (*s == 0)
+ break;
+ *r++ = *s++;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* This needs better error handling. */
+/* Expand W for use as an argument to a unary or binary operator in a
+ [[...]] expression. If SPECIAL is nonzero, this is the rhs argument
+ to the != or == operator, and should be treated as a pattern. In
+ this case, we quote the string specially for the globbing code. The
+ caller is responsible for removing the backslashes if the unquoted
+ words is needed later. */
+char *
+cond_expand_word (w, special)
+ WORD_DESC *w;
+ int special;
+{
+ char *r, *p;
+ WORD_LIST *l;
+
+ if (w->word == 0 || w->word[0] == '\0')
+ return ((char *)NULL);
+
+ l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
+ if (l)
+ {
+ if (special == 0)
+ {
+ dequote_list (l);
+ r = string_list (l);
+ }
+ else
+ {
+ p = string_list (l);
+ r = quote_string_for_globbing (p, QGLOB_CVTNULL);
+ free (p);
+ }
+ dispose_words (l);
+ }
+ else
+ r = (char *)NULL;
+
+ return r;
+}
+#endif
+
+/* Call expand_word_internal to expand W and handle error returns.
+ A convenience function for functions that don't want to handle
+ any errors or free any memory before aborting. */
+static WORD_LIST *
+call_expand_word_internal (w, q, i, c, e)
+ WORD_DESC *w;
+ int q, i, *c, *e;
+{
+ WORD_LIST *result;
+
+ result = expand_word_internal (w, q, i, c, e);
+ if (result == &expand_word_error || result == &expand_word_fatal)
+ {
+ /* By convention, each time this error is returned, w->word has
+ already been freed (it sometimes may not be in the fatal case,
+ but that doesn't result in a memory leak because we're going
+ to exit in most cases). */
+ w->word = (char *)NULL;
+ last_command_exit_value = EXECUTION_FAILURE;
+ exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
+ /* NOTREACHED */
+ }
+ else
+ return (result);
+}
+
+/* Perform parameter expansion, command substitution, and arithmetic
+ expansion on STRING, as if it were a word. Leave the result quoted. */
+static WORD_LIST *
+expand_string_internal (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_DESC td;
+ WORD_LIST *tresult;
+
+ if (string == 0 || *string == 0)
+ return ((WORD_LIST *)NULL);
+
+ td.flags = 0;
+ td.word = savestring (string);
+
+ tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
+
+ FREE (td.word);
+ return (tresult);
+}
+
+/* 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 in here because word splitting normally
+ takes care of quote removal. */
+WORD_LIST *
+expand_string_unsplit (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_LIST *value;
+
+ if (string == 0 || *string == '\0')
+ return ((WORD_LIST *)NULL);
+
+ expand_no_split_dollar_star = 1;
+ value = expand_string_internal (string, quoted);
+ expand_no_split_dollar_star = 0;
+
+ if (value)
+ {
+ if (value->word)
+ {
+ remove_quoted_nulls (value->word->word);
+ value->word->flags &= ~W_HASQUOTEDNULL;
+ }
+ dequote_list (value);
+ }
+ return (value);
+}
+
+/* Expand the rhs of an assignment statement */
+WORD_LIST *
+expand_string_assignment (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_DESC td;
+ WORD_LIST *value;
+
+ if (string == 0 || *string == '\0')
+ return ((WORD_LIST *)NULL);
+
+ expand_no_split_dollar_star = 1;
+
+ td.flags = W_ASSIGNRHS;
+ td.word = savestring (string);
+ value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
+ FREE (td.word);
+
+ expand_no_split_dollar_star = 0;
+
+ if (value)
+ {
+ if (value->word)
+ {
+ remove_quoted_nulls (value->word->word);
+ value->word->flags &= ~W_HASQUOTEDNULL;
+ }
+ dequote_list (value);
+ }
+ return (value);
+}
+
+
+/* Expand one of the PS? prompt strings. This is a sort of combination of
+ expand_string_unsplit and expand_string_internal, but returns the
+ passed string when an error occurs. Might want to trap other calls
+ to jump_to_top_level here so we don't endlessly loop. */
+WORD_LIST *
+expand_prompt_string (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_LIST *value;
+ WORD_DESC td;
+
+ if (string == 0 || *string == 0)
+ return ((WORD_LIST *)NULL);
+
+ td.flags = 0;
+ td.word = savestring (string);
+
+ no_longjmp_on_fatal_error = 1;
+ value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
+ no_longjmp_on_fatal_error = 0;
+
+ if (value == &expand_word_error || value == &expand_word_fatal)
+ {
+ value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
+ return value;
+ }
+ FREE (td.word);
+ if (value)
+ {
+ if (value->word)
+ {
+ remove_quoted_nulls (value->word->word);
+ value->word->flags &= ~W_HASQUOTEDNULL;
+ }
+ dequote_list (value);
+ }
+ return (value);
+}
+
+/* Expand STRING just as if you were expanding a word, but do not dequote
+ the resultant WORD_LIST. This is called only from within this file,
+ and is used to correctly preserve quoted characters when expanding
+ things like ${1+"$@"}. This does parameter expansion, command
+ substitution, arithmetic expansion, and word splitting. */
+static WORD_LIST *
+expand_string_leave_quoted (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_LIST *tlist;
+ WORD_LIST *tresult;
+
+ if (string == 0 || *string == '\0')
+ return ((WORD_LIST *)NULL);
+
+ tlist = expand_string_internal (string, quoted);
+
+ if (tlist)
+ {
+ tresult = word_list_split (tlist);
+ dispose_words (tlist);
+ return (tresult);
+ }
+ return ((WORD_LIST *)NULL);
+}
+
+/* This does not perform word splitting or dequote the WORD_LIST
+ it returns. */
+static WORD_LIST *
+expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
+ char *string;
+ int quoted, *dollar_at_p, *has_dollar_at;
+{
+ WORD_DESC td;
+ WORD_LIST *tresult;
+
+ if (string == 0 || *string == '\0')
+ return (WORD_LIST *)NULL;
+
+ td.flags = 0;
+ td.word = string;
+ tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
+ return (tresult);
+}
+
+/* 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. */
+WORD_LIST *
+expand_string (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_LIST *result;
+
+ if (string == 0 || *string == '\0')
+ return ((WORD_LIST *)NULL);
+
+ result = expand_string_leave_quoted (string, quoted);
+ return (result ? dequote_list (result) : result);
+}
+
+/***************************************************
+ * *
+ * Functions to handle quoting chars *
+ * *
+ ***************************************************/
+
+/* Conventions:
+
+ A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
+ The parser passes CTLNUL as CTLESC CTLNUL. */
+
+/* Quote escape characters in string s, but no other characters. This is
+ used to protect CTLESC and CTLNUL in variable values from the rest of
+ the word expansion process after the variable is expanded. */
+char *
+quote_escapes (string)
+ char *string;
+{
+ register char *s, *t;
+ size_t slen;
+ char *result, *send;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ send = string + slen;
+
+ t = result = (char *)xmalloc ((slen * 2) + 1);
+ s = string;
+
+ while (*s)
+ {
+ if (*s == CTLESC || *s == CTLNUL)
+ *t++ = CTLESC;
+ COPY_CHAR_P (t, s, send);
+ }
+ *t = '\0';
+ return (result);
+}
+
+static WORD_LIST *
+list_quote_escapes (list)
+ WORD_LIST *list;
+{
+ register WORD_LIST *w;
+ char *t;
+
+ for (w = list; w; w = w->next)
+ {
+ t = w->word->word;
+ w->word->word = quote_escapes (t);
+ free (t);
+ }
+ return list;
+}
+
+/* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
+
+ The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
+ This is necessary to make unquoted CTLESC and CTLNUL characters in the
+ data stream pass through properly.
+
+ We need to remove doubled CTLESC characters inside quoted strings before
+ quoting the entire string, so we do not double the number of CTLESC
+ characters.
+
+ Also used by parts of the pattern substitution code. */
+static char *
+dequote_escapes (string)
+ char *string;
+{
+ register char *s, *t;
+ size_t slen;
+ char *result, *send;
+ DECLARE_MBSTATE;
+
+ if (string == 0)
+ return string;
+
+ slen = strlen (string);
+ send = string + slen;
+
+ t = result = (char *)xmalloc (slen + 1);
+ s = string;
+
+ if (strchr (string, CTLESC) == 0)
+ return (strcpy (result, s));
+
+ while (*s)
+ {
+ if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
+ {
+ s++;
+ if (*s == '\0')
+ break;
+ }
+ COPY_CHAR_P (t, s, send);
+ }
+ *t = '\0';
+ return result;
+}
+
+/* Return a new string with the quoted representation of character C. */
+static char *
+make_quoted_char (c)
+ int c;
+{
+ char *temp;
+
+ temp = (char *)xmalloc (3);
+ if (c == 0)
+ {
+ temp[0] = CTLNUL;
+ temp[1] = '\0';
+ }
+ else
+ {
+ temp[0] = CTLESC;
+ temp[1] = c;
+ temp[2] = '\0';
+ }
+ return (temp);
+}
+
+/* Quote STRING. Return a new string. */
+char *
+quote_string (string)
+ char *string;
+{
+ register char *t;
+ size_t slen;
+ char *result, *send;
+
+ if (*string == 0)
+ {
+ result = (char *)xmalloc (2);
+ result[0] = CTLNUL;
+ result[1] = '\0';
+ }
+ else
+ {
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ send = string + slen;
+
+ result = (char *)xmalloc ((slen * 2) + 1);
+
+ for (t = result; string < send; )
+ {
+ *t++ = CTLESC;
+ COPY_CHAR_P (t, string, send);
+ }
+ *t = '\0';
+ }
+ return (result);
+}
+
+/* De-quoted quoted characters in STRING. */
+char *
+dequote_string (string)
+ char *string;
+{
+ register char *s, *t;
+ size_t slen;
+ char *result, *send;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+
+ t = result = (char *)xmalloc (slen + 1);
+
+ if (QUOTED_NULL (string))
+ {
+ result[0] = '\0';
+ return (result);
+ }
+
+ /* If no character in the string can be quoted, don't bother examining
+ each character. Just return a copy of the string passed to us. */
+ if (strchr (string, CTLESC) == NULL)
+ return (strcpy (result, string));
+
+ send = string + slen;
+ s = string;
+ while (*s)
+ {
+ if (*s == CTLESC)
+ {
+ s++;
+ if (*s == '\0')
+ break;
+ }
+ COPY_CHAR_P (t, s, send);
+ }
+
+ *t = '\0';
+ return (result);
+}
+
+/* Quote the entire WORD_LIST list. */
+static WORD_LIST *
+quote_list (list)
+ WORD_LIST *list;
+{
+ register WORD_LIST *w;
+ char *t;
+
+ for (w = list; w; w = w->next)
+ {
+ t = w->word->word;
+ w->word->word = quote_string (t);
+ free (t);
+ w->word->flags |= W_QUOTED;
+ }
+ return list;
+}
+
+static WORD_LIST *
+dequote_list (list)
+ WORD_LIST *list;
+{
+ register char *s;
+ register WORD_LIST *tlist;
+
+ for (tlist = list; tlist; tlist = tlist->next)
+ {
+ s = dequote_string (tlist->word->word);
+ free (tlist->word->word);
+ tlist->word->word = s;
+ }
+ return list;
+}
+
+/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
+ string. */
+static char *
+remove_quoted_escapes (string)
+ char *string;
+{
+ char *t;
+
+ if (string)
+ {
+ t = dequote_escapes (string);
+ strcpy (string, t);
+ free (t);
+ }
+
+ return (string);
+}
+
+/* Perform quoted null character removal on STRING. We don't allow any
+ quoted null characters in the middle or at the ends of strings because
+ of how expand_word_internal works. remove_quoted_nulls () turns
+ STRING into an empty string iff it only consists of a quoted null,
+ and removes all unquoted CTLNUL characters. */
+static char *
+remove_quoted_nulls (string)
+ char *string;
+{
+ register size_t slen;
+ register int i, j, prev_i;
+ DECLARE_MBSTATE;
+
+ if (strchr (string, CTLNUL) == 0) /* XXX */
+ return string; /* XXX */
+
+ slen = strlen (string);
+ i = j = 0;
+
+ while (i < slen)
+ {
+ if (string[i] == CTLESC)
+ {
+ /* Old code had j++, but we cannot assume that i == j at this
+ point -- what if a CTLNUL has already been removed from the
+ string? We don't want to drop the CTLESC or recopy characters
+ that we've already copied down. */
+ i++; string[j++] = CTLESC;
+ if (i == slen)
+ break;
+ }
+ else if (string[i] == CTLNUL)
+ i++;
+
+ prev_i = i;
+ ADVANCE_CHAR (string, slen, i);
+ if (j < prev_i)
+ {
+ do string[j++] = string[prev_i++]; while (prev_i < i);
+ }
+ else
+ j = i;
+ }
+ string[j] = '\0';
+
+ return (string);
+}
+
+/* Perform quoted null character removal on each element of LIST.
+ This modifies LIST. */
+void
+word_list_remove_quoted_nulls (list)
+ WORD_LIST *list;
+{
+ register WORD_LIST *t;
+
+ for (t = list; t; t = t->next)
+ {
+ remove_quoted_nulls (t->word->word);
+ t->word->flags &= ~W_HASQUOTEDNULL;
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Functions for Matching and Removing Patterns */
+/* */
+/* **************************************************************** */
+
+#if defined (HANDLE_MULTIBYTE)
+#if 0 /* Currently unused */
+static unsigned char *
+mb_getcharlens (string, len)
+ char *string;
+ int len;
+{
+ int i, offset, last;
+ unsigned char *ret;
+ char *p;
+ DECLARE_MBSTATE;
+
+ i = offset = 0;
+ last = 0;
+ ret = (unsigned char *)xmalloc (len);
+ memset (ret, 0, len);
+ while (string[last])
+ {
+ ADVANCE_CHAR (string, len, offset);
+ ret[last] = offset - last;
+ last = offset;
+ }
+ return ret;
+}
+#endif
+#endif
+
+/* Remove the portion of PARAM matched by PATTERN according to OP, where OP
+ can have one of 4 values:
+ RP_LONG_LEFT remove longest matching portion at start of PARAM
+ RP_SHORT_LEFT remove shortest matching portion at start of PARAM
+ RP_LONG_RIGHT remove longest matching portion at end of PARAM
+ RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
+*/
+
+#define RP_LONG_LEFT 1
+#define RP_SHORT_LEFT 2
+#define RP_LONG_RIGHT 3
+#define RP_SHORT_RIGHT 4
+
+static char *
+remove_upattern (param, pattern, op)
+ char *param, *pattern;
+ int op;
+{
+ register int len;
+ register char *end;
+ register char *p, *ret, c;
+
+ len = STRLEN (param);
+ end = param + len;
+
+ switch (op)
+ {
+ case RP_LONG_LEFT: /* remove longest match at start */
+ for (p = end; p >= param; p--)
+ {
+ c = *p; *p = '\0';
+ if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ *p = c;
+ return (savestring (p));
+ }
+ *p = c;
+
+ }
+ break;
+
+ case RP_SHORT_LEFT: /* remove shortest match at start */
+ for (p = param; p <= end; p++)
+ {
+ c = *p; *p = '\0';
+ if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ *p = c;
+ return (savestring (p));
+ }
+ *p = c;
+ }
+ break;
+
+ case RP_LONG_RIGHT: /* remove longest match at end */
+ for (p = param; p <= end; p++)
+ {
+ if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ c = *p; *p = '\0';
+ ret = savestring (param);
+ *p = c;
+ return (ret);
+ }
+ }
+ break;
+
+ case RP_SHORT_RIGHT: /* remove shortest match at end */
+ for (p = end; p >= param; p--)
+ {
+ if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ c = *p; *p = '\0';
+ ret = savestring (param);
+ *p = c;
+ return (ret);
+ }
+ }
+ break;
+ }
+
+ return (savestring (param)); /* no match, return original string */
+}
+
+#if defined (HANDLE_MULTIBYTE)
+
+#if !defined (HAVE_WCSDUP)
+static wchar_t *
+wcsdup (ws)
+ wchar_t *ws;
+{
+ wchar_t *ret;
+ size_t len;
+
+ len = wcslen (ws);
+ ret = xmalloc ((len + 1) * sizeof (wchar_t));
+ if (ret == 0)
+ return ret;
+ return (wcscpy (ret, ws));
+}
+#endif /* !HAVE_WCSDUP */
+
+static wchar_t *
+remove_wpattern (wparam, wstrlen, wpattern, op)
+ wchar_t *wparam;
+ size_t wstrlen;
+ wchar_t *wpattern;
+ int op;
+{
+ wchar_t wc;
+ int n, n1;
+ wchar_t *ret;
+
+ switch (op)
+ {
+ case RP_LONG_LEFT: /* remove longest match at start */
+ for (n = wstrlen; n >= 0; n--)
+ {
+ wc = wparam[n]; wparam[n] = L'\0';
+ if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ wparam[n] = wc;
+ return (wcsdup (wparam + n));
+ }
+ wparam[n] = wc;
+ }
+ break;
+
+ case RP_SHORT_LEFT: /* remove shortest match at start */
+ for (n = 0; n <= wstrlen; n++)
+ {
+ wc = wparam[n]; wparam[n] = L'\0';
+ if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ wparam[n] = wc;
+ return (wcsdup (wparam + n));
+ }
+ wparam[n] = wc;
+ }
+ break;
+
+ case RP_LONG_RIGHT: /* remove longest match at end */
+ for (n = 0; n <= wstrlen; n++)
+ {
+ if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ wc = wparam[n]; wparam[n] = L'\0';
+ ret = wcsdup (wparam);
+ wparam[n] = wc;
+ return (ret);
+ }
+ }
+ break;
+
+ case RP_SHORT_RIGHT: /* remove shortest match at end */
+ for (n = wstrlen; n >= 0; n--)
+ {
+ if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ wc = wparam[n]; wparam[n] = L'\0';
+ ret = wcsdup (wparam);
+ wparam[n] = wc;
+ return (ret);
+ }
+ }
+ break;
+ }
+
+ return (wcsdup (wparam)); /* no match, return original string */
+}
+#endif /* HANDLE_MULTIBYTE */
+
+static char *
+remove_pattern (param, pattern, op)
+ char *param, *pattern;
+ int op;
+{
+ if (param == NULL)
+ return (param);
+ if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
+ return (savestring (param));
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1)
+ {
+ wchar_t *ret, *oret;
+ size_t n;
+ wchar_t *wparam, *wpattern;
+ mbstate_t ps;
+ char *xret;
+
+ n = xdupmbstowcs (&wpattern, NULL, pattern);
+ if (n == (size_t)-1)
+ return (remove_upattern (param, pattern, op));
+ n = xdupmbstowcs (&wparam, NULL, param);
+ if (n == (size_t)-1)
+ {
+ free (wpattern);
+ return (remove_upattern (param, pattern, op));
+ }
+ oret = ret = remove_wpattern (wparam, n, wpattern, op);
+
+ free (wparam);
+ free (wpattern);
+
+ n = strlen (param);
+ xret = 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 */
+ free (oret);
+ return xret;
+ }
+ else
+#endif
+ return (remove_upattern (param, pattern, op));
+}
+
+/* Return 1 of the first character of STRING could match the first
+ character of pattern PAT. Used to avoid n2 calls to strmatch(). */
+static int
+match_pattern_char (pat, string)
+ char *pat, *string;
+{
+ char c;
+
+ if (*string == 0)
+ return (0);
+
+ switch (c = *pat++)
+ {
+ default:
+ return (*string == c);
+ case '\\':
+ return (*string == *pat);
+ case '?':
+ return (*pat == LPAREN ? 1 : (*string != '\0'));
+ case '*':
+ return (1);
+ case '+':
+ case '!':
+ case '@':
+ return (*pat == LPAREN ? 1 : (*string == c));
+ case '[':
+ return (*string != '\0');
+ }
+}
+
+/* Match PAT anywhere in STRING and return the match boundaries.
+ This returns 1 in case of a successful match, 0 otherwise. SP
+ and EP are pointers into the string where the match begins and
+ ends, respectively. MTYPE controls what kind of match is attempted.
+ MATCH_BEG and MATCH_END anchor the match at the beginning and end
+ of the string, respectively. The longest match is returned. */
+static int
+match_upattern (string, pat, mtype, sp, ep)
+ char *string, *pat;
+ int mtype;
+ char **sp, **ep;
+{
+ int c, len;
+ register char *p, *p1, *npat;
+ char *end;
+
+ /* If the pattern doesn't match anywhere in the string, go ahead and
+ short-circuit right away. A minor optimization, saves a bunch of
+ unnecessary calls to strmatch (up to N calls for a string of N
+ characters) if the match is unsuccessful. To preserve the semantics
+ of the substring matches below, we make sure that the pattern has
+ `*' as first and last character, making a new pattern if necessary. */
+ /* XXX - check this later if I ever implement `**' with special meaning,
+ since this will potentially result in `**' at the beginning or end */
+ len = STRLEN (pat);
+ if (pat[0] != '*' || pat[len - 1] != '*')
+ {
+ p = npat = xmalloc (len + 3);
+ p1 = pat;
+ if (*p1 != '*')
+ *p++ = '*';
+ while (*p1)
+ *p++ = *p1++;
+ if (p1[-1] != '*' || p[-2] == '\\')
+ *p++ = '*';
+ *p = '\0';
+ }
+ else
+ npat = pat;
+ c = strmatch (npat, string, FNMATCH_EXTFLAG);
+ if (npat != pat)
+ free (npat);
+ if (c == FNM_NOMATCH)
+ return (0);
+
+ len = STRLEN (string);
+ end = string + len;
+
+ switch (mtype)
+ {
+ case MATCH_ANY:
+ for (p = string; p <= end; p++)
+ {
+ if (match_pattern_char (pat, p))
+ {
+ for (p1 = end; p1 >= p; p1--)
+ {
+ c = *p1; *p1 = '\0';
+ if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
+ {
+ *p1 = c;
+ *sp = p;
+ *ep = p1;
+ return 1;
+ }
+ *p1 = c;
+ }
+ }
+ }
+
+ return (0);
+
+ case MATCH_BEG:
+ if (match_pattern_char (pat, string) == 0)
+ return (0);
+
+ for (p = end; p >= string; p--)
+ {
+ c = *p; *p = '\0';
+ if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
+ {
+ *p = c;
+ *sp = string;
+ *ep = p;
+ return 1;
+ }
+ *p = c;
+ }
+
+ return (0);
+
+ case MATCH_END:
+ for (p = string; p <= end; p++)
+ {
+ if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
+ {
+ *sp = p;
+ *ep = end;
+ return 1;
+ }
+
+ }
+
+ return (0);
+ }
+
+ return (0);
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Return 1 of the first character of WSTRING could match the first
+ character of pattern WPAT. Wide character version. */
+static int
+match_pattern_wchar (wpat, wstring)
+ wchar_t *wpat, *wstring;
+{
+ wchar_t wc;
+
+ if (*wstring == 0)
+ return (0);
+
+ switch (wc = *wpat++)
+ {
+ default:
+ return (*wstring == wc);
+ case L'\\':
+ return (*wstring == *wpat);
+ case L'?':
+ return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
+ case L'*':
+ return (1);
+ case L'+':
+ case L'!':
+ case L'@':
+ return (*wpat == LPAREN ? 1 : (*wstring == wc));
+ case L'[':
+ return (*wstring != L'\0');
+ }
+}
+
+/* Match WPAT anywhere in WSTRING and return the match boundaries.
+ This returns 1 in case of a successful match, 0 otherwise. Wide
+ character version. */
+static int
+match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
+ wchar_t *wstring;
+ char **indices;
+ size_t wstrlen;
+ wchar_t *wpat;
+ int mtype;
+ char **sp, **ep;
+{
+ wchar_t wc, *wp, *nwpat, *wp1;
+ int len;
+#if 0
+ size_t n, n1; /* Apple's gcc seems to miscompile this badly */
+#else
+ int n, n1;
+#endif
+
+ /* If the pattern doesn't match anywhere in the string, go ahead and
+ short-circuit right away. A minor optimization, saves a bunch of
+ unnecessary calls to strmatch (up to N calls for a string of N
+ characters) if the match is unsuccessful. To preserve the semantics
+ of the substring matches below, we make sure that the pattern has
+ `*' as first and last character, making a new pattern if necessary. */
+ /* XXX - check this later if I ever implement `**' with special meaning,
+ since this will potentially result in `**' at the beginning or end */
+ len = wcslen (wpat);
+ if (wpat[0] != L'*' || wpat[len - 1] != L'*')
+ {
+ wp = nwpat = xmalloc ((len + 3) * sizeof (wchar_t));
+ wp1 = wpat;
+ if (*wp1 != L'*')
+ *wp++ = L'*';
+ while (*wp1 != L'\0')
+ *wp++ = *wp1++;
+ if (wp1[-1] != L'*' || wp1[-2] == L'\\')
+ *wp++ = L'*';
+ *wp = '\0';
+ }
+ else
+ nwpat = wpat;
+ len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
+ if (nwpat != wpat)
+ free (nwpat);
+ if (len == FNM_NOMATCH)
+ return (0);
+
+ switch (mtype)
+ {
+ case MATCH_ANY:
+ for (n = 0; n <= wstrlen; n++)
+ {
+ if (match_pattern_wchar (wpat, wstring + n))
+ {
+ for (n1 = wstrlen; n1 >= n; n1--)
+ {
+ wc = wstring[n1]; wstring[n1] = L'\0';
+ if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
+ {
+ wstring[n1] = wc;
+ *sp = indices[n];
+ *ep = indices[n1];
+ return 1;
+ }
+ wstring[n1] = wc;
+ }
+ }
+ }
+
+ return (0);
+
+ case MATCH_BEG:
+ if (match_pattern_wchar (wpat, wstring) == 0)
+ return (0);
+
+ for (n = wstrlen; n >= 0; n--)
+ {
+ wc = wstring[n]; wstring[n] = L'\0';
+ if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
+ {
+ wstring[n] = wc;
+ *sp = indices[0];
+ *ep = indices[n];
+ return 1;
+ }
+ wstring[n] = wc;
+ }
+
+ return (0);
+
+ case MATCH_END:
+ for (n = 0; n <= wstrlen; n++)
+ {
+ if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
+ {
+ *sp = indices[n];
+ *ep = indices[wstrlen];
+ return 1;
+ }
+ }
+
+ return (0);
+ }
+
+ return (0);
+}
+#endif /* HANDLE_MULTIBYTE */
+
+static int
+match_pattern (string, pat, mtype, sp, ep)
+ char *string, *pat;
+ int mtype;
+ char **sp, **ep;
+{
+#if defined (HANDLE_MULTIBYTE)
+ int ret;
+ size_t n;
+ wchar_t *wstring, *wpat;
+ char **indices;
+#endif
+
+ if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
+ return (0);
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1)
+ {
+ n = xdupmbstowcs (&wpat, NULL, pat);
+ if (n == (size_t)-1)
+ return (match_upattern (string, pat, mtype, sp, ep));
+ n = xdupmbstowcs (&wstring, &indices, string);
+ if (n == (size_t)-1)
+ {
+ free (wpat);
+ return (match_upattern (string, pat, mtype, sp, ep));
+ }
+ ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
+
+ free (wpat);
+ free (wstring);
+ free (indices);
+
+ return (ret);
+ }
+ else
+#endif
+ return (match_upattern (string, pat, mtype, sp, ep));
+}
+
+static int
+getpatspec (c, value)
+ int c;
+ char *value;
+{
+ if (c == '#')
+ return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
+ else /* c == '%' */
+ return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
+}
+
+/* Posix.2 says that the WORD should be run through tilde expansion,
+ parameter expansion, command substitution and arithmetic expansion.
+ This leaves the result quoted, so quote_string_for_globbing () has
+ to be called to fix it up for strmatch (). If QUOTED is non-zero,
+ it means that the entire expression was enclosed in double quotes.
+ This means that quoting characters in the pattern do not make any
+ special pattern characters quoted. For example, the `*' in the
+ following retains its special meaning: "${foo#'*'}". */
+static char *
+getpattern (value, quoted, expandpat)
+ char *value;
+ int quoted, expandpat;
+{
+ char *pat, *tword;
+ WORD_LIST *l;
+ int i;
+
+ /* There is a problem here: how to handle single or double quotes in the
+ pattern string when the whole expression is between double quotes?
+ POSIX.2 says that enclosing double quotes do not cause the pattern to
+ be quoted, but does that leave us a problem with @ and array[@] and their
+ expansions inside a pattern? */
+#if 0
+ if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
+ {
+ i = 0;
+ pat = string_extract_double_quoted (tword, &i, 1);
+ free (tword);
+ tword = pat;
+ }
+#endif
+
+ /* expand_string_for_rhs () leaves WORD quoted and does not perform
+ word splitting. */
+ l = *value ? expand_string_for_rhs (value,
+ (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
+ (int *)NULL, (int *)NULL)
+ : (WORD_LIST *)0;
+ pat = string_list (l);
+ dispose_words (l);
+ if (pat)
+ {
+ tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
+ free (pat);
+ pat = tword;
+ }
+ return (pat);
+}
+
+#if 0
+/* Handle removing a pattern from a string as a result of ${name%[%]value}
+ or ${name#[#]value}. */
+static char *
+variable_remove_pattern (value, pattern, patspec, quoted)
+ char *value, *pattern;
+ int patspec, quoted;
+{
+ char *tword;
+
+ tword = remove_pattern (value, pattern, patspec);
+
+ return (tword);
+}
+#endif
+
+static char *
+list_remove_pattern (list, pattern, patspec, itype, quoted)
+ WORD_LIST *list;
+ char *pattern;
+ int patspec, itype, quoted;
+{
+ WORD_LIST *new, *l;
+ WORD_DESC *w;
+ char *tword;
+
+ for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
+ {
+ tword = remove_pattern (l->word->word, pattern, patspec);
+ w = alloc_word_desc ();
+ w->word = tword ? tword : savestring ("");
+ new = make_word_list (w, new);
+ }
+
+ l = REVERSE_LIST (new, WORD_LIST *);
+ if (itype == '*')
+ tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
+ else
+ tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
+
+ dispose_words (l);
+ return (tword);
+}
+
+static char *
+parameter_list_remove_pattern (itype, pattern, patspec, quoted)
+ int itype;
+ char *pattern;
+ int patspec, quoted;
+{
+ char *ret;
+ WORD_LIST *list;
+
+ list = list_rest_of_args ();
+ if (list == 0)
+ return ((char *)NULL);
+ ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
+ dispose_words (list);
+ return (ret);
+}
+
+#if defined (ARRAY_VARS)
+static char *
+array_remove_pattern (a, pattern, patspec, varname, quoted)
+ ARRAY *a;
+ char *pattern;
+ int patspec;
+ char *varname; /* so we can figure out how it's indexed */
+ int quoted;
+{
+ int itype;
+ char *ret;
+ WORD_LIST *list;
+ SHELL_VAR *v;
+
+ /* compute itype from varname here */
+ v = array_variable_part (varname, &ret, 0);
+ itype = ret[0];
+
+ list = array_to_word_list (a);
+ if (list == 0)
+ return ((char *)NULL);
+ ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
+ dispose_words (list);
+
+ return ret;
+}
+#endif /* ARRAY_VARS */
+
+static char *
+parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
+ char *varname, *value, *patstr;
+ int rtype, quoted;
+{
+ int vtype, patspec, starsub;
+ char *temp1, *val, *pattern;
+ SHELL_VAR *v;
+
+ if (value == 0)
+ return ((char *)NULL);
+
+ this_command_name = varname;
+
+ vtype = get_var_and_type (varname, value, quoted, &v, &val);
+ if (vtype == -1)
+ return ((char *)NULL);
+
+ starsub = vtype & VT_STARSUB;
+ vtype &= ~VT_STARSUB;
+
+ patspec = getpatspec (rtype, patstr);
+ if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
+ patstr++;
+
+ pattern = getpattern (patstr, quoted, 1);
+
+ temp1 = (char *)NULL; /* shut up gcc */
+ switch (vtype)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+ temp1 = remove_pattern (val, pattern, patspec);
+ if (vtype == VT_VARIABLE)
+ FREE (val);
+ if (temp1)
+ {
+ val = quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ temp1 = array_remove_pattern (array_cell (v), pattern, patspec, varname, quoted);
+ if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ {
+ val = quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+#endif
+ case VT_POSPARMS:
+ temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
+ if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ {
+ val = quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+ }
+
+ FREE (pattern);
+ return temp1;
+}
+
+/*******************************************
+ * *
+ * Functions to expand WORD_DESCs *
+ * *
+ *******************************************/
+
+/* Expand WORD, performing word splitting on the result. This does
+ parameter expansion, command substitution, arithmetic expansion,
+ word splitting, and quote removal. */
+
+WORD_LIST *
+expand_word (word, quoted)
+ WORD_DESC *word;
+ int quoted;
+{
+ WORD_LIST *result, *tresult;
+
+ tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
+ result = word_list_split (tresult);
+ dispose_words (tresult);
+ return (result ? dequote_list (result) : result);
+}
+
+/* Expand WORD, but do not perform word splitting on the result. This
+ does parameter expansion, command substitution, arithmetic expansion,
+ and quote removal. */
+WORD_LIST *
+expand_word_unsplit (word, quoted)
+ WORD_DESC *word;
+ int quoted;
+{
+ WORD_LIST *result;
+
+ expand_no_split_dollar_star = 1;
+ result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
+ expand_no_split_dollar_star = 0;
+
+ return (result ? dequote_list (result) : result);
+}
+
+/* Perform shell expansions on WORD, but do not perform word splitting or
+ quote removal on the result. */
+WORD_LIST *
+expand_word_leave_quoted (word, quoted)
+ WORD_DESC *word;
+ int quoted;
+{
+ return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
+}
+
+#if defined (PROCESS_SUBSTITUTION)
+
+/*****************************************************************/
+/* */
+/* Hacking Process Substitution */
+/* */
+/*****************************************************************/
+
+#if !defined (HAVE_DEV_FD)
+/* Named pipes must be removed explicitly with `unlink'. This keeps a list
+ of FIFOs the shell has open. unlink_fifo_list will walk the list and
+ unlink all of them. add_fifo_list adds the name of an open FIFO to the
+ list. NFIFO is a count of the number of FIFOs in the list. */
+#define FIFO_INCR 20
+
+struct temp_fifo {
+ char *file;
+ pid_t proc;
+};
+
+static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
+static int nfifo;
+static int fifo_list_size;
+
+static void
+add_fifo_list (pathname)
+ char *pathname;
+{
+ if (nfifo >= fifo_list_size - 1)
+ {
+ fifo_list_size += FIFO_INCR;
+ fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
+ fifo_list_size * sizeof (struct temp_fifo));
+ }
+
+ fifo_list[nfifo].file = savestring (pathname);
+ nfifo++;
+}
+
+void
+unlink_fifo_list ()
+{
+ int saved, i, j;
+
+ if (nfifo == 0)
+ return;
+
+ for (i = saved = 0; i < nfifo; i++)
+ {
+ if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
+ {
+ unlink (fifo_list[i].file);
+ free (fifo_list[i].file);
+ fifo_list[i].file = (char *)NULL;
+ fifo_list[i].proc = -1;
+ }
+ else
+ saved++;
+ }
+
+ /* If we didn't remove some of the FIFOs, compact the list. */
+ if (saved)
+ {
+ for (i = j = 0; i < nfifo; i++)
+ if (fifo_list[i].file)
+ {
+ fifo_list[j].file = fifo_list[i].file;
+ fifo_list[j].proc = fifo_list[i].proc;
+ j++;
+ }
+ nfifo = j;
+ }
+ else
+ nfifo = 0;
+}
+
+static char *
+make_named_pipe ()
+{
+ char *tname;
+
+ tname = sh_mktmpname ("sh-np", MT_USERANDOM);
+ if (mkfifo (tname, 0600) < 0)
+ {
+ free (tname);
+ return ((char *)NULL);
+ }
+
+ add_fifo_list (tname);
+ return (tname);
+}
+
+#else /* HAVE_DEV_FD */
+
+/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
+ has open to children. NFDS is a count of the number of bits currently
+ set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
+ of open files. */
+static char *dev_fd_list = (char *)NULL;
+static int nfds;
+static int totfds; /* The highest possible number of open files. */
+
+static void
+add_fifo_list (fd)
+ int fd;
+{
+ if (!dev_fd_list || fd >= totfds)
+ {
+ int ofds;
+
+ ofds = totfds;
+ totfds = getdtablesize ();
+ if (totfds < 0 || totfds > 256)
+ totfds = 256;
+ if (fd > totfds)
+ totfds = fd + 2;
+
+ dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
+ memset (dev_fd_list + ofds, '\0', totfds - ofds);
+ }
+
+ dev_fd_list[fd] = 1;
+ nfds++;
+}
+
+void
+unlink_fifo_list ()
+{
+ register int i;
+
+ if (nfds == 0)
+ return;
+
+ for (i = 0; nfds && i < totfds; i++)
+ if (dev_fd_list[i])
+ {
+ close (i);
+ dev_fd_list[i] = 0;
+ nfds--;
+ }
+
+ nfds = 0;
+}
+
+#if defined (NOTDEF)
+print_dev_fd_list ()
+{
+ register int i;
+
+ fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
+ fflush (stderr);
+
+ for (i = 0; i < totfds; i++)
+ {
+ if (dev_fd_list[i])
+ fprintf (stderr, " %d", i);
+ }
+ fprintf (stderr, "\n");
+}
+#endif /* NOTDEF */
+
+static char *
+make_dev_fd_filename (fd)
+ int fd;
+{
+ char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
+
+ ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 4);
+
+ strcpy (ret, DEV_FD_PREFIX);
+ p = inttostr (fd, intbuf, sizeof (intbuf));
+ strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
+
+ add_fifo_list (fd);
+ return (ret);
+}
+
+#endif /* HAVE_DEV_FD */
+
+/* Return a filename that will open a connection to the process defined by
+ executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
+ a filename in /dev/fd corresponding to a descriptor that is one of the
+ ends of the pipe. If not defined, we use named pipes on systems that have
+ them. Systems without /dev/fd and named pipes are out of luck.
+
+ OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
+ use the read end of the pipe and dup that file descriptor to fd 0 in
+ the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
+ writing or use the write end of the pipe in the child, and dup that
+ file descriptor to fd 1 in the child. The parent does the opposite. */
+
+static char *
+process_substitute (string, open_for_read_in_child)
+ char *string;
+ int open_for_read_in_child;
+{
+ char *pathname;
+ int fd, result;
+ pid_t old_pid, pid;
+#if defined (HAVE_DEV_FD)
+ int parent_pipe_fd, child_pipe_fd;
+ int fildes[2];
+#endif /* HAVE_DEV_FD */
+#if defined (JOB_CONTROL)
+ pid_t old_pipeline_pgrp;
+#endif
+
+ if (!string || !*string || wordexp_only)
+ return ((char *)NULL);
+
+#if !defined (HAVE_DEV_FD)
+ pathname = make_named_pipe ();
+#else /* HAVE_DEV_FD */
+ if (pipe (fildes) < 0)
+ {
+ sys_error (_("cannot make pipe for process substitution"));
+ return ((char *)NULL);
+ }
+ /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
+ the pipe in the parent, otherwise the read end. */
+ parent_pipe_fd = fildes[open_for_read_in_child];
+ child_pipe_fd = fildes[1 - open_for_read_in_child];
+ /* Move the parent end of the pipe to some high file descriptor, to
+ avoid clashes with FDs used by the script. */
+ parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
+
+ pathname = make_dev_fd_filename (parent_pipe_fd);
+#endif /* HAVE_DEV_FD */
+
+ if (!pathname)
+ {
+ sys_error (_("cannot make pipe for process substitution"));
+ return ((char *)NULL);
+ }
+
+ old_pid = last_made_pid;
+
+#if defined (JOB_CONTROL)
+ old_pipeline_pgrp = pipeline_pgrp;
+ pipeline_pgrp = shell_pgrp;
+ save_pipeline (1);
+#endif /* JOB_CONTROL */
+
+ pid = make_child ((char *)NULL, 1);
+ if (pid == 0)
+ {
+ reset_terminating_signals (); /* XXX */
+ free_pushed_string_input ();
+ /* Cancel traps, in trap.c. */
+ restore_original_signals ();
+ setup_async_signals ();
+ subshell_environment |= SUBSHELL_COMSUB;
+ }
+
+#if defined (JOB_CONTROL)
+ set_sigchld_handler ();
+ stop_making_children ();
+ pipeline_pgrp = old_pipeline_pgrp;
+#endif /* JOB_CONTROL */
+
+ if (pid < 0)
+ {
+ sys_error (_("cannot make child for process substitution"));
+ free (pathname);
+#if defined (HAVE_DEV_FD)
+ close (parent_pipe_fd);
+ close (child_pipe_fd);
+#endif /* HAVE_DEV_FD */
+ return ((char *)NULL);
+ }
+
+ if (pid > 0)
+ {
+#if defined (JOB_CONTROL)
+ restore_pipeline (1);
+#endif
+
+#if !defined (HAVE_DEV_FD)
+ fifo_list[nfifo-1].proc = pid;
+#endif
+
+ last_made_pid = old_pid;
+
+#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
+ close_pgrp_pipe ();
+#endif /* JOB_CONTROL && PGRP_PIPE */
+
+#if defined (HAVE_DEV_FD)
+ close (child_pipe_fd);
+#endif /* HAVE_DEV_FD */
+
+ return (pathname);
+ }
+
+ set_sigint_handler ();
+
+#if defined (JOB_CONTROL)
+ set_job_control (0);
+#endif /* JOB_CONTROL */
+
+#if !defined (HAVE_DEV_FD)
+ /* Open the named pipe in the child. */
+ fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
+ if (fd < 0)
+ {
+ /* Two separate strings for ease of translation. */
+ if (open_for_read_in_child)
+ sys_error (_("cannot open named pipe %s for reading"), pathname);
+ else
+ sys_error (_("cannot open named pipe %s for writing"), pathname);
+
+ exit (127);
+ }
+ if (open_for_read_in_child)
+ {
+ if (sh_unset_nodelay_mode (fd) < 0)
+ {
+ sys_error (_("cannout reset nodelay mode for fd %d"), fd);
+ exit (127);
+ }
+ }
+#else /* HAVE_DEV_FD */
+ fd = child_pipe_fd;
+#endif /* HAVE_DEV_FD */
+
+ if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
+ {
+ sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
+ open_for_read_in_child ? 0 : 1);
+ exit (127);
+ }
+
+ if (fd != (open_for_read_in_child ? 0 : 1))
+ close (fd);
+
+ /* Need to close any files that this process has open to pipes inherited
+ from its parent. */
+ if (current_fds_to_close)
+ {
+ close_fd_bitmap (current_fds_to_close);
+ current_fds_to_close = (struct fd_bitmap *)NULL;
+ }
+
+#if defined (HAVE_DEV_FD)
+ /* Make sure we close the parent's end of the pipe and clear the slot
+ in the fd list so it is not closed later, if reallocated by, for
+ instance, pipe(2). */
+ close (parent_pipe_fd);
+ dev_fd_list[parent_pipe_fd] = 0;
+#endif /* HAVE_DEV_FD */
+
+ result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
+
+#if !defined (HAVE_DEV_FD)
+ /* Make sure we close the named pipe in the child before we exit. */
+ close (open_for_read_in_child ? 0 : 1);
+#endif /* !HAVE_DEV_FD */
+
+ exit (result);
+ /*NOTREACHED*/
+}
+#endif /* PROCESS_SUBSTITUTION */
+
+/***********************************/
+/* */
+/* Command Substitution */
+/* */
+/***********************************/
+
+static char *
+read_comsub (fd, quoted)
+ int fd, quoted;
+{
+ char *istring, buf[128], *bufp;
+ int istring_index, istring_size, c;
+ ssize_t bufn;
+
+ istring = (char *)NULL;
+ istring_index = istring_size = bufn = 0;
+
+#ifdef __CYGWIN__
+ setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
+#endif
+
+ /* Read the output of the command through the pipe. */
+ while (1)
+ {
+ if (fd < 0)
+ break;
+ if (--bufn <= 0)
+ {
+ bufn = zread (fd, buf, sizeof (buf));
+ if (bufn <= 0)
+ break;
+ bufp = buf;
+ }
+ c = *bufp++;
+
+ if (c == 0)
+ {
+#if 0
+ internal_warning ("read_comsub: ignored null byte in input");
+#endif
+ continue;
+ }
+
+ /* Add the character to ISTRING, possibly after resizing it. */
+ RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
+
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
+ istring[istring_index++] = CTLESC;
+
+ istring[istring_index++] = c;
+
+#if 0
+#if defined (__CYGWIN__)
+ if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
+ {
+ istring_index--;
+ istring[istring_index - 1] = '\n';
+ }
+#endif
+#endif
+ }
+
+ if (istring)
+ istring[istring_index] = '\0';
+
+ /* If we read no output, just return now and save ourselves some
+ trouble. */
+ if (istring_index == 0)
+ {
+ FREE (istring);
+ return (char *)NULL;
+ }
+
+ /* Strip trailing newlines from the output of the command. */
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ {
+ while (istring_index > 0)
+ {
+ if (istring[istring_index - 1] == '\n')
+ {
+ --istring_index;
+
+ /* If the newline was quoted, remove the quoting char. */
+ if (istring[istring_index - 1] == CTLESC)
+ --istring_index;
+ }
+ else
+ break;
+ }
+ istring[istring_index] = '\0';
+ }
+ else
+ strip_trailing (istring, istring_index - 1, 1);
+
+ return istring;
+}
+
+/* Perform command substitution on STRING. This returns a string,
+ possibly quoted. */
+char *
+command_substitute (string, quoted)
+ char *string;
+ int quoted;
+{
+ pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
+ char *istring;
+ int result, fildes[2], function_value, pflags, rc;
+
+ istring = (char *)NULL;
+
+ /* Don't fork () if there is no need to. In the case of no command to
+ run, just return NULL. */
+ if (!string || !*string || (string[0] == '\n' && !string[1]))
+ return ((char *)NULL);
+
+ if (wordexp_only && read_but_dont_execute)
+ {
+ last_command_exit_value = 125;
+ jump_to_top_level (EXITPROG);
+ }
+
+ /* We're making the assumption here that the command substitution will
+ eventually run a command from the file system. Since we'll run
+ maybe_make_export_env in this subshell before executing that command,
+ the parent shell and any other shells it starts will have to remake
+ the environment. If we make it before we fork, other shells won't
+ have to. Don't bother if we have any temporary variable assignments,
+ though, because the export environment will be remade after this
+ command completes anyway, but do it if all the words to be expanded
+ are variable assignments. */
+ if (subst_assign_varlist == 0 || garglist == 0)
+ maybe_make_export_env (); /* XXX */
+
+ /* Flags to pass to parse_and_execute() */
+ pflags = interactive ? SEVAL_RESETLINE : 0;
+
+ /* Pipe the output of executing STRING into the current shell. */
+ if (pipe (fildes) < 0)
+ {
+ sys_error (_("cannot make pipe for command substitution"));
+ goto error_exit;
+ }
+
+ old_pid = last_made_pid;
+#if defined (JOB_CONTROL)
+ old_pipeline_pgrp = pipeline_pgrp;
+ /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
+ if ((subshell_environment & SUBSHELL_PIPE) == 0)
+ pipeline_pgrp = shell_pgrp;
+ cleanup_the_pipeline ();
+#endif /* JOB_CONTROL */
+
+ old_async_pid = last_asynchronous_pid;
+#if 0
+ pid = make_child ((char *)NULL, 0);
+#else
+ pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
+#endif
+ last_asynchronous_pid = old_async_pid;
+
+ if (pid == 0)
+ /* Reset the signal handlers in the child, but don't free the
+ trap strings. */
+ reset_signal_handlers ();
+
+#if defined (JOB_CONTROL)
+ set_sigchld_handler ();
+ stop_making_children ();
+ pipeline_pgrp = old_pipeline_pgrp;
+#else
+ stop_making_children ();
+#endif /* JOB_CONTROL */
+
+ if (pid < 0)
+ {
+ sys_error (_("cannot make child for command substitution"));
+ error_exit:
+
+ FREE (istring);
+ close (fildes[0]);
+ close (fildes[1]);
+ return ((char *)NULL);
+ }
+
+ if (pid == 0)
+ {
+ set_sigint_handler (); /* XXX */
+
+ free_pushed_string_input ();
+
+ if (dup2 (fildes[1], 1) < 0)
+ {
+ sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
+ exit (EXECUTION_FAILURE);
+ }
+
+ /* If standard output is closed in the parent shell
+ (such as after `exec >&-'), file descriptor 1 will be
+ the lowest available file descriptor, and end up in
+ fildes[0]. This can happen for stdin and stderr as well,
+ but stdout is more important -- it will cause no output
+ to be generated from this command. */
+ if ((fildes[1] != fileno (stdin)) &&
+ (fildes[1] != fileno (stdout)) &&
+ (fildes[1] != fileno (stderr)))
+ close (fildes[1]);
+
+ if ((fildes[0] != fileno (stdin)) &&
+ (fildes[0] != fileno (stdout)) &&
+ (fildes[0] != fileno (stderr)))
+ close (fildes[0]);
+
+ /* The currently executing shell is not interactive. */
+ interactive = 0;
+
+ /* This is a subshell environment. */
+ subshell_environment |= SUBSHELL_COMSUB;
+
+ /* When not in POSIX mode, command substitution does not inherit
+ the -e flag. */
+ if (posixly_correct == 0)
+ exit_immediately_on_error = 0;
+
+ remove_quoted_escapes (string);
+
+ startup_state = 2; /* see if we can avoid a fork */
+ /* Give command substitution a place to jump back to on failure,
+ so we don't go back up to main (). */
+ result = setjmp (top_level);
+
+ /* If we're running a command substitution inside a shell function,
+ trap `return' so we don't return from the function in the subshell
+ and go off to never-never land. */
+ if (result == 0 && return_catch_flag)
+ function_value = setjmp (return_catch);
+ else
+ function_value = 0;
+
+ if (result == ERREXIT)
+ rc = last_command_exit_value;
+ else if (result == EXITPROG)
+ rc = last_command_exit_value;
+ else if (result)
+ rc = EXECUTION_FAILURE;
+ else if (function_value)
+ rc = return_catch_value;
+ else
+ {
+ subshell_level++;
+ rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
+ subshell_level--;
+ }
+
+ last_command_exit_value = rc;
+ rc = run_exit_trap ();
+ exit (rc);
+ }
+ else
+ {
+#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
+ close_pgrp_pipe ();
+#endif /* JOB_CONTROL && PGRP_PIPE */
+
+ close (fildes[1]);
+
+ istring = read_comsub (fildes[0], quoted);
+
+ close (fildes[0]);
+
+ current_command_subst_pid = pid;
+ last_command_exit_value = wait_for (pid);
+ last_command_subst_pid = pid;
+ last_made_pid = old_pid;
+
+#if defined (JOB_CONTROL)
+ /* If last_command_exit_value > 128, then the substituted command
+ was terminated by a signal. If that signal was SIGINT, then send
+ SIGINT to ourselves. This will break out of loops, for instance. */
+ if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
+ kill (getpid (), SIGINT);
+
+ /* wait_for gives the terminal back to shell_pgrp. If some other
+ process group should have it, give it away to that group here.
+ pipeline_pgrp is non-zero only while we are constructing a
+ pipline, so what we are concerned about is whether or not that
+ pipeline was started in the background. A pipeline started in
+ the background should never get the tty back here. */
+#if 0
+ if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
+#else
+ if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
+#endif
+ give_terminal_to (pipeline_pgrp, 0);
+#endif /* JOB_CONTROL */
+
+ return (istring);
+ }
+}
+
+/********************************************************
+ * *
+ * Utility functions for parameter expansion *
+ * *
+ ********************************************************/
+
+#if defined (ARRAY_VARS)
+
+static arrayind_t
+array_length_reference (s)
+ char *s;
+{
+ int len;
+ arrayind_t ind;
+ char *t, c;
+ ARRAY *array;
+ SHELL_VAR *var;
+
+ var = array_variable_part (s, &t, &len);
+
+ /* If unbound variables should generate an error, report one and return
+ failure. */
+ if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
+ {
+ c = *--t;
+ *t = '\0';
+ err_unboundvar (s);
+ *t = c;
+ return (-1);
+ }
+ else if (var == 0)
+ return 0;
+
+ /* We support a couple of expansions for variables that are not arrays.
+ We'll return the length of the value for v[0], and 1 for v[@] or
+ v[*]. Return 0 for everything else. */
+
+ array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
+
+ if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
+ return (array_p (var) ? array_num_elements (array) : 1);
+
+ ind = array_expand_index (t, len);
+ if (ind < 0)
+ {
+ err_badarraysub (t);
+ return (-1);
+ }
+
+ if (array_p (var))
+ t = array_reference (array, ind);
+ else
+ t = (ind == 0) ? value_cell (var) : (char *)NULL;
+
+ len = STRLEN (t);
+ return (len);
+}
+#endif /* ARRAY_VARS */
+
+static int
+valid_brace_expansion_word (name, var_is_special)
+ char *name;
+ int var_is_special;
+{
+ if (DIGIT (*name) && all_digits (name))
+ return 1;
+ else if (var_is_special)
+ return 1;
+#if defined (ARRAY_VARS)
+ else if (valid_array_reference (name))
+ return 1;
+#endif /* ARRAY_VARS */
+ else if (legal_identifier (name))
+ return 1;
+ else
+ return 0;
+}
+
+static int
+chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
+ char *name;
+ int quoted;
+ int *quoted_dollar_atp, *contains_dollar_at;
+{
+ char *temp1;
+
+ if (name == 0)
+ {
+ if (quoted_dollar_atp)
+ *quoted_dollar_atp = 0;
+ if (contains_dollar_at)
+ *contains_dollar_at = 0;
+ return 0;
+ }
+
+ /* check for $@ and $* */
+ if (name[0] == '@' && name[1] == 0)
+ {
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ return 1;
+ }
+ else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
+ {
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ return 1;
+ }
+
+ /* Now check for ${array[@]} and ${array[*]} */
+#if defined (ARRAY_VARS)
+ else if (valid_array_reference (name))
+ {
+ temp1 = xstrchr (name, '[');
+ if (temp1 && temp1[1] == '@' && temp1[2] == ']')
+ {
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ return 1;
+ } /* [ */
+ /* ${array[*]}, when unquoted, should be treated like ${array[@]},
+ which should result in separate words even when IFS is unset. */
+ if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
+ {
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
+
+/* Parameter expand NAME, and return a new string which is the expansion,
+ or NULL if there was no expansion.
+ VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
+ the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
+ NAME was found inside of a double-quoted expression. */
+static WORD_DESC *
+parameter_brace_expand_word (name, var_is_special, quoted)
+ char *name;
+ int var_is_special, quoted;
+{
+ WORD_DESC *ret;
+ char *temp, *tt;
+ intmax_t arg_index;
+ SHELL_VAR *var;
+ int atype;
+
+ ret = 0;
+ temp = 0;
+
+ /* Handle multiple digit arguments, as in ${11}. */
+ if (legal_number (name, &arg_index))
+ {
+ tt = get_dollar_var_value (arg_index);
+ if (tt)
+ temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ ? quote_string (tt)
+ : quote_escapes (tt);
+ else
+ temp = (char *)NULL;
+ FREE (tt);
+ }
+ else if (var_is_special) /* ${@} */
+ {
+ int sindex;
+ tt = (char *)xmalloc (2 + strlen (name));
+ tt[sindex = 0] = '$';
+ strcpy (tt + 1, name);
+
+ ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
+ (int *)NULL, (int *)NULL, 0);
+ free (tt);
+ }
+#if defined (ARRAY_VARS)
+ else if (valid_array_reference (name))
+ {
+ temp = array_value (name, quoted, &atype);
+ if (atype == 0 && temp)
+ temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ ? quote_string (temp)
+ : quote_escapes (temp);
+ }
+#endif
+ else if (var = find_variable (name))
+ {
+ if (var_isset (var) && invisible_p (var) == 0)
+ {
+#if defined (ARRAY_VARS)
+ temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
+#else
+ temp = value_cell (var);
+#endif
+
+ if (temp)
+ temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ ? quote_string (temp)
+ : quote_escapes (temp);
+ }
+ else
+ temp = (char *)NULL;
+ }
+ else
+ temp = (char *)NULL;
+
+ if (ret == 0)
+ {
+ ret = alloc_word_desc ();
+ ret->word = temp;
+ }
+ return ret;
+}
+
+/* Expand an indirect reference to a variable: ${!NAME} expands to the
+ value of the variable whose name is the value of NAME. */
+static WORD_DESC *
+parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
+ char *name;
+ int var_is_special, quoted;
+ int *quoted_dollar_atp, *contains_dollar_at;
+{
+ char *temp, *t;
+ WORD_DESC *w;
+
+ w = parameter_brace_expand_word (name, var_is_special, quoted);
+ t = w->word;
+ /* Have to dequote here if necessary */
+ if (t)
+ {
+ temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ ? dequote_string (t)
+ : dequote_escapes (t);
+ free (t);
+ t = temp;
+ }
+ dispose_word_desc (w);
+
+ chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
+ if (t == 0)
+ return (WORD_DESC *)NULL;
+
+ w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
+ free (t);
+
+ return w;
+}
+
+/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
+ depending on the value of C, the separating character. C can be one of
+ "-", "+", or "=". QUOTED is true if the entire brace expression occurs
+ between double quotes. */
+static WORD_DESC *
+parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
+ char *name, *value;
+ int c, quoted, *qdollaratp, *hasdollarat;
+{
+ WORD_DESC *w;
+ WORD_LIST *l;
+ char *t, *t1, *temp;
+ int hasdol;
+
+ /* If the entire expression is between double quotes, we want to treat
+ the value as a double-quoted string, with the exception that we strip
+ embedded unescaped double quotes. */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
+ {
+ hasdol = 0;
+ temp = string_extract_double_quoted (value, &hasdol, 1);
+ }
+ else
+ temp = value;
+
+ w = alloc_word_desc ();
+ hasdol = 0;
+ /* XXX was 0 not quoted */
+ l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
+ : (WORD_LIST *)0;
+ if (hasdollarat)
+ *hasdollarat = hasdol || (l && l->next);
+ if (temp != value)
+ free (temp);
+ if (l)
+ {
+ /* The expansion of TEMP returned something. We need to treat things
+ slightly differently if HASDOL is non-zero. If we have "$@", the
+ individual words have already been quoted. We need to turn them
+ into a string with the words separated by the first character of
+ $IFS without any additional quoting, so string_list_dollar_at won't
+ do the right thing. We use string_list_dollar_star instead. */
+ temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
+
+ /* If l->next is not null, we know that TEMP contained "$@", since that
+ is the only expansion that creates more than one word. */
+ if (qdollaratp && ((hasdol && quoted) || l->next))
+ *qdollaratp = 1;
+ dispose_words (l);
+ }
+ else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
+ {
+ /* The brace expansion occurred between double quotes and there was
+ a $@ in TEMP. It does not matter if the $@ is quoted, as long as
+ it does not expand to anything. In this case, we want to return
+ a quoted empty string. */
+ temp = (char *)xmalloc (2);
+ temp[0] = CTLNUL;
+ temp[1] = '\0';
+ w->flags |= W_HASQUOTEDNULL;
+ }
+ else
+ temp = (char *)NULL;
+
+ if (c == '-' || c == '+')
+ {
+ w->word = temp;
+ return w;
+ }
+
+ /* c == '=' */
+ t = temp ? savestring (temp) : savestring ("");
+ t1 = dequote_string (t);
+ free (t);
+#if defined (ARRAY_VARS)
+ if (valid_array_reference (name))
+ assign_array_element (name, t1, 0);
+ else
+#endif /* ARRAY_VARS */
+ bind_variable (name, t1, 0);
+ free (t1);
+
+ w->word = temp;
+ return w;
+}
+
+/* Deal with the right hand side of a ${name:?value} expansion in the case
+ that NAME is null or not set. If VALUE is non-null it is expanded and
+ used as the error message to print, otherwise a standard message is
+ printed. */
+static void
+parameter_brace_expand_error (name, value)
+ char *name, *value;
+{
+ WORD_LIST *l;
+ char *temp;
+
+ if (value && *value)
+ {
+ l = expand_string (value, 0);
+ temp = string_list (l);
+ report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
+ FREE (temp);
+ dispose_words (l);
+ }
+ else
+ report_error (_("%s: parameter null or not set"), name);
+
+ /* Free the data we have allocated during this expansion, since we
+ are about to longjmp out. */
+ free (name);
+ FREE (value);
+}
+
+/* Return 1 if NAME is something for which parameter_brace_expand_length is
+ OK to do. */
+static int
+valid_length_expression (name)
+ char *name;
+{
+ return (name[1] == '\0' || /* ${#} */
+ ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
+ (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
+#if defined (ARRAY_VARS)
+ valid_array_reference (name + 1) || /* ${#a[7]} */
+#endif
+ legal_identifier (name + 1)); /* ${#PS1} */
+}
+
+#if defined (HANDLE_MULTIBYTE)
+size_t
+mbstrlen (s)
+ const char *s;
+{
+ size_t clen, nc;
+ mbstate_t mbs, mbsbak;
+
+ nc = 0;
+ memset (&mbs, 0, sizeof (mbs));
+ mbsbak = mbs;
+ while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
+ {
+ if (MB_INVALIDCH(clen))
+ {
+ clen = 1; /* assume single byte */
+ mbs = mbsbak;
+ }
+
+ s += clen;
+ nc++;
+ mbsbak = mbs;
+ }
+ return nc;
+}
+#endif
+
+
+/* Handle the parameter brace expansion that requires us to return the
+ length of a parameter. */
+static intmax_t
+parameter_brace_expand_length (name)
+ char *name;
+{
+ char *t, *newname;
+ intmax_t number, arg_index;
+ WORD_LIST *list;
+#if defined (ARRAY_VARS)
+ SHELL_VAR *var;
+#endif
+
+ if (name[1] == '\0') /* ${#} */
+ number = number_of_args ();
+ else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
+ number = number_of_args ();
+ else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
+ {
+ /* Take the lengths of some of the shell's special parameters. */
+ switch (name[1])
+ {
+ case '-':
+ t = which_set_flags ();
+ break;
+ case '?':
+ t = itos (last_command_exit_value);
+ break;
+ case '$':
+ t = itos (dollar_dollar_pid);
+ break;
+ case '!':
+ if (last_asynchronous_pid == NO_PID)
+ t = (char *)NULL;
+ else
+ t = itos (last_asynchronous_pid);
+ break;
+ case '#':
+ t = itos (number_of_args ());
+ break;
+ }
+ number = STRLEN (t);
+ FREE (t);
+ }
+#if defined (ARRAY_VARS)
+ else if (valid_array_reference (name + 1))
+ number = array_length_reference (name + 1);
+#endif /* ARRAY_VARS */
+ else
+ {
+ number = 0;
+
+ if (legal_number (name + 1, &arg_index)) /* ${#1} */
+ {
+ t = get_dollar_var_value (arg_index);
+ number = MB_STRLEN (t);
+ FREE (t);
+ }
+#if defined (ARRAY_VARS)
+ else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && array_p (var))
+ {
+ t = array_reference (array_cell (var), 0);
+ number = MB_STRLEN (t);
+ }
+#endif
+ else /* ${#PS1} */
+ {
+ newname = savestring (name);
+ newname[0] = '$';
+ list = expand_string (newname, Q_DOUBLE_QUOTES);
+ t = list ? string_list (list) : (char *)NULL;
+ free (newname);
+ if (list)
+ dispose_words (list);
+
+ number = MB_STRLEN (t);
+ FREE (t);
+ }
+ }
+
+ return (number);
+}
+
+/* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
+ so we do some ad-hoc parsing of an arithmetic expression to find
+ the first DELIM, instead of using strchr(3). Two rules:
+ 1. If the substring contains a `(', read until closing `)'.
+ 2. If the substring contains a `?', read past one `:' for each `?'.
+*/
+
+static char *
+skiparith (substr, delim)
+ char *substr;
+ int delim;
+{
+ size_t sublen;
+ int skipcol, pcount, i;
+ DECLARE_MBSTATE;
+
+ sublen = strlen (substr);
+ i = skipcol = pcount = 0;
+ while (substr[i])
+ {
+ /* Balance parens */
+ if (substr[i] == LPAREN)
+ {
+ pcount++;
+ i++;
+ continue;
+ }
+ if (substr[i] == RPAREN && pcount)
+ {
+ pcount--;
+ i++;
+ continue;
+ }
+ if (pcount)
+ {
+ ADVANCE_CHAR (substr, sublen, i);
+ continue;
+ }
+
+ /* Skip one `:' for each `?' */
+ if (substr[i] == ':' && skipcol)
+ {
+ skipcol--;
+ i++;
+ continue;
+ }
+ if (substr[i] == delim)
+ break;
+ if (substr[i] == '?')
+ {
+ skipcol++;
+ i++;
+ continue;
+ }
+ ADVANCE_CHAR (substr, sublen, i);
+ }
+
+ return (substr + i);
+}
+
+/* Verify and limit the start and end of the desired substring. If
+ VTYPE == 0, a regular shell variable is being used; if it is 1,
+ then the positional parameters are being used; if it is 2, then
+ VALUE is really a pointer to an array variable that should be used.
+ Return value is 1 if both values were OK, 0 if there was a problem
+ with an invalid expression, or -1 if the values were out of range. */
+static int
+verify_substring_values (value, substr, vtype, e1p, e2p)
+ char *value, *substr;
+ int vtype;
+ intmax_t *e1p, *e2p;
+{
+ char *t, *temp1, *temp2;
+ arrayind_t len;
+ int expok;
+#if defined (ARRAY_VARS)
+ ARRAY *a;
+#endif
+
+ /* duplicate behavior of strchr(3) */
+ t = skiparith (substr, ':');
+ if (*t && *t == ':')
+ *t = '\0';
+ 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)
+ return (0);
+
+ len = -1; /* paranoia */
+ switch (vtype)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+ len = MB_STRLEN (value);
+ break;
+ case VT_POSPARMS:
+ len = number_of_args () + 1;
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ a = (ARRAY *)value;
+ /* For arrays, the first value deals with array indices. Negative
+ offsets count from one past the array's maximum index. */
+ len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
+ break;
+#endif
+ }
+
+ if (len == -1) /* paranoia */
+ return -1;
+
+ if (*e1p < 0) /* negative offsets count from end */
+ *e1p += len;
+
+ if (*e1p > len || *e1p < 0)
+ return (-1);
+
+#if defined (ARRAY_VARS)
+ /* For arrays, the second offset deals with the number of elements. */
+ if (vtype == VT_ARRAYVAR)
+ len = array_num_elements (a);
+#endif
+
+ if (t)
+ {
+ 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);
+ free (temp1);
+ if (expok == 0)
+ return (0);
+ if (*e2p < 0)
+ {
+ internal_error (_("%s: substring expression < 0"), t);
+ return (0);
+ }
+#if defined (ARRAY_VARS)
+ /* In order to deal with sparse arrays, push the intelligence about how
+ to deal with the number of elements desired down to the array-
+ specific functions. */
+ if (vtype != VT_ARRAYVAR)
+#endif
+ {
+ *e2p += *e1p; /* want E2 chars starting at E1 */
+ if (*e2p > len)
+ *e2p = len;
+ }
+ }
+ else
+ *e2p = len;
+
+ return (1);
+}
+
+/* Return the type of variable specified by VARNAME (simple variable,
+ positional param, or array variable). Also return the value specified
+ by VARNAME (value of a variable or a reference to an array element).
+ If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
+ characters in the value are quoted with CTLESC and takes appropriate
+ steps. For convenience, *VALP is set to the dequoted VALUE. */
+static int
+get_var_and_type (varname, value, quoted, varp, valp)
+ char *varname, *value;
+ int quoted;
+ SHELL_VAR **varp;
+ char **valp;
+{
+ int vtype;
+ char *temp;
+#if defined (ARRAY_VARS)
+ SHELL_VAR *v;
+#endif
+
+ /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
+ vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
+ if (vtype == VT_POSPARMS && varname[0] == '*')
+ vtype |= VT_STARSUB;
+ *varp = (SHELL_VAR *)NULL;
+
+#if defined (ARRAY_VARS)
+ if (valid_array_reference (varname))
+ {
+ v = array_variable_part (varname, &temp, (int *)0);
+ if (v && array_p (v))
+ { /* [ */
+ if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
+ {
+ vtype = VT_ARRAYVAR;
+ if (temp[0] == '*')
+ vtype |= VT_STARSUB;
+ *valp = (char *)array_cell (v);
+ }
+ else
+ {
+ vtype = VT_ARRAYMEMBER;
+ *valp = array_value (varname, 1, (int *)NULL);
+ }
+ *varp = v;
+ }
+ else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
+ {
+ vtype = VT_VARIABLE;
+ *varp = v;
+ if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ *valp = dequote_string (value);
+ else
+ *valp = dequote_escapes (value);
+ }
+ else
+ return -1;
+ }
+ else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && array_p (v))
+ {
+ vtype = VT_ARRAYMEMBER;
+ *varp = v;
+ *valp = array_reference (array_cell (v), 0);
+ }
+ else
+#endif
+ {
+ if (value && vtype == VT_VARIABLE)
+ {
+ if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ *valp = dequote_string (value);
+ else
+ *valp = dequote_escapes (value);
+ }
+ else
+ *valp = value;
+ }
+
+ return vtype;
+}
+
+/******************************************************/
+/* */
+/* Functions to extract substrings of variable values */
+/* */
+/******************************************************/
+
+#if defined (HANDLE_MULTIBYTE)
+/* Character-oriented rather than strictly byte-oriented substrings. S and
+ E, rather being strict indices into STRING, indicate character (possibly
+ multibyte character) positions that require calculation.
+ Used by the ${param:offset[:length]} expansion. */
+static char *
+mb_substring (string, s, e)
+ char *string;
+ int s, e;
+{
+ char *tt;
+ int start, stop, i, slen;
+ DECLARE_MBSTATE;
+
+ start = 0;
+ /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
+ slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
+
+ i = s;
+ while (string[start] && i--)
+ ADVANCE_CHAR (string, slen, start);
+ stop = start;
+ i = e - s;
+ while (string[stop] && i--)
+ ADVANCE_CHAR (string, slen, stop);
+ tt = substring (string, start, stop);
+ return tt;
+}
+#endif
+
+/* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
+ is `@', use the positional parameters; otherwise, use the value of
+ VARNAME. If VARNAME is an array variable, use the array elements. */
+
+static char *
+parameter_brace_substring (varname, value, substr, quoted)
+ char *varname, *value, *substr;
+ int quoted;
+{
+ intmax_t e1, e2;
+ int vtype, r, starsub;
+ char *temp, *val, *tt;
+ SHELL_VAR *v;
+
+ if (value == 0)
+ return ((char *)NULL);
+
+ this_command_name = varname;
+
+ vtype = get_var_and_type (varname, value, quoted, &v, &val);
+ if (vtype == -1)
+ return ((char *)NULL);
+
+ starsub = vtype & VT_STARSUB;
+ vtype &= ~VT_STARSUB;
+
+ r = verify_substring_values (val, substr, vtype, &e1, &e2);
+ if (r <= 0)
+ return ((r == 0) ? &expand_param_error : (char *)NULL);
+
+ switch (vtype)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1)
+ tt = mb_substring (val, e1, e2);
+ else
+#endif
+ tt = substring (val, e1, e2);
+
+ if (vtype == VT_VARIABLE)
+ FREE (val);
+ if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ temp = quote_string (tt);
+ else
+ temp = tt ? quote_escapes (tt) : (char *)NULL;
+ FREE (tt);
+ break;
+ case VT_POSPARMS:
+ tt = pos_params (varname, e1, e2, quoted);
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
+ {
+ temp = tt ? quote_escapes (tt) : (char *)NULL;
+ FREE (tt);
+ }
+ else
+ temp = tt;
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ /* We want E2 to be the number of elements desired (arrays can be sparse,
+ so verify_substring_values just returns the numbers specified and we
+ rely on array_subrange to understand how to deal with them). */
+ tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
+ {
+ temp = tt ? quote_escapes (tt) : (char *)NULL;
+ FREE (tt);
+ }
+ else
+ temp = tt;
+ break;
+#endif
+ default:
+ temp = (char *)NULL;
+ }
+
+ return temp;
+}
+
+/****************************************************************/
+/* */
+/* Functions to perform pattern substitution on variable values */
+/* */
+/****************************************************************/
+
+char *
+pat_subst (string, pat, rep, mflags)
+ char *string, *pat, *rep;
+ int mflags;
+{
+ char *ret, *s, *e, *str;
+ int rsize, rptr, l, replen, mtype;
+
+ mtype = mflags & MATCH_TYPEMASK;
+
+ /* Special cases:
+ * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
+ * with REP and return the result.
+ * 2. A null pattern with mtype == MATCH_END means to append REP to
+ * STRING and return the result.
+ */
+ if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
+ {
+ replen = STRLEN (rep);
+ l = strlen (string);
+ ret = (char *)xmalloc (replen + l + 2);
+ if (replen == 0)
+ strcpy (ret, string);
+ else if (mtype == MATCH_BEG)
+ {
+ strcpy (ret, rep);
+ strcpy (ret + replen, string);
+ }
+ else
+ {
+ strcpy (ret, string);
+ strcpy (ret + l, rep);
+ }
+ return (ret);
+ }
+
+ ret = (char *)xmalloc (rsize = 64);
+ ret[0] = '\0';
+
+ for (replen = STRLEN (rep), rptr = 0, str = string;;)
+ {
+ if (match_pattern (str, pat, mtype, &s, &e) == 0)
+ break;
+ l = s - str;
+ RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
+
+ /* OK, now copy the leading unmatched portion of the string (from
+ str to s) to ret starting at rptr (the current offset). Then copy
+ the replacement string at ret + rptr + (s - str). Increment
+ rptr (if necessary) and str and go on. */
+ if (l)
+ {
+ strncpy (ret + rptr, str, l);
+ rptr += l;
+ }
+ if (replen)
+ {
+ strncpy (ret + rptr, rep, replen);
+ rptr += replen;
+ }
+ str = e; /* e == end of match */
+
+ if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
+ break;
+
+ if (s == e)
+ e++, str++; /* avoid infinite recursion on zero-length match */
+ }
+
+ /* Now copy the unmatched portion of the input string */
+ if (*str)
+ {
+ RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
+ strcpy (ret + rptr, str);
+ }
+ else
+ ret[rptr] = '\0';
+
+ return ret;
+}
+
+/* Do pattern match and replacement on the positional parameters. */
+static char *
+pos_params_pat_subst (string, pat, rep, mflags)
+ char *string, *pat, *rep;
+ int mflags;
+{
+ WORD_LIST *save, *params;
+ WORD_DESC *w;
+ char *ret, *tt;
+
+ save = params = list_rest_of_args ();
+ if (save == 0)
+ return ((char *)NULL);
+
+ for ( ; params; params = params->next)
+ {
+ ret = pat_subst (params->word->word, pat, rep, mflags);
+ w = alloc_word_desc ();
+ w->word = ret ? ret : savestring ("");
+ dispose_word (params->word);
+ params->word = w;
+ }
+
+ if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
+ ret = string_list_dollar_star (quote_list (save));
+ else
+ ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
+ dispose_words (save);
+
+ return (ret);
+}
+
+/* Perform pattern substitution on VALUE, which is the expansion of
+ VARNAME. PATSUB is an expression supplying the pattern to match
+ and the string to substitute. QUOTED is a flags word containing
+ the type of quoting currently in effect. */
+static char *
+parameter_brace_patsub (varname, value, patsub, quoted)
+ char *varname, *value, *patsub;
+ int quoted;
+{
+ int vtype, mflags, starsub;
+ char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
+ SHELL_VAR *v;
+
+ if (value == 0)
+ return ((char *)NULL);
+
+ this_command_name = varname;
+
+ vtype = get_var_and_type (varname, value, quoted, &v, &val);
+ if (vtype == -1)
+ return ((char *)NULL);
+
+ starsub = vtype & VT_STARSUB;
+ 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. */
+ lpatsub = savestring (patsub);
+
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ mflags |= MATCH_QUOTED;
+
+ if (starsub)
+ mflags |= MATCH_STARSUB;
+
+ if (rep = quoted_strchr (lpatsub, '/', ST_BACKSL))
+ *rep++ = '\0';
+ else
+ rep = (char *)NULL;
+
+ if (rep && *rep == '\0')
+ rep = (char *)NULL;
+
+ /* Perform the same expansions on the pattern as performed by the
+ pattern removal expansions. */
+ pat = getpattern (lpatsub, quoted, 1);
+
+ if (rep)
+ {
+ if ((mflags & MATCH_QUOTED) == 0)
+ rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
+ else
+ rep = expand_string_to_string_internal (rep, quoted, expand_string_unsplit);
+ }
+
+ p = pat;
+ if (pat && pat[0] == '#' && (mflags&MATCH_GLOBREP) == 0)
+ {
+ mflags |= MATCH_BEG;
+ p++;
+ }
+ else if (pat && pat[0] == '%' && (mflags&MATCH_GLOBREP) == 0)
+ {
+ mflags |= MATCH_END;
+ p++;
+ }
+ else
+ mflags |= MATCH_ANY;
+
+ /* OK, we now want to substitute REP for PAT in VAL. If
+ flags & MATCH_GLOBREP is non-zero, the substitution is done
+ everywhere, otherwise only the first occurrence of PAT is
+ replaced. The pattern matching code doesn't understand
+ CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
+ values passed in (VT_VARIABLE) so the pattern substitution
+ code works right. We need to requote special chars after
+ we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
+ other cases if QUOTED == 0, since the posparams and arrays
+ indexed by * or @ do special things when QUOTED != 0. */
+
+ switch (vtype)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+ temp = pat_subst (val, p, rep, mflags);
+ if (vtype == VT_VARIABLE)
+ FREE (val);
+ if (temp)
+ {
+ tt = quote_escapes (temp);
+ free (temp);
+ temp = tt;
+ }
+ break;
+ case VT_POSPARMS:
+ temp = pos_params_pat_subst (val, p, rep, mflags);
+ if (temp && (mflags & MATCH_QUOTED) == 0)
+ {
+ tt = quote_escapes (temp);
+ free (temp);
+ temp = tt;
+ }
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ temp = array_patsub (array_cell (v), p, rep, mflags);
+ if (temp && (mflags & MATCH_QUOTED) == 0)
+ {
+ tt = quote_escapes (temp);
+ free (temp);
+ temp = tt;
+ }
+ break;
+#endif
+ }
+
+ FREE (pat);
+ FREE (rep);
+ free (lpatsub);
+
+ return temp;
+}
+
+/****************************************************************/
+/* */
+/* Functions to perform parameter expansion on a string */
+/* */
+/****************************************************************/
+
+/* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
+static WORD_DESC *
+parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
+ char *string;
+ int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
+{
+ int check_nullness, var_is_set, var_is_null, var_is_special;
+ int want_substring, want_indir, want_patsub;
+ char *name, *value, *temp, *temp1;
+ WORD_DESC *tdesc, *ret;
+ int t_index, sindex, c, tflag;
+ intmax_t number;
+
+ value = (char *)NULL;
+ var_is_set = var_is_null = var_is_special = check_nullness = 0;
+ want_substring = want_indir = want_patsub = 0;
+
+ sindex = *indexp;
+ t_index = ++sindex;
+ name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
+
+ ret = 0;
+ tflag = 0;
+
+ /* If the name really consists of a special variable, then make sure
+ that we have the entire name. We don't allow indirect references
+ to special variables except `#', `?', `@' and `*'. */
+ if ((sindex == t_index &&
+ (string[t_index] == '-' ||
+ string[t_index] == '?' ||
+ string[t_index] == '#')) ||
+ (sindex == t_index - 1 && string[sindex] == '!' &&
+ (string[t_index] == '#' ||
+ string[t_index] == '?' ||
+ string[t_index] == '@' ||
+ string[t_index] == '*')))
+ {
+ t_index++;
+ free (name);
+ temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
+ name = (char *)xmalloc (3 + (strlen (temp1)));
+ *name = string[sindex];
+ if (string[sindex] == '!')
+ {
+ /* indirect reference of $#, $?, $@, or $* */
+ name[1] = string[sindex + 1];
+ strcpy (name + 2, temp1);
+ }
+ else
+ strcpy (name + 1, temp1);
+ free (temp1);
+ }
+ sindex = t_index;
+
+ /* Find out what character ended the variable name. Then
+ do the appropriate thing. */
+ if (c = string[sindex])
+ sindex++;
+
+ /* If c is followed by one of the valid parameter expansion
+ characters, move past it as normal. If not, assume that
+ a substring specification is being given, and do not move
+ past it. */
+ if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
+ {
+ check_nullness++;
+ if (c = string[sindex])
+ sindex++;
+ }
+ else if (c == ':' && string[sindex] != RBRACE)
+ want_substring = 1;
+ else if (c == '/' && string[sindex] != RBRACE)
+ want_patsub = 1;
+
+ /* Catch the valid and invalid brace expressions that made it through the
+ tests above. */
+ /* ${#-} is a valid expansion and means to take the length of $-.
+ Similarly for ${#?} and ${##}... */
+ if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
+ VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
+ {
+ name = (char *)xrealloc (name, 3);
+ name[1] = c;
+ name[2] = '\0';
+ c = string[sindex++];
+ }
+
+ /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
+ if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
+ member (c, "%:=+/") && string[sindex] == RBRACE)
+ {
+ temp = (char *)NULL;
+ goto bad_substitution;
+ }
+
+ /* Indirect expansion begins with a `!'. A valid indirect expansion is
+ either a variable name, one of the positional parameters or a special
+ variable that expands to one of the positional parameters. */
+ want_indir = *name == '!' &&
+ (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
+ || VALID_INDIR_PARAM (name[1]));
+
+ /* Determine the value of this variable. */
+
+ /* Check for special variables, directly referenced. */
+ if (SPECIAL_VAR (name, want_indir))
+ var_is_special++;
+
+ /* Check for special expansion things, like the length of a parameter */
+ if (*name == '#' && name[1])
+ {
+ /* If we are not pointing at the character just after the
+ closing brace, then we haven't gotten all of the name.
+ Since it begins with a special character, this is a bad
+ substitution. Also check NAME for validity before trying
+ to go on. */
+ if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
+ {
+ temp = (char *)NULL;
+ goto bad_substitution;
+ }
+
+ number = parameter_brace_expand_length (name);
+ free (name);
+
+ *indexp = sindex;
+ if (number < 0)
+ return (&expand_wdesc_error);
+ else
+ {
+ ret = alloc_word_desc ();
+ ret->word = itos (number);
+ return ret;
+ }
+ }
+
+ /* ${@} is identical to $@. */
+ if (name[0] == '@' && name[1] == '\0')
+ {
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ }
+
+ /* Process ${!PREFIX*} expansion. */
+ if (want_indir && string[sindex - 1] == RBRACE &&
+ (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
+ legal_variable_starter ((unsigned char) name[1]))
+ {
+ char **x;
+ WORD_LIST *xlist;
+
+ temp1 = savestring (name + 1);
+ number = strlen (temp1);
+ temp1[number - 1] = '\0';
+ x = all_variables_matching_prefix (temp1);
+ xlist = strvec_to_word_list (x, 0, 0);
+ if (string[sindex - 2] == '*')
+ temp = string_list_dollar_star (xlist);
+ else
+ {
+ temp = string_list_dollar_at (xlist, quoted);
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ }
+ free (x);
+ free (xlist);
+ free (temp1);
+ *indexp = sindex;
+
+ ret = alloc_word_desc ();
+ ret->word = temp;
+ return ret;
+ }
+
+#if defined (ARRAY_VARS)
+ /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
+ if (want_indir && string[sindex - 1] == RBRACE &&
+ string[sindex - 2] == ']' && valid_array_reference (name+1))
+ {
+ char *x, *x1;
+
+ temp1 = savestring (name + 1);
+ x = array_variable_name (temp1, &x1, (int *)0); /* [ */
+ FREE (x);
+ if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
+ {
+ temp = array_keys (temp1, quoted);
+ if (x1[0] == '@')
+ {
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ }
+
+ free (temp1);
+ *indexp = sindex;
+
+ ret = alloc_word_desc ();
+ ret->word = temp;
+ return ret;
+ }
+
+ free (temp1);
+ }
+#endif /* ARRAY_VARS */
+
+ /* Make sure that NAME is valid before trying to go on. */
+ if (valid_brace_expansion_word (want_indir ? name + 1 : name,
+ var_is_special) == 0)
+ {
+ temp = (char *)NULL;
+ goto bad_substitution;
+ }
+
+ if (want_indir)
+ tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
+ else
+ tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
+
+ if (tdesc)
+ {
+ temp = tdesc->word;
+ tflag = tdesc->flags;
+ dispose_word_desc (tdesc);
+ }
+ else
+ temp = (char *)0;
+
+#if defined (ARRAY_VARS)
+ if (valid_array_reference (name))
+ chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
+#endif
+
+ var_is_set = temp != (char *)0;
+ var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
+
+ /* Get the rest of the stuff inside the braces. */
+ if (c && c != RBRACE)
+ {
+ /* Extract the contents of the ${ ... } expansion
+ according to the Posix.2 rules. */
+ value = extract_dollar_brace_string (string, &sindex, quoted, 0);
+ if (string[sindex] == RBRACE)
+ sindex++;
+ else
+ goto bad_substitution;
+ }
+ else
+ value = (char *)NULL;
+
+ *indexp = sindex;
+
+ /* If this is a substring spec, process it and add the result. */
+ if (want_substring)
+ {
+ temp1 = parameter_brace_substring (name, temp, value, quoted);
+ FREE (name);
+ FREE (value);
+ FREE (temp);
+
+ if (temp1 == &expand_param_error)
+ return (&expand_wdesc_error);
+ else if (temp1 == &expand_param_fatal)
+ return (&expand_wdesc_fatal);
+
+ ret = alloc_word_desc ();
+ ret->word = temp1;
+ return ret;
+ }
+ else if (want_patsub)
+ {
+ temp1 = parameter_brace_patsub (name, temp, value, quoted);
+ FREE (name);
+ FREE (value);
+ FREE (temp);
+
+ if (temp1 == &expand_param_error)
+ return (&expand_wdesc_error);
+ else if (temp1 == &expand_param_fatal)
+ return (&expand_wdesc_fatal);
+
+ ret = alloc_word_desc ();
+ ret->word = temp1;
+ return ret;
+ }
+
+ /* Do the right thing based on which character ended the variable name. */
+ switch (c)
+ {
+ default:
+ case '\0':
+ bad_substitution:
+ report_error (_("%s: bad substitution"), string ? string : "??");
+ FREE (value);
+ FREE (temp);
+ free (name);
+ return &expand_wdesc_error;
+
+ case RBRACE:
+ if (var_is_set == 0 && unbound_vars_is_error)
+ {
+ err_unboundvar (name);
+ FREE (value);
+ FREE (temp);
+ free (name);
+ last_command_exit_value = EXECUTION_FAILURE;
+ return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+ }
+ break;
+
+ case '#': /* ${param#[#]pattern} */
+ case '%': /* ${param%[%]pattern} */
+ if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
+ {
+ FREE (value);
+ break;
+ }
+ temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
+ free (temp);
+ free (value);
+ temp = temp1;
+ break;
+
+ case '-':
+ case '=':
+ case '?':
+ case '+':
+ if (var_is_set && var_is_null == 0)
+ {
+ /* If the operator is `+', we don't want the value of the named
+ variable for anything, just the value of the right hand side. */
+
+ if (c == '+')
+ {
+ /* XXX -- if we're double-quoted and the named variable is "$@",
+ we want to turn off any special handling of "$@" --
+ we're not using it, so whatever is on the rhs applies. */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 0;
+ if (contains_dollar_at)
+ *contains_dollar_at = 0;
+
+ FREE (temp);
+ if (value)
+ {
+ ret = parameter_brace_expand_rhs (name, value, c,
+ quoted,
+ quoted_dollar_atp,
+ contains_dollar_at);
+ /* XXX - fix up later, esp. noting presence of
+ W_HASQUOTEDNULL in ret->flags */
+ free (value);
+ }
+ else
+ temp = (char *)NULL;
+ }
+ else
+ {
+ FREE (value);
+ }
+ /* Otherwise do nothing; just use the value in TEMP. */
+ }
+ else /* VAR not set or VAR is NULL. */
+ {
+ FREE (temp);
+ temp = (char *)NULL;
+ if (c == '=' && var_is_special)
+ {
+ report_error (_("$%s: cannot assign in this way"), name);
+ free (name);
+ free (value);
+ return &expand_wdesc_error;
+ }
+ else if (c == '?')
+ {
+ parameter_brace_expand_error (name, value);
+ return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+ }
+ else if (c != '+')
+ {
+ /* XXX -- if we're double-quoted and the named variable is "$@",
+ we want to turn off any special handling of "$@" --
+ we're not using it, so whatever is on the rhs applies. */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 0;
+ if (contains_dollar_at)
+ *contains_dollar_at = 0;
+
+ ret = parameter_brace_expand_rhs (name, value, c, quoted,
+ quoted_dollar_atp,
+ contains_dollar_at);
+ /* XXX - fix up later, esp. noting presence of
+ W_HASQUOTEDNULL in tdesc->flags */
+ }
+ free (value);
+ }
+
+ break;
+ }
+ free (name);
+
+ if (ret == 0)
+ {
+ ret = alloc_word_desc ();
+ ret->flags = tflag;
+ ret->word = temp;
+ }
+ return (ret);
+}
+
+/* Expand a single ${xxx} expansion. The braces are optional. When
+ the braces are used, parameter_brace_expand() does the work,
+ possibly calling param_expand recursively. */
+static WORD_DESC *
+param_expand (string, sindex, quoted, expanded_something,
+ contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
+ pflags)
+ char *string;
+ int *sindex, quoted, *expanded_something, *contains_dollar_at;
+ int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
+{
+ char *temp, *temp1, uerror[3];
+ int zindex, t_index, expok;
+ unsigned char c;
+ intmax_t number;
+ SHELL_VAR *var;
+ WORD_LIST *list;
+ WORD_DESC *tdesc, *ret;
+ int tflag;
+
+ zindex = *sindex;
+ c = string[++zindex];
+
+ temp = (char *)NULL;
+ ret = tdesc = (WORD_DESC *)NULL;
+ tflag = 0;
+
+ /* Do simple cases first. Switch on what follows '$'. */
+ switch (c)
+ {
+ /* $0 .. $9? */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ temp1 = dollar_vars[TODIGIT (c)];
+ if (unbound_vars_is_error && temp1 == (char *)NULL)
+ {
+ uerror[0] = '$';
+ uerror[1] = c;
+ uerror[2] = '\0';
+ err_unboundvar (uerror);
+ last_command_exit_value = EXECUTION_FAILURE;
+ return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+ }
+ if (temp1)
+ temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ ? quote_string (temp1)
+ : quote_escapes (temp1);
+ else
+ temp = (char *)NULL;
+
+ break;
+
+ /* $$ -- pid of the invoking shell. */
+ case '$':
+ temp = itos (dollar_dollar_pid);
+ break;
+
+ /* $# -- number of positional parameters. */
+ case '#':
+ temp = itos (number_of_args ());
+ break;
+
+ /* $? -- return value of the last synchronous command. */
+ case '?':
+ temp = itos (last_command_exit_value);
+ break;
+
+ /* $- -- flags supplied to the shell on invocation or by `set'. */
+ case '-':
+ temp = which_set_flags ();
+ break;
+
+ /* $! -- Pid of the last asynchronous command. */
+ case '!':
+ /* If no asynchronous pids have been created, expand to nothing.
+ If `set -u' has been executed, and no async processes have
+ been created, this is an expansion error. */
+ if (last_asynchronous_pid == NO_PID)
+ {
+ if (expanded_something)
+ *expanded_something = 0;
+ temp = (char *)NULL;
+ if (unbound_vars_is_error)
+ {
+ uerror[0] = '$';
+ uerror[1] = c;
+ uerror[2] = '\0';
+ err_unboundvar (uerror);
+ last_command_exit_value = EXECUTION_FAILURE;
+ return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+ }
+ }
+ else
+ temp = itos (last_asynchronous_pid);
+ break;
+
+ /* The only difference between this and $@ is when the arg is quoted. */
+ case '*': /* `$*' */
+ list = list_rest_of_args ();
+
+ /* If there are no command-line arguments, this should just
+ disappear if there are other characters in the expansion,
+ even if it's quoted. */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
+ temp = (char *)NULL;
+ else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ {
+ /* If we have "$*" we want to make a string of the positional
+ parameters, separated by the first character of $IFS, and
+ quote the whole string, including the separators. If IFS
+ is unset, the parameters are separated by ' '; if $IFS is
+ null, the parameters are concatenated. */
+ temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
+ temp1 = quote_string (temp);
+ if (*temp == 0)
+ tflag |= W_HASQUOTEDNULL;
+ free (temp);
+ temp = temp1;
+ }
+ else
+ {
+ /* We check whether or not we're eventually going to split $* here,
+ for example when IFS is empty and we are processing the rhs of
+ an assignment statement. In that case, we don't separate the
+ arguments at all. Otherwise, if the $* is not quoted it is
+ identical to $@ */
+#if 1
+# if defined (HANDLE_MULTIBYTE)
+ if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
+# else
+ if (expand_no_split_dollar_star && ifs_firstc == 0)
+# endif
+ temp = string_list_dollar_star (list);
+ else
+ temp = string_list_dollar_at (list, quoted);
+#else
+ temp = string_list_dollar_at (list, quoted);
+#endif
+ if (expand_no_split_dollar_star == 0 && contains_dollar_at)
+ *contains_dollar_at = 1;
+ }
+
+ dispose_words (list);
+ break;
+
+ /* When we have "$@" what we want is "$1" "$2" "$3" ... This
+ means that we have to turn quoting off after we split into
+ the individually quoted arguments so that the final split
+ on the first character of $IFS is still done. */
+ case '@': /* `$@' */
+ list = list_rest_of_args ();
+
+ /* We want to flag the fact that we saw this. We can't turn
+ off quoting entirely, because other characters in the
+ string might need it (consider "\"$@\""), but we need some
+ way to signal that the final split on the first character
+ of $IFS should be done, even though QUOTED is 1. */
+ if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ *quoted_dollar_at_p = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+
+ /* We want to separate the positional parameters with the first
+ character of $IFS in case $IFS is something other than a space.
+ We also want to make sure that splitting is done no matter what --
+ according to POSIX.2, this expands to a list of the positional
+ parameters no matter what IFS is set to. */
+ temp = string_list_dollar_at (list, quoted);
+
+ dispose_words (list);
+ break;
+
+ case LBRACE:
+ tdesc = parameter_brace_expand (string, &zindex, quoted,
+ quoted_dollar_at_p,
+ contains_dollar_at);
+
+ /* Fix this later when parameter_brace_expand returns a WORD_DESC * */
+ if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
+ return (tdesc);
+ temp = tdesc ? tdesc->word : (char *)0;
+
+ /* XXX */
+ /* Quoted nulls should be removed if there is anything else
+ in the string. */
+ /* Note that we saw the quoted null so we can add one back at
+ the end of this function if there are no other characters
+ in the string, discard TEMP, and go on. The exception to
+ this is when we have "${@}" and $1 is '', since $@ needs
+ special handling. */
+ /* XXX - fix this once parameter_brace_expand returns a WORD_DESC * */
+#if 0
+ if (temp && QUOTED_NULL (temp))
+#else
+ if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
+#endif
+ {
+ if (had_quoted_null_p)
+ *had_quoted_null_p = 1;
+ if (*quoted_dollar_at_p == 0)
+ {
+ free (temp);
+ tdesc->word = temp = (char *)NULL;
+ }
+
+ }
+
+ ret = tdesc;
+ goto return0;
+
+ /* Do command or arithmetic substitution. */
+ case LPAREN:
+ /* We have to extract the contents of this paren substitution. */
+ t_index = zindex + 1;
+ temp = extract_command_subst (string, &t_index);
+ zindex = t_index;
+
+ /* For Posix.2-style `$(( ))' arithmetic substitution,
+ extract the expression and pass it to the evaluator. */
+ if (temp && *temp == LPAREN)
+ {
+ char *temp2;
+ temp1 = temp + 1;
+ temp2 = savestring (temp1);
+ t_index = strlen (temp2) - 1;
+
+ if (temp2[t_index] != RPAREN)
+ {
+ free (temp2);
+ goto comsub;
+ }
+
+ /* Cut off ending `)' */
+ 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:
+ /* No error messages. */
+ this_command_name = (char *)NULL;
+ number = evalexp (temp1, &expok);
+ free (temp);
+ free (temp1);
+ if (expok == 0)
+ {
+ if (interactive_shell == 0 && posixly_correct)
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ return (&expand_wdesc_fatal);
+ }
+ else
+ return (&expand_wdesc_error);
+ }
+ temp = itos (number);
+ break;
+ }
+
+comsub:
+ if (pflags & PF_NOCOMSUB)
+ /* we need zindex+1 because string[zindex] == RPAREN */
+ temp1 = substring (string, *sindex, zindex+1);
+ else
+ temp1 = command_substitute (temp, quoted);
+ FREE (temp);
+ temp = temp1;
+ break;
+
+ /* Do POSIX.2d9-style arithmetic substitution. This will probably go
+ away in a future bash release. */
+ case '[':
+ /* Extract the contents of this arithmetic substitution. */
+ t_index = zindex + 1;
+ temp = extract_arithmetic_subst (string, &t_index);
+ 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;
+
+ default:
+ /* Find the variable in VARIABLE_LIST. */
+ temp = (char *)NULL;
+
+ for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
+ ;
+ temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
+
+ /* If this isn't a variable name, then just output the `$'. */
+ if (temp1 == 0 || *temp1 == '\0')
+ {
+ FREE (temp1);
+ temp = (char *)xmalloc (2);
+ temp[0] = '$';
+ temp[1] = '\0';
+ if (expanded_something)
+ *expanded_something = 0;
+ goto return0;
+ }
+
+ /* If the variable exists, return its value cell. */
+ var = find_variable (temp1);
+
+ if (var && invisible_p (var) == 0 && var_isset (var))
+ {
+#if defined (ARRAY_VARS)
+ if (array_p (var))
+ {
+ temp = array_reference (array_cell (var), 0);
+ if (temp)
+ temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ ? quote_string (temp)
+ : quote_escapes (temp);
+ else if (unbound_vars_is_error)
+ goto unbound_variable;
+ }
+ else
+#endif
+ {
+ temp = value_cell (var);
+
+ temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ ? quote_string (temp)
+ : quote_escapes (temp);
+ }
+
+ free (temp1);
+
+ goto return0;
+ }
+
+ temp = (char *)NULL;
+
+unbound_variable:
+ if (unbound_vars_is_error)
+ err_unboundvar (temp1);
+ else
+ {
+ free (temp1);
+ goto return0;
+ }
+
+ free (temp1);
+ last_command_exit_value = EXECUTION_FAILURE;
+ return ((unbound_vars_is_error && interactive_shell == 0)
+ ? &expand_wdesc_fatal
+ : &expand_wdesc_error);
+ }
+
+ if (string[zindex])
+ zindex++;
+
+return0:
+ *sindex = zindex;
+
+ if (ret == 0)
+ {
+ ret = alloc_word_desc ();
+ ret->flags = tflag; /* XXX */
+ ret->word = temp;
+ }
+ return ret;
+}
+
+/* Make a word list which is the result of parameter and variable
+ expansion, command substitution, arithmetic substitution, and
+ quote removal of WORD. Return a pointer to a WORD_LIST which is
+ the result of the expansion. If WORD contains a null word, the
+ word list returned is also null.
+
+ QUOTED contains flag values defined in shell.h.
+
+ ISEXP is used to tell expand_word_internal that the word should be
+ treated as the result of an expansion. This has implications for
+ how IFS characters in the word are treated.
+
+ CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
+ they point to an integer value which receives information about expansion.
+ CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
+ EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
+ else zero.
+
+ This only does word splitting in the case of $@ expansion. In that
+ case, we split on ' '. */
+
+/* Values for the local variable quoted_state. */
+#define UNQUOTED 0
+#define PARTIALLY_QUOTED 1
+#define WHOLLY_QUOTED 2
+
+static WORD_LIST *
+expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
+ WORD_DESC *word;
+ int quoted, isexp;
+ int *contains_dollar_at;
+ int *expanded_something;
+{
+ WORD_LIST *list;
+ WORD_DESC *tword;
+
+ /* The intermediate string that we build while expanding. */
+ char *istring;
+
+ /* The current size of the above object. */
+ int istring_size;
+
+ /* Index into ISTRING. */
+ int istring_index;
+
+ /* Temporary string storage. */
+ char *temp, *temp1;
+
+ /* The text of WORD. */
+ register char *string;
+
+ /* The size of STRING. */
+ size_t string_size;
+
+ /* The index into STRING. */
+ int sindex;
+
+ /* This gets 1 if we see a $@ while quoted. */
+ int quoted_dollar_at;
+
+ /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
+ whether WORD contains no quoting characters, a partially quoted
+ string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
+ int quoted_state;
+
+ /* State flags */
+ int had_quoted_null;
+ int has_dollar_at;
+ int tflag;
+
+ int assignoff; /* If assignment, offset of `=' */
+
+ register unsigned char c; /* Current character. */
+ int t_index; /* For calls to string_extract_xxx. */
+
+ char twochars[2];
+
+ DECLARE_MBSTATE;
+
+ istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
+ istring[istring_index = 0] = '\0';
+ quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
+ quoted_state = UNQUOTED;
+
+ string = word->word;
+ if (string == 0)
+ goto finished_with_string;
+ /* Don't need the string length for the SADD... and COPY_ macros unless
+ multibyte characters are possible. */
+ string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
+
+ if (contains_dollar_at)
+ *contains_dollar_at = 0;
+
+ assignoff = -1;
+
+ /* Begin the expansion. */
+
+ for (sindex = 0; ;)
+ {
+ c = string[sindex];
+
+ /* Case on toplevel character. */
+ switch (c)
+ {
+ case '\0':
+ goto finished_with_string;
+
+ case CTLESC:
+ sindex++;
+#if HANDLE_MULTIBYTE
+ if (MB_CUR_MAX > 1 && string[sindex])
+ {
+ SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
+ }
+ else
+#endif
+ {
+ temp = (char *)xmalloc (3);
+ temp[0] = CTLESC;
+ temp[1] = c = string[sindex];
+ temp[2] = '\0';
+ }
+
+dollar_add_string:
+ if (string[sindex])
+ sindex++;
+
+add_string:
+ if (temp)
+ {
+ istring = sub_append_string (temp, istring, &istring_index, &istring_size);
+ temp = (char *)0;
+ }
+
+ break;
+
+#if defined (PROCESS_SUBSTITUTION)
+ /* Process substitution. */
+ case '<':
+ case '>':
+ {
+ if (string[++sindex] != LPAREN || (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (word->flags & W_DQUOTE) || posixly_correct)
+ {
+ sindex--; /* add_character: label increments sindex */
+ goto add_character;
+ }
+ else
+ t_index = sindex + 1; /* skip past both '<' and LPAREN */
+
+ temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
+ sindex = t_index;
+
+ /* If the process substitution specification is `<()', we want to
+ open the pipe for writing in the child and produce output; if
+ it is `>()', we want to open the pipe for reading in the child
+ and consume input. */
+ temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
+
+ FREE (temp1);
+
+ goto dollar_add_string;
+ }
+#endif /* PROCESS_SUBSTITUTION */
+
+ case '=':
+ /* Posix.2 section 3.6.1 says that tildes following `=' in words
+ which are not assignment statements are not expanded. If the
+ shell isn't in posix mode, though, we perform tilde expansion
+ on `likely candidate' unquoted assignment statements (flags
+ include W_ASSIGNMENT but not W_QUOTED). A likely candidate
+ contains an unquoted :~ or =~. Something to think about: we
+ now have a flag that says to perform tilde expansion on arguments
+ to `assignment builtins' like declare and export that look like
+ assignment statements. We now do tilde expansion on such words
+ even in POSIX mode. */
+ if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
+ goto add_character;
+ /* If we're not in posix mode or forcing assignment-statement tilde
+ expansion, note where the `=' appears in the word and prepare to
+ do tilde expansion following the first `='. */
+ if ((word->flags & W_ASSIGNMENT) &&
+ (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
+ assignoff == -1 && sindex > 0)
+ assignoff = sindex;
+ if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
+ word->flags |= W_ITILDE;
+#if 0
+ else if ((word->flags & W_ASSIGNMENT) &&
+ (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
+ string[sindex+1] == '~')
+ word->flags |= W_ITILDE;
+#endif
+ goto add_character;
+
+ case ':':
+ if (word->flags & W_NOTILDE)
+ goto add_character;
+
+ if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
+ string[sindex+1] == '~')
+ word->flags |= W_ITILDE;
+ goto add_character;
+
+ case '~':
+ /* If the word isn't supposed to be tilde expanded, or we're not
+ at the start of a word or after an unquoted : or = in an
+ assignment statement, we don't do tilde expansion. */
+ if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
+ (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
+ (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ {
+ word->flags &= ~W_ITILDE;
+ goto add_character;
+ }
+
+ if (word->flags & W_ASSIGNRHS)
+ tflag = 2;
+ else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
+ tflag = 1;
+ else
+ tflag = 0;
+
+ temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
+
+ word->flags &= ~W_ITILDE;
+
+ 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;
+ goto add_string;
+ }
+ else
+ {
+ FREE (temp);
+ goto add_character;
+ }
+
+ case '$':
+ if (expanded_something)
+ *expanded_something = 1;
+
+ has_dollar_at = 0;
+ tword = param_expand (string, &sindex, quoted, expanded_something,
+ &has_dollar_at, &quoted_dollar_at,
+ &had_quoted_null,
+ (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
+
+ if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
+ {
+ free (string);
+ free (istring);
+ return ((tword == &expand_wdesc_error) ? &expand_word_error
+ : &expand_word_fatal);
+ }
+ if (contains_dollar_at && has_dollar_at)
+ *contains_dollar_at = 1;
+
+ if (tword && (tword->flags & W_HASQUOTEDNULL))
+ had_quoted_null = 1;
+
+ temp = tword->word;
+ dispose_word_desc (tword);
+
+ goto add_string;
+ break;
+
+ case '`': /* Backquoted command substitution. */
+ {
+ t_index = sindex++;
+
+ temp = string_extract (string, &sindex, "`", EX_REQMATCH);
+ /* The test of sindex against t_index is to allow bare instances of
+ ` to pass through, for backwards compatibility. */
+ if (temp == &extract_string_error || temp == &extract_string_fatal)
+ {
+ if (sindex - 1 == t_index)
+ {
+ sindex = t_index;
+ goto add_character;
+ }
+ report_error ("bad substitution: no closing \"`\" in %s", string+t_index);
+ free (string);
+ free (istring);
+ return ((temp == &extract_string_error) ? &expand_word_error
+ : &expand_word_fatal);
+ }
+
+ if (expanded_something)
+ *expanded_something = 1;
+
+ if (word->flags & W_NOCOMSUB)
+ /* sindex + 1 because string[sindex] == '`' */
+ temp1 = substring (string, t_index, sindex + 1);
+ else
+ {
+ de_backslash (temp);
+ temp1 = command_substitute (temp, quoted);
+ }
+ FREE (temp);
+ temp = temp1;
+ goto dollar_add_string;
+ }
+
+ case '\\':
+ if (string[sindex + 1] == '\n')
+ {
+ sindex += 2;
+ continue;
+ }
+
+ c = string[++sindex];
+
+ if (quoted & Q_HERE_DOCUMENT)
+ tflag = CBSHDOC;
+ else if (quoted & Q_DOUBLE_QUOTES)
+ tflag = CBSDQUOTE;
+ else
+ tflag = 0;
+
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
+ {
+ SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
+ }
+ else if (c == 0)
+ {
+ c = CTLNUL;
+ sindex--; /* add_character: label increments sindex */
+ goto add_character;
+ }
+ else
+ {
+ SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
+ }
+
+ sindex++;
+add_twochars:
+ /* BEFORE jumping here, we need to increment sindex if appropriate */
+ RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
+ DEFAULT_ARRAY_SIZE);
+ istring[istring_index++] = twochars[0];
+ istring[istring_index++] = twochars[1];
+ istring[istring_index] = '\0';
+
+ break;
+
+ case '"':
+#if 0
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
+#else
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+#endif
+ goto add_character;
+
+ t_index = ++sindex;
+ temp = string_extract_double_quoted (string, &sindex, 0);
+
+ /* If the quotes surrounded the entire string, then the
+ whole word was quoted. */
+ quoted_state = (t_index == 1 && string[sindex] == '\0')
+ ? WHOLLY_QUOTED
+ : PARTIALLY_QUOTED;
+
+ if (temp && *temp)
+ {
+ tword = alloc_word_desc ();
+ tword->word = temp;
+
+ temp = (char *)NULL;
+
+ has_dollar_at = 0;
+ /* Need to get W_HASQUOTEDNULL flag through this function. */
+ list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
+
+ if (list == &expand_word_error || list == &expand_word_fatal)
+ {
+ free (istring);
+ free (string);
+ /* expand_word_internal has already freed temp_word->word
+ for us because of the way it prints error messages. */
+ tword->word = (char *)NULL;
+ dispose_word (tword);
+ return list;
+ }
+
+ dispose_word (tword);
+
+ /* "$@" (a double-quoted dollar-at) expands into nothing,
+ not even a NULL word, when there are no positional
+ parameters. */
+ if (list == 0 && has_dollar_at)
+ {
+ quoted_dollar_at++;
+ break;
+ }
+
+ /* If we get "$@", we know we have expanded something, so we
+ need to remember it for the final split on $IFS. This is
+ a special case; it's the only case where a quoted string
+ can expand into more than one word. It's going to come back
+ from the above call to expand_word_internal as a list with
+ a single word, in which all characters are quoted and
+ separated by blanks. What we want to do is to turn it back
+ into a list for the next piece of code. */
+ if (list)
+ dequote_list (list);
+
+ if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
+ had_quoted_null = 1;
+
+ if (has_dollar_at)
+ {
+ quoted_dollar_at++;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ if (expanded_something)
+ *expanded_something = 1;
+ }
+ }
+ else
+ {
+ /* What we have is "". This is a minor optimization. */
+ FREE (temp);
+ list = (WORD_LIST *)NULL;
+ }
+
+ /* The code above *might* return a list (consider the case of "$@",
+ where it returns "$1", "$2", etc.). We can't throw away the
+ rest of the list, and we have to make sure each word gets added
+ as quoted. We test on tresult->next: if it is non-NULL, we
+ quote the whole list, save it to a string with string_list, and
+ add that string. We don't need to quote the results of this
+ (and it would be wrong, since that would quote the separators
+ as well), so we go directly to add_string. */
+ if (list)
+ {
+ if (list->next)
+ {
+ /* Testing quoted_dollar_at makes sure that "$@" is
+ split correctly when $IFS does not contain a space. */
+ temp = quoted_dollar_at
+ ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
+ : string_list (quote_list (list));
+ dispose_words (list);
+ goto add_string;
+ }
+ else
+ {
+ temp = savestring (list->word->word);
+ tflag = list->word->flags;
+ dispose_words (list);
+
+ /* If the string is not a quoted null string, we want
+ to remove any embedded unquoted CTLNUL characters.
+ We do not want to turn quoted null strings back into
+ the empty string, though. We do this because we
+ want to remove any quoted nulls from expansions that
+ contain other characters. For example, if we have
+ x"$*"y or "x$*y" and there are no positional parameters,
+ the $* should expand into nothing. */
+ /* We use the W_HASQUOTEDNULL flag to differentiate the
+ cases: a quoted null character as above and when
+ CTLNUL is contained in the (non-null) expansion
+ of some variable. We use the had_quoted_null flag to
+ pass the value through this function to its caller. */
+ if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
+ remove_quoted_nulls (temp); /* XXX */
+ }
+ }
+ else
+ temp = (char *)NULL;
+
+ /* We do not want to add quoted nulls to strings that are only
+ partially quoted; we can throw them away. */
+ if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
+ continue;
+
+ add_quoted_string:
+
+ if (temp)
+ {
+ temp1 = temp;
+ temp = quote_string (temp);
+ free (temp1);
+ goto add_string;
+ }
+ else
+ {
+ /* Add NULL arg. */
+ c = CTLNUL;
+ sindex--; /* add_character: label increments sindex */
+ goto add_character;
+ }
+
+ /* break; */
+
+ case '\'':
+#if 0
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
+#else
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+#endif
+ goto add_character;
+
+ t_index = ++sindex;
+ temp = string_extract_single_quoted (string, &sindex);
+
+ /* If the entire STRING was surrounded by single quotes,
+ then the string is wholly quoted. */
+ quoted_state = (t_index == 1 && string[sindex] == '\0')
+ ? WHOLLY_QUOTED
+ : PARTIALLY_QUOTED;
+
+ /* If all we had was '', it is a null expansion. */
+ if (*temp == '\0')
+ {
+ free (temp);
+ temp = (char *)NULL;
+ }
+ else
+ remove_quoted_escapes (temp); /* ??? */
+
+ /* We do not want to add quoted nulls to strings that are only
+ partially quoted; such nulls are discarded. */
+ if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
+ continue;
+
+ /* If we have a quoted null expansion, add a quoted NULL to istring. */
+ if (temp == 0)
+ {
+ c = CTLNUL;
+ sindex--; /* add_character: label increments sindex */
+ goto add_character;
+ }
+ else
+ goto add_quoted_string;
+
+ /* break; */
+
+ default:
+ /* This is the fix for " $@ " */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
+ {
+ if (string[sindex]) /* from old goto dollar_add_string */
+ sindex++;
+ if (c == 0)
+ {
+ c = CTLNUL;
+ goto add_character;
+ }
+ else
+ {
+#if HANDLE_MULTIBYTE
+ if (MB_CUR_MAX > 1)
+ sindex--;
+
+ if (MB_CUR_MAX > 1)
+ {
+ SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
+ }
+ else
+#endif
+ {
+ twochars[0] = CTLESC;
+ twochars[1] = c;
+ goto add_twochars;
+ }
+ }
+ }
+
+ SADD_MBCHAR (temp, string, sindex, string_size);
+
+ add_character:
+ RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
+ DEFAULT_ARRAY_SIZE);
+ istring[istring_index++] = c;
+ istring[istring_index] = '\0';
+
+ /* Next character. */
+ sindex++;
+ }
+ }
+
+finished_with_string:
+ /* OK, we're ready to return. If we have a quoted string, and
+ quoted_dollar_at is not set, we do no splitting at all; otherwise
+ we split on ' '. The routines that call this will handle what to
+ do if nothing has been expanded. */
+
+ /* Partially and wholly quoted strings which expand to the empty
+ string are retained as an empty arguments. Unquoted strings
+ which expand to the empty string are discarded. The single
+ exception is the case of expanding "$@" when there are no
+ positional parameters. In that case, we discard the expansion. */
+
+ /* Because of how the code that handles "" and '' in partially
+ quoted strings works, we need to make ISTRING into a QUOTED_NULL
+ if we saw quoting characters, but the expansion was empty.
+ "" and '' are tossed away before we get to this point when
+ processing partially quoted strings. This makes "" and $xxx""
+ equivalent when xxx is unset. We also look to see whether we
+ saw a quoted null from a ${} expansion and add one back if we
+ need to. */
+
+ /* If we expand to nothing and there were no single or double quotes
+ in the word, we throw it away. Otherwise, we return a NULL word.
+ The single exception is for $@ surrounded by double quotes when
+ there are no positional parameters. In that case, we also throw
+ the word away. */
+
+ if (*istring == '\0')
+ {
+ if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
+ {
+ istring[0] = CTLNUL;
+ istring[1] = '\0';
+ tword = make_bare_word (istring);
+ tword->flags |= W_HASQUOTEDNULL; /* XXX */
+ list = make_word_list (tword, (WORD_LIST *)NULL);
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ tword->flags |= W_QUOTED;
+ }
+ /* According to sh, ksh, and Posix.2, if a word expands into nothing
+ and a double-quoted "$@" appears anywhere in it, then the entire
+ word is removed. */
+ else if (quoted_state == UNQUOTED || quoted_dollar_at)
+ list = (WORD_LIST *)NULL;
+#if 0
+ else
+ {
+ tword = make_bare_word (istring);
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ tword->flags |= W_QUOTED;
+ list = make_word_list (tword, (WORD_LIST *)NULL);
+ }
+#else
+ else
+ list = (WORD_LIST *)NULL;
+#endif
+ }
+ else if (word->flags & W_NOSPLIT)
+ {
+ tword = make_bare_word (istring);
+ if (word->flags & W_ASSIGNMENT)
+ tword->flags |= W_ASSIGNMENT; /* XXX */
+ if (word->flags & W_COMPASSIGN)
+ tword->flags |= W_COMPASSIGN; /* XXX */
+ if (word->flags & W_NOGLOB)
+ tword->flags |= W_NOGLOB; /* XXX */
+ if (word->flags & W_NOEXPAND)
+ tword->flags |= W_NOEXPAND; /* XXX */
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ tword->flags |= W_QUOTED;
+ if (had_quoted_null)
+ tword->flags |= W_HASQUOTEDNULL;
+ list = make_word_list (tword, (WORD_LIST *)NULL);
+ }
+ else
+ {
+ char *ifs_chars;
+
+ ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
+
+ /* If we have $@, we need to split the results no matter what. If
+ IFS is unset or NULL, string_list_dollar_at has separated the
+ positional parameters with a space, so we split on space (we have
+ set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
+ string_list_dollar_at has separated the positional parameters
+ with the first character of $IFS, so we split on $IFS. */
+ if (has_dollar_at && ifs_chars)
+ list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
+ else
+ {
+ tword = make_bare_word (istring);
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
+ tword->flags |= W_QUOTED;
+ if (word->flags & W_ASSIGNMENT)
+ tword->flags |= W_ASSIGNMENT;
+ if (word->flags & W_COMPASSIGN)
+ tword->flags |= W_COMPASSIGN;
+ if (word->flags & W_NOGLOB)
+ tword->flags |= W_NOGLOB;
+ if (word->flags & W_NOEXPAND)
+ tword->flags |= W_NOEXPAND;
+ if (had_quoted_null)
+ tword->flags |= W_HASQUOTEDNULL; /* XXX */
+ list = make_word_list (tword, (WORD_LIST *)NULL);
+ }
+ }
+
+ free (istring);
+ return (list);
+}
+
+/* **************************************************************** */
+/* */
+/* Functions for Quote Removal */
+/* */
+/* **************************************************************** */
+
+/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
+ backslash quoting rules for within double quotes or a here document. */
+char *
+string_quote_removal (string, quoted)
+ char *string;
+ int quoted;
+{
+ size_t slen;
+ char *r, *result_string, *temp, *send;
+ int sindex, tindex, dquote;
+ unsigned char c;
+ DECLARE_MBSTATE;
+
+ /* The result can be no longer than the original string. */
+ slen = strlen (string);
+ send = string + slen;
+
+ r = result_string = (char *)xmalloc (slen + 1);
+
+ for (dquote = sindex = 0; c = string[sindex];)
+ {
+ switch (c)
+ {
+ case '\\':
+ c = string[++sindex];
+ if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
+ *r++ = '\\';
+ /* FALLTHROUGH */
+
+ default:
+ SCOPY_CHAR_M (r, string, send, sindex);
+ break;
+
+ case '\'':
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
+ {
+ *r++ = c;
+ sindex++;
+ break;
+ }
+ tindex = sindex + 1;
+ temp = string_extract_single_quoted (string, &tindex);
+ if (temp)
+ {
+ strcpy (r, temp);
+ r += strlen (r);
+ free (temp);
+ }
+ sindex = tindex;
+ break;
+
+ case '"':
+ dquote = 1 - dquote;
+ sindex++;
+ break;
+ }
+ }
+ *r = '\0';
+ return (result_string);
+}
+
+#if 0
+/* UNUSED */
+/* Perform quote removal on word WORD. This allocates and returns a new
+ WORD_DESC *. */
+WORD_DESC *
+word_quote_removal (word, quoted)
+ WORD_DESC *word;
+ int quoted;
+{
+ WORD_DESC *w;
+ char *t;
+
+ t = string_quote_removal (word->word, quoted);
+ w = alloc_word_desc ();
+ w->word = t ? t : savestring ("");
+ return (w);
+}
+
+/* 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. */
+WORD_LIST *
+word_list_quote_removal (list, quoted)
+ WORD_LIST *list;
+ int quoted;
+{
+ WORD_LIST *result, *t, *tresult, *e;
+
+ for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
+ {
+ tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
+#if 0
+ result = (WORD_LIST *) list_append (result, tresult);
+#else
+ if (result == 0)
+ result = e = tresult;
+ else
+ {
+ e->next = tresult;
+ while (e->next)
+ e = e->next;
+ }
+#endif
+ }
+ return (result);
+}
+#endif
+
+/*******************************************
+ * *
+ * Functions to perform word splitting *
+ * *
+ *******************************************/
+
+void
+setifs (v)
+ SHELL_VAR *v;
+{
+ char *t;
+ unsigned char uc;
+
+ ifs_var = v;
+#if 0
+ ifs_value = v ? value_cell (v) : " \t\n";
+#else
+ ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
+#endif
+
+ /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
+ handle multibyte chars in IFS */
+ memset (ifs_cmap, '\0', sizeof (ifs_cmap));
+ for (t = ifs_value ; t && *t; t++)
+ {
+ uc = *t;
+ ifs_cmap[uc] = 1;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ if (ifs_value == 0)
+ {
+ ifs_firstc[0] = '\0';
+ ifs_firstc_len = 1;
+ }
+ else
+ {
+ size_t ifs_len;
+ ifs_len = strnlen (ifs_value, MB_CUR_MAX);
+ ifs_firstc_len = MBLEN (ifs_value, ifs_len);
+ if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
+ {
+ ifs_firstc[0] = ifs_value[0];
+ ifs_firstc[1] = '\0';
+ ifs_firstc_len = 1;
+ }
+ else
+ memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
+ }
+#else
+ ifs_firstc = ifs_value ? *ifs_value : 0;
+#endif
+}
+
+char *
+getifs ()
+{
+ return ifs_value;
+}
+
+/* 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. */
+WORD_LIST *
+word_split (w, ifs_chars)
+ WORD_DESC *w;
+ char *ifs_chars;
+{
+ WORD_LIST *result;
+
+ if (w)
+ {
+ char *xifs;
+
+ xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
+ result = list_string (w->word, xifs, w->flags & W_QUOTED);
+ }
+ else
+ result = (WORD_LIST *)NULL;
+
+ return (result);
+}
+
+/* Perform word splitting on LIST and return the RESULT. It is possible
+ to return (WORD_LIST *)NULL. */
+static WORD_LIST *
+word_list_split (list)
+ WORD_LIST *list;
+{
+ WORD_LIST *result, *t, *tresult, *e;
+
+ for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
+ {
+ tresult = word_split (t->word, ifs_value);
+#if 0
+ result = (WORD_LIST *) list_append (result, tresult);
+#else
+ if (result == 0)
+ result = e = tresult;
+ else
+ {
+ e->next = tresult;
+ while (e->next)
+ e = e->next;
+ }
+#endif
+ }
+ return (result);
+}
+
+/**************************************************
+ * *
+ * Functions to expand an entire WORD_LIST *
+ * *
+ **************************************************/
+
+/* Do any word-expansion-specific cleanup and jump to top_level */
+static void
+exp_jump_to_top_level (v)
+ int v;
+{
+ /* Cleanup code goes here. */
+ expand_no_split_dollar_star = 0; /* XXX */
+ expanding_redir = 0;
+
+ jump_to_top_level (v);
+}
+
+/* Put NLIST (which is a WORD_LIST * of only one element) at the front of
+ ELIST, and set ELIST to the new list. */
+#define PREPEND_LIST(nlist, elist) \
+ do { nlist->next = elist; elist = nlist; } while (0)
+
+/* Separate out any initial variable assignments from TLIST. If set -k has
+ been executed, remove all assignment statements from TLIST. Initial
+ variable assignments and other environment assignments are placed
+ on SUBST_ASSIGN_VARLIST. */
+static WORD_LIST *
+separate_out_assignments (tlist)
+ WORD_LIST *tlist;
+{
+ register WORD_LIST *vp, *lp;
+
+ if (!tlist)
+ return ((WORD_LIST *)NULL);
+
+ if (subst_assign_varlist)
+ dispose_words (subst_assign_varlist); /* Clean up after previous error */
+
+ subst_assign_varlist = (WORD_LIST *)NULL;
+ vp = lp = tlist;
+
+ /* Separate out variable assignments at the start of the command.
+ Loop invariant: vp->next == lp
+ Loop postcondition:
+ lp = list of words left after assignment statements skipped
+ tlist = original list of words
+ */
+ while (lp && (lp->word->flags & W_ASSIGNMENT))
+ {
+ vp = lp;
+ lp = lp->next;
+ }
+
+ /* If lp != tlist, we have some initial assignment statements.
+ We make SUBST_ASSIGN_VARLIST point to the list of assignment
+ words and TLIST point to the remaining words. */
+ if (lp != tlist)
+ {
+ subst_assign_varlist = tlist;
+ /* ASSERT(vp->next == lp); */
+ vp->next = (WORD_LIST *)NULL; /* terminate variable list */
+ tlist = lp; /* remainder of word list */
+ }
+
+ /* vp == end of variable list */
+ /* tlist == remainder of original word list without variable assignments */
+ if (!tlist)
+ /* All the words in tlist were assignment statements */
+ return ((WORD_LIST *)NULL);
+
+ /* ASSERT(tlist != NULL); */
+ /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
+
+ /* If the -k option is in effect, we need to go through the remaining
+ words, separate out the assignment words, and place them on
+ SUBST_ASSIGN_VARLIST. */
+ if (place_keywords_in_env)
+ {
+ WORD_LIST *tp; /* tp == running pointer into tlist */
+
+ tp = tlist;
+ lp = tlist->next;
+
+ /* Loop Invariant: tp->next == lp */
+ /* Loop postcondition: tlist == word list without assignment statements */
+ while (lp)
+ {
+ if (lp->word->flags & W_ASSIGNMENT)
+ {
+ /* Found an assignment statement, add this word to end of
+ subst_assign_varlist (vp). */
+ if (!subst_assign_varlist)
+ subst_assign_varlist = vp = lp;
+ else
+ {
+ vp->next = lp;
+ vp = lp;
+ }
+
+ /* Remove the word pointed to by LP from TLIST. */
+ tp->next = lp->next;
+ /* ASSERT(vp == lp); */
+ lp->next = (WORD_LIST *)NULL;
+ lp = tp->next;
+ }
+ else
+ {
+ tp = lp;
+ lp = lp->next;
+ }
+ }
+ }
+ return (tlist);
+}
+
+#define WEXP_VARASSIGN 0x001
+#define WEXP_BRACEEXP 0x002
+#define WEXP_TILDEEXP 0x004
+#define WEXP_PARAMEXP 0x008
+#define WEXP_PATHEXP 0x010
+
+/* All of the expansions, including variable assignments at the start of
+ the list. */
+#define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
+
+/* All of the expansions except variable assignments at the start of
+ the list. */
+#define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
+
+/* All of the `shell expansions': brace expansion, tilde expansion, parameter
+ expansion, command substitution, arithmetic expansion, word splitting, and
+ quote removal. */
+#define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
+
+/* 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. */
+
+WORD_LIST *
+expand_words (list)
+ WORD_LIST *list;
+{
+ return (expand_word_list_internal (list, WEXP_ALL));
+}
+
+/* Same as expand_words (), but doesn't hack variable or environment
+ variables. */
+WORD_LIST *
+expand_words_no_vars (list)
+ WORD_LIST *list;
+{
+ return (expand_word_list_internal (list, WEXP_NOVARS));
+}
+
+WORD_LIST *
+expand_words_shellexp (list)
+ WORD_LIST *list;
+{
+ return (expand_word_list_internal (list, WEXP_SHELLEXP));
+}
+
+static WORD_LIST *
+glob_expand_word_list (tlist, eflags)
+ WORD_LIST *tlist;
+ int eflags;
+{
+ char **glob_array, *temp_string;
+ register int glob_index;
+ WORD_LIST *glob_list, *output_list, *disposables, *next;
+ WORD_DESC *tword;
+
+ output_list = disposables = (WORD_LIST *)NULL;
+ glob_array = (char **)NULL;
+ while (tlist)
+ {
+ /* For each word, either globbing is attempted or the word is
+ added to orig_list. If globbing succeeds, the results are
+ added to orig_list and the word (tlist) is added to the list
+ of disposable words. If globbing fails and failed glob
+ expansions are left unchanged (the shell default), the
+ original word is added to orig_list. If globbing fails and
+ failed glob expansions are removed, the original word is
+ added to the list of disposable words. orig_list ends up
+ in reverse order and requires a call to REVERSE_LIST to
+ be set right. After all words are examined, the disposable
+ words are freed. */
+ next = tlist->next;
+
+ /* If the word isn't an assignment and contains an unquoted
+ pattern matching character, then glob it. */
+ if ((tlist->word->flags & W_NOGLOB) == 0 &&
+ unquoted_glob_pattern_p (tlist->word->word))
+ {
+ glob_array = shell_glob_filename (tlist->word->word);
+
+ /* Handle error cases.
+ I don't think we should report errors like "No such file
+ or directory". However, I would like to report errors
+ like "Read failed". */
+
+ if (glob_array == 0 || GLOB_FAILED (glob_array))
+ {
+ glob_array = (char **)xmalloc (sizeof (char *));
+ glob_array[0] = (char *)NULL;
+ }
+
+ /* Dequote the current word in case we have to use it. */
+ if (glob_array[0] == NULL)
+ {
+ temp_string = dequote_string (tlist->word->word);
+ free (tlist->word->word);
+ tlist->word->word = temp_string;
+ }
+
+ /* Make the array into a word list. */
+ glob_list = (WORD_LIST *)NULL;
+ for (glob_index = 0; glob_array[glob_index]; glob_index++)
+ {
+ tword = make_bare_word (glob_array[glob_index]);
+ tword->flags |= W_GLOBEXP; /* XXX */
+ glob_list = make_word_list (tword, glob_list);
+ }
+
+ if (glob_list)
+ {
+ output_list = (WORD_LIST *)list_append (glob_list, output_list);
+ PREPEND_LIST (tlist, disposables);
+ }
+ else if (fail_glob_expansion != 0)
+ {
+ report_error (_("no match: %s"), tlist->word->word);
+ jump_to_top_level (DISCARD);
+ }
+ else if (allow_null_glob_expansion == 0)
+ {
+ /* Failed glob expressions are left unchanged. */
+ PREPEND_LIST (tlist, output_list);
+ }
+ else
+ {
+ /* Failed glob expressions are removed. */
+ PREPEND_LIST (tlist, disposables);
+ }
+ }
+ else
+ {
+ /* Dequote the string. */
+ temp_string = dequote_string (tlist->word->word);
+ free (tlist->word->word);
+ tlist->word->word = temp_string;
+ PREPEND_LIST (tlist, output_list);
+ }
+
+ strvec_dispose (glob_array);
+ glob_array = (char **)NULL;
+
+ tlist = next;
+ }
+
+ if (disposables)
+ dispose_words (disposables);
+
+ if (output_list)
+ output_list = REVERSE_LIST (output_list, WORD_LIST *);
+
+ return (output_list);
+}
+
+#if defined (BRACE_EXPANSION)
+static WORD_LIST *
+brace_expand_word_list (tlist, eflags)
+ WORD_LIST *tlist;
+ int eflags;
+{
+ register char **expansions;
+ char *temp_string;
+ WORD_LIST *disposables, *output_list, *next;
+ WORD_DESC *w;
+ int eindex;
+
+ for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
+ {
+ next = tlist->next;
+
+ /* Only do brace expansion if the word has a brace character. If
+ not, just add the word list element to BRACES and continue. In
+ the common case, at least when running shell scripts, this will
+ degenerate to a bunch of calls to `xstrchr', and then what is
+ basically a reversal of TLIST into BRACES, which is corrected
+ by a call to REVERSE_LIST () on BRACES when the end of TLIST
+ is reached. */
+ if (xstrchr (tlist->word->word, LBRACE))
+ {
+ expansions = brace_expand (tlist->word->word);
+
+ for (eindex = 0; temp_string = expansions[eindex]; eindex++)
+ {
+ w = make_word (temp_string);
+ /* If brace expansion didn't change the word, preserve
+ the flags. We may want to preserve the flags
+ unconditionally someday -- XXX */
+ if (STREQ (temp_string, tlist->word->word))
+ w->flags = tlist->word->flags;
+ output_list = make_word_list (w, output_list);
+ free (expansions[eindex]);
+ }
+ free (expansions);
+
+ /* Add TLIST to the list of words to be freed after brace
+ expansion has been performed. */
+ PREPEND_LIST (tlist, disposables);
+ }
+ else
+ PREPEND_LIST (tlist, output_list);
+ }
+
+ if (disposables)
+ dispose_words (disposables);
+
+ if (output_list)
+ output_list = REVERSE_LIST (output_list, WORD_LIST *);
+
+ return (output_list);
+}
+#endif
+
+static WORD_LIST *
+shell_expand_word_list (tlist, eflags)
+ WORD_LIST *tlist;
+ int eflags;
+{
+ WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
+ int expanded_something, has_dollar_at;
+ char *temp_string;
+
+ /* We do tilde expansion all the time. This is what 1003.2 says. */
+ new_list = (WORD_LIST *)NULL;
+ for (orig_list = tlist; tlist; tlist = next)
+ {
+ temp_string = tlist->word->word;
+
+ next = tlist->next;
+
+#if defined (ARRAY_VARS)
+ /* If this is a compound array assignment to a builtin that accepts
+ such assignments (e.g., `declare'), take the assignment and perform
+ it separately, handling the semantics of declarations inside shell
+ functions. This avoids the double-evaluation of such arguments,
+ because `declare' does some evaluation of compound assignments on
+ its own. */
+ if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
+ {
+ int t;
+
+ t = do_word_assignment (tlist->word);
+ if (t == 0)
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ exp_jump_to_top_level (DISCARD);
+ }
+
+ /* Now transform the word as ksh93 appears to do and go on */
+ t = assignment (tlist->word->word, 0);
+ tlist->word->word[t] = '\0';
+ tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG);
+ }
+#endif
+
+ expanded_something = 0;
+ expanded = expand_word_internal
+ (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
+
+ if (expanded == &expand_word_error || expanded == &expand_word_fatal)
+ {
+ /* By convention, each time this error is returned,
+ tlist->word->word has already been freed. */
+ tlist->word->word = (char *)NULL;
+
+ /* Dispose our copy of the original list. */
+ dispose_words (orig_list);
+ /* Dispose the new list we're building. */
+ dispose_words (new_list);
+
+ last_command_exit_value = EXECUTION_FAILURE;
+ if (expanded == &expand_word_error)
+ exp_jump_to_top_level (DISCARD);
+ else
+ exp_jump_to_top_level (FORCE_EOF);
+ }
+
+ /* Don't split words marked W_NOSPLIT. */
+ if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
+ {
+ temp_list = word_list_split (expanded);
+ dispose_words (expanded);
+ }
+ else
+ {
+ /* If no parameter expansion, command substitution, process
+ substitution, or arithmetic substitution took place, then
+ do not do word splitting. We still have to remove quoted
+ null characters from the result. */
+ word_list_remove_quoted_nulls (expanded);
+ temp_list = expanded;
+ }
+
+ expanded = REVERSE_LIST (temp_list, WORD_LIST *);
+ new_list = (WORD_LIST *)list_append (expanded, new_list);
+ }
+
+ if (orig_list)
+ dispose_words (orig_list);
+
+ if (new_list)
+ new_list = REVERSE_LIST (new_list, WORD_LIST *);
+
+ return (new_list);
+}
+
+/* The workhorse for expand_words () and expand_words_no_vars ().
+ First arg is LIST, a WORD_LIST of words.
+ Second arg EFLAGS is a flags word controlling which expansions are
+ performed.
+
+ This does all of the substitutions: brace expansion, tilde expansion,
+ parameter expansion, command substitution, arithmetic expansion,
+ process substitution, word splitting, and pathname expansion, according
+ to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
+ set, or for which no expansion is done, do not undergo word splitting.
+ Words with the W_NOGLOB bit set do not undergo pathname expansion. */
+static WORD_LIST *
+expand_word_list_internal (list, eflags)
+ WORD_LIST *list;
+ int eflags;
+{
+ WORD_LIST *new_list, *temp_list;
+ int tint;
+
+ if (list == 0)
+ return ((WORD_LIST *)NULL);
+
+ garglist = new_list = copy_word_list (list);
+ if (eflags & WEXP_VARASSIGN)
+ {
+ garglist = new_list = separate_out_assignments (new_list);
+ if (new_list == 0)
+ {
+ if (subst_assign_varlist)
+ {
+ /* All the words were variable assignments, so they are placed
+ into the shell's environment. */
+ for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
+ {
+ this_command_name = (char *)NULL; /* no arithmetic errors */
+ tint = do_word_assignment (temp_list->word);
+ /* Variable assignment errors in non-interactive shells
+ running in Posix.2 mode cause the shell to exit. */
+ if (tint == 0)
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ if (interactive_shell == 0 && posixly_correct)
+ exp_jump_to_top_level (FORCE_EOF);
+ else
+ exp_jump_to_top_level (DISCARD);
+ }
+ }
+ dispose_words (subst_assign_varlist);
+ subst_assign_varlist = (WORD_LIST *)NULL;
+ }
+ return ((WORD_LIST *)NULL);
+ }
+ }
+
+ /* Begin expanding the words that remain. The expansions take place on
+ things that aren't really variable assignments. */
+
+#if defined (BRACE_EXPANSION)
+ /* Do brace expansion on this word if there are any brace characters
+ in the string. */
+ if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
+ new_list = brace_expand_word_list (new_list, eflags);
+#endif /* BRACE_EXPANSION */
+
+ /* Perform the `normal' shell expansions: tilde expansion, parameter and
+ variable substitution, command substitution, arithmetic expansion,
+ and word splitting. */
+ new_list = shell_expand_word_list (new_list, eflags);
+
+ /* Okay, we're almost done. Now let's just do some filename
+ globbing. */
+ if (new_list)
+ {
+ if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
+ /* Glob expand the word list unless globbing has been disabled. */
+ new_list = glob_expand_word_list (new_list, eflags);
+ else
+ /* Dequote the words, because we're not performing globbing. */
+ new_list = dequote_list (new_list);
+ }
+
+ if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
+ {
+ sh_wassign_func_t *assign_func;
+
+ /* If the remainder of the words expand to nothing, Posix.2 requires
+ that the variable and environment assignments affect the shell's
+ environment. */
+ assign_func = new_list ? assign_in_env : do_word_assignment;
+ tempenv_assign_error = 0;
+
+ for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
+ {
+ this_command_name = (char *)NULL;
+ tint = (*assign_func) (temp_list->word);
+ /* Variable assignment errors in non-interactive shells running
+ in Posix.2 mode cause the shell to exit. */
+ if (tint == 0)
+ {
+ if (assign_func == do_word_assignment)
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ if (interactive_shell == 0 && posixly_correct)
+ exp_jump_to_top_level (FORCE_EOF);
+ else
+ exp_jump_to_top_level (DISCARD);
+ }
+ else
+ tempenv_assign_error++;
+ }
+ }
+
+ dispose_words (subst_assign_varlist);
+ subst_assign_varlist = (WORD_LIST *)NULL;
+ }
+
+#if 0
+ tint = list_length (new_list) + 1;
+ RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
+ for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
+ glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
+ glob_argv_flags[tint] = '\0';
+#endif
+
+ return (new_list);
+}
diff --git a/subst.c~ b/subst.c~
new file mode 100644
index 00000000..45bb54d8
--- /dev/null
+++ b/subst.c~
@@ -0,0 +1,8091 @@
+/* subst.c -- The part of the shell that does parameter, command, arithmetic,
+ and globbing substitutions. */
+
+/* ``Have a little faith, there's magic in the night. You ain't a
+ beauty, but, hey, you're alright.'' */
+
+/* Copyright (C) 1987-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"
+
+#include "bashtypes.h"
+#include <stdio.h>
+#include "chartypes.h"
+#include <pwd.h>
+#include <signal.h>
+#include <errno.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include "bashansi.h"
+#include "posixstat.h"
+#include "bashintl.h"
+
+#include "shell.h"
+#include "flags.h"
+#include "jobs.h"
+#include "execute_cmd.h"
+#include "filecntl.h"
+#include "trap.h"
+#include "pathexp.h"
+#include "mailcheck.h"
+
+#include "shmbutil.h"
+
+#include "builtins/getopt.h"
+#include "builtins/common.h"
+
+#include <tilde/tilde.h>
+#include <glob/strmatch.h>
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+/* The size that strings change by. */
+#define DEFAULT_INITIAL_ARRAY_SIZE 112
+#define DEFAULT_ARRAY_SIZE 128
+
+/* Variable types. */
+#define VT_VARIABLE 0
+#define VT_POSPARMS 1
+#define VT_ARRAYVAR 2
+#define VT_ARRAYMEMBER 3
+
+#define VT_STARSUB 128 /* $* or ${array[*]} -- used to split */
+
+/* Flags for quoted_strchr */
+#define ST_BACKSL 0x01
+#define ST_CTLESC 0x02
+#define ST_SQUOTE 0x04 /* unused yet */
+#define ST_DQUOTE 0x08 /* unused yet */
+
+/* Flags for the string extraction functions. */
+#define EX_NOALLOC 0x01 /* just skip; don't return substring */
+#define EX_VARNAME 0x02 /* variable name; for string_extract () */
+#define EX_REQMATCH 0x04 /* closing/matching delimiter required */
+
+/* Flags for the `pflags' argument to param_expand() */
+#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
+
+/* These defs make it easier to use the editor. */
+#define LBRACE '{'
+#define RBRACE '}'
+#define LPAREN '('
+#define RPAREN ')'
+
+/* Evaluates to 1 if C is one of the shell's special parameters whose length
+ can be taken, but is also one of the special expansion characters. */
+#define VALID_SPECIAL_LENGTH_PARAM(c) \
+ ((c) == '-' || (c) == '?' || (c) == '#')
+
+/* Evaluates to 1 if C is one of the shell's special parameters for which an
+ indirect variable reference may be made. */
+#define VALID_INDIR_PARAM(c) \
+ ((c) == '#' || (c) == '?' || (c) == '@' || (c) == '*')
+
+/* Evaluates to 1 if C is one of the OP characters that follows the parameter
+ in ${parameter[:]OPword}. */
+#define VALID_PARAM_EXPAND_CHAR(c) (sh_syntaxtab[(unsigned char)c] & CSUBSTOP)
+
+/* Evaluates to 1 if this is one of the shell's special variables. */
+#define SPECIAL_VAR(name, wi) \
+ ((DIGIT (*name) && all_digits (name)) || \
+ (name[1] == '\0' && (sh_syntaxtab[(unsigned char)*name] & CSPECVAR)) || \
+ (wi && name[2] == '\0' && VALID_INDIR_PARAM (name[1])))
+
+/* An expansion function that takes a string and a quoted flag and returns
+ a WORD_LIST *. Used as the type of the third argument to
+ expand_string_if_necessary(). */
+typedef WORD_LIST *EXPFUNC __P((char *, int));
+
+/* Process ID of the last command executed within command substitution. */
+pid_t last_command_subst_pid = NO_PID;
+pid_t current_command_subst_pid = NO_PID;
+
+/* Variables used to keep track of the characters in IFS. */
+SHELL_VAR *ifs_var;
+char *ifs_value;
+unsigned char ifs_cmap[UCHAR_MAX + 1];
+
+#if defined (HANDLE_MULTIBYTE)
+unsigned char ifs_firstc[MB_LEN_MAX];
+size_t ifs_firstc_len;
+#else
+unsigned char ifs_firstc;
+#endif
+
+/* Extern functions and variables from different files. */
+extern int last_command_exit_value, last_command_exit_signal;
+extern int subshell_environment;
+extern int subshell_level;
+extern int eof_encountered;
+extern int return_catch_flag, return_catch_value;
+extern pid_t dollar_dollar_pid;
+extern int posixly_correct;
+extern char *this_command_name;
+extern struct fd_bitmap *current_fds_to_close;
+extern int wordexp_only;
+extern int expanding_redir;
+extern int tempenv_assign_error;
+
+/* Non-zero means to allow unmatched globbed filenames to expand to
+ a null file. */
+int allow_null_glob_expansion;
+
+/* Non-zero means to throw an error when globbing fails to match anything. */
+int fail_glob_expansion;
+
+#if 0
+/* Variables to keep track of which words in an expanded word list (the
+ output of expand_word_list_internal) are the result of globbing
+ expansions. GLOB_ARGV_FLAGS is used by execute_cmd.c.
+ (CURRENTLY UNUSED). */
+char *glob_argv_flags;
+static int glob_argv_flags_size;
+#endif
+
+static WORD_LIST expand_word_error, expand_word_fatal;
+static WORD_DESC expand_wdesc_error, expand_wdesc_fatal;
+static char expand_param_error, expand_param_fatal;
+static char extract_string_error, extract_string_fatal;
+
+/* Tell the expansion functions to not longjmp back to top_level on fatal
+ errors. Enabled when doing completion and prompt string expansion. */
+static int no_longjmp_on_fatal_error = 0;
+
+/* Set by expand_word_unsplit; used to inhibit splitting and re-joining
+ $* on $IFS, primarily when doing assignment statements. */
+static int expand_no_split_dollar_star = 0;
+
+/* Used to hold a list of variable assignments preceding a command. Global
+ so the SIGCHLD handler in jobs.c can unwind-protect it when it runs a
+ SIGCHLD trap. */
+WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
+
+/* A WORD_LIST of words to be expanded by expand_word_list_internal,
+ without any leading variable assignments. */
+static WORD_LIST *garglist = (WORD_LIST *)NULL;
+
+static char *quoted_substring __P((char *, int, int));
+static int quoted_strlen __P((char *));
+static char *quoted_strchr __P((char *, int, int));
+
+static char *expand_string_if_necessary __P((char *, int, EXPFUNC *));
+static inline char *expand_string_to_string_internal __P((char *, int, EXPFUNC *));
+static WORD_LIST *call_expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
+static WORD_LIST *expand_string_internal __P((char *, int));
+static WORD_LIST *expand_string_leave_quoted __P((char *, int));
+static WORD_LIST *expand_string_for_rhs __P((char *, int, int *, int *));
+
+static WORD_LIST *list_quote_escapes __P((WORD_LIST *));
+static char *dequote_escapes __P((char *));
+static char *make_quoted_char __P((int));
+static WORD_LIST *quote_list __P((WORD_LIST *));
+static WORD_LIST *dequote_list __P((WORD_LIST *));
+static char *remove_quoted_escapes __P((char *));
+static char *remove_quoted_nulls __P((char *));
+
+static int unquoted_substring __P((char *, char *));
+static int unquoted_member __P((int, char *));
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *do_compound_assignment __P((char *, char *, int));
+#endif
+static int do_assignment_internal __P((const WORD_DESC *, int));
+
+static char *string_extract_verbatim __P((char *, size_t, int *, char *));
+static char *string_extract __P((char *, int *, char *, int));
+static char *string_extract_double_quoted __P((char *, int *, int));
+static inline char *string_extract_single_quoted __P((char *, int *));
+static inline int skip_single_quoted __P((char *, size_t, int));
+static int skip_double_quoted __P((char *, size_t, int));
+static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
+static char *extract_dollar_brace_string __P((char *, int *, int, int));
+
+static char *pos_params __P((char *, int, int, int));
+
+static unsigned char *mb_getcharlens __P((char *, int));
+
+static char *remove_upattern __P((char *, char *, int));
+#if defined (HANDLE_MULTIBYTE)
+# if !defined (HAVE_WCSDUP)
+static wchar_t *wcsdup __P((wchar_t *));
+# endif
+static wchar_t *remove_wpattern __P((wchar_t *, size_t, wchar_t *, int));
+#endif
+static char *remove_pattern __P((char *, char *, int));
+
+static int match_pattern_char __P((char *, char *));
+static int match_upattern __P((char *, char *, int, char **, char **));
+#if defined (HANDLE_MULTIBYTE)
+static int match_pattern_wchar __P((wchar_t *, wchar_t *));
+static int match_wpattern __P((wchar_t *, char **, size_t, wchar_t *, int, char **, char **));
+#endif
+static int match_pattern __P((char *, char *, int, char **, char **));
+static int getpatspec __P((int, char *));
+static char *getpattern __P((char *, int, int));
+static char *variable_remove_pattern __P((char *, char *, int, int));
+static char *list_remove_pattern __P((WORD_LIST *, char *, int, int, int));
+static char *parameter_list_remove_pattern __P((int, char *, int, int));
+#ifdef ARRAY_VARS
+static char *array_remove_pattern __P((ARRAY *, char *, int, char *, int));
+#endif
+static char *parameter_brace_remove_pattern __P((char *, char *, char *, int, int));
+
+static char *process_substitute __P((char *, int));
+
+static char *read_comsub __P((int, int));
+
+#ifdef ARRAY_VARS
+static arrayind_t array_length_reference __P((char *));
+#endif
+
+static int valid_brace_expansion_word __P((char *, int));
+static int chk_atstar __P((char *, int, int *, int *));
+
+static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
+static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
+static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
+static void parameter_brace_expand_error __P((char *, char *));
+
+static int valid_length_expression __P((char *));
+static intmax_t parameter_brace_expand_length __P((char *));
+
+static char *skiparith __P((char *, int));
+static int verify_substring_values __P((char *, char *, int, intmax_t *, intmax_t *));
+static int get_var_and_type __P((char *, char *, int, SHELL_VAR **, char **));
+static char *mb_substring __P((char *, int, int));
+static char *parameter_brace_substring __P((char *, char *, char *, int));
+
+static char *pos_params_pat_subst __P((char *, char *, char *, int));
+
+static char *parameter_brace_patsub __P((char *, char *, char *, int));
+
+static WORD_DESC *parameter_brace_expand __P((char *, int *, int, int *, int *));
+static WORD_DESC *param_expand __P((char *, int *, int, int *, int *, int *, int *, int));
+
+static WORD_LIST *expand_word_internal __P((WORD_DESC *, int, int, int *, int *));
+
+static WORD_LIST *word_list_split __P((WORD_LIST *));
+
+static void exp_jump_to_top_level __P((int));
+
+static WORD_LIST *separate_out_assignments __P((WORD_LIST *));
+static WORD_LIST *glob_expand_word_list __P((WORD_LIST *, int));
+#ifdef BRACE_EXPANSION
+static WORD_LIST *brace_expand_word_list __P((WORD_LIST *, int));
+#endif
+static WORD_LIST *shell_expand_word_list __P((WORD_LIST *, int));
+static WORD_LIST *expand_word_list_internal __P((WORD_LIST *, int));
+
+/* **************************************************************** */
+/* */
+/* Utility Functions */
+/* */
+/* **************************************************************** */
+
+#ifdef INCLUDE_UNUSED
+static char *
+quoted_substring (string, start, end)
+ char *string;
+ int start, end;
+{
+ register int len, l;
+ register char *result, *s, *r;
+
+ len = end - start;
+
+ /* Move to string[start], skipping quoted characters. */
+ for (s = string, l = 0; *s && l < start; )
+ {
+ if (*s == CTLESC)
+ {
+ s++;
+ continue;
+ }
+ l++;
+ if (*s == 0)
+ break;
+ }
+
+ r = result = (char *)xmalloc (2*len + 1); /* save room for quotes */
+
+ /* Copy LEN characters, including quote characters. */
+ s = string + l;
+ for (l = 0; l < len; s++)
+ {
+ if (*s == CTLESC)
+ *r++ = *s++;
+ *r++ = *s;
+ l++;
+ if (*s == 0)
+ break;
+ }
+ *r = '\0';
+ return result;
+}
+#endif
+
+#ifdef INCLUDE_UNUSED
+/* Return the length of S, skipping over quoted characters */
+static int
+quoted_strlen (s)
+ char *s;
+{
+ register char *p;
+ int i;
+
+ i = 0;
+ for (p = s; *p; p++)
+ {
+ if (*p == CTLESC)
+ {
+ p++;
+ if (*p == 0)
+ return (i + 1);
+ }
+ i++;
+ }
+
+ return i;
+}
+#endif
+
+/* Find the first occurrence of character C in string S, obeying shell
+ quoting rules. If (FLAGS & ST_BACKSL) is non-zero, backslash-escaped
+ characters are skipped. If (FLAGS & ST_CTLESC) is non-zero, characters
+ escaped with CTLESC are skipped. */
+static char *
+quoted_strchr (s, c, flags)
+ char *s;
+ int c, flags;
+{
+ register char *p;
+
+ for (p = s; *p; p++)
+ {
+ if (((flags & ST_BACKSL) && *p == '\\')
+ || ((flags & ST_CTLESC) && *p == CTLESC))
+ {
+ p++;
+ if (*p == '\0')
+ return ((char *)NULL);
+ continue;
+ }
+ else if (*p == c)
+ return p;
+ }
+ return ((char *)NULL);
+}
+
+/* Return 1 if CHARACTER appears in an unquoted portion of
+ STRING. Return 0 otherwise. CHARACTER must be a single-byte character. */
+static int
+unquoted_member (character, string)
+ int character;
+ char *string;
+{
+ size_t slen;
+ int sindex, c;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ sindex = 0;
+ while (c = string[sindex])
+ {
+ if (c == character)
+ return (1);
+
+ switch (c)
+ {
+ default:
+ ADVANCE_CHAR (string, slen, sindex);
+ break;
+
+ case '\\':
+ sindex++;
+ if (string[sindex])
+ ADVANCE_CHAR (string, slen, sindex);
+ break;
+
+ case '\'':
+ sindex = skip_single_quoted (string, slen, ++sindex);
+ break;
+
+ case '"':
+ sindex = skip_double_quoted (string, slen, ++sindex);
+ break;
+ }
+ }
+ return (0);
+}
+
+/* Return 1 if SUBSTR appears in an unquoted portion of STRING. */
+static int
+unquoted_substring (substr, string)
+ char *substr, *string;
+{
+ size_t slen;
+ int sindex, c, sublen;
+ DECLARE_MBSTATE;
+
+ if (substr == 0 || *substr == '\0')
+ return (0);
+
+ slen = strlen (string);
+ sublen = strlen (substr);
+ for (sindex = 0; c = string[sindex]; )
+ {
+ if (STREQN (string + sindex, substr, sublen))
+ return (1);
+
+ switch (c)
+ {
+ case '\\':
+ sindex++;
+
+ if (string[sindex])
+ ADVANCE_CHAR (string, slen, sindex);
+ break;
+
+ case '\'':
+ sindex = skip_single_quoted (string, slen, ++sindex);
+ break;
+
+ case '"':
+ sindex = skip_double_quoted (string, slen, ++sindex);
+ break;
+
+ default:
+ ADVANCE_CHAR (string, slen, sindex);
+ break;
+ }
+ }
+ return (0);
+}
+
+/* Most of the substitutions must be done in parallel. In order
+ to avoid using tons of unclear goto's, I have some functions
+ for manipulating malloc'ed strings. They all take INDX, a
+ pointer to an integer which is the offset into the string
+ where manipulation is taking place. They also take SIZE, a
+ pointer to an integer which is the current length of the
+ character array for this string. */
+
+/* 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 freeing it.
+ Returns TARGET in case the location has changed. */
+INLINE char *
+sub_append_string (source, target, indx, size)
+ char *source, *target;
+ int *indx, *size;
+{
+ if (source)
+ {
+ int srclen, n;
+
+ srclen = STRLEN (source);
+ if (srclen >= (int)(*size - *indx))
+ {
+ n = srclen + *indx;
+ n = (n + DEFAULT_ARRAY_SIZE) - (n % DEFAULT_ARRAY_SIZE);
+ target = (char *)xrealloc (target, (*size = n));
+ }
+
+ FASTCOPY (source, target + *indx, srclen);
+ *indx += srclen;
+ target[*indx] = '\0';
+
+ free (source);
+ }
+ return (target);
+}
+
+#if 0
+/* UNUSED */
+/* Append the textual representation of NUMBER to TARGET.
+ INDX and SIZE are as in SUB_APPEND_STRING. */
+char *
+sub_append_number (number, target, indx, size)
+ intmax_t number;
+ int *indx, *size;
+ char *target;
+{
+ char *temp;
+
+ temp = itos (number);
+ return (sub_append_string (temp, target, indx, size));
+}
+#endif
+
+/* Extract a substring from STRING, starting at SINDEX and ending with
+ one of the characters in CHARLIST. Don't make the ending character
+ part of the string. Leave SINDEX pointing at the ending character.
+ Understand about backslashes in the string. If (flags & EX_VARNAME)
+ is non-zero, and array variables have been compiled into the shell,
+ everything between a `[' and a corresponding `]' is skipped over.
+ If (flags & EX_NOALLOC) is non-zero, don't return the substring, just
+ update SINDEX. If (flags & EX_REQMATCH) is non-zero, the string must
+ contain a closing character from CHARLIST. */
+static char *
+string_extract (string, sindex, charlist, flags)
+ char *string;
+ int *sindex;
+ char *charlist;
+ int flags;
+{
+ register int c, i;
+ int found;
+ size_t slen;
+ char *temp;
+ DECLARE_MBSTATE;
+
+ slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
+ i = *sindex;
+ found = 0;
+ while (c = string[i])
+ {
+ if (c == '\\')
+ {
+ if (string[i + 1])
+ i++;
+ else
+ break;
+ }
+#if defined (ARRAY_VARS)
+ else if ((flags & EX_VARNAME) && c == '[')
+ {
+ int ni;
+ /* If this is an array subscript, skip over it and continue. */
+ ni = skipsubscript (string, i);
+ if (string[ni] == ']')
+ i = ni;
+ }
+#endif
+ else if (MEMBER (c, charlist))
+ {
+ found = 1;
+ break;
+ }
+
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ /* If we had to have a matching delimiter and didn't find one, return an
+ error and let the caller deal with it. */
+ if ((flags & EX_REQMATCH) && found == 0)
+ {
+ *sindex = i;
+ return (&extract_string_error);
+ }
+
+ temp = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
+ *sindex = i;
+
+ return (temp);
+}
+
+/* Extract the contents of STRING as if it is enclosed in double quotes.
+ SINDEX, when passed in, is the offset of the character immediately
+ following the opening double quote; on exit, SINDEX is left pointing after
+ the closing double quote. If STRIPDQ is non-zero, unquoted double
+ quotes are stripped and the string is terminated by a null byte.
+ Backslashes between the embedded double quotes are processed. If STRIPDQ
+ is zero, an unquoted `"' terminates the string. */
+static char *
+string_extract_double_quoted (string, sindex, stripdq)
+ char *string;
+ int *sindex, stripdq;
+{
+ size_t slen;
+ char *send;
+ int j, i, t;
+ unsigned char c;
+ char *temp, *ret; /* The new string we return. */
+ int pass_next, backquote, si; /* State variables for the machine. */
+ int dquote;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string + *sindex) + *sindex;
+ send = string + slen;
+
+ pass_next = backquote = dquote = 0;
+ temp = (char *)xmalloc (1 + slen - *sindex);
+
+ j = 0;
+ i = *sindex;
+ while (c = string[i])
+ {
+ /* Process a character that was quoted by a backslash. */
+ if (pass_next)
+ {
+ /* Posix.2 sez:
+
+ ``The backslash shall retain its special meaning as an escape
+ character only when followed by one of the characters:
+ $ ` " \ <newline>''.
+
+ If STRIPDQ is zero, we handle the double quotes here and let
+ expand_word_internal handle the rest. If STRIPDQ is non-zero,
+ we have already been through one round of backslash stripping,
+ and want to strip these backslashes only if DQUOTE is non-zero,
+ indicating that we are inside an embedded double-quoted string. */
+
+ /* If we are in an embedded quoted string, then don't strip
+ backslashes before characters for which the backslash
+ retains its special meaning, but remove backslashes in
+ front of other characters. If we are not in an
+ embedded quoted string, don't strip backslashes at all.
+ This mess is necessary because the string was already
+ surrounded by double quotes (and sh has some really weird
+ quoting rules).
+ The returned string will be run through expansion as if
+ it were double-quoted. */
+ if ((stripdq == 0 && c != '"') ||
+ (stripdq && ((dquote && (sh_syntaxtab[c] & CBSDQUOTE)) || dquote == 0)))
+ temp[j++] = '\\';
+ pass_next = 0;
+
+add_one_character:
+ COPY_CHAR_I (temp, j, string, send, i);
+ continue;
+ }
+
+ /* A backslash protects the next character. The code just above
+ handles preserving the backslash in front of any character but
+ a double quote. */
+ if (c == '\\')
+ {
+ pass_next++;
+ i++;
+ continue;
+ }
+
+ /* Inside backquotes, ``the portion of the quoted string from the
+ initial backquote and the characters up to the next backquote
+ that is not preceded by a backslash, having escape characters
+ removed, defines that command''. */
+ if (backquote)
+ {
+ if (c == '`')
+ backquote = 0;
+ temp[j++] = c;
+ i++;
+ continue;
+ }
+
+ if (c == '`')
+ {
+ temp[j++] = c;
+ backquote++;
+ i++;
+ continue;
+ }
+
+ /* Pass everything between `$(' and the matching `)' or a quoted
+ ${ ... } pair through according to the Posix.2 specification. */
+ if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
+ {
+ int free_ret = 1;
+
+ si = i + 2;
+ if (string[i + 1] == LPAREN)
+ ret = extract_delimited_string (string, &si, "$(", "(", ")", 0); /*)*/
+ else
+ ret = extract_dollar_brace_string (string, &si, 1, 0);
+
+ temp[j++] = '$';
+ temp[j++] = string[i + 1];
+
+ /* Just paranoia; ret will not be 0 unless no_longjmp_on_fatal_error
+ is set. */
+ if (ret == 0 && no_longjmp_on_fatal_error)
+ {
+ free_ret = 0;
+ ret = string + i + 2;
+ }
+
+ for (t = 0; ret[t]; t++, j++)
+ temp[j] = ret[t];
+ temp[j] = string[si];
+
+ if (string[si])
+ {
+ j++;
+ i = si + 1;
+ }
+ else
+ i = si;
+
+ if (free_ret)
+ free (ret);
+ continue;
+ }
+
+ /* Add any character but a double quote to the quoted string we're
+ accumulating. */
+ if (c != '"')
+ goto add_one_character;
+
+ /* c == '"' */
+ if (stripdq)
+ {
+ dquote ^= 1;
+ i++;
+ continue;
+ }
+
+ break;
+ }
+ temp[j] = '\0';
+
+ /* Point to after the closing quote. */
+ if (c)
+ i++;
+ *sindex = i;
+
+ return (temp);
+}
+
+/* This should really be another option to string_extract_double_quoted. */
+static int
+skip_double_quoted (string, slen, sind)
+ char *string;
+ size_t slen;
+ int sind;
+{
+ int c, i;
+ char *ret;
+ int pass_next, backquote, si;
+ DECLARE_MBSTATE;
+
+ pass_next = backquote = 0;
+ i = sind;
+ while (c = string[i])
+ {
+ if (pass_next)
+ {
+ pass_next = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '\\')
+ {
+ pass_next++;
+ i++;
+ continue;
+ }
+ else if (backquote)
+ {
+ if (c == '`')
+ backquote = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '`')
+ {
+ backquote++;
+ i++;
+ continue;
+ }
+ else if (c == '$' && ((string[i + 1] == LPAREN) || (string[i + 1] == LBRACE)))
+ {
+ si = i + 2;
+ if (string[i + 1] == LPAREN)
+ ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
+ else
+ ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
+
+ i = si + 1;
+ continue;
+ }
+ else if (c != '"')
+ {
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else
+ break;
+ }
+
+ if (c)
+ i++;
+
+ return (i);
+}
+
+/* Extract the contents of STRING as if it is enclosed in single quotes.
+ SINDEX, when passed in, is the offset of the character immediately
+ following the opening single quote; on exit, SINDEX is left pointing after
+ the closing single quote. */
+static inline char *
+string_extract_single_quoted (string, sindex)
+ char *string;
+ int *sindex;
+{
+ register int i;
+ size_t slen;
+ char *t;
+ DECLARE_MBSTATE;
+
+ /* Don't need slen for ADVANCE_CHAR unless multibyte chars possible. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 0;
+ i = *sindex;
+ while (string[i] && string[i] != '\'')
+ ADVANCE_CHAR (string, slen, i);
+
+ t = substring (string, *sindex, i);
+
+ if (string[i])
+ i++;
+ *sindex = i;
+
+ return (t);
+}
+
+static inline int
+skip_single_quoted (string, slen, sind)
+ char *string;
+ size_t slen;
+ int sind;
+{
+ register int c;
+ DECLARE_MBSTATE;
+
+ c = sind;
+ while (string[c] && string[c] != '\'')
+ ADVANCE_CHAR (string, slen, c);
+
+ if (string[c])
+ c++;
+ return c;
+}
+
+/* Just like string_extract, but doesn't hack backslashes or any of
+ that other stuff. Obeys CTLESC quoting. Used to do splitting on $IFS. */
+static char *
+string_extract_verbatim (string, slen, sindex, charlist)
+ char *string;
+ size_t slen;
+ int *sindex;
+ char *charlist;
+{
+ register int i = *sindex;
+#if defined (HANDLE_MULTIBYTE)
+ size_t clen;
+ wchar_t *wcharlist;
+#endif
+ int c;
+ char *temp;
+ DECLARE_MBSTATE;
+
+ if (charlist[0] == '\'' && charlist[1] == '\0')
+ {
+ temp = string_extract_single_quoted (string, sindex);
+ --*sindex; /* leave *sindex at separator character */
+ return temp;
+ }
+
+ i = *sindex;
+#if 0
+ /* See how the MBLEN and ADVANCE_CHAR macros work to understand why we need
+ this only if MB_CUR_MAX > 1. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string + *sindex) + *sindex : 1;
+#endif
+#if defined (HANDLE_MULTIBYTE)
+ clen = strlen (charlist);
+ wcharlist = 0;
+#endif
+ while (c = string[i])
+ {
+#if defined (HANDLE_MULTIBYTE)
+ size_t mblength;
+#endif
+ if (c == CTLESC)
+ {
+ i += 2;
+ continue;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ mblength = MBLEN (string + i, slen - i);
+ if (mblength > 1)
+ {
+ wchar_t wc;
+ mblength = mbtowc (&wc, string + i, slen - i);
+ if (MB_INVALIDCH (mblength))
+ {
+ if (MEMBER (c, charlist))
+ break;
+ }
+ else
+ {
+ if (wcharlist == 0)
+ {
+ size_t len;
+ len = mbstowcs (wcharlist, charlist, 0);
+ if (len == -1)
+ len = 0;
+ wcharlist = xmalloc ((sizeof (wchar_t) * len) + 1);
+ mbstowcs (wcharlist, charlist, len);
+ }
+
+ if (wcschr (wcharlist, wc))
+ break;
+ }
+ }
+ else
+#endif
+ if (MEMBER (c, charlist))
+ break;
+
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ FREE (wcharlist);
+#endif
+
+ temp = substring (string, *sindex, i);
+ *sindex = i;
+
+ return (temp);
+}
+
+/* Extract the $( construct in STRING, and return a new string.
+ Start extracting at (SINDEX) as if we had just seen "$(".
+ Make (SINDEX) get the position of the matching ")". ) */
+char *
+extract_command_subst (string, sindex)
+ char *string;
+ int *sindex;
+{
+ return (extract_delimited_string (string, sindex, "$(", "(", ")", 0)); /*)*/
+}
+
+/* Extract the $[ construct in STRING, and return a new string. (])
+ Start extracting at (SINDEX) as if we had just seen "$[".
+ Make (SINDEX) get the position of the matching "]". */
+char *
+extract_arithmetic_subst (string, sindex)
+ char *string;
+ int *sindex;
+{
+ return (extract_delimited_string (string, sindex, "$[", "[", "]", 0)); /*]*/
+}
+
+#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 of the matching ")". */ /*))*/
+char *
+extract_process_subst (string, starter, sindex)
+ char *string;
+ char *starter;
+ int *sindex;
+{
+ return (extract_delimited_string (string, sindex, starter, "(", ")", 0));
+}
+#endif /* PROCESS_SUBSTITUTION */
+
+#if defined (ARRAY_VARS)
+/* This can be fooled by unquoted right parens in the passed string. If
+ each caller verifies that the last character in STRING is a right paren,
+ we don't even need to call extract_delimited_string. */
+char *
+extract_array_assignment_list (string, sindex)
+ char *string;
+ int *sindex;
+{
+ int slen;
+ char *ret;
+
+ slen = strlen (string); /* ( */
+ if (string[slen - 1] == ')')
+ {
+ ret = substring (string, *sindex, slen - 1);
+ *sindex = slen - 1;
+ return ret;
+ }
+ return 0;
+}
+#endif
+
+/* Extract and create a new string from the contents of STRING, a
+ character string delimited with OPENER and CLOSER. SINDEX is
+ the address of an int describing the current offset in STRING;
+ it should point to just after the first OPENER found. On exit,
+ SINDEX gets the position of the last character of the matching CLOSER.
+ If OPENER is more than a single character, ALT_OPENER, if non-null,
+ contains a character string that can also match CLOSER and thus
+ needs to be skipped. */
+static char *
+extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
+ char *string;
+ int *sindex;
+ char *opener, *alt_opener, *closer;
+ int flags;
+{
+ int i, c, si;
+ size_t slen;
+ char *t, *result;
+ int pass_character, nesting_level;
+ int len_closer, len_opener, len_alt_opener;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string + *sindex) + *sindex;
+ len_opener = STRLEN (opener);
+ len_alt_opener = STRLEN (alt_opener);
+ len_closer = STRLEN (closer);
+
+ pass_character = 0;
+
+ nesting_level = 1;
+ i = *sindex;
+
+ while (nesting_level)
+ {
+ c = string[i];
+
+ if (c == 0)
+ break;
+
+ if (pass_character) /* previous char was backslash */
+ {
+ pass_character = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+
+ if (c == CTLESC || c == '\\')
+ {
+ pass_character++;
+ i++;
+ continue;
+ }
+
+ /* Process a nested OPENER. */
+ if (STREQN (string + i, opener, len_opener))
+ {
+ si = i + len_opener;
+ t = extract_delimited_string (string, &si, opener, alt_opener, closer, flags|EX_NOALLOC);
+ i = si + 1;
+ continue;
+ }
+
+ /* Process a nested ALT_OPENER */
+ if (len_alt_opener && STREQN (string + i, alt_opener, len_alt_opener))
+ {
+ si = i + len_alt_opener;
+ t = extract_delimited_string (string, &si, alt_opener, alt_opener, closer, flags|EX_NOALLOC);
+ i = si + 1;
+ continue;
+ }
+
+ /* If the current substring terminates the delimited string, decrement
+ the nesting level. */
+ if (STREQN (string + i, closer, len_closer))
+ {
+ i += len_closer - 1; /* move to last byte of the closer */
+ nesting_level--;
+ if (nesting_level == 0)
+ break;
+ }
+
+ /* Pass old-style command substitution through verbatim. */
+ if (c == '`')
+ {
+ si = i + 1;
+ t = string_extract (string, &si, "`", flags|EX_NOALLOC);
+ i = si + 1;
+ continue;
+ }
+
+ /* Pass single-quoted and double-quoted strings through verbatim. */
+ if (c == '\'' || c == '"')
+ {
+ si = i + 1;
+ i = (c == '\'') ? skip_single_quoted (string, slen, si)
+ : skip_double_quoted (string, slen, si);
+ continue;
+ }
+
+ /* move past this character, which was not special. */
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ if (c == 0 && nesting_level)
+ {
+ if (no_longjmp_on_fatal_error == 0)
+ {
+ report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
+ last_command_exit_value = EXECUTION_FAILURE;
+ exp_jump_to_top_level (DISCARD);
+ }
+ else
+ {
+ *sindex = i;
+ return (char *)NULL;
+ }
+ }
+
+ si = i - *sindex - len_closer + 1;
+ if (flags & EX_NOALLOC)
+ result = (char *)NULL;
+ else
+ {
+ result = (char *)xmalloc (1 + si);
+ strncpy (result, string + *sindex, si);
+ result[si] = '\0';
+ }
+ *sindex = i;
+
+ return (result);
+}
+
+/* Extract a parameter expansion expression within ${ and } from STRING.
+ Obey the Posix.2 rules for finding the ending `}': count braces while
+ skipping over enclosed quoted strings and command substitutions.
+ SINDEX is the address of an int describing the current offset in STRING;
+ it should point to just after the first `{' found. On exit, SINDEX
+ gets the position of the matching `}'. QUOTED is non-zero if this
+ occurs inside double quotes. */
+/* XXX -- this is very similar to extract_delimited_string -- XXX */
+static char *
+extract_dollar_brace_string (string, sindex, quoted, flags)
+ char *string;
+ int *sindex, quoted, flags;
+{
+ register int i, c;
+ size_t slen;
+ int pass_character, nesting_level, si;
+ char *result, *t;
+ DECLARE_MBSTATE;
+
+ pass_character = 0;
+ nesting_level = 1;
+ slen = strlen (string + *sindex) + *sindex;
+
+ i = *sindex;
+ while (c = string[i])
+ {
+ if (pass_character)
+ {
+ pass_character = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+
+ /* CTLESCs and backslashes quote the next character. */
+ if (c == CTLESC || c == '\\')
+ {
+ pass_character++;
+ i++;
+ continue;
+ }
+
+ if (string[i] == '$' && string[i+1] == LBRACE)
+ {
+ nesting_level++;
+ i += 2;
+ continue;
+ }
+
+ if (c == RBRACE)
+ {
+ nesting_level--;
+ if (nesting_level == 0)
+ break;
+ i++;
+ continue;
+ }
+
+ /* Pass the contents of old-style command substitutions through
+ verbatim. */
+ if (c == '`')
+ {
+ si = i + 1;
+ t = string_extract (string, &si, "`", flags|EX_NOALLOC);
+ i = si + 1;
+ continue;
+ }
+
+ /* Pass the contents of new-style command substitutions and
+ arithmetic substitutions through verbatim. */
+ if (string[i] == '$' && string[i+1] == LPAREN)
+ {
+ si = i + 2;
+ t = extract_delimited_string (string, &si, "$(", "(", ")", flags|EX_NOALLOC); /*)*/
+ i = si + 1;
+ continue;
+ }
+
+ /* Pass the contents of single-quoted and double-quoted strings
+ through verbatim. */
+ if (c == '\'' || c == '"')
+ {
+ si = i + 1;
+ i = (c == '\'') ? skip_single_quoted (string, slen, si)
+ : skip_double_quoted (string, slen, si);
+ /* skip_XXX_quoted leaves index one past close quote */
+ continue;
+ }
+
+ /* move past this character, which was not special. */
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ if (c == 0 && nesting_level)
+ {
+ if (no_longjmp_on_fatal_error == 0)
+ { /* { */
+ report_error ("bad substitution: no closing `%s' in %s", "}", string);
+ last_command_exit_value = EXECUTION_FAILURE;
+ exp_jump_to_top_level (DISCARD);
+ }
+ else
+ {
+ *sindex = i;
+ return ((char *)NULL);
+ }
+ }
+
+ result = (flags & EX_NOALLOC) ? (char *)NULL : substring (string, *sindex, i);
+ *sindex = i;
+
+ return (result);
+}
+
+/* Remove backslashes which are quoting backquotes from STRING. Modifies
+ STRING, and returns a pointer to it. */
+char *
+de_backslash (string)
+ char *string;
+{
+ register size_t slen;
+ register int i, j, prev_i;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ i = j = 0;
+
+ /* Loop copying string[i] to string[j], i >= j. */
+ while (i < slen)
+ {
+ if (string[i] == '\\' && (string[i + 1] == '`' || string[i + 1] == '\\' ||
+ string[i + 1] == '$'))
+ i++;
+ prev_i = i;
+ ADVANCE_CHAR (string, slen, i);
+ if (j < prev_i)
+ do string[j++] = string[prev_i++]; while (prev_i < i);
+ else
+ j = i;
+ }
+ string[j] = '\0';
+
+ return (string);
+}
+
+#if 0
+/*UNUSED*/
+/* Replace instances of \! in a string with !. */
+void
+unquote_bang (string)
+ char *string;
+{
+ register int i, j;
+ register char *temp;
+
+ temp = (char *)xmalloc (1 + strlen (string));
+
+ for (i = 0, j = 0; (temp[j] = string[i]); i++, j++)
+ {
+ if (string[i] == '\\' && string[i + 1] == '!')
+ {
+ temp[j] = '!';
+ i++;
+ }
+ }
+ strcpy (string, temp);
+ free (temp);
+}
+#endif
+
+#if defined (READLINE)
+/* Return 1 if the portion of STRING ending at EINDEX is quoted (there is
+ an unclosed quoted string), or if the character at EINDEX is quoted
+ by a backslash. NO_LONGJMP_ON_FATAL_ERROR is used to flag that the various
+ single and double-quoted string parsing functions should not return an
+ error if there are unclosed quotes or braces. The characters that this
+ recognizes need to be the same as the contents of
+ rl_completer_quote_characters. */
+
+#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
+
+int
+char_is_quoted (string, eindex)
+ char *string;
+ int eindex;
+{
+ int i, pass_next, c;
+ size_t slen;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ no_longjmp_on_fatal_error = 1;
+ i = pass_next = 0;
+ while (i <= eindex)
+ {
+ c = string[i];
+
+ if (pass_next)
+ {
+ pass_next = 0;
+ if (i >= eindex) /* XXX was if (i >= eindex - 1) */
+ CQ_RETURN(1);
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '\\')
+ {
+ pass_next = 1;
+ i++;
+ continue;
+ }
+ else if (c == '\'' || c == '"')
+ {
+ i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
+ : skip_double_quoted (string, slen, ++i);
+ if (i > eindex)
+ CQ_RETURN(1);
+ /* no increment, the skip_xxx functions go one past end */
+ }
+ else
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ CQ_RETURN(0);
+}
+
+int
+unclosed_pair (string, eindex, openstr)
+ char *string;
+ int eindex;
+ char *openstr;
+{
+ int i, pass_next, openc, olen;
+ size_t slen;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ olen = strlen (openstr);
+ i = pass_next = openc = 0;
+ while (i <= eindex)
+ {
+ if (pass_next)
+ {
+ pass_next = 0;
+ if (i >= eindex) /* XXX was if (i >= eindex - 1) */
+ return 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (string[i] == '\\')
+ {
+ pass_next = 1;
+ i++;
+ continue;
+ }
+ else if (STREQN (string + i, openstr, olen))
+ {
+ openc = 1 - openc;
+ i += olen;
+ }
+ else if (string[i] == '\'' || string[i] == '"')
+ {
+ i = (string[i] == '\'') ? skip_single_quoted (string, slen, i)
+ : skip_double_quoted (string, slen, i);
+ if (i > eindex)
+ return 0;
+ }
+ else
+ ADVANCE_CHAR (string, slen, i);
+ }
+ return (openc);
+}
+
+/* Skip characters in STRING until we find a character in DELIMS, and return
+ the index of that character. START is the index into string at which we
+ begin. This is similar in spirit to strpbrk, but it returns an index into
+ STRING and takes a starting index. This little piece of code knows quite
+ a lot of shell syntax. It's very similar to skip_double_quoted and other
+ functions of that ilk. */
+int
+skip_to_delim (string, start, delims)
+ char *string;
+ int start;
+ char *delims;
+{
+ int i, pass_next, backq, si, c;
+ size_t slen;
+ char *temp;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string + start) + start;
+ no_longjmp_on_fatal_error = 1;
+ i = start;
+ pass_next = backq = 0;
+ while (c = string[i])
+ {
+ if (pass_next)
+ {
+ pass_next = 0;
+ if (c == 0)
+ CQ_RETURN(i);
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '\\')
+ {
+ pass_next = 1;
+ i++;
+ continue;
+ }
+ else if (backq)
+ {
+ if (c == '`')
+ backq = 0;
+ ADVANCE_CHAR (string, slen, i);
+ continue;
+ }
+ else if (c == '`')
+ {
+ backq = 1;
+ i++;
+ continue;
+ }
+ else if (c == '\'' || c == '"')
+ {
+ i = (c == '\'') ? skip_single_quoted (string, slen, ++i)
+ : skip_double_quoted (string, slen, ++i);
+ /* no increment, the skip functions increment past the closing quote. */
+ }
+ else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
+ {
+ si = i + 2;
+ if (string[si] == '\0')
+ CQ_RETURN(si);
+
+ if (string[i+1] == LPAREN)
+ temp = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
+ else
+ temp = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
+ i = si;
+ if (string[i] == '\0') /* don't increment i past EOS in loop */
+ break;
+ i++;
+ continue;
+ }
+ else if (member (c, delims))
+ break;
+ else
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ CQ_RETURN(i);
+}
+
+/* Split STRING (length SLEN) at DELIMS, and return a WORD_LIST with the
+ individual words. If DELIMS is NULL, the current value of $IFS is used
+ to split the string, and the function follows the shell field splitting
+ rules. SENTINEL is an index to look for. NWP, if non-NULL,
+ gets the number of words in the returned list. CWP, if non-NULL, gets
+ the index of the word containing SENTINEL. Non-whitespace chars in
+ DELIMS delimit separate fields. */
+WORD_LIST *
+split_at_delims (string, slen, delims, sentinel, nwp, cwp)
+ char *string;
+ int slen;
+ char *delims;
+ int sentinel;
+ int *nwp, *cwp;
+{
+ int ts, te, i, nw, cw, ifs_split;
+ char *token, *d, *d2;
+ WORD_LIST *ret, *tl;
+
+ if (string == 0 || *string == '\0')
+ {
+ if (nwp)
+ *nwp = 0;
+ if (cwp)
+ *cwp = 0;
+ return ((WORD_LIST *)NULL);
+ }
+
+ d = (delims == 0) ? ifs_value : delims;
+ ifs_split = delims == 0;
+
+ /* Make d2 the non-whitespace characters in delims */
+ d2 = 0;
+ if (delims)
+ {
+ size_t slength;
+#if defined (HANDLE_MULTIBYTE)
+ size_t mblength = 1;
+#endif
+ DECLARE_MBSTATE;
+
+ slength = strlen (delims);
+ d2 = (char *)xmalloc (slength + 1);
+ i = ts = 0;
+ while (delims[i])
+ {
+#if defined (HANDLE_MULTIBYTE)
+ mbstate_t state_bak = state;
+ mblength = MBRLEN (delims + i, slength, &state);
+ if (MB_INVALIDCH (mblength))
+ state = state_bak;
+ else if (mblength > 1)
+ {
+ memcpy (d2 + ts, delims + i, mblength);
+ ts += mblength;
+ i += mblength;
+ slength -= mblength;
+ continue;
+ }
+#endif
+ if (whitespace (delims[i]) == 0)
+ d2[ts++] = delims[i];
+
+ i++;
+ slength--;
+ }
+ d2[ts] = '\0';
+ }
+
+ ret = (WORD_LIST *)NULL;
+
+ /* Remove sequences of whitspace characters at the start of the string, as
+ long as those characters are delimiters. */
+ for (i = 0; member (string[i], d) && spctabnl (string[i]); i++)
+ ;
+ if (string[i] == '\0')
+ return (ret);
+
+ ts = i;
+ nw = 0;
+ cw = -1;
+ while (1)
+ {
+ te = skip_to_delim (string, ts, d);
+
+ /* If we have a non-whitespace delimiter character, use it to make a
+ separate field. This is just about what $IFS splitting does and
+ is closer to the behavior of the shell parser. */
+ if (ts == te && d2 && member (string[ts], d2))
+ {
+ te = ts + 1;
+ /* If we're using IFS splitting, the non-whitespace delimiter char
+ and any additional IFS whitespace delimits a field. */
+ if (ifs_split)
+ while (member (string[te], d) && spctabnl (string[te]))
+ te++;
+ else
+ while (member (string[te], d2))
+ te++;
+ }
+
+ token = substring (string, ts, te);
+
+ ret = add_string_to_list (token, ret);
+ free (token);
+ nw++;
+
+ if (sentinel >= ts && sentinel <= te)
+ cw = nw;
+
+ /* If the cursor is at whitespace just before word start, set the
+ sentinel word to the current word. */
+ if (cwp && cw == -1 && sentinel == ts-1)
+ cw = nw;
+
+ /* If the cursor is at whitespace between two words, make a new, empty
+ word, add it before (well, after, since the list is in reverse order)
+ the word we just added, and set the current word to that one. */
+ if (cwp && cw == -1 && sentinel < ts)
+ {
+ tl = make_word_list (make_word (""), ret->next);
+ ret->next = tl;
+ cw = nw;
+ nw++;
+ }
+
+ if (string[te] == 0)
+ break;
+
+ i = te;
+ while (member (string[i], d) && (ifs_split || spctabnl(string[i])))
+ i++;
+
+ if (string[i])
+ ts = i;
+ else
+ break;
+ }
+
+ /* Special case for SENTINEL at the end of STRING. If we haven't found
+ the word containing SENTINEL yet, and the index we're looking for is at
+ the end of STRING, add an additional null argument and set the current
+ word pointer to that. */
+ if (cwp && cw == -1 && sentinel >= slen)
+ {
+ if (whitespace (string[sentinel - 1]))
+ {
+ token = "";
+ ret = add_string_to_list (token, ret);
+ nw++;
+ }
+ cw = nw;
+ }
+
+ if (nwp)
+ *nwp = nw;
+ if (cwp)
+ *cwp = cw;
+
+ return (REVERSE_LIST (ret, WORD_LIST *));
+}
+#endif /* READLINE */
+
+#if 0
+/* UNUSED */
+/* Extract the name of the variable to bind to from the assignment string. */
+char *
+assignment_name (string)
+ char *string;
+{
+ int offset;
+ char *temp;
+
+ offset = assignment (string, 0);
+ if (offset == 0)
+ return (char *)NULL;
+ temp = substring (string, 0, offset);
+ return (temp);
+}
+#endif
+
+/* **************************************************************** */
+/* */
+/* Functions to convert strings to WORD_LISTs and vice versa */
+/* */
+/* **************************************************************** */
+
+/* Return a single string of all the words in LIST. SEP is the separator
+ to put between individual elements of LIST in the output string. */
+char *
+string_list_internal (list, sep)
+ WORD_LIST *list;
+ char *sep;
+{
+ register WORD_LIST *t;
+ char *result, *r;
+ int word_len, sep_len, result_size;
+
+ if (list == 0)
+ return ((char *)NULL);
+
+ /* Short-circuit quickly if we don't need to separate anything. */
+ if (list->next == 0)
+ return (savestring (list->word->word));
+
+ /* This is nearly always called with either sep[0] == 0 or sep[1] == 0. */
+ sep_len = STRLEN (sep);
+ result_size = 0;
+
+ for (t = list; t; t = t->next)
+ {
+ if (t != list)
+ result_size += sep_len;
+ result_size += strlen (t->word->word);
+ }
+
+ r = result = (char *)xmalloc (result_size + 1);
+
+ for (t = list; t; t = t->next)
+ {
+ if (t != list && sep_len)
+ {
+ if (sep_len > 1)
+ {
+ FASTCOPY (sep, r, sep_len);
+ r += sep_len;
+ }
+ else
+ *r++ = sep[0];
+ }
+
+ word_len = strlen (t->word->word);
+ FASTCOPY (t->word->word, r, word_len);
+ r += word_len;
+ }
+
+ *r = '\0';
+ return (result);
+}
+
+/* Return a single string of all the words present in LIST, separating
+ each word with a space. */
+char *
+string_list (list)
+ WORD_LIST *list;
+{
+ return (string_list_internal (list, " "));
+}
+
+/* Return a single string of all the words present in LIST, obeying the
+ quoting rules for "$*", to wit: (P1003.2, draft 11, 3.5.2) "If the
+ expansion [of $*] appears within a double quoted string, it expands
+ to a single field with the value of each parameter separated by the
+ first character of the IFS variable, or by a <space> if IFS is unset." */
+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];
+ sep[1] = '\0';
+ }
+ else
+ {
+ memcpy (sep, ifs_firstc, ifs_firstc_len);
+ sep[ifs_firstc_len] = '\0';
+ }
+#else
+ sep[0] = ifs_firstc;
+ sep[1] = '\0';
+#endif
+
+ 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))
+ is non-zero, the $@ appears within double quotes, and we should quote
+ the list before converting it into a string. If IFS is unset, and the
+ word is not quoted, we just need to quote CTLESC and CTLNUL characters
+ in the words in the list, because the default value of $IFS is
+ <space><tab><newline>, IFS characters in the words in the list should
+ also be split. If IFS is null, and the word is not quoted, we need
+ to quote the words in the list to preserve the positional parameters
+ exactly. */
+char *
+string_list_dollar_at (list, quoted)
+ WORD_LIST *list;
+ int 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
+ WORD_LIST *tlist;
+
+ /* XXX this could just be ifs = ifs_value; */
+ 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)
+ {
+ sep[0] = ifs_firstc[0];
+ sep[1] = '\0';
+ }
+ else
+ {
+ memcpy (sep, ifs_firstc, ifs_firstc_len);
+ sep[ifs_firstc_len] = '\0';
+ }
+ }
+ else
+ {
+ sep[0] = ' ';
+ sep[1] = '\0';
+ }
+#else
+ sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
+ sep[1] = '\0';
+#endif
+
+ tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
+ ? quote_list (list)
+ : list_quote_escapes (list);
+
+ 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
+ words at any of the characters found in SEPARATORS. If QUOTED is
+ non-zero then word in the list will have its quoted flag set, otherwise
+ the quoted flag is left as make_word () deemed fit.
+
+ This obeys the P1003.2 word splitting semantics. If `separators' is
+ exactly <space><tab><newline>, then the splitting algorithm is that of
+ the Bourne shell, which treats any sequence of characters from `separators'
+ as a delimiter. If IFS is unset, which results in `separators' being set
+ to "", no splitting occurs. If separators has some other value, the
+ following rules are applied (`IFS white space' means zero or more
+ occurrences of <space>, <tab>, or <newline>, as long as those characters
+ are in `separators'):
+
+ 1) IFS white space is ignored at the start and the end of the
+ string.
+ 2) Each occurrence of a character in `separators' that is not
+ IFS white space, along with any adjacent occurrences of
+ IFS white space delimits a field.
+ 3) Any nonzero-length sequence of IFS white space delimits a field.
+ */
+
+/* BEWARE! list_string strips null arguments. Don't call it twice and
+ expect to have "" preserved! */
+
+/* This performs word splitting and quoted null character removal on
+ STRING. */
+#define issep(c) \
+ (((separators)[0]) ? ((separators)[1] ? isifs(c) \
+ : (c) == (separators)[0]) \
+ : 0)
+
+WORD_LIST *
+list_string (string, separators, quoted)
+ register char *string, *separators;
+ int quoted;
+{
+ WORD_LIST *result;
+ WORD_DESC *t;
+ char *current_word, *s;
+ int sindex, sh_style_split, whitesep;
+ size_t slen;
+
+ if (!string || !*string)
+ return ((WORD_LIST *)NULL);
+
+ sh_style_split = separators && separators[0] == ' ' &&
+ separators[1] == '\t' &&
+ separators[2] == '\n' &&
+ separators[3] == '\0';
+
+ slen = 0;
+ /* Remove sequences of whitespace at the beginning of STRING, as
+ long as those characters appear in IFS. Do not do this if
+ STRING is quoted or if there are no separator characters. */
+ if (!quoted || !separators || !*separators)
+ {
+ for (s = string; *s && spctabnl (*s) && issep (*s); s++);
+
+ if (!*s)
+ return ((WORD_LIST *)NULL);
+
+ string = s;
+ }
+
+ /* OK, now STRING points to a word that does not begin with white space.
+ The splitting algorithm is:
+ extract a word, stopping at a separator
+ skip sequences of spc, tab, or nl as long as they are separators
+ This obeys the field splitting rules in Posix.2. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string) : 1;
+ for (result = (WORD_LIST *)NULL, sindex = 0; string[sindex]; )
+ {
+ /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
+ unless multibyte chars are possible. */
+ current_word = string_extract_verbatim (string, slen, &sindex, separators);
+ if (current_word == 0)
+ break;
+
+ /* If we have a quoted empty string, add a quoted null argument. We
+ want to preserve the quoted null character iff this is a quoted
+ empty string; otherwise the quoted null characters are removed
+ below. */
+ if (QUOTED_NULL (current_word))
+ {
+ t = alloc_word_desc ();
+ t->word = make_quoted_char ('\0');
+ t->flags |= W_QUOTED|W_HASQUOTEDNULL;
+ result = make_word_list (t, result);
+ }
+ else if (current_word[0] != '\0')
+ {
+ /* If we have something, then add it regardless. However,
+ perform quoted null character removal on the current word. */
+ remove_quoted_nulls (current_word);
+ result = add_string_to_list (current_word, result);
+ result->word->flags &= ~W_HASQUOTEDNULL; /* just to be sure */
+ if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ result->word->flags |= W_QUOTED;
+ }
+
+ /* If we're not doing sequences of separators in the traditional
+ Bourne shell style, then add a quoted null argument. */
+ else if (!sh_style_split && !spctabnl (string[sindex]))
+ {
+ t = alloc_word_desc ();
+ t->word = make_quoted_char ('\0');
+ t->flags |= W_QUOTED|W_HASQUOTEDNULL;
+ result = make_word_list (t, result);
+ }
+
+ free (current_word);
+
+ /* Note whether or not the separator is IFS whitespace, used later. */
+ whitesep = string[sindex] && spctabnl (string[sindex]);
+
+ /* Move past the current separator character. */
+ if (string[sindex])
+ {
+ DECLARE_MBSTATE;
+ ADVANCE_CHAR (string, slen, sindex);
+ }
+
+ /* Now skip sequences of space, tab, or newline characters if they are
+ in the list of separators. */
+ while (string[sindex] && spctabnl (string[sindex]) && issep (string[sindex]))
+ sindex++;
+
+ /* If the first separator was IFS whitespace and the current character
+ is a non-whitespace IFS character, it should be part of the current
+ field delimiter, not a separate delimiter that would result in an
+ empty field. Look at POSIX.2, 3.6.5, (3)(b). */
+ if (string[sindex] && whitesep && issep (string[sindex]) && !spctabnl (string[sindex]))
+ {
+ sindex++;
+ /* An IFS character that is not IFS white space, along with any
+ adjacent IFS white space, shall delimit a field. (SUSv3) */
+ while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
+ sindex++;
+ }
+ }
+ return (REVERSE_LIST (result, WORD_LIST *));
+}
+
+/* Parse a single word from STRING, using SEPARATORS to separate fields.
+ ENDPTR is set to the first character after the word. This is used by
+ the `read' builtin. This is never called with SEPARATORS != $IFS;
+ it should be simplified.
+
+ XXX - this function is very similar to list_string; they should be
+ combined - XXX */
+char *
+get_word_from_string (stringp, separators, endptr)
+ char **stringp, *separators, **endptr;
+{
+ register char *s;
+ char *current_word;
+ int sindex, sh_style_split, whitesep;
+ size_t slen;
+
+ if (!stringp || !*stringp || !**stringp)
+ return ((char *)NULL);
+
+ s = *stringp;
+
+ sh_style_split = separators && separators[0] == ' ' &&
+ separators[1] == '\t' &&
+ separators[2] == '\n' &&
+ separators[3] == '\0';
+
+ slen = 0;
+
+ /* Remove sequences of whitespace at the beginning of STRING, as
+ long as those characters appear in IFS. */
+ if (sh_style_split || !separators || !*separators)
+ {
+ for (; *s && spctabnl (*s) && isifs (*s); s++);
+
+ /* If the string is nothing but whitespace, update it and return. */
+ if (!*s)
+ {
+ *stringp = s;
+ if (endptr)
+ *endptr = s;
+ return ((char *)NULL);
+ }
+ }
+
+ /* OK, S points to a word that does not begin with white space.
+ Now extract a word, stopping at a separator, save a pointer to
+ the first character after the word, then skip sequences of spc,
+ tab, or nl as long as they are separators.
+
+ This obeys the field splitting rules in Posix.2. */
+ sindex = 0;
+ /* Don't need string length in ADVANCE_CHAR or string_extract_verbatim
+ unless multibyte chars are possible. */
+ slen = (MB_CUR_MAX > 1) ? strlen (s) : 1;
+ current_word = string_extract_verbatim (s, slen, &sindex, separators);
+
+ /* Set ENDPTR to the first character after the end of the word. */
+ if (endptr)
+ *endptr = s + sindex;
+
+ /* Note whether or not the separator is IFS whitespace, used later. */
+ whitesep = s[sindex] && spctabnl (s[sindex]);
+
+ /* Move past the current separator character. */
+ if (s[sindex])
+ {
+ DECLARE_MBSTATE;
+ ADVANCE_CHAR (s, slen, sindex);
+ }
+
+ /* Now skip sequences of space, tab, or newline characters if they are
+ in the list of separators. */
+ while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
+ sindex++;
+
+ /* If the first separator was IFS whitespace and the current character is
+ a non-whitespace IFS character, it should be part of the current field
+ delimiter, not a separate delimiter that would result in an empty field.
+ Look at POSIX.2, 3.6.5, (3)(b). */
+ if (s[sindex] && whitesep && isifs (s[sindex]) && !spctabnl (s[sindex]))
+ {
+ sindex++;
+ /* An IFS character that is not IFS white space, along with any adjacent
+ IFS white space, shall delimit a field. */
+ while (s[sindex] && spctabnl (s[sindex]) && isifs (s[sindex]))
+ sindex++;
+ }
+
+ /* Update STRING to point to the next field. */
+ *stringp = s + sindex;
+ return (current_word);
+}
+
+/* Remove IFS white space at the end of STRING. Start at the end
+ of the string and walk backwards until the beginning of the string
+ or we find a character that's not IFS white space and not CTLESC.
+ Only let CTLESC escape a white space character if SAW_ESCAPE is
+ non-zero. */
+char *
+strip_trailing_ifs_whitespace (string, separators, saw_escape)
+ char *string, *separators;
+ int saw_escape;
+{
+ char *s;
+
+ s = string + STRLEN (string) - 1;
+ while (s > string && ((spctabnl (*s) && isifs (*s)) ||
+ (saw_escape && *s == CTLESC && spctabnl (s[1]))))
+ s--;
+ *++s = '\0';
+ return string;
+}
+
+#if 0
+/* UNUSED */
+/* Split STRING into words at whitespace. Obeys shell-style quoting with
+ backslashes, single and double quotes. */
+WORD_LIST *
+list_string_with_quotes (string)
+ char *string;
+{
+ WORD_LIST *list;
+ char *token, *s;
+ size_t s_len;
+ int c, i, tokstart, len;
+
+ for (s = string; s && *s && spctabnl (*s); s++)
+ ;
+ if (s == 0 || *s == 0)
+ return ((WORD_LIST *)NULL);
+
+ s_len = strlen (s);
+ tokstart = i = 0;
+ list = (WORD_LIST *)NULL;
+ while (1)
+ {
+ c = s[i];
+ if (c == '\\')
+ {
+ i++;
+ if (s[i])
+ i++;
+ }
+ else if (c == '\'')
+ i = skip_single_quoted (s, s_len, ++i);
+ else if (c == '"')
+ i = skip_double_quoted (s, s_len, ++i);
+ else if (c == 0 || spctabnl (c))
+ {
+ /* We have found the end of a token. Make a word out of it and
+ add it to the word list. */
+ token = substring (s, tokstart, i);
+ list = add_string_to_list (token, list);
+ free (token);
+ while (spctabnl (s[i]))
+ i++;
+ if (s[i])
+ tokstart = i;
+ else
+ break;
+ }
+ else
+ i++; /* normal character */
+ }
+ return (REVERSE_LIST (list, WORD_LIST *));
+}
+#endif
+
+/********************************************************/
+/* */
+/* Functions to perform assignment statements */
+/* */
+/********************************************************/
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *
+do_compound_assignment (name, value, flags)
+ char *name, *value;
+ int flags;
+{
+ SHELL_VAR *v;
+ int off, mklocal;
+
+ mklocal = flags & ASS_MKLOCAL;
+
+ if (mklocal && variable_context)
+ {
+ 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);
+ }
+ else
+ v = assign_array_from_string (name, value, flags);
+
+ return (v);
+}
+#endif
+
+/* 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 parameter expansion, command substitution, and arithmetic
+ expansion on the right-hand side. Perform tilde expansion in any
+ case. Do not perform word splitting on the result of expansion. */
+static int
+do_assignment_internal (word, expand)
+ const WORD_DESC *word;
+ int expand;
+{
+ int offset, tlen, appendop, assign_list, aflags;
+ char *name, *value, *ovalue, *nvalue;
+ SHELL_VAR *entry;
+#if defined (ARRAY_VARS)
+ char *t;
+ int ni;
+#endif
+ const char *string;
+
+ if (word == 0 || word->word == 0)
+ return 0;
+
+ appendop = assign_list = aflags = 0;
+ string = word->word;
+ offset = assignment (string, 0);
+ name = savestring (string);
+ value = (char *)NULL;
+
+ if (name[offset] == '=')
+ {
+ char *temp;
+
+ if (name[offset - 1] == '+')
+ {
+ appendop = 1;
+ name[offset - 1] = '\0';
+ }
+
+ name[offset] = 0; /* might need this set later */
+ temp = name + offset + 1;
+ tlen = STRLEN (temp);
+
+#if defined (ARRAY_VARS)
+# if 0
+ if (expand && temp[0] == LPAREN && temp[tlen-1] == RPAREN)
+#else
+ if (expand && (word->flags & W_COMPASSIGN))
+#endif
+ {
+ assign_list = ni = 1;
+ value = extract_array_assignment_list (temp, &ni);
+ }
+ else
+#endif
+
+ if (expand && temp[0])
+ value = expand_string_if_necessary (temp, 0, expand_string_assignment);
+ else
+ value = savestring (temp);
+ }
+
+ if (value == 0)
+ {
+ value = (char *)xmalloc (1);
+ value[0] = '\0';
+ }
+
+ if (echo_command_at_execute)
+ {
+ if (appendop)
+ name[offset - 1] = '+';
+ xtrace_print_assignment (name, value, assign_list, 1);
+ if (appendop)
+ name[offset - 1] = '\0';
+ }
+
+#define ASSIGN_RETURN(r) do { FREE (value); free (name); return (r); } while (0)
+
+ if (appendop)
+ aflags |= ASS_APPEND;
+
+#if defined (ARRAY_VARS)
+ if (t = xstrchr (name, '[')) /*]*/
+ {
+ if (assign_list)
+ {
+ report_error (_("%s: cannot assign list to array member"), name);
+ ASSIGN_RETURN (0);
+ }
+ entry = assign_array_element (name, value, aflags);
+ if (entry == 0)
+ ASSIGN_RETURN (0);
+ }
+ else if (assign_list)
+ {
+ if (word->flags & W_ASSIGNARG)
+ aflags |= ASS_MKLOCAL;
+ entry = do_compound_assignment (name, value, aflags);
+ }
+ else
+#endif /* ARRAY_VARS */
+ entry = bind_variable (name, value, aflags);
+
+ stupidly_hack_special_variables (name);
+
+ if (entry)
+ VUNSETATTR (entry, att_invisible);
+
+ /* Return 1 if the assignment seems to have been performed correctly. */
+ ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
+}
+
+/* Perform the assignment statement in STRING, and expand the
+ right side by doing tilde, command and parameter expansion. */
+int
+do_assignment (string)
+ char *string;
+{
+ WORD_DESC td;
+
+ td.flags = W_ASSIGNMENT;
+ td.word = string;
+
+ return do_assignment_internal (&td, 1);
+}
+
+int
+do_word_assignment (word)
+ WORD_DESC *word;
+{
+ return do_assignment_internal (word, 1);
+}
+
+/* Given STRING, an assignment string, get the value of the right side
+ of the `=', and bind it to the left side. Do not perform any word
+ expansions on the right hand side. */
+int
+do_assignment_no_expand (string)
+ char *string;
+{
+ WORD_DESC td;
+
+ td.flags = W_ASSIGNMENT;
+ td.word = string;
+
+ return (do_assignment_internal (&td, 0));
+}
+
+/***************************************************
+ * *
+ * Functions to manage the positional parameters *
+ * *
+ ***************************************************/
+
+/* Return the word list that corresponds to `$*'. */
+WORD_LIST *
+list_rest_of_args ()
+{
+ register WORD_LIST *list, *args;
+ int i;
+
+ /* Break out of the loop as soon as one of the dollar variables is null. */
+ for (i = 1, list = (WORD_LIST *)NULL; i < 10 && dollar_vars[i]; i++)
+ list = make_word_list (make_bare_word (dollar_vars[i]), list);
+
+ for (args = rest_of_args; args; args = args->next)
+ list = make_word_list (make_bare_word (args->word->word), list);
+
+ return (REVERSE_LIST (list, WORD_LIST *));
+}
+
+int
+number_of_args ()
+{
+ register WORD_LIST *list;
+ int n;
+
+ for (n = 0; n < 9 && dollar_vars[n+1]; n++)
+ ;
+ for (list = rest_of_args; list; list = list->next)
+ n++;
+ return n;
+}
+
+/* Return the value of a positional parameter. This handles values > 10. */
+char *
+get_dollar_var_value (ind)
+ intmax_t ind;
+{
+ char *temp;
+ WORD_LIST *p;
+
+ if (ind < 10)
+ temp = dollar_vars[ind] ? savestring (dollar_vars[ind]) : (char *)NULL;
+ else /* We want something like ${11} */
+ {
+ ind -= 10;
+ for (p = rest_of_args; p && ind--; p = p->next)
+ ;
+ temp = p ? savestring (p->word->word) : (char *)NULL;
+ }
+ return (temp);
+}
+
+/* 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. */
+char *
+string_rest_of_args (dollar_star)
+ int dollar_star;
+{
+ register WORD_LIST *list;
+ char *string;
+
+ list = list_rest_of_args ();
+ string = dollar_star ? string_list_dollar_star (list) : string_list (list);
+ dispose_words (list);
+ return (string);
+}
+
+/* Return a string containing the positional parameters from START to
+ END, inclusive. If STRING[0] == '*', we obey the rules for $*,
+ which only makes a difference if QUOTED is non-zero. If QUOTED includes
+ Q_HERE_DOCUMENT or Q_DOUBLE_QUOTES, this returns a quoted list, otherwise
+ no quoting chars are added. */
+static char *
+pos_params (string, start, end, quoted)
+ char *string;
+ int start, end, quoted;
+{
+ WORD_LIST *save, *params, *h, *t;
+ char *ret;
+ int i;
+
+ /* see if we can short-circuit. if start == end, we want 0 parameters. */
+ if (start == end)
+ return ((char *)NULL);
+
+ save = params = list_rest_of_args ();
+ if (save == 0)
+ return ((char *)NULL);
+
+ for (i = 1; params && i < start; i++)
+ params = params->next;
+ if (params == 0)
+ return ((char *)NULL);
+ for (h = t = params; params && i < end; i++)
+ {
+ t = params;
+ params = params->next;
+ }
+
+ t->next = (WORD_LIST *)NULL;
+ if (string[0] == '*')
+ {
+ if (quoted & Q_DOUBLE_QUOTES)
+ ret = string_list_dollar_star (quote_list (h));
+ else if (quoted & Q_HERE_DOCUMENT)
+ ret = string_list (quote_list (h));
+ else
+ ret = string_list (h);
+ }
+ else
+ ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (h) : h);
+ if (t != params)
+ t->next = params;
+
+ dispose_words (save);
+ return (ret);
+}
+
+/******************************************************************/
+/* */
+/* Functions to expand strings to strings or WORD_LISTs */
+/* */
+/******************************************************************/
+
+#if defined (PROCESS_SUBSTITUTION)
+#define EXP_CHAR(s) (s == '$' || s == '`' || s == '<' || s == '>' || s == CTLESC || s == '~')
+#else
+#define EXP_CHAR(s) (s == '$' || s == '`' || s == CTLESC || s == '~')
+#endif
+
+/* If there are any characters in STRING that require full expansion,
+ then call FUNC to expand STRING; otherwise just perform quote
+ removal if necessary. This returns a new string. */
+static char *
+expand_string_if_necessary (string, quoted, func)
+ char *string;
+ int quoted;
+ EXPFUNC *func;
+{
+ WORD_LIST *list;
+ size_t slen;
+ int i, saw_quote;
+ char *ret;
+ DECLARE_MBSTATE;
+
+ /* Don't need string length for ADVANCE_CHAR unless multibyte chars possible. */
+ slen = (MB_CUR_MAX > 1) ? strlen (string) : 0;
+ i = saw_quote = 0;
+ while (string[i])
+ {
+ if (EXP_CHAR (string[i]))
+ break;
+ else if (string[i] == '\'' || string[i] == '\\' || string[i] == '"')
+ saw_quote = 1;
+ ADVANCE_CHAR (string, slen, i);
+ }
+
+ if (string[i])
+ {
+ list = (*func) (string, quoted);
+ if (list)
+ {
+ ret = string_list (list);
+ dispose_words (list);
+ }
+ else
+ ret = (char *)NULL;
+ }
+ else if (saw_quote && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ ret = string_quote_removal (string, quoted);
+ else
+ ret = savestring (string);
+
+ return ret;
+}
+
+static inline char *
+expand_string_to_string_internal (string, quoted, func)
+ char *string;
+ int quoted;
+ EXPFUNC *func;
+{
+ WORD_LIST *list;
+ char *ret;
+
+ if (string == 0 || *string == '\0')
+ return ((char *)NULL);
+
+ list = (*func) (string, quoted);
+ if (list)
+ {
+ ret = string_list (list);
+ dispose_words (list);
+ }
+ else
+ ret = (char *)NULL;
+
+ return (ret);
+}
+
+char *
+expand_string_to_string (string, quoted)
+ char *string;
+ int quoted;
+{
+ return (expand_string_to_string_internal (string, quoted, expand_string));
+}
+
+char *
+expand_string_unsplit_to_string (string, quoted)
+ char *string;
+ int quoted;
+{
+ return (expand_string_to_string_internal (string, quoted, expand_string_unsplit));
+}
+
+char *
+expand_assignment_string_to_string (string, quoted)
+ char *string;
+ int 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 *
+remove_backslashes (string)
+ char *string;
+{
+ char *r, *ret, *s;
+
+ r = ret = (char *)xmalloc (strlen (string) + 1);
+ for (s = string; s && *s; )
+ {
+ if (*s == '\\')
+ s++;
+ if (*s == 0)
+ break;
+ *r++ = *s++;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* This needs better error handling. */
+/* Expand W for use as an argument to a unary or binary operator in a
+ [[...]] expression. If SPECIAL is nonzero, this is the rhs argument
+ to the != or == operator, and should be treated as a pattern. In
+ this case, we quote the string specially for the globbing code. The
+ caller is responsible for removing the backslashes if the unquoted
+ words is needed later. */
+char *
+cond_expand_word (w, special)
+ WORD_DESC *w;
+ int special;
+{
+ char *r, *p;
+ WORD_LIST *l;
+
+ if (w->word == 0 || w->word[0] == '\0')
+ return ((char *)NULL);
+
+ l = call_expand_word_internal (w, 0, 0, (int *)0, (int *)0);
+ if (l)
+ {
+ if (special == 0)
+ {
+ dequote_list (l);
+ r = string_list (l);
+ }
+ else
+ {
+ p = string_list (l);
+ r = quote_string_for_globbing (p, QGLOB_CVTNULL);
+ free (p);
+ }
+ dispose_words (l);
+ }
+ else
+ r = (char *)NULL;
+
+ return r;
+}
+#endif
+
+/* Call expand_word_internal to expand W and handle error returns.
+ A convenience function for functions that don't want to handle
+ any errors or free any memory before aborting. */
+static WORD_LIST *
+call_expand_word_internal (w, q, i, c, e)
+ WORD_DESC *w;
+ int q, i, *c, *e;
+{
+ WORD_LIST *result;
+
+ result = expand_word_internal (w, q, i, c, e);
+ if (result == &expand_word_error || result == &expand_word_fatal)
+ {
+ /* By convention, each time this error is returned, w->word has
+ already been freed (it sometimes may not be in the fatal case,
+ but that doesn't result in a memory leak because we're going
+ to exit in most cases). */
+ w->word = (char *)NULL;
+ last_command_exit_value = EXECUTION_FAILURE;
+ exp_jump_to_top_level ((result == &expand_word_error) ? DISCARD : FORCE_EOF);
+ /* NOTREACHED */
+ }
+ else
+ return (result);
+}
+
+/* Perform parameter expansion, command substitution, and arithmetic
+ expansion on STRING, as if it were a word. Leave the result quoted. */
+static WORD_LIST *
+expand_string_internal (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_DESC td;
+ WORD_LIST *tresult;
+
+ if (string == 0 || *string == 0)
+ return ((WORD_LIST *)NULL);
+
+ td.flags = 0;
+ td.word = savestring (string);
+
+ tresult = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
+
+ FREE (td.word);
+ return (tresult);
+}
+
+/* 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 in here because word splitting normally
+ takes care of quote removal. */
+WORD_LIST *
+expand_string_unsplit (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_LIST *value;
+
+ if (string == 0 || *string == '\0')
+ return ((WORD_LIST *)NULL);
+
+ expand_no_split_dollar_star = 1;
+ value = expand_string_internal (string, quoted);
+ expand_no_split_dollar_star = 0;
+
+ if (value)
+ {
+ if (value->word)
+ {
+ remove_quoted_nulls (value->word->word);
+ value->word->flags &= ~W_HASQUOTEDNULL;
+ }
+ dequote_list (value);
+ }
+ return (value);
+}
+
+/* Expand the rhs of an assignment statement */
+WORD_LIST *
+expand_string_assignment (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_DESC td;
+ WORD_LIST *value;
+
+ if (string == 0 || *string == '\0')
+ return ((WORD_LIST *)NULL);
+
+ expand_no_split_dollar_star = 1;
+
+ td.flags = W_ASSIGNRHS;
+ td.word = savestring (string);
+ value = call_expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
+ FREE (td.word);
+
+ expand_no_split_dollar_star = 0;
+
+ if (value)
+ {
+ if (value->word)
+ {
+ remove_quoted_nulls (value->word->word);
+ value->word->flags &= ~W_HASQUOTEDNULL;
+ }
+ dequote_list (value);
+ }
+ return (value);
+}
+
+
+/* Expand one of the PS? prompt strings. This is a sort of combination of
+ expand_string_unsplit and expand_string_internal, but returns the
+ passed string when an error occurs. Might want to trap other calls
+ to jump_to_top_level here so we don't endlessly loop. */
+WORD_LIST *
+expand_prompt_string (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_LIST *value;
+ WORD_DESC td;
+
+ if (string == 0 || *string == 0)
+ return ((WORD_LIST *)NULL);
+
+ td.flags = 0;
+ td.word = savestring (string);
+
+ no_longjmp_on_fatal_error = 1;
+ value = expand_word_internal (&td, quoted, 0, (int *)NULL, (int *)NULL);
+ no_longjmp_on_fatal_error = 0;
+
+ if (value == &expand_word_error || value == &expand_word_fatal)
+ {
+ value = make_word_list (make_bare_word (string), (WORD_LIST *)NULL);
+ return value;
+ }
+ FREE (td.word);
+ if (value)
+ {
+ if (value->word)
+ {
+ remove_quoted_nulls (value->word->word);
+ value->word->flags &= ~W_HASQUOTEDNULL;
+ }
+ dequote_list (value);
+ }
+ return (value);
+}
+
+/* Expand STRING just as if you were expanding a word, but do not dequote
+ the resultant WORD_LIST. This is called only from within this file,
+ and is used to correctly preserve quoted characters when expanding
+ things like ${1+"$@"}. This does parameter expansion, command
+ substitution, arithmetic expansion, and word splitting. */
+static WORD_LIST *
+expand_string_leave_quoted (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_LIST *tlist;
+ WORD_LIST *tresult;
+
+ if (string == 0 || *string == '\0')
+ return ((WORD_LIST *)NULL);
+
+ tlist = expand_string_internal (string, quoted);
+
+ if (tlist)
+ {
+ tresult = word_list_split (tlist);
+ dispose_words (tlist);
+ return (tresult);
+ }
+ return ((WORD_LIST *)NULL);
+}
+
+/* This does not perform word splitting or dequote the WORD_LIST
+ it returns. */
+static WORD_LIST *
+expand_string_for_rhs (string, quoted, dollar_at_p, has_dollar_at)
+ char *string;
+ int quoted, *dollar_at_p, *has_dollar_at;
+{
+ WORD_DESC td;
+ WORD_LIST *tresult;
+
+ if (string == 0 || *string == '\0')
+ return (WORD_LIST *)NULL;
+
+ td.flags = 0;
+ td.word = string;
+ tresult = call_expand_word_internal (&td, quoted, 1, dollar_at_p, has_dollar_at);
+ return (tresult);
+}
+
+/* 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. */
+WORD_LIST *
+expand_string (string, quoted)
+ char *string;
+ int quoted;
+{
+ WORD_LIST *result;
+
+ if (string == 0 || *string == '\0')
+ return ((WORD_LIST *)NULL);
+
+ result = expand_string_leave_quoted (string, quoted);
+ return (result ? dequote_list (result) : result);
+}
+
+/***************************************************
+ * *
+ * Functions to handle quoting chars *
+ * *
+ ***************************************************/
+
+/* Conventions:
+
+ A string with s[0] == CTLNUL && s[1] == 0 is a quoted null string.
+ The parser passes CTLNUL as CTLESC CTLNUL. */
+
+/* Quote escape characters in string s, but no other characters. This is
+ used to protect CTLESC and CTLNUL in variable values from the rest of
+ the word expansion process after the variable is expanded. */
+char *
+quote_escapes (string)
+ char *string;
+{
+ register char *s, *t;
+ size_t slen;
+ char *result, *send;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ send = string + slen;
+
+ t = result = (char *)xmalloc ((slen * 2) + 1);
+ s = string;
+
+ while (*s)
+ {
+ if (*s == CTLESC || *s == CTLNUL)
+ *t++ = CTLESC;
+ COPY_CHAR_P (t, s, send);
+ }
+ *t = '\0';
+ return (result);
+}
+
+static WORD_LIST *
+list_quote_escapes (list)
+ WORD_LIST *list;
+{
+ register WORD_LIST *w;
+ char *t;
+
+ for (w = list; w; w = w->next)
+ {
+ t = w->word->word;
+ w->word->word = quote_escapes (t);
+ free (t);
+ }
+ return list;
+}
+
+/* Inverse of quote_escapes; remove CTLESC protecting CTLESC or CTLNUL.
+
+ The parser passes us CTLESC as CTLESC CTLESC and CTLNUL as CTLESC CTLNUL.
+ This is necessary to make unquoted CTLESC and CTLNUL characters in the
+ data stream pass through properly.
+
+ We need to remove doubled CTLESC characters inside quoted strings before
+ quoting the entire string, so we do not double the number of CTLESC
+ characters.
+
+ Also used by parts of the pattern substitution code. */
+static char *
+dequote_escapes (string)
+ char *string;
+{
+ register char *s, *t;
+ size_t slen;
+ char *result, *send;
+ DECLARE_MBSTATE;
+
+ if (string == 0)
+ return string;
+
+ slen = strlen (string);
+ send = string + slen;
+
+ t = result = (char *)xmalloc (slen + 1);
+ s = string;
+
+ if (strchr (string, CTLESC) == 0)
+ return (strcpy (result, s));
+
+ while (*s)
+ {
+ if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL))
+ {
+ s++;
+ if (*s == '\0')
+ break;
+ }
+ COPY_CHAR_P (t, s, send);
+ }
+ *t = '\0';
+ return result;
+}
+
+/* Return a new string with the quoted representation of character C. */
+static char *
+make_quoted_char (c)
+ int c;
+{
+ char *temp;
+
+ temp = (char *)xmalloc (3);
+ if (c == 0)
+ {
+ temp[0] = CTLNUL;
+ temp[1] = '\0';
+ }
+ else
+ {
+ temp[0] = CTLESC;
+ temp[1] = c;
+ temp[2] = '\0';
+ }
+ return (temp);
+}
+
+/* Quote STRING. Return a new string. */
+char *
+quote_string (string)
+ char *string;
+{
+ register char *t;
+ size_t slen;
+ char *result, *send;
+
+ if (*string == 0)
+ {
+ result = (char *)xmalloc (2);
+ result[0] = CTLNUL;
+ result[1] = '\0';
+ }
+ else
+ {
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+ send = string + slen;
+
+ result = (char *)xmalloc ((slen * 2) + 1);
+
+ for (t = result; string < send; )
+ {
+ *t++ = CTLESC;
+ COPY_CHAR_P (t, string, send);
+ }
+ *t = '\0';
+ }
+ return (result);
+}
+
+/* De-quoted quoted characters in STRING. */
+char *
+dequote_string (string)
+ char *string;
+{
+ register char *s, *t;
+ size_t slen;
+ char *result, *send;
+ DECLARE_MBSTATE;
+
+ slen = strlen (string);
+
+ t = result = (char *)xmalloc (slen + 1);
+
+ if (QUOTED_NULL (string))
+ {
+ result[0] = '\0';
+ return (result);
+ }
+
+ /* If no character in the string can be quoted, don't bother examining
+ each character. Just return a copy of the string passed to us. */
+ if (strchr (string, CTLESC) == NULL)
+ return (strcpy (result, string));
+
+ send = string + slen;
+ s = string;
+ while (*s)
+ {
+ if (*s == CTLESC)
+ {
+ s++;
+ if (*s == '\0')
+ break;
+ }
+ COPY_CHAR_P (t, s, send);
+ }
+
+ *t = '\0';
+ return (result);
+}
+
+/* Quote the entire WORD_LIST list. */
+static WORD_LIST *
+quote_list (list)
+ WORD_LIST *list;
+{
+ register WORD_LIST *w;
+ char *t;
+
+ for (w = list; w; w = w->next)
+ {
+ t = w->word->word;
+ w->word->word = quote_string (t);
+ free (t);
+ w->word->flags |= W_QUOTED;
+ }
+ return list;
+}
+
+static WORD_LIST *
+dequote_list (list)
+ WORD_LIST *list;
+{
+ register char *s;
+ register WORD_LIST *tlist;
+
+ for (tlist = list; tlist; tlist = tlist->next)
+ {
+ s = dequote_string (tlist->word->word);
+ free (tlist->word->word);
+ tlist->word->word = s;
+ }
+ return list;
+}
+
+/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
+ string. */
+static char *
+remove_quoted_escapes (string)
+ char *string;
+{
+ char *t;
+
+ if (string)
+ {
+ t = dequote_escapes (string);
+ strcpy (string, t);
+ free (t);
+ }
+
+ return (string);
+}
+
+/* Perform quoted null character removal on STRING. We don't allow any
+ quoted null characters in the middle or at the ends of strings because
+ of how expand_word_internal works. remove_quoted_nulls () turns
+ STRING into an empty string iff it only consists of a quoted null,
+ and removes all unquoted CTLNUL characters. */
+static char *
+remove_quoted_nulls (string)
+ char *string;
+{
+ register size_t slen;
+ register int i, j, prev_i;
+ DECLARE_MBSTATE;
+
+ if (strchr (string, CTLNUL) == 0) /* XXX */
+ return string; /* XXX */
+
+ slen = strlen (string);
+ i = j = 0;
+
+ while (i < slen)
+ {
+ if (string[i] == CTLESC)
+ {
+ /* Old code had j++, but we cannot assume that i == j at this
+ point -- what if a CTLNUL has already been removed from the
+ string? We don't want to drop the CTLESC or recopy characters
+ that we've already copied down. */
+ i++; string[j++] = CTLESC;
+ if (i == slen)
+ break;
+ }
+ else if (string[i] == CTLNUL)
+ i++;
+
+ prev_i = i;
+ ADVANCE_CHAR (string, slen, i);
+ if (j < prev_i)
+ {
+ do string[j++] = string[prev_i++]; while (prev_i < i);
+ }
+ else
+ j = i;
+ }
+ string[j] = '\0';
+
+ return (string);
+}
+
+/* Perform quoted null character removal on each element of LIST.
+ This modifies LIST. */
+void
+word_list_remove_quoted_nulls (list)
+ WORD_LIST *list;
+{
+ register WORD_LIST *t;
+
+ for (t = list; t; t = t->next)
+ {
+ remove_quoted_nulls (t->word->word);
+ t->word->flags &= ~W_HASQUOTEDNULL;
+ }
+}
+
+/* **************************************************************** */
+/* */
+/* Functions for Matching and Removing Patterns */
+/* */
+/* **************************************************************** */
+
+#if defined (HANDLE_MULTIBYTE)
+#if 0 /* Currently unused */
+static unsigned char *
+mb_getcharlens (string, len)
+ char *string;
+ int len;
+{
+ int i, offset, last;
+ unsigned char *ret;
+ char *p;
+ DECLARE_MBSTATE;
+
+ i = offset = 0;
+ last = 0;
+ ret = (unsigned char *)xmalloc (len);
+ memset (ret, 0, len);
+ while (string[last])
+ {
+ ADVANCE_CHAR (string, len, offset);
+ ret[last] = offset - last;
+ last = offset;
+ }
+ return ret;
+}
+#endif
+#endif
+
+/* Remove the portion of PARAM matched by PATTERN according to OP, where OP
+ can have one of 4 values:
+ RP_LONG_LEFT remove longest matching portion at start of PARAM
+ RP_SHORT_LEFT remove shortest matching portion at start of PARAM
+ RP_LONG_RIGHT remove longest matching portion at end of PARAM
+ RP_SHORT_RIGHT remove shortest matching portion at end of PARAM
+*/
+
+#define RP_LONG_LEFT 1
+#define RP_SHORT_LEFT 2
+#define RP_LONG_RIGHT 3
+#define RP_SHORT_RIGHT 4
+
+static char *
+remove_upattern (param, pattern, op)
+ char *param, *pattern;
+ int op;
+{
+ register int len;
+ register char *end;
+ register char *p, *ret, c;
+
+ len = STRLEN (param);
+ end = param + len;
+
+ switch (op)
+ {
+ case RP_LONG_LEFT: /* remove longest match at start */
+ for (p = end; p >= param; p--)
+ {
+ c = *p; *p = '\0';
+ if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ *p = c;
+ return (savestring (p));
+ }
+ *p = c;
+
+ }
+ break;
+
+ case RP_SHORT_LEFT: /* remove shortest match at start */
+ for (p = param; p <= end; p++)
+ {
+ c = *p; *p = '\0';
+ if (strmatch (pattern, param, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ *p = c;
+ return (savestring (p));
+ }
+ *p = c;
+ }
+ break;
+
+ case RP_LONG_RIGHT: /* remove longest match at end */
+ for (p = param; p <= end; p++)
+ {
+ if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ c = *p; *p = '\0';
+ ret = savestring (param);
+ *p = c;
+ return (ret);
+ }
+ }
+ break;
+
+ case RP_SHORT_RIGHT: /* remove shortest match at end */
+ for (p = end; p >= param; p--)
+ {
+ if (strmatch (pattern, p, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ c = *p; *p = '\0';
+ ret = savestring (param);
+ *p = c;
+ return (ret);
+ }
+ }
+ break;
+ }
+
+ return (savestring (param)); /* no match, return original string */
+}
+
+#if defined (HANDLE_MULTIBYTE)
+
+#if !defined (HAVE_WCSDUP)
+static wchar_t *
+wcsdup (ws)
+ wchar_t *ws;
+{
+ wchar_t *ret;
+ size_t len;
+
+ len = wcslen (ws);
+ ret = xmalloc ((len + 1) * sizeof (wchar_t));
+ if (ret == 0)
+ return ret;
+ return (wcscpy (ret, ws));
+}
+#endif /* !HAVE_WCSDUP */
+
+static wchar_t *
+remove_wpattern (wparam, wstrlen, wpattern, op)
+ wchar_t *wparam;
+ size_t wstrlen;
+ wchar_t *wpattern;
+ int op;
+{
+ wchar_t wc;
+ int n, n1;
+ wchar_t *ret;
+
+ switch (op)
+ {
+ case RP_LONG_LEFT: /* remove longest match at start */
+ for (n = wstrlen; n >= 0; n--)
+ {
+ wc = wparam[n]; wparam[n] = L'\0';
+ if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ wparam[n] = wc;
+ return (wcsdup (wparam + n));
+ }
+ wparam[n] = wc;
+ }
+ break;
+
+ case RP_SHORT_LEFT: /* remove shortest match at start */
+ for (n = 0; n <= wstrlen; n++)
+ {
+ wc = wparam[n]; wparam[n] = L'\0';
+ if (wcsmatch (wpattern, wparam, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ wparam[n] = wc;
+ return (wcsdup (wparam + n));
+ }
+ wparam[n] = wc;
+ }
+ break;
+
+ case RP_LONG_RIGHT: /* remove longest match at end */
+ for (n = 0; n <= wstrlen; n++)
+ {
+ if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ wc = wparam[n]; wparam[n] = L'\0';
+ ret = wcsdup (wparam);
+ wparam[n] = wc;
+ return (ret);
+ }
+ }
+ break;
+
+ case RP_SHORT_RIGHT: /* remove shortest match at end */
+ for (n = wstrlen; n >= 0; n--)
+ {
+ if (wcsmatch (wpattern, wparam + n, FNMATCH_EXTFLAG) != FNM_NOMATCH)
+ {
+ wc = wparam[n]; wparam[n] = L'\0';
+ ret = wcsdup (wparam);
+ wparam[n] = wc;
+ return (ret);
+ }
+ }
+ break;
+ }
+
+ return (wcsdup (wparam)); /* no match, return original string */
+}
+#endif /* HANDLE_MULTIBYTE */
+
+static char *
+remove_pattern (param, pattern, op)
+ char *param, *pattern;
+ int op;
+{
+ if (param == NULL)
+ return (param);
+ if (*param == '\0' || pattern == NULL || *pattern == '\0') /* minor optimization */
+ return (savestring (param));
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1)
+ {
+ wchar_t *ret, *oret;
+ size_t n;
+ wchar_t *wparam, *wpattern;
+ mbstate_t ps;
+ char *xret;
+
+ n = xdupmbstowcs (&wpattern, NULL, pattern);
+ if (n == (size_t)-1)
+ return (remove_upattern (param, pattern, op));
+ n = xdupmbstowcs (&wparam, NULL, param);
+ if (n == (size_t)-1)
+ {
+ free (wpattern);
+ return (remove_upattern (param, pattern, op));
+ }
+ oret = ret = remove_wpattern (wparam, n, wpattern, op);
+
+ free (wparam);
+ free (wpattern);
+
+ n = strlen (param);
+ 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 */
+ free (oret);
+ return xret;
+ }
+ else
+#endif
+ return (remove_upattern (param, pattern, op));
+}
+
+/* Return 1 of the first character of STRING could match the first
+ character of pattern PAT. Used to avoid n2 calls to strmatch(). */
+static int
+match_pattern_char (pat, string)
+ char *pat, *string;
+{
+ char c;
+
+ if (*string == 0)
+ return (0);
+
+ switch (c = *pat++)
+ {
+ default:
+ return (*string == c);
+ case '\\':
+ return (*string == *pat);
+ case '?':
+ return (*pat == LPAREN ? 1 : (*string != '\0'));
+ case '*':
+ return (1);
+ case '+':
+ case '!':
+ case '@':
+ return (*pat == LPAREN ? 1 : (*string == c));
+ case '[':
+ return (*string != '\0');
+ }
+}
+
+/* Match PAT anywhere in STRING and return the match boundaries.
+ This returns 1 in case of a successful match, 0 otherwise. SP
+ and EP are pointers into the string where the match begins and
+ ends, respectively. MTYPE controls what kind of match is attempted.
+ MATCH_BEG and MATCH_END anchor the match at the beginning and end
+ of the string, respectively. The longest match is returned. */
+static int
+match_upattern (string, pat, mtype, sp, ep)
+ char *string, *pat;
+ int mtype;
+ char **sp, **ep;
+{
+ int c, len;
+ register char *p, *p1, *npat;
+ char *end;
+
+ /* If the pattern doesn't match anywhere in the string, go ahead and
+ short-circuit right away. A minor optimization, saves a bunch of
+ unnecessary calls to strmatch (up to N calls for a string of N
+ characters) if the match is unsuccessful. To preserve the semantics
+ of the substring matches below, we make sure that the pattern has
+ `*' as first and last character, making a new pattern if necessary. */
+ /* XXX - check this later if I ever implement `**' with special meaning,
+ since this will potentially result in `**' at the beginning or end */
+ len = STRLEN (pat);
+ if (pat[0] != '*' || pat[len - 1] != '*')
+ {
+ p = npat = (char *)xmalloc (len + 3);
+ p1 = pat;
+ if (*p1 != '*')
+ *p++ = '*';
+ while (*p1)
+ *p++ = *p1++;
+ if (p1[-1] != '*' || p[-2] == '\\')
+ *p++ = '*';
+ *p = '\0';
+ }
+ else
+ npat = pat;
+ c = strmatch (npat, string, FNMATCH_EXTFLAG);
+ if (npat != pat)
+ free (npat);
+ if (c == FNM_NOMATCH)
+ return (0);
+
+ len = STRLEN (string);
+ end = string + len;
+
+ switch (mtype)
+ {
+ case MATCH_ANY:
+ for (p = string; p <= end; p++)
+ {
+ if (match_pattern_char (pat, p))
+ {
+ for (p1 = end; p1 >= p; p1--)
+ {
+ c = *p1; *p1 = '\0';
+ if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
+ {
+ *p1 = c;
+ *sp = p;
+ *ep = p1;
+ return 1;
+ }
+ *p1 = c;
+ }
+ }
+ }
+
+ return (0);
+
+ case MATCH_BEG:
+ if (match_pattern_char (pat, string) == 0)
+ return (0);
+
+ for (p = end; p >= string; p--)
+ {
+ c = *p; *p = '\0';
+ if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
+ {
+ *p = c;
+ *sp = string;
+ *ep = p;
+ return 1;
+ }
+ *p = c;
+ }
+
+ return (0);
+
+ case MATCH_END:
+ for (p = string; p <= end; p++)
+ {
+ if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
+ {
+ *sp = p;
+ *ep = end;
+ return 1;
+ }
+
+ }
+
+ return (0);
+ }
+
+ return (0);
+}
+
+#if defined (HANDLE_MULTIBYTE)
+/* Return 1 of the first character of WSTRING could match the first
+ character of pattern WPAT. Wide character version. */
+static int
+match_pattern_wchar (wpat, wstring)
+ wchar_t *wpat, *wstring;
+{
+ wchar_t wc;
+
+ if (*wstring == 0)
+ return (0);
+
+ switch (wc = *wpat++)
+ {
+ default:
+ return (*wstring == wc);
+ case L'\\':
+ return (*wstring == *wpat);
+ case L'?':
+ return (*wpat == LPAREN ? 1 : (*wstring != L'\0'));
+ case L'*':
+ return (1);
+ case L'+':
+ case L'!':
+ case L'@':
+ return (*wpat == LPAREN ? 1 : (*wstring == wc));
+ case L'[':
+ return (*wstring != L'\0');
+ }
+}
+
+/* Match WPAT anywhere in WSTRING and return the match boundaries.
+ This returns 1 in case of a successful match, 0 otherwise. Wide
+ character version. */
+static int
+match_wpattern (wstring, indices, wstrlen, wpat, mtype, sp, ep)
+ wchar_t *wstring;
+ char **indices;
+ size_t wstrlen;
+ wchar_t *wpat;
+ int mtype;
+ char **sp, **ep;
+{
+ wchar_t wc, *wp, *nwpat, *wp1;
+ int len;
+#if 0
+ size_t n, n1; /* Apple's gcc seems to miscompile this badly */
+#else
+ int n, n1;
+#endif
+
+ /* If the pattern doesn't match anywhere in the string, go ahead and
+ short-circuit right away. A minor optimization, saves a bunch of
+ unnecessary calls to strmatch (up to N calls for a string of N
+ characters) if the match is unsuccessful. To preserve the semantics
+ of the substring matches below, we make sure that the pattern has
+ `*' as first and last character, making a new pattern if necessary. */
+ /* XXX - check this later if I ever implement `**' with special meaning,
+ since this will potentially result in `**' at the beginning or end */
+ len = wcslen (wpat);
+ if (wpat[0] != L'*' || wpat[len - 1] != L'*')
+ {
+ wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
+ wp1 = wpat;
+ if (*wp1 != L'*')
+ *wp++ = L'*';
+ while (*wp1 != L'\0')
+ *wp++ = *wp1++;
+ if (wp1[-1] != L'*' || wp1[-2] == L'\\')
+ *wp++ = L'*';
+ *wp = '\0';
+ }
+ else
+ nwpat = wpat;
+ len = wcsmatch (nwpat, wstring, FNMATCH_EXTFLAG);
+ if (nwpat != wpat)
+ free (nwpat);
+ if (len == FNM_NOMATCH)
+ return (0);
+
+ switch (mtype)
+ {
+ case MATCH_ANY:
+ for (n = 0; n <= wstrlen; n++)
+ {
+ if (match_pattern_wchar (wpat, wstring + n))
+ {
+ for (n1 = wstrlen; n1 >= n; n1--)
+ {
+ wc = wstring[n1]; wstring[n1] = L'\0';
+ if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
+ {
+ wstring[n1] = wc;
+ *sp = indices[n];
+ *ep = indices[n1];
+ return 1;
+ }
+ wstring[n1] = wc;
+ }
+ }
+ }
+
+ return (0);
+
+ case MATCH_BEG:
+ if (match_pattern_wchar (wpat, wstring) == 0)
+ return (0);
+
+ for (n = wstrlen; n >= 0; n--)
+ {
+ wc = wstring[n]; wstring[n] = L'\0';
+ if (wcsmatch (wpat, wstring, FNMATCH_EXTFLAG) == 0)
+ {
+ wstring[n] = wc;
+ *sp = indices[0];
+ *ep = indices[n];
+ return 1;
+ }
+ wstring[n] = wc;
+ }
+
+ return (0);
+
+ case MATCH_END:
+ for (n = 0; n <= wstrlen; n++)
+ {
+ if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
+ {
+ *sp = indices[n];
+ *ep = indices[wstrlen];
+ return 1;
+ }
+ }
+
+ return (0);
+ }
+
+ return (0);
+}
+#endif /* HANDLE_MULTIBYTE */
+
+static int
+match_pattern (string, pat, mtype, sp, ep)
+ char *string, *pat;
+ int mtype;
+ char **sp, **ep;
+{
+#if defined (HANDLE_MULTIBYTE)
+ int ret;
+ size_t n;
+ wchar_t *wstring, *wpat;
+ char **indices;
+#endif
+
+ if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
+ return (0);
+
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1)
+ {
+ n = xdupmbstowcs (&wpat, NULL, pat);
+ if (n == (size_t)-1)
+ return (match_upattern (string, pat, mtype, sp, ep));
+ n = xdupmbstowcs (&wstring, &indices, string);
+ if (n == (size_t)-1)
+ {
+ free (wpat);
+ return (match_upattern (string, pat, mtype, sp, ep));
+ }
+ ret = match_wpattern (wstring, indices, n, wpat, mtype, sp, ep);
+
+ free (wpat);
+ free (wstring);
+ free (indices);
+
+ return (ret);
+ }
+ else
+#endif
+ return (match_upattern (string, pat, mtype, sp, ep));
+}
+
+static int
+getpatspec (c, value)
+ int c;
+ char *value;
+{
+ if (c == '#')
+ return ((*value == '#') ? RP_LONG_LEFT : RP_SHORT_LEFT);
+ else /* c == '%' */
+ return ((*value == '%') ? RP_LONG_RIGHT : RP_SHORT_RIGHT);
+}
+
+/* Posix.2 says that the WORD should be run through tilde expansion,
+ parameter expansion, command substitution and arithmetic expansion.
+ This leaves the result quoted, so quote_string_for_globbing () has
+ to be called to fix it up for strmatch (). If QUOTED is non-zero,
+ it means that the entire expression was enclosed in double quotes.
+ This means that quoting characters in the pattern do not make any
+ special pattern characters quoted. For example, the `*' in the
+ following retains its special meaning: "${foo#'*'}". */
+static char *
+getpattern (value, quoted, expandpat)
+ char *value;
+ int quoted, expandpat;
+{
+ char *pat, *tword;
+ WORD_LIST *l;
+ int i;
+
+ /* There is a problem here: how to handle single or double quotes in the
+ pattern string when the whole expression is between double quotes?
+ POSIX.2 says that enclosing double quotes do not cause the pattern to
+ be quoted, but does that leave us a problem with @ and array[@] and their
+ expansions inside a pattern? */
+#if 0
+ if (expandpat && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *tword)
+ {
+ i = 0;
+ pat = string_extract_double_quoted (tword, &i, 1);
+ free (tword);
+ tword = pat;
+ }
+#endif
+
+ /* expand_string_for_rhs () leaves WORD quoted and does not perform
+ word splitting. */
+ l = *value ? expand_string_for_rhs (value,
+ (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? Q_PATQUOTE : quoted,
+ (int *)NULL, (int *)NULL)
+ : (WORD_LIST *)0;
+ pat = string_list (l);
+ dispose_words (l);
+ if (pat)
+ {
+ tword = quote_string_for_globbing (pat, QGLOB_CVTNULL);
+ free (pat);
+ pat = tword;
+ }
+ return (pat);
+}
+
+#if 0
+/* Handle removing a pattern from a string as a result of ${name%[%]value}
+ or ${name#[#]value}. */
+static char *
+variable_remove_pattern (value, pattern, patspec, quoted)
+ char *value, *pattern;
+ int patspec, quoted;
+{
+ char *tword;
+
+ tword = remove_pattern (value, pattern, patspec);
+
+ return (tword);
+}
+#endif
+
+static char *
+list_remove_pattern (list, pattern, patspec, itype, quoted)
+ WORD_LIST *list;
+ char *pattern;
+ int patspec, itype, quoted;
+{
+ WORD_LIST *new, *l;
+ WORD_DESC *w;
+ char *tword;
+
+ for (new = (WORD_LIST *)NULL, l = list; l; l = l->next)
+ {
+ tword = remove_pattern (l->word->word, pattern, patspec);
+ w = alloc_word_desc ();
+ w->word = tword ? tword : savestring ("");
+ new = make_word_list (w, new);
+ }
+
+ l = REVERSE_LIST (new, WORD_LIST *);
+ if (itype == '*')
+ tword = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (l) : string_list (l);
+ else
+ tword = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (l) : l);
+
+ dispose_words (l);
+ return (tword);
+}
+
+static char *
+parameter_list_remove_pattern (itype, pattern, patspec, quoted)
+ int itype;
+ char *pattern;
+ int patspec, quoted;
+{
+ char *ret;
+ WORD_LIST *list;
+
+ list = list_rest_of_args ();
+ if (list == 0)
+ return ((char *)NULL);
+ ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
+ dispose_words (list);
+ return (ret);
+}
+
+#if defined (ARRAY_VARS)
+static char *
+array_remove_pattern (a, pattern, patspec, varname, quoted)
+ ARRAY *a;
+ char *pattern;
+ int patspec;
+ char *varname; /* so we can figure out how it's indexed */
+ int quoted;
+{
+ int itype;
+ char *ret;
+ WORD_LIST *list;
+ SHELL_VAR *v;
+
+ /* compute itype from varname here */
+ v = array_variable_part (varname, &ret, 0);
+ itype = ret[0];
+
+ list = array_to_word_list (a);
+ if (list == 0)
+ return ((char *)NULL);
+ ret = list_remove_pattern (list, pattern, patspec, itype, quoted);
+ dispose_words (list);
+
+ return ret;
+}
+#endif /* ARRAY_VARS */
+
+static char *
+parameter_brace_remove_pattern (varname, value, patstr, rtype, quoted)
+ char *varname, *value, *patstr;
+ int rtype, quoted;
+{
+ int vtype, patspec, starsub;
+ char *temp1, *val, *pattern;
+ SHELL_VAR *v;
+
+ if (value == 0)
+ return ((char *)NULL);
+
+ this_command_name = varname;
+
+ vtype = get_var_and_type (varname, value, quoted, &v, &val);
+ if (vtype == -1)
+ return ((char *)NULL);
+
+ starsub = vtype & VT_STARSUB;
+ vtype &= ~VT_STARSUB;
+
+ patspec = getpatspec (rtype, patstr);
+ if (patspec == RP_LONG_LEFT || patspec == RP_LONG_RIGHT)
+ patstr++;
+
+ pattern = getpattern (patstr, quoted, 1);
+
+ temp1 = (char *)NULL; /* shut up gcc */
+ switch (vtype)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+ temp1 = remove_pattern (val, pattern, patspec);
+ if (vtype == VT_VARIABLE)
+ FREE (val);
+ if (temp1)
+ {
+ val = quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ temp1 = array_remove_pattern (array_cell (v), pattern, patspec, varname, quoted);
+ if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ {
+ val = quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+#endif
+ case VT_POSPARMS:
+ temp1 = parameter_list_remove_pattern (varname[0], pattern, patspec, quoted);
+ if (temp1 && ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) == 0))
+ {
+ val = quote_escapes (temp1);
+ free (temp1);
+ temp1 = val;
+ }
+ break;
+ }
+
+ FREE (pattern);
+ return temp1;
+}
+
+/*******************************************
+ * *
+ * Functions to expand WORD_DESCs *
+ * *
+ *******************************************/
+
+/* Expand WORD, performing word splitting on the result. This does
+ parameter expansion, command substitution, arithmetic expansion,
+ word splitting, and quote removal. */
+
+WORD_LIST *
+expand_word (word, quoted)
+ WORD_DESC *word;
+ int quoted;
+{
+ WORD_LIST *result, *tresult;
+
+ tresult = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
+ result = word_list_split (tresult);
+ dispose_words (tresult);
+ return (result ? dequote_list (result) : result);
+}
+
+/* Expand WORD, but do not perform word splitting on the result. This
+ does parameter expansion, command substitution, arithmetic expansion,
+ and quote removal. */
+WORD_LIST *
+expand_word_unsplit (word, quoted)
+ WORD_DESC *word;
+ int quoted;
+{
+ WORD_LIST *result;
+
+ expand_no_split_dollar_star = 1;
+ result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
+ expand_no_split_dollar_star = 0;
+
+ return (result ? dequote_list (result) : result);
+}
+
+/* Perform shell expansions on WORD, but do not perform word splitting or
+ quote removal on the result. */
+WORD_LIST *
+expand_word_leave_quoted (word, quoted)
+ WORD_DESC *word;
+ int quoted;
+{
+ return (call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL));
+}
+
+#if defined (PROCESS_SUBSTITUTION)
+
+/*****************************************************************/
+/* */
+/* Hacking Process Substitution */
+/* */
+/*****************************************************************/
+
+#if !defined (HAVE_DEV_FD)
+/* Named pipes must be removed explicitly with `unlink'. This keeps a list
+ of FIFOs the shell has open. unlink_fifo_list will walk the list and
+ unlink all of them. add_fifo_list adds the name of an open FIFO to the
+ list. NFIFO is a count of the number of FIFOs in the list. */
+#define FIFO_INCR 20
+
+struct temp_fifo {
+ char *file;
+ pid_t proc;
+};
+
+static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
+static int nfifo;
+static int fifo_list_size;
+
+static void
+add_fifo_list (pathname)
+ char *pathname;
+{
+ if (nfifo >= fifo_list_size - 1)
+ {
+ fifo_list_size += FIFO_INCR;
+ fifo_list = (struct temp_fifo *)xrealloc (fifo_list,
+ fifo_list_size * sizeof (struct temp_fifo));
+ }
+
+ fifo_list[nfifo].file = savestring (pathname);
+ nfifo++;
+}
+
+void
+unlink_fifo_list ()
+{
+ int saved, i, j;
+
+ if (nfifo == 0)
+ return;
+
+ for (i = saved = 0; i < nfifo; i++)
+ {
+ if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
+ {
+ unlink (fifo_list[i].file);
+ free (fifo_list[i].file);
+ fifo_list[i].file = (char *)NULL;
+ fifo_list[i].proc = -1;
+ }
+ else
+ saved++;
+ }
+
+ /* If we didn't remove some of the FIFOs, compact the list. */
+ if (saved)
+ {
+ for (i = j = 0; i < nfifo; i++)
+ if (fifo_list[i].file)
+ {
+ fifo_list[j].file = fifo_list[i].file;
+ fifo_list[j].proc = fifo_list[i].proc;
+ j++;
+ }
+ nfifo = j;
+ }
+ else
+ nfifo = 0;
+}
+
+static char *
+make_named_pipe ()
+{
+ char *tname;
+
+ tname = sh_mktmpname ("sh-np", MT_USERANDOM);
+ if (mkfifo (tname, 0600) < 0)
+ {
+ free (tname);
+ return ((char *)NULL);
+ }
+
+ add_fifo_list (tname);
+ return (tname);
+}
+
+#else /* HAVE_DEV_FD */
+
+/* DEV_FD_LIST is a bitmap of file descriptors attached to pipes the shell
+ has open to children. NFDS is a count of the number of bits currently
+ set in DEV_FD_LIST. TOTFDS is a count of the highest possible number
+ of open files. */
+static char *dev_fd_list = (char *)NULL;
+static int nfds;
+static int totfds; /* The highest possible number of open files. */
+
+static void
+add_fifo_list (fd)
+ int fd;
+{
+ if (!dev_fd_list || fd >= totfds)
+ {
+ int ofds;
+
+ ofds = totfds;
+ totfds = getdtablesize ();
+ if (totfds < 0 || totfds > 256)
+ totfds = 256;
+ if (fd > totfds)
+ totfds = fd + 2;
+
+ dev_fd_list = (char *)xrealloc (dev_fd_list, totfds);
+ memset (dev_fd_list + ofds, '\0', totfds - ofds);
+ }
+
+ dev_fd_list[fd] = 1;
+ nfds++;
+}
+
+void
+unlink_fifo_list ()
+{
+ register int i;
+
+ if (nfds == 0)
+ return;
+
+ for (i = 0; nfds && i < totfds; i++)
+ if (dev_fd_list[i])
+ {
+ close (i);
+ dev_fd_list[i] = 0;
+ nfds--;
+ }
+
+ nfds = 0;
+}
+
+#if defined (NOTDEF)
+print_dev_fd_list ()
+{
+ register int i;
+
+ fprintf (stderr, "pid %ld: dev_fd_list:", (long)getpid ());
+ fflush (stderr);
+
+ for (i = 0; i < totfds; i++)
+ {
+ if (dev_fd_list[i])
+ fprintf (stderr, " %d", i);
+ }
+ fprintf (stderr, "\n");
+}
+#endif /* NOTDEF */
+
+static char *
+make_dev_fd_filename (fd)
+ int fd;
+{
+ char *ret, intbuf[INT_STRLEN_BOUND (int) + 1], *p;
+
+ ret = (char *)xmalloc (sizeof (DEV_FD_PREFIX) + 4);
+
+ strcpy (ret, DEV_FD_PREFIX);
+ p = inttostr (fd, intbuf, sizeof (intbuf));
+ strcpy (ret + sizeof (DEV_FD_PREFIX) - 1, p);
+
+ add_fifo_list (fd);
+ return (ret);
+}
+
+#endif /* HAVE_DEV_FD */
+
+/* Return a filename that will open a connection to the process defined by
+ executing STRING. HAVE_DEV_FD, if defined, means open a pipe and return
+ a filename in /dev/fd corresponding to a descriptor that is one of the
+ ends of the pipe. If not defined, we use named pipes on systems that have
+ them. Systems without /dev/fd and named pipes are out of luck.
+
+ OPEN_FOR_READ_IN_CHILD, if 1, means open the named pipe for reading or
+ use the read end of the pipe and dup that file descriptor to fd 0 in
+ the child. If OPEN_FOR_READ_IN_CHILD is 0, we open the named pipe for
+ writing or use the write end of the pipe in the child, and dup that
+ file descriptor to fd 1 in the child. The parent does the opposite. */
+
+static char *
+process_substitute (string, open_for_read_in_child)
+ char *string;
+ int open_for_read_in_child;
+{
+ char *pathname;
+ int fd, result;
+ pid_t old_pid, pid;
+#if defined (HAVE_DEV_FD)
+ int parent_pipe_fd, child_pipe_fd;
+ int fildes[2];
+#endif /* HAVE_DEV_FD */
+#if defined (JOB_CONTROL)
+ pid_t old_pipeline_pgrp;
+#endif
+
+ if (!string || !*string || wordexp_only)
+ return ((char *)NULL);
+
+#if !defined (HAVE_DEV_FD)
+ pathname = make_named_pipe ();
+#else /* HAVE_DEV_FD */
+ if (pipe (fildes) < 0)
+ {
+ sys_error (_("cannot make pipe for process substitution"));
+ return ((char *)NULL);
+ }
+ /* If OPEN_FOR_READ_IN_CHILD == 1, we want to use the write end of
+ the pipe in the parent, otherwise the read end. */
+ parent_pipe_fd = fildes[open_for_read_in_child];
+ child_pipe_fd = fildes[1 - open_for_read_in_child];
+ /* Move the parent end of the pipe to some high file descriptor, to
+ avoid clashes with FDs used by the script. */
+ parent_pipe_fd = move_to_high_fd (parent_pipe_fd, 1, 64);
+
+ pathname = make_dev_fd_filename (parent_pipe_fd);
+#endif /* HAVE_DEV_FD */
+
+ if (!pathname)
+ {
+ sys_error (_("cannot make pipe for process substitution"));
+ return ((char *)NULL);
+ }
+
+ old_pid = last_made_pid;
+
+#if defined (JOB_CONTROL)
+ old_pipeline_pgrp = pipeline_pgrp;
+ pipeline_pgrp = shell_pgrp;
+ save_pipeline (1);
+#endif /* JOB_CONTROL */
+
+ pid = make_child ((char *)NULL, 1);
+ if (pid == 0)
+ {
+ reset_terminating_signals (); /* XXX */
+ free_pushed_string_input ();
+ /* Cancel traps, in trap.c. */
+ restore_original_signals ();
+ setup_async_signals ();
+ subshell_environment |= SUBSHELL_COMSUB;
+ }
+
+#if defined (JOB_CONTROL)
+ set_sigchld_handler ();
+ stop_making_children ();
+ pipeline_pgrp = old_pipeline_pgrp;
+#endif /* JOB_CONTROL */
+
+ if (pid < 0)
+ {
+ sys_error (_("cannot make child for process substitution"));
+ free (pathname);
+#if defined (HAVE_DEV_FD)
+ close (parent_pipe_fd);
+ close (child_pipe_fd);
+#endif /* HAVE_DEV_FD */
+ return ((char *)NULL);
+ }
+
+ if (pid > 0)
+ {
+#if defined (JOB_CONTROL)
+ restore_pipeline (1);
+#endif
+
+#if !defined (HAVE_DEV_FD)
+ fifo_list[nfifo-1].proc = pid;
+#endif
+
+ last_made_pid = old_pid;
+
+#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
+ close_pgrp_pipe ();
+#endif /* JOB_CONTROL && PGRP_PIPE */
+
+#if defined (HAVE_DEV_FD)
+ close (child_pipe_fd);
+#endif /* HAVE_DEV_FD */
+
+ return (pathname);
+ }
+
+ set_sigint_handler ();
+
+#if defined (JOB_CONTROL)
+ set_job_control (0);
+#endif /* JOB_CONTROL */
+
+#if !defined (HAVE_DEV_FD)
+ /* Open the named pipe in the child. */
+ fd = open (pathname, open_for_read_in_child ? O_RDONLY|O_NONBLOCK : O_WRONLY);
+ if (fd < 0)
+ {
+ /* Two separate strings for ease of translation. */
+ if (open_for_read_in_child)
+ sys_error (_("cannot open named pipe %s for reading"), pathname);
+ else
+ sys_error (_("cannot open named pipe %s for writing"), pathname);
+
+ exit (127);
+ }
+ if (open_for_read_in_child)
+ {
+ if (sh_unset_nodelay_mode (fd) < 0)
+ {
+ sys_error (_("cannout reset nodelay mode for fd %d"), fd);
+ exit (127);
+ }
+ }
+#else /* HAVE_DEV_FD */
+ fd = child_pipe_fd;
+#endif /* HAVE_DEV_FD */
+
+ if (dup2 (fd, open_for_read_in_child ? 0 : 1) < 0)
+ {
+ sys_error (_("cannot duplicate named pipe %s as fd %d"), pathname,
+ open_for_read_in_child ? 0 : 1);
+ exit (127);
+ }
+
+ if (fd != (open_for_read_in_child ? 0 : 1))
+ close (fd);
+
+ /* Need to close any files that this process has open to pipes inherited
+ from its parent. */
+ if (current_fds_to_close)
+ {
+ close_fd_bitmap (current_fds_to_close);
+ current_fds_to_close = (struct fd_bitmap *)NULL;
+ }
+
+#if defined (HAVE_DEV_FD)
+ /* Make sure we close the parent's end of the pipe and clear the slot
+ in the fd list so it is not closed later, if reallocated by, for
+ instance, pipe(2). */
+ close (parent_pipe_fd);
+ dev_fd_list[parent_pipe_fd] = 0;
+#endif /* HAVE_DEV_FD */
+
+ result = parse_and_execute (string, "process substitution", (SEVAL_NONINT|SEVAL_NOHIST));
+
+#if !defined (HAVE_DEV_FD)
+ /* Make sure we close the named pipe in the child before we exit. */
+ close (open_for_read_in_child ? 0 : 1);
+#endif /* !HAVE_DEV_FD */
+
+ exit (result);
+ /*NOTREACHED*/
+}
+#endif /* PROCESS_SUBSTITUTION */
+
+/***********************************/
+/* */
+/* Command Substitution */
+/* */
+/***********************************/
+
+static char *
+read_comsub (fd, quoted)
+ int fd, quoted;
+{
+ char *istring, buf[128], *bufp;
+ int istring_index, istring_size, c;
+ ssize_t bufn;
+
+ istring = (char *)NULL;
+ istring_index = istring_size = bufn = 0;
+
+#ifdef __CYGWIN__
+ setmode (fd, O_TEXT); /* we don't want CR/LF, we want Unix-style */
+#endif
+
+ /* Read the output of the command through the pipe. */
+ while (1)
+ {
+ if (fd < 0)
+ break;
+ if (--bufn <= 0)
+ {
+ bufn = zread (fd, buf, sizeof (buf));
+ if (bufn <= 0)
+ break;
+ bufp = buf;
+ }
+ c = *bufp++;
+
+ if (c == 0)
+ {
+#if 0
+ internal_warning ("read_comsub: ignored null byte in input");
+#endif
+ continue;
+ }
+
+ /* Add the character to ISTRING, possibly after resizing it. */
+ RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE);
+
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || c == CTLESC || c == CTLNUL)
+ istring[istring_index++] = CTLESC;
+
+ istring[istring_index++] = c;
+
+#if 0
+#if defined (__CYGWIN__)
+ if (c == '\n' && istring_index > 1 && istring[istring_index - 2] == '\r')
+ {
+ istring_index--;
+ istring[istring_index - 1] = '\n';
+ }
+#endif
+#endif
+ }
+
+ if (istring)
+ istring[istring_index] = '\0';
+
+ /* If we read no output, just return now and save ourselves some
+ trouble. */
+ if (istring_index == 0)
+ {
+ FREE (istring);
+ return (char *)NULL;
+ }
+
+ /* Strip trailing newlines from the output of the command. */
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ {
+ while (istring_index > 0)
+ {
+ if (istring[istring_index - 1] == '\n')
+ {
+ --istring_index;
+
+ /* If the newline was quoted, remove the quoting char. */
+ if (istring[istring_index - 1] == CTLESC)
+ --istring_index;
+ }
+ else
+ break;
+ }
+ istring[istring_index] = '\0';
+ }
+ else
+ strip_trailing (istring, istring_index - 1, 1);
+
+ return istring;
+}
+
+/* Perform command substitution on STRING. This returns a string,
+ possibly quoted. */
+char *
+command_substitute (string, quoted)
+ char *string;
+ int quoted;
+{
+ pid_t pid, old_pid, old_pipeline_pgrp, old_async_pid;
+ char *istring;
+ int result, fildes[2], function_value, pflags, rc;
+
+ istring = (char *)NULL;
+
+ /* Don't fork () if there is no need to. In the case of no command to
+ run, just return NULL. */
+ if (!string || !*string || (string[0] == '\n' && !string[1]))
+ return ((char *)NULL);
+
+ if (wordexp_only && read_but_dont_execute)
+ {
+ last_command_exit_value = 125;
+ jump_to_top_level (EXITPROG);
+ }
+
+ /* We're making the assumption here that the command substitution will
+ eventually run a command from the file system. Since we'll run
+ maybe_make_export_env in this subshell before executing that command,
+ the parent shell and any other shells it starts will have to remake
+ the environment. If we make it before we fork, other shells won't
+ have to. Don't bother if we have any temporary variable assignments,
+ though, because the export environment will be remade after this
+ command completes anyway, but do it if all the words to be expanded
+ are variable assignments. */
+ if (subst_assign_varlist == 0 || garglist == 0)
+ maybe_make_export_env (); /* XXX */
+
+ /* Flags to pass to parse_and_execute() */
+ pflags = interactive ? SEVAL_RESETLINE : 0;
+
+ /* Pipe the output of executing STRING into the current shell. */
+ if (pipe (fildes) < 0)
+ {
+ sys_error (_("cannot make pipe for command substitution"));
+ goto error_exit;
+ }
+
+ old_pid = last_made_pid;
+#if defined (JOB_CONTROL)
+ old_pipeline_pgrp = pipeline_pgrp;
+ /* Don't reset the pipeline pgrp if we're already a subshell in a pipeline. */
+ if ((subshell_environment & SUBSHELL_PIPE) == 0)
+ pipeline_pgrp = shell_pgrp;
+ cleanup_the_pipeline ();
+#endif /* JOB_CONTROL */
+
+ old_async_pid = last_asynchronous_pid;
+#if 0
+ pid = make_child ((char *)NULL, 0);
+#else
+ pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
+#endif
+ last_asynchronous_pid = old_async_pid;
+
+ if (pid == 0)
+ /* Reset the signal handlers in the child, but don't free the
+ trap strings. */
+ reset_signal_handlers ();
+
+#if defined (JOB_CONTROL)
+ set_sigchld_handler ();
+ stop_making_children ();
+ pipeline_pgrp = old_pipeline_pgrp;
+#else
+ stop_making_children ();
+#endif /* JOB_CONTROL */
+
+ if (pid < 0)
+ {
+ sys_error (_("cannot make child for command substitution"));
+ error_exit:
+
+ FREE (istring);
+ close (fildes[0]);
+ close (fildes[1]);
+ return ((char *)NULL);
+ }
+
+ if (pid == 0)
+ {
+ set_sigint_handler (); /* XXX */
+
+ free_pushed_string_input ();
+
+ if (dup2 (fildes[1], 1) < 0)
+ {
+ sys_error (_("command_substitute: cannot duplicate pipe as fd 1"));
+ exit (EXECUTION_FAILURE);
+ }
+
+ /* If standard output is closed in the parent shell
+ (such as after `exec >&-'), file descriptor 1 will be
+ the lowest available file descriptor, and end up in
+ fildes[0]. This can happen for stdin and stderr as well,
+ but stdout is more important -- it will cause no output
+ to be generated from this command. */
+ if ((fildes[1] != fileno (stdin)) &&
+ (fildes[1] != fileno (stdout)) &&
+ (fildes[1] != fileno (stderr)))
+ close (fildes[1]);
+
+ if ((fildes[0] != fileno (stdin)) &&
+ (fildes[0] != fileno (stdout)) &&
+ (fildes[0] != fileno (stderr)))
+ close (fildes[0]);
+
+ /* The currently executing shell is not interactive. */
+ interactive = 0;
+
+ /* This is a subshell environment. */
+ subshell_environment |= SUBSHELL_COMSUB;
+
+ /* When not in POSIX mode, command substitution does not inherit
+ the -e flag. */
+ if (posixly_correct == 0)
+ exit_immediately_on_error = 0;
+
+ remove_quoted_escapes (string);
+
+ startup_state = 2; /* see if we can avoid a fork */
+ /* Give command substitution a place to jump back to on failure,
+ so we don't go back up to main (). */
+ result = setjmp (top_level);
+
+ /* If we're running a command substitution inside a shell function,
+ trap `return' so we don't return from the function in the subshell
+ and go off to never-never land. */
+ if (result == 0 && return_catch_flag)
+ function_value = setjmp (return_catch);
+ else
+ function_value = 0;
+
+ if (result == ERREXIT)
+ rc = last_command_exit_value;
+ else if (result == EXITPROG)
+ rc = last_command_exit_value;
+ else if (result)
+ rc = EXECUTION_FAILURE;
+ else if (function_value)
+ rc = return_catch_value;
+ else
+ {
+ subshell_level++;
+ rc = parse_and_execute (string, "command substitution", pflags|SEVAL_NOHIST);
+ subshell_level--;
+ }
+
+ last_command_exit_value = rc;
+ rc = run_exit_trap ();
+ exit (rc);
+ }
+ else
+ {
+#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
+ close_pgrp_pipe ();
+#endif /* JOB_CONTROL && PGRP_PIPE */
+
+ close (fildes[1]);
+
+ istring = read_comsub (fildes[0], quoted);
+
+ close (fildes[0]);
+
+ current_command_subst_pid = pid;
+ last_command_exit_value = wait_for (pid);
+ last_command_subst_pid = pid;
+ last_made_pid = old_pid;
+
+#if defined (JOB_CONTROL)
+ /* If last_command_exit_value > 128, then the substituted command
+ was terminated by a signal. If that signal was SIGINT, then send
+ SIGINT to ourselves. This will break out of loops, for instance. */
+ if (last_command_exit_value == (128 + SIGINT) && last_command_exit_signal == SIGINT)
+ kill (getpid (), SIGINT);
+
+ /* wait_for gives the terminal back to shell_pgrp. If some other
+ process group should have it, give it away to that group here.
+ pipeline_pgrp is non-zero only while we are constructing a
+ pipline, so what we are concerned about is whether or not that
+ pipeline was started in the background. A pipeline started in
+ the background should never get the tty back here. */
+#if 0
+ if (interactive && pipeline_pgrp != (pid_t)0 && pipeline_pgrp != last_asynchronous_pid)
+#else
+ if (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
+#endif
+ give_terminal_to (pipeline_pgrp, 0);
+#endif /* JOB_CONTROL */
+
+ return (istring);
+ }
+}
+
+/********************************************************
+ * *
+ * Utility functions for parameter expansion *
+ * *
+ ********************************************************/
+
+#if defined (ARRAY_VARS)
+
+static arrayind_t
+array_length_reference (s)
+ char *s;
+{
+ int len;
+ arrayind_t ind;
+ char *t, c;
+ ARRAY *array;
+ SHELL_VAR *var;
+
+ var = array_variable_part (s, &t, &len);
+
+ /* If unbound variables should generate an error, report one and return
+ failure. */
+ if ((var == 0 || array_p (var) == 0) && unbound_vars_is_error)
+ {
+ c = *--t;
+ *t = '\0';
+ err_unboundvar (s);
+ *t = c;
+ return (-1);
+ }
+ else if (var == 0)
+ return 0;
+
+ /* We support a couple of expansions for variables that are not arrays.
+ We'll return the length of the value for v[0], and 1 for v[@] or
+ v[*]. Return 0 for everything else. */
+
+ array = array_p (var) ? array_cell (var) : (ARRAY *)NULL;
+
+ if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
+ return (array_p (var) ? array_num_elements (array) : 1);
+
+ ind = array_expand_index (t, len);
+ if (ind < 0)
+ {
+ err_badarraysub (t);
+ return (-1);
+ }
+
+ if (array_p (var))
+ t = array_reference (array, ind);
+ else
+ t = (ind == 0) ? value_cell (var) : (char *)NULL;
+
+ len = STRLEN (t);
+ return (len);
+}
+#endif /* ARRAY_VARS */
+
+static int
+valid_brace_expansion_word (name, var_is_special)
+ char *name;
+ int var_is_special;
+{
+ if (DIGIT (*name) && all_digits (name))
+ return 1;
+ else if (var_is_special)
+ return 1;
+#if defined (ARRAY_VARS)
+ else if (valid_array_reference (name))
+ return 1;
+#endif /* ARRAY_VARS */
+ else if (legal_identifier (name))
+ return 1;
+ else
+ return 0;
+}
+
+static int
+chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
+ char *name;
+ int quoted;
+ int *quoted_dollar_atp, *contains_dollar_at;
+{
+ char *temp1;
+
+ if (name == 0)
+ {
+ if (quoted_dollar_atp)
+ *quoted_dollar_atp = 0;
+ if (contains_dollar_at)
+ *contains_dollar_at = 0;
+ return 0;
+ }
+
+ /* check for $@ and $* */
+ if (name[0] == '@' && name[1] == 0)
+ {
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ return 1;
+ }
+ else if (name[0] == '*' && name[1] == '\0' && quoted == 0)
+ {
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ return 1;
+ }
+
+ /* Now check for ${array[@]} and ${array[*]} */
+#if defined (ARRAY_VARS)
+ else if (valid_array_reference (name))
+ {
+ temp1 = xstrchr (name, '[');
+ if (temp1 && temp1[1] == '@' && temp1[2] == ']')
+ {
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ return 1;
+ } /* [ */
+ /* ${array[*]}, when unquoted, should be treated like ${array[@]},
+ which should result in separate words even when IFS is unset. */
+ if (temp1 && temp1[1] == '*' && temp1[2] == ']' && quoted == 0)
+ {
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
+
+/* Parameter expand NAME, and return a new string which is the expansion,
+ or NULL if there was no expansion.
+ VAR_IS_SPECIAL is non-zero if NAME is one of the special variables in
+ the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
+ NAME was found inside of a double-quoted expression. */
+static WORD_DESC *
+parameter_brace_expand_word (name, var_is_special, quoted)
+ char *name;
+ int var_is_special, quoted;
+{
+ WORD_DESC *ret;
+ char *temp, *tt;
+ intmax_t arg_index;
+ SHELL_VAR *var;
+ int atype;
+
+ ret = 0;
+ temp = 0;
+
+ /* Handle multiple digit arguments, as in ${11}. */
+ if (legal_number (name, &arg_index))
+ {
+ tt = get_dollar_var_value (arg_index);
+ if (tt)
+ temp = (*tt && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ ? quote_string (tt)
+ : quote_escapes (tt);
+ else
+ temp = (char *)NULL;
+ FREE (tt);
+ }
+ else if (var_is_special) /* ${@} */
+ {
+ int sindex;
+ tt = (char *)xmalloc (2 + strlen (name));
+ tt[sindex = 0] = '$';
+ strcpy (tt + 1, name);
+
+ ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
+ (int *)NULL, (int *)NULL, 0);
+ free (tt);
+ }
+#if defined (ARRAY_VARS)
+ else if (valid_array_reference (name))
+ {
+ temp = array_value (name, quoted, &atype);
+ if (atype == 0 && temp)
+ temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ ? quote_string (temp)
+ : quote_escapes (temp);
+ }
+#endif
+ else if (var = find_variable (name))
+ {
+ if (var_isset (var) && invisible_p (var) == 0)
+ {
+#if defined (ARRAY_VARS)
+ temp = array_p (var) ? array_reference (array_cell (var), 0) : value_cell (var);
+#else
+ temp = value_cell (var);
+#endif
+
+ if (temp)
+ temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ ? quote_string (temp)
+ : quote_escapes (temp);
+ }
+ else
+ temp = (char *)NULL;
+ }
+ else
+ temp = (char *)NULL;
+
+ if (ret == 0)
+ {
+ ret = alloc_word_desc ();
+ ret->word = temp;
+ }
+ return ret;
+}
+
+/* Expand an indirect reference to a variable: ${!NAME} expands to the
+ value of the variable whose name is the value of NAME. */
+static WORD_DESC *
+parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at)
+ char *name;
+ int var_is_special, quoted;
+ int *quoted_dollar_atp, *contains_dollar_at;
+{
+ char *temp, *t;
+ WORD_DESC *w;
+
+ w = parameter_brace_expand_word (name, var_is_special, quoted);
+ t = w->word;
+ /* Have to dequote here if necessary */
+ if (t)
+ {
+ temp = (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ ? dequote_string (t)
+ : dequote_escapes (t);
+ free (t);
+ t = temp;
+ }
+ dispose_word_desc (w);
+
+ chk_atstar (t, quoted, quoted_dollar_atp, contains_dollar_at);
+ if (t == 0)
+ return (WORD_DESC *)NULL;
+
+ w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
+ free (t);
+
+ return w;
+}
+
+/* Expand the right side of a parameter expansion of the form ${NAMEcVALUE},
+ depending on the value of C, the separating character. C can be one of
+ "-", "+", or "=". QUOTED is true if the entire brace expression occurs
+ between double quotes. */
+static WORD_DESC *
+parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
+ char *name, *value;
+ int c, quoted, *qdollaratp, *hasdollarat;
+{
+ WORD_DESC *w;
+ WORD_LIST *l;
+ char *t, *t1, *temp;
+ int hasdol;
+
+ /* If the entire expression is between double quotes, we want to treat
+ the value as a double-quoted string, with the exception that we strip
+ embedded unescaped double quotes. */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && *value)
+ {
+ hasdol = 0;
+ temp = string_extract_double_quoted (value, &hasdol, 1);
+ }
+ else
+ temp = value;
+
+ w = alloc_word_desc ();
+ hasdol = 0;
+ /* XXX was 0 not quoted */
+ l = *temp ? expand_string_for_rhs (temp, quoted, &hasdol, (int *)NULL)
+ : (WORD_LIST *)0;
+ if (hasdollarat)
+ *hasdollarat = hasdol || (l && l->next);
+ if (temp != value)
+ free (temp);
+ if (l)
+ {
+ /* The expansion of TEMP returned something. We need to treat things
+ slightly differently if HASDOL is non-zero. If we have "$@", the
+ individual words have already been quoted. We need to turn them
+ into a string with the words separated by the first character of
+ $IFS without any additional quoting, so string_list_dollar_at won't
+ do the right thing. We use string_list_dollar_star instead. */
+ temp = (hasdol || l->next) ? string_list_dollar_star (l) : string_list (l);
+
+ /* If l->next is not null, we know that TEMP contained "$@", since that
+ is the only expansion that creates more than one word. */
+ if (qdollaratp && ((hasdol && quoted) || l->next))
+ *qdollaratp = 1;
+ dispose_words (l);
+ }
+ else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && hasdol)
+ {
+ /* The brace expansion occurred between double quotes and there was
+ a $@ in TEMP. It does not matter if the $@ is quoted, as long as
+ it does not expand to anything. In this case, we want to return
+ a quoted empty string. */
+ temp = (char *)xmalloc (2);
+ temp[0] = CTLNUL;
+ temp[1] = '\0';
+ w->flags |= W_HASQUOTEDNULL;
+ }
+ else
+ temp = (char *)NULL;
+
+ if (c == '-' || c == '+')
+ {
+ w->word = temp;
+ return w;
+ }
+
+ /* c == '=' */
+ t = temp ? savestring (temp) : savestring ("");
+ t1 = dequote_string (t);
+ free (t);
+#if defined (ARRAY_VARS)
+ if (valid_array_reference (name))
+ assign_array_element (name, t1, 0);
+ else
+#endif /* ARRAY_VARS */
+ bind_variable (name, t1, 0);
+ free (t1);
+
+ w->word = temp;
+ return w;
+}
+
+/* Deal with the right hand side of a ${name:?value} expansion in the case
+ that NAME is null or not set. If VALUE is non-null it is expanded and
+ used as the error message to print, otherwise a standard message is
+ printed. */
+static void
+parameter_brace_expand_error (name, value)
+ char *name, *value;
+{
+ WORD_LIST *l;
+ char *temp;
+
+ if (value && *value)
+ {
+ l = expand_string (value, 0);
+ temp = string_list (l);
+ report_error ("%s: %s", name, temp ? temp : ""); /* XXX was value not "" */
+ FREE (temp);
+ dispose_words (l);
+ }
+ else
+ report_error (_("%s: parameter null or not set"), name);
+
+ /* Free the data we have allocated during this expansion, since we
+ are about to longjmp out. */
+ free (name);
+ FREE (value);
+}
+
+/* Return 1 if NAME is something for which parameter_brace_expand_length is
+ OK to do. */
+static int
+valid_length_expression (name)
+ char *name;
+{
+ return (name[1] == '\0' || /* ${#} */
+ ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0') || /* special param */
+ (DIGIT (name[1]) && all_digits (name + 1)) || /* ${#11} */
+#if defined (ARRAY_VARS)
+ valid_array_reference (name + 1) || /* ${#a[7]} */
+#endif
+ legal_identifier (name + 1)); /* ${#PS1} */
+}
+
+#if defined (HANDLE_MULTIBYTE)
+size_t
+mbstrlen (s)
+ const char *s;
+{
+ size_t clen, nc;
+ mbstate_t mbs, mbsbak;
+
+ nc = 0;
+ memset (&mbs, 0, sizeof (mbs));
+ mbsbak = mbs;
+ while ((clen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0)
+ {
+ if (MB_INVALIDCH(clen))
+ {
+ clen = 1; /* assume single byte */
+ mbs = mbsbak;
+ }
+
+ s += clen;
+ nc++;
+ mbsbak = mbs;
+ }
+ return nc;
+}
+#endif
+
+
+/* Handle the parameter brace expansion that requires us to return the
+ length of a parameter. */
+static intmax_t
+parameter_brace_expand_length (name)
+ char *name;
+{
+ char *t, *newname;
+ intmax_t number, arg_index;
+ WORD_LIST *list;
+#if defined (ARRAY_VARS)
+ SHELL_VAR *var;
+#endif
+
+ if (name[1] == '\0') /* ${#} */
+ number = number_of_args ();
+ else if ((name[1] == '@' || name[1] == '*') && name[2] == '\0') /* ${#@}, ${#*} */
+ number = number_of_args ();
+ else if ((sh_syntaxtab[(unsigned char) name[1]] & CSPECVAR) && name[2] == '\0')
+ {
+ /* Take the lengths of some of the shell's special parameters. */
+ switch (name[1])
+ {
+ case '-':
+ t = which_set_flags ();
+ break;
+ case '?':
+ t = itos (last_command_exit_value);
+ break;
+ case '$':
+ t = itos (dollar_dollar_pid);
+ break;
+ case '!':
+ if (last_asynchronous_pid == NO_PID)
+ t = (char *)NULL;
+ else
+ t = itos (last_asynchronous_pid);
+ break;
+ case '#':
+ t = itos (number_of_args ());
+ break;
+ }
+ number = STRLEN (t);
+ FREE (t);
+ }
+#if defined (ARRAY_VARS)
+ else if (valid_array_reference (name + 1))
+ number = array_length_reference (name + 1);
+#endif /* ARRAY_VARS */
+ else
+ {
+ number = 0;
+
+ if (legal_number (name + 1, &arg_index)) /* ${#1} */
+ {
+ t = get_dollar_var_value (arg_index);
+ number = MB_STRLEN (t);
+ FREE (t);
+ }
+#if defined (ARRAY_VARS)
+ else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && array_p (var))
+ {
+ t = array_reference (array_cell (var), 0);
+ number = MB_STRLEN (t);
+ }
+#endif
+ else /* ${#PS1} */
+ {
+ newname = savestring (name);
+ newname[0] = '$';
+ list = expand_string (newname, Q_DOUBLE_QUOTES);
+ t = list ? string_list (list) : (char *)NULL;
+ free (newname);
+ if (list)
+ dispose_words (list);
+
+ number = MB_STRLEN (t);
+ FREE (t);
+ }
+ }
+
+ return (number);
+}
+
+/* Skip characters in SUBSTR until DELIM. SUBSTR is an arithmetic expression,
+ so we do some ad-hoc parsing of an arithmetic expression to find
+ the first DELIM, instead of using strchr(3). Two rules:
+ 1. If the substring contains a `(', read until closing `)'.
+ 2. If the substring contains a `?', read past one `:' for each `?'.
+*/
+
+static char *
+skiparith (substr, delim)
+ char *substr;
+ int delim;
+{
+ size_t sublen;
+ int skipcol, pcount, i;
+ DECLARE_MBSTATE;
+
+ sublen = strlen (substr);
+ i = skipcol = pcount = 0;
+ while (substr[i])
+ {
+ /* Balance parens */
+ if (substr[i] == LPAREN)
+ {
+ pcount++;
+ i++;
+ continue;
+ }
+ if (substr[i] == RPAREN && pcount)
+ {
+ pcount--;
+ i++;
+ continue;
+ }
+ if (pcount)
+ {
+ ADVANCE_CHAR (substr, sublen, i);
+ continue;
+ }
+
+ /* Skip one `:' for each `?' */
+ if (substr[i] == ':' && skipcol)
+ {
+ skipcol--;
+ i++;
+ continue;
+ }
+ if (substr[i] == delim)
+ break;
+ if (substr[i] == '?')
+ {
+ skipcol++;
+ i++;
+ continue;
+ }
+ ADVANCE_CHAR (substr, sublen, i);
+ }
+
+ return (substr + i);
+}
+
+/* Verify and limit the start and end of the desired substring. If
+ VTYPE == 0, a regular shell variable is being used; if it is 1,
+ then the positional parameters are being used; if it is 2, then
+ VALUE is really a pointer to an array variable that should be used.
+ Return value is 1 if both values were OK, 0 if there was a problem
+ with an invalid expression, or -1 if the values were out of range. */
+static int
+verify_substring_values (value, substr, vtype, e1p, e2p)
+ char *value, *substr;
+ int vtype;
+ intmax_t *e1p, *e2p;
+{
+ char *t, *temp1, *temp2;
+ arrayind_t len;
+ int expok;
+#if defined (ARRAY_VARS)
+ ARRAY *a;
+#endif
+
+ /* duplicate behavior of strchr(3) */
+ t = skiparith (substr, ':');
+ if (*t && *t == ':')
+ *t = '\0';
+ 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)
+ return (0);
+
+ len = -1; /* paranoia */
+ switch (vtype)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+ len = MB_STRLEN (value);
+ break;
+ case VT_POSPARMS:
+ len = number_of_args () + 1;
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ a = (ARRAY *)value;
+ /* For arrays, the first value deals with array indices. Negative
+ offsets count from one past the array's maximum index. */
+ len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
+ break;
+#endif
+ }
+
+ if (len == -1) /* paranoia */
+ return -1;
+
+ if (*e1p < 0) /* negative offsets count from end */
+ *e1p += len;
+
+ if (*e1p > len || *e1p < 0)
+ return (-1);
+
+#if defined (ARRAY_VARS)
+ /* For arrays, the second offset deals with the number of elements. */
+ if (vtype == VT_ARRAYVAR)
+ len = array_num_elements (a);
+#endif
+
+ if (t)
+ {
+ 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);
+ free (temp1);
+ if (expok == 0)
+ return (0);
+ if (*e2p < 0)
+ {
+ internal_error (_("%s: substring expression < 0"), t);
+ return (0);
+ }
+#if defined (ARRAY_VARS)
+ /* In order to deal with sparse arrays, push the intelligence about how
+ to deal with the number of elements desired down to the array-
+ specific functions. */
+ if (vtype != VT_ARRAYVAR)
+#endif
+ {
+ *e2p += *e1p; /* want E2 chars starting at E1 */
+ if (*e2p > len)
+ *e2p = len;
+ }
+ }
+ else
+ *e2p = len;
+
+ return (1);
+}
+
+/* Return the type of variable specified by VARNAME (simple variable,
+ positional param, or array variable). Also return the value specified
+ by VARNAME (value of a variable or a reference to an array element).
+ If this returns VT_VARIABLE, the caller assumes that CTLESC and CTLNUL
+ characters in the value are quoted with CTLESC and takes appropriate
+ steps. For convenience, *VALP is set to the dequoted VALUE. */
+static int
+get_var_and_type (varname, value, quoted, varp, valp)
+ char *varname, *value;
+ int quoted;
+ SHELL_VAR **varp;
+ char **valp;
+{
+ int vtype;
+ char *temp;
+#if defined (ARRAY_VARS)
+ SHELL_VAR *v;
+#endif
+
+ /* This sets vtype to VT_VARIABLE or VT_POSPARMS */
+ vtype = (varname[0] == '@' || varname[0] == '*') && varname[1] == '\0';
+ if (vtype == VT_POSPARMS && varname[0] == '*')
+ vtype |= VT_STARSUB;
+ *varp = (SHELL_VAR *)NULL;
+
+#if defined (ARRAY_VARS)
+ if (valid_array_reference (varname))
+ {
+ v = array_variable_part (varname, &temp, (int *)0);
+ if (v && array_p (v))
+ { /* [ */
+ if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
+ {
+ vtype = VT_ARRAYVAR;
+ if (temp[0] == '*')
+ vtype |= VT_STARSUB;
+ *valp = (char *)array_cell (v);
+ }
+ else
+ {
+ vtype = VT_ARRAYMEMBER;
+ *valp = array_value (varname, 1, (int *)NULL);
+ }
+ *varp = v;
+ }
+ else if (v && (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']'))
+ {
+ vtype = VT_VARIABLE;
+ *varp = v;
+ if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ *valp = dequote_string (value);
+ else
+ *valp = dequote_escapes (value);
+ }
+ else
+ return -1;
+ }
+ else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && array_p (v))
+ {
+ vtype = VT_ARRAYMEMBER;
+ *varp = v;
+ *valp = array_reference (array_cell (v), 0);
+ }
+ else
+#endif
+ {
+ if (value && vtype == VT_VARIABLE)
+ {
+ if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ *valp = dequote_string (value);
+ else
+ *valp = dequote_escapes (value);
+ }
+ else
+ *valp = value;
+ }
+
+ return vtype;
+}
+
+/******************************************************/
+/* */
+/* Functions to extract substrings of variable values */
+/* */
+/******************************************************/
+
+#if defined (HANDLE_MULTIBYTE)
+/* Character-oriented rather than strictly byte-oriented substrings. S and
+ E, rather being strict indices into STRING, indicate character (possibly
+ multibyte character) positions that require calculation.
+ Used by the ${param:offset[:length]} expansion. */
+static char *
+mb_substring (string, s, e)
+ char *string;
+ int s, e;
+{
+ char *tt;
+ int start, stop, i, slen;
+ DECLARE_MBSTATE;
+
+ start = 0;
+ /* Don't need string length in ADVANCE_CHAR unless multibyte chars possible. */
+ slen = (MB_CUR_MAX > 1) ? STRLEN (string) : 0;
+
+ i = s;
+ while (string[start] && i--)
+ ADVANCE_CHAR (string, slen, start);
+ stop = start;
+ i = e - s;
+ while (string[stop] && i--)
+ ADVANCE_CHAR (string, slen, stop);
+ tt = substring (string, start, stop);
+ return tt;
+}
+#endif
+
+/* Process a variable substring expansion: ${name:e1[:e2]}. If VARNAME
+ is `@', use the positional parameters; otherwise, use the value of
+ VARNAME. If VARNAME is an array variable, use the array elements. */
+
+static char *
+parameter_brace_substring (varname, value, substr, quoted)
+ char *varname, *value, *substr;
+ int quoted;
+{
+ intmax_t e1, e2;
+ int vtype, r, starsub;
+ char *temp, *val, *tt;
+ SHELL_VAR *v;
+
+ if (value == 0)
+ return ((char *)NULL);
+
+ this_command_name = varname;
+
+ vtype = get_var_and_type (varname, value, quoted, &v, &val);
+ if (vtype == -1)
+ return ((char *)NULL);
+
+ starsub = vtype & VT_STARSUB;
+ vtype &= ~VT_STARSUB;
+
+ r = verify_substring_values (val, substr, vtype, &e1, &e2);
+ if (r <= 0)
+ return ((r == 0) ? &expand_param_error : (char *)NULL);
+
+ switch (vtype)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+#if defined (HANDLE_MULTIBYTE)
+ if (MB_CUR_MAX > 1)
+ tt = mb_substring (val, e1, e2);
+ else
+#endif
+ tt = substring (val, e1, e2);
+
+ if (vtype == VT_VARIABLE)
+ FREE (val);
+ if (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT))
+ temp = quote_string (tt);
+ else
+ temp = tt ? quote_escapes (tt) : (char *)NULL;
+ FREE (tt);
+ break;
+ case VT_POSPARMS:
+ tt = pos_params (varname, e1, e2, quoted);
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
+ {
+ temp = tt ? quote_escapes (tt) : (char *)NULL;
+ FREE (tt);
+ }
+ else
+ temp = tt;
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ /* We want E2 to be the number of elements desired (arrays can be sparse,
+ so verify_substring_values just returns the numbers specified and we
+ rely on array_subrange to understand how to deal with them). */
+ tt = array_subrange (array_cell (v), e1, e2, starsub, quoted);
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
+ {
+ temp = tt ? quote_escapes (tt) : (char *)NULL;
+ FREE (tt);
+ }
+ else
+ temp = tt;
+ break;
+#endif
+ default:
+ temp = (char *)NULL;
+ }
+
+ return temp;
+}
+
+/****************************************************************/
+/* */
+/* Functions to perform pattern substitution on variable values */
+/* */
+/****************************************************************/
+
+char *
+pat_subst (string, pat, rep, mflags)
+ char *string, *pat, *rep;
+ int mflags;
+{
+ char *ret, *s, *e, *str;
+ int rsize, rptr, l, replen, mtype;
+
+ mtype = mflags & MATCH_TYPEMASK;
+
+ /* Special cases:
+ * 1. A null pattern with mtype == MATCH_BEG means to prefix STRING
+ * with REP and return the result.
+ * 2. A null pattern with mtype == MATCH_END means to append REP to
+ * STRING and return the result.
+ */
+ if ((pat == 0 || *pat == 0) && (mtype == MATCH_BEG || mtype == MATCH_END))
+ {
+ replen = STRLEN (rep);
+ l = strlen (string);
+ ret = (char *)xmalloc (replen + l + 2);
+ if (replen == 0)
+ strcpy (ret, string);
+ else if (mtype == MATCH_BEG)
+ {
+ strcpy (ret, rep);
+ strcpy (ret + replen, string);
+ }
+ else
+ {
+ strcpy (ret, string);
+ strcpy (ret + l, rep);
+ }
+ return (ret);
+ }
+
+ ret = (char *)xmalloc (rsize = 64);
+ ret[0] = '\0';
+
+ for (replen = STRLEN (rep), rptr = 0, str = string;;)
+ {
+ if (match_pattern (str, pat, mtype, &s, &e) == 0)
+ break;
+ l = s - str;
+ RESIZE_MALLOCED_BUFFER (ret, rptr, (l + replen), rsize, 64);
+
+ /* OK, now copy the leading unmatched portion of the string (from
+ str to s) to ret starting at rptr (the current offset). Then copy
+ the replacement string at ret + rptr + (s - str). Increment
+ rptr (if necessary) and str and go on. */
+ if (l)
+ {
+ strncpy (ret + rptr, str, l);
+ rptr += l;
+ }
+ if (replen)
+ {
+ strncpy (ret + rptr, rep, replen);
+ rptr += replen;
+ }
+ str = e; /* e == end of match */
+
+ if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
+ break;
+
+ if (s == e)
+ e++, str++; /* avoid infinite recursion on zero-length match */
+ }
+
+ /* Now copy the unmatched portion of the input string */
+ if (*str)
+ {
+ RESIZE_MALLOCED_BUFFER (ret, rptr, STRLEN(str) + 1, rsize, 64);
+ strcpy (ret + rptr, str);
+ }
+ else
+ ret[rptr] = '\0';
+
+ return ret;
+}
+
+/* Do pattern match and replacement on the positional parameters. */
+static char *
+pos_params_pat_subst (string, pat, rep, mflags)
+ char *string, *pat, *rep;
+ int mflags;
+{
+ WORD_LIST *save, *params;
+ WORD_DESC *w;
+ char *ret, *tt;
+
+ save = params = list_rest_of_args ();
+ if (save == 0)
+ return ((char *)NULL);
+
+ for ( ; params; params = params->next)
+ {
+ ret = pat_subst (params->word->word, pat, rep, mflags);
+ w = alloc_word_desc ();
+ w->word = ret ? ret : savestring ("");
+ dispose_word (params->word);
+ params->word = w;
+ }
+
+ if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
+ ret = string_list_dollar_star (quote_list (save));
+ else
+ ret = string_list ((mflags & MATCH_QUOTED) ? quote_list (save) : save);
+ dispose_words (save);
+
+ return (ret);
+}
+
+/* Perform pattern substitution on VALUE, which is the expansion of
+ VARNAME. PATSUB is an expression supplying the pattern to match
+ and the string to substitute. QUOTED is a flags word containing
+ the type of quoting currently in effect. */
+static char *
+parameter_brace_patsub (varname, value, patsub, quoted)
+ char *varname, *value, *patsub;
+ int quoted;
+{
+ int vtype, mflags, starsub;
+ char *val, *temp, *pat, *rep, *p, *lpatsub, *tt;
+ SHELL_VAR *v;
+
+ if (value == 0)
+ return ((char *)NULL);
+
+ this_command_name = varname;
+
+ vtype = get_var_and_type (varname, value, quoted, &v, &val);
+ if (vtype == -1)
+ return ((char *)NULL);
+
+ starsub = vtype & VT_STARSUB;
+ vtype &= ~VT_STARSUB;
+
+ mflags = 0;
+
+ /* Malloc this because expand_string_if_necessary or one of the expansion
+ functions in its call chain may free it on a substitution error. */
+ lpatsub = savestring (patsub);
+
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ mflags |= MATCH_QUOTED;
+
+ if (starsub)
+ 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
+ rep = (char *)NULL;
+
+ if (rep && *rep == '\0')
+ rep = (char *)NULL;
+
+ /* Perform the same expansions on the pattern as performed by the
+ pattern removal expansions. */
+ pat = getpattern (lpatsub, quoted, 1);
+
+ if (rep)
+ {
+ if ((mflags & MATCH_QUOTED) == 0)
+ rep = expand_string_if_necessary (rep, quoted, expand_string_unsplit);
+ else
+ 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] == '/')
+ {
+ mflags |= MATCH_GLOBREP|MATCH_ANY;
+ p++;
+ }
+ else if (pat && pat[0] == '#')
+ {
+ mflags |= MATCH_BEG;
+ p++;
+ }
+ else if (pat && pat[0] == '%')
+ {
+ mflags |= MATCH_END;
+ p++;
+ }
+ else
+ mflags |= MATCH_ANY;
+
+ /* OK, we now want to substitute REP for PAT in VAL. If
+ flags & MATCH_GLOBREP is non-zero, the substitution is done
+ everywhere, otherwise only the first occurrence of PAT is
+ replaced. The pattern matching code doesn't understand
+ CTLESC quoting CTLESC and CTLNUL so we use the dequoted variable
+ values passed in (VT_VARIABLE) so the pattern substitution
+ code works right. We need to requote special chars after
+ we're done for VT_VARIABLE and VT_ARRAYMEMBER, and for the
+ other cases if QUOTED == 0, since the posparams and arrays
+ indexed by * or @ do special things when QUOTED != 0. */
+
+ switch (vtype)
+ {
+ case VT_VARIABLE:
+ case VT_ARRAYMEMBER:
+ temp = pat_subst (val, p, rep, mflags);
+ if (vtype == VT_VARIABLE)
+ FREE (val);
+ if (temp)
+ {
+ tt = quote_escapes (temp);
+ free (temp);
+ temp = tt;
+ }
+ break;
+ case VT_POSPARMS:
+ temp = pos_params_pat_subst (val, p, rep, mflags);
+ if (temp && (mflags & MATCH_QUOTED) == 0)
+ {
+ tt = quote_escapes (temp);
+ free (temp);
+ temp = tt;
+ }
+ break;
+#if defined (ARRAY_VARS)
+ case VT_ARRAYVAR:
+ temp = array_patsub (array_cell (v), p, rep, mflags);
+ if (temp && (mflags & MATCH_QUOTED) == 0)
+ {
+ tt = quote_escapes (temp);
+ free (temp);
+ temp = tt;
+ }
+ break;
+#endif
+ }
+
+ FREE (pat);
+ FREE (rep);
+ free (lpatsub);
+
+ return temp;
+}
+
+/****************************************************************/
+/* */
+/* Functions to perform parameter expansion on a string */
+/* */
+/****************************************************************/
+
+/* ${[#][!]name[[:]#[#]%[%]-=?+[word][:e1[:e2]]]} */
+static WORD_DESC *
+parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_dollar_at)
+ char *string;
+ int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at;
+{
+ int check_nullness, var_is_set, var_is_null, var_is_special;
+ int want_substring, want_indir, want_patsub;
+ char *name, *value, *temp, *temp1;
+ WORD_DESC *tdesc, *ret;
+ int t_index, sindex, c, tflag;
+ intmax_t number;
+
+ value = (char *)NULL;
+ var_is_set = var_is_null = var_is_special = check_nullness = 0;
+ want_substring = want_indir = want_patsub = 0;
+
+ sindex = *indexp;
+ t_index = ++sindex;
+ name = string_extract (string, &t_index, "#%:-=?+/}", EX_VARNAME);
+
+ ret = 0;
+ tflag = 0;
+
+ /* If the name really consists of a special variable, then make sure
+ that we have the entire name. We don't allow indirect references
+ to special variables except `#', `?', `@' and `*'. */
+ if ((sindex == t_index &&
+ (string[t_index] == '-' ||
+ string[t_index] == '?' ||
+ string[t_index] == '#')) ||
+ (sindex == t_index - 1 && string[sindex] == '!' &&
+ (string[t_index] == '#' ||
+ string[t_index] == '?' ||
+ string[t_index] == '@' ||
+ string[t_index] == '*')))
+ {
+ t_index++;
+ free (name);
+ temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
+ name = (char *)xmalloc (3 + (strlen (temp1)));
+ *name = string[sindex];
+ if (string[sindex] == '!')
+ {
+ /* indirect reference of $#, $?, $@, or $* */
+ name[1] = string[sindex + 1];
+ strcpy (name + 2, temp1);
+ }
+ else
+ strcpy (name + 1, temp1);
+ free (temp1);
+ }
+ sindex = t_index;
+
+ /* Find out what character ended the variable name. Then
+ do the appropriate thing. */
+ if (c = string[sindex])
+ sindex++;
+
+ /* If c is followed by one of the valid parameter expansion
+ characters, move past it as normal. If not, assume that
+ a substring specification is being given, and do not move
+ past it. */
+ if (c == ':' && VALID_PARAM_EXPAND_CHAR (string[sindex]))
+ {
+ check_nullness++;
+ if (c = string[sindex])
+ sindex++;
+ }
+ else if (c == ':' && string[sindex] != RBRACE)
+ want_substring = 1;
+ else if (c == '/' && string[sindex] != RBRACE)
+ want_patsub = 1;
+
+ /* Catch the valid and invalid brace expressions that made it through the
+ tests above. */
+ /* ${#-} is a valid expansion and means to take the length of $-.
+ Similarly for ${#?} and ${##}... */
+ if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
+ VALID_SPECIAL_LENGTH_PARAM (c) && string[sindex] == RBRACE)
+ {
+ name = (char *)xrealloc (name, 3);
+ name[1] = c;
+ name[2] = '\0';
+ c = string[sindex++];
+ }
+
+ /* ...but ${#%}, ${#:}, ${#=}, ${#+}, and ${#/} are errors. */
+ if (name[0] == '#' && name[1] == '\0' && check_nullness == 0 &&
+ member (c, "%:=+/") && string[sindex] == RBRACE)
+ {
+ temp = (char *)NULL;
+ goto bad_substitution;
+ }
+
+ /* Indirect expansion begins with a `!'. A valid indirect expansion is
+ either a variable name, one of the positional parameters or a special
+ variable that expands to one of the positional parameters. */
+ want_indir = *name == '!' &&
+ (legal_variable_starter ((unsigned char)name[1]) || DIGIT (name[1])
+ || VALID_INDIR_PARAM (name[1]));
+
+ /* Determine the value of this variable. */
+
+ /* Check for special variables, directly referenced. */
+ if (SPECIAL_VAR (name, want_indir))
+ var_is_special++;
+
+ /* Check for special expansion things, like the length of a parameter */
+ if (*name == '#' && name[1])
+ {
+ /* If we are not pointing at the character just after the
+ closing brace, then we haven't gotten all of the name.
+ Since it begins with a special character, this is a bad
+ substitution. Also check NAME for validity before trying
+ to go on. */
+ if (string[sindex - 1] != RBRACE || (valid_length_expression (name) == 0))
+ {
+ temp = (char *)NULL;
+ goto bad_substitution;
+ }
+
+ number = parameter_brace_expand_length (name);
+ free (name);
+
+ *indexp = sindex;
+ if (number < 0)
+ return (&expand_wdesc_error);
+ else
+ {
+ ret = alloc_word_desc ();
+ ret->word = itos (number);
+ return ret;
+ }
+ }
+
+ /* ${@} is identical to $@. */
+ if (name[0] == '@' && name[1] == '\0')
+ {
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ }
+
+ /* Process ${!PREFIX*} expansion. */
+ if (want_indir && string[sindex - 1] == RBRACE &&
+ (string[sindex - 2] == '*' || string[sindex - 2] == '@') &&
+ legal_variable_starter ((unsigned char) name[1]))
+ {
+ char **x;
+ WORD_LIST *xlist;
+
+ temp1 = savestring (name + 1);
+ number = strlen (temp1);
+ temp1[number - 1] = '\0';
+ x = all_variables_matching_prefix (temp1);
+ xlist = strvec_to_word_list (x, 0, 0);
+ if (string[sindex - 2] == '*')
+ temp = string_list_dollar_star (xlist);
+ else
+ {
+ temp = string_list_dollar_at (xlist, quoted);
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ }
+ free (x);
+ free (xlist);
+ free (temp1);
+ *indexp = sindex;
+
+ ret = alloc_word_desc ();
+ ret->word = temp;
+ return ret;
+ }
+
+#if defined (ARRAY_VARS)
+ /* Process ${!ARRAY[@]} and ${!ARRAY[*]} expansion. */ /* [ */
+ if (want_indir && string[sindex - 1] == RBRACE &&
+ string[sindex - 2] == ']' && valid_array_reference (name+1))
+ {
+ char *x, *x1;
+
+ temp1 = savestring (name + 1);
+ x = array_variable_name (temp1, &x1, (int *)0); /* [ */
+ FREE (x);
+ if (ALL_ELEMENT_SUB (x1[0]) && x1[1] == ']')
+ {
+ temp = array_keys (temp1, quoted);
+ if (x1[0] == '@')
+ {
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ }
+
+ free (temp1);
+ *indexp = sindex;
+
+ ret = alloc_word_desc ();
+ ret->word = temp;
+ return ret;
+ }
+
+ free (temp1);
+ }
+#endif /* ARRAY_VARS */
+
+ /* Make sure that NAME is valid before trying to go on. */
+ if (valid_brace_expansion_word (want_indir ? name + 1 : name,
+ var_is_special) == 0)
+ {
+ temp = (char *)NULL;
+ goto bad_substitution;
+ }
+
+ if (want_indir)
+ tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
+ else
+ tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
+
+ if (tdesc)
+ {
+ temp = tdesc->word;
+ tflag = tdesc->flags;
+ dispose_word_desc (tdesc);
+ }
+ else
+ temp = (char *)0;
+
+#if defined (ARRAY_VARS)
+ if (valid_array_reference (name))
+ chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at);
+#endif
+
+ var_is_set = temp != (char *)0;
+ var_is_null = check_nullness && (var_is_set == 0 || *temp == 0);
+
+ /* Get the rest of the stuff inside the braces. */
+ if (c && c != RBRACE)
+ {
+ /* Extract the contents of the ${ ... } expansion
+ according to the Posix.2 rules. */
+ value = extract_dollar_brace_string (string, &sindex, quoted, 0);
+ if (string[sindex] == RBRACE)
+ sindex++;
+ else
+ goto bad_substitution;
+ }
+ else
+ value = (char *)NULL;
+
+ *indexp = sindex;
+
+ /* If this is a substring spec, process it and add the result. */
+ if (want_substring)
+ {
+ temp1 = parameter_brace_substring (name, temp, value, quoted);
+ FREE (name);
+ FREE (value);
+ FREE (temp);
+
+ if (temp1 == &expand_param_error)
+ return (&expand_wdesc_error);
+ else if (temp1 == &expand_param_fatal)
+ return (&expand_wdesc_fatal);
+
+ ret = alloc_word_desc ();
+ ret->word = temp1;
+ return ret;
+ }
+ else if (want_patsub)
+ {
+ temp1 = parameter_brace_patsub (name, temp, value, quoted);
+ FREE (name);
+ FREE (value);
+ FREE (temp);
+
+ if (temp1 == &expand_param_error)
+ return (&expand_wdesc_error);
+ else if (temp1 == &expand_param_fatal)
+ return (&expand_wdesc_fatal);
+
+ ret = alloc_word_desc ();
+ ret->word = temp1;
+ return ret;
+ }
+
+ /* Do the right thing based on which character ended the variable name. */
+ switch (c)
+ {
+ default:
+ case '\0':
+ bad_substitution:
+ report_error (_("%s: bad substitution"), string ? string : "??");
+ FREE (value);
+ FREE (temp);
+ free (name);
+ return &expand_wdesc_error;
+
+ case RBRACE:
+ if (var_is_set == 0 && unbound_vars_is_error)
+ {
+ err_unboundvar (name);
+ FREE (value);
+ FREE (temp);
+ free (name);
+ last_command_exit_value = EXECUTION_FAILURE;
+ return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+ }
+ break;
+
+ case '#': /* ${param#[#]pattern} */
+ case '%': /* ${param%[%]pattern} */
+ if (value == 0 || *value == '\0' || temp == 0 || *temp == '\0')
+ {
+ FREE (value);
+ break;
+ }
+ temp1 = parameter_brace_remove_pattern (name, temp, value, c, quoted);
+ free (temp);
+ free (value);
+ temp = temp1;
+ break;
+
+ case '-':
+ case '=':
+ case '?':
+ case '+':
+ if (var_is_set && var_is_null == 0)
+ {
+ /* If the operator is `+', we don't want the value of the named
+ variable for anything, just the value of the right hand side. */
+
+ if (c == '+')
+ {
+ /* XXX -- if we're double-quoted and the named variable is "$@",
+ we want to turn off any special handling of "$@" --
+ we're not using it, so whatever is on the rhs applies. */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 0;
+ if (contains_dollar_at)
+ *contains_dollar_at = 0;
+
+ FREE (temp);
+ if (value)
+ {
+ ret = parameter_brace_expand_rhs (name, value, c,
+ quoted,
+ quoted_dollar_atp,
+ contains_dollar_at);
+ /* XXX - fix up later, esp. noting presence of
+ W_HASQUOTEDNULL in ret->flags */
+ free (value);
+ }
+ else
+ temp = (char *)NULL;
+ }
+ else
+ {
+ FREE (value);
+ }
+ /* Otherwise do nothing; just use the value in TEMP. */
+ }
+ else /* VAR not set or VAR is NULL. */
+ {
+ FREE (temp);
+ temp = (char *)NULL;
+ if (c == '=' && var_is_special)
+ {
+ report_error (_("$%s: cannot assign in this way"), name);
+ free (name);
+ free (value);
+ return &expand_wdesc_error;
+ }
+ else if (c == '?')
+ {
+ parameter_brace_expand_error (name, value);
+ return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+ }
+ else if (c != '+')
+ {
+ /* XXX -- if we're double-quoted and the named variable is "$@",
+ we want to turn off any special handling of "$@" --
+ we're not using it, so whatever is on the rhs applies. */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && quoted_dollar_atp)
+ *quoted_dollar_atp = 0;
+ if (contains_dollar_at)
+ *contains_dollar_at = 0;
+
+ ret = parameter_brace_expand_rhs (name, value, c, quoted,
+ quoted_dollar_atp,
+ contains_dollar_at);
+ /* XXX - fix up later, esp. noting presence of
+ W_HASQUOTEDNULL in tdesc->flags */
+ }
+ free (value);
+ }
+
+ break;
+ }
+ free (name);
+
+ if (ret == 0)
+ {
+ ret = alloc_word_desc ();
+ ret->flags = tflag;
+ ret->word = temp;
+ }
+ return (ret);
+}
+
+/* Expand a single ${xxx} expansion. The braces are optional. When
+ the braces are used, parameter_brace_expand() does the work,
+ possibly calling param_expand recursively. */
+static WORD_DESC *
+param_expand (string, sindex, quoted, expanded_something,
+ contains_dollar_at, quoted_dollar_at_p, had_quoted_null_p,
+ pflags)
+ char *string;
+ int *sindex, quoted, *expanded_something, *contains_dollar_at;
+ int *quoted_dollar_at_p, *had_quoted_null_p, pflags;
+{
+ char *temp, *temp1, uerror[3];
+ int zindex, t_index, expok;
+ unsigned char c;
+ intmax_t number;
+ SHELL_VAR *var;
+ WORD_LIST *list;
+ WORD_DESC *tdesc, *ret;
+ int tflag;
+
+ zindex = *sindex;
+ c = string[++zindex];
+
+ temp = (char *)NULL;
+ ret = tdesc = (WORD_DESC *)NULL;
+ tflag = 0;
+
+ /* Do simple cases first. Switch on what follows '$'. */
+ switch (c)
+ {
+ /* $0 .. $9? */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ temp1 = dollar_vars[TODIGIT (c)];
+ if (unbound_vars_is_error && temp1 == (char *)NULL)
+ {
+ uerror[0] = '$';
+ uerror[1] = c;
+ uerror[2] = '\0';
+ err_unboundvar (uerror);
+ last_command_exit_value = EXECUTION_FAILURE;
+ return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+ }
+ if (temp1)
+ temp = (*temp1 && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ ? quote_string (temp1)
+ : quote_escapes (temp1);
+ else
+ temp = (char *)NULL;
+
+ break;
+
+ /* $$ -- pid of the invoking shell. */
+ case '$':
+ temp = itos (dollar_dollar_pid);
+ break;
+
+ /* $# -- number of positional parameters. */
+ case '#':
+ temp = itos (number_of_args ());
+ break;
+
+ /* $? -- return value of the last synchronous command. */
+ case '?':
+ temp = itos (last_command_exit_value);
+ break;
+
+ /* $- -- flags supplied to the shell on invocation or by `set'. */
+ case '-':
+ temp = which_set_flags ();
+ break;
+
+ /* $! -- Pid of the last asynchronous command. */
+ case '!':
+ /* If no asynchronous pids have been created, expand to nothing.
+ If `set -u' has been executed, and no async processes have
+ been created, this is an expansion error. */
+ if (last_asynchronous_pid == NO_PID)
+ {
+ if (expanded_something)
+ *expanded_something = 0;
+ temp = (char *)NULL;
+ if (unbound_vars_is_error)
+ {
+ uerror[0] = '$';
+ uerror[1] = c;
+ uerror[2] = '\0';
+ err_unboundvar (uerror);
+ last_command_exit_value = EXECUTION_FAILURE;
+ return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
+ }
+ }
+ else
+ temp = itos (last_asynchronous_pid);
+ break;
+
+ /* The only difference between this and $@ is when the arg is quoted. */
+ case '*': /* `$*' */
+ list = list_rest_of_args ();
+
+ /* If there are no command-line arguments, this should just
+ disappear if there are other characters in the expansion,
+ even if it's quoted. */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && list == 0)
+ temp = (char *)NULL;
+ else if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ {
+ /* If we have "$*" we want to make a string of the positional
+ parameters, separated by the first character of $IFS, and
+ quote the whole string, including the separators. If IFS
+ is unset, the parameters are separated by ' '; if $IFS is
+ null, the parameters are concatenated. */
+ temp = (quoted & Q_DOUBLE_QUOTES) ? string_list_dollar_star (list) : string_list (list);
+ temp1 = quote_string (temp);
+ if (*temp == 0)
+ tflag |= W_HASQUOTEDNULL;
+ free (temp);
+ temp = temp1;
+ }
+ else
+ {
+ /* We check whether or not we're eventually going to split $* here,
+ for example when IFS is empty and we are processing the rhs of
+ an assignment statement. In that case, we don't separate the
+ arguments at all. Otherwise, if the $* is not quoted it is
+ identical to $@ */
+#if 1
+# if defined (HANDLE_MULTIBYTE)
+ if (expand_no_split_dollar_star && ifs_firstc[0] == 0)
+# else
+ if (expand_no_split_dollar_star && ifs_firstc == 0)
+# endif
+ temp = string_list_dollar_star (list);
+ else
+ temp = string_list_dollar_at (list, quoted);
+#else
+ temp = string_list_dollar_at (list, quoted);
+#endif
+ if (expand_no_split_dollar_star == 0 && contains_dollar_at)
+ *contains_dollar_at = 1;
+ }
+
+ dispose_words (list);
+ break;
+
+ /* When we have "$@" what we want is "$1" "$2" "$3" ... This
+ means that we have to turn quoting off after we split into
+ the individually quoted arguments so that the final split
+ on the first character of $IFS is still done. */
+ case '@': /* `$@' */
+ list = list_rest_of_args ();
+
+ /* We want to flag the fact that we saw this. We can't turn
+ off quoting entirely, because other characters in the
+ string might need it (consider "\"$@\""), but we need some
+ way to signal that the final split on the first character
+ of $IFS should be done, even though QUOTED is 1. */
+ if (quoted_dollar_at_p && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ *quoted_dollar_at_p = 1;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+
+ /* We want to separate the positional parameters with the first
+ character of $IFS in case $IFS is something other than a space.
+ We also want to make sure that splitting is done no matter what --
+ according to POSIX.2, this expands to a list of the positional
+ parameters no matter what IFS is set to. */
+ temp = string_list_dollar_at (list, quoted);
+
+ dispose_words (list);
+ break;
+
+ case LBRACE:
+ tdesc = parameter_brace_expand (string, &zindex, quoted,
+ quoted_dollar_at_p,
+ contains_dollar_at);
+
+ /* Fix this later when parameter_brace_expand returns a WORD_DESC * */
+ if (tdesc == &expand_wdesc_error || tdesc == &expand_wdesc_fatal)
+ return (tdesc);
+ temp = tdesc ? tdesc->word : (char *)0;
+
+ /* XXX */
+ /* Quoted nulls should be removed if there is anything else
+ in the string. */
+ /* Note that we saw the quoted null so we can add one back at
+ the end of this function if there are no other characters
+ in the string, discard TEMP, and go on. The exception to
+ this is when we have "${@}" and $1 is '', since $@ needs
+ special handling. */
+ /* XXX - fix this once parameter_brace_expand returns a WORD_DESC * */
+#if 0
+ if (temp && QUOTED_NULL (temp))
+#else
+ if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
+#endif
+ {
+ if (had_quoted_null_p)
+ *had_quoted_null_p = 1;
+ if (*quoted_dollar_at_p == 0)
+ {
+ free (temp);
+ tdesc->word = temp = (char *)NULL;
+ }
+
+ }
+
+ ret = tdesc;
+ goto return0;
+
+ /* Do command or arithmetic substitution. */
+ case LPAREN:
+ /* We have to extract the contents of this paren substitution. */
+ t_index = zindex + 1;
+ temp = extract_command_subst (string, &t_index);
+ zindex = t_index;
+
+ /* For Posix.2-style `$(( ))' arithmetic substitution,
+ extract the expression and pass it to the evaluator. */
+ if (temp && *temp == LPAREN)
+ {
+ char *temp2;
+ temp1 = temp + 1;
+ temp2 = savestring (temp1);
+ t_index = strlen (temp2) - 1;
+
+ if (temp2[t_index] != RPAREN)
+ {
+ free (temp2);
+ goto comsub;
+ }
+
+ /* Cut off ending `)' */
+ 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:
+ /* No error messages. */
+ this_command_name = (char *)NULL;
+ number = evalexp (temp1, &expok);
+ free (temp);
+ free (temp1);
+ if (expok == 0)
+ {
+ if (interactive_shell == 0 && posixly_correct)
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ return (&expand_wdesc_fatal);
+ }
+ else
+ return (&expand_wdesc_error);
+ }
+ temp = itos (number);
+ break;
+ }
+
+comsub:
+ if (pflags & PF_NOCOMSUB)
+ /* we need zindex+1 because string[zindex] == RPAREN */
+ temp1 = substring (string, *sindex, zindex+1);
+ else
+ temp1 = command_substitute (temp, quoted);
+ FREE (temp);
+ temp = temp1;
+ break;
+
+ /* Do POSIX.2d9-style arithmetic substitution. This will probably go
+ away in a future bash release. */
+ case '[':
+ /* Extract the contents of this arithmetic substitution. */
+ t_index = zindex + 1;
+ temp = extract_arithmetic_subst (string, &t_index);
+ 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;
+
+ default:
+ /* Find the variable in VARIABLE_LIST. */
+ temp = (char *)NULL;
+
+ for (t_index = zindex; (c = string[zindex]) && legal_variable_char (c); zindex++)
+ ;
+ temp1 = (zindex > t_index) ? substring (string, t_index, zindex) : (char *)NULL;
+
+ /* If this isn't a variable name, then just output the `$'. */
+ if (temp1 == 0 || *temp1 == '\0')
+ {
+ FREE (temp1);
+ temp = (char *)xmalloc (2);
+ temp[0] = '$';
+ temp[1] = '\0';
+ if (expanded_something)
+ *expanded_something = 0;
+ goto return0;
+ }
+
+ /* If the variable exists, return its value cell. */
+ var = find_variable (temp1);
+
+ if (var && invisible_p (var) == 0 && var_isset (var))
+ {
+#if defined (ARRAY_VARS)
+ if (array_p (var))
+ {
+ temp = array_reference (array_cell (var), 0);
+ if (temp)
+ temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ ? quote_string (temp)
+ : quote_escapes (temp);
+ else if (unbound_vars_is_error)
+ goto unbound_variable;
+ }
+ else
+#endif
+ {
+ temp = value_cell (var);
+
+ temp = (*temp && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
+ ? quote_string (temp)
+ : quote_escapes (temp);
+ }
+
+ free (temp1);
+
+ goto return0;
+ }
+
+ temp = (char *)NULL;
+
+unbound_variable:
+ if (unbound_vars_is_error)
+ err_unboundvar (temp1);
+ else
+ {
+ free (temp1);
+ goto return0;
+ }
+
+ free (temp1);
+ last_command_exit_value = EXECUTION_FAILURE;
+ return ((unbound_vars_is_error && interactive_shell == 0)
+ ? &expand_wdesc_fatal
+ : &expand_wdesc_error);
+ }
+
+ if (string[zindex])
+ zindex++;
+
+return0:
+ *sindex = zindex;
+
+ if (ret == 0)
+ {
+ ret = alloc_word_desc ();
+ ret->flags = tflag; /* XXX */
+ ret->word = temp;
+ }
+ return ret;
+}
+
+/* Make a word list which is the result of parameter and variable
+ expansion, command substitution, arithmetic substitution, and
+ quote removal of WORD. Return a pointer to a WORD_LIST which is
+ the result of the expansion. If WORD contains a null word, the
+ word list returned is also null.
+
+ QUOTED contains flag values defined in shell.h.
+
+ ISEXP is used to tell expand_word_internal that the word should be
+ treated as the result of an expansion. This has implications for
+ how IFS characters in the word are treated.
+
+ CONTAINS_DOLLAR_AT and EXPANDED_SOMETHING are return values; when non-null
+ they point to an integer value which receives information about expansion.
+ CONTAINS_DOLLAR_AT gets non-zero if WORD contained "$@", else zero.
+ EXPANDED_SOMETHING get non-zero if WORD contained any parameter expansions,
+ else zero.
+
+ This only does word splitting in the case of $@ expansion. In that
+ case, we split on ' '. */
+
+/* Values for the local variable quoted_state. */
+#define UNQUOTED 0
+#define PARTIALLY_QUOTED 1
+#define WHOLLY_QUOTED 2
+
+static WORD_LIST *
+expand_word_internal (word, quoted, isexp, contains_dollar_at, expanded_something)
+ WORD_DESC *word;
+ int quoted, isexp;
+ int *contains_dollar_at;
+ int *expanded_something;
+{
+ WORD_LIST *list;
+ WORD_DESC *tword;
+
+ /* The intermediate string that we build while expanding. */
+ char *istring;
+
+ /* The current size of the above object. */
+ int istring_size;
+
+ /* Index into ISTRING. */
+ int istring_index;
+
+ /* Temporary string storage. */
+ char *temp, *temp1;
+
+ /* The text of WORD. */
+ register char *string;
+
+ /* The size of STRING. */
+ size_t string_size;
+
+ /* The index into STRING. */
+ int sindex;
+
+ /* This gets 1 if we see a $@ while quoted. */
+ int quoted_dollar_at;
+
+ /* One of UNQUOTED, PARTIALLY_QUOTED, or WHOLLY_QUOTED, depending on
+ whether WORD contains no quoting characters, a partially quoted
+ string (e.g., "xx"ab), or is fully quoted (e.g., "xxab"). */
+ int quoted_state;
+
+ /* State flags */
+ int had_quoted_null;
+ int has_dollar_at;
+ int tflag;
+
+ int assignoff; /* If assignment, offset of `=' */
+
+ register unsigned char c; /* Current character. */
+ int t_index; /* For calls to string_extract_xxx. */
+
+ char twochars[2];
+
+ DECLARE_MBSTATE;
+
+ istring = (char *)xmalloc (istring_size = DEFAULT_INITIAL_ARRAY_SIZE);
+ istring[istring_index = 0] = '\0';
+ quoted_dollar_at = had_quoted_null = has_dollar_at = 0;
+ quoted_state = UNQUOTED;
+
+ string = word->word;
+ if (string == 0)
+ goto finished_with_string;
+ /* Don't need the string length for the SADD... and COPY_ macros unless
+ multibyte characters are possible. */
+ string_size = (MB_CUR_MAX > 1) ? strlen (string) : 1;
+
+ if (contains_dollar_at)
+ *contains_dollar_at = 0;
+
+ assignoff = -1;
+
+ /* Begin the expansion. */
+
+ for (sindex = 0; ;)
+ {
+ c = string[sindex];
+
+ /* Case on toplevel character. */
+ switch (c)
+ {
+ case '\0':
+ goto finished_with_string;
+
+ case CTLESC:
+ sindex++;
+#if HANDLE_MULTIBYTE
+ if (MB_CUR_MAX > 1 && string[sindex])
+ {
+ SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
+ }
+ else
+#endif
+ {
+ temp = (char *)xmalloc (3);
+ temp[0] = CTLESC;
+ temp[1] = c = string[sindex];
+ temp[2] = '\0';
+ }
+
+dollar_add_string:
+ if (string[sindex])
+ sindex++;
+
+add_string:
+ if (temp)
+ {
+ istring = sub_append_string (temp, istring, &istring_index, &istring_size);
+ temp = (char *)0;
+ }
+
+ break;
+
+#if defined (PROCESS_SUBSTITUTION)
+ /* Process substitution. */
+ case '<':
+ 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 */
+ goto add_character;
+ }
+ else
+ t_index = sindex + 1; /* skip past both '<' and LPAREN */
+
+ temp1 = extract_process_subst (string, (c == '<') ? "<(" : ">(", &t_index); /*))*/
+ sindex = t_index;
+
+ /* If the process substitution specification is `<()', we want to
+ open the pipe for writing in the child and produce output; if
+ it is `>()', we want to open the pipe for reading in the child
+ and consume input. */
+ temp = temp1 ? process_substitute (temp1, (c == '>')) : (char *)0;
+
+ FREE (temp1);
+
+ goto dollar_add_string;
+ }
+#endif /* PROCESS_SUBSTITUTION */
+
+ case '=':
+ /* Posix.2 section 3.6.1 says that tildes following `=' in words
+ which are not assignment statements are not expanded. If the
+ shell isn't in posix mode, though, we perform tilde expansion
+ on `likely candidate' unquoted assignment statements (flags
+ include W_ASSIGNMENT but not W_QUOTED). A likely candidate
+ contains an unquoted :~ or =~. Something to think about: we
+ now have a flag that says to perform tilde expansion on arguments
+ to `assignment builtins' like declare and export that look like
+ assignment statements. We now do tilde expansion on such words
+ even in POSIX mode. */
+ if (word->flags & (W_ASSIGNRHS|W_NOTILDE))
+ goto add_character;
+ /* If we're not in posix mode or forcing assignment-statement tilde
+ expansion, note where the `=' appears in the word and prepare to
+ do tilde expansion following the first `='. */
+ if ((word->flags & W_ASSIGNMENT) &&
+ (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
+ assignoff == -1 && sindex > 0)
+ assignoff = sindex;
+ if (sindex == assignoff && string[sindex+1] == '~') /* XXX */
+ word->flags |= W_ITILDE;
+#if 0
+ else if ((word->flags & W_ASSIGNMENT) &&
+ (posixly_correct == 0 || (word->flags & W_TILDEEXP)) &&
+ string[sindex+1] == '~')
+ word->flags |= W_ITILDE;
+#endif
+ goto add_character;
+
+ case ':':
+ if (word->flags & W_NOTILDE)
+ goto add_character;
+
+ if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
+ string[sindex+1] == '~')
+ word->flags |= W_ITILDE;
+ goto add_character;
+
+ case '~':
+ /* If the word isn't supposed to be tilde expanded, or we're not
+ at the start of a word or after an unquoted : or = in an
+ assignment statement, we don't do tilde expansion. */
+ if ((word->flags & (W_NOTILDE|W_DQUOTE)) ||
+ (sindex > 0 && ((word->flags & W_ITILDE) == 0)) ||
+ (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+ {
+ word->flags &= ~W_ITILDE;
+ goto add_character;
+ }
+
+ if (word->flags & W_ASSIGNRHS)
+ tflag = 2;
+ else if (word->flags & (W_ASSIGNMENT|W_TILDEEXP))
+ tflag = 1;
+ else
+ tflag = 0;
+
+ temp = bash_tilde_find_word (string + sindex, tflag, &t_index);
+
+ word->flags &= ~W_ITILDE;
+
+ 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;
+ goto add_string;
+ }
+ else
+ {
+ FREE (temp);
+ goto add_character;
+ }
+
+ case '$':
+ if (expanded_something)
+ *expanded_something = 1;
+
+ has_dollar_at = 0;
+ tword = param_expand (string, &sindex, quoted, expanded_something,
+ &has_dollar_at, &quoted_dollar_at,
+ &had_quoted_null,
+ (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0);
+
+ if (tword == &expand_wdesc_error || tword == &expand_wdesc_fatal)
+ {
+ free (string);
+ free (istring);
+ return ((tword == &expand_wdesc_error) ? &expand_word_error
+ : &expand_word_fatal);
+ }
+ if (contains_dollar_at && has_dollar_at)
+ *contains_dollar_at = 1;
+
+ if (tword && (tword->flags & W_HASQUOTEDNULL))
+ had_quoted_null = 1;
+
+ temp = tword->word;
+ dispose_word_desc (tword);
+
+ goto add_string;
+ break;
+
+ case '`': /* Backquoted command substitution. */
+ {
+ t_index = sindex++;
+
+ temp = string_extract (string, &sindex, "`", EX_REQMATCH);
+ /* The test of sindex against t_index is to allow bare instances of
+ ` to pass through, for backwards compatibility. */
+ if (temp == &extract_string_error || temp == &extract_string_fatal)
+ {
+ if (sindex - 1 == t_index)
+ {
+ sindex = t_index;
+ goto add_character;
+ }
+ report_error ("bad substitution: no closing \"`\" in %s", string+t_index);
+ free (string);
+ free (istring);
+ return ((temp == &extract_string_error) ? &expand_word_error
+ : &expand_word_fatal);
+ }
+
+ if (expanded_something)
+ *expanded_something = 1;
+
+ if (word->flags & W_NOCOMSUB)
+ /* sindex + 1 because string[sindex] == '`' */
+ temp1 = substring (string, t_index, sindex + 1);
+ else
+ {
+ de_backslash (temp);
+ temp1 = command_substitute (temp, quoted);
+ }
+ FREE (temp);
+ temp = temp1;
+ goto dollar_add_string;
+ }
+
+ case '\\':
+ if (string[sindex + 1] == '\n')
+ {
+ sindex += 2;
+ continue;
+ }
+
+ c = string[++sindex];
+
+ if (quoted & Q_HERE_DOCUMENT)
+ tflag = CBSHDOC;
+ else if (quoted & Q_DOUBLE_QUOTES)
+ tflag = CBSDQUOTE;
+ else
+ tflag = 0;
+
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
+ {
+ SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
+ }
+ else if (c == 0)
+ {
+ c = CTLNUL;
+ sindex--; /* add_character: label increments sindex */
+ goto add_character;
+ }
+ else
+ {
+ SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
+ }
+
+ sindex++;
+add_twochars:
+ /* BEFORE jumping here, we need to increment sindex if appropriate */
+ RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size,
+ DEFAULT_ARRAY_SIZE);
+ istring[istring_index++] = twochars[0];
+ istring[istring_index++] = twochars[1];
+ istring[istring_index] = '\0';
+
+ break;
+
+ case '"':
+#if 0
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
+#else
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+#endif
+ goto add_character;
+
+ t_index = ++sindex;
+ temp = string_extract_double_quoted (string, &sindex, 0);
+
+ /* If the quotes surrounded the entire string, then the
+ whole word was quoted. */
+ quoted_state = (t_index == 1 && string[sindex] == '\0')
+ ? WHOLLY_QUOTED
+ : PARTIALLY_QUOTED;
+
+ if (temp && *temp)
+ {
+ tword = alloc_word_desc ();
+ tword->word = temp;
+
+ temp = (char *)NULL;
+
+ has_dollar_at = 0;
+ /* Need to get W_HASQUOTEDNULL flag through this function. */
+ list = expand_word_internal (tword, Q_DOUBLE_QUOTES, 0, &has_dollar_at, (int *)NULL);
+
+ if (list == &expand_word_error || list == &expand_word_fatal)
+ {
+ free (istring);
+ free (string);
+ /* expand_word_internal has already freed temp_word->word
+ for us because of the way it prints error messages. */
+ tword->word = (char *)NULL;
+ dispose_word (tword);
+ return list;
+ }
+
+ dispose_word (tword);
+
+ /* "$@" (a double-quoted dollar-at) expands into nothing,
+ not even a NULL word, when there are no positional
+ parameters. */
+ if (list == 0 && has_dollar_at)
+ {
+ quoted_dollar_at++;
+ break;
+ }
+
+ /* If we get "$@", we know we have expanded something, so we
+ need to remember it for the final split on $IFS. This is
+ a special case; it's the only case where a quoted string
+ can expand into more than one word. It's going to come back
+ from the above call to expand_word_internal as a list with
+ a single word, in which all characters are quoted and
+ separated by blanks. What we want to do is to turn it back
+ into a list for the next piece of code. */
+ if (list)
+ dequote_list (list);
+
+ if (list && list->word && (list->word->flags & W_HASQUOTEDNULL))
+ had_quoted_null = 1;
+
+ if (has_dollar_at)
+ {
+ quoted_dollar_at++;
+ if (contains_dollar_at)
+ *contains_dollar_at = 1;
+ if (expanded_something)
+ *expanded_something = 1;
+ }
+ }
+ else
+ {
+ /* What we have is "". This is a minor optimization. */
+ FREE (temp);
+ list = (WORD_LIST *)NULL;
+ }
+
+ /* The code above *might* return a list (consider the case of "$@",
+ where it returns "$1", "$2", etc.). We can't throw away the
+ rest of the list, and we have to make sure each word gets added
+ as quoted. We test on tresult->next: if it is non-NULL, we
+ quote the whole list, save it to a string with string_list, and
+ add that string. We don't need to quote the results of this
+ (and it would be wrong, since that would quote the separators
+ as well), so we go directly to add_string. */
+ if (list)
+ {
+ if (list->next)
+ {
+ /* Testing quoted_dollar_at makes sure that "$@" is
+ split correctly when $IFS does not contain a space. */
+ temp = quoted_dollar_at
+ ? string_list_dollar_at (list, Q_DOUBLE_QUOTES)
+ : string_list (quote_list (list));
+ dispose_words (list);
+ goto add_string;
+ }
+ else
+ {
+ temp = savestring (list->word->word);
+ tflag = list->word->flags;
+ dispose_words (list);
+
+ /* If the string is not a quoted null string, we want
+ to remove any embedded unquoted CTLNUL characters.
+ We do not want to turn quoted null strings back into
+ the empty string, though. We do this because we
+ want to remove any quoted nulls from expansions that
+ contain other characters. For example, if we have
+ x"$*"y or "x$*y" and there are no positional parameters,
+ the $* should expand into nothing. */
+ /* We use the W_HASQUOTEDNULL flag to differentiate the
+ cases: a quoted null character as above and when
+ CTLNUL is contained in the (non-null) expansion
+ of some variable. We use the had_quoted_null flag to
+ pass the value through this function to its caller. */
+ if ((tflag & W_HASQUOTEDNULL) && QUOTED_NULL (temp) == 0)
+ remove_quoted_nulls (temp); /* XXX */
+ }
+ }
+ else
+ temp = (char *)NULL;
+
+ /* We do not want to add quoted nulls to strings that are only
+ partially quoted; we can throw them away. */
+ if (temp == 0 && quoted_state == PARTIALLY_QUOTED)
+ continue;
+
+ add_quoted_string:
+
+ if (temp)
+ {
+ temp1 = temp;
+ temp = quote_string (temp);
+ free (temp1);
+ goto add_string;
+ }
+ else
+ {
+ /* Add NULL arg. */
+ c = CTLNUL;
+ sindex--; /* add_character: label increments sindex */
+ goto add_character;
+ }
+
+ /* break; */
+
+ case '\'':
+#if 0
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (word->flags & W_DQUOTE))
+#else
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
+#endif
+ goto add_character;
+
+ t_index = ++sindex;
+ temp = string_extract_single_quoted (string, &sindex);
+
+ /* If the entire STRING was surrounded by single quotes,
+ then the string is wholly quoted. */
+ quoted_state = (t_index == 1 && string[sindex] == '\0')
+ ? WHOLLY_QUOTED
+ : PARTIALLY_QUOTED;
+
+ /* If all we had was '', it is a null expansion. */
+ if (*temp == '\0')
+ {
+ free (temp);
+ temp = (char *)NULL;
+ }
+ else
+ remove_quoted_escapes (temp); /* ??? */
+
+ /* We do not want to add quoted nulls to strings that are only
+ partially quoted; such nulls are discarded. */
+ if (temp == 0 && (quoted_state == PARTIALLY_QUOTED))
+ continue;
+
+ /* If we have a quoted null expansion, add a quoted NULL to istring. */
+ if (temp == 0)
+ {
+ c = CTLNUL;
+ sindex--; /* add_character: label increments sindex */
+ goto add_character;
+ }
+ else
+ goto add_quoted_string;
+
+ /* break; */
+
+ default:
+ /* This is the fix for " $@ " */
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (isexp == 0 && isifs (c)))
+ {
+ if (string[sindex]) /* from old goto dollar_add_string */
+ sindex++;
+ if (c == 0)
+ {
+ c = CTLNUL;
+ goto add_character;
+ }
+ else
+ {
+#if HANDLE_MULTIBYTE
+ if (MB_CUR_MAX > 1)
+ sindex--;
+
+ if (MB_CUR_MAX > 1)
+ {
+ SADD_MBQCHAR_BODY(temp, string, sindex, string_size);
+ }
+ else
+#endif
+ {
+ twochars[0] = CTLESC;
+ twochars[1] = c;
+ goto add_twochars;
+ }
+ }
+ }
+
+ SADD_MBCHAR (temp, string, sindex, string_size);
+
+ add_character:
+ RESIZE_MALLOCED_BUFFER (istring, istring_index, 1, istring_size,
+ DEFAULT_ARRAY_SIZE);
+ istring[istring_index++] = c;
+ istring[istring_index] = '\0';
+
+ /* Next character. */
+ sindex++;
+ }
+ }
+
+finished_with_string:
+ /* OK, we're ready to return. If we have a quoted string, and
+ quoted_dollar_at is not set, we do no splitting at all; otherwise
+ we split on ' '. The routines that call this will handle what to
+ do if nothing has been expanded. */
+
+ /* Partially and wholly quoted strings which expand to the empty
+ string are retained as an empty arguments. Unquoted strings
+ which expand to the empty string are discarded. The single
+ exception is the case of expanding "$@" when there are no
+ positional parameters. In that case, we discard the expansion. */
+
+ /* Because of how the code that handles "" and '' in partially
+ quoted strings works, we need to make ISTRING into a QUOTED_NULL
+ if we saw quoting characters, but the expansion was empty.
+ "" and '' are tossed away before we get to this point when
+ processing partially quoted strings. This makes "" and $xxx""
+ equivalent when xxx is unset. We also look to see whether we
+ saw a quoted null from a ${} expansion and add one back if we
+ need to. */
+
+ /* If we expand to nothing and there were no single or double quotes
+ in the word, we throw it away. Otherwise, we return a NULL word.
+ The single exception is for $@ surrounded by double quotes when
+ there are no positional parameters. In that case, we also throw
+ the word away. */
+
+ if (*istring == '\0')
+ {
+ if (quoted_dollar_at == 0 && (had_quoted_null || quoted_state == PARTIALLY_QUOTED))
+ {
+ istring[0] = CTLNUL;
+ istring[1] = '\0';
+ tword = make_bare_word (istring);
+ tword->flags |= W_HASQUOTEDNULL; /* XXX */
+ list = make_word_list (tword, (WORD_LIST *)NULL);
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ tword->flags |= W_QUOTED;
+ }
+ /* According to sh, ksh, and Posix.2, if a word expands into nothing
+ and a double-quoted "$@" appears anywhere in it, then the entire
+ word is removed. */
+ else if (quoted_state == UNQUOTED || quoted_dollar_at)
+ list = (WORD_LIST *)NULL;
+#if 0
+ else
+ {
+ tword = make_bare_word (istring);
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ tword->flags |= W_QUOTED;
+ list = make_word_list (tword, (WORD_LIST *)NULL);
+ }
+#else
+ else
+ list = (WORD_LIST *)NULL;
+#endif
+ }
+ else if (word->flags & W_NOSPLIT)
+ {
+ tword = make_bare_word (istring);
+ if (word->flags & W_ASSIGNMENT)
+ tword->flags |= W_ASSIGNMENT; /* XXX */
+ if (word->flags & W_COMPASSIGN)
+ tword->flags |= W_COMPASSIGN; /* XXX */
+ if (word->flags & W_NOGLOB)
+ tword->flags |= W_NOGLOB; /* XXX */
+ if (word->flags & W_NOEXPAND)
+ tword->flags |= W_NOEXPAND; /* XXX */
+ if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
+ tword->flags |= W_QUOTED;
+ if (had_quoted_null)
+ tword->flags |= W_HASQUOTEDNULL;
+ list = make_word_list (tword, (WORD_LIST *)NULL);
+ }
+ else
+ {
+ char *ifs_chars;
+
+ ifs_chars = (quoted_dollar_at || has_dollar_at) ? ifs_value : (char *)NULL;
+
+ /* If we have $@, we need to split the results no matter what. If
+ IFS is unset or NULL, string_list_dollar_at has separated the
+ positional parameters with a space, so we split on space (we have
+ set ifs_chars to " \t\n" above if ifs is unset). If IFS is set,
+ string_list_dollar_at has separated the positional parameters
+ with the first character of $IFS, so we split on $IFS. */
+ if (has_dollar_at && ifs_chars)
+ list = list_string (istring, *ifs_chars ? ifs_chars : " ", 1);
+ else
+ {
+ tword = make_bare_word (istring);
+ if ((quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) || (quoted_state == WHOLLY_QUOTED))
+ tword->flags |= W_QUOTED;
+ if (word->flags & W_ASSIGNMENT)
+ tword->flags |= W_ASSIGNMENT;
+ if (word->flags & W_COMPASSIGN)
+ tword->flags |= W_COMPASSIGN;
+ if (word->flags & W_NOGLOB)
+ tword->flags |= W_NOGLOB;
+ if (word->flags & W_NOEXPAND)
+ tword->flags |= W_NOEXPAND;
+ if (had_quoted_null)
+ tword->flags |= W_HASQUOTEDNULL; /* XXX */
+ list = make_word_list (tword, (WORD_LIST *)NULL);
+ }
+ }
+
+ free (istring);
+ return (list);
+}
+
+/* **************************************************************** */
+/* */
+/* Functions for Quote Removal */
+/* */
+/* **************************************************************** */
+
+/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
+ backslash quoting rules for within double quotes or a here document. */
+char *
+string_quote_removal (string, quoted)
+ char *string;
+ int quoted;
+{
+ size_t slen;
+ char *r, *result_string, *temp, *send;
+ int sindex, tindex, dquote;
+ unsigned char c;
+ DECLARE_MBSTATE;
+
+ /* The result can be no longer than the original string. */
+ slen = strlen (string);
+ send = string + slen;
+
+ r = result_string = (char *)xmalloc (slen + 1);
+
+ for (dquote = sindex = 0; c = string[sindex];)
+ {
+ switch (c)
+ {
+ case '\\':
+ c = string[++sindex];
+ if (((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote) && (sh_syntaxtab[c] & CBSDQUOTE) == 0)
+ *r++ = '\\';
+ /* FALLTHROUGH */
+
+ default:
+ SCOPY_CHAR_M (r, string, send, sindex);
+ break;
+
+ case '\'':
+ if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || dquote)
+ {
+ *r++ = c;
+ sindex++;
+ break;
+ }
+ tindex = sindex + 1;
+ temp = string_extract_single_quoted (string, &tindex);
+ if (temp)
+ {
+ strcpy (r, temp);
+ r += strlen (r);
+ free (temp);
+ }
+ sindex = tindex;
+ break;
+
+ case '"':
+ dquote = 1 - dquote;
+ sindex++;
+ break;
+ }
+ }
+ *r = '\0';
+ return (result_string);
+}
+
+#if 0
+/* UNUSED */
+/* Perform quote removal on word WORD. This allocates and returns a new
+ WORD_DESC *. */
+WORD_DESC *
+word_quote_removal (word, quoted)
+ WORD_DESC *word;
+ int quoted;
+{
+ WORD_DESC *w;
+ char *t;
+
+ t = string_quote_removal (word->word, quoted);
+ w = alloc_word_desc ();
+ w->word = t ? t : savestring ("");
+ return (w);
+}
+
+/* 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. */
+WORD_LIST *
+word_list_quote_removal (list, quoted)
+ WORD_LIST *list;
+ int quoted;
+{
+ WORD_LIST *result, *t, *tresult, *e;
+
+ for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
+ {
+ tresult = make_word_list (word_quote_removal (t->word, quoted), (WORD_LIST *)NULL);
+#if 0
+ result = (WORD_LIST *) list_append (result, tresult);
+#else
+ if (result == 0)
+ result = e = tresult;
+ else
+ {
+ e->next = tresult;
+ while (e->next)
+ e = e->next;
+ }
+#endif
+ }
+ return (result);
+}
+#endif
+
+/*******************************************
+ * *
+ * Functions to perform word splitting *
+ * *
+ *******************************************/
+
+void
+setifs (v)
+ SHELL_VAR *v;
+{
+ char *t;
+ unsigned char uc;
+
+ ifs_var = v;
+#if 0
+ ifs_value = v ? value_cell (v) : " \t\n";
+#else
+ ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
+#endif
+
+ /* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
+ handle multibyte chars in IFS */
+ memset (ifs_cmap, '\0', sizeof (ifs_cmap));
+ for (t = ifs_value ; t && *t; t++)
+ {
+ uc = *t;
+ ifs_cmap[uc] = 1;
+ }
+
+#if defined (HANDLE_MULTIBYTE)
+ if (ifs_value == 0)
+ {
+ ifs_firstc[0] = '\0';
+ ifs_firstc_len = 1;
+ }
+ else
+ {
+ size_t ifs_len;
+ ifs_len = strnlen (ifs_value, MB_CUR_MAX);
+ ifs_firstc_len = MBLEN (ifs_value, ifs_len);
+ if (ifs_firstc_len == 1 || ifs_firstc_len == 0 || MB_INVALIDCH (ifs_firstc_len))
+ {
+ ifs_firstc[0] = ifs_value[0];
+ ifs_firstc[1] = '\0';
+ ifs_firstc_len = 1;
+ }
+ else
+ memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
+ }
+#else
+ ifs_firstc = ifs_value ? *ifs_value : 0;
+#endif
+}
+
+char *
+getifs ()
+{
+ return ifs_value;
+}
+
+/* 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. */
+WORD_LIST *
+word_split (w, ifs_chars)
+ WORD_DESC *w;
+ char *ifs_chars;
+{
+ WORD_LIST *result;
+
+ if (w)
+ {
+ char *xifs;
+
+ xifs = ((w->flags & W_QUOTED) || ifs_chars == 0) ? "" : ifs_chars;
+ result = list_string (w->word, xifs, w->flags & W_QUOTED);
+ }
+ else
+ result = (WORD_LIST *)NULL;
+
+ return (result);
+}
+
+/* Perform word splitting on LIST and return the RESULT. It is possible
+ to return (WORD_LIST *)NULL. */
+static WORD_LIST *
+word_list_split (list)
+ WORD_LIST *list;
+{
+ WORD_LIST *result, *t, *tresult, *e;
+
+ for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
+ {
+ tresult = word_split (t->word, ifs_value);
+#if 0
+ result = (WORD_LIST *) list_append (result, tresult);
+#else
+ if (result == 0)
+ result = e = tresult;
+ else
+ {
+ e->next = tresult;
+ while (e->next)
+ e = e->next;
+ }
+#endif
+ }
+ return (result);
+}
+
+/**************************************************
+ * *
+ * Functions to expand an entire WORD_LIST *
+ * *
+ **************************************************/
+
+/* Do any word-expansion-specific cleanup and jump to top_level */
+static void
+exp_jump_to_top_level (v)
+ int v;
+{
+ /* Cleanup code goes here. */
+ expand_no_split_dollar_star = 0; /* XXX */
+ expanding_redir = 0;
+
+ jump_to_top_level (v);
+}
+
+/* Put NLIST (which is a WORD_LIST * of only one element) at the front of
+ ELIST, and set ELIST to the new list. */
+#define PREPEND_LIST(nlist, elist) \
+ do { nlist->next = elist; elist = nlist; } while (0)
+
+/* Separate out any initial variable assignments from TLIST. If set -k has
+ been executed, remove all assignment statements from TLIST. Initial
+ variable assignments and other environment assignments are placed
+ on SUBST_ASSIGN_VARLIST. */
+static WORD_LIST *
+separate_out_assignments (tlist)
+ WORD_LIST *tlist;
+{
+ register WORD_LIST *vp, *lp;
+
+ if (!tlist)
+ return ((WORD_LIST *)NULL);
+
+ if (subst_assign_varlist)
+ dispose_words (subst_assign_varlist); /* Clean up after previous error */
+
+ subst_assign_varlist = (WORD_LIST *)NULL;
+ vp = lp = tlist;
+
+ /* Separate out variable assignments at the start of the command.
+ Loop invariant: vp->next == lp
+ Loop postcondition:
+ lp = list of words left after assignment statements skipped
+ tlist = original list of words
+ */
+ while (lp && (lp->word->flags & W_ASSIGNMENT))
+ {
+ vp = lp;
+ lp = lp->next;
+ }
+
+ /* If lp != tlist, we have some initial assignment statements.
+ We make SUBST_ASSIGN_VARLIST point to the list of assignment
+ words and TLIST point to the remaining words. */
+ if (lp != tlist)
+ {
+ subst_assign_varlist = tlist;
+ /* ASSERT(vp->next == lp); */
+ vp->next = (WORD_LIST *)NULL; /* terminate variable list */
+ tlist = lp; /* remainder of word list */
+ }
+
+ /* vp == end of variable list */
+ /* tlist == remainder of original word list without variable assignments */
+ if (!tlist)
+ /* All the words in tlist were assignment statements */
+ return ((WORD_LIST *)NULL);
+
+ /* ASSERT(tlist != NULL); */
+ /* ASSERT((tlist->word->flags & W_ASSIGNMENT) == 0); */
+
+ /* If the -k option is in effect, we need to go through the remaining
+ words, separate out the assignment words, and place them on
+ SUBST_ASSIGN_VARLIST. */
+ if (place_keywords_in_env)
+ {
+ WORD_LIST *tp; /* tp == running pointer into tlist */
+
+ tp = tlist;
+ lp = tlist->next;
+
+ /* Loop Invariant: tp->next == lp */
+ /* Loop postcondition: tlist == word list without assignment statements */
+ while (lp)
+ {
+ if (lp->word->flags & W_ASSIGNMENT)
+ {
+ /* Found an assignment statement, add this word to end of
+ subst_assign_varlist (vp). */
+ if (!subst_assign_varlist)
+ subst_assign_varlist = vp = lp;
+ else
+ {
+ vp->next = lp;
+ vp = lp;
+ }
+
+ /* Remove the word pointed to by LP from TLIST. */
+ tp->next = lp->next;
+ /* ASSERT(vp == lp); */
+ lp->next = (WORD_LIST *)NULL;
+ lp = tp->next;
+ }
+ else
+ {
+ tp = lp;
+ lp = lp->next;
+ }
+ }
+ }
+ return (tlist);
+}
+
+#define WEXP_VARASSIGN 0x001
+#define WEXP_BRACEEXP 0x002
+#define WEXP_TILDEEXP 0x004
+#define WEXP_PARAMEXP 0x008
+#define WEXP_PATHEXP 0x010
+
+/* All of the expansions, including variable assignments at the start of
+ the list. */
+#define WEXP_ALL (WEXP_VARASSIGN|WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
+
+/* All of the expansions except variable assignments at the start of
+ the list. */
+#define WEXP_NOVARS (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP|WEXP_PATHEXP)
+
+/* All of the `shell expansions': brace expansion, tilde expansion, parameter
+ expansion, command substitution, arithmetic expansion, word splitting, and
+ quote removal. */
+#define WEXP_SHELLEXP (WEXP_BRACEEXP|WEXP_TILDEEXP|WEXP_PARAMEXP)
+
+/* 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. */
+
+WORD_LIST *
+expand_words (list)
+ WORD_LIST *list;
+{
+ return (expand_word_list_internal (list, WEXP_ALL));
+}
+
+/* Same as expand_words (), but doesn't hack variable or environment
+ variables. */
+WORD_LIST *
+expand_words_no_vars (list)
+ WORD_LIST *list;
+{
+ return (expand_word_list_internal (list, WEXP_NOVARS));
+}
+
+WORD_LIST *
+expand_words_shellexp (list)
+ WORD_LIST *list;
+{
+ return (expand_word_list_internal (list, WEXP_SHELLEXP));
+}
+
+static WORD_LIST *
+glob_expand_word_list (tlist, eflags)
+ WORD_LIST *tlist;
+ int eflags;
+{
+ char **glob_array, *temp_string;
+ register int glob_index;
+ WORD_LIST *glob_list, *output_list, *disposables, *next;
+ WORD_DESC *tword;
+
+ output_list = disposables = (WORD_LIST *)NULL;
+ glob_array = (char **)NULL;
+ while (tlist)
+ {
+ /* For each word, either globbing is attempted or the word is
+ added to orig_list. If globbing succeeds, the results are
+ added to orig_list and the word (tlist) is added to the list
+ of disposable words. If globbing fails and failed glob
+ expansions are left unchanged (the shell default), the
+ original word is added to orig_list. If globbing fails and
+ failed glob expansions are removed, the original word is
+ added to the list of disposable words. orig_list ends up
+ in reverse order and requires a call to REVERSE_LIST to
+ be set right. After all words are examined, the disposable
+ words are freed. */
+ next = tlist->next;
+
+ /* If the word isn't an assignment and contains an unquoted
+ pattern matching character, then glob it. */
+ if ((tlist->word->flags & W_NOGLOB) == 0 &&
+ unquoted_glob_pattern_p (tlist->word->word))
+ {
+ glob_array = shell_glob_filename (tlist->word->word);
+
+ /* Handle error cases.
+ I don't think we should report errors like "No such file
+ or directory". However, I would like to report errors
+ like "Read failed". */
+
+ if (glob_array == 0 || GLOB_FAILED (glob_array))
+ {
+ glob_array = (char **)xmalloc (sizeof (char *));
+ glob_array[0] = (char *)NULL;
+ }
+
+ /* Dequote the current word in case we have to use it. */
+ if (glob_array[0] == NULL)
+ {
+ temp_string = dequote_string (tlist->word->word);
+ free (tlist->word->word);
+ tlist->word->word = temp_string;
+ }
+
+ /* Make the array into a word list. */
+ glob_list = (WORD_LIST *)NULL;
+ for (glob_index = 0; glob_array[glob_index]; glob_index++)
+ {
+ tword = make_bare_word (glob_array[glob_index]);
+ tword->flags |= W_GLOBEXP; /* XXX */
+ glob_list = make_word_list (tword, glob_list);
+ }
+
+ if (glob_list)
+ {
+ output_list = (WORD_LIST *)list_append (glob_list, output_list);
+ PREPEND_LIST (tlist, disposables);
+ }
+ else if (fail_glob_expansion != 0)
+ {
+ report_error (_("no match: %s"), tlist->word->word);
+ jump_to_top_level (DISCARD);
+ }
+ else if (allow_null_glob_expansion == 0)
+ {
+ /* Failed glob expressions are left unchanged. */
+ PREPEND_LIST (tlist, output_list);
+ }
+ else
+ {
+ /* Failed glob expressions are removed. */
+ PREPEND_LIST (tlist, disposables);
+ }
+ }
+ else
+ {
+ /* Dequote the string. */
+ temp_string = dequote_string (tlist->word->word);
+ free (tlist->word->word);
+ tlist->word->word = temp_string;
+ PREPEND_LIST (tlist, output_list);
+ }
+
+ strvec_dispose (glob_array);
+ glob_array = (char **)NULL;
+
+ tlist = next;
+ }
+
+ if (disposables)
+ dispose_words (disposables);
+
+ if (output_list)
+ output_list = REVERSE_LIST (output_list, WORD_LIST *);
+
+ return (output_list);
+}
+
+#if defined (BRACE_EXPANSION)
+static WORD_LIST *
+brace_expand_word_list (tlist, eflags)
+ WORD_LIST *tlist;
+ int eflags;
+{
+ register char **expansions;
+ char *temp_string;
+ WORD_LIST *disposables, *output_list, *next;
+ WORD_DESC *w;
+ int eindex;
+
+ for (disposables = output_list = (WORD_LIST *)NULL; tlist; tlist = next)
+ {
+ next = tlist->next;
+
+ /* Only do brace expansion if the word has a brace character. If
+ not, just add the word list element to BRACES and continue. In
+ the common case, at least when running shell scripts, this will
+ degenerate to a bunch of calls to `xstrchr', and then what is
+ basically a reversal of TLIST into BRACES, which is corrected
+ by a call to REVERSE_LIST () on BRACES when the end of TLIST
+ is reached. */
+ if (xstrchr (tlist->word->word, LBRACE))
+ {
+ expansions = brace_expand (tlist->word->word);
+
+ for (eindex = 0; temp_string = expansions[eindex]; eindex++)
+ {
+ w = make_word (temp_string);
+ /* If brace expansion didn't change the word, preserve
+ the flags. We may want to preserve the flags
+ unconditionally someday -- XXX */
+ if (STREQ (temp_string, tlist->word->word))
+ w->flags = tlist->word->flags;
+ output_list = make_word_list (w, output_list);
+ free (expansions[eindex]);
+ }
+ free (expansions);
+
+ /* Add TLIST to the list of words to be freed after brace
+ expansion has been performed. */
+ PREPEND_LIST (tlist, disposables);
+ }
+ else
+ PREPEND_LIST (tlist, output_list);
+ }
+
+ if (disposables)
+ dispose_words (disposables);
+
+ if (output_list)
+ output_list = REVERSE_LIST (output_list, WORD_LIST *);
+
+ return (output_list);
+}
+#endif
+
+static WORD_LIST *
+shell_expand_word_list (tlist, eflags)
+ WORD_LIST *tlist;
+ int eflags;
+{
+ WORD_LIST *expanded, *orig_list, *new_list, *next, *temp_list;
+ int expanded_something, has_dollar_at;
+ char *temp_string;
+
+ /* We do tilde expansion all the time. This is what 1003.2 says. */
+ new_list = (WORD_LIST *)NULL;
+ for (orig_list = tlist; tlist; tlist = next)
+ {
+ temp_string = tlist->word->word;
+
+ next = tlist->next;
+
+#if defined (ARRAY_VARS)
+ /* If this is a compound array assignment to a builtin that accepts
+ such assignments (e.g., `declare'), take the assignment and perform
+ it separately, handling the semantics of declarations inside shell
+ functions. This avoids the double-evaluation of such arguments,
+ because `declare' does some evaluation of compound assignments on
+ its own. */
+ if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
+ {
+ int t;
+
+ t = do_word_assignment (tlist->word);
+ if (t == 0)
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ exp_jump_to_top_level (DISCARD);
+ }
+
+ /* Now transform the word as ksh93 appears to do and go on */
+ t = assignment (tlist->word->word, 0);
+ tlist->word->word[t] = '\0';
+ tlist->word->flags &= ~(W_ASSIGNMENT|W_NOSPLIT|W_COMPASSIGN|W_ASSIGNARG);
+ }
+#endif
+
+ expanded_something = 0;
+ expanded = expand_word_internal
+ (tlist->word, 0, 0, &has_dollar_at, &expanded_something);
+
+ if (expanded == &expand_word_error || expanded == &expand_word_fatal)
+ {
+ /* By convention, each time this error is returned,
+ tlist->word->word has already been freed. */
+ tlist->word->word = (char *)NULL;
+
+ /* Dispose our copy of the original list. */
+ dispose_words (orig_list);
+ /* Dispose the new list we're building. */
+ dispose_words (new_list);
+
+ last_command_exit_value = EXECUTION_FAILURE;
+ if (expanded == &expand_word_error)
+ exp_jump_to_top_level (DISCARD);
+ else
+ exp_jump_to_top_level (FORCE_EOF);
+ }
+
+ /* Don't split words marked W_NOSPLIT. */
+ if (expanded_something && (tlist->word->flags & W_NOSPLIT) == 0)
+ {
+ temp_list = word_list_split (expanded);
+ dispose_words (expanded);
+ }
+ else
+ {
+ /* If no parameter expansion, command substitution, process
+ substitution, or arithmetic substitution took place, then
+ do not do word splitting. We still have to remove quoted
+ null characters from the result. */
+ word_list_remove_quoted_nulls (expanded);
+ temp_list = expanded;
+ }
+
+ expanded = REVERSE_LIST (temp_list, WORD_LIST *);
+ new_list = (WORD_LIST *)list_append (expanded, new_list);
+ }
+
+ if (orig_list)
+ dispose_words (orig_list);
+
+ if (new_list)
+ new_list = REVERSE_LIST (new_list, WORD_LIST *);
+
+ return (new_list);
+}
+
+/* The workhorse for expand_words () and expand_words_no_vars ().
+ First arg is LIST, a WORD_LIST of words.
+ Second arg EFLAGS is a flags word controlling which expansions are
+ performed.
+
+ This does all of the substitutions: brace expansion, tilde expansion,
+ parameter expansion, command substitution, arithmetic expansion,
+ process substitution, word splitting, and pathname expansion, according
+ to the bits set in EFLAGS. Words with the W_QUOTED or W_NOSPLIT bits
+ set, or for which no expansion is done, do not undergo word splitting.
+ Words with the W_NOGLOB bit set do not undergo pathname expansion. */
+static WORD_LIST *
+expand_word_list_internal (list, eflags)
+ WORD_LIST *list;
+ int eflags;
+{
+ WORD_LIST *new_list, *temp_list;
+ int tint;
+
+ if (list == 0)
+ return ((WORD_LIST *)NULL);
+
+ garglist = new_list = copy_word_list (list);
+ if (eflags & WEXP_VARASSIGN)
+ {
+ garglist = new_list = separate_out_assignments (new_list);
+ if (new_list == 0)
+ {
+ if (subst_assign_varlist)
+ {
+ /* All the words were variable assignments, so they are placed
+ into the shell's environment. */
+ for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
+ {
+ this_command_name = (char *)NULL; /* no arithmetic errors */
+ tint = do_word_assignment (temp_list->word);
+ /* Variable assignment errors in non-interactive shells
+ running in Posix.2 mode cause the shell to exit. */
+ if (tint == 0)
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ if (interactive_shell == 0 && posixly_correct)
+ exp_jump_to_top_level (FORCE_EOF);
+ else
+ exp_jump_to_top_level (DISCARD);
+ }
+ }
+ dispose_words (subst_assign_varlist);
+ subst_assign_varlist = (WORD_LIST *)NULL;
+ }
+ return ((WORD_LIST *)NULL);
+ }
+ }
+
+ /* Begin expanding the words that remain. The expansions take place on
+ things that aren't really variable assignments. */
+
+#if defined (BRACE_EXPANSION)
+ /* Do brace expansion on this word if there are any brace characters
+ in the string. */
+ if ((eflags & WEXP_BRACEEXP) && brace_expansion && new_list)
+ new_list = brace_expand_word_list (new_list, eflags);
+#endif /* BRACE_EXPANSION */
+
+ /* Perform the `normal' shell expansions: tilde expansion, parameter and
+ variable substitution, command substitution, arithmetic expansion,
+ and word splitting. */
+ new_list = shell_expand_word_list (new_list, eflags);
+
+ /* Okay, we're almost done. Now let's just do some filename
+ globbing. */
+ if (new_list)
+ {
+ if ((eflags & WEXP_PATHEXP) && disallow_filename_globbing == 0)
+ /* Glob expand the word list unless globbing has been disabled. */
+ new_list = glob_expand_word_list (new_list, eflags);
+ else
+ /* Dequote the words, because we're not performing globbing. */
+ new_list = dequote_list (new_list);
+ }
+
+ if ((eflags & WEXP_VARASSIGN) && subst_assign_varlist)
+ {
+ sh_wassign_func_t *assign_func;
+
+ /* If the remainder of the words expand to nothing, Posix.2 requires
+ that the variable and environment assignments affect the shell's
+ environment. */
+ assign_func = new_list ? assign_in_env : do_word_assignment;
+ tempenv_assign_error = 0;
+
+ for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
+ {
+ this_command_name = (char *)NULL;
+ tint = (*assign_func) (temp_list->word);
+ /* Variable assignment errors in non-interactive shells running
+ in Posix.2 mode cause the shell to exit. */
+ if (tint == 0)
+ {
+ if (assign_func == do_word_assignment)
+ {
+ last_command_exit_value = EXECUTION_FAILURE;
+ if (interactive_shell == 0 && posixly_correct)
+ exp_jump_to_top_level (FORCE_EOF);
+ else
+ exp_jump_to_top_level (DISCARD);
+ }
+ else
+ tempenv_assign_error++;
+ }
+ }
+
+ dispose_words (subst_assign_varlist);
+ subst_assign_varlist = (WORD_LIST *)NULL;
+ }
+
+#if 0
+ tint = list_length (new_list) + 1;
+ RESIZE_MALLOCED_BUFFER (glob_argv_flags, 0, tint, glob_argv_flags_size, 16);
+ for (tint = 0, temp_list = new_list; temp_list; temp_list = temp_list->next)
+ glob_argv_flags[tint++] = (temp_list->word->flags & W_GLOBEXP) ? '1' : '0';
+ glob_argv_flags[tint] = '\0';
+#endif
+
+ return (new_list);
+}
diff --git a/subst.h b/subst.h
index 33d3f49e..b7c6682b 100644
--- a/subst.h
+++ b/subst.h
@@ -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 *));
diff --git a/subst.h~ b/subst.h~
new file mode 100644
index 00000000..33d3f49e
--- /dev/null
+++ b/subst.h~
@@ -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_ */
diff --git a/support/Makefile.in b/support/Makefile.in
index b49bd45d..b94e445d 100644
--- a/support/Makefile.in
+++ b/support/Makefile.in
@@ -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)
diff --git a/support/Makefile.in~ b/support/Makefile.in~
new file mode 100644
index 00000000..b49bd45d
--- /dev/null
+++ b/support/Makefile.in~
@@ -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
diff --git a/support/mksignames.c b/support/mksignames.c
index e6a15189..a31c5b8c 100644
--- a/support/mksignames.c
+++ b/support/mksignames.c
@@ -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&LTOSTOP) */
- 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);
}
diff --git a/support/mksignames.c.save b/support/mksignames.c.save
new file mode 100644
index 00000000..8b96a5a1
--- /dev/null
+++ b/support/mksignames.c.save
@@ -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&LTOSTOP) */
+ 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);
+}
diff --git a/support/mksignames.c~ b/support/mksignames.c~
new file mode 100644
index 00000000..fc08ff55
--- /dev/null
+++ b/support/mksignames.c~
@@ -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);
+}
diff --git a/support/signames.c b/support/signames.c
new file mode 100644
index 00000000..89cee53b
--- /dev/null
+++ b/support/signames.c
@@ -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&LTOSTOP) */
+ 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";
+}
diff --git a/support/signames.c~ b/support/signames.c~
new file mode 100644
index 00000000..7a0d8665
--- /dev/null
+++ b/support/signames.c~
@@ -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&LTOSTOP) */
+ 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";
+}
diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST
index 3efcf32d..72ec06a2 100755
--- a/tests/RUN-ONE-TEST
+++ b/tests/RUN-ONE-TEST
@@ -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
diff --git a/tests/RUN-ONE-TEST~ b/tests/RUN-ONE-TEST~
new file mode 100755
index 00000000..3efcf32d
--- /dev/null
+++ b/tests/RUN-ONE-TEST~
@@ -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 "$@"
diff --git a/tests/new-exp.right b/tests/new-exp.right
index 8866835d..9136132d 100644
--- a/tests/new-exp.right
+++ b/tests/new-exp.right
@@ -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>
diff --git a/tests/new-exp.tests b/tests/new-exp.tests
index e0c2702a..5932ed36 100644
--- a/tests/new-exp.tests
+++ b/tests/new-exp.tests
@@ -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##?}
diff --git a/tests/new-exp.tests.save1 b/tests/new-exp.tests.save1
new file mode 100644
index 00000000..e0c2702a
--- /dev/null
+++ b/tests/new-exp.tests.save1
@@ -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"}
diff --git a/tests/new-exp.tests~ b/tests/new-exp.tests~
new file mode 100644
index 00000000..2d6d8f90
--- /dev/null
+++ b/tests/new-exp.tests~
@@ -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"}
diff --git a/tests/tilde.right b/tests/tilde.right
index b22dabf1..fe58ae34 100644
--- a/tests/tilde.right
+++ b/tests/tilde.right
@@ -22,3 +22,4 @@ abcd:~chet
ok 1
ok 2
ok 3
+~root
diff --git a/tests/tilde.right~ b/tests/tilde.right~
new file mode 100644
index 00000000..b22dabf1
--- /dev/null
+++ b/tests/tilde.right~
@@ -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
diff --git a/tests/tilde.tests b/tests/tilde.tests
index f5f53090..8b2bdb8b 100644
--- a/tests/tilde.tests
+++ b/tests/tilde.tests
@@ -64,3 +64,6 @@ case $unset in
"") echo ok 3 ;;
*) echo bad 3 ;;
esac
+
+USER=root # should exist just about everywhere
+echo ~$USER
diff --git a/tests/tilde.tests~ b/tests/tilde.tests~
new file mode 100644
index 00000000..f5f53090
--- /dev/null
+++ b/tests/tilde.tests~
@@ -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
diff --git a/trap.c b/trap.c
index 1125534a..e3ff2cba 100644
--- a/trap.c
+++ b/trap.c
@@ -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;
diff --git a/trap.c~ b/trap.c~
new file mode 100644
index 00000000..1125534a
--- /dev/null
+++ b/trap.c~
@@ -0,0 +1,1002 @@
+/* trap.c -- Not the trap command, but useful functions for manipulating
+ those objects. The trap command is in builtins/trap.def. */
+
+/* Copyright (C) 1987-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 (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include "bashtypes.h"
+#include "bashansi.h"
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "bashintl.h"
+
+#include "trap.h"
+
+#include "shell.h"
+#include "flags.h"
+#include "input.h" /* for save_token_state, restore_token_state */
+#include "signames.h"
+#include "builtins.h"
+#include "builtins/common.h"
+#include "builtins/builtext.h"
+
+#ifndef errno
+extern int errno;
+#endif
+
+/* Flags which describe the current handling state of a signal. */
+#define SIG_INHERITED 0x0 /* Value inherited from parent. */
+#define SIG_TRAPPED 0x1 /* Currently trapped. */
+#define SIG_HARD_IGNORE 0x2 /* Signal was ignored on shell entry. */
+#define SIG_SPECIAL 0x4 /* Treat this signal specially. */
+#define SIG_NO_TRAP 0x8 /* Signal cannot be trapped. */
+#define SIG_INPROGRESS 0x10 /* Signal handler currently executing. */
+#define SIG_CHANGED 0x20 /* Trap value changed in trap handler. */
+#define SIG_IGNORED 0x40 /* The signal is currently being ignored. */
+
+#define SPECIAL_TRAP(s) ((s) == EXIT_TRAP || (s) == DEBUG_TRAP || (s) == ERROR_TRAP || (s) == RETURN_TRAP)
+
+/* An array of such flags, one for each signal, describing what the
+ shell will do with a signal. DEBUG_TRAP == NSIG; some code below
+ assumes this. */
+static int sigmodes[BASH_NSIG];
+
+static void free_trap_command __P((int));
+static void change_signal __P((int, char *));
+
+static void get_original_signal __P((int));
+
+static int _run_trap_internal __P((int, char *));
+
+static void reset_signal __P((int));
+static void restore_signal __P((int));
+static void reset_or_restore_signal_handlers __P((sh_resetsig_func_t *));
+
+/* Variables used here but defined in other files. */
+extern int interrupt_immediately;
+extern int last_command_exit_value;
+extern int line_number;
+
+extern char *this_command_name;
+extern sh_builtin_func_t *this_shell_builtin;
+extern procenv_t wait_intr_buf;
+extern int return_catch_flag, return_catch_value;
+extern int subshell_level;
+
+/* The list of things to do originally, before we started trapping. */
+SigHandler *original_signals[NSIG];
+
+/* For each signal, a slot for a string, which is a command to be
+ executed when that signal is recieved. The slot can also contain
+ DEFAULT_SIG, which means do whatever you were going to do before
+ you were so rudely interrupted, or IGNORE_SIG, which says ignore
+ this signal. */
+char *trap_list[BASH_NSIG];
+
+/* A bitmap of signals received for which we have trap handlers. */
+int pending_traps[NSIG];
+
+/* Set to the number of the signal we're running the trap for + 1.
+ Used in execute_cmd.c and builtins/common.c to clean up when
+ parse_and_execute does not return normally after executing the
+ trap command (e.g., when `return' is executed in the trap command). */
+int running_trap;
+
+/* Set to last_command_exit_value before running a trap. */
+int trap_saved_exit_value;
+
+/* The (trapped) signal received while executing in the `wait' builtin */
+int wait_signal_received;
+
+/* A value which can never be the target of a trap handler. */
+#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
+
+void
+initialize_traps ()
+{
+ register int i;
+
+ 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;
+
+ for (i = 1; i < NSIG; i++)
+ {
+ pending_traps[i] = 0;
+ trap_list[i] = (char *)DEFAULT_SIG;
+ sigmodes[i] = SIG_INHERITED;
+ original_signals[i] = IMPOSSIBLE_TRAP_HANDLER;
+ }
+
+ /* Show which signals are treated specially by the shell. */
+#if defined (SIGCHLD)
+ original_signals[SIGCHLD] =
+ (SigHandler *) set_signal_handler (SIGCHLD, SIG_DFL);
+ set_signal_handler (SIGCHLD, original_signals[SIGCHLD]);
+ sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
+#endif /* SIGCHLD */
+
+ original_signals[SIGINT] =
+ (SigHandler *) set_signal_handler (SIGINT, SIG_DFL);
+ set_signal_handler (SIGINT, original_signals[SIGINT]);
+ sigmodes[SIGINT] |= SIG_SPECIAL;
+
+#if defined (__BEOS__)
+ /* BeOS sets SIGINT to SIG_IGN! */
+ original_signals[SIGINT] = SIG_DFL;
+#endif
+
+ original_signals[SIGQUIT] =
+ (SigHandler *) set_signal_handler (SIGQUIT, SIG_DFL);
+ set_signal_handler (SIGQUIT, original_signals[SIGQUIT]);
+ sigmodes[SIGQUIT] |= SIG_SPECIAL;
+
+ if (interactive)
+ {
+ original_signals[SIGTERM] =
+ (SigHandler *)set_signal_handler (SIGTERM, SIG_DFL);
+ set_signal_handler (SIGTERM, original_signals[SIGTERM]);
+ sigmodes[SIGTERM] |= SIG_SPECIAL;
+ }
+}
+
+#ifdef INCLUDE_UNUSED
+/* Return a printable representation of the trap handler for SIG. */
+static char *
+trap_handler_string (sig)
+ int sig;
+{
+ if (trap_list[sig] == (char *)DEFAULT_SIG)
+ return "DEFAULT_SIG";
+ else if (trap_list[sig] == (char *)IGNORE_SIG)
+ return "IGNORE_SIG";
+ else if (trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
+ return "IMPOSSIBLE_TRAP_HANDLER";
+ else if (trap_list[sig])
+ return trap_list[sig];
+ else
+ return "NULL";
+}
+#endif
+
+/* Return the print name of this signal. */
+char *
+signal_name (sig)
+ int sig;
+{
+ char *ret;
+
+ /* on cygwin32, signal_names[sig] could be null */
+ ret = (sig >= BASH_NSIG || sig < 0 || signal_names[sig] == NULL)
+ ? _("invalid signal number")
+ : signal_names[sig];
+
+ return ret;
+}
+
+/* Turn a string into a signal number, or a number into
+ a signal number. If STRING is "2", "SIGINT", or "INT",
+ then (int)2 is returned. Return NO_SIG if STRING doesn't
+ contain a valid signal descriptor. */
+int
+decode_signal (string, flags)
+ char *string;
+ int flags;
+{
+ intmax_t sig;
+ char *name;
+
+ if (legal_number (string, &sig))
+ return ((sig >= 0 && sig < NSIG) ? (int)sig : NO_SIG);
+
+ /* A leading `SIG' may be omitted. */
+ for (sig = 0; sig < BASH_NSIG; sig++)
+ {
+ name = signal_names[sig];
+ if (name == 0 || name[0] == '\0')
+ continue;
+
+ /* Check name without the SIG prefix first case sensitivly or
+ insensitively depending on whether flags includes DSIG_NOCASE */
+ if (STREQN (name, "SIG", 3))
+ {
+ name += 3;
+
+ if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
+ return ((int)sig);
+ else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
+ return ((int)sig);
+ /* If we can't use the `SIG' prefix to match, punt on this
+ name now. */
+ else if ((flags & DSIG_SIGPREFIX) == 0)
+ continue;
+ }
+
+ /* Check name with SIG prefix case sensitively or insensitively
+ depending on whether flags includes DSIG_NOCASE */
+ name = signal_names[sig];
+ if ((flags & DSIG_NOCASE) && strcasecmp (string, name) == 0)
+ return ((int)sig);
+ else if ((flags & DSIG_NOCASE) == 0 && strcmp (string, name) == 0)
+ return ((int)sig);
+ }
+
+ return (NO_SIG);
+}
+
+/* Non-zero when we catch a trapped signal. */
+static int catch_flag;
+
+void
+run_pending_traps ()
+{
+ register int sig;
+ int old_exit_value, *token_state;
+
+ if (catch_flag == 0) /* simple optimization */
+ return;
+
+ catch_flag = 0;
+
+ /* Preserve $? when running trap. */
+ old_exit_value = last_command_exit_value;
+
+ for (sig = 1; sig < NSIG; sig++)
+ {
+ /* XXX this could be made into a counter by using
+ while (pending_traps[sig]--) instead of the if statement. */
+ if (pending_traps[sig])
+ {
+#if defined (HAVE_POSIX_SIGNALS)
+ sigset_t set, oset;
+
+ sigemptyset (&set);
+ sigemptyset (&oset);
+
+ sigaddset (&set, sig);
+ sigprocmask (SIG_BLOCK, &set, &oset);
+#else
+# if defined (HAVE_BSD_SIGNALS)
+ int oldmask = sigblock (sigmask (sig));
+# endif
+#endif /* HAVE_POSIX_SIGNALS */
+
+ if (sig == SIGINT)
+ {
+ run_interrupt_trap ();
+ CLRINTERRUPT;
+ }
+ else if (trap_list[sig] == (char *)DEFAULT_SIG ||
+ trap_list[sig] == (char *)IGNORE_SIG ||
+ trap_list[sig] == (char *)IMPOSSIBLE_TRAP_HANDLER)
+ {
+ /* This is possible due to a race condition. Say a bash
+ process has SIGTERM trapped. A subshell is spawned
+ using { list; } & and the parent does something and kills
+ the subshell with SIGTERM. It's possible for the subshell
+ to set pending_traps[SIGTERM] to 1 before the code in
+ execute_cmd.c eventually calls restore_original_signals
+ to reset the SIGTERM signal handler in the subshell. The
+ next time run_pending_traps is called, pending_traps[SIGTERM]
+ will be 1, but the trap handler in trap_list[SIGTERM] will
+ be invalid (probably DEFAULT_SIG, but it could be IGNORE_SIG).
+ Unless we catch this, the subshell will dump core when
+ trap_list[SIGTERM] == DEFAULT_SIG, because DEFAULT_SIG is
+ usually 0x0. */
+ internal_warning (_("run_pending_traps: bad value in trap_list[%d]: %p"),
+ sig, trap_list[sig]);
+ if (trap_list[sig] == (char *)DEFAULT_SIG)
+ {
+ internal_warning (_("run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"), sig, signal_name (sig));
+ kill (getpid (), sig);
+ }
+ }
+ else
+ {
+ token_state = save_token_state ();
+ parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST);
+ restore_token_state (token_state);
+ free (token_state);
+ }
+
+ pending_traps[sig] = 0;
+
+#if defined (HAVE_POSIX_SIGNALS)
+ sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
+#else
+# if defined (HAVE_BSD_SIGNALS)
+ sigsetmask (oldmask);
+# endif
+#endif /* POSIX_VERSION */
+ }
+ }
+
+ last_command_exit_value = old_exit_value;
+}
+
+sighandler
+trap_handler (sig)
+ int sig;
+{
+ int oerrno;
+
+ if ((sig >= NSIG) ||
+ (trap_list[sig] == (char *)DEFAULT_SIG) ||
+ (trap_list[sig] == (char *)IGNORE_SIG))
+ programming_error (_("trap_handler: bad signal %d"), sig);
+ else
+ {
+ oerrno = errno;
+#if defined (MUST_REINSTALL_SIGHANDLERS)
+ set_signal_handler (sig, trap_handler);
+#endif /* MUST_REINSTALL_SIGHANDLERS */
+
+ catch_flag = 1;
+ pending_traps[sig]++;
+
+ if (interrupt_immediately && this_shell_builtin && (this_shell_builtin == wait_builtin))
+ {
+ wait_signal_received = sig;
+ longjmp (wait_intr_buf, 1);
+ }
+
+ if (interrupt_immediately)
+ run_pending_traps ();
+
+ errno = oerrno;
+ }
+
+ SIGRETURN (0);
+}
+
+#if defined (JOB_CONTROL) && defined (SIGCHLD)
+
+#ifdef INCLUDE_UNUSED
+/* Make COMMAND_STRING be executed when SIGCHLD is caught. */
+void
+set_sigchld_trap (command_string)
+ char *command_string;
+{
+ set_signal (SIGCHLD, command_string);
+}
+#endif
+
+/* Make COMMAND_STRING be executed when SIGCHLD is caught iff SIGCHLD
+ is not already trapped. */
+void
+maybe_set_sigchld_trap (command_string)
+ char *command_string;
+{
+ if ((sigmodes[SIGCHLD] & SIG_TRAPPED) == 0)
+ set_signal (SIGCHLD, command_string);
+}
+#endif /* JOB_CONTROL && SIGCHLD */
+
+void
+set_debug_trap (command)
+ char *command;
+{
+ set_signal (DEBUG_TRAP, command);
+}
+
+void
+set_error_trap (command)
+ char *command;
+{
+ set_signal (ERROR_TRAP, command);
+}
+
+void
+set_return_trap (command)
+ char *command;
+{
+ set_signal (RETURN_TRAP, command);
+}
+
+#ifdef INCLUDE_UNUSED
+void
+set_sigint_trap (command)
+ char *command;
+{
+ set_signal (SIGINT, command);
+}
+#endif
+
+/* Reset the SIGINT handler so that subshells that are doing `shellsy'
+ things, like waiting for command substitution or executing commands
+ in explicit subshells ( ( cmd ) ), can catch interrupts properly. */
+SigHandler *
+set_sigint_handler ()
+{
+ if (sigmodes[SIGINT] & SIG_HARD_IGNORE)
+ return ((SigHandler *)SIG_IGN);
+
+ else if (sigmodes[SIGINT] & SIG_IGNORED)
+ return ((SigHandler *)set_signal_handler (SIGINT, SIG_IGN)); /* XXX */
+
+ else if (sigmodes[SIGINT] & SIG_TRAPPED)
+ return ((SigHandler *)set_signal_handler (SIGINT, trap_handler));
+
+ /* The signal is not trapped, so set the handler to the shell's special
+ interrupt handler. */
+ else if (interactive) /* XXX - was interactive_shell */
+ return (set_signal_handler (SIGINT, sigint_sighandler));
+ else
+ return (set_signal_handler (SIGINT, termination_unwind_protect));
+}
+
+/* Return the correct handler for signal SIG according to the values in
+ sigmodes[SIG]. */
+SigHandler *
+trap_to_sighandler (sig)
+ int sig;
+{
+ if (sigmodes[sig] & (SIG_IGNORED|SIG_HARD_IGNORE))
+ return (SIG_IGN);
+ else if (sigmodes[sig] & SIG_TRAPPED)
+ return (trap_handler);
+ else
+ return (SIG_DFL);
+}
+
+/* Set SIG to call STRING as a command. */
+void
+set_signal (sig, string)
+ int sig;
+ char *string;
+{
+ if (SPECIAL_TRAP (sig))
+ {
+ change_signal (sig, savestring (string));
+ if (sig == EXIT_TRAP && interactive == 0)
+ initialize_terminating_signals ();
+ return;
+ }
+
+ /* A signal ignored on entry to the shell cannot be trapped or reset, but
+ no error is reported when attempting to do so. -- Posix.2 */
+ if (sigmodes[sig] & SIG_HARD_IGNORE)
+ return;
+
+ /* Make sure we have original_signals[sig] if the signal has not yet
+ been trapped. */
+ if ((sigmodes[sig] & SIG_TRAPPED) == 0)
+ {
+ /* If we aren't sure of the original value, check it. */
+ if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
+ {
+ original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL);
+ set_signal_handler (sig, original_signals[sig]);
+ }
+
+ /* Signals ignored on entry to the shell cannot be trapped or reset. */
+ if (original_signals[sig] == SIG_IGN)
+ {
+ sigmodes[sig] |= SIG_HARD_IGNORE;
+ return;
+ }
+ }
+
+ /* Only change the system signal handler if SIG_NO_TRAP is not set.
+ The trap command string is changed in either case. The shell signal
+ handlers for SIGINT and SIGCHLD run the user specified traps in an
+ environment in which it is safe to do so. */
+ if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
+ {
+ set_signal_handler (sig, SIG_IGN);
+ change_signal (sig, savestring (string));
+ set_signal_handler (sig, trap_handler);
+ }
+ else
+ change_signal (sig, savestring (string));
+}
+
+static void
+free_trap_command (sig)
+ int sig;
+{
+ if ((sigmodes[sig] & SIG_TRAPPED) && trap_list[sig] &&
+ (trap_list[sig] != (char *)IGNORE_SIG) &&
+ (trap_list[sig] != (char *)DEFAULT_SIG) &&
+ (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER))
+ free (trap_list[sig]);
+}
+
+/* If SIG has a string assigned to it, get rid of it. Then give it
+ VALUE. */
+static void
+change_signal (sig, value)
+ int sig;
+ char *value;
+{
+ if ((sigmodes[sig] & SIG_INPROGRESS) == 0)
+ free_trap_command (sig);
+ trap_list[sig] = value;
+
+ sigmodes[sig] |= SIG_TRAPPED;
+ if (value == (char *)IGNORE_SIG)
+ sigmodes[sig] |= SIG_IGNORED;
+ else
+ sigmodes[sig] &= ~SIG_IGNORED;
+ if (sigmodes[sig] & SIG_INPROGRESS)
+ sigmodes[sig] |= SIG_CHANGED;
+}
+
+#define GET_ORIGINAL_SIGNAL(sig) \
+ if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
+ get_original_signal (sig)
+
+static void
+get_original_signal (sig)
+ int sig;
+{
+ /* If we aren't sure the of the original value, then get it. */
+ if (original_signals[sig] == (SigHandler *)IMPOSSIBLE_TRAP_HANDLER)
+ {
+ original_signals[sig] =
+ (SigHandler *) set_signal_handler (sig, SIG_DFL);
+ set_signal_handler (sig, original_signals[sig]);
+
+ /* Signals ignored on entry to the shell cannot be trapped. */
+ if (original_signals[sig] == SIG_IGN)
+ sigmodes[sig] |= SIG_HARD_IGNORE;
+ }
+}
+
+/* Restore the default action for SIG; i.e., the action the shell
+ would have taken before you used the trap command. This is called
+ from trap_builtin (), which takes care to restore the handlers for
+ the signals the shell treats specially. */
+void
+restore_default_signal (sig)
+ int sig;
+{
+ if (SPECIAL_TRAP (sig))
+ {
+ if ((sig != DEBUG_TRAP && sig != ERROR_TRAP && sig != RETURN_TRAP) ||
+ (sigmodes[sig] & SIG_INPROGRESS) == 0)
+ free_trap_command (sig);
+ trap_list[sig] = (char *)NULL;
+ sigmodes[sig] &= ~SIG_TRAPPED;
+ if (sigmodes[sig] & SIG_INPROGRESS)
+ sigmodes[sig] |= SIG_CHANGED;
+ return;
+ }
+
+ GET_ORIGINAL_SIGNAL (sig);
+
+ /* A signal ignored on entry to the shell cannot be trapped or reset, but
+ no error is reported when attempting to do so. Thanks Posix.2. */
+ if (sigmodes[sig] & SIG_HARD_IGNORE)
+ return;
+
+ /* If we aren't trapping this signal, don't bother doing anything else. */
+ if ((sigmodes[sig] & SIG_TRAPPED) == 0)
+ return;
+
+ /* Only change the signal handler for SIG if it allows it. */
+ if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
+ set_signal_handler (sig, original_signals[sig]);
+
+ /* Change the trap command in either case. */
+ change_signal (sig, (char *)DEFAULT_SIG);
+
+ /* Mark the signal as no longer trapped. */
+ sigmodes[sig] &= ~SIG_TRAPPED;
+}
+
+/* Make this signal be ignored. */
+void
+ignore_signal (sig)
+ int sig;
+{
+ if (SPECIAL_TRAP (sig) && ((sigmodes[sig] & SIG_IGNORED) == 0))
+ {
+ change_signal (sig, (char *)IGNORE_SIG);
+ return;
+ }
+
+ GET_ORIGINAL_SIGNAL (sig);
+
+ /* A signal ignored on entry to the shell cannot be trapped or reset.
+ No error is reported when the user attempts to do so. */
+ if (sigmodes[sig] & SIG_HARD_IGNORE)
+ return;
+
+ /* If already trapped and ignored, no change necessary. */
+ if (sigmodes[sig] & SIG_IGNORED)
+ return;
+
+ /* Only change the signal handler for SIG if it allows it. */
+ if ((sigmodes[sig] & SIG_NO_TRAP) == 0)
+ set_signal_handler (sig, SIG_IGN);
+
+ /* Change the trap command in either case. */
+ change_signal (sig, (char *)IGNORE_SIG);
+}
+
+/* Handle the calling of "trap 0". The only sticky situation is when
+ the command to be executed includes an "exit". This is why we have
+ to provide our own place for top_level to jump to. */
+int
+run_exit_trap ()
+{
+ char *trap_command;
+ int code, function_code, retval;
+
+ trap_saved_exit_value = last_command_exit_value;
+ function_code = 0;
+
+ /* Run the trap only if signal 0 is trapped and not ignored, and we are not
+ currently running in the trap handler (call to exit in the list of
+ commands given to trap 0). */
+ if ((sigmodes[EXIT_TRAP] & SIG_TRAPPED) &&
+ (sigmodes[EXIT_TRAP] & (SIG_IGNORED|SIG_INPROGRESS)) == 0)
+ {
+ trap_command = savestring (trap_list[EXIT_TRAP]);
+ sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
+ sigmodes[EXIT_TRAP] |= SIG_INPROGRESS;
+
+ retval = trap_saved_exit_value;
+ running_trap = 1;
+
+ code = setjmp (top_level);
+
+ /* If we're in a function, make sure return longjmps come here, too. */
+ if (return_catch_flag)
+ function_code = setjmp (return_catch);
+
+ if (code == 0 && function_code == 0)
+ {
+ reset_parser ();
+ parse_and_execute (trap_command, "exit trap", SEVAL_NONINT|SEVAL_NOHIST);
+ }
+ else if (code == ERREXIT)
+ retval = last_command_exit_value;
+ else if (code == EXITPROG)
+ retval = last_command_exit_value;
+ else if (function_code != 0)
+ retval = return_catch_value;
+ else
+ retval = trap_saved_exit_value;
+
+ running_trap = 0;
+ return retval;
+ }
+
+ return (trap_saved_exit_value);
+}
+
+void
+run_trap_cleanup (sig)
+ int sig;
+{
+ sigmodes[sig] &= ~(SIG_INPROGRESS|SIG_CHANGED);
+}
+
+/* Run a trap command for SIG. SIG is one of the signals the shell treats
+ specially. Returns the exit status of the executed trap command list. */
+static int
+_run_trap_internal (sig, tag)
+ int sig;
+ char *tag;
+{
+ char *trap_command, *old_trap;
+ int trap_exit_value, *token_state;
+ int save_return_catch_flag, function_code;
+ procenv_t save_return_catch;
+
+ trap_exit_value = function_code = 0;
+ /* Run the trap only if SIG is trapped and not ignored, and we are not
+ currently executing in the trap handler. */
+ if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0) &&
+ (trap_list[sig] != (char *)IMPOSSIBLE_TRAP_HANDLER) &&
+ ((sigmodes[sig] & SIG_INPROGRESS) == 0))
+ {
+ old_trap = trap_list[sig];
+ sigmodes[sig] |= SIG_INPROGRESS;
+ sigmodes[sig] &= ~SIG_CHANGED; /* just to be sure */
+ trap_command = savestring (old_trap);
+
+ running_trap = sig + 1;
+ trap_saved_exit_value = last_command_exit_value;
+
+ token_state = save_token_state ();
+
+ /* If we're in a function, make sure return longjmps come here, too. */
+ save_return_catch_flag = return_catch_flag;
+ if (return_catch_flag)
+ {
+ COPY_PROCENV (return_catch, save_return_catch);
+ function_code = setjmp (return_catch);
+ }
+
+ if (function_code == 0)
+ parse_and_execute (trap_command, tag, SEVAL_NONINT|SEVAL_NOHIST);
+
+ restore_token_state (token_state);
+ free (token_state);
+
+ trap_exit_value = last_command_exit_value;
+ last_command_exit_value = trap_saved_exit_value;
+ running_trap = 0;
+
+ sigmodes[sig] &= ~SIG_INPROGRESS;
+
+ if (sigmodes[sig] & SIG_CHANGED)
+ {
+#if 0
+ /* Special traps like EXIT, DEBUG, RETURN are handled explicitly in
+ the places where they can be changed using unwind-protects. For
+ example, look at execute_cmd.c:execute_function(). */
+ if (SPECIAL_TRAP (sig) == 0)
+#endif
+ free (old_trap);
+ sigmodes[sig] &= ~SIG_CHANGED;
+ }
+
+ if (save_return_catch_flag)
+ {
+ return_catch_flag = save_return_catch_flag;
+ return_catch_value = trap_exit_value;
+ COPY_PROCENV (save_return_catch, return_catch);
+ if (function_code)
+ longjmp (return_catch, 1);
+ }
+ }
+
+ return trap_exit_value;
+}
+
+int
+run_debug_trap ()
+{
+ int trap_exit_value;
+
+ /* XXX - question: should the DEBUG trap inherit the RETURN trap? */
+ trap_exit_value = 0;
+ if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
+ {
+ trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
+
+#if defined (DEBUGGER)
+ /* If we're in the debugger and the DEBUG trap returns 2 while we're in
+ a function or sourced script, we force a `return'. */
+ if (debugging_mode && trap_exit_value == 2 && return_catch_flag)
+ {
+ return_catch_value = trap_exit_value;
+ longjmp (return_catch, 1);
+ }
+#endif
+ }
+ return trap_exit_value;
+}
+
+void
+run_error_trap ()
+{
+ if ((sigmodes[ERROR_TRAP] & SIG_TRAPPED) && ((sigmodes[ERROR_TRAP] & SIG_IGNORED) == 0) && (sigmodes[ERROR_TRAP] & SIG_INPROGRESS) == 0)
+ _run_trap_internal (ERROR_TRAP, "error trap");
+}
+
+void
+run_return_trap ()
+{
+ int old_exit_value;
+
+#if 0
+ if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && (sigmodes[DEBUG_TRAP] & SIG_INPROGRESS))
+ return;
+#endif
+
+ if ((sigmodes[RETURN_TRAP] & SIG_TRAPPED) && ((sigmodes[RETURN_TRAP] & SIG_IGNORED) == 0) && (sigmodes[RETURN_TRAP] & SIG_INPROGRESS) == 0)
+ {
+ old_exit_value = last_command_exit_value;
+ _run_trap_internal (RETURN_TRAP, "return trap");
+ last_command_exit_value = old_exit_value;
+ }
+}
+
+/* Run a trap set on SIGINT. This is called from throw_to_top_level (), and
+ declared here to localize the trap functions. */
+void
+run_interrupt_trap ()
+{
+ _run_trap_internal (SIGINT, "interrupt trap");
+}
+
+#ifdef INCLUDE_UNUSED
+/* Free all the allocated strings in the list of traps and reset the trap
+ values to the default. */
+void
+free_trap_strings ()
+{
+ register int i;
+
+ for (i = 0; i < BASH_NSIG; i++)
+ {
+ free_trap_command (i);
+ trap_list[i] = (char *)DEFAULT_SIG;
+ sigmodes[i] &= ~SIG_TRAPPED;
+ }
+ trap_list[DEBUG_TRAP] = trap_list[EXIT_TRAP] = trap_list[ERROR_TRAP] = trap_list[RETURN_TRAP] = (char *)NULL;
+}
+#endif
+
+/* Reset the handler for SIG to the original value. */
+static void
+reset_signal (sig)
+ int sig;
+{
+ set_signal_handler (sig, original_signals[sig]);
+ sigmodes[sig] &= ~SIG_TRAPPED;
+}
+
+/* Set the handler signal SIG to the original and free any trap
+ command associated with it. */
+static void
+restore_signal (sig)
+ int sig;
+{
+ set_signal_handler (sig, original_signals[sig]);
+ change_signal (sig, (char *)DEFAULT_SIG);
+ sigmodes[sig] &= ~SIG_TRAPPED;
+}
+
+static void
+reset_or_restore_signal_handlers (reset)
+ sh_resetsig_func_t *reset;
+{
+ register int i;
+
+ /* Take care of the exit trap first */
+ if (sigmodes[EXIT_TRAP] & SIG_TRAPPED)
+ {
+ sigmodes[EXIT_TRAP] &= ~SIG_TRAPPED;
+ if (reset != reset_signal)
+ {
+ free_trap_command (EXIT_TRAP);
+ trap_list[EXIT_TRAP] = (char *)NULL;
+ }
+ }
+
+ for (i = 1; i < NSIG; i++)
+ {
+ if (sigmodes[i] & SIG_TRAPPED)
+ {
+ if (trap_list[i] == (char *)IGNORE_SIG)
+ set_signal_handler (i, SIG_IGN);
+ else
+ (*reset) (i);
+ }
+ else if (sigmodes[i] & SIG_SPECIAL)
+ (*reset) (i);
+ }
+
+ /* Command substitution and other child processes don't inherit the
+ debug, error, or return traps. If we're in the debugger, and the
+ `functrace' or `errtrace' options have been set, then let command
+ substitutions inherit them. Let command substitution inherit the
+ RETURN trap if we're in the debugger and tracing functions. */
+#if defined (DEBUGGER)
+ if (debugging_mode == 0 || function_trace_mode == 0)
+#endif
+ sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
+#if defined (DEBUGGER)
+ if (debugging_mode == 0 || error_trace_mode == 0)
+#endif
+ sigmodes[ERROR_TRAP] &= ~SIG_TRAPPED;
+#if defined (DEBUGGER)
+ if (debugging_mode == 0 || function_trace_mode == 0)
+#endif
+ sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
+}
+
+/* Reset trapped signals to their original values, but don't free the
+ trap strings. Called by the command substitution code. */
+void
+reset_signal_handlers ()
+{
+ reset_or_restore_signal_handlers (reset_signal);
+}
+
+/* Reset all trapped signals to their original values. Signals set to be
+ ignored with trap '' SIGNAL should be ignored, so we make sure that they
+ are. Called by child processes after they are forked. */
+void
+restore_original_signals ()
+{
+ reset_or_restore_signal_handlers (restore_signal);
+}
+
+/* If a trap handler exists for signal SIG, then call it; otherwise just
+ return failure. */
+int
+maybe_call_trap_handler (sig)
+ int sig;
+{
+ /* Call the trap handler for SIG if the signal is trapped and not ignored. */
+ if ((sigmodes[sig] & SIG_TRAPPED) && ((sigmodes[sig] & SIG_IGNORED) == 0))
+ {
+ switch (sig)
+ {
+ case SIGINT:
+ run_interrupt_trap ();
+ break;
+ case EXIT_TRAP:
+ run_exit_trap ();
+ break;
+ case DEBUG_TRAP:
+ run_debug_trap ();
+ break;
+ case ERROR_TRAP:
+ run_error_trap ();
+ break;
+ default:
+ trap_handler (sig);
+ break;
+ }
+ return (1);
+ }
+ else
+ return (0);
+}
+
+int
+signal_is_trapped (sig)
+ int sig;
+{
+ return (sigmodes[sig] & SIG_TRAPPED);
+}
+
+int
+signal_is_special (sig)
+ int sig;
+{
+ return (sigmodes[sig] & SIG_SPECIAL);
+}
+
+int
+signal_is_ignored (sig)
+ int sig;
+{
+ return (sigmodes[sig] & SIG_IGNORED);
+}
+
+void
+set_signal_ignored (sig)
+ int sig;
+{
+ sigmodes[sig] |= SIG_HARD_IGNORE;
+ original_signals[sig] = SIG_IGN;
+}
+
+int
+signal_in_progress (sig)
+ int sig;
+{
+ return (sigmodes[sig] & SIG_INPROGRESS);
+}
diff --git a/variables.c b/variables.c
index 7772012b..d54f10a2 100644
--- a/variables.c
+++ b/variables.c
@@ -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;
}
}
}
diff --git a/variables.c~ b/variables.c~
index 62e2604a..6c41e4cd 100644
--- a/variables.c~
+++ b/variables.c~
@@ -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;
}
}
}