summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES~5482
-rw-r--r--COMPAT~225
-rw-r--r--CWRU/CWRU.chlog~13650
-rw-r--r--CWRU/POSIX.NOTES.old82
-rw-r--r--CWRU/old/set.def.save544
-rw-r--r--CWRU/save/unwind_prot.h.save50
-rw-r--r--MANIFEST~989
-rw-r--r--Makefile.in.save1439
-rw-r--r--Makefile.in~1460
-rw-r--r--NOTES~333
-rw-r--r--aclocal.m4~3966
-rw-r--r--arrayfunc.c.save817
-rw-r--r--arrayfunc.c~844
-rw-r--r--arrayfunc.h.save55
-rw-r--r--arrayfunc.h~58
-rw-r--r--bashhist.c~820
-rw-r--r--bashline.c~3198
-rw-r--r--braces.c.orig561
-rw-r--r--braces.c~630
-rw-r--r--builtins/cd.def~525
-rw-r--r--builtins/declare.def~475
-rw-r--r--builtins/echo.def~185
-rw-r--r--builtins/evalfile.c~320
-rw-r--r--builtins/evalstring.c~352
-rw-r--r--builtins/fc.def~631
-rw-r--r--builtins/hash.def~271
-rw-r--r--builtins/mkbuiltins.c~1566
-rw-r--r--builtins/printf.def~1008
-rw-r--r--builtins/read.def~779
-rw-r--r--builtins/source.def~174
-rw-r--r--builtins/suspend.def~119
-rw-r--r--builtins/trap.def~265
-rw-r--r--builtins/ulimit.def~750
-rw-r--r--builtins/wait.def~177
-rw-r--r--command.h~345
-rw-r--r--config.h.in~1013
-rw-r--r--configure.in~1111
-rw-r--r--cross-build/cygwin32.cache.old42
-rw-r--r--dd~152
-rw-r--r--doc/FAQ.orig1745
-rw-r--r--doc/FAQ.save1745
-rw-r--r--doc/FAQ~1803
-rw-r--r--doc/bash.1.orig8583
-rw-r--r--doc/bash.1~8888
-rw-r--r--doc/bashref.texi.orig7105
-rw-r--r--doc/bashref.texi~7423
-rw-r--r--doc/version.texi~10
-rw-r--r--error.c~454
-rwxr-xr-xexamples/scripts/adventure.sh.save1549
-rw-r--r--execute_cmd.c~4127
-rw-r--r--expr.c~1348
-rw-r--r--externs.h~396
-rw-r--r--general.c~1030
-rw-r--r--include/memalloc.h.save58
-rw-r--r--input.c~625
-rw-r--r--jobs.c.diff521
-rw-r--r--jobs.c.save3952
-rw-r--r--jobs.c.save14053
-rw-r--r--jobs.c~4067
-rw-r--r--lib/glob/glob.c~891
-rw-r--r--lib/glob/xmbsrtowcs.c~250
-rw-r--r--lib/malloc/stats.c~202
-rw-r--r--lib/malloc/table.c~290
-rw-r--r--lib/readline/bind.c~2309
-rw-r--r--lib/readline/callback.c.save261
-rw-r--r--lib/readline/callback.c~260
-rw-r--r--lib/readline/complete.c.orig2216
-rw-r--r--lib/readline/complete.c~2216
-rw-r--r--lib/readline/display.c.save2396
-rw-r--r--lib/readline/display.c~2439
-rw-r--r--lib/readline/doc/Makefile.old76
-rw-r--r--lib/readline/doc/rltech.texi~2287
-rw-r--r--lib/readline/doc/version.texi~10
-rw-r--r--lib/readline/histexpand.c~1593
-rw-r--r--lib/readline/histfile.c~542
-rw-r--r--lib/readline/history.c~486
-rw-r--r--lib/readline/input.c~591
-rw-r--r--lib/readline/isearch.c.orig560
-rw-r--r--lib/readline/isearch.c~666
-rw-r--r--lib/readline/kill.c~693
-rw-r--r--lib/readline/misc.c~601
-rw-r--r--lib/readline/readline.c~1215
-rw-r--r--lib/readline/readline.h~849
-rw-r--r--lib/readline/rlprivate.h~429
-rw-r--r--lib/readline/rltty.c~1035
-rw-r--r--lib/readline/search.c~572
-rw-r--r--lib/readline/signals.c~470
-rw-r--r--lib/readline/terminal.c~701
-rw-r--r--lib/readline/text.c~1637
-rw-r--r--lib/readline/undo.c~292
-rw-r--r--lib/readline/vi_mode.c~1748
-rw-r--r--lib/sh/Makefile.in~470
-rw-r--r--lib/sh/eaccess.c~222
-rw-r--r--lib/sh/netopen.c~340
-rw-r--r--lib/sh/shaccess.c~219
-rw-r--r--lib/sh/shmatch.c~121
-rw-r--r--lib/sh/strtrans.c~284
-rw-r--r--lib/sh/tmpfile.c~214
-rw-r--r--lib/sh/winsize.c~82
-rw-r--r--lib/termcap/termcap.c~800
-rw-r--r--lib/termcap/tparam.c~334
-rw-r--r--locale.c~507
-rw-r--r--make_cmd.c~853
-rw-r--r--mksyntax.c~413
-rw-r--r--parse.y.diff251
-rw-r--r--parse.y.save14911
-rw-r--r--parse.y.save264927
-rw-r--r--parse.y~4951
-rw-r--r--print_cmd.c~1307
-rw-r--r--shell.c~1793
-rw-r--r--sig.c~570
-rw-r--r--subst.c.new8103
-rw-r--r--subst.c.save18064
-rw-r--r--subst.c~8138
-rw-r--r--subst.h~260
-rw-r--r--support/Makefile.in~87
-rw-r--r--support/mksignames.c.save446
-rw-r--r--support/mksignames.c~110
-rw-r--r--support/signames.c~393
-rw-r--r--syntax.h~102
-rw-r--r--terminal.c.diff41
-rw-r--r--test.c.orig924
-rw-r--r--test.c~834
-rw-r--r--test.h~40
-rwxr-xr-xtests/RUN-ONE-TEST~9
-rw-r--r--tests/array4.sub~30
-rw-r--r--tests/braces.tests~70
-rw-r--r--tests/cprint.right.save172
-rw-r--r--tests/func.right~150
-rw-r--r--tests/func.tests~176
-rw-r--r--tests/history.tests.save97
-rw-r--r--tests/misc/regress/log.orig50
-rw-r--r--tests/misc/regress/shx.orig10
-rw-r--r--tests/new-exp.tests.save1558
-rw-r--r--tests/new-exp.tests~558
-rw-r--r--tests/quote.tests~101
-rw-r--r--tests/tilde.right~24
-rw-r--r--tests/tilde.tests~66
-rw-r--r--trap.c~984
-rw-r--r--unwind_prot.c~320
-rw-r--r--variables.c~4267
141 files changed, 0 insertions, 193381 deletions
diff --git a/CHANGES~ b/CHANGES~
deleted file mode 100644
index b168b407..00000000
--- a/CHANGES~
+++ /dev/null
@@ -1,5482 +0,0 @@
-This document details the changes between this version, bash-3.2-alpha,
-and the previous version, bash-3.1-release.
-
-1. Changes to Bash
-
-a. Fixed a source bug that caused the minimal configuration to not compile.
-
-b. Fixed memory leaks in error handling for the `read' builtin.
-
-c. Changed the [[ and (( compound commands to set PIPESTATUS with their exit
- status.
-
-d. Fixed some parsing problems with compound array assignments.
-
-e. Added additional configuration changes for: NetBSD (incomplete multibyte
- character support)
-
-f. Fixed two bugs with local array variable creation when shadowing a variable
- of the same name from a previous context.
-
-g. Fixed the `read' builtin to restore the correct set of completion functions
- if a timeout occurs.
-
-h. Added code to defer the initialization of HISTSIZE (and its stifling of the
- history list) until the history file is loaded, allowing a startup file to
- override the default value.
-
-i. Tightened up the arithmetic expression parsing to produce better error
- messages when presented with invalid operators.
-
-j. Fixed the cross-compilation support to build the signal list at shell
- invocation rather than compile time if cross-compiling.
-
-k. Fixed multibyte support for non-gcc compilers (or compilers that do not
- allow automatic array variable sizing based on a non-constant value).
-
-l. Several fixes to the code that manages the list of terminated jobs and
- their exit statuses, and the list of active and recently-terminated jobs
- to avoid pid aliasing/wraparound and allocation errors.
-
-m. Fixed a problem that allowed scripts to die due to SIGINT while waiting
- for children, even when started in the background or otherwise ignoring
- SIGINT.
-
-n. Fixed a bug that caused shells invoked as -/bin/bash from not being
- recognized as login shells.
-
-o. Fixed a problem that caused shells in the background to give the terminal
- to a process group other than the foreground shell process group.
-
-p. Fixed a problem with extracting the `varname' in ${#varname}.
-
-q. Fixed the code that handles SIGQUIT to not exit immediately -- thereby
- calling functions that may not be called in a signal handler context --
- but set a flag and exit afterward (like SIGINT).
-
-r. Changed the brace expansion code to skip over braces that don't begin a
- valid matched brace expansion construct.
-
-s. Fixed `typeset' and `declare' to not require that their shell function
- operands to be valid shell identifiers.
-
-t. Changed `test' to use access(2) with a temporary uid/euid swap when testing
- file attributes and running setuid, and access(2) in most other cases.
-
-u. Changed completion code to not attempt command name completion on a line
- consisting solely of whitespace when no_empty_command_completion is set.
-
-v. The `hash' builtin now prints nothing in posix mode when the hash table is
- empty, and prints a message to that effect to stdout instead of stderr
- when not in posix mode.
-
-w. Fixed a bug in the extended pattern matching code that caused it to fail to
- match periods with certain patterns.
-
-x. Fixed a bug that caused the shell to dump core when performing filename
- generation in directories with thousands of files.
-
-y. Returned to the original Bourne shell rules for parsing ``: no recursive
- parsing of embedded quoted strings or ${...} constructs.
-
-z. The inheritence of the DEBUG, RETURN, and ERR traps is now dependent only
- on the settings of the `functrace' and `errtrace' shell options, rather
- than whether or not the shell is in debugging mode.
-
-aa. Fixed a problem with $HOME being converted to ~ in the expansion of
- members of the DIRSTACK array.
-
-bb. Fixed a problem with quoted arguments to arithmetic expansions in certain
- constructs.
-
-cc. The command word completion code now no longer returns matching directories
- while searching $PATH.
-
-dd. Fixed a bug with zero-padding and precision handling in snprintf()
- replacement.
-
-ee. Fixed a bug that caused the command substitution code not to take embedded
- shell comments into account.
-
-ff. Fixed a bug that caused $((...);(...)) to be misinterpreted as an
- arithmetic substitution.
-
-gg. Fixed a bug in the prompt expansion code that inappropriately added a
- \001 before a \002 under certain circumstances.
-
-hh. Fixed a bug that caused `unset LANG' to not properly reset the locale
- (previous versions would set the locale back to what it was when bash
- was started rather than the system's "native" locale).
-
-ii. Fixed a bug that could cause file descriptors > 10 to not be closed even
- when closed explicitly by a script.
-
-jj. Fixed a bug that caused single quotes to be stripped from ANSI-C quoting
- inside double-quoted command substitutions.
-
-2. Changes to Readline
-
-a. Fixed a problem that caused segmentation faults when using readline in
- callback mode and typing consecutive DEL characters on an empty line.
-
-b. Fixed several redisplay problems with multibyte characters, all having to
- do with the different code paths and variable meanings between single-byte
- and multibyte character redisplay.
-
-c. Fixed a problem with key sequence translation when presented with the
- sequence \M-\C-x.
-
-d. Fixed a problem that prevented the `a' command in vi mode from being
- undone and redone properly.
-
-e. Fixed a problem that prevented empty inserts in vi mode from being undone
- properly.
-
-f. Fixed a problem that caused readline to initialize with an incorrect idea
- of whether or not the terminal can autowrap.
-
-g. Fixed output of key bindings (like bash `bind -p') to honor the setting of
- convert-meta and use \e where appropriate.
-
-h. Changed the default filename completion function to call the filename
- dequoting function if the directory completion hook isn't set. This means
- that any directory completion hooks need to dequote the directory name,
- since application-specific hooks need to know how the word was quoted,
- even if no other changes are made.
-
-i. Fixed a bug with creating the prompt for a non-interactive search string
- when there are non-printing characters in the primary prompt.
-
-j. Fixed a bug that caused prompts with invisible characters to be redrawn
- multiple times in a multibyte locale.
-
-k. Fixed a bug that could cause the key sequence scanning code to return the
- wrong function.
-
-l. Fixed a problem with the callback interface that caused it to fail when
- using multi-character keyboard macros.
-
-m. Fixed a bug that could cause a core dump when an edited history entry was
- re-executed under certain conditions.
-
-n. Fixed a bug that caused readline to reference freed memory when attmpting
- to display a portion of the prompt.
-
-3. New Features in Bash
-
-a. Changed the parameter pattern replacement functions to not anchor the
- pattern at the beginning of the string if doing global replacement - that
- combination doesn't make any sense.
-
-b. When running in `word expansion only' mode (--wordexp option), inhibit
- process substitution.
-
-c. Loadable builtins now work on MacOS X 10.[34].
-
-d. Shells running in posix mode no longer set $HOME, as POSIX requires.
-
-e. The code that checks for binary files being executed as shell scripts now
- checks only for NUL rather than any non-printing character.
-
-f. Quoting the string argument to the [[ command's =~ operator now forces
- string matching, as with the other pattern-matching operators.
-
-4. New Features in Readline
-
-a. Calling applications can now set the keyboard timeout to 0, allowing
- poll-like behavior.
-
-b. The value of SYS_INPUTRC (configurable at compilation time) is now used as
- the default last-ditch startup file.
-
-c. The history file reading functions now allow windows-like \r\n line
- terminators.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.1-release,
-and the previous version, bash-3.1-rc2.
-
-1. Changes to Readline
-
-a. Several changes to the multibyte redisplay code to fix problems with
- prompts containing invisible characters.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.1-rc2,
-and the previous version, bash-3.1-rc1.
-
-1. Changes to Bash
-
-a. Fixed a bug that caused a DEBUG trap to overwrite a command string that's
- eventually attached to a background job.
-
-b. Changed some code so that filenames with leading tildes with spaces in the
- name aren't tilde-expanded by the bash completion code.
-
-c. Fixed a bug that caused the pushd builtin to fail to change to
- directories with leading `-'.
-
-d. Fixed a small memory leak in the programmable completion code.
-
-2. Changes to Readline
-
-a. Fixed a redisplay bug caused by moving the cursor vertically to a line
- with invisible characters in the prompt in a multibyte locale.
-
-b. Fixed a bug that could cause the terminal special chars to be bound in the
- wrong keymap in vi mode.
-
-3. New Features in Bash
-
-a. If compiled for strict POSIX conformance, LINES and COLUMNS may now
- override the true terminal size.
-
-4. New Features in Readline
-
-a. A new external application-controllable variable that allows the LINES
- and COLUMNS environment variables to set the window size regardless of
- what the kernel returns.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.1-rc1,
-and the previous version, bash-3.1-beta1.
-
-1. Changes to Bash
-
-a. Fixed a bug that could cause core dumps due to accessing the current
- pipeline while in the middle of modifying it.
-
-b. Fixed a bug that caused pathnames with backslashes still quoting characters
- to be passed to opendir().
-
-c. Command word completion now obeys the setting of completion-ignore-case.
-
-d. Fixed a problem with redirection that caused file descriptors greater than
- 2 to be inappropriately marked as close-on-exec.
-
-e. In Posix mode, after `wait' is called to wait for a particular process
- explicitly, that process is removed from the list of processes known to
- the shell, and subsequent attempts to wait for it return errors.
-
-f. Fixed a bug that caused extended pattern matching to incorrectly scan
- backslash-escaped pattern characters.
-
-g. Fixed a synchronization problem that could cause core dumps when handling
- a SIGWINCH.
-
-h. Fixed a bug that caused an unmatched backquote to be accepted without an
- error when processing here documents.
-
-i. Fixed a small memory leak in the `cd' builtin.
-
-j. Fix for MacOS X so it gets the values for the HOSTTYPE, MACHTYPE, and
- OSTYPE variables at build time, to support universal binaries.
-
-k. Fixed a bug that could cause an exit trap to return the exit status of
- the trap command rather than the status as it was before the trap was
- run as the shell's exit status.
-
-2. New Features in Bash
-
-3. Changes to Readline
-
-a. Fixed a bug that caused reversing the incremental search direction to
- not work correctly.
-
-b. Fixed the vi-mode `U' command to only undo up to the first time insert mode
- was entered, as Posix specifies.
-
-c. Fixed a bug in the vi-mode `r' command that left the cursor in the wrong
- place.
-
-4. New Features in Readline
-
-a. New application-callable auxiliary function, rl_variable_value, returns
- a string corresponding to a readline variable's value.
-
-b. When parsing inputrc files and variable binding commands, the parser
- strips trailing whitespace from values assigned to boolean variables
- before checking them.
-
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.1-beta1,
-and the previous version, bash-3.1-alpha1.
-
-1. Changes to Bash
-
-a. Added some system-specific signal names.
-
-b. Fixed a typo in the ulimit builtin to make `x' the right option to
- maniuplate the limit on file locks.
-
-c. Fixed a problem with using += to append to index 0 of an array variable
- when not using subscript syntax.
-
-d. A few changes to configure.in to remove calls to obsolete or outdated
- macros.
-
-e. Make sure changes to variables bash handles specially (e.g., LC_ALL) are
- made when the variable is set in the temporary environment to a command.
-
-f. Make sure changes to variables bash handles specially (e.g., LC_ALL) are
- made when the variable is modified using `printf -v'.
-
-g. The export environment is now remade on cygwin when HOME is changed, so
- DLLs bash is linked against pick up the new value. This fixes problems
- with tilde expansion when linking against and already-installed readline.
-
-h. Small fix to the logic for performing tilde expansion in posix mode, so
- expansion on the right-hand side of an assignment statement takes place.
-
-i. Fixed a bug that prevented redirections associated with a shell function
- from being executed when in a subshell.
-
-j. Fixed `source' and `.' builtins to not require an executable file when
- searching $PATH for a file to source.
-
-k. Fixed a bug that caused incorrect word splitting in a function when IFS
- was declared local, then unset.
-
-l. Fixed a problem with the `kill' builtin that prevented sending signals
- to a process group under certain circumstances when providing a pid < 0.
-
-m. When in POSIX mode, `pwd' now checks that the value it prints is the same
- directory as `.', even when displaying $PWD.
-
-n. Fixed a problem with the `read' builtin when reading a script from standard
- input and reading data from the same file.
-
-o. Fixed a problem with the `type' and `command' builtins that caused absolute
- pathnames to be displayed incorrectly.
-
-p. Some changes to the `bg' builtin for POSIX conformance.
-
-q. The `fc' builtin now removes the `fc' command that caused it to invoke an
- editor on specified history entries from the history entirely, rather than
- simply ignoring it.
-
-r. When in POSIX mode, the `v' command in vi editing mode simply invokes vi
- on the current command, rather than checking $FCEDIT and $EDITOR.
-
-s. Fixed a small memory leak in the pathname canonicalization code.
-
-t. Fixed a bug that caused the expanded value of a $'...' string to be
- incorrectly re-quoted if it occurred within a double-quoted ${...}
- parameter expansion.
-
-u. Restored default emacs-mode key binding of M-TAB to dynamic-complete-history.
-
-v. Fixed a bug that caused core dumps when interrupting loops running builtins
- on some systems.
-
-w. Make sure that some of the functions bash provides replacements for are
- not cpp defines.
-
-x. The code that scans embedded commands for the parser (`...` and $(...)) is
- now more aware of embedded comments and their effect on quoted strings.
-
-y. Changed the `-n' option to the `history' builtin to not reset the number of
- history lines read in the current session after reading the new lines from
- the history file if the history is being appended when it is written to
- the file, since the appending takes care of the problem that the adjustment
- was intended to solve.
-
-z. Improved the error message displayed when a shell script fails to execute
- because the environment and size of command line arguments are too large.
-
-aa. A small fix to make sure that $HISTCMD is evaluated whenever the shell is
- saving commands to the history list, not just when HISTSIZE is defined.
-
-2. Changes to Readline
-
-a. The `change-case' command now correctly changes the case of multibyte
- characters.
-
-b. Changes to the shared library construction scripts to deal with Windows
- DLL naming conventions for Cygwin.
-
-c. Fixed the redisplay code to avoid core dumps resulting from a poorly-timed
- SIGWINCH.
-
-d. Fixed the non-incremental search code in vi mode to dispose of any current
- undo list when copying a line from the history into the current editing
- buffer.
-
-e. The variable assignment code now ignores whitespace at the end of lines
- when assigning to boolean variables.
-
-f. The `C-w' binding in incremental search now understands multibyte
- characters.
-
-3. New Features in Bash
-
-a. A new configuration option, `--enable-strict-posix-default', which will
- build bash to be POSIX conforming by default.
-
-4. New Features in Readline
-
-a. If the rl_completion_query_items is set to a value < 0, readline never
- asks the user whether or not to view the possible completions.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.1-alpha1,
-and the previous version, bash-3.0-release.
-
-1. Changes to Bash
-
-a. Fixed a bug that caused bash to crash if referencing an unset local array.
-
-b. Fixed a problem that caused tilde expansion to not be performed before
- attempting globbing word completion.
-
-c. Fixed an incompatibility so that a first argument to trap that's a valid
- signal number will be trated as a signal rather than a command to execute.
-
-d. Fixed ${#word} expansion to correctly compute the length of a string
- containing multibyte characters.
-
-e. Fixed a bug that caused bash to not pass the correct flags for signal
- disposition to child processes.
-
-f. Fixed a bug that caused `fc -l' to list one too many history entries.
-
-g. Some fixes to `fc' for POSIX conformance.
-
-h. Some fixes to job status display for POSIX conformance.
-
-i. Fixed a bug that caused `command -v' to display output if a command was not
- found -- it should be silent.
-
-j. In POSIX mode, `type' and `command -[vV]' do not report non-executable
- files, even if the shell will attempt to execute them.
-
-k. Fixed a bug that caused the `==' operator to the [[ command to not attempt
- extended pattern matching.
-
-l. Fixed the brace expansion code to handle characters whose value exceeds 128.
-
-m. Fixed `printf' to handle strings with a leading `\0' whose length is
- non-zero.
-
-n. Fixed a couple of problems with brace expansion where `${' was handled
- incorrectly.
-
-o. Fixed off-by-one error when calculating the upper bound of `offset' when
- processing the ${array[@]:offset:length} expansion.
-
-p. System-specific configuration changes for: FreeBSD 5.x, Interix, MacOS X
- 10.4, Linux 2.4+ kernels, Linux 3.x kernels, Dragonfly BSD, QNX 6.x,
- Cygwin
-
-q. Fixed a bug that caused the shell to ignore the status of the rightmost
- command in a pipeline when the `pipefail' option was enabled.
-
-r. Fixed a completion bug that caused core dumps when expanding a directory
- name.
-
-s. Fixed a bug that prevented `hash -d' from removing commands from the hash
- table.
-
-t. Fixed word splitting to avoid really bad quadratic performance when
- expanding long lists.
-
-u. Fixed a bug that caused negative offsets in substring expansion to use the
- wrong values.
-
-v. Fixed a bug in printf that caused it to not return failure on write errors.
-
-w. Fixed a bug that caused commands in subshells to not be properly timed.
-
-x. The shell parser no longer attempts to parse a compound assignment specially
- unless in a position where an assignment statement is acceptable or parsing
- arguments to a builtin that accepts assignment statements.
-
-y. Fixed a problem that caused a `case' statement to be added to the history
- incorrectly as a single command if the `case word' was on one line and the
- `in' on another.
-
-z. Fixed a problem that caused internal shell quoting characters to be
- incorrectly quoted with backslashes under some circumstances.
-
-aa. The shell now performs correct word splitting when IFS contains multibyte
- characters.
-
-bb. The mail checking code now resets the cached file information if the size
- drops to 0, even if the times don't change.
-
-cc. A completed command name that is found in $PATH as well as the name of a
- directory in the current directory no longer has a slash appended in certain
- circumstances: a single instance found in $PATH when `.' is not in $PATH,
- and multiple instances found in $PATH, even when `.' is in $PATH.
-
-dd. Incorporated tilde expansion into the word expansion code rather than as a
- separately-called function, fixing some cases where it was performed
- inappropriately (e.g., after the second `=' in an assignment statement or
- in a double-quoted parameter expansion).
-
-ee. Fixed several bugs encountered when parsing compound assignment statements,
- so that compound assignments appearing as arguments to builtins are no
- longer double-expanded.
-
-ff. Fixed a bug in the command execution code that caused asynchronous commands
- containing command substitutions to not put the terminal in the wrong
- process group.
-
-gg. Bash now handles the case where the WCONTINUED flag causes waitpid() to
- return -1/EINVAL at runtime as well as configuration time.
-
-hh. Fixed parser to generate an error when the pipeline `argument' to `!' or
- `time' is NULL.
-
-ii. The shell now takes a little more care when manipulating file descriptors
- greater than 9 with the `exec' builtin.
-
-jj. Fixed a bug that caused variable assignments preceding the `command' builtin
- preceding a special builtin to be preserved after the command completed in
- POSIX mode.
-
-kk. Fixed a bug that allowed variables beginning with a digit to be created.
-
-ll. Fixed a bug that caused a \<newline> to be removed when parsing a $'...'
- construct.
-
-mm. A shell whose name begins with `-' will now be a restricted shell if the
- remainder of the name indicates it should be restricted.
-
-nn. Fixed a bug that could cause a core dump if FUNCNAME were changed or unset
- during a function's execution.
-
-oo. Fixed a bug that caused executing a `return' in a function to not execute
- a RETURN trap. The RETURN trap is inherited by shell functions only if
- function tracing is globally enabled or has been enabled for that function.
-
-pp. Fixed cases where var[@] was not handled exactly like var, when var is a
- scalar variable.
-
-qq. Fixed a bug that caused the first character after a SIGINT to be discarded
- under certain circumstances.
-
-rr. Fixed exit status code so that a suspended job returns 128+signal as its
- exit status (preventing commands after it in `&&' lists from being
- executed).
-
-ss. Fixed a bug that caused the shell parser state to be changed by executing
- a shell function as a result of word completion.
-
-tt. Fixed a long-standing bug that caused '\177' characters in variable
- values to be discarded when expanded in double-quoted strings.
-
-uu. Fixed a bug that caused $RANDOM to be re-seeded multiple times in a
- subshell environment.
-
-vv. Extensive changes to the job management code to avoid the pid-reuse and
- pid-aliasing problems caused by retaining the exit status of too many jobs,
- but still retain as many background job statuses as POSIX requires.
-
-ww. Fixed a parser bug in processing \<newline> that caused things like
-
- ((echo 5) \
- (echo 6))
-
- to not work correctly.
-
-xx. `pwd -P' now sets $PWD to a directory name containing no symbolic links
- when in posix mode, as POSIX requires.
-
-yy. In posix mode, bash no longer sets $PWD to a name containing no symbolic
- links if a directory is chosen from $CDPATH.
-
-zz. The word splitting code now treats an IFS character that is not space,
- tab, or newline and any adjacent IFS white space as a single delimiter, as
- SUSv3/XPG6 require.
-
-aaa. The `read' builtin now checks whether or not the number of fields read is
- exactly the same as the number of variables instead of just assigning the
- rest of the line (minus any trailing IFS white space) to the last
- variable. This is what POSIX/SUS/XPG all require.
-
-bbb. Fixed a bug that caused `read' to always check whether or not fd 0 was a
- pipe, even when reading from another file descriptor.
-
-ccc. Fixed a bug that caused short-circuiting of execution even if the return
- value was being inverted.
-
-ddd. Fixed a bug that caused a core dump while decoding \W escapes in PS1 if
- PWD was unset.
-
-eee. Fixed a bug in `read' that counted internal quoting characters for the
- purposes of `read -n'.
-
-fff. Fixed a bug so that a function definition in a pipeline causes a child
- process to be forked at the right time.
-
-ggg. Bash will not attempt to link against a readline library that doesn't
- have rl_gnu_readline_p == 1.
-
-hhh. Fixed a bug that caused `read' to consume one too many characters when
- reading a fixed number of characters and the Nth character is a backslash.
-
-iii. Fixed a bug that caused `unset' on variables in the temporary environment
- to leave them set when `unset' completed.
-
-jjj. Fixed a bug that caused bash to close fd 2 if an `exec' failed and the
- shell didn't exit.
-
-kkk. The completion code is more careful to not turn `/' or `///' into `//',
- for those systems on which `//' has special meaning.
-
-lll. Fixed a bug that caused command substitution in asynchronous commands to
- close the wrong file descriptors.
-
-mmm. The shell no longer prints status messages about terminated background
- processes unless job control is active.
-
-nnn. Fixed a bug that prevented multiple consecutive invocations of `history -s'
- from adding all the commands to the history list.
-
-ooo. Added a couple of changes to make arithmetic expansion more consistent in
- all its contexts (still not perfect).
-
-ppp. Fixed a bug that caused the parser to occasionally not find the right
- terminating "`" in an old-style command substitution.
-
-qqq. Fixed a bug that caused core dumps when the shell was reading its non-
- interactive input from fd 0 and fd 0 was duplicated and restored using a
- combination of `exec' (to save) and redirection (to restore).
-
-rrr. Fixed a problem that caused loops in sourced scripts to not be cleaned
- up properly when a `return' is executed.
-
-sss. Change internal command substitution completion function to append a slash
- to directory names in the command.
-
-2. Changes to Readline
-
-a. Fixed a bug that caused multiliine prompts to be wrapped and displayed
- incorrectly.
-
-b. Fixed a bug that caused ^P/^N in emacs mode to fail to display the current
- line correctly.
-
-c. Fixed a problem in computing the number of invisible characters on the first
- line of a prompt whose length exceeds the screen width.
-
-d. Fixed vi-mode searching so that failure preserves the current line rather
- than the last line in the history list.
-
-e. Fixed the vi-mode `~' command (change-case) to have the correct behavior at
- end-of-line when manipulating multibyte characters.
-
-f. Fixed the vi-mode `r' command (change-char) to have the correct behavior at
- end-of-line when manipulating multibyte characters.
-
-g. Fixed multiple bugs in the redisplay of multibyte characters: displaying
- prompts longer than the screen width containing multibyte characters,
-
-h. Fix the calculation of the number of physical characters in the prompt
- string when it contains multibyte characters.
-
-i. A non-zero value for the `rl_complete_suppress_append' variable now causes
- no `/' to be appended to a directory name.
-
-j. Fixed forward-word and backward-word to work when words contained
- multibyte characters.
-
-k. Fixed a bug in finding the delimiter of a `?' substring when performing
- history expansion in a locale that supports multibyte characters.
-
-l. Fixed a memory leak caused by not freeing the timestamp in a history entry.
-
-m. Fixed a bug that caused "\M-x" style key bindings to not obey the setting
- of the `convert-meta' variable.
-
-n. Fixed saving and restoring primary prompt when prompting for incremental
- and non-incremental searches; search prompts now display multibyte
- characters correctly.
-
-o. Fixed a bug that caused keys originally bound to self-insert but shadowed
- by a multi-character key sequence to not be inserted.
-
-p. Fixed code so rl_prep_term_function and rl_deprep_term_function aren't
- dereferenced if NULL (matching the documentation).
-
-q. Extensive changes to readline to add enough state so that commands
- requiring additional characters (searches, multi-key sequences, numeric
- arguments, commands requiring an additional specifier character like
- vi-mode change-char, etc.) work without synchronously waiting for
- additional input.
-
-r. Lots of changes so readline builds and runs on MinGW.
-
-s. Readline no longer tries to modify the terminal settings when running in
- callback mode.
-
-t. The Readline display code no longer sets the location of the last invisible
- character in the prompt if the \[\] sequence is empty.
-
-3. New Features in Bash
-
-a. Bash now understands LC_TIME as a special variable so that time display
- tracks the current locale.
-
-b. BASH_ARGC, BASH_ARGV, BASH_SOURCE, and BASH_LINENO are no longer created
- as `invisible' variables and may not be unset.
-
-c. In POSIX mode, if `xpg_echo' option is enabled, the `echo' builtin doesn't
- try to interpret any options at all, as POSIX requires.
-
-d. The `bg' builtin now accepts multiple arguments, as POSIX seems to specify.
-
-e. Fixed vi-mode word completion and glob expansion to perform tilde
- expansion.
-
-f. The `**' mathematic exponentiation operator is now right-associative.
-
-g. The `ulimit' builtin has new options: -i (max number of pending signals),
- -q (max size of POSIX message queues), and -x (max number of file locks).
-
-h. A bare `%' once again expands to the current job when used as a job
- specifier.
-
-i. The `+=' assignment operator (append to the value of a string or array) is
- now supported for assignment statements and arguments to builtin commands
- that accept assignment statements.
-
-j. BASH_COMMAND now preserves its value when a DEBUG trap is executed.
-
-k. The `gnu_errfmt' option is enabled automatically if the shell is running
- in an emacs terminal window.
-
-l. New configuration option: --single-help-strings. Causes long help text
- to be written as a single string; intended to ease translation.
-
-m. The COMP_WORDBREAKS variable now causes the list of word break characters
- to be emptied when the variable is unset.
-
-n. An unquoted expansion of $* when $IFS is empty now causes the positional
- parameters to be concatenated if the expansion doesn't undergo word
- splitting.
-
-o. Bash now inherits $_ from the environment if it appears there at startup.
-
-p. New shell option: nocasematch. If non-zero, shell pattern matching ignores
- case when used by `case' and `[[' commands.
-
-q. The `printf' builtin takes a new option: -v var. That causes the output
- to be placed into var instead of on stdout.
-
-r. By default, the shell no longer reports processes dying from SIGPIPE.
-
-s. Bash now sets the extern variable `environ' to the export environment it
- creates, so C library functions that call getenv() (and can't use the
- shell-provided replacement) get current values of environment variables.
-
-4. New Features in Readline
-
-a. The key sequence sent by the keypad `delete' key is now automatically
- bound to delete-char.
-
-b. A negative argument to menu-complete now cycles backward through the
- completion list.
-
-c. A new bindable readline variable: bind-tty-special-chars. If non-zero,
- readline will bind the terminal special characters to their readline
- equivalents when it's called (on by default).
-
-d. New bindable command: vi-rubout. Saves deleted text for possible
- reinsertion, as with any vi-mode `text modification' command; `X' is bound
- to this in vi command mode.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.0-release,
-and the previous version, bash-3.0-rc1.
-
-1. Changes to Bash
-
-a. Fixed a boundary overrun that could cause segmentation faults when the
- completion code hands an incomplete construct to the word expansion
- functions.
-
-b. Changed posix mode behavior so that an error in a variable assignment
- preceding a special builtin causes a non-interactive shell to exit.
-
-c. Change the directory expansion portion of the completion code to not
- expand embedded command substitutions if the directory name appears in
- the file system.
-
-d. Fixed a problem that caused `bash -r' to turn on restrictions before
- reading the startup files.
-
-e. Fixed a problem with the default operation of the `umask' builtin.
-
-2. Changes to Readline
-
-a. Fixed a problem with readline saving the contents of the current line
- before beginning a non-interactive search.
-
-b. Fixed a problem with EOF detection when using rl_event_hook.
-
-c. Fixed a problem with the vi mode `p' and `P' commands ignoring numeric
- arguments.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.0-rc1,
-and the previous version, bash-3.0-beta1.
-
-1. Changes to Bash
-
-a. Fixed a bug that caused incorrect behavior when referecing element 0 of
- an array using $array, element 0 was unset, and `set -u' was enabled.
-
-b. System-specific changes for: SCO Unix 3.2, Tandem.
-
-c. Fixed a bug that caused inappropriate word splitting when a variable was
- expanded within a double-quoted string that also included $@.
-
-d. Fixed a bug that caused `pwd' to not display anything in physical mode
- when the file system had changed underneath the shell.
-
-e. Fixed a bug in the pre- and post- increment and decrement parsing in the
- expression evaluator that caused errors when the operands and corresponding
- operators were separated by whitespace.
-
-f. Fixed a bug that caused `history -p' to add an entry to the history list,
- counter to the documentation. (Keeps the history expansions invoked by
- emacs-mode command line editing from doing that as well.)
-
-g. Fixed a bug that could cause a core dump if `cd' is asked to print out a
- pathname longer than PATH_MAX characters.
-
-h. Fixed a bug that caused jobs to be put into the wrong process group under
- some circumstances after enabling job control with `set -m'.
-
-i. `unalias' now returns failure if no alias name arguments are supplied.
-
-j. Documented the characters not allowed to appear in an alias name.
-
-k. $* is no longer expanded as if in double quotes when it appears in the
- body of a here document, as the SUS seems to require.
-
-l. The `bashbug' script now uses a directory in $TMPDIR for exclusive
- access rather than trying to guess how the underlying OS provides for
- secure temporary file creation.
-
-m. Fixed a few problems with `cd' and `pwd' when asked to operate on pathnames
- longer than PATH_MAX characters.
-
-n. Fixed a memory leak caused when creating multiple local array variables
- with identical names.
-
-o. Fixed a problem with calls to getcwd() so that bash now operates better
- when the full pathname to the current directory is longer than PATH_MAX
- bytes.
-
-p. The `trap' builtin now reports an error if a single non-signal argument
- is specified.
-
-q. Fixed a bug that caused `umask' to not work correctly when presented
- with a mask of all 0s.
-
-r. When `getopts' reaches the end of options, OPTARG is unset, as POSIX
- appears to specify.
-
-s. Interactive mode now depends on whether or not stdin and stderr are
- connected to a tty; formerly it was stdin and stdout. POSIX requires
- this.
-
-t. Fixed vi-mode completion to work more as POSIX specifies (e.g., doing the
- right kind of filename generation).
-
-2. Changes to Readline
-
-a. Fixed a problem that could cause readline to refer to freed memory when
- moving between history lines while doing searches.
-
-b. Improvements to the code that expands and displays prompt strings
- containing multibyte characters.
-
-c. Fixed a problem with vi-mode not correctly remembering the numeric argument
- to the last `c'hange command for later use with `.'.
-
-d. Fixed a bug in vi-mode that caused multi-digit count arguments to work
- incorrectly.
-
-e. Fixed a problem in vi-mode that caused the last text modification command
- to not be remembered across different command lines.
-
-f. Fixed problems with changing characters and changing case at the end of
- the line.
-
-3. New Features in Bash
-
-a. The `jobs', `kill', and `wait' builtins now accept job control notation
- even if job control is not enabled.
-
-b. The historical behavior of `trap' that allows a missing `action' argument
- to cause each specified signal's handling to be reset to its default is
- now only supported when `trap' is given a single non-option argument.
-
-4. New Features in Readline
-
-a. When listing completions, directories have a `/' appended if the
- `mark-directories' option has been enabled.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.0-beta1,
-and the previous version, bash-3.0-alpha.
-
-1. Changes to Bash
-
-a. Fixes to build correctly when arrays are not compiled into the shell.
-
-b. Fixed command substitution to run any exit trap defined in the command
- substitution before returning; the exit trap is not inherited from the
- calling shell.
-
-c. Fixes to process group synchronization code so that every child process
- attempts to set the terminal's process group; fixes some synchronization
- problems on Linux kernels that schedule the child to always run before
- the parent.
-
-d. Fixed processing of octal and hex constants in printf builtin for POSIX.2
- compliance.
-
-e. Fixed a couple of core dumps in the pattern removal code.
-
-f. Fixes to the array subrange extraction code to deal better with sparse
- arrays.
-
-g. Parser errors and other errors that result in the shell exiting now cause
- the exit trap to be run.
-
-h. Change the command substitution completion functions to not append any
- closing quote, because it would be inserted a closing "`" or ")".
-
-i. Fix history initialization so assignments to $histchars made in startup
- files are honored.
-
-j. If an exit trap does not contain a call to `exit', the shell now uses
- the exit status of the last command executed before the trap as the exit
- status of the shell.
-
-k. The parser now prompts with $PS2 if it reads a newline while parsing a
- compound array assignment statement.
-
-l. When performing a compound array assignment, the parser doesn't treat
- words of the form [index]=value as assignments if they're the result of
- expansions.
-
-m. Fixed a bug that caused `return' executed in a trap command to make the
- shell think it was still running the trap.
-
-n. Fixed the value of errno set by the pathname canonicalization functions.
-
-o. Changed the grammar so that `time' alone on a line times a null command
- rather than being a syntax error.
-
-p. The pattern substitution code no longer performs quote removal on the
- pattern before trying to match it, as the pattern removal functions do.
-
-q. Fixed a bug that could cause core dumps when checking whether a quoted
- command name was being completed.
-
-r. Fixes to the pattern removal and pattern replacement expansions to deal
- with multibyte characters better (and faster).
-
-s. Fix to the substring expansion (${param:off[:len]}) to deal with (possibly
- multibyte) characters instead of raw bytes.
-
-t. Fixed a bug that caused some key bindings set in an inputrc to be ignored
- at shell startup.
-
-u. Fixed a bug that caused unsetting a local variable within a function to
- not work correctly.
-
-v. Fixed a bug that caused invalid variables to be created when using
- `read -a'.
-
-w. Fixed a bug that caused "$@" to expand incorrectly when used as the right
- hand side of a parameter expansion such as ${word:="$@"} if the first
- character of $IFS was not a space.
-
-x. Fixed a slight cosmetic problem when printing commands containing a
- `>&word' redirection.
-
-y. Fixed a problem that could cause here documents to not be created correctly
- if the system temporary directory did not allow writing.
-
-2. Changes to Readline
-
-a. Change to history expansion functions to treat `^' as equivalent to word
- one, as the documention states.
-
-b. Some changes to the display code to improve display and redisplay of
- multibyte characters.
-
-c. Changes to speed up the multibyte character redisplay code.
-
-d. Fixed a bug in the vi-mode `E' command that caused it to skip over the
- last character of a word if invoked while point was on the word's
- next-to-last character.
-
-e. Fixed a bug that could cause incorrect filename quoting when
- case-insensitive completion was enabled and the word being completed
- contained backslashes quoting word break characters.
-
-f. Fixed a bug in redisplay triggered when the prompt string contains
- invisible characters.
-
-g. Fixed some display (and other) bugs encountered in multibyte locales
- when a non-ascii character was the last character on a line.
-
-h. Fixed some display bugs caused by multibyte characters in prompt strings.
-
-i. Fixed a problem with history expansion caused by non-whitespace characters
- used as history word delimiters.
-
-3. New Features in Bash
-
-a. printf builtin understands two new escape sequences: \" and \?.
-
-b. `echo -e' understands two new escape sequences: \" and \?.
-
-c. The GNU `gettext' package and libintl have been integrated; the shell's
- messages can be translated into different languages.
-
-d. The `\W' prompt expansion now abbreviates $HOME as `~', like `\w'.
-
-e. The error message printed when bash cannot open a shell script supplied
- as argument 1 now includes the name of the shell, to better identify
- the error as coming from bash.
-
-4. New Features in Readline
-
-a. New application variable, rl_completion_quote_character, set to any
- quote character readline finds before it calls the application completion
- function.
-
-b. New application variable, rl_completion_suppress_quote, settable by an
- application completion function. If set to non-zero, readline does not
- attempt to append a closing quote to a completed word.
-
-c. New application variable, rl_completion_found_quote, set to a non-zero
- value if readline determines that the word to be completed is quoted.
- Set before readline calls any application completion function.
-
-d. New function hook, rl_completion_word_break_hook, called when readline
- needs to break a line into words when completion is attempted. Allows
- the word break characters to vary based on position in the line.
-
-e. New bindable command: unix-filename-rubout. Does the same thing as
- unix-word-rubout, but adds `/' to the set of word delimiters.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-3.0-alpha,
-and the previous version, bash-2.05b-release.
-
-1. Changes to Bash
-
-a. Fixes so that the shell will compile without some of the default options
- defined.
-
-b. Fixed an error message that did not pass enough arguments to printf.
-
-c. Fixed a bug that caused input redirection to a builtin inside a script
- being read from standard input to result in the rest of the already-
- read and buffered script to be discarded.
-
-d. Fixed a bug that caused subshell initialization to close the file
- descriptor from which the shell was reading a script under certain
- circumstances.
-
-e. Fixed a bug that caused the shell to not advance a string pointer over
- a null wide character when doing string operations.
-
-f. Fixed the internal logout code so that shells that time out waiting for
- input (using $TMOUT) run ~/.bash_logout.
-
-g. Portability and configuration changes for: cygwin, HP/UX, GNU/FreeBSD.
-
-h. The parser no longer adds implicit double quotes to ((...)) arithmetic
- commands.
-
-i. The ((...)) arithmetic command evaluation code was fixed to not dump core
- when the expanded string is null.
-
-j. The ((...)) arithmetic command evaluation code was fixed to not perform
- variable assignments while expanding the expression.
-
-k. Fixed a bug that caused word splitting to be performed incorrectly when
- IFS is set, but null.
-
-l. Fixed a bug in brace expansion that caused a quoted `$' preceding an
- open brace to inhibit brace expansion.
-
-m. Fixed a bug that caused a leading `-' in the shell's name to cause it to
- not be recognized as a restricted shell.
-
-n. Fixed a bug in the arithmetic evaluation code that could cause longjmps
- to an invalid location and result in a core dump.
-
-o. Fixed a bug in the calculation of how many history lines are new in a
- single shell session when reading new history lines from a file with
- `history -n'.
-
-p. Fixed a bug in pathname canonicalization that caused the shell to dump
- core when presented with a pathname longer than PATH_MAX.
-
-q. Fixed the parser so that it doesn't try to compare a char variable to
- EOF, which fails when chars are unsigned.
-
-r. Fixed a bug in the simple command execution code that caused occasional
- core dumps.
-
-s. The shell does a better job of saving any partial parsing state during
- operations which cause a command to be executed while a line is being
- entered and parsed.
-
-t. The completion code now splits words more like the expansion code when
- $IFS is used to split.
-
-u. The locale code does a better job of recomputing the various locale
- variable values when LC_ALL is unset.
-
-v. The programmable completion code does a better job of dequoting expanded
- word lists before comparing them against the word to be matched.
-
-w. The shell no longer seg faults if the expanded value of $PS4 is null
- and `set -x' is enabled.
-
-x. Fixed a bug that caused core dumps when a here string expanded to NULL.
-
-y. The mail checking code now makes sure the mailbox is bigger before
- reporting the existence of new mail.
-
-z. The parser does not try to expand $'...' and $"..." when the appear
- within double quotes unless the `extquote' option has been enabled with
- `shopt'. For backwards compatibility, it is enabled by default.
-
-aa. Fixed a bug that caused `for x; do ...' and `select x; do ... to use
- $@ instead of "$@" for the implicit list of arguments.
-
-bb. Fixed a bug that caused a subshell of a restricted shell (e.g., one
- spawned to execute a pipeline) to not exit immediately if attempting
- to use a command containing a slash.
-
-cc. Fixed a problem with empty replacements for a pattern that doesn't match
- when performing ${param/word/} expansion.
-
-dd. Word expansions performed while expanding redirections no longer search
- a command's temporary environment to expand variable values.
-
-ee. Improvements to the alias expansion code when expanding subsequent words
- because an aliase's value ends with a space.
-
-ff. `cd -' now prints the current working directory after a successful chdir
- even when the shell is not interactive, as the standard requires.
-
-gg. The shell does a better job of ensuring a child process dies of SIGINT
- before resending SIGINT to itself.
-
-hh. The arithmetic expansion variable assignment code now does the right
- thing when assigning to `special' variables like OPTIND.
-
-ii. When history expansion verification is enabled, the bash readline helper
- functions that do history expansion on the current line don't print
- the results.
-
-jj. Fixed bugs with multiple consecutive alias expansion when one of the
- expansions ends with a space.
-
-kk. Fixed a problem in the programmable completion code that could cause core
- dumps when trying to initialize a set of possible completions from a
- list of variables.
-
-ll. The \[ and \] escape characters are now ignored when decoding the prompt
- string if the shell is started with editing disabled.
-
-mm. Fixed a bug that could leave extra characters in a string when doing
- quoted null character removal.
-
-nn. Command substitution and other subshell operations no longer reset the
- line number (aids the bash debugger).
-
-oo. Better line number management when executing simple commands, conditional
- commands, for commands, and select commands.
-
-pp. The globbing code now uses malloc, with its better failure properties,
- rather than alloca().
-
-qq. Fixed a bug that caused expansions like #{a[2]:=value} to create the
- appropriate array element instead of a variable named `a[2]'.
-
-rr. Fixed a bug in the handling of a `?(...)' pattern immediately following
- a `*' when extglob is enabled.
-
-ss. Fixed a bug that caused a `return' invoked in an exit trap when exit is
- invoked in a function to misbehave.
-
-tt. Fixed a bug that caused CTLESC and CTLNUL characters to not be escaped
- by the internal shell string quoting functions.
-
-uu. Fixed a bug that caused quoted null characters in an expanded word list
- to be inappropriately assigned to an array variable when using `read -a'.
-
-vv. Fixed a bug that caused redirections accompanying a null command to persist
- in the current shell.
-
-ww. Fixed a bug that caused the prompt to be printed when the shell was
- expanding a multiline alias.
-
-xx. Fixed a bug that resulted in core dumps when the completion for a command
- changed the compspec.
-
-yy. Fixed a bug that caused evaluation of programmable completions to print
- notifications of completed jobs.
-
-zz. Bash now disables line editing when $EMACS == `t' and $TERM == `dumb'
- (which is what emacs shell windows do).
-
-aaa. In posix mode, `kill -l' causes signal names to be displayed without
- a leading `SIG'.
-
-bbb. Clear error flag on standard output so it doesn't persist across multiple
- builtin commands.
-
-ccc. In posix mode, `alias' displays alias values without the leading `alias',
- so the output cannot be used as subsequent input.
-
-ddd. In posix mode, the `trap' builtin doesn't check whether or not its
- first argument is a signal specification and revert the signal handling
- to its original disposition if it is.
-
-eee. Fixed several bugs in the handling of "$*" and "${array[*]}" by the
- pattern substitution and removal expansions.
-
-fff. Fixed several problems with the handling of ${array[@]}, ${array[*]},
- $@, and $* by the indirect variable expansion code.
-
-ggg. Fixed a bug that did not allow `time' to be aliased.
-
-hhh. Improved the mail checking code so it won't check (and possibly cause an
- NFS file system mount) until MAILPATH or MAIL is given a value -- there
- is no default if DEFAULT_MAIL_DIRECTORY is not defined at compile time.
- (It is computed by configure, but can be #undef'd in config-bot.h.)
-
-iii. If the `chkwinsize' option is enabled, the shell checks for window size
- changes if a child process exits due to a signal.
-
-jjj. Removed the attempts to avoid adding a slash at the end of a completed
- executable name if there was a directory with the same name in the
- current directory.
-
-kkk. Fixed PATH lookup code so it treats the permission bits separately for
- owner, group, and other, rather than checking them all.
-
-lll. Fixed the locale code to reset the parser's idea of the character class
- <blank>, which controls how it splits tokens, when the locale changes.
-
-mmm. The shell now binds its special readline functions and key bindings only
- if the user's inputrc file has not already bound them.
-
-nnn. The shell now reports on processes that dump core due to signals when
- invoked as `-c command'.
-
-2. Changes to Readline
-
-a. Fixes to avoid core dumps because of null pointer references in the
- multibyte character code.
-
-b. Fix to avoid infinite recursion caused by certain key combinations.
-
-c. Fixed a bug that caused the vi-mode `last command' to be set incorrectly.
-
-d. Readline no longer tries to read ahead more than one line of input, even
- when more is available.
-
-e. Fixed the code that adjusts the point to not mishandle null wide
- characters.
-
-f. Fixed a bug in the history expansion `g' modifier that caused it to skip
- every other match.
-
-g. Fixed a bug that caused the prompt to overwrite previous output when the
- output doesn't contain a newline and the locale supports multibyte
- characters. This same change fixes the problem of readline redisplay
- slowing down dramatically as the line gets longer in multibyte locales.
-
-h. History traversal with arrow keys in vi insertion mode causes the cursor
- to be placed at the end of the new line, like in emacs mode.
-
-i. The locale initialization code does a better job of using the right
- precedence and defaulting when checking the appropriate environment
- variables.
-
-j. Fixed the history word tokenizer to handle <( and >( better when used as
- part of bash.
-
-k. The overwrite mode code received several bug fixes to improve undo.
-
-l. Many speedups to the multibyte character redisplay code.
-
-m. The callback character reading interface should not hang waiting to read
- keyboard input.
-
-n. Fixed a bug with redoing vi-mode `s' command.
-
-o. The code that initializes the terminal tracks changes made to the terminal
- special characters with stty(1) (or equivalent), so that these changes
- are reflected in the readline bindings. New application-callable function
- to make it work: rl_tty_unset_default_bindings().
-
-p. Fixed a bug that could cause garbage to be inserted in the buffer when
- changing character case in vi mode when using a multibyte locale.
-
-q. Fixed a bug in the redisplay code that caused problems on systems
- supporting multibyte characters when moving between history lines when the
- new line has more glyphs but fewer bytes.
-
-r. Undo and redo now work better after exiting vi insertion mode.
-
-s. Make sure system calls are restarted after a SIGWINCH is received using
- SA_RESTART.
-
-t. Improvements to the code that displays possible completions when using
- multibyte characters.
-
-u. Fixed a problem when parsing nested if statements in inputrc files.
-
-v. The completer now takes multibyte characters into account when looking for
- quoted substrings on which to perform completion.
-
-w. The history search functions now perform better bounds checking on the
- history list.
-
-3. New Features in Bash
-
-a. ANSI string expansion now implements the \x{hexdigits} escape.
-
-b. There is a new loadable `strftime' builtin.
-
-c. New variable, COMP_WORDBREAKS, which controls the readline completer's
- idea of word break characters.
-
-d. The `type' builtin no longer reports on aliases unless alias expansion
- will actually be performed.
-
-e. HISTCONTROL is now a colon-separated list of values, which permits
- more extensibility and backwards compatibility.
-
-f. HISTCONTROL may now include the `erasedups' option, which causes all lines
- matching a line being added to be removed from the history list.
-
-g. `configure' has a new `--enable-multibyte' argument that permits multibyte
- character support to be disabled even on systems that support it.
-
-h. New variables to support the bash debugger: BASH_ARGC, BASH_ARGV,
- BASH_SOURCE, BASH_LINENO, BASH_SUBSHELL, BASH_EXECUTION_STRING,
- BASH_COMMAND
-
-i. FUNCNAME has been changed to support the debugger: it's now an array
- variable.
-
-j. for, case, select, arithmetic commands now keep line number information
- for the debugger.
-
-k. There is a new `RETURN' trap executed when a function or sourced script
- returns (not inherited child processes; inherited by command substitution
- if function tracing is enabled and the debugger is active).
-
-l. New invocation option: --debugger. Enables debugging and turns on new
- `extdebug' shell option.
-
-m. New `functrace' and `errtrace' options to `set -o' cause DEBUG and ERR
- traps, respectively, to be inherited by shell functions. Equivalent to
- `set -T' and `set -E' respectively. The `functrace' option also controls
- whether or not the DEBUG trap is inherited by sourced scripts.
-
-n. The DEBUG trap is run before binding the variable and running the action
- list in a `for' command, binding the selection variable and running the
- query in a `select' command, and before attempting a match in a `case'
- command.
-
-o. New `--enable-debugger' option to `configure' to compile in the debugger
- support code.
-
-p. `declare -F' now prints out extra line number and source file information
- if the `extdebug' option is set.
-
-q. If `extdebug' is enabled, a non-zero return value from a DEBUG trap causes
- the next command to be skipped, and a return value of 2 while in a
- function or sourced script forces a `return'.
-
-r. New `caller' builtin to provide a call stack for the bash debugger.
-
-s. The DEBUG trap is run just before the first command in a function body is
- executed, for the debugger.
-
-t. `for', `select', and `case' command heads are printed when `set -x' is
- enabled.
-
-u. There is a new {x..y} brace expansion, which is shorthand for {x.x+1,
- x+2,...,y}. x and y can be integers or single characters; the sequence
- may ascend or descend; the increment is always 1.
-
-v. New ksh93-like ${!array[@]} expansion, expands to all the keys (indices)
- of array.
-
-w. New `force_fignore' shopt option; if enabled, suffixes specified by
- FIGNORE cause words to be ignored when performing word completion even
- if they're the only possibilities.
-
-x. New `gnu_errfmt' shopt option; if enabled, error messages follow the `gnu
- style' (filename:lineno:message) format.
-
-y. New `-o bashdefault' option to complete and compgen; if set, causes the
- whole set of bash completions to be performed if the compspec doesn't
- result in a match.
-
-z. New `-o plusdirs' option to complete and compgen; if set, causes directory
- name completion to be performed and the results added to the rest of the
- possible completions.
-
-aa. `kill' is available as a builtin even when the shell is built without
- job control.
-
-bb. New HISTTIMEFORMAT variable; value is a format string to pass to
- strftime(3). If set and not null, the `history' builtin prints out
- timestamp information according to the specified format when displaying
- history entries. If set, bash tells the history library to write out
- timestamp information when the history file is written.
-
-cc. The [[ ... ]] command has a new binary `=~' operator that performs
- extended regular expression (egrep-like) matching.
-
-dd. `configure' has a new `--enable-cond-regexp' option (enabled by default)
- to enable the =~ operator and regexp matching in [[ ... ]].
-
-ee. Subexpressions matched by the =~ operator are placed in the new
- BASH_REMATCH array variable.
-
-ff. New `failglob' option that causes an expansion error when pathname
- expansion fails to produce a match.
-
-gg. New `set -o pipefail' option that causes a pipeline to return a failure
- status if any of the processes in the pipeline fail, not just the last
- one.
-
-4. New Features in Readline
-
-a. History expansion has a new `a' modifier equivalent to the `g' modifier
- for compatibility with the BSD csh.
-
-b. History expansion has a new `G' modifier equivalent to the BSD csh `g'
- modifier, which performs a substitution once per word.
-
-c. All non-incremental search operations may now undo the operation of
- replacing the current line with the history line.
-
-d. The text inserted by an `a' command in vi mode can be reinserted with
- `.'.
-
-e. New bindable variable, `show-all-if-unmodified'. If set, the readline
- completer will list possible completions immediately if there is more
- than one completion and partial completion cannot be performed.
-
-f. There is a new application-callable `free_history_entry()' function.
-
-g. History list entries now contain timestamp information; the history file
- functions know how to read and write timestamp information associated
- with each entry.
-
-h. Four new key binding functions have been added:
-
- rl_bind_key_if_unbound()
- rl_bind_key_if_unbound_in_map()
- rl_bind_keyseq_if_unbound()
- rl_bind_keyseq_if_unbound_in_map()
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05b-release,
-and the previous version, bash-2.05b-beta2.
-
-1. Changes to Bash
-
-a. Fixed an off-by-one error in the function that translates job
- specifications.
-
-b. Note that we're running under Emacs and disable line editing if
- $EMACS == `t'.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05b-beta2,
-and the previous version, bash-2.05b-beta1.
-
-1. Changes to Bash
-
-a. Fixed the /= and %= arithmetic operators to catch division by zero.
-
-b. Added putenv, setenv, unsetenv to getenv replacement for completeness.
-
-c. Fixed a bug that could cause the -O expand_aliases invocation option
- to not take effect.
-
-d. Fixed a problem with process substitution that resulted in incorrect
- behavior when the number of process substitutions in an individual
- command approached 64.
-
-2. Changes to Readline
-
-a. Fixed a problem with backward-char-search when on a system with support
- for multibyte characters when running in a locale without any multibyte
- characters.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05b-beta1,
-and the previous version, bash-2.05b-alpha1.
-
-1. Changes to Bash
-
-a. Fixed a problem when parsing a POSIX.2 character class name while
- evaluating a bracket expression containing multibyte characters.
-
-b. Changed the help text for `bind' to make it clear that any command
- that may be placed in ~/.inputrc is a valid argument to `bind'.
-
-c. Added `help' builtin entries for `((', `[[', and arithmetic for.
-
-d. malloc updated again:
- o slightly better overflow and underflow detection by putting the
- chunk size at the beginning and end of the chunk and making
- sure they match in free/realloc
- o partial page allocated to make things page-aligned no longer
- completely wasted
- o block coalescing now enabled by default
- o splitting and coalescing enabled for 32-byte chunks, the most
- common size requested
- o fixed a problem that resulted in spurious underflow messages and
- aborts
- o bin sizes are precomputed and stored in an array rather than
- being computed at run time
- o malloc will return memory blocks back to the system if the block
- being freed is at the top of the heap and of sufficient size to
- make it worthwhile
- o malloc/free/realloc now inline memset instead of calling the
- libc function; uses Duff's device for good performance
-
-e. Check for getservent(); make the service name completion code dependent
- on its presence.
-
-f. Changed the readline callback that executes a command bound to a key
- sequence to not save the executed command on the history list and to
- save and restore the parsing state.
-
-g. Changes to lib/sh/snprintf.c: fixed some bugs in the `g' and `G'
- floating point format display; implemented the "'" flag character
- that turns on thousands' grouping; fixed behavior on systems where
- MB_CUR_MAX does not evaluate to a constant.
-
-h. The `unset' builtin no longer returns a failure status when asked to
- unset a previously-unset variable or function.
-
-i. Changes to the build system to make it easier to cross-compile bash
- for different systems.
-
-j. Added `,' to the characters that are backslash-escaped during filename
- completion, to avoid problems with complete-into-braces and RCS filenames
- containing commas.
-
-k. Some changes to the multibyte character support code to avoid many calls
- to strlen().
-
-l. Bash now correctly honors setting LANG to some value when LC_ALL does not
- already have a value.
-
-m. Fixed a bug that could cause SIGSEGV when processing nested traps with
- trap handlers.
-
-n. The `source/.' builtin now restores the positional parameters when it
- returns unless they were changed using the `set' builtin during the file's
- execution.
-
-o. Fixed a bug that caused a syntax error when a command was terminated by
- EOF.
-
-2. New Features in Bash
-
-a. There is now support for placing the long help text into separate files
- installed into ${datadir}/bash. Not enabled by default; can be turned
- on with `--enable-separate-helpfiles' option to configure.
-
-b. All builtins that take operands accept a `--' pseudo-option, except
- `echo'.
-
-c. The `echo' builtin now accepts \0xxx (zero to three octal digits following
- the `0') in addition to \xxx (one to three octal digits) for SUSv3/XPG6/
- POSIX.1-2001 compliance.
-
-3. Changes to Readline
-
-a. Fixed a small problem in _rl_insert_char with multibyte characters.
-
-b. Fixes from IBM for line wrapping problems when using multibyte characters.
-
-c. Fixed a problem which caused the display to be messed up when the last
- line of a multi-line prompt (possibly containing invisible characters)
- was longer than the screen width.
-
-d. Fixed a problem with the vi-mode `r' command that ocurred on systems with
- support for multibyte characters when running in a locale without any
- multibyte characters.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05b-alpha1,
-and the previous version, bash-2.05a-release.
-
-1. Changes to Bash
-
-a. Some changes to work around inlining differences between compilers.
-
-b. Added more prototypes for internal shell typedefs, to catch argument
- passing errors when using pointers to functions.
-
-c. The `cd' builtin now fails in posix mode when a valid directory cannot be
- constructed from a relative pathname argument and the $PWD using pathname
- canonicalization, and the -P option has not been supplied. Previously,
- the shell would attempt to use what the user typed, leading to weird
- values for $PWD and discrepancies between the value of $PWD and the
- actual working directory.
-
-d. The `cd' builtin now resets $PWD when canonicalization fails but a chdir
- to the pathname passed as an argument succeeds (when not in posix mode).
-
-e. The `fc' builtin has been fixed, as POSIX requires, to use the closest
- history position in range when given an out-of-range argument.
-
-f. The history file loading code was changed to allow lines to be saved in
- the history list from the shell startup files.
-
-g. `history -s args' now works better in compound commands.
-
-h. The tilde expansion code was fixed to better recognize when it's being
- invoked in an assignment context, which enables expansion after `='
- and `:'.
-
-i. Fixed the command name completion code so a slash is no longer appended
- to a single match if there happens to be a directory with that name in
- $PWD.
-
-j. Fixed compound array assignment to no longer perform alias expansion, to
- allow reserved words as array members, and to not produce extra output
- when the `-v' option had been enabled.
-
-k. Fixed the programmable completion code to better handle newlines in lists
- of possible completions (e.g., `complete -W').
-
-l. Removed the reserved words from the `bash-builtins' manual page.
-
-m. Parser error reporting now attempts to do a better job of identifying the
- token in error rather than doing straight textual analysis.
-
-n. Fixes for Inf/NaN, locales, wide/multibyte characters and zero-length
- arguments in the library snprintf(3) replacement.
-
-o. `read -e' no longer does command name completion on the first word on
- the line being read.
-
-p. `select' now returns failure if the read of the user's selection fails.
-
-q. Fixed a bug that could cause a core dump when setting $PIPESTATUS.
-
-r. Fixes to not allocate so many job slots when the shell is running a loop
- with job control enabled in a subshell of an interactive shell.
-
-s. Fixed a bug in the trap code that caused traps to be inherited by
- command substitutions in some cases.
-
-t. Fixed a bug that could cause alias expansion to inappropriately expand
- the word following the alias.
-
-u. Fixed a bug in the `kill' builtin that mishandled negative pid arguments.
-
-v. The parser is less lenient when parsing assignment statements where the
- characters before the `=' don't comprise a valid identifier.
-
-w. The arithmetic expression evaluation code now honors the setting of the
- `-u' option when expanding variable names.
-
-x. Fixed the arithmetic evaluation code to allow array subscripts to be
- assigned (`let b[7]=42') and auto-incremented and auto-decremented
- (e.g., b[7]++).
-
-y. Reimplemented the existing prompt string date and time expansions using
- strftime(3), which changed the output of \@ in some locales.
-
-z. Fixed a bug that could cause a core dump when a special shell variable
- (like RANDOM) was converted to an array with a variable assignment.
-
-aa. Fixed a bug that would reset the handler for a signal the user had
- trapped to a function that would exit the shell when setting the exit
- trap in a non-interactive shell.
-
-bb. Changed the execve(2) wrapper code to check whether or not a failing
- command is a directory before looking at whether a `#!' interpreter
- failed for some reason.
-
-cc. Fixed a bug in the command printing code so it no longer inserts a `;'
- after a newline, which produces a syntax error when reused as input.
-
-dd. The code that expands $PS4 no longer inherits the `-x' flag.
-
-ee. The bash-specific completion functions may now take advantage of the
- double-TAB and M-? features of the standard readline completion
- functions.
-
-ff. The mail checking code no longer prints a message if the checked file's
- size has not increased, even if the access time is less than the modification time.
-
-gg. Rewrote the variable symbol table code: there is now a stack of
- contexts, each possibly including a separate symbol table; there can
- be more than one temporary environment supplied to nested invocations
- of `./source'; the temporary environments no longer require so much
- special-case code; shell functions now handle the temporary environment
- and local variables more consistently; function scope exit is faster now
- that the entire symbol table does not have to be traversed to dispose of
- local variables; it is now easier to push vars from the temporary
- environment to the shell's variable table in posix mode; some duplicated
- code has been removed.
-
-hh. Regularized the error message printing code; builtin_error is now called
- more consistently, and common error message strings are handled by small
- functions. This should make eventual message translation easier.
-
-ii. Error messages now include the line number in a script when the shell
- is not interactive.
-
-jj. Array subscript expansion now takes place even when the array variable is
- unset, so side effects will take place.
-
-kk. Fixed a bug in the SICGHLD child-reaping code so that it won't find
- jobs already marked as terminated if the OS reuses pids quickly enough.
-
-ll. Fixed a bug that could cause a signal to not interrupt the `wait'
- builtin while it was waiting for a background process to terminate.
-
-mm. A couple of changes to make it easier for multiple shells to share history
- files using `history -n', `history -r', and `history -w'.
-
-nn. The `getopts' builtin always increments OPTIND to point to the next
- option to be handled when an option is returned, whether it's valid
- or not, as POSIX 1003.x-2001 requires.
-
-oo. Changed some parts of the expansion code to avoid allocating and
- immediately freeing memory without using the results for anything.
-
-pp. The shell now keeps track of $IFS internally, updating its internal map
- each time the variable is assigned a new value (or at local scope exit).
- This saves thousands of hash lookups for IFS, which, while individually
- cheap, add up.
-
-qq. Rewrote the hash table code: searching and insertion are much faster now,
- and it uses a better string hashing function; augmented the function
- interface to simplify other parts of the code and remove duplicated code
-
-rr. The shell now uses a simple, generic `object cache' for allocating and
- caching words and word lists, which were the major users of
- malloc/free.
-
-ss. Fixed the assignment statement parsing code to allow whitespace and
- newlines in subscripts when performing array element assignment.
-
-tt. The shell now issues many fewer calls to sigprocmask and other signal
- masking system calls.
-
-uu. Fixed the `test' and conditional command file comparison operators to
- work right when one file has a non-positive timestamp and the other
- does not exist.
-
-vv. Fixed some cases where the special characters '\001' and '\177' in the
- values of variables or positional parameters caused incorrect expansion
- results.
-
-2. Changes to Readline
-
-a. Fixed output of comment-begin character when listing variable values.
-
-b. Added some default key bindings for common escape sequences produced by
- HOME and END keys.
-
-c. Fixed the mark handling code to be more emacs-compatible.
-
-d. A bug was fixed in the code that prints possible completions to keep it
- from printing empty strings in certain circumstances.
-
-e. Change the key sequence printing code to print ESC as M\- if ESC is a
- meta-prefix character -- it's easier for users to understand than \e.
-
-f. Fixed unstifle_history() to return values that match the documentation.
-
-g. Fixed the event loop (rl_event_hook) to handle the case where the input
- file descriptor is invalidated.
-
-h. Fixed the prompt display code to work better when the application has a
- custom redisplay function.
-
-i. Changes to make reading and writing the history file a little faster, and
- to cope with huge history files without calling abort(3) from xmalloc.
-
-j. The vi-mode `S' and `s' commands are now undone correctly.
-
-3. New Features in Bash
-
-a. If set, TMOUT is the default timeout for the `read' builtin.
-
-b. `type' has two new options: `-f' suppresses shell function lookup, and
- `-P' forces a $PATH search.
-
-c. New code to handle multibyte characters.
-
-d. `select' was changed to be more ksh-compatible, in that the menu is
- reprinted each time through the loop only if REPLY is set to NULL.
- The previous behavior is available as a compile-time option.
-
-e. `complete -d' and `complete -o dirnames' now force a slash to be
- appended to names which are symlinks to directories.
-
-f. There is now a bindable edit-and-execute-command readline command,
- like the vi-mode `v' command, bound to C-xC-e in emacs mode.
-
-g. Added support for ksh93-like [:word:] character class in pattern matching.
-
-h. The $'...' quoting construct now expands \cX to Control-X.
-
-i. A new \D{...} prompt expansion; passes the `...' to strftime and inserts
- the result into the expanded prompt.
-
-j. The shell now performs arithmetic in the largest integer size the
- machine supports (intmax_t), instead of long.
-
-k. If a numeric argument is supplied to one of the bash globbing completion
- functions, a `*' is appended to the word before expansion is attempted.
-
-l. The bash globbing completion functions now allow completions to be listed
- with double tabs or if `show-all-if-ambiguous' is set.
-
-m. New `-o nospace' option for `complete' and `compgen' builtins; suppresses
- readline's appending a space to the completed word.
-
-n. 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).
-
-p. There is a new configuration option `--enable-mem-scramble', controls
- bash malloc behavior of writing garbage characters into memory at
- allocation and free time.
-
-q. The `complete' and `compgen' builtins now have a new `-s/-A service'
- option to complete on names from /etc/services.
-
-r. `read' has a new `-u fd' option to read from a specified file descriptor.
-
-s. Fix the completion code so that expansion errors in a directory name
- don't cause a longjmp back to the command loop.
-
-t. Fixed word completion inside command substitution to work a little more
- intuitively.
-
-u. The `printf' %q format specifier now uses $'...' quoting to print the
- argument if it contains non-printing characters.
-
-v. The `declare' and `typeset' builtins have a new `-t' option. When applied
- to functions, it causes the DEBUG trap to be inherited by the named
- function. Currently has no effect on variables.
-
-w. The DEBUG trap is now run *before* simple commands, ((...)) commands,
- [[...]] conditional commands, and for ((...)) loops.
-
-x. 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.
-
-y. 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. Code
- from Gary Vaughan.
-
-z. New [n]<&word- and [n]>&word- redirections from ksh93 -- move fds (dup
- and close).
-
-aa. There is a new `-l' invocation option, equivalent to `--login'.
-
-bb. The `hash' builtin has a new `-l' option to list contents in a reusable
- format, and a `-d' option to remove a name from the hash table.
-
-4. New Features in Readline
-
-a. Support for key `subsequences': allows, e.g., ESC and ESC-a to both
- be bound to readline functions. Now the arrow keys may be used in vi
- insert mode.
-
-b. When listing completions, and the number of lines displayed is more than
- the screen length, readline uses an internal pager to display the results.
- This is controlled by the `page-completions' variable (default on).
-
-c. New code to handle editing and displaying multibyte characters.
-
-d. The behavior introduced in bash-2.05a of deciding whether or not to
- append a slash to a completed name that is a symlink to a directory has
- been made optional, controlled by the `mark-symlinked-directories'
- variable (default is the 2.05a behavior).
-
-e. The `insert-comment' command now acts as a toggle if given a numeric
- argument: if the first characters on the line don't specify a
- comment, insert one; if they do, delete the comment text
-
-f. New application-settable completion variable:
- rl_completion_mark_symlink_dirs, allows an application's completion
- function to temporarily override the user's preference for appending
- slashes to names which are symlinks to directories.
-
-g. New function available to application completion functions:
- rl_completion_mode, to tell how the completion function was invoked
- and decide which argument to supply to rl_complete_internal (to list
- completions, etc.).
-
-h. Readline now has an overwrite mode, toggled by the `overwrite-mode'
- bindable command, which could be bound to `Insert'.
-
-i. New application-settable completion variable:
- rl_completion_suppress_append, inhibits appending of
- rl_completion_append_character to completed words.
-
-j. New key bindings when reading an incremental search string: ^W yanks
- the currently-matched word out of the current line into the search
- string; ^Y yanks the rest of the current line into the search string,
- DEL or ^H deletes characters from the search string.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05a-release,
-and the previous version, bash-2.05a-rc1.
-
-1. Changes to Bash
-
-a. Fixed the `printf' builtin so that the variable name supplied as an
- argument to a %n conversion must be a valid shell identifier.
-
-b. Improved the random number generator slightly.
-
-c. Changes to configuration to not put -I/usr/include into $CFLAGS, since
- it messes up some includes.
-
-d. Corrected description of POSIXLY_CORRECT in man page and info manual.
-
-e. Fixed a couple of cases of incorrect function prototypes that sneaked
- through and caused compilation problems.
-
-f. A few changes to avoid potential core dumps in the programmable completion
- code.
-
-g. Fixed a configure problem that could cause a non-existent file to show
- up in LIBOBJS.
-
-h. Fixed a configure problem that could cause siglist.o to not be built when
- required.
-
-i. Changes to the strtoimax and strtoumax replacement functions to work
- around buggy compilers.
-
-j. Fixed a problem with the snprintf replacement function that could
- potentially cause a core dump.
-
-2. Changes to Readline
-
-a. Fixed a locale-specific problem in the vi-mode `goto mark' command.
-
-b. Fixed Makefile to not put -I/usr/include into CFLAGS, since it can cause
- include file problems.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05a-rc1,
-and the previous version, bash-2.05a-beta1.
-
-1. Changes to Bash
-
-a. Fixed the snprintf replacement to correctly implement the `alternate form'
- of the %g and %G conversions.
-
-b. Fixed snprintf to correctly handle the optional precision with the %g and
- %G conversions.
-
-c. Fixed the arithmetic evaluation code to correct the values of `@' and `_'
- when translating base-64 constants (they were backwards).
-
-d. New library functions for formatting long and long long ints.
-
-e. Fixed a few places where negative array subscripts could have occurred,
- mostly as the result of systems using signed characters.
-
-f. Fixed a few places that assumed a pid_t was no wider than an int.
-
-g. Fixed the `maildir' mail checking code to work on systems where a
- `struct stat' doesn't include an `st_blocks' member.
-
-h. Fixed snprintf to make `unsigned long long' conversion formats (%llu)
- work better.
-
-i. Fixed snprintf to not print a sign when asked to do an unsigned conversion.
-
-j. Made configure changes to avoid compiling empty source files in lib/sh.
-
-k. New replacement functions (if necessary) for strtoull, strtoll, strtoimax,
- strtoumax.
-
-l. The `printf' builtin now handles the `ll' and `j' length modifiers
- directly, since they can affect the type and width of the argument
- passed to printf(3).
-
-m. Renamed a number of the bash-specific autoconf macros in aclocal.m4 to
- have more sytematic naming, with accompanying changes to configure.in.
-
-n. Fixed snprintf to handle long doubles and the %a/%A conversions by
- falling back to sprintf, as long as sprintf supports them.
-
-o. Fixed return value from vsnprintf/snprintf to be the number of characters
- that would have been printed, even if that number exceeds the buffer
- size passed as an argument.
-
-p. Bash no longer attempts to define its own versions of some ctype macros
- if they are implemented as functions in libc but not as macros in
- <ctype.h>.
-
-q. Changed the variable printing code (used by `set', `export', etc.) to
- not use the $'...' syntax when in posix mode, since that caused
- interoperability problems with other shells (most notably with autoconf).
- When not in posix mode, it uses $'...' if the string to be printed
- contains non-printing characters and regular single quotes otherwise.
-
-r. snprintf now recognizes the %F conversion.
-
-s. Fixed a bug that could cause the wrong status to be returned by a shell
- function when the shell is compiled without job control and a null
- command containing a command substutition was executed in the function.
-
-t. When in posix mode, the default value for MAILCHECK is 600.
-
-u. Bash only initializes FUNCNAME, GROUPS, and DIRSTACK as special variables
- if they're not in the initial environment.
-
-v. If SECONDS appears in the initial environment with a valid integer value,
- bash uses that as the starting value, as if an assignment had been
- performed.
-
-w. Bash no longer auto-exports HOME, PATH, SHELL, or TERM, even though it
- gives them default values if they don't appear in the initial environment.
-
-x. Bash no longer auto-exports HOSTNAME, HOSTTYPE, MACHTYPE, or OSTYPE,
- even if it assigns them default values.
-
-y. Bash no longer removes the export attribute from SSH_CLIENT or SSH2_CLIENT
- if they appear in the initial environment.
-
-z. Bash no longer attempts to discover if it's being run by sshd in order to
- run the startup files. If the SSH_SOURCE_BASHRC is uncommented in
- config-top.h it will attempt to do so as previously, but that's commented
- out in the distributed version.
-
-aa. Fixed a typo in the code that tests for LC_NUMERIC.
-
-bb. The POSIXLY_CORRECT shell variable and its effects are now documented.
-
-cc. Some changes to several of the support shell scripts included in the
- definitions to try to avoid race conditions and attacks.
-
-dd. Several changes to avoid warnings from `gcc -Wall'.
-
-ee. Fixed a problem with the `unset' builtin that could cause incorrect
- results if asked to unset a variable and an array subscript in the
- same command.
-
-ff. A few changes to the shell's temporary file creation code to avoid
- potential file descriptor leaks and to prefer the system's idea of
- the temporary directory to use.
-
-gg. Fixes to build with the C alloca in lib/malloc/alloca.c if the system
- requires it but the shell has been configured --without-bash-malloc.
-
-hh. Updated the documentation to note that only interactive shells resend
- SIGHUP to all jobs before exiting.
-
-ii. Fixes to only pass unquoted tilde words to tilde_expand, rather than
- rely on tilde_expand or getpwnam(3) to handle the quotes (MacOS 10.x
- will remove backslashes in any login name passed to getpwnam(3)).
-
-jj. Small change from Paul Eggert to make LINENO right in commands run with
- `bash -c'.
-
-2. New Features in Bash
-
-a. The `printf' builtin now handles the %a and %A conversions if they're
- implemented by printf(3).
-
-b. The `printf' builtin now handles the %F conversion (just about like %f).
-
-c. The `printf' builtin now handles the %n conversion like printf(3). The
- corresponding argument is the name of a shell variable to which the
- value is assigned.
-
-3. Changes to Readline
-
-a. Fixed a few places where negative array subscripts could have occurred.
-
-b. Fixed the vi-mode code to use a better method to determine the bounds of
- the array used to hold the marks.
-
-c. Fixed the defines in chardefs.h to work better when chars are signed.
-
-d. Fixed configure.in to use the new names for bash autoconf macros.
-
-e. Readline no longer attempts to define its own versions of some ctype
- macros if they are implemented as functions in libc but not as macros in
- <ctype.h>.
-
-f. Fixed a problem where rl_backward could possibly set point to before
- the beginning of the line.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05a-beta1,
-and the previous version, bash-2.05a-alpha1.
-
-1. Changes to Bash
-
-a. Fixed a bug in the evalution of arithmetic `for' statements when the
- expanded expression is NULL.
-
-b. Fixed an unassigned variable problem in the redirection printing code.
-
-c. Added more prototypes to extern function declarations in the header
- files and to static function declarations in C source files.
-
-d. Make sure called functions have a prototype in scope, to get the arguments
- and return values right instead of casting. Removed extern function
- declarations from C source files that were already included in header
- files.
-
-e. Changed some function arguments to use function typedefs in general.h so
- the prototypes can be checked. The only use of Function and VFunction
- now is for unwind-protects.
-
-f. More const changes to function arguments and appropriate variables.
-
-g. Changed the mail checking support to handle `maildir'-style mail
- directories.
-
-h. Augmented the bash malloc to pass in the file and line number information
- for each malloc, realloc, and free. This should result in better error
- messages.
-
-i. The `old' gnu malloc is no longer a configuration option.
-
-j. Augmented the bash malloc with optional tracing and registering allocated
- and freed memory.
-
-k. Prompt string decoding now saves and restores the value of $? when it
- expands the prompt string, so command substitutions don't change $?.
-
-i. Array indices are now `long', since shell arithmetic is performed as long,
- and the internal arrayind_t type is used consistently.
-
-j. Some more `unsigned char *' fixes from Paul Eggert.
-
-k. Fixed a bad call to builtin_error that could cause core dumps when making
- local variables.
-
-l. `return' may no longer be used to terminate a `select' command, for
- compatibility with ksh.
-
-m. Changed code that reads octal numbers to do a better job of detecting
- overflows.
-
-n. The time formatting code no longer uses absolute indices into a buffer,
- because the buffer size changes depending on the size of a `time_t'.
-
-o. `umask' now prints four digits when printing in octal mode, for
- compatibility with other shells.
-
-p. Lots of changes to the `printf' builtin from Paul Eggert: it handles `L'
- formats and long doubles better, and internal functions have been
- simpified where appropriate.
-
-q. Some `time_t' fixes for machines were a time_t is bigger than a long.
-
-r. Replaced some bash-specific autoconf macros with standard equivalents.
-
-s. Improvmed the code that constructs temporary filenames to make the
- generated names a bit more random.
-
-t. Added code that checks for ascii before calling any of the is* ctype
- functions.
-
-u. Changed some places where a `char' was used as an array subscript to use
- `unsigned char', since a `char' can be negative if it's signed by default.
-
-v. Lots of changes to the `ulimit' builtin from Paul Eggert to add support
- for the new POSIX-200x RLIM_SAVED_CUR and RLIM_SAVED_MAX values and
- simplify the code.
-
-w. `ulimit' now prints the description of a resource in any error message
- relating to fetching or setting that resource's limits.
-
-x. The `snprintf' replacement now computes maximum values at compile
- time rather than using huge constants for things like long long.
-
-y. Interactive shells now ignore `set -n'.
-
-z. Changed the malloc bookkeeping information so that it's now 8 bytes
- instead of 12 on most 32-bit machines (saving 4 bytes per allocation),
- restoring 8-byte alignment.
-
-aa. The malloc error reporting code now attempts to print the file and line
- number of the call that caused the error.
-
-bb. Changed the redirection error reporting code to catch EBADF errors and
- report the file descriptor number rather than the file being redirected
- to or from (e.g., things like `exec 4242<x' where 4242 is an out-of-range
- file descriptor).
-
-cc. `printf', `echo -e', and the $'...' code now process only two hex digits
- after a `\x' escape sequence for compatibility with other shells, and
- the documentation was changed to note that the octal and hex escape
- sequences result in an eight-bit value rather than strict ASCII.
-
-2. Changes to Readline
-
-a. The completion code now attempts to do a better job of preserving the
- case of the word the user typed if ignoring case in completions.
-
-b. Readline defaults to not echoing the input and lets the terminal
- initialization code enable echoing if there is a controlling terminal.
-
-c. The key binding code now processes only two hex digits after a `\x'
- escape sequence, and the documentation was changed to note that the
- octal and hex escape sequences result in an eight-bit value rather
- than strict ASCII.
-
-3. New Features in Bash
-
-a. The builtin `ulimit' now takes two new non-numeric arguments: `hard',
- meaning the current hard limit, and `soft', meaning the current soft
- limit, in addition to `unlimited'
-
-b. `ulimit' now prints the option letter associated with a particular
- resource when printing more than one limit.
-
-c. `ulimit' prints `hard' or `soft' when a value is not `unlimited' but is
- one of RLIM_SAVED_MAX or RLIM_SAVED_CUR, respectively.
-
-4. New Features in Readline
-
-a. New bindable variable `history-preserve-point'. If set, the history
- code attempts to place the user at the same location on each history
- line retrived with previous-history or next-history.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05a-alpha1,
-and the previous version, bash-2.05-release.
-
-1. Changes to Bash
-
-a. Better checks in the redirection code for write errors.
-
-b. bashbug now uses $TMPDIR, defaulting to /tmp, and uses mktemp(1) more
- portably.
-
-c. System-specific configuration changes for: Interix, OpenBSD, FreeBSD,
- MacOS X.
-
-d. Some more `const' cleanups through the code.
-
-e. Fixed a typo in the /dev/fd redirection code, better checks for valid
- numeric fds in /dev/fd.
-
-f. Fixed many parts of the shell to handle integer overflow more gracefully
- and to do more stringent checks for valid numbers.
-
-g. Fixed mksignames to include config.h.
-
-h. Fixed an uninitialized variable problem that could cause the shell to core
- dump when replacing characters in a string.
-
-i. New mechanism for updating the patch level when official patches are
- released (patchlevel.h).
-
-j. configure.in changed to no longer require external files _distribution and
- _patchlevel.
-
-k. Fixed non-interactive shell initialization problem when bash started as
- `bash -i filename'.
-
-l. Fixed printf builtin conversion error handling to be POSIX.2-conformant.
-
-m. autoconf-2.52 is now used to build configure; autoconf-2.50 or newer is
- required. Some of the bash-specific macros were removed, since they are
- now standard.
-
-n. Startup files and files read with source or `.' are no longer required to
- be regular files.
-
-o. Fixed core dump in builtin printf when user-supplied precision or field
- width is 0.
-
-p. Fixed builtin printf to treat a negative field width as a positive field
- width with left-justification.
-
-r. New unwind-protect implementation from Paul Eggert.
-
-s. Fixed an inadvertently-unclosed comment in the bash completion code that
- caused programmable completions to not add trailing slashes or spaces to
- completions.
-
-t. Fixed the process substitution code to cope better when stdin is closed.
-
-v. Fixes, mostly from Paul Eggert, for a few possible buffer overflows in
- the shell.
-
-w. Fixes from Paul Eggert to avoid most of the type casts in the shell code,
- and use more appropriate types for a number of variables.
-
-x. Command substition no longer inherits the DEBUG trap.
-
-y. Some fixes to the process substition code on machines without /dev/fd so
- that named pipes are not removed inappropriately.
-
-z. The loadable `getconf' builtin is now much more complete, and will become
- part of the shell in the future.
-
-aa. The select command no longer terminates on a `return', so it can be used
- to return from an enclosing function (as ksh does it).
-
-bb. Fixed the extended pattern matching code to behave better when presented
- with incorrectly-formed patterns.
-
-cc. Some changes were made with the intent of making cross-compilation easier.
-
-dd. The network code (/dev/tcp and /dev/udp redirections) uses getaddrinfo(3)
- if it's available, which adds support for IPv6.
-
-ee. Subshells of login shells no longer source ~/.bash_logout when they exit.
-
-ff. Fixes so that subshells don't exit inappropriately if the -e option has
- been set.
-
-gg. Restricted shells no longer allow functions to be exported.
-
-hh. Changes to the pattern matching code so extended pattern matching works
- on systems with deficient shared library implementations, like MacOS X.
-
-ii. Better error messages when a script with a leading `#!interp' fails
- to execute because of problems with `interp'.
-
-jj. Fixed `compgen' to handle the `-o default' option better.
-
-kk. Fixed the job control code to force an asynchronous process's standard
- input to /dev/null only if job control is not active.
-
-ll. Fixed a possible infinite recursion problem when `fc ""=abc' (a null
- pattern) is used to re-execute a previous command.
-
-mm. Fixed `declare [-a] var=value' to assign VALUE to element 0 if VAR is an
- array variable. Similarly for `declare [-a] var[N]=value'. This is like
- ksh93.
-
-nn. Fixed a bug that caused `read -a aname' to work even if ANAME had been
- declared readonly.
-
-oo. Fixed a possible integer overflow problem when constructing names for
- temporary files.
-
-2. New Features in Bash
-
-a. Added support for DESTDIR installation root prefix, so you can do a
- `make install DESTDIR=bash-root' and do easier binary packaging.
-
-b. Added support for builtin printf "'" flag character as per latest POSIX
- drafts.
-
-c. Support for POSIX.2 printf(1) length specifiers `j', `t', and `z' (from
- ISO C99).
-
-d. New autoconf macro, RL_LIB_READLINE_VERSION, for use by other applications
- (bash doesn't use very much of what it returns).
-
-e. `set [-+]o nolog' is recognized as required by the latest POSIX drafts,
- but ignored.
-
-f. New read-only `shopt' option: login_shell. Set to non-zero value if the
- shell is a login shell.
-
-g. New `\A' prompt string escape sequence; expands to time in 24 HH:MM format.
-
-h. New `-A group/-g' option to complete and compgen; does group name
- completion.
-
-i. New `-t' option to `hash' to list hash values for each filename argument.
-
-j. New [-+]O invocation option to set and unset `shopt' options at startup.
-
-k. configure's `--with-installed-readline' option now takes an optional
- `=PATH' suffix to set the root of the tree where readline is installed
- to PATH.
-
-l. The ksh-like `ERR' trap has been added. The `ERR' trap will be run
- whenever the shell would have exited if the -e option were enabled.
- It is not inherited by shell functions.
-
-m. `readonly', `export', and `declare' now print variables which have been
- given attributes but not set by assigning a value as just a command and
- a variable name (like `export foo') when listing, as the latest POSIX
- drafts require.
-
-n. `bashbug' now requires that the subject be changed from the default.
-
-o. configure has a new `--enable-largefile' option, like other GNU utilities.
-
-p. `for' loops now allow empty word lists after `in', like the latest POSIX
- drafts require.
-
-3. Changes to Readline
-
-a. More `const' and type casting fixes.
-
-b. Changed rl_message() to use vsnprintf(3) (if available) to fix buffer
- overflow problems.
-
-c. The completion code no longer appends a `/' or ` ' to a match when
- completing a symbolic link that resolves to a directory name, unless
- the match does not add anything to the word being completed. This
- means that a tab will complete the word up to the full name, but not
- add anything, and a subsequent tab will add a slash.
-
-d. Fixed a trivial typo that made the vi-mode `dT' command not work.
-
-e. Fixed the tty code so that ^S and ^Q can be inserted with rl_quoted_insert.
-
-f. Fixed the tty code so that ^V works more than once.
-
-g. Changed the use of __P((...)) for function prototypes to PARAMS((...))
- because the use of __P in typedefs conflicted g++ and glibc.
-
-4. New Features in Readline
-
-a. Added extern declaration for rl_get_termcap to readline.h, making it a
- public function (it was always there, just not in readline.h).
-
-b. New #defines in readline.h: RL_READLINE_VERSION, currently 0x0402,
- RL_VERSION_MAJOR, currently 4, and RL_VERSION_MINOR, currently 2.
-
-c. New readline variable: rl_readline_version, mirrors RL_READLINE_VERSION.
-
-d. New bindable boolean readline variable: match-hidden-files. Controls
- completion of files beginning with a `.' (on Unix). Enabled by default.
-
-e. The history expansion code now allows any character to terminate a
- `:first-' modifier, like csh.
-
-f. The incremental search code remembers the last search string and uses
- it if ^R^R is typed without a search string.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05-release,
-and the previous version, bash-2.05-beta2.
-
-1. Changes to Bash
-
-a. Make sure we note that the first line of a multi-line command was not
- saved in the history if the tests for HISTCONTROL succeed, but the
- HISTIGNORE check fails.
-
-b. Fixed a bug in the pattern matching code that caused `[' to be treated
- as a special character inside a `[...]' bracket expression.
-
-c. Fixed a bug in the pattern matching code that caused `]' to terminate
- a bracket expression even if it was the first character after the `['
- (or a leading `!' or `^').
-
-d. Made a small change to report a more user-friendly error message if
- execve(2) fails because of an error with the interpreter in a script
- with a leading `#! interpreter'.
-
-e. If the OS does not support an exec(2) magic number of `#!', make sure we
- have a non-null interpreter name before attempting to execute it.
-
-f. Fixed a bug that caused the shell process to end up in a different
- process group than the controlling terminal if a job-control shell was
- run with `exec' in the startup files.
-
-g. When started in POSIX mode, either by `bash --posix', `bash -o posix', or
- `sh', $SHELLOPTS includes `posix' and POSIXLY_CORRECT is set.
-
-h. Fixed a problem that caused the `\W' prompt string escape sequence to
- expand to nothing when $PWD was `//'.
-
-i. The `bashbug' shell script no longer uses $(...) command substitution.
-
-j. When `set' is invoked without options in POSIX mode, it no longer prints
- the names and definitions of shell functions.
-
-2. Changes to Readline
-
-a. rl_set_paren_blink_timeout() is now documented.
-
-b. Corrected history.3 man page: `$' is not in the default value of
- history_word_delimiters.
-
-c. If a hook function assigned to rl_event_hook sets rl_done to a non-zero
- value, rl_read_key() now immediately returns '\n' (which is assumed to
- be bound to accept-line).
-
-3. New Features in Bash
-
-a. The `>&word' redirection now works in POSIX mode as it does by default,
- since POSIX.2 leaves it unspecified.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05-beta2,
-and the previous version, bash-2.05-beta1.
-
-1. Changes to Bash
-
-a. Fixed a bug in the arithmetic evaluation code so that a^=b is supported.
-
-b. Fixed startup so posixly_correct is retained across subshells begun to
- execute scripts without a leading `#!'.
-
-c. Fixed a bug that caused $(< file) to not work in a (...) subshell.
-
-d. Added config support for Linux running on the IBM S390.
-
-e. Fixed a bug that caused bash to get its input pointer out of sync when
- reading commands through a pipe and running a command with standard
- input redirected from a file.
-
-f. Made a change so that command completion now makes about half as many
- stat(2) calls when searching the $PATH.
-
-g. Fixed a bug that caused variable assignments preceding `return' to not
- be propagated to the shell environment in POSIX mode.
-
-h. Fixed a bug with ${parameter[:]?word} -- tilde expansion was not performed
- on `word'.
-
-i. In POSIX mode, `break' and `continue' do not complain and return success
- if called when the shell is not executing a loop.
-
-j. Fixed `bash -o posix' to work the same as `bash --posix'.
-
-k. Fixed a bug where variable assignments preceding `eval' or `source/.'
- would not show up in the environment exported to subshells run by the
- commands.
-
-l. In POSIX mode, shells started to execute command substitutions inherit
- the value of the `-e' option from their parent shell.
-
-m. In POSIX mode, aliases are expanded even in non-interactive shells.
-
-n. Changed some of the job control messages to display the text required by
- POSIX.2 when the shell is in POSIX mode.
-
-o. Fixed a bug in `test' that caused it to occasionally return incorrect
- results when non-numeric arguments were supplied to `-t'.
-
-2. Changes to Readline
-
-a. Some changes were made to avoid gcc warnings with -Wall.
-
-b. rl_get_keymap_by_name now finds keymaps case-insensitively, so
- `set keymap EMACS' works.
-
-c. The history file writing and truncation functions now return a useful
- status on error.
-
-d. Fixed a bug that could cause applications to dereference a NULL pointer
- if a NULL second argument was passed to history_expand().
-
-3. New Features in Bash
-
-a. doc/readline.3 has been moved to the readline distribution.
-
-4. New Features in Readline
-
-a. New function, rl_get_screen_size (int *rows, int *columns), returns
- readline's idea of the screen dimensions.
-
-b. The timeout in rl_gather_tyi (readline keyboard input polling function)
- is now settable via a function (rl_set_keyboard_input_timeout()).
-
-c. Renamed the max_input_history variable to history_max_entries; the old
- variable is maintained for backwards compatibility.
-
-d. The list of characters that separate words for the history tokenizer is
- now settable with a variable: history_word_delimiters. The default
- value is as before.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05-beta1,
-and the previous version, bash-2.05-alpha1.
-
-1. Changes to Bash
-
-a. Changes to allow shared library and object building on the GNU Hurd.
-
-b. Fixes to the way exported functions are placed into the environment and
- cached.
-
-c. The globbing library once again respects locales when processing ranges
- in bracket expressions while doing pattern matching.
-
-d. System-specific configuration changes for: Tru 64, Interix
-
-e. Bashbug now uses /usr/bin/editor as one of the editing alternatives, and
- will use mktemp(1) or tempfile(1), if present, for temporary file creation.
-
-f. Bash no longer performs a binary file check on a script argument that's
- really a tty (like /dev/fd/0 or /dev/stdin).
-
-g. Fixed a bug in the execution of shell scripts that caused the effects of
- $BASH_ENV to be undone in some cases.
-
-h. Fixed several bugs that made `bash [-i] /dev/stdin' not work correctly.
-
-i. Several changes to the job control code to avoid some signal state
- manipulation.
-
-j. The Bash malloc no longer blocks signals as often, which should make it
- faster.
-
-k. Fixed a parsing bug that did not allow backslash to escape a single quote
- inside a $'...' construct.
-
-l. Fixed a bug that caused things like ${var:=$'value'} to be parsed
- incorrectly. This showed up in newer versions of autoconf.
-
-m. Fixed a bug in the bash-specific readline initialization that caused
- key bindings to bash-specific function names appearing in .inputrc to
- not be honored.
-
-n. Bash now sets the file descriptor it uses to save the file descriptor
- opened on a shell script to close on exec.
-
-o. Fixed a bug in the prompt string decoding that caused it to misbehave
- when presented an octal sequence of fewer than three characters.
-
-p. Fixed the `test' builtin to return an error if `[' is supplied a single
- argument that is not `]'.
-
-q. Fixed a bug that caused subshells started to run executable shell scripts
- without a leading `#!' to incorrectly inherit an argument list preceding
- a shell builtin (like such a script called from a script sourced with `.',
- where there were variable assignments preceding the `.' command)
-
-r. Fixed a bug that caused changes to variables supplied in an assignment
- statement preceding a shell builtin to not be honored (like a script
- run with `.').
-
-s. HOSTTYPE, OSTYPE, and MACHTYPE are set only if they do not have values
- when the shell is started.
-
-t. Fixed a bug that caused SIGINT to kill shell scripts after the script
- called `wait'.
-
-u. The `fc' builtin now tries to create its temporary files in the directory
- named by $TMPDIR.
-
-v. Bash no longer calls any Readline functions or uses any Readline variables
- not declared in readline.h.
-
-w. Fixed a bug that caused some substitutions involving $@ to not be split
- correctly, especially expansions of the form ${paramterOPword}.
-
-x. SSH2_CLIENT is now treated like SSH_CLIENT and not auto-exported if it
- appears in the initial environment.
-
-y. Fixed a couple of problems with shell scripts without a leading `#!'
- being executed out of shell functions that could cause core dumps if
- such a script attempted to execute `return'.
-
-z. Fixed a problem with the `-nt' and `-ot' binary operators for the
- `test/[' builtin and the `[[' conditional command that caused wrong
- return values if one of the file arguments did not exist.
-
-aa. Fixed a bug that caused non-interactive shells which had previously
- executed `shopt -s expand_aliases' to fail to expand aliases in a
- command like `(command) &'.
-
-2. Changes to Readline
-
-a. Changes to make most (but not yet all -- there is still crlf()) of the
- exported readline functions declared in readline.h have an rl_ prefix.
-
-b. More `const' changes in function arguments, mostly for completion
- functions.
-
-c. Fixed a bug in rl_forward that could cause the point to be set to before
- the beginning of the line in vi mode.
-
-d. Fixed a bug in the callback read-char interface to make it work when a
- readline function pushes some input onto the input stream with
- rl_execute_next (like the incremental search functions).
-
-e. Fixed a file descriptor leak in the history file manipulation code that
- was tripped when attempting to truncate a non-regular file (like
- /dev/null).
-
-f. Some existing variables are now documented and part of the public
- interface (declared in readline.h): rl_explict_arg, rl_numeric_arg,
- rl_editing_mode, rl_last_func.
-
-g. Renamed rltty_set_default_bindings to rl_tty_set_default_bindings and
- crlf to rl_crlf, so there are no public functions declared in readline.h
- without an `rl_' prefix. The old functions still exist for backwards
- compatibility.
-
-3. New Features in Bash
-
-a. A new loadable builtin, realpath, which canonicalizes and expands symlinks
- in pathname arguments.
-
-b. 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.
-
-4. New Features in Readline
-
-a. New application-callable function rl_set_prompt(const char *prompt):
- expands its prompt string argument and sets rl_prompt to the result.
-
-b. New application-callable function rl_set_screen_size(int rows, int cols):
- public method for applications to set readline's idea of the screen
- dimensions.
-
-c. The history example program (examples/histexamp.c) is now built as one
- of the examples.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.05-alpha1,
-and the previous version, bash-2.04-release.
-
-1. Changes to Bash
-
-a. A fix was made to allow newlines in compond array assignments.
-
-b. configure now checks for real-time signals with unusable values.
-
-c. Interactive shells no longer exit if a substitution fails because of an
- unset variable within a sourced file.
-
-d. Fixed a problem with incorrect matching of extended glob patterns when
- doing pattern substitution.
-
-e. `{' is now quoted by the completion code when it appears in a filename.
-
-f. Fixed an error in pattern matching that caused the matcher to not
- correctly skip the rest of a bracket expression after a character
- matched.
-
-g. Fixed a bug in the IFS word splitting code to make a non-whitespace IFS
- character preceded by IFS whitespace part of the current delimiter rather
- than generating a separate field.
-
-h. The {!prefix@} expansion now generates separate words, analogous to $@,
- when double-quoted.
-
-i. Command substitution now ignores NUL bytes in the command output, and the
- parser ignores them on input.
-
-j. A fix was made to the job control code to prevent hanging processes when
- the shell thinks background processes are running but the kernel returns
- -1/ECHILD from waitpid().
-
-k. `pwd' now prints an error message if the write fails when displaying the
- current directory.
-
-l. When in POSIX mode, the shell prints trap dispostions without a leading
- `SIG' in the signal specification.
-
-m. Fixed a parser bug that caused the current command's line count to be
- messed up by a compound array assignment.
-
-n. Fixed a bug in the unwind-protect code that caused bad behavior on machines
- where ints and pointers are not the same size.
-
-o. System-specific configure changes for: MacOS X.
-
-p. Changes for Cygwin to translate \r\n and \r to \n and to set file
- descriptors used for reading input to text mode in various places.
-
-q. Fixed a bug that caused `!' to occasionally not be honored when in
- a (...) subshell.
-
-r. Bash no longer assumes that getcwd() will return any useful error message
- in the buffer passed as an argument if the call fails.
-
-s. The `source', `.', and `fc' builtins no longer check whether a file is
- binary before reading commands from it.
-
-t. Subshells no longer turn off job control when they exit, since that
- sometimes resulted in the terminal being reset to the wrong process
- group.
-
-u. The history code no longer tries to save the second and subsequent lines
- of a multi-line command if the first line was not saved.
-
-v. The history saving code now does a better job of saving blank lines in a
- multi-line command.
-
-w. Removed a `feature' that made `ulimit' silently translate `unlimited' to
- the current hard limit, which obscured some kernel error returns.
-
-x. Fixed the grammar so that `}' is recognized as a reserved word after
- another reserved word, rather than requiring a `;' or newline. This
- means that constructs like
-
- { { echo a b c ; } }
-
- work as expected.
-
-y. Conditional commands ([[...]]) now perform tilde expansion on their
- arguments.
-
-z. Noted in the documentation that `set -a' will cause functions to be
- exported if they are defined after `set -a' is executed.
-
-aa. When an interactive login shell starts, if $PWD and $HOME refer to the
- same directory but are not the same string, $PWD is set to $HOME.
-
-bb. Fixed `printf' to handle invalid floating point numbers better.
-
-cc. Temporary files are now created with random filenames, to improve security.
-
-dd. The readline initialization code now binds the custom bash functions and
- key bindings after the readline defaults are set up.
-
-ee. Fixed the `source' builtin to no longer overwrite a shell function's
- argument list, even if the sourced file changes the positional parameters.
-
-ff. A bug fix was made in the expansion of `$*' in contexts where it should
- not be split, like assignment statements.
-
-gg. Fixed a bug in the parameter substring expansion to handle conditional
- arithmetic expressions ( exp ? val1 : val2 ) without cutting the expression
- off at the wrong `:'.
-
-hh. The `<>' redirection is no longer subject to the current setting of
- `noclobber', as POSIX.2 specifies.
-
-ii. Fixed a bug in the conditional command parsing code that caused expressions
- in parentheses to occasionally be parsed incorrectly.
-
-jj. Fixed a bug in the ((...)) arithmetic command to allow do...done or
- {...} to follow the )) without an intervening list terminator.
-
-kk. `printf' now treats `\E' the same as `\e' when performing backslash escape
- expansion for the `%b' format specifier.
-
-ll. When in POSIX mode, the shell no longer searches the current directory for
- a file to be sourced with `.' or `source' if `.' is not in $PATH.
-
-mm. Interactive comments are no longer turned off when POSIX mode is disabled.
-
-nn. The UID, EUID, HOSTNAME variables are not set if they are in the shell's
- environment when it starts up.
-
-oo. Fixed a bug in the `command' builtin so the effect of a command like
- `command exec 4<file' is as if the `command' had been omitted.
-
-pp. ${foo[@]} and ${foo[*]} now work as in ksh93 if `foo' is not an array
- variable.
-
-qq. ${#foo[X]}, where X is 0, @, or *, now work as in ksh93 if `foo' is not
- an array variable.
-
-rr. The shell's idea of an absolute pathname now takes into account a
- possible drive specification on Cygwin and other Windows systems.
-
-ss. Fixed a bug which caused incorrect parsing of some multi-character
- constructs if they were split across input lines with backslash-newline
- line continuation.
-
-tt. Fixed a bug that caused restricted shell mode to be set inappropriately
- when trying to execute a shell script without a leading `#!'.
-
-uu. Shell function definitions no longer require that the body be a group
- command ( {...} ), as POSIX.2 requires.
-
-vv. The `cd' and `pwd' builtins now process symlinks in pathnames internally
- and should require many fewer calls to getcwd().
-
-ww. Fixed a bug that caused a pipeline's process group to be set incorrectly
- if one of the pipeline elements contained a command substitution.
-
-xx. Fixed a bug that caused core dumps when expanding the value of HISTIGNORE.
-
-yy. The output of `set' is now quoted using $'...' so invisible characters are
- displayed as escape sequences.
-
-zz. Fixed the help text for `unset', since PATH and IFS may both be unset.
-
-aaa. The shell no longer puts directory names into the command hash table.
-
-bbb. Fixed a bug in `read' that caused it to occasionally free memory twice if
- it was interrupted after reading a large amount of data.
-
-ccc. Assignment statements that attempt to assign values to readonly variables
- now cause the command to return an error status.
-
-ddd. Fixed a bug that could cause incorrect output if a $(<file) construct was
- interrupted.
-
-eee. GROUPS and FUNCNAME now return an error status when assignment is
- attempted, but may be unset (in which case they lose their special
- properties). In all respects except unsetting, they are readonly.
-
-fff. The string-to-integer conversion code now ignores trailing whitespace in
- the string, even if strtol(3) does not.
-
-ggg. The tcsh magic-space function now does a better job of inserting the
- space close to where the point was before the history expansion, rather
- than just appending it.
-
-hhh. Fixed a bug which caused a file sourced from an interactive shell to
- fill up the jobs table if it ran lots of jobs.
-
-iii. Fixed a bug in the parameter pattern substitution code to avoid infinite
- recursion on zero-length matches.
-
-2. Changes to Readline
-
-a. When setting the terminal attributes on systems using `struct termio',
- readline waits for output to drain before changing the attributes.
-
-b. A fix was made to the history word tokenization code to avoid attempts to
- dereference a null pointer.
-
-c. Readline now defaults rl_terminal_name to $TERM if the calling application
- has left it unset, and tries to initialize with the resultant value.
-
-d. Instead of calling (*rl_getc_function)() directly to get input in certain
- places, readline now calls rl_read_key() consistently.
-
-e. Fixed a bug in the completion code that allowed a backslash to quote a
- single quote inside a single-quoted string.
-
-f. rl_prompt is no longer assigned directly from the argument to readline(),
- but uses memory allocated by readline. This allows constant strings to
- be passed to readline without problems arising when the prompt processing
- code wants to modify the string.
-
-g. Fixed a bug that caused non-interactive history searches to return the
- wrong line when performing multiple searches backward for the same string.
-
-h. Many variables, function arguments, and function return values are now
- declared `const' where appropriate, to improve behavior when linking with
- C++ code.
-
-i. The control character detection code now works better on systems where
- `char' is unsigned by default.
-
-j. The vi-mode numeric argument is now capped at 999999, just like emacs mode.
-
-k. The Function, CPFunction, CPPFunction, and VFunction typedefs have been
- replaced with a set of specific prototyped typedefs, though they are
- still in the readline header files for backwards compatibility.
-
-m. Nearly all of the (undocumented) internal global variables in the library
- now have an _rl_ prefix -- there were a number that did not, like
- screenheight, screenwidth, alphabetic, etc.
-
-n. The ding() convenience function has been renamed to rl_ding(), though the
- old function is still defined for backwards compatibility.
-
-o. The completion convenience functions filename_completion_function,
- username_completion_function, and completion_matches now have an rl_
- prefix, though the old names are still defined for backwards compatibility.
-
-p. The functions shared by readline and bash (linkage is satisfied from bash
- when compiling with bash, and internally otherwise) now have an sh_ prefix.
-
-q. Changed the shared library creation procedure on Linux and BSD/OS 4.x so
- that the `soname' contains only the major version number rather than the
- major and minor numbers.
-
-r. Fixed a redisplay bug that occurred when the prompt spanned more than one
- physical line and contained invisible characters.
-
-3. New Features in Bash
-
-a. Added a new `--init-file' invocation argument as a synonym for `--rcfile',
- per the new GNU coding standards.
-
-b. The /dev/tcp and /dev/udp redirections now accept service names as well as
- port numbers.
-
-c. `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
-
-4. New Features in Readline
-
-a. The blink timeout for paren matching is now settable by applications.
-
-b. _rl_executing_macro has been renamed to rl_executing_macro, which means
- it's now part of the public interface.
-
-c. Readline has a new variable, rl_readline_state, which is a bitmap that
- encapsulates the current state of the library; intended for use by
- callbacks and hook functions.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.04-release,
-and the previous version, bash-2.04-beta5.
-
-1. Changes to Bash
-
-a. Better compile-time and configure-time checks for the necessity of
- inet_aton().
-
-b. A bug was fixed in the expansion of "${@:-}" when there are positional
- parameters.
-
-c. A typo was fixed in the output of `complete'.
-
-d. The matches generated for a word by the `-W' argument to complete and
- compgen are now matched against the word being completed, and only
- matches are returned as the result.
-
-e. Some fixes were made for systems which do not restart read(2) when a
- signal caught by bash is received.
-
-f. A bug was fixed which caused the umask to be set to 0 when an invalid
- symbolic mode mask was parsed.
-
-g. Fixed a bug that could cause a core dump if a SIGCHLD was received while
- performing an assignment statement using command substitution.
-
-h. Changed the word splitting function for programmable completion so cases
- in which the cursor is between words are handled a bit better.
-
-2. Changes to Readline
-
-a. rl_funmap_names() is now documented.
-
-3. New Features in Bash
-
-a. The LC_NUMERIC variable is now treated specially, and used to set the
- LC_NUMERIC locale category for number formatting, e.g., when `printf'
- displays floating-point numbers.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.04-beta5,
-and the previous version, bash-2.04-beta4.
-
-1. Changes to Bash
-
-a. A couple of changes were made to the Makefiles for easier building on
- non-Unix systems.
-
-b. Fixed a bug where the current prompt would be set to $PS2 at startup.
-
-c. The shell script that tests an already-installed version was changed to
- remove the directory it created its test programs in at exit.
-
-d. Several changes were made to the code that tokenizes an input line for
- the programmable completion code. Shell metacharacters will now appear
- as individual words in the word list passed to the completion functions.
- Some of the example completion shell functions were changed to understand
- redirection operators.
-
-e. A bug was fixed that, under obscure circumstances, could confuse the
- parser when a shell function was run by the programmable completion code.
-
-f. A bug was fixed in the ulimit builtin for systems not using getrlimit().
-
-g. The execution code now propagates the correct exit status back to the rest
- of the code if the return value of a subshell command was being inverted.
- Some new test cases for inverting return values with the `!' reserved
- word have been added.
-
-h. Negative exponents in the arithmetic evaluation of v**e now return an
- evaluation error.
-
-i. A bug that caused bash to check the wrong process in a pipeline for
- abnormal termination (and consequently resetting the terminal attributes)
- was fixed.
-
-j. Fixed a bug that caused $PS2 to be displayed after PROMPT_COMMAND was
- executed.
-
-2. Changes to Readline
-
-1. Fixed a bug in a C preprocessor define that caused the keypad control
- functions to be compiled out for all platforms except DJGPP.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.04-beta4,
-and the previous version, bash-2.04-beta3.
-
-1. Changes to Bash
-
-a. A couple of changes were made to the redirection to attempt to avoid
- race conditions and malicious file replacement.
-
-2. A change was made to the string evaluation code (used for command
- substitution, `eval', and the `.' builtin) to fix an obscure core
- dump on alpha machines.
-
-3. A bug that caused $LINENO to be wrong when executing arithmetic for
- commands was fixed.
-
-4. A couple of memory leaks in the programmable completion code were fixed.
-
-5. A bug that could cause a core dump by freeing memory twice during a call
- to `eval' if `set -u' had been enabled and an undefined variable was
- referenced was fixed.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.04-beta3,
-and the previous version, bash-2.04-beta2.
-
-1. Changes to Bash
-
-a. Bash should run the appropriate startup files when invoked by ssh2.
-
-b. Fixed a bug in the parsing of conditional commands that could cause a
- core dump.
-
-c. Fixed a bug in parsing job specifications that occasionally caused
- core dumps when an out-of-range job was referenced.
-
-d. Fixed the `type' and `command' builtins to do better reporting of
- commands that are not found in $PATH or the hash table.
-
-e. Fixed a POSIX.2 compliance problem in the command builtin -- commands
- are supposed to be reported as full pathnames.
-
-f. The `echo' builtin now returns failure if a write error occurs.
-
-g. Fixed a bug which caused the locale to not be reset correctly when
- LC_ALL was unset.
-
-h. Changed description of `getopts' in man page and reference manual to make
- it clear that option characters may be characters other than letters.
-
-i. If the shell exits while in a function, make sure that any trap on EXIT
- doesn't think the function is still executing.
-
-j. Bashbug now tries harder to find a usable editor if $EDITOR is not set,
- rather than simply defaulting to `emacs'.
-
-k. Changes to the scripts that guess and canonicalize the system type, from
- the latest `automake' distribution via Debian.
-
-l. When using named pipes for process substitution, make sure the file
- descriptors opened for reading are set to non-blocking mode.
-
-m. Fixed a bug that caused termination of pipelines that are killed by a
- signal to not be reported in some cases.
-
-n. When not in literal-history mode, shell comment lines are not added to
- the history list.
-
-o. When running in POSIX.2 mode, bash no longer performs word splitting on
- the expanded value of the word supplied as the filename argument to
- redirection operators.
-
-p. The prompt string decoding code now backslash-quotes only characters that
- are special within double quotes when expanding the \w and \W escape
- sequences.
-
-q. Fixed a bug in the prompt decoding code that could cause a non-interactive
- shell to seg fault if `\u' was used in PS4 and the shell was in xtrace
- mode.
-
-r. Fixed a bug that caused function definitions to be printed with any
- redirections that should be attached to the entire function before the
- closing brace.
-
-s. Changed the tilde expansion code for Cygwin systems to avoid creating
- pathnames beginning with `//' if $HOME == `/'.
-
-t. Fixed a couple of autoconf tests to avoid creating files with fixed names
- in /tmp.
-
-u. The `trap' and `kill' builtins now know the names of the POSIX.1b real-
- time signals on systems which support them.
-
-2. Changes to Readline
-
-a. Fixed a problem with the single-quote quoting function that could cause
- buffer overflows.
-
-b. Fixed a bug that caused incorrect `stat characters' to be printed if
- the files being completed were in the root directory and visible-stats
- was enabled.
-
-3. New Features in Bash
-
-a. There is a new `rbash.1' manual page, from the Debian release.
-
-b. The `--enable-usg-echo-default' option to `configure' has been renamed to
- `--enable-xpg-echo-default'. The old option is still there for backwards
- compatibility.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.04-beta2,
-and the previous version, bash-2.04-beta1.
-
-1. Changes to Bash
-
-a. Fixed a bug that could cause pipes to be closed inappropriately in
- some obscure cases.
-
-b. Fixed a bug that caused creation of the exported environment to clobber
- the current command string if there were any exported shell functions.
-
-c. Some changes were made to reduce bash's memory usage.
-
-d. Fixed a problem with programmable completion and filenames to be
- completed containing quote characters.
-
-e. Changed the code the removes named pipes created for the <(...) and >(...)
- expansions to defer removal until after any current shell function has
- finished executing.
-
-f. Fixed a bug in `select' which caused it to not handle the `continue'
- builtin correctly.
-
-g. Autoconf tests added for cygwin32 and mingw32.
-
-2. New Features in Bash
-
-a. The `--with-bash-malloc' configure option replaces `--with-gnu-malloc'
- (which is still there for backwards compatibility).
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.04-beta1,
-and the previous version, bash-2.04-alpha1.
-
-1. Changes to Bash
-
-a. Fixed a bug in the programmable completion code that occurred when
- trying to complete command lines containing a `;' or `@'.
-
-b. The file descriptor from which the shell is reading a script is now
- moved to a file descriptor above the user-addressible range.
-
-c. Changes to `printf' so that it can handle integers beginning with 0
- or 0x as octal and hex, respectively.
-
-d. Fixes to the programmable completion code so it handles nonsense like
- `compgen -C xyz' gracefully.
-
-e. The shell no longer modifies the signal handler for SIGPROF, allowing
- profiling again on certain systems.
-
-f. The shell checks for a new window size, if the user has requested it,
- after a process exits due to a signal.
-
-g. Fixed a bug with variables with null values in a program's temporary
- environment and the bash getenv() replacement.
-
-h. `declare' and the other builtins that take variable assignments as
- arguments now honor `set -a' and mark modified variables for export.
-
-i. Some changes were made for --dump-po-strings mode when writing strings
- with embedded newlines.
-
-j. The code that caches export strings from the initial environment now
- duplicates the string rather than just pointing into the environment.
-
-k. The filename completion quoting code now uses single quotes by default
- if the filename being completed contains newlines, since \<newline>
- has a special meaning to the parser.
-
-l. Bash now uses typedefs bits32_t and u_bits32_t instead of int32_t and
- u_int32_t, respectively to avoid conflicts on certain Unix versions.
-
-m. Configuration changes were made for: Rhapsody, Mac OS, FreeBSD-3.x.
-
-n. Fixed a problem with hostname-to-ip-address translation in the
- /dev/(tcp|udp)/hostname/port redirection code.
-
-o. The texinfo manual has been reorganized slightly.
-
-p. Filename generation (globbing) range comparisons in bracket expressions
- no longer use strcoll(3) even if it is available, since it has unwanted
- effects in certain locales.
-
-q. Fixed a cosmetic problem in the source that caused the shell to not
- compile if DPAREN_ARITHMETIC was not defined but ARITH_FOR_COMMAND was.
-
-r. Fixed a bug in the here-document code tripped when the file descriptor
- opened to the file containing the text of the here document was the
- same as a redirector specified by the user.
-
-s. Fixed a bug where the INVERT_RETURN flag was not being set for `pipeline'
- in `time ! pipeline'.
-
-t. Fixed a bug with the `wait' builtin which manifested itself when an
- interrupt was received while the shell was waiting for asynchronous
- processes in a shell script.
-
-u. Fixed the DEBUG trap code so that it has the correct value of $?.
-
-v. Fixed a bug in the parameter pattern substitution code that could cause
- the shell to attempt to free unallocated memory if the pattern started
- with `/' and an expansion error occurs.
-
-w. Fixed a bug in the positional parameter substring code that could
- cause the shell to loop freeing freed memory.
-
-x. Fixed a bug in the positional parameter pattern substitution code so
- that it correctly handles null replacement strings with a pattern
- string prefixed with `%' or `#'.
-
-y. The shell no longer attempts to import functions from the environment if
- started with `-n'.
-
-z. Fixed a bug that caused `return' in a command substitution executed in
- a shell function to return from the function in a subshell and continue
- execution.
-
-aa. `hash -p /pathname/with/slashes name' is no longer allowed when the shell
- is restricted.
-
-bb. The wait* job control functions now behave better if called when there
- are no unwaited-for children.
-
-cc. Command substitution no longer unconditionally disables job control in
- the subshell started to run the command.
-
-dd. A bug was fixed that occasionally caused traps to mess up the parser
- state.
-
-ee. `bashbug' now honors user headers in the mail message it sends.
-
-ff. A bug was fixed that caused the `:p' history modifier to not print the
- history expansion if the `histverify' option was set.
-
-2. Changes to Readline
-
-a. Fixed a bug in the redisplay code for lines with more than 256 line
- breaks.
-
-b. A bug was fixed which caused invisible character markers to not be
- stripped from the prompt string if the terminal was in no-echo mode.
-
-c. Readline no longer tries to get the variables it needs for redisplay
- from the termcap entry if the calling application has specified its
- own redisplay function. Readline treats the terminal as `dumb' in
- this case.
-
-d. Fixes to the SIGWINCH code so that a multiple-line prompt with escape
- sequences is redrawn correctly.
-
-3. New Features in Bash
-
-a. `bashbug' now accepts `--help' and `--version' options.
-
-b. There is a new `xpg_echo' option to `shopt' that controls the behavior
- of echo with respect to backslash-escaped characters at runtime.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.04-alpha1,
-and the previous version, bash-2.04-devel.
-
-1. Changes to Bash
-
-a. Fixed a bug that could cause core dumps when performing substring
- expansion.
-
-b. Shared object configuration changes for: Solaris, OSF/1
-
-c. The POSIX_GLOB_LIBRARY code that uses the POSIX.2 globbing facilities
- for pathname expansion now understands GLOBIGNORE.
-
-d. The code that implements `eval' was changed to save the value of the
- current prompt, so an eval in a shell function called by the programmable
- completion code will not change the prompt to $PS2.
-
-e. Restored the undocumented NON_INTERACTIVE_LOGIN_SHELLS #define to
- config-top.h. If this is defined, all login shells will read the
- startup files, not just interactive and non-interactive started with
- the `--login' option.
-
-f. Fixed a bug that caused the expansion code to occasionally dump core if
- IFS contained characters > 128.
-
-g. Fixed a problem with the grammar so that a newline is not required
- after the `))' in the new-style arithmetic for statement; a semicolon
- may be used as expected.
-
-h. Variable indirection may now reference the shell's special variables.
-
-i. The $'...' and $"..." constructs are now added to the history correctly
- if they contain newlines and command-oriented history is enabled.
-
-j. It is now an error to try to assign a value to a function-local copy
- of a readonly shell variable (declared with the `local' builtin).
-
-2. Changes to Readline
-
-a. The history file code now uses O_BINARY mode when reading and writing
- the history file on cygwin32.
-
-3. New Features in Bash
-
-a. A new programmable completion facility, with two new builtin commands:
- complete and compgen.
-
-b. configure has a new option, `--enable-progcomp', to compile in the
- programmable completion features (enabled by default).
-
-c. `shopt' has a new option, `progcomp', to enable and disable programmable
- completion at runtime.
-
-d. Unsetting HOSTFILE now clears the list of hostnames used for completion.
-
-4. New Features in Readline
-
-a. A new variable, rl_gnu_readline_p, always 1. The intent is that an
- application can verify whether or not it is linked with the `real'
- readline library or some substitute.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.04-devel,
-and the previous version, bash-2.03-release.
-
-1. Changes to Bash
-
-a. System-specific configuration and source changes for: Interix, Rhapsody
-
-b. Fixed a bug in execute_cmd.c that resulted in a compile-time error if
- JOB_CONTROL was not defined.
-
-c. An obscure race condition in the trap code was fixed.
-
-d. The string resulting from $'...' is now requoted to avoid any further
- expansion.
-
-e. The $'...' quoting syntax now allows backslash to escape a single quote,
- for ksh-93 compatibility.
-
-f. The $"..." quoting syntax now escapes backslashes and double quotes in
- the translated string when displaying them with the --dump-po-strings
- option.
-
-g. `echo -e' no longer converts \' to '.
-
-h. Fixes were made to the extended globbing code to handle embedded (...)
- patterns better.
-
-i. Some improvements were made to the code that unsets `nodelay' mode on
- the file descriptor from which bash is reading input.
-
-j. Some changes were made to the replacement termcap library for better
- operation on MS-DOS.
-
-k. Some changes were made to the tilde expansion code to handle backslash
- as a pathname separator on MS-DOS.
-
-l. The source has been reorganized a little bit -- there is now an `include'
- subdirectory, and lib/posixheaders has been removed.
-
-m. Improvements were made to the `read' builtin so that it makes many
- fewer read(2) system calls.
-
-n. The expansion of $- will include `c' and `s' when those options are
- supplied at shell invocation.
-
-o. Several improvments were made to the completion code: variable completion
- now works better when there are unterminated expansions, command
- completion understands quotes better, and completion now works in certain
- unclosed $(... constructs.
-
-p. The arithmetic expansion code was fixed to not need the value of a
- variable being assigned a value (fixes the "ss=09; let ss=10" bug).
-
-q. Some changes were made to make exported environment creation faster.
-
-r. The html documentation will be installed into $(htmldir) if that variable
- has a value when `make install' is run.
-
-s. Fixed a bug that would cause the bashrc file to be sourced inappropriately
- when bash is started by sshd.
-
-t. The SSH_CLIENT environment variable is no longer auto-exported.
-
-u. A bug that caused redirections with (...) subshells to be performed in
- the wrong order was fixed.
-
-v. A bug that occasionally caused inappropriate expansion of assignment
- statements in compound array assignments was fixed.
-
-w. The code that parses the words in a compound array assignment was
- simplified considerably and should work better now.
-
-x. Fixes to the non-job-control code in nojobs.c to make it POSIX.2-compliant
- when a user attempts to retrieve the status of a terminated background
- process.
-
-y. Fixes to the `printf' builtin so that it doesn't try to expand all
- backslash escape sequences in the format string before parsing it for
- % format specifiers.
-
-2. Changes to Readline
-
-a. The history library tries to truncate the history file only if it is a
- regular file.
-
-b. A bug that caused _rl_dispatch to address negative array indices on
- systems with signed chars was fixed.
-
-c. rl-yank-nth-arg now leaves the history position the same as when it was
- called.
-
-d. Changes to the completion code to handle MS-DOS drive-letter:pathname
- filenames.
-
-e. Completion is now case-insensitive by default on MS-DOS.
-
-f. Fixes to the history file manipulation code for MS-DOS.
-
-g. Readline attempts to bind the arrow keys to appropriate defaults on MS-DOS.
-
-h. Some fixes were made to the redisplay code for better operation on MS-DOS.
-
-i. The quoted-insert code will now insert tty special chars like ^C.
-
-j. A bug was fixed that caused the display code to reference memory before
- the start of the prompt string.
-
-k. More support for __EMX__ (OS/2).
-
-l. A bug was fixed in readline's signal handling that could cause infinite
- recursion in signal handlers.
-
-m. A bug was fixed that caused the point to be less than zero when rl_forward
- was given a very large numeric argument.
-
-n. The vi-mode code now gets characters via the application-settable value
- of rl_getc_function rather than calling rl_getc directly.
-
-3. New Features in Bash
-
-a. The history builtin has a `-d offset' option to delete the history entry
- at position `offset'.
-
-b. The prompt expansion code has two new escape sequences: \j, the number of
- active jobs; and \l, the basename of the shell's tty device name.
-
-c. The `bind' builtin has a new `-x' option to bind key sequences to shell
- commands.
-
-d. There is a new shell option, no_empty_command_completion, which, when
- enabled, disables command completion when TAB is typed on an empty line.
-
-e. The `help' builtin has a `-s' option to just print a builtin's usage
- synopsys.
-
-f. There are several new arithmetic operators: id++, id-- (variable
- post-increment/decrement), ++id, --id (variabl pre-increment/decrement),
- expr1 , expr2 (comma operator).
-
-g. There is a new ksh-93 style arithmetic for command:
- for ((expr1 ; expr2; expr3 )); do list; done
-
-h. The `read' builtin has a number of new options:
- -t timeout only wait timeout seconds for input
- -n nchars only read nchars from input instead of a full line
- -d delim read until delim rather than newline
- -s don't echo input chars as they are read
-
-i. The redirection code now handles several filenames specially:
- /dev/fd/N, /dev/stdin, /dev/stdout, and /dev/stderr, whether or
- not they are present in the file system.
-
-j. The redirection code now recognizes pathnames of the form
- /dev/tcp/host/port and /dev/udp/host/port, and tries to open a socket
- of the appropriate type to the specified port on the specified host.
-
-k. The ksh-93 ${!prefix*} expansion, which expands to the names of all
- shell variables whose names start with prefix, has been implemented.
-
-l. There is a new dynamic variable, FUNCNAME, which expands to the name of
- a currently-executing function. Assignments to FUNCNAME have no effect.
-
-m. The GROUPS variable is no longer readonly; assignments to it are silently
- discarded. This means it can be unset.
-
-4. New Features in Readline
-
-a. Parentheses matching is now always compiled into readline, and enabled
- or disabled when the value of the `blink-matching-paren' variable is
- changed.
-
-b. MS-DOS systems now use ~/_inputrc as the last-ditch inputrc filename.
-
-c. MS-DOS systems now use ~/_history as the default history file.
-
-d. history-search-{forward,backward} now leave the point at the end of the
- line when the string to search for is empty, like
- {reverse,forward}-search-history.
-
-e. history-search-{forward,backward} now leave the last history line found
- in the readline buffer if the second or subsequent search fails.
-
-f. New function for use by applications: rl_on_new_line_with_prompt, used
- when an application displays the prompt itself before calling readline().
-
-g. New variable for use by applications: rl_already_prompted. An application
- that displays the prompt itself before calling readline() must set this to
- a non-zero value.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.03-release,
-and the previous version, bash-2.03-beta2.
-
-1. Changes to Bash
-
-a. A file descriptor leak in the `fc' builtin was fixed.
-
-b. A bug was fixed in the `read' builtin that caused occasional spurious
- failures when using `read -e'.
-
-c. The version code needed to use the value of the cpp variable
- CONF_MACHTYPE rather than MACHTYPE.
-
-d. A new test was added to exercise the command printing and copying code.
-
-e. A bug was fixed that caused `time' to be recognized as a reserved word
- if it was the first pattern in a `case' statement pattern list.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.03-beta2,
-and the previous version, bash-2.03-beta1.
-
-1. Changes to Bash
-
-a. Slight additions to support/shobj-conf, mostly for the benefit of AIX 4.2.
-
-b. config.{guess,sub} support added for the NEC SX4.
-
-c. Changed some of the cross-compiling sections of the configure macros in
- aclocal.m4 so that configure won't abort.
-
-d. Slight changes to how the HTML versions of the bash and readline manuals
- are generated.
-
-e. Fixed conditional command printing to avoid interpreting printf `%'-escapes
- in arguments to [[.
-
-f. Don't include the bash malloc on all variants of the alpha processor.
-
-g. Changes to configure to make --enable-profiling work on Solaris 2.x.
-
-h. Fixed a bug that manifested itself when shell functions were called
- between calls to `getopts'.
-
-i. Fixed pattern substitution so that a bare `#'as a pattern causes the
- replacement string to be prefixed to the search string, and a bare
- `%' causes the replacement string to be appended to the search string.
-
-j. Fixed a bug in the command execution code that caused child processes
- to occasionally have the wrong value for $!.
-
-2. Changes to Readline
-
-a. Added code to the history library to catch history substitutions using
- `&' without a previous history substitution or search having been
- performed.
-
-3. New Features in Bash
-
-4. New Features in Readline
-
-a. New bindable variable: `isearch-terminators'.
-
-b. New bindable function: `forward-backward-delete-char' (unbound by default).
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.03-beta1,
-and the previous version, bash-2.03-alpha.
-
-1. Changes to Bash
-
-a. A change was made to the help text for `{...}' to make it clear that a
- semicolon is required before the closing brace.
-
-b. A fix was made to the `test' builtin so that syntax errors cause test
- to return an exit status > 1.
-
-c. Globbing is no longer performed on assignment statements that appear as
- arguments to `assignment builtins' such as `export'.
-
-d. System-specific configuration changes were made for: Rhapsody,
- AIX 4.2/gcc, BSD/OS 4.0.
-
-e. New loadable builtins: ln, unlink.
-
-f. Some fixes were made to the globbing code to handle extended glob patterns
- which immediately follow a `*'.
-
-g. A fix was made to the command printing code to ensure that redirections
- following compound commands have a space separating them from the rest
- of the command.
-
-h. The pathname canonicalization code was changed to produce fewer leading
- `//' sequences, since those are interpreted as network file system
- pathnames on some systems.
-
-i. A fix was made so that loops containing `eval' commands in commands passed
- to `bash -c' would not exit prematurely.
-
-j. Some changes were made to the job reaping code when the shell is not
- interactive, so the shell will retain exit statuses longer for examination
- by `wait'.
-
-k. A fix was made so that `jobs | command' works again.
-
-l. The erroneous compound array assignment var=((...)) is now a syntax error.
-
-m. A change was made to the dynamic loading code in `enable' to support
- Tenon's MachTen.
-
-n. A fix was made to the globbing code so that extended globbing patterns
- will correctly match `.' in a bracket expression.
-
-2. Changes to Readline
-
-a. A fix was made to the completion code in which a typo caused the wrong
- value to be passed to the function that computed the longest common
- prefix of the list of matches.
-
-b. The completion code now checks the value of rl_filename_completion_desired,
- which is set by application-supplied completion functions to indicate
- that filename completion is being performed, to decide whether or not to
- call an application-supplied `ignore completions' function.
-
-3. New Features in Bash
-
-a. A change was made to the startup file code so that any shell begun with
- the `--login' option, even non-interactive shells, will source the login
- shell startup files.
-
-4. New Features in Readline
-
-a. A new variable, rl_erase_empty_line, which, if set by an application using
- readline, will cause readline to erase, prompt and all, lines on which the
- only thing typed was a newline.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.03-alpha,
-and the previous version, bash-2.02.1-release.
-
-1. Changes to Bash
-
-a. System-specific configuration changes were made for: Irix 6.x, Unixware 7.
-
-b. The texi2dvi and texi2html scripts were updated to the latest versions
- from the net.
-
-c. The configure tests that determine which native type is 32 bits were
- changed to not require a compiled program.
-
-d. Fixed a bug in shell_execve that could cause memory to be freed twice
- after a failed exec.
-
-e. The `printf' test uses `diff -a' if it's available to prevent confusion
- due to the non-ascii output.
-
-f. Shared object configuration is now performed by a shell script,
- support/shobj-conf, which generates values to be substituted into
- makefiles by configure.
-
-g. Some changes were made to `ulimit' to avoid the use of RLIM_INVALID as a
- return value.
-
-h. Changes were made to `ulimit' to work around HPUX 9.x's peculiar
- handling of RLIMIT_FILESIZE.
-
-i. Some new loadable builtins were added: id, printenv, sync, whoami, push,
- mkdir. `pushd', `popd', and `dirs' can now be built as regular or
- loadable builtins from the same source file.
-
-j. Changes were made to `printf' to handle NUL bytes in the expanded format
- string.
-
-k. The various `make clean' Makefile targets now descend into lib/sh.
-
-l. The `type' builtin was changed to use the internal `getopt' so that things
- like `type -ap' work as expected.
-
-m. There is a new configuration option, --with-installed-readline, to link
- bash with a locally-installed version of readline. Only readline version
- 4.0 and later releases can support this. Shared and static libraries
- are supported. The installed include files are used.
-
-n. There is a new autoconf macro used to find which basic type is 64 bits.
-
-o. Dynamic linking and loadable builtins should now work on SCO 3.2v5*,
- AIX 4.2 with gcc, Unixware 7, and many other systems using gcc, where
- the `-shared' options works correctly.
-
-p. A bug was fixed in the bash filename completion code that caused memory to
- be freed twice if a directory name containing an unset variable was
- completed and the -u option was set.
-
-q. The prompt expansion code now quotes the `$' in the `\$' expansion so it
- is not processed by subsequent parameter expansion.
-
-r. Fixed a parsing bug that caused a single or double quote after a `$$' to
- trigger ANSI C expansion or locale translation.
-
-s. Fixed a bug in the globbing code that caused quoted filenames containing
- no globbing characters to sometimes be incorrectly expanded.
-
-t. Changes to the default prompt strings if prompt string decoding is not
- compiled into the shell.
-
-u. Added `do', `then', `else', `{', and `(' to the list of keywords that may
- precede the `time' reserved word.
-
-v. The shell may now be cross-built for BeOS as well as cygwin32.
-
-w. The conditional command execution code now treats `=' the same as `=='
- for deciding when to perform pattern matching.
-
-x. The `-e' option no longer causes the shell to exit if a command exits
- with a non-zero status while running the startup files.
-
-y. The `printf' builtin no longer dumps core if a modifier is supplied in
- the format string without a conversion character (e.g. `%h').
-
-z. Array assignments of the form a=(...) no longer show up in the history
- list.
-
-aa. The parser was fixed to obey the POSIX.2 rules for finding the closing
- `}' in a ${...} expression.
-
-bb. The history file is now opened with mode 0600 rather than 0666, so bash
- no longer relies on the user's umask being set appropriately.
-
-cc. Setting LANG no longer causes LC_ALL to be assigned a value; bash now
- relies on proper behavior from the C library.
-
-dd. Minor changes were made to allow quoted variable expansions using
- ${...} to be completed correctly if there is no closing `"'.
-
-ee. Changes were made to builtins/Makefile.in so that configuring the shell
- with `--enable-profiling' works right and builtins/mkbuiltins is
- generated.
-
-2. Changes to Readline
-
-a. The version number is now 4.0.
-
-b. There is no longer any #ifdef SHELL code in the source files.
-
-c. Some changes were made to the key binding code to fix memory leaks and
- better support Win32 systems.
-
-d. Fixed a silly typo in the paren matching code -- it's microseconds, not
- milliseconds.
-
-e. The readline library should be compilable by C++ compilers.
-
-f. The readline.h public header file now includes function prototypes for
- all readline functions, and some changes were made to fix errors in the
- source files uncovered by the use of prototypes.
-
-g. The maximum numeric argument is now clamped at 1000000.
-
-h. Fixes to rl_yank_last_arg to make it behave better.
-
-i. Fixed a bug in the display code that caused core dumps if the prompt
- string length exceeded 1024 characters.
-
-j. The menu completion code was fixed to properly insert a single completion
- if there is only one match.
-
-k. A bug was fixed that caused the display code to improperly display tabs
- after newlines.
-
-3. New Features in Bash
-
-a. New `shopt' option, `restricted_shell', indicating whether or not the
- shell was started in restricted mode, for use in startup files.
-
-b. Filename generation is now performed on the words between ( and ) in
- array assignments (which it probably should have done all along).
-
-c. OLDPWD is now auto-exported, as POSIX.2 seems to require.
-
-d. ENV and BASH_ENV are read-only variables in a restricted shell.
-
-4. New Features in Readline
-
-a. Many changes to the signal handling:
- o Readline now catches SIGQUIT and cleans up the tty before returning;
- o A new variable, rl_catch_signals, is available to application writers
- to indicate to readline whether or not it should install its own
- signal handlers for SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP,
- SIGTTIN, and SIGTTOU;
- o A new variable, rl_catch_sigwinch, is available to application
- writers to indicate to readline whether or not it should install its
- own signal handler for SIGWINCH, which will chain to the calling
- applications's SIGWINCH handler, if one is installed;
- o There is a new function, rl_free_line_state, for application signal
- handlers to call to free up the state associated with the current
- line after receiving a signal;
- o There is a new function, rl_cleanup_after_signal, to clean up the
- display and terminal state after receiving a signal;
- o There is a new function, rl_reset_after_signal, to reinitialize the
- terminal and display state after an application signal handler
- returns and readline continues
-
-b. There is a new function, rl_resize_terminal, to reset readline's idea of
- the screen size after a SIGWINCH.
-
-c. New public functions: rl_save_prompt and rl_restore_prompt. These were
- previously private functions with a `_' prefix.
-
-d. New function hook: rl_pre_input_hook, called just before readline starts
- reading input, after initialization.
-
-e. New function hook: rl_display_matches_hook, called when readline would
- display the list of completion matches. The new function
- rl_display_match_list is what readline uses internally, and is available
- for use by application functions called via this hook.
-
-f. New bindable function, delete-char-or-list, like tcsh.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.02.1-release,
-and the previous version, bash-2.02-release.
-
-1. Changes to Bash
-
-a. A bug that caused the bash readline support to not compile unless aliases
- and csh-style history were configured into the shell was fixed.
-
-b. Fixed a bug that could cause a core dump when here documents contained
- more than 1000 characters.
-
-c. Fixed a bug that caused a CDPATH entry of "" to not be treated the same
- as the current directory when in POSIX mode.
-
-d. Fixed an alignment problem with the memory returned by the bash malloc,
- so returned memory is now 64-bit aligned.
-
-e. Fixed a bug that caused command substitutions executed within pipelines
- to put the terminal in the wrong process group.
-
-f. Fixes to support/config.sub for: alphas, SCO Open Server and Open Desktop,
- Unixware 2, and Unixware 7.
-
-g. Fixes to the pattern matching code to make it work correctly for eight-bit
- characters.
-
-h. Fixed a problem that occasionally caused the shell to display the wrong
- value for the new working directory when changing to a directory found
- in $CDPATH when in physical mode.
-
-i. Fixed a bug that caused core dumps when using conditional commands in
- shell functions.
-
-j. Fixed a bug that caused the printf builtin to loop forever if the format
- string did not consume any of the arguments.
-
-k. Fixed a bug in the parameter expansion code that caused "$@" to be
- incorrectly split if $IFS did not contain a space character.
-
-l. Fixed a bug that could cause a core dump when completing hostnames if
- the number of matching hostnames was an exact multiple of 16.
-
-m. Fixed a bug that caused the shell to fork too early when a command
- such as `%2 &' was given.
-
-2. Changes to Readline
-
-a. Fixed a problem with redisplay that showed up when the prompt string was
- longer than the screen width and the prompt contained invisible characters.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.02-release,
-and the previous version, bash-2.02-beta2.
-
-1. Changes to Bash
-
-a. A bug was fixed that caused the terminal process group to be set
- incorrectly when performing command substitution of builtins in a
- pipeline.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.02-beta2,
-and the previous version, bash-2.02-beta1.
-
-1. Changes to Bash
-
-a. Attempting to `wait' for stopped jobs now generates a warning message.
-
-b. Pipelines which exit due to SIGPIPE in non-interactive shells are now
- not reported if the shell is compiled -DDONT_REPORT_SIGPIPE.
-
-c. Some changes were made to builtins/psize.sh and support/bashbug.sh to
- attempt to avoid some /tmp file races and surreptitious file
- substitutions.
-
-d. Fixed a bug that caused the shell not to compile if configured with
- dparen arithmetic but without aliases.
-
-e. Fixed a bug that caused the input stream to be switched when assigning
- empty arrays with `bash -c'.
-
-f. A bug was fixed in the readline expansion glue code that caused bash to
- dump core when expanding lines with an unclosed single quote.
-
-g. A fix was made to the `cd' builtin so that using a non-empty directory
- from $CDPATH results in an absolute pathname of the new current working
- directory to be displayed after the current directory is changed.
-
-h. Fixed a bug in the variable assignment code that caused the shell to
- dump core when referencing an unset variable with `set -u' enabled in
- an assignment statement preceding a command.
-
-i. Fixed a bug in the exit trap code that caused reserved words to not be
- recognized under certain circumstances.
-
-j. Fixed a bug in the parameter pattern substitution code so that quote
- removal is performed.
-
-k. The shell should now configure correctly on Apple Rhapsody systems.
-
-l. The `kill' builtin now prints a usage message if it is not passed any
- arguments.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.02-beta1,
-and the previous version, bash-2.02-alpha1.
-
-1. Changes to Bash
-
-a. A few compilation bugs were fixed in the new extended globbing code.
-
-b. Executing arithmetic commands now sets the command name to `((' so
- error messages look right.
-
-c. Fixed some build problems with various configuration options.
-
-d. The `printf' builtin now aborts immediately if an illegal format
- character is encountered.
-
-e. The code that creates here-documents now behaves better if the file it's
- trying to create already exists for some reason.
-
-f. Fixed a problem with the extended globbing code that made patterns like
- `x+*' expand incorrectly.
-
-g. The prompt string expansion code no longer quotes tildes with backslashes.
-
-h. The bash getcwd() implementation in lib/sh/getcwd.c now behaves better in
- the presence of lstat(2) failures.
-
-i. Fixed a bug with strsub() that caused core dumps when executing `fc -s'.
-
-j. The mail checking code now ensures that it has a valid default mailpath.
-
-k. A bug was fixed that caused local variables to be unset inappropriately
- when sourcing a script from within another sourced script.
-
-l. A bug was fixed in the history saving code so that functions are saved
- in the history list correctly if `cmdhist' is enabled, but `lithist'
- is not.
-
-m. A bug was fixed that caused printf overflows when displaying error
- messages.
-
-n. It should be easier to build the loadble builtins in examples/loadables,
- though some manual editing of the generated Makefile is still required.
-
-o. The user's primary group is now always ${GROUPS[0]}.
-
-p. Some updates were made to support/config.guess from the GNU master copy.
-
-q. Some changes were made to the autoconf support for Solaris 2.6 large
- files.
-
-r. The `command' builtins now does the right thing when confstr(3) cannot
- find a value for _CS_PATH.
-
-s. Extended globbing expressions like `*.!(c)' are not history expanded if
- `extglob' is enabled.
-
-t. Using the `-P' option to `cd' will force the value that is assigned to
- PWD to not contain any symbolic links.
-
-2. Changes to Readline
-
-a. The code that prints completion listings now behaves better if one or
- more of the filenames contains non-printable characters.
-
-b. The time delay when showing matching parentheses is now 0.5 seconds.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.02-alpha1,
-and the previous version, bash-2.01.1-release.
-
-1. Changes to Bash
-
-a. OS-specific configuration changes for: BSD/OS 3.x, Minix 2.x,
- Solaris 2.6, SINIX SVR4.
-
-b. Changes were made to the generated `info' files so that `install-info'
- works correctly.
-
-c. PWD is now auto-exported.
-
-d. A fix was made to the pipeline code to make sure that the shell forks
- to execute simple commands consisting solely of assignment statements.
-
-e. Changes to the test suite for systems with 14-character filenames.
-
-f. The default sizes of some internal hash tables have been made smaller
- to reduce the shell's memory footprint.
-
-g. The `((...))' arithmetic command is now executed directly instead of
- being translated into `let "..."'.
-
-h. Fixes were made to the expansion code so that "$*", "$@", "${array[@]}",
- and "${array[@]}" expand correctly when IFS does not contain a space
- character, is unset, or is set to NULL.
-
-i. The indirect expansion code (${!var}) was changed so that the only
- valid values of `var' are variable names, positional parameters, `#',
- `@', and `*'.
-
-j. An arithmetic expression error in a $((...)) expansion now causes a
- non-interactive shell running in posix mode to exit.
-
-k. Compound array assignment now splits the words within the parentheses
- on shell metacharacters like the parser would before expansing them
- and performing the assignment. This is for compatibility with ksh-93.
-
-l. The internal shell backslash-quoting code (used in the output of `set'
- and completion) now quotes tildes if they appear at the start of the
- string or after a `=' or `:'.
-
-m. A couple of bugs with `shopt -o' were fixed.
-
-n. `bash +o' now displays the same output as `set +o' before starting an
- interactive shell.
-
-o. A bug that caused command substitution and the `eval' builtin to
- occasionally free memory twice when an error was encountered was fixed.
-
-p. The filename globbing code no longer requires read permission for a
- directory when the filename to be matched does not contain any globbing
- characters, as POSIX.2 specifies.
-
-q. A bug was fixed so that the job containing the last asynchronous
- process is not removed from the job table until a `wait' is executed
- for that process or another asynchronous process is started. This
- satisfies a POSIX.2 requirement.
-
-r. A `select' bug was fixed so that a non-numeric user response is treated
- the same as a numeric response that is out of range.
-
-s. The shell no longer parses the value of SHELLOPTS from the environment
- if it is restricted, running setuid, or running in `privileged mode'.
-
-t. Fixes were made to enable large file support on systems such as
- Solaris 2.6, where the size of a file may be larger than can be held
- in an `int'.
-
-u. The filename hashing code was fixed to not add `./' to the beginning of
- filenames which already begin with `./'.
-
-v. The configure script was changed so that the GNU termcap library is not
- compiled in if `prefer-curses' has been specified.
-
-w. HISTCONTROL and HISTIGNORE are no longer applied to the second and
- subsequent lines of a multi-line command.
-
-x. A fix was made to `disown' so that it does a better job of catching
- out-of-range jobs.
-
-y. Non-interactive shells no longer report the status of processes terminated
- due to SIGINT, even if the standard output is a terminal.
-
-z. A bug that caused the output of `jobs' to have extra carriage returns
- was fixed.
-
-aa. A bug that caused PIPESTATUS to not be set when builtins or shell
- functions were executed in the foreground was fixed.
-
-bb. Bash now attempts to detect when it is being run by sshd, and treats
- that case identically to being run by rshd.
-
-cc. A bug that caused `set -a' to export SHELLOPTS when one of the shell
- options was changed was fixed.
-
-dd. The `kill' builtin now disallows empty or missing process id arguments
- instead of treating them as identical to `0', which means the current
- process.
-
-ee. `var=value declare -x var' now behaves identically to
- `var=value export var'. Similarly for `var=value declare -r var' and
- `var=value readonly var'.
-
-ff. A few memory leaks were fixed.
-
-gg. `alias' and `unalias' now print error messages when passed an argument
- that is not an alias for printing or deletion, even when the shell is
- not interactive, as POSIX.2 specifies.
-
-hh. `alias' and `alias -p' now return a status of 0 when no aliases are
- defined, as POSIX.2 specifes.
-
-ii. `cd -' now prints the pathname of the new working directory if the shell
- is interactive.
-
-jj. A fix was made so that the code that binds $PWD now copes with getcwd()
- returning NULL.
-
-kk. `unset' now checks whether or not a function name it's trying to unset
- is a valid shell identifier only when the shell is running in posix mode.
-
-ll. A change was made to the code that generates filenames for here documents
- to make them less prone to name collisions.
-
-mm. The parser was changed so that `time' is recognized as a reserved word
- only at the beginning of a pipeline.
-
-nn. The pathname canonicalization code was changed so that `//' is converted
- into `/', but all other pathnames beginning with `//' are left alone, as
- POSIX.2 specifies.
-
-oo. The `logout' builtin will no longer exit a non-interactive non-login
- shell.
-
-2. Changes to Readline
-
-a. Fixed a problem in the readline test program rltest.c that caused a core
- dump.
-
-b. The code that handles parser directives in inputrc files now displays
- more error messages.
-
-c. The history expansion code was fixed so that the appearance of the
- history comment character at the beginning of a word inhibits history
- expansion for that word and the rest of the input line.
-
-3. New Features in Bash
-
-a. A new version of malloc, based on the older GNU malloc, that has many
- changes, is more page-based, is more conservative with memory usage,
- and does not `orphan' large blocks when they are freed.
-
-b. A new version of gmalloc, based on the old GLIBC malloc, with many
- changes and range checking included by default.
-
-c. A new implementation of fnmatch(3) that includes full POSIX.2 Basic
- Regular Expression matching, including character classes, collating
- symbols, equivalence classes, and support for case-insensitive pattern
- matching.
-
-d. ksh-88 egrep-style extended pattern matching ([@+*?!](patlist)) has been
- implemented, controlled by a new `shopt' option, `extglob'.
-
-e. There is a new ksh-like `[[' compound command, which implements
- extended `test' functionality.
-
-f. There is a new `printf' builtin, implemented according to the POSIX.2
- specification.
-
-g. There is a new feature for command substitution: $(< filename) now expands
- to the contents of `filename', with any trailing newlines removed
- (equivalent to $(cat filename)).
-
-h. There are new tilde prefixes which expand to directories from the
- directory stack.
-
-i. There is a new `**' arithmetic operator to do exponentiation.
-
-j. There are new configuration options to control how bash is linked:
- `--enable-profiling', to allow bash to be profiled with gprof, and
- `--enable-static-link', to allow bash to be linked statically.
-
-k. There is a new configuration option, `--enable-cond-command', which
- controls whether or not the `[[' command is included. It is on by
- default.
-
-l. There is a new configuration option, `--enable-extended-glob', which
- controls whether or not the ksh extended globbing feature is included.
- It is enabled by default.
-
-m. There is a new configuration #define in config.h.top that, when enabled,
- will cause all login shells to source /etc/profile and one of the user-
- specific login shell startup files, whether or not the shell is
- interactive.
-
-n. There is a new invocation option, `--dump-po-strings', to dump
- a shell script's translatable strings ($"...") in GNU `po' format.
-
-o. There is a new `shopt' option, `nocaseglob', to enable case-insensitive
- pattern matching when globbing filenames and using the `case' construct.
-
-p. There is a new `shopt' option, `huponexit', which, when enabled, causes
- the shell to send SIGHUP to all jobs when an interactive login shell
- exits.
-
-q. `bind' has a new `-u' option, which takes a readline function name as an
- argument and unbinds all key sequences bound to that function in a
- specified keymap.
-
-r. `disown' now has `-a' and `-r' options, to limit operation to all jobs
- and running jobs, respectively.
-
-s. The `shopt' `-p' option now causes output to be displayed in a reusable
- format.
-
-t. `test' has a new `-N' option, which returns true if the filename argument
- has been modified since it was last accessed.
-
-u. `umask' now has a `-p' option to print output in a reusable format.
-
-v. A new escape sequence, `\xNNN', has been added to the `echo -e' and $'...'
- translation code. It expands to the character whose ascii code is NNN
- in hexadecimal.
-
-w. The prompt string expansion code has a new `\r' escape sequence.
-
-x. The shell may now be cross-compiled for the CYGWIN32 environment on
- a Unix machine.
-
-4. New Features in Readline
-
-a. There is now an option for `iterative' yank-last-arg handline, so a user
- can keep entering `M-.', yanking the last argument of successive history
- lines.
-
-b. New variable, `print-completions-horizontally', which causes completion
- matches to be displayed across the screen (like `ls -x') rather than up
- and down the screen (like `ls').
-
-c. New variable, `completion-ignore-case', which causes filename completion
- and matching to be performed case-insensitively.
-
-d. There is a new bindable command, `magic-space', which causes history
- expansion to be performed on the current readline buffer and a space to
- be inserted into the result.
-
-e. There is a new bindable command, `menu-complete', which enables tcsh-like
- menu completion (successive executions of menu-complete insert a single
- completion match, cycling through the list of possible completions).
-
-f. There is a new bindable command, `paste-from-clipboard', for use on Win32
- systems, to insert the text from the Win32 clipboard into the editing
- buffer.
-
-g. The key sequence translation code now understands printf-style backslash
- escape sequences, including \NNN octal escapes. These escape sequences
- may be used in key sequence definitions or macro values.
-
-h. An `$include' inputrc file parser directive has been added.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.01.1-release,
-and the previous version, bash-2.01-release.
-
-1. Changes to Bash
-
-a. The select command was fixed to check the validity of the user's
- input more strenuously.
-
-b. A bug was fixed that prevented `time' from timing commands correctly
- when supplied as an argument to `bash -c'.
-
-c. A fix was made to the mail checking code to keep from adding the same
- mail file to the list of files to check multiple times when parsing
- $MAILPATH.
-
-d. Fixed an off-by-one error in the tilde expansion library.
-
-e. When using the compound array assignment syntax, the old value of
- the array is cleared before assigning the new value.
-
-f. Fixed a bug that could cause a core dump when a trap handler was reset
- to the default in the trap command associated with that signal.
-
-g. Fixed a bug in the locale code that occurred when assigning a value
- to LC_ALL.
-
-h. A change was made to the parser so that words of the form xxx=(...)
- are not considered compound assignment statements unless there are
- characters before the `='.
-
-i. A fix was made to the command tracing code to correctly quote each
- word of output.
-
-j. Some changes were made to the bash-specific autoconf tests to make them
- more portable.
-
-k. Completion of words with globbing characters now correctly quotes the
- result.
-
-l. The directory /var/spool/mail is now preferred to /usr/spool/mail when
- configure is deciding on the default mail directory.
-
-m. The brace completion code was fixed to not quote the `{' and `}'.
-
-n. Some fixes were made to make $RANDOM more random in subshells.
-
-o. System-specific changes were made to configure for: SVR4.2
-
-p. Changes were made so that completion of words containing globbing chars
- substitutes the result only if a single filename was matched.
-
-q. The window size is now recomputed after a job is stopped with SIGTSTP if
- the user has set `checkwinsize' with `shopt'.
-
-r. When doing substring expansion, out-of-range substring specifiers now
- cause nothing to be substituted rather than an expansion error.
-
-s. A fix was made so that you can no longer trap `SIGEXIT' or `SIGDEBUG' --
- only `EXIT' and `DEBUG' are accepted.
-
-t. The display of trapped signals now uses the signal number if signals
- for which bash does not know the name are trapped.
-
-u. A fix was made so that `bash -r' does not turn on restricted mode until
- after the startup files are executed.
-
-v. A bug was fixed that occasionally caused a core dump when a variable
- found in the temporary environment of export/declare/readonly had a
- null value.
-
-w. A bug that occasionally caused unallocated memory to be passed to free()
- when doing arithmetic substitution was fixed.
-
-x. A bug that caused a buffer overrun when expanding a prompt string
- containing `\w' and ${#PWD} exceeded PATH_MAX was fixed.
-
-y. A problem with the completion code that occasionally caused it to
- refer to a character before the beginning of the readline line buffer
- was fixed.
-
-z. A bug was fixed so that the `read' builtin restarts reads when
- interrupted by signals other than SIGINT.
-
-aa. Fixed a bug that caused a command to be freed twice when there was
- an evaluation error in the `eval' command.
-
-2. Changes to Readline
-
-a. Added a missing `extern' to a declaration in readline.h that kept
- readline from compiling cleanly on some systems.
-
-b. The history file is now opened with mode 0600 when it is written for
- better security.
-
-c. Changes were made to the SIGWINCH handling code so that prompt redisplay
- is done better.
-
-d. ^G now interrupts incremental searches correctly.
-
-e. A bug that caused a core dump when the set of characters to be quoted
- when completing words was empty was fixed.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.01-release,
-and the previous version, bash-2.01-beta2.
-
-1. Changes to Bash
-
-a. The `distclean' target should remove the `printenv' executable if it
- has been created.
-
-b. The test suite was changed slightly to ensure that the error messages
- are printed in English.
-
-c. A bug that caused the shell to dump core when a filename containing a
- `/' was passed to `hash' was fixed.
-
-d. Pathname canonicalization now leaves a leading `//' intact, as POSIX.1
- requires.
-
-e. A memory leak when completing commands was fixed.
-
-f. A memory leak that occurred when checking the hash table for commands
- with relative paths was fixed.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.01-beta2,
-and the previous version, bash-2.01-beta1.
-
-1. Changes to Bash
-
-a. The `ulimit' builtin translates RLIM_INFINITY to the hard limit only if
- the current (soft) limit is less than or equal to the hard limit.
-
-b. Fixed a bug that caused the bash emulation of strcasecmp to produce
- incorrect results.
-
-c. A bug that caused memory to be freed twice when a trap handler resets
- the trap more than once was fixed.
-
-d. A bug that caused machines where sizeof (pointer) > sizeof (int) to
- fail (and possibly dump core) when trying to unwind-protect a null
- pointer was fixed.
-
-e. The startup files should not be run with job control enabled. This fix
- allows SIGINT to once again interrupt startup file execution.
-
-f. Bash should not change the SIGPROF handler if it is set to something
- other than SIG_DFL.
-
-g. The completion code that provides bash-specific completions for readline
- now quotes characters that the readline code would treat as word break
- characters if they appear in a file name.
-
-h. The completion code now correctly quotes filenames containing a `!',
- even if the user attempted to use double quotes when attempting
- completion.
-
-i. A bug that caused the shell to dump core when `disown' was called without
- arguments and there was no current job was fixed.
-
-j. A construct like $((foo);bar) is now processed as a command substitution
- rather than as a bad arithmetic substitution.
-
-k. A couple of bugs that caused `fc' to not obey the `cmdhist' and `lithist'
- shell options when editing and re-executing a series of commands were
- fixed.
-
-l. A fix was made to the grammar -- the list of commands between `do' and
- `done' in the body of a `for' command should be treated the same as a
- while loop.
-
-2. Changes to Readline
-
-a. A couple of bugs that caused the history search functions to attempt to
- free a NULL pointer were fixed.
-
-b. If the C library provides setlocale(3), readline does not need to look
- at various environment variables to decide whether or not to go into
- eight-bit mode automatically -- just check whether the current locale
- is not `C' or `POSIX'.
-
-c. If the filename completion function finds that a directory was not closed
- by a previous (interrupted) completion, it closes the directory with
- closedir().
-
-3. New Features in Bash
-
-a. New bindable readline commands: history-and-alias-expand-line and
- alias-expand-line. The code was always in there, there was just no
- way to execute it.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.01-beta1,
-and the previous version, bash-2.01-alpha1.
-
-1. Changes to Bash
-
-a. Fixed a problem that could cause file descriptors used for process
- substitution to conflict with those used explicitly in redirections.
-
-b. Made it easier to regenerate configure if the user changes configure.in.
-
-c. ${GROUPS[0]} should always be the primary group, even on systems without
- multiple groups.
-
-d. Spelling correction is no longer enabled by default.
-
-e. Fixes to quoting problems in `bashbug'.
-
-f. OS-specific configuration changes were made for: Irix 6.
-
-g. OS-specific code changes were made for: QNX.
-
-h. A more meaningful message is now printed when the file in /tmp for a
- here document cannot be created.
-
-i. Many changes to the shell's variable initialization code to speed
- non-interactive startup.
-
-j. Changes to the non-job-control code so that it does not try to open
- /dev/tty.
-
-k. The output of `set' and `export' is once again sorted, as POSIX wants.
-
-l. Fixed a problem caused by a recursive call reparsing the value of
- $SHELLOPTS.
-
-m. The tilde code no longer calls getenv() when it's compiled as part of
- the shell, which should eliminate problems on systems that cannot
- redefine getenv(), like the NeXT OS.
-
-n. Fixed a problem that caused `bash -o' or `bash +o' to not list all
- the shell options.
-
-o. Fixed `ulimit' to convert RLIM_INFINITY to the appropriate hard limit
- only if the hard limit is greater than the current (soft) limit.
-
-p. Fixed a problem that arose when building bash in a different directory
- than the source and y.tab.[ch] were remade with something other than
- bison. This came up most often on NetBSD.
-
-q. Fixed a problem with completion -- it thought that `pwd`/[TAB] indicated
- an unfinished command completion (`/), which generated errors.
-
-r. The bash special tilde expansions (~-, ~+) are now attempted before
- calling the standard tilde expansion code, which should eliminate the
- problems people have been seeing with this on Solaris 2.5.1.
-
-s. Added support for <stdarg.h> to places where it was missing.
-
-t. Changed the code that reads the output of a command substitution to not
- go through stdio. This reduces the memory requirements and is faster.
-
-u. A number of changes to speed up export environment creation were made.
-
-v. A number of memory leaks were fixed as the result of running the test
- scripts through Purify.
-
-w. Fixed a bug that caused subshells forked to interpret executable
- scripts without a leading `#!' to not reinitialize the values of
- the shell options.
-
-2. Changes to Readline
-
-a. History library has less `#ifdef SHELL' code -- abstracted stuff out
- into application-specific function hooks.
-
-b. Readline no longer calls getenv() if it's compiled as part of the shell,
- which should eliminate problems on systems that cannot redefine getenv(),
- like the NeXT OS.
-
-c. Fixed translation of ESC when `untranslating' macro values.
-
-d. The region kill operation now fixes the mark if it ends up beyond the
- boundaries of the line after the region is deleted.
-
-3. New Features in Bash
-
-a. New argument for `configure': `--with-curses'. This can be used to
- override the selection of the termcap library on systems where it is
- deficient.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.01-alpha1,
-and the previous version, bash-2.0-release.
-
-1. Changes to Bash
-
-a. System-specific configuration changes for: FreeBSD, SunOS4, Irix,
- MachTen, QNX 4.2, Harris Night Hawk, SunOS5.
-
-b. System-specific code changes were made for: Linux, 4.4 BSD, QNX 4.2,
- HP-UX, AIX 4.2.
-
-c. A bug that caused the exec builtin to fail because the full pathname of
- the command could not be found was fixed.
-
-d. The code that performs output redirections is now more resistant to
- race conditions and possible security exploits.
-
-e. A bug that caused the shell to dump core when performing pattern
- substitutions on variable values was fixed.
-
-f. More hosts are now recognized by the auto-configuration mechanism
- (OpenBSD, QNX, others).
-
-g. Assignments to read-only variables that attempt to convert them to
- arrays are now errors.
-
-h. A bug that caused shell scripts using array assignments in POSIX mode
- to exit after the assignment was performed was fixed.
-
-i. The substring expansion code is now more careful about running off the
- ends of the expanded variable value.
-
-j. A bug that caused completion to fail if a backquoted command substitution
- appeared anywhere on the line was fixed.
-
-k. The `source' builtin no longer turns off history if it has been enabled
- in a non-interactive shell.
-
-l. A bug that caused the shell to crash when `disown' was given a pid
- instead of a job number was fixed.
-
-m. The `cd' spelling correction code will not try to change to `.' if no
- directory entries match a single-character argument.
-
-n. A bad variable name supplied to `declare', `export', or `readonly' no
- longer causes a non-interactive shell in POSIX mode to exit.
-
-o. Some fixes were made to the test suite to handle peculiarities of
- various Unix versions.
-
-p. The bash completion code now quotes characters that readline would
- treat as word breaks for completion but are not shell metacharacters.
-
-q. Bad options supplied at invocation now cause a usage message to be
- displayed.
-
-r. Fixes were made to the code that handles DEBUG traps so that the trap
- string is not freed inappropriately.
-
-s. Some changes were made to the bash debugger in examples/bashdb -- it
- should be closer to working now.
-
-t. A problem that caused the default filename used for mail checking to be
- wrong was fixed.
-
-u. A fix was made to the `echo' builtin so that NUL characters printed with
- `echo -e' do not cause the output to be truncated.
-
-v. A fix was made to the job control code so that the shell behaves better
- when monitor mode is enabled in a non-interactive shell.
-
-w. Bash no longer catches all of the terminating signals in a non-
- interactive shell until a trap is set on EXIT, which should result in
- quicker startup.
-
-x. A fix was made to the command timing code so that `time' can be used in
- a loop.
-
-y. A fix was made to the parser so that `((cmd); cmd2)' is now parsed as
- a nested subshell rather than strictly as an (erroneous) arithmetic
- command.
-
-z. A fix was made to the globbing code so that it correctly matches quoted
- filenames beginning with a `.'.
-
-aa. A bug in `fc' that caused some multi-line commands to not be stored as
- one command in the history when they were re-executed after editing
- (with `fc -e') was fixed.
-
-bb. The `ulimit' builtin now attempts to catch some classes of integer
- overflows.
-
-cc. The command-oriented-history code no longer attempts to add `;'
- inappropriately when a newline appears while reading a $(...) command
- substitution.
-
-dd. A bug that caused the shell to dump core when `help --' was executed
- was fixed.
-
-ee. A bug that caused the shell to crash when an unset variable appeared
- in the body of a here document after `set -u' had been executed was
- fixed.
-
-ff. Implicit input redirections from /dev/null for asynchronous commands
- are now handled better.
-
-gg. A bug that caused the shell to fail to compile when configured with
- `--disable-readline' was fixed.
-
-hh. The globbing code should now be interruptible.
-
-ii. Bash now notices when the `kill' builtin is used to send SIGCONT to a
- stopped job and adjusts the data structures accordingly, as if `bg' had
- been executed instead.
-
-jj. A bug that caused the shell to crash when mixing calls to `getopts'
- and `shift' on the same set of positional parameters was fixed.
-
-kk. The command printing code now preserves the `-p' flag to `time'.
-
-ll. The command printing code now handles here documents better when there
- are other redirections associated with the command.
-
-mm. The special glibc environment variable (NNN_GNU_nonoption_argv_flags_)
- is no longer placed into the environment of executed commands -- users
- of glibc had too many problems with it.
-
-nn. Reorganized the code that generates signames.h. The signal_names list
- is now more complete but may be slightly different (SIGABRT is favored
- over SIGIOT, for example). The preferred signal names are those
- listed in the POSIX.2 standard.
-
-oo. `bashbug' now uses a filename shorter than 14 characters for its
- temporary file, and asks for confirmation before sending the bug
- report.
-
-pp. A bug that caused TAB completion in vi editing mode to not be turned
- off when `set -o posix' was executed or back on when `set +o posix'
- was executed was fixed.
-
-qq. A bug in the brace expansion code that caused brace expansions appearing
- in new-style $(...) command substitutions to be inappropriately expanded
- was fixed.
-
-rr. A bug in the readline hook shell-expand-line that could cause memory to
- be inappropriately freed was fixed.
-
-ss. A bug that caused some arithmetic expressions containing `&&' and `||'
- to be parsed with the wrong precedence has been fixed.
-
-tt. References to unbound variables after `set -u' has been executed now
- cause the shell to exit immediately, as they should.
-
-uu. A bug that caused the shell to exit inappropriately when `set -e' had
- been executed and a command's return status was being inverted with the
- `!' reserved word was fixed.
-
-vv. A bug that could occasionally cause the shell to crash with a
- divide-by-zero error when timing a command was fixed.
-
-ww. A bug that caused parameter pattern substitution to leave stray
- backslashes in the replacement string when the expression is in
- double quotes was fixed.
-
-xx. The `break' and `continue' builtins now break out of all loops when an
- invalid count argument is supplied.
-
-yy. Fixed a bug that caused PATH to be set to the empty string if
- `command -p' is executed with PATH unset.
-
-zz. Fixed `kill -l signum' to print the signal name without the `SIG' prefix,
- as POSIX specifies.
-
-aaa. Fixed a bug that caused the shell to crash while setting $SHELLOPTS
- if there were no shell options set.
-
-bbb. Fixed `export -p' and `readonly -p' so that when the shell is in POSIX
- mode, their output is as POSIX.2 specifies.
-
-ccc. Fixed a bug in `readonly' so that `readonly -a avar=(...)' actually
- creates an array variable.
-
-ddd. Fixed a bug that prevented `time' from correctly timing background
- pipelines.
-
-2. Changes to Readline
-
-a. A bug that caused an extra newline to be printed when the cursor was on
- an otherwise empty line was fixed.
-
-b. An instance of memory being used after it was freed was corrected.
-
-c. The redisplay code now works when the prompt is longer than the screen
- width.
-
-d. `dump-macros' is now a bindable name, as it should have been all along.
-
-e. Non-printable characters are now expanded when displaying macros and
- their values.
-
-f. The `dump-variables' and `dump-macros' commands now output a leading
- newline if they're called as the result of a key sequence, rather
- than directly by an application.
-
-3. New Features in Bash
-
-a. There is a new builtin array variable: GROUPS, the set of groups to which
- the user belongs. This is used by the test suite.
-
-4. New Features in Readline
-
-a. If a key sequence bound to `universal-argument' is read while reading a
- numeric argument started with `universal-argument', it terminates the
- argument but is otherwise ignored. This provides a way to insert multiple
- instances of a digit string, and is how GNU emacs does it.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.0-release,
-and the previous version, bash-2.0-beta3.
-
-1. Changes to Bash
-
-a. Fix to the `getopts' builtin so that it does the right thing when a
- required option argument is not present.
-
-b. The completion code now updates the common prefix of matched names
- after FIGNORE processing is done, since any names that were removed
- may have changed the common prefix.
-
-c. Fixed a bug that made messages in MAILPATH entries not work correctly.
-
-d. Fixed a serious documentation error in the description of the new
- ${parameter:offset[:length]} expansion.
-
-e. Fixes to make parameter substring expansion ({$param:offset[:length]})
- work when within double quotes.
-
-f. Fixes to make ^A (CTLESC) survive an unquoted expansion of positional
- parameters.
-
-g. Corrected a misspelling of `unlimited' in the output of `ulimit'.
-
-h. Fixed a bug that caused executable scripts without a leading `#!' to
- occasionally pick up the wrong set of positional parameters.
-
-i. Linux systems now have a working `ulimit -v', using RLIMIT_AS.
-
-j. Updated config.guess so that many more machine types are recognized.
-
-k. Fixed a bug with backslash-quoted slashes in the ${param/pat[/sub]}
- expansion.
-
-l. If the shell is named `-su', and `-c command' is supplied, read and
- execute the login shell startup files even though the shell is not
- interactive. This is to support the `-' option to `su'.
-
-m. Fixed a bug that caused core dumps when the DEBUG trap was ignored
- with `trap "" DEBUG' and a shell function was subsequently executed.
-
-n. Fixed a bug that caused core dumps in the read builtin when IFS was
- set to the null string and the input had leading whitespace.
-
-2. Changes to Readline
-
-a. Fixed a bug that caused a numeric argument of 1024 to be ignored when
- inserting text.
-
-b. Fixed the display code so that the numeric argument is displayed as it's
- being entered.
-
-c. Fixed the numeric argument reading code so that `M-- command' is
- equivalent to `M--1 command', as the prompt implies.
-
-3. New Features in Bash
-
-a. `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'.
-
-b. Integer constants have been extended to base 64.
-
-4. New Features in Readline
-
-a. The `home' and `end' keys are now bound to beginning-of-line and
- end-of-line, respectively, if the corresponding termcap capabilities
- are present.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.0-beta3,
-and the previous version, bash-2.0-beta2.
-
-1. Changes to Bash
-
-a. System-specific changes for: AIX 4.2, SCO 3.2v[45], HP-UX.
-
-b. When in POSIX mode, variable assignments preceding a special builtin
- persist in the shell environment after the builtin completes.
-
-c. Changed all calls to getwd() to getcwd(). Improved check for systems
- where the libc getcwd() calls popen(), since that breaks on some
- systems when job control is being used.
-
-d. Fixed a bug that caused seg faults when executing scripts with the
- execute bit set but without a leading `#!'.
-
-e. The environment passed to executed commands is never sorted.
-
-f. A bug was fixed in the code that expands ${name[@]} to the number of
- elements in an array variable.
-
-g. A bug was fixed in the array compound assignment code ( A=( ... ) ).
-
-h. Window size changes now correctly propagate down to readline if
- the shopt `checkwinsize' option is enabled.
-
-i. A fix was made in the code that expands to the length of a variable
- value (${#var}).
-
-j. A fix was made to the command builtin so that it did not turn on the
- `no fork' flag inappropriately.
-
-k. A fix was made to make `set -n' work more reliably.
-
-l. A fix was made to the job control initialization code so that the
- terminal process group is set to the shell's process group if the
- shell changes its own process group.
-
-2. Changes to Readline
-
-a. System-specific changes for: SCO 3.2v[45].
-
-b. The behavior of the vi-mode `.' when redoing an `i' command was changed
- to insert the text previously inserted by the `i' command rather than
- simply entering insert mode.
-
-3. New features in Bash
-
-a. There is a new version of the autoload function package, in
- examples/functions/autoload.v2, that uses arrays and provides more
- functionality.
-
-b. Support for LC_COLLATE and locale-specific sorting of the results of
- pathname expansion if strcoll() is available.
-
-4. New Features in Readline
-
-a. Support for locale-specific sorting of completion possibilities if
- strcoll() is available.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.0-beta2,
-and the previous version, bash-2.0-beta1.
-
-1. Changes to Bash
-
-a. `pushd -' is once again equivalent to `pushd $OLDPWD'.
-
-b. OS-specific changes for: SCO 3.2v[45].
-
-c. A change was made to the fix for the recently-reported security hole
- when reading characters with octal value 255 to make it work better on
- systems with restartable system calls when not using readline.
-
-d. Some changes were made to the test suite so that it works if you
- configure bash with --enable-usg-echo-default.
-
-e. A fix was made to the parsing of conditional arithmetic expressions.
-
-f. Illegal arithmetic bases now cause an arithmetic evaluation error rather
- than being silently reset.
-
-g. Multiple arithmetic bases now cause an arithmetic evaluation error
- instead of being ignored.
-
-h. A fix was made to the evaluation of ${param?word} to conform to POSIX.2.
-
-i. A bug that sometimes caused array indices to be evaluated twice (which
- would cause errors when they contained assignment statements) was fixed.
-
-j. `ulimit' was rewritten to avoid problems with getrlimit(2) returning
- unsigned values and to simplify the code.
-
-k. A bug in the command-oriented-history code that caused it to sometimes
- put semicolons after right parens inappropriately was fixed.
-
-l. The values inserted into the prompt by the \w and \W escape sequences
- are now quoted to prevent further expansion.
-
-m. An interactive shell invoked as `sh' now reads and executes commands
- from the file named by $ENV when it starts up. If it's a login shell,
- it does this after reading /etc/profile and ~/.profile.
-
-n. The file named by $ENV is never read by non-interactive shells.
-
-2. Changes to Readline
-
-a. A few changes were made to hide some macros and functions that should not
- be public.
-
-b. An off-by-one error that caused seg faults in the history expansion code
- was fixed.
-
-3. New Features in Bash
-
-a. The ksh-style ((...)) arithmetic command was implemented. It is exactly
- identical to let "...". This is controlled by a new option to configure,
- `--enable-dparen-arithmetic', which is on by default.
-
-b. There is a new #define available in config.h.top: SYS_BASH_LOGOUT. If
- defined to a filename, bash reads and executes commands from that file
- when a login shell exits. It's commented out by default.
-
-c. `ulimit' has a `-l' option that reports the maximum amount of data that
- may be locked into memory on 4.4BSD-based systems.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.0-beta1,
-and the previous version, bash-2.0-alpha4.
-
-1. Changes to Bash
-
-a. A bug that sometimes caused traps to be ignored on signals the
- shell treats specially was fixed.
-
-b. The internationalization code was changed to track the values of
- LC_* variables and call setlocale() as appropriate. The TEXTDOMAIN
- and TEXTDOMAINDIR variables are also tracked; changes cause calls
- to textdomain() and bindtextdomain(), if available.
-
-c. A bug was fixed that sometimes caused double-quoted strings to be
- parsed incorrectly.
-
-d. Changes were made so that the siglist code compiles correctly on
- Solaris 2.5.
-
-e. Added `:' to the set of characters that cause word breaks for the
- completion code so that pathnames in assignments to $PATH can be
- completed.
-
-f. The `select' command was fixed to print $PS3 to stderr.
-
-g. Fixed an error in the manual page section describing the effect that
- setting and unsetting GLOBIGNORE has on the setting of the `dotglob'
- option.
-
-h. The time conversion code now uses CLK_TCK rather than CLOCKS_PER_SEC
- on systems without gettimeofday() and resources.
-
-i. The getopt static variables are now initialized each time a subshell
- is started, so subshells using `getopts' work right.
-
-j. A sign-extension bug that caused a possible security hole was fixed.
-
-k. The parser now reads characters between backquotes within a double-
- quoted string as a single word, so double quotes in the backquoted
- string don't terminate the enclosing double-quoted string.
-
-l. A bug that caused `^O' to work incorrectly when typed as the first
- thing to an interactive shell was fixed.
-
-m. A rarely-exercised off-by-one error in the code that quotes variable
- values was fixed.
-
-n. Some memory and file descriptor leaks encountered when running a
- shell script that is executable but does not have a leading `#!'
- were plugged.
-
-2. Changes to Readline
-
-a. A bug that sometimes caused incorrect results when trying to read
- typeahead on systems without FIONREAD was fixed.
-
-3. New Features in Bash
-
-a. The command timing code now uses the value of the TIMEFORMAT variable
- to format and display timing statistics.
-
-b. The `time' reserved word now accepts a `-p' option to force the
- POSIX.2 output format.
-
-c. There are a couple of new and updated scripts to convert csh startup
- files to bash format.
-
-d. There is a new builtin array variable: BASH_VERSINFO. The various
- members hold the parts of the version information in BASH_VERSION,
- plus the value of MACHTYPE.
-
-4. New Features in Readline
-
-a. Setting LANG to `en_US.ISO8859-1' now causes readline to enter
- eight-bit mode.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.0-alpha4,
-and the previous version, bash-2.0-alpha3.
-
-1. Changes to Bash
-
-a. There is better detection of rsh connections on Solaris 2.
-
-b. Assignments to read-only variables preceding a command name are now
- variable assignment errors. Variable assignment errors cause
- non-interactive shells running in posix mode to exit.
-
-c. The word tokenizer was rewritten to handle nested quotes and pairs
- ('', "", ``, ${...}, $(...), $[...], $'...', $"...", <(...), >(...))
- correctly. Some of the parameter expansion code was updated as a
- consequence.
-
-d. A fix was made to `test' when given three arguments so that a binary
- operator is checked for first, before checking that the first argument
- is `!'.
-
-e. 2''>/dev/null is no longer equivalent to 2>/dev/null.
-
-f. Parser error messages were regularized, and in most cases the name of
- the shell script being read by a non-interactive shell is not printed
- twice.
-
-g. A fix was made to the completion code so that it no longer removes the
- text the user typed in some cases.
-
-h. The special glibc `getopt' environment variable is no longer put into
- the environment on machines with small values of ARG_MAX.
-
-i. The expansion of ${...} now follows the POSIX.2 rules for finding the
- closing `}'.
-
-j. The shell no longer displays spurious status messages for background
- jobs in shell scripts that complete successfully when the script is
- run from a terminal.
-
-k. `shopt -o' now correctly updates $SHELLOPTS.
-
-l. A bug that caused the $PATH searching code to return a non-executable
- file even when an executable file with the same name appeared later in
- $PATH was fixed.
-
-m. The shell now does tilde expansions on unquoted `:~' in assignment
- statements when not in posix mode.
-
-n. Variable assignment errors when a command consists only of assignments
- now cause non-interactive shells to exit when in posix mode.
-
-o. If the variable in a `for' or `select' command is read-only, or not a
- legal shell identifier, a variable assignment error occurs.
-
-p. `test' now handles `-a' and `-o' as binary operators when three arguments
- are supplied, and correctly parses `( word )' as equivalent to `word'.
-
-q. `test' was fixed so that file names of the form /dev/fd/NN mean the same
- thing on all systems, even Linux.
-
-r. Fixed a bug in the globbing code that caused patterns with multiple
- consecutive `*'s to not be matched correctly.
-
-s. Fixed a bug that caused $PS2 to not be printed when an interactive shell
- not using readline is reading a here document.
-
-t. Fixed a bug that caused history expansion to be performed inappropriately
- when a single-quoted string spanned more than one line.
-
-u. `getopts' now checks that the variable name passed by the user as the
- second argument is a legal shell identifier and that the variable is
- not read-only.
-
-v. Fixed `getopts' to obey POSIX.2 rules for setting $OPTIND when it
- encounters an error.
-
-w. Fixed `set' to display variable values in a form that can be re-read.
-
-x. Fixed a bug in the code that keeps track of whether or not local variables
- have been declared at the current level of function nesting.
-
-y. Non-interactive shells in posix mode now exit if the name in a function
- declaration is not a legal identifier.
-
-z. The job control code now ignores stopped children when the shell is not
- interactive.
-
-aa. The `cd' builtin no longer attempts spelling correction on the directory
- name if the shell is not interactive, regardless of the setting of the
- `cdspell' option.
-
-bb. Some OS-specific changes were made for SCO 3.2v[45] and AIX 4.2.
-
-cc. `time' now prints its output to stderr, as POSIX.2 specifies.
-
-2. Fixes to Readline
-
-a. After printing possible completions, all lines of a multi-line prompt
- are redisplayed.
-
-b. Some changes were made to the terminal handling code in rltty.c to
- work around AIX 4.2 bugs.
-
-3. New Features in Bash
-
-a. There is a new loadable builtin: sprintf, with calling syntax
- sprintf var format [args]
- This provides an easy way to simulate ksh left- and right-justified
- variable values.
-
-b. The expansions of \h and \H in prompt strings were swapped. \h now
- expands to the hostname up to the first `.', as in bash-1.14.
-
-4. New Features in Readline
-
-a. The bash-1.14 behavior when ^M is typed while doing an incremental
- search was restored. ^J may now be used to terminate the search without
- accepting the line.
-
-b. There is a new bindable variable: disable-completion. This inhibits
- word completion and causes the completion character to be inserted as
- if it had been bound to self-insert.
-
-------------------------------------------------------------------------------
-This document details the changes between this version, bash-2.0-alpha3,
-and the previous version, bash-2.0-alpha2.
-
-There is now a file `COMPAT' included in the distribution that lists the
-user-visible incompatibilities between 1.14 and 2.0.
-
-1. Changes to Bash
-
-a. Some work was done so that word splitting of the rhs of assignment
- statements conforms more closely to historical practice.
-
-b. A couple of errant memory frees were fixed.
-
-c. A fix was made to the test builtin so it recognizes `<' and `>' as
- binary operators.
-
-d. The GNU malloc in lib/malloc/malloc.c now scrambles memory as it's
- allocated and freed. This is to catch callers that refer to freed
- memory or assume something about newly-allocated memory.
-
-e. Fixed a problem with conversion to 12-hour time in the prompt
- expansion code.
-
-f. Fixed a problem with configure's argument parsing order. Now you can
- correctly turn on specific options after using --enable-minimal-config.
-
-g. The configure script now automatically disables the use of GNU malloc
- on systems where it's appropriate (better than having people read the
- NOTES file and do it manually).
-
-h. There are new prompt expansions (\v and \V) to insert version information
- into the prompt strings.
-
-i. The default prompt string now includes the version number.
-
-j. Most of the builtins that take no options were changed to use the
- internal getopt so they can produce proper error messages for -?
- and incorrect options.
-
-k. Some system-specific changes were made for SVR4.2 and Solaris 2.5.
-
-l. Bash now uses PATH_MAX instead of MAXPATHLEN and NAME_MAX instead of
- MAXNAMLEN.
-
-m. A couple of problems caused by uninitialized variables were fixed.
-
-n. There are a number of new loadable builtin examples: logname, basename,
- dirname, tty, pathchk, tee, head, and rmdir. All of these conform to
- POSIX.2.
-
-o. Bash now notices changes in TZ and calls tzset() if present, so
- changing TZ will alter the time printed by prompt expansions.
-
-p. The source was reorganized a bit so I don't have to wait so long for
- some files to compile, and to facilitate the creation of a `shell
- library' at some future point.
-
-q. Bash no longer turns off job control if called as `sh', since the
- POSIX.2 spec includes job control as a standard feature.
-
-r. `bash -o posix' now works as intended.
-
-s. Fixed a problem with the completion code: when completing a filename
- that contained globbing characters, if show-all-if-ambiguous was set,
- the completion code would remove the user's text.
-
-t. Fixed ulimit so that (hopefully) the full range of limits is available
- on HPUX systems.
-
-u. A new `shopt' option (`hostcomplete') enables and disables hostname
- completion.
-
-v. The shell no longer attempts to save the history on an abort(),
- which is usually called by programming_error().
-
-w. The `-s' option to `fc' was changed to echo the command to be executed
- to stderr instead of stdout.
-
-x. If the editor invoked by `fc -e' exits with a non-zero status, no
- commands are executed.
-
-y. Fixed a bug that made the shopt `histverify' option work incorrectly.
-
-z. There is a new variable `MACHTYPE' whose value is the GNU-style
- `cpu-company-system' system description as set by configure. (The
- values of MACHTYPE and HOSTTYPE should really be swapped.)
-
-aa. The `ulimit' builtin now allows the maximum virtual memory size to be
- set via setrlimit(2) if RLIMIT_VMEM is defined.
-
-bb. `bash -nc 'command'' no longer runs `command'.
-
-2. Changes to Readline
-
-a. Fixed a typo in the code that checked for FIONREAD in input.c.
-
-b. Fixed a bug in the code that outputs keybindings, so things like C-\
- are quoted properly.
-
-c. Fixed a bug in the inputrc file parsing code to handle the problems
- caused by inputrc files created from the output of `bind -p' in
- previous versions of bash. The problem was due to the bug fixed
- in item b above.
-
-d. Readline no longer turns off the terminal's meta key, and turns it on
- once the first time it's called.
-
-------------------------------------------------------------------------------
-This file documents the changes between this version, bash-2.0-alpha2,
-and the previous version, bash-2.0-alpha.
-
-1. Changes to Bash
-
-a. The shell no longer thinks directories are executable.
-
-b. `disown' has a new option, `h', which inhibits the resending of SIGHUP
- but does not remove the job from the jobs table.
-
-c. The varargs functions in error.c now use ANSI-C `stdarg' if available.
-
-d. The build process now treats the `build version' in .build as local to
- the build directory, so different versions built from the same source
- tree have different `build versions'.
-
-e. Some problems with the grammar have been fixed. (It used `list' in a few
- productions where `compound_list' was needed. A `list' must be terminated
- with a newline or semicolon; a `compound_list' need not be.)
-
-f. A fix was made to keep `wait' from hanging when waiting for all background
- jobs.
-
-g. `bash --help' now writes its output to stdout, like the GNU Coding Standards
- specify, and includes the machine type (the value of MACHTYPE).
-
-h. `bash --version' now prints more information and exits successfully, like
- the GNU Coding Standards specify.
-
-i. The output of `time' and `times' now prints fractional seconds with three
- places after the decimal point.
-
-j. A bug that caused process substitutions to screw up the pipeline printed
- by `jobs' was fixed.
-
-k. Fixes were made to the code that implements $'...' and $"..." so they
- work as documented.
-
-l. The process substitution code now opens named pipes for reading with
- O_NONBLOCK to avoid hanging.
-
-m. Fixes were made to the trap code so the shell cleans up correctly if the
- trap command contains a `return' and we're executing a function or
- sourcing a script with `.'.
-
-n. Fixes to doc/Makefile.in so that it doesn't try to remake all of the
- documentation (ps, dvi, etc.) on a `make install'.
-
-o. Fixed an auto-increment error that caused bash -c args to sometimes dump
- core.
-
-p. Fixed a bug that caused $HISTIGNORE to fail when the history line
- contained globbing characters.
-
-2. Changes to Readline
-
-a. There is a new string variable, rl_library_version, available for use by
- applications. The current value is "2.1".
-
-b. A bug encountered when expand-tilde was enabled and file completion was
- attempted on a word beginning with `~/' was fixed.
-
-c. A slight change was made to the incremental search termination behavior.
- ESC still terminates the search, but if input is pending or arrives
- within 0.1 seconds (on systems with select(2)), it is used as a prefix
- character. This is intented to allow users to terminate searches with
- the arrow keys and get the behavior they expect.
diff --git a/COMPAT~ b/COMPAT~
deleted file mode 100644
index 4acbcdc0..00000000
--- a/COMPAT~
+++ /dev/null
@@ -1,225 +0,0 @@
-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~
deleted file mode 100644
index 17091008..00000000
--- a/CWRU/CWRU.chlog~
+++ /dev/null
@@ -1,13650 +0,0 @@
- 4/9/2001
- --------
-[bash-2.05 released]
-
- 4/10
- ----
-redir.c
- - check return value of fclose() in write_here_document() for error
- returns; don't just rely on fwrite() failing
-
-support/bashbug.sh
- - set TMPDIR to /tmp if it's null or unset
- - use $TMPDIR in the TEMP tempfile name template
- - fixed the call to `mktemp', if it exists, to make it more portable
-
-jobs.c
- - if WCONTINUED is not defined, define it to 0 and add a define for
- WIFCONTINUED(wstatus) which expands to 0
- - add WCONTINUED to the flags passed to waitpid(2) in waitchld()
- - don't increment children_exited if waitpid's status is WIFCONTINUED,
- since we don't want to call a SIGCHLD trap handler in this case
- - in waitchld(), we set child->running to 1 if WIFCONTINUED(status)
- is non-zero
- - make sure pretty_print_job doesn't check for the core dump bit if
- the process has been continued; it's only valid if the job is dead
- - in set_job_status_and_cleanup, set the job to JRUNNING if job_state
- is non-zero and the job was previously marked as JSTOPPED
-
-configure.in
- - add -DBROKEN_DIRENT_D_INO to interix LOCAL_CFLAGS
-
-lib/glob/glob.c
- - if BROKEN_DIRENT_D_INO is defined, define REAL_DIR_ENTRY to 1
-
-jobs.c
- - in kill_pid, we only need to block and unblock SIGCHLD if the
- `group' argument is non-zero, since otherwise we just call `kill'
- on the pid argument
-
-version.c
- - update copyright date to 2001
-
-bashline.c
- - prog_complete_return needs to take a `const char *' as its first
- argument
- - history_completion_generator needs to take a `const char *' as
- its first argument, and `text' needs to be a `const char *'
-
- 4/11
- ----
-redir.c
- - fixed a weird typo in redir_special_open, case RF_DEVFD, added
- call to all_digits before call to legal_number
- - fixed do_redirection_internal to call legal_number instead of atol(3)
- when translating r_duplicating_{in,out}put_word, so it handles
- overflow better
- - produce an error message in redirection_error for out-of-range
- file descriptors
- - change allocation strategy in redirection_error so we don't have to
- malloc scratch memory if redirection_expand() fails
-
-jobs.h
- - added defines for `running' member of a struct process
-
-general.c
- - fix legal_number to return 0 when strtol(3) reports overflow or
- underflow
-
-parse.y
- - changed read_token_word to call legal_number instead of atoi(3)
-
-input.c
- - return -1/EBADF from close_buffered_fd if fd is < 0
-
-command.h
- - fixed bogus comment about IS_DESCRIPTOR in description of the
- REDIRECTEE struct
-
-print_cmd.c
- - change cprintf's 'd' modifier code to display negative numbers as
- an out-of-range value. We can do this only because the only use
- of %d is to output file descriptor numbers in redirections
-
-support/mksignames.c
- - need to include config.h to get a possible value for
- UNUSABLE_RT_SIGNALS
-
- 4/16
- ----
-lib/readline/doc/rluser.texinfo
- - corrected a small error in one description of M-DEL
-
- 4/17
- ----
-stringlib.c
- - need to initialize `ind' before calls to RESIZE_MALLOCED_BUFFER
- in strcreplace()
-
-support/bashversion.c
- - new file, prints bash version information
-
-Makefile.in
- - rules for building bashversion and linking it to version.o
-
- 4/24
- ----
-conftypes.h
- - new file with HOSTTYPE, OSTYPE, MACHTYPE, etc. defines from
- variables.h
-
-variables.h, version.c
- - include conftypes.h
-
-patchlevel.h
- - new file, contains define for PATCHLEVEL. Doing away with the old
- scheme of having the information in configure.in
-
-version.c
- - include patchlevel.h
-
-Makefile.in
- - run bashversion -p to find patch level rather than have configure
- substitute in a value
- - pass -S ${top_srcdir} to support/mkversion.sh
-
-support/mkversion.sh
- - don't put PATCHLEVEL define into version.h, but accept and ignore
- a -p option
- - take a new -S srcdir option
- - find the patch level by parsing it out of patchlevel.h
-
-configure.in
- - hard-code BASHVERS assignment instead of reading it from a file
- - remove BASHPATCH; don't substitute it
-
-_distribution,_patchlevel
- - removed
-
- 4/26
- ----
-shell.c
- - call init_noninteractive() in open_shell_script if forced_interactive
- is non-zero (the shell was started with -i) and fd_is_tty is 0
- (the script file is a real file, not something like /dev/stdin),
- since it wasn't done earlier
-
-builtins/printf.def
- - change for POSIX.2 compliance when conversion errors are encountered
- when processing %d, %u, and floating point conversion operators
- (print a warning message, return the value accumulated at the time
- of the error -- which is always 0 -- and exit with a non-zero status)
-
-command.h
- - added CMD_COMMAND_BUILTIN for use by the `command' builtin and the
- code in execute_cmd.c
-
-builtins/command.def
- - add CMD_COMMAND_BUILTIN to the created command's flags
-
- 5/1
- ---
-configure.in
- - add call to AC_C_CONST to test `const' compiler behavior
- - add call to AC_C_INLINE to test `inline' compiler behavior
- - add call to AC_C_STRINGIZE to test cpp #x stringizing operator
-
-config.h.in
- - add `#undef const' for configure to substitute
- - add `#undef inline' for configure to substitute
- - add `#undef HAVE_STRINGIZE' for configure to substitute
-
-include/stdc.h
- - remove code that defines or undefines `const' and `inline'
- - change the __STRING macro to be defined depending on the value
- of HAVE_STRINGIZE
-
-lib/malloc/malloc.c
- - change the __STRING macro to be defined depending on the value
- of HAVE_STRINGIZE
-
-lib/readline/{readline,rlprivate}.h
- - moved rl_get_termcap to readline.h, making it a public function
-
-lib/readline/readline.h
- - new #define, RL_READLINE_VERSION, hex-encoded library version
- number, currently set to 0x0402
- - new public int variable, rl_readline_version
-
-lib/readline/readline.c
- - #define RL_READLINE_VERSION if it is not already defined (which it
- should be in readline.h)
- - initialize rl_readline_version to RL_READLINE_VERSION
-
-lib/readline/doc/rltech.texinfo
- - documented rl_get_termcap
- - documented rl_readline_version
-
-jobs.c
- - job_exit_status should return an int, not a WAIT (undetected
- before because on most POSIX-like systems a WAIT is really an int)
-
-builtins/evalfile.c
- - added FEVAL_REGFILE (file must be a regular file) to accepted
- _evalfile flags
- - fc_execute_file() adds FEVAL_REGFILE to _evalfile flags. This
- means that startup files and files read with `.' no longer need
- to be regular files
-
- 5/2
- ---
-
-lib/termcap/Makefile.in
- - fix target for installed termcap library (normally unused)
-
-lib/tilde/Makefile.in
- - fix install target to install in $(libdir) (normally unused)
-
-Makefile.in
- - don't make $(man3dir) since there's nothing installed there
-
-Makefile.in,doc/Makefile.in
- - change `man1ext' to `.1', `man3ext' to `.3'
- - change appropriate install targets to use new values of man[13]ext
- - use `test ...' instead of `[...]'
- - add support for DESTDIR root installation prefix, for package
- building (installdirs, install, install-strip, uninstall targets)
-
-builtins/common.c
- - new function int get_exitstat(WORD_LIST *list) returns an eight-bit
- exit status value for use in return, exit, logout builtins
-
-builtins/common.h
- - extern declaration for get_exitstat()
-
-builtins/{exit,return}.def
- - call get_exitstat where appropriate
-
-builtins/printf.def
- - add support for "'" flag character as posix 1003.2-200x d6 says
- - fix core dump when user-supplied field width or precision is 0
- - fix to printstr() to handle zero-length precision with `%b' format
- specifier (printf '%.0b-%.0s\n' foo bar)
- - fix to printstr() to treat a negative field width as a positive
- field width with left-justification
- - fix to mklong to avoid static buffers, which can always be overrun
- by someone sufficiently motivated
-
-bashline.c
- - change var in add_host_name to type `size_t' for passing to xrealloc
-
- 5/3
- ---
-execute_cmd.c
- - change restore_signal_mask to accept a sigset_t *, since a sigset_t
- may not fit into a pointer, change call
-
-unwind_prot.c
- - use a union UWP in restore_variable when restoring a variable whose
- size is the same as sizeof(int), the reverse of the method used to
- store it in unwind_protect_int
-
-builtins/printf.def
- - use a #define LENMODS containing the length modifiers instead of
- testing against each possible modifier character, save any mod
- character found
- - add support for ISO C99 length specifiers `j', `t', and `z'
- - if `L' modifier is supplied with a floating point conversion char,
- pass a `long double' to printf if HAVE_LONG_DOUBLE is defined
-
-configure.in,config.h.in
- - call AC_C_LONG_DOUBLE to check for `long double'; define
- HAVE_LONG_DOUBLE if supported
-
-bashline.c
- - fix an inadvertantly-unclosed comment in attempt_shell_completion
- - make set_saved_history return a value
- - make dynamic_complete_history return a useful value
-
-{make_cmd,execute_cmd,shell,subst,trap,variables,input,unwind_prot,test,
-pcomplete}.c
- - removed some declared-but-unused variables
-
-builtins/{cd,enable,fc,set,setattr,type,umask,printf,complete}.def
- - removed some declared-but-unused variables
-
-lib/sh/{zread,netopen}.c
- - removed some declared-but-unused variables
-
-execute_cmd.c
- - in execute_arith_command, use a long variable to hold the result
- of evalexp(), since that's what it returns
-
-builtins/evalstring.c
- - make cat_file return -1 on a read or write error
-
-lib/sh/stringlib.c
- - make merge_stringlists() return the right value
-
- 5/7
- ---
-pcomplete.c
- - remove typo that caused empty declaration (;;)
-
-parse.y
- - fix yyerror() to accept a single string argument; fix callers
-
-trap.c
- - cast pointer to long instead of int when printing message with
- internal_warning() in run_pending_traps()
-
-subst.c
- - fix process_substitute to handle stdin being closed
-
-test.c
- - change `while' to `if' in and() and or(), since the loop isn't
- actually performed -- there's an unconditional `return' in the
- loop body
- - check for integer overflow of arguments to `-t'
-
-lib/sh/netopen.c
- - change _getserv() to reject negative port/service numbers
-
-expr.c
- - fix strlong() to not convert the base specification from long to
- int before checking for overflow, since truncation on machines
- where sizeof(int) != sizeof(long) may mask errors
-
-builtins/{jobs,kill,wait}.def
- - use legal_number instead of atoi when converting strings to pid_t;
- check for numeric overflow
-
-input.c
- - fix for cygwin in b_fill_buffer -- off-by-one error when checking
- buffer for \r\n termination
-
-general.h
- - new #define INT_STRLEN_BOUND(t), computes max length of string
- representing integer value of type T, possibly including a sign
- character
- - include <limits.h> if it's present
-
-{execute_cmd,findcmd,test}.c
- - don't include <limits.h>, since general.h does it now
-
-{execute_cmd,lib/sh/itos,pcomplete,print_cmd,subst,variables}.c
- - use INT_STRLEN_BOUND instead of static array sizes when converting
- various strings to integer values
-
-shell.h
- - struct fd_bitmap now uses an `int' size, since it's bounded by
- the number of file descriptors, which must fit into an `int'
-
-execute_cmd.c
- - FD_BITMAP_DEFAULT_SIZE is now 32, not 32L
- - new_fd_bitmap takes an `int' size parameter, not a `long'
-
-execute_cmd.h
- - change prototype for new_fd_bitmap()
-
-test.c
- - fix test_stat to check for overflow when parsing the integer file
- descriptor number; return ENOENT instead of EBADF for files that
- are not open
-
-hashlib.c
- - don't discard the upper 32 bits of the random value, if present
-
-lib/readline/shell.c
- - use the same INT_STRLEN_BOUND mechanism to decide how much space to
- allocated in sh_set_lines_and_columns
-
- 5/8
- ---
-aclocal.m4
- - add check for libtinfo (termcap-specific portion of ncurses-5.2) to
- BASH_CHECK_LIB_TERMCAP
- - new macro, RL_LIB_READLINE_VERSION, checks version of installed
- readline library and (optionally) writes version #defines to
- config.h. Bash doesn't use the version defines
-
-configure.in
- - call RL_LIB_READLINE_VERSION instead of support/rlvers.sh
-
-execute_cmd.c
- - fix execute_shell_script and the WHITECHAR and STRINGCHAR macros
- to check array bounds before indexing into the sample string
-
-unwind_prot.[ch]
- - import new versions submitted by Paul Eggert <eggert@twinsun.com>
- with a couple of changes for backwards compatibility, so the rest
- of the source doesn't need to be changed yet
-
-jobs.c
- - use unwind_protect_var on last_made_pid in run_sigchld_trap
-
-builtins/bind.def
- - use unwind_protect_var on rl_outstream
-
-general.c
- - rework print_rlimtype to use INT_STRLEN_BOUND and handle the
- most negative number correctly
-
-expr.c
- - `tokval' should have been a `long', since all arithmetic is done
- as longs
-
-builtins/history.def
- - consolidate tests for valid history position in one block to
- avoid duplicate code and strings
-
-builtins/ulimit.def
- - fix check for overflow when setting limit to work when int is 32
- bits and RLIMTYPE is 64
-
-lib/sh/tmpfile.c
- - don't truncate the result of time(3) to int; just use time_t,
- since it's being assigned to an `unsigned long'
-
-mailcheck.c
- - use legal_number instead of atoi in time_to_check_mail() to catch
- more numeric errors; consolidate error checking in one block
- - last_time_mail_checked should be a time_t
-
- 5/9
- ---
-builtins/set.def
- - recognize `set [-+]o nolog' if HISTORY is defined
-
-bashline.c
- - new variable `dont_save_function_defs', set by `set -o nolog';
- currently ignored
-
-command.h
- - the `dest' member of a REDIRECTEE is now an `int'
-
-parse.y,redir.c
- - changed uses of `redir.test' (where redir is a REDIRECTEE) since
- it's now an int
-
-lib/readline/rlstdc.h
- - don't mess around with `const', rely on configure to supply a
- proper definition if the compiler doesn't support it
-
-lib/tilde/tilde.h
- - include <config.h> if HAVE_CONFIG_H is defined
- - don't mess around with `const', rely on configure
-
-builtins/shopt.def
- - new read-only `shopt' option, login_shell, non-zero if shell is a
- login shell (as decided by shell.c)
- - new function set_login_shell(), sets shopt private value of
- login_shell
-
-builtins/common.h
- - new extern declaration for set_login_shell
-
-shell.c
- - call set_login_shell after setting value of login_shell (in
- main() and set_shell_name())
-
-parse.y
- - added new `\A' prompt string escape sequence: time in 24-hour
- HH:MM format
-
-configure.in, config.h.in
- - check for <grp.h>, define HAVE_GRP_H if found
-
-builtins/complete.def
- - add new `-A group/-g' option to complete group names
-
-pcomplete.h
- - new define for CA_GROUP, used with group name completion
-
-pcomplete.c
- - add code to support CA_GROUP group name completion
-
-bashline.c
- - new function, bash_groupname_completion_function(), supports
- programmable completion of group names
-
-bashline.h
- - extern declaration for bash_groupname_completion_function
-
-lib/readline/bind.c
- - new inputrc variable, `match-hidden-files', controls completion
- matching files beginning with a `.' (on Unix)
-
-lib/readline/complete.c
- - new variable, _rl_match_hidden_files, mirrors `match-hidden-files'
- inputrc variable
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_match_hidden_files
-
-builtins/hash.def
- - new `-t' option to list hash values for each filename argument
-
-builtins/read.def
- - alarm(3) takes an `unsigned int' argument, not int
- - check for arithmetic overflow with -t and -n options
-
-input.c
- - check for read error before doing \r\n translation on cygwin in
- b_fill_buffer
- - reset bp->b_used to 0 instead of leaving it at -1 on read error
- in b_fill_buffer
-
-builtins/shopt.def
- - new functions, shopt_setopt(name, mode) and
- shopt_listopt(name, mode) to give the rest of the shell an easy
- interface
-
-builtins/common.h
- - extern declarations for shopt_setopt and shopt_listopt
-
-shell.c
- - new invocation options -O and +O, to list or set/unset shopt
- options like +o/-o sets and unsets `set -o' options
-
-doc/{bash.1,bashref.texi}
- - document `set -o nolog'
- - document `login_shell' shopt option
- - document new `\A' prompt string escape sequence
- - document new `-t' option to `hash'
- - document new `[+-]O' invocation option
-
-doc/bashref.texi
- - add text to `Invoking Bash' section defining a login shell; text
- taken from man page
-
-doc/bash.1, lib/readline/doc/rluser.texinfo
- - documented new complete/compgen `-A group/-g' option
-
-lib/readline/doc/{rluser.texinfo,readline.3}, doc/bash.1
- - documented new `match-hidden-files' inputrc variable
-
- 5/10
- ----
-configure.in
- - fix AC_CHECK_PROG(ar, ...)
- - add AC_CHECK_TYPE for ssize_t
-
-config.h.in
- - new #undef for ssize_t
-
-lib/sh/zread.c
- - int -> ssize_t fixes to mirror modern declarations of read and write
- - the `off' variable in zsyncfd should be an off_t since it computes
- a file offset
- - the local buffer `lbuf' is now char, since it's not nice to pass
- unsigned char * to read(2), and the values from it are assigned to
- a char anyway
- - lind and lused are now size_t, since they index into a buffer
- - set lused to 0 on read error
-
-lib/sh/zwrite.c
- - change second argument to type `char *', since ISO C says you have
- to pass a `char *' to `write'
-
-externs.h
- - fix extern declarations of zread, zread1, zreadc, and zwrite
- - prototype extern declaration of qsort_string_compare
- - add extern declaration for history_delimiting_chars() from parse.y
-
-input.h
- - b_used and b_inputp members ofr struct BSTREAM are now size_t
-
-builtins/evalstring.c
- - the number of chars read with zread in cat_file should be assigned
- to a variable of type ssize_t
-
-input.c
- - the number of chars read with zread in b_fill_buffer should be
- assigned to a variable of type ssize_t
- - `localbuf' is now type char[], since POSIX says you shouldn't pass
- unsigned char * to read(2)
- - in getc_with_restart(), use a variable of type unsigned char to
- get a value from the local buffer and return it
- - in ungetc_with_restart, explicitly return the character arg passed
- to avoid relying on localbuf being unsigned char
-
-subst.c
- - the number of chars read with zread in read_comsub should be
- assigned to a variable of type ssize_t
-
-mksyntax.c
- - instead of casting to unsigned char * in addcstr, use a variable
- of type unsigned char and let the compiler do the work
-
-parse.y
- - instead of casting to unsigned char * in yy_readline_get, use a
- variable of type unsigned char and let the compiler do the work
- - ditto for yy_string_get and shell_getc (cast to unsigned char)
-
-subst.c
- - instead of casting to unsigned char when assigning to ifscmap in
- expand_word_internal, use a variable of type unsigned char and
- let the compiler do the work
-
-lib/sh/strtrans.c
- - instead of casting to unsigned char in ansic_quote, use a variable
- of type unsigned char and let the compiler do the work
-
-builtins/evalstring.c
- - remove extern declarations for zwrite and run_trap_cleanup; they're
- in externs.h
- - prototype cat_file forward declaration
-
-Makefile.in
- - remove -I$(includedir) from INCLUDES and SUBDIR_INCLUDES
-
-aclocal.m4
- - change RL_LIB_READLINE_VERSION to set RL_PREFIX, RL_LIBDIR,
- and RL_INCLUDEDIR to what it used to test the installed readline
- library version for use by the caller
- - change RL_LIB_READLINE_VERSION to not compute ac_cv_rl_prefix if
- the caller has already assigned it a value
- - rename _rl_prefix -> ac_cv_rl_prefix, _rl_libdir -> ac_cv_rl_libdir,
- _rl_includedir -> ac_cv_rl_includedir
-
-configure.in
- - change testing of whether to use the value of
- $opt_with_installed_readline to be != no, to allow the user to
- specify a prefix where the installed readline library may be found
- - if --with-installed-readline=PREFIX is supplied, set ac_cv_rl_prefix
- to PREFIX before calling RL_LIB_READLINE_VERSION
- - if --with-installed-readline[=PREFIX] is supplied, don't set
- RL_LIBDIR and RL_INCLUDEDIR; let RL_LIB_READLINE_VERSION take care
- of it, set RL_INCLUDE=-I${RL_INCLUDEDIR}
- - if --with-installed-readline[=PREFIX] is supplied, and we're
- linking with the history library, assign $RL_LIBDIR to HIST_LIBDIR
- so we use the same version of the installed readline and history
- libraries
-
-Makefile.in, builtins/Makefile.in
- - have configure substitute RL_INCLUDEDIR, set RL_INCLUDEDIR variable
-
-doc/bashref.texi
- - updated description of --with-installed-readline configure option
-
-general.c
- - moved QSFUNC typedef here from builtins/common.c
-
-{alias,bashline,variables,lib/sh/stringvec}.c
- - cast fourth argument to qsort to (QSFUNC *)
-
-alias.c
- - prototype forward declaration of qsort_alias_compare
-
-bashhist.c
- - include <glob/glob.h> for extern declaration of glob_pattern_p
- - remove extern declaration of history_delimiting_chars; it's now
- in externs.h
- - prototype forward declarations of histignore_item_func,
- maybe_add_history, and bash_add_history
-
-bracecomp.c
- - remove extern declaration for sh_backslash_quote; it's in externs.h
-
-braces.c
- - remove extern declaration for extract_command_subst; it's in subst.h
- - prototype forward declarations for expand_amble, array_concat, and
- brace_gobbler
-
-error.c
- - prototype extern declaration of give_terminal_to, fix bad call
-
-{execute_cmd,expr,findcmd,jobs,mailcheck,nojobs,pcomplete,print_cmd,redir,
-shell}.c
- - prototype all static forward function declarations
-
-pcomplete.c
- - changed some function parameters to `const char *' to avoid discarding
- const qualifier
-
-make_cmd.c
- - make_bare_word, make_word_flags, and make_word now take a
- `const char *' string argument
-
-make_cmd.h
- - changed extern declarations for make_bare_word and make_word
-
-print_cmd.c
- - cprintf now takes a `const char *' as its first argument, like
- xprintf and printf
- - the conditional define for xprintf should have been HAVE_VPRINTF,
- not HAVE_VFPRINTF
-
-shell.c
- - in isnetconn(), the return value of sizeof() is size_t
-
-aclocal.m4
- - add inclusion of stddef.h if STDC_HEADERS is defined to 1 in
- BASH_CHECK_TYPE
-
-configure.in
- - add a call to BASH_CHECK_TYPE for socklen_t (type of third argument
- to getpeername(2))
-
- 5/11
- ----
-lib/readline/bind.c
- - make `useq' a char array to pass to rl_macro_bind in
- rl_parse_and_bind
-
-lib/readline/{{bind,isearch}.c,rlprivate.h}
- - _rl_isearch_terminators is now a char *, not unsigned char *
-
-{subst,variables,lib/sh/tmpfile}.c
- - dollar_dollar_pid is now a `pid_t' instead of `int'
-
-variables.c
- - sbrand() now takes an `unsigned long' to set the seed value
- - changed last_random_value to type int, since it's always between
- 0 and 32767
- - use strtoul to convert the value in assign_random instead of atoi
- - take out casts in any arguments to sbrand()
- - take out cast to int in call to inttostr in set_ppid()
-
-subst.c
- - don't cast last_asynchronous_pid when passing to itos()
-
-{sig,subst}.c
- - prototype all static forward function declarations
-
- 5/14
- ----
-{test,trap,variables}.c
- - prototype all static forward function declarations
-
-variables.c
- - free_variable_hash_data() now takes a PTR_T, a `generic pointer'
-
-builtins/{alias,bind,break,cd,complete,declare,enable,exit,fc,fg_bg,help,
-history,jobs,pushd,read,set,trap,umask,
- - prototype all static forward function declarations
-
-builtins/read.def
- - reset_eol_delim now takes a `char *' arg, since that's what the
- unwind_protect functions pass it, and it ignores its arguments
- anyway
-
-lib/readline/{histsearch,input,kill,rltty,search,vi_mode}.c
- - prototype all static forward function declarations
-
-lib/tilde/tilde.c
- - prototype all static forward function declarations
- - tilde_find_prefix, tilde_find_suffix, isolate_tilde_prefix, and
- glue_prefix_and_suffix now take `const char *' arguments where
- appropriate
-
-configure.in,config.h.in
- - check for vsnprintf, define HAVE_VSNPRINTF if found
-
-lib/readline/display.c
- - use vsnprintf() in rl_message if it's available; if we don't, at
- least set the last character in msg_buf to 0 to avoid overrun --
- we really can't do anything about overflow at this point. if it's
- available, this fixes buffer overflow problems in rl_message
-
- 5/15
- ----
-lib/readline/histexpand.c
- - in get_history_word_specifier, allow any character to terminate
- a `:first-' modifier, not just `:' and null. This is what csh
- appears to do. This allows things like `!:0- xyzzy' to replace the
- last argument with xyzzy
-
- 5/18
- ----
-configure.in, config.h.in
- - check for <stdint.h>, define HAVE_STDINT_H if found
- - check for intmax_t in <stdint.h>, define intmax_t as long if not
- found
-
- 5/21
- ----
-builtins/kill.def
- - change to use strerror() for error message when kill(2) fails
-
-aclocal.m4
- - new macro, BASH_C_LONG_LONG, check for `long long'
-
-configure.in, config.h.in
- - call BASH_C_LONG_LONG, define HAVE_LONG_LONG if found
-
-lib/sh/snprintf.c
- - new file, with implementations of snprintf, vsnprintf, asprintf,
- and vasprintf, derived from inetutils version
-
-Makefile.in, lib/sh/Makefile.in
- - add snprintf.c/snprintf.o
-
-configure.in, config.h.in
- - add checks for snprintf, asprintf, vasprintf, with appropriate
- cpp defines
-
-lib/readline/{rldefs,xmalloc}.h, lib/readline/xmalloc.c
- - xmalloc and xrealloc now take `size_t' arguments, like their bash
- counterparts
-
-externs.h,lib/sh/itos.c
- - inttostr and itos now take `long' arguments
- - inttostr takes a `size_t' argument for the buffer size
-
-{expr,lib/malloc/malloc,variables,general}.c
- - fixed calls to itos() by removing casts, etc.
-
-subst.[ch]
- - get_dollar_var_value now takes a long, not an int
- - sub_append_number now takes a long, not an int
-
-subst.c
- - in parameter_brace_expand_word, use a long and legal_number to
- translate ${N}, to avoid overflow
- - in parameter_brace_expand_length, use a long and legal_number to
- translate ${#N}, to avoid overflow
- - in do_array_element_assignment, array_expand_index,
- array_value_internal, use arrayind_t instead of int
- - let verify_substring_values take long * arguments for the return
- value of evalexp()
- - pass long * arguments to verify_substring_values in
- parameter_brace_substring
- - parameter_brace_expand_length now returns `long'
- - parameter_brace_expand now uses a long variable for the return
- value of parameter_brace_expand_length
- - param_expand now uses a long variable for the return value from
- evalexp
- - array_length reference now returns an `arrayind_t', since it can
- return the num_elements member of an array, which is of type
- arrayind_t
-
-subst.h
- - array_expand_index now returns an `arrayind_t'
-
-array.[ch]
- - array_subrange now takes arrayind_t arguments, not `int'
- - dup_array_subrange now uses arrayind_t local variable to do
- array indexing
- - use long to print array indices in print_element
-
-variables.c
- - null_array_assign, assign_dirstack, bind_array_variable
- now take arrayind_t arguments as array indices
- - assign_array_var_from_word_list, assign_array_var_from_string,
- unbind_array_element now use arrayind_t local variables for
- array indexing
-
-variables.h
- - change extern declaration of bind_array_variable
-
-builtins/common.[ch]
- - get_numeric_arg now returns a `long', since it usually returns
- the value of legal_number()
-
-builtins/{shift,break}.def
- - use long variables for the return value of get_numeric_arg
-
-builtins/history.def
- - convert string argument to int only if it's in range
-
-builtins/pushd.def
- - set_dirstack_element and get_dirstack_element now take `long'
- index arguments
- - get_dirstack_index now takes a `long' index argument, since it's
- passed the converted value from legal_number
-
-lib/sh/timeval.c
- - in print_timeval, don't assume that the number of minutes fits into
- an int, since it's just seconds/60.
-
-lib/sh/clock.c
- - ditto for print_clock_t
-
- 5/22
- ----
-shell.c
- - since the -O option settings may possibly be overridden by the
- normal shell initialization or posix initialization, save the
- invocation options on an alist (with add_shopt_to_alist) and
- process them after basic initialization (with run_shopt_alist)
-
- 5/23
- ----
-trap.h
- - new define, BASH_NSIG, all system signals plus special bash traps
-
-trap.c, builtins/trap.def
- - use BASH_NSIG for array bounds and loops where appropriate
-
-trap.c
- - change decode_signal to disallow numeric signal numbers above
- NSIG -- this means you can only reference special traps like
- DEBUG by name
- - new SPECIAL_TRAP(s) macro to test whether s is one of the special
- bash traps (currently DEBUG and EXIT)
- - change reset_or_restore_signal_handlers so command substitution
- doesn't inherit the debug trap (like ksh93), and child processes
- don't have to rely on initialize_traps being run to get rid of
- any debug trap
-
-support/mksignames.c
- - add extra "ERR" signal name, value NSIG+1, allocate space for it
- and write it out in signal_names[]
-
-trap.h
- - new define: ERROR_TRAP == NSIG+1, change BASH_NSIG to NSIG+2
- - extern declarations for set_error_trap, run_error_trap
- - new define: TRAP_STRING(s), expands to trap_list[s] if signal S
- is trapped and not ignored, NULL otherwise
-
-trap.c
- - add ERROR_TRAP to SPECIAL_TRAPS define
- - initialize ERROR_TRAP stuff in initialize_traps
- - new function: set_error_trap(command), sets the ERR trap string
- - new function: run_error_trap(command), runs the ERR trap string
- - set trap string for ERROR_TRAP to NULL in free_trap_strings
- - change reset_or_restore_signal_handlers so child processes don't
- inherit the ERR trap
- - add case to call run_error_trap in maybe_call_trap_handler
-
-execute_cmd.c
- - in execute_command_internal, keep track of ERR trap and call it if
- necessary
- - use TRAP_STRING to get the value of debug and error traps
- - in execute_function, arrange things so the ERR trap is not inherited
- by shell functions, and is saved and restored like the DEBUG trap
-
-doc/{bash.1,bashref.texi}
- - documented new ERR trap
-
-tests/{trap.{tests,right},trap2.sub,trap2a.sub}
- - added ERR trap tests
-
-subst.c
- - on machines without /dev/fd, change the named pipe fifo list to a
- list of structs containing pathname and proc information
- - change unlink_fifo_list to kill the proc in the fifo list with
- signal 0 and not remove the fifo if the proc is still alive. This
- should fix the problem on those backward systems without /dev/fd
- where fifos were removed when a job using process substitution was
- suspended
-
- 5/24
- ----
-examples/loadables/getconf.h
- - new file, with basic defines needed to make getconf work minimally
- on POSIX systems without the necessary definitions
-
-examples/loadables/getconf.c
- - replacement functions for confstr, sysconf, pathconf for systems
- that lack them, providing a minimal posix interface
- - heavily augmented getconf, now supports all POSIX.1-200x,
- POSIX.2-200x, Solaris 7, AIX 4.2 getconf variables
-
- 5/29
- ----
-builtins/setattr.def
- - make `readonly', `export', and `declare' print `invisible' variables
- as just a command and variable name, without a value, when listing
- all variables (as POSIX.2-200x d6 requires)
-
- 5/30
- ----
-
-configure.in
- - upgraded to autoconf-2.50 on main development machine, so require
- autoconf-2.50 in preparation for using some if its new features
- - call AC_C_PROTOTYPES
- - remove call to AC_EXEEXT, which now does the wrong thing
- - changed AC_INIT to new flavor
- - added call to AC_CONFIG_SRCDIR
- - AC_CONFIG_HEADER -> AC_CONFIG_HEADERS
- - AC_RETSIGTYPE -> AC_TYPE_SIGNAL
-
-configure.in, aclocal.m4, config.h.in
- - removed call to BASH_LARGE_FILE_SUPPORT, use AC_SYS_LARGEFILE
- standard support, with new macros _FILE_OFFSET_BITS and
- _LARGE_FILES
- - removed definition of BASH_LARGE_FILE_SUPPORT
-
-doc/bashref.texi
- - document new `--enable-largefile' configure option
-
-lib/readline/readline.c
- - change rl_set_prompt to call rl_expand_prompt unconditionally, so
- local_prompt and local_prompt_prefix get set correctly
-
- 6/6
- ---
-lib/readline/complete.c
- - don't append `/' or ` ' to a match when completing a symlink that
- resolves to a directory, unless the match doesn't add anything
- to the word. This means that a tab will complete the word up to
- the full name, but not add anything, and a subsequent tab will add
- a slash. Change to append_to_match; callers changed
-
-hashlib.c
- - new function, hash_table_nentries (table), returns the number of
- items in TABLE
-
-hashlib.h
- - extern declaration for hash_table_nentries
-
-configure.in
- - configure without bash malloc on openbsd; they claim it needs
- eight-bit alignment (which the bash malloc provides, but...)
-
- 7/2
- ---
-stringlib.c
- - only call RESIZE_MALLOCED_BUFFER from strsub() if the replacement
- string length is > 0, avoid possible hangs if replacement is null
-
-subst.c
- - don't include input.h; no longer needed
-
-configure.in
- - remove calls to AC_SYS_RESTARTABLE_SYSCALLS and
- BASH_SYS_RESTARTABLE_SYSCALLS; the results are no longer used
-
-config.h.in
- - remove define for HAVE_RESTARTABLE_SYSCALLS
-
-aclocal.m4
- - removed definition of BASH_SYS_RESTARTABLE_SYSCALLS; no longer used
-
-execute_cmd.c
- - changed select command so `return' no longer terminates the select
- command, so it can be used to return from an enclosing function.
- This is as ksh (88 and 93) does it
-
-lib/readline/vi_mode.c
- - fix trivial typo in declaration of vi_motion; `t' appears twice;
- the second instance should be `T'
-
- 7/3
- ---
-configure.in
- - don't add -static to LDFLAGS on Solaris 2.x. This means that the
- auxiliary programs will be built as dynamic executables, but that
- should do no harm
-
- 7/5
- ---
-lib/glob/fnmatch.c
- - fix the code that processes **(pattern) to short-circuit if the
- pattern is ill-formed or lacks a trailing `)' -- this fixes the
- segfault on **(/*)
-
-Makefile.in, builtins/Makefile.in
- - split CCFLAGS into CCFLAGS_FOR_BUILD and CFLAGS, to aid in
- cross-compilation
- - build programs that use $(CC_FOR_BUILD) using $(CCFLAGS_FOR_BUILD)
-
-configure.in, config.h.in
- - check for getaddrinfo(3), define HAVE_GETADDRINFO if found
-
-lib/sh/netopen.c
- - implemented a version of _netopen (_netopen6) that uses
- getaddrinfo(3) if available, use if HAVE_GETADDRINFO is defined.
- old _netopen is _netopen4; _netopen now calls either _netopen6
- or _netopen4 as appropriate
-
- 7/9
- ---
-builtins/exit.def
- - don't source ~/.bash_logout if subshell_environment is non-zero
-
-execute_command.c
- - in execute_until_or_while, handle the case where `breaking' is
- set in the loop test (e.g., by the job control code when a job
- is stopped with SIGTSTP), but the return value from the test is
- something that would cause the loop to break. Need to decrement
- `breaking' in this case
-
- 7/10
- ----
-execute_cmd.c
- - in execute_in_subshell, make sure a command of type cm_subshell
- inherits its `enclosing' command's CMD_IGNORE_RETURN flag
-
-variables.c
- - in maybe_make_export_env, don't allow restricted shells to put
- exported functions in the export environment
-
- 7/11
- ----
-lib/glob/strmatch.h
- - renamed old fnmatch.h
- - changed guard #ifdef to _STRMATCH_H
- - include system <fnmatch.h> if HAVE_LIBC_FNM_EXTMATCH is defined
-
-lib/glob/strmatch.c
- - renamed old fnmatch.c
- - include "strmatch.h"
- - if HAVE_LIBC_FNM_EXTMATCH is defined, define a dummy version of
- strmatch() that just calls fnmatch(3)
-
-lib/glob/glob.c
- - include "strmatch.h"
- - fnmatch -> strmatch
-
-Makefile.in, lib/glob/Makefile.in
- - fnmatch -> strmatch
-
-{bashhist,execute_cmd,pathexp,pcomplete,shell,stringlib,subst,test}.c,
-pathexp.h,builtins/help.def
- - include <glob/strmatch.h>
- - fnmatch -> strmatch
-
-execute_cmd.c
- - broke the code that parses the interpreter name from a #! line
- out from execute_shell_script to a new function, getinterp()
- - call getinterp from execute_shell_script
- - use return value from getinterp in error message about bad
- #! interpreter in shell_execve
-
- 7/12
- ----
-lib/readline/isearch.c
- - the last isearch string is now remembered in a new static variable,
- last_isearch_string
- - if ^R^R is typed, readline now searches for the remembered isearch
- string, if one exists
-
- 7/24
- ----
-pcomplete.h
- - extern declaration for completions_to_stringlist()
-
- 7/25
- ----
-builtins/complete.def
- - make compgen handle -o default option
- - make compgen return success only if sl->list_len is non-zero,
- indicating that there are items on the list
-
- 7/31
- ----
-execute_cmd.c
- - in execute_connection, force stdin to /dev/null for asynchronous
- commands if job control is not active, not just if the shell is
- running a shell script (since you can run `set -m' in a script)
-
-lib/readline/rltty.c
- - make sure _rl_tty_restore_signals resets `tty_sigs_disabled' on
- successful restoration of the terminal modes
- - make sure _rl_tty_disable_signals turns off IXON so that ^S and
- ^Q can be read by rl_quoted_insert
-
- 8/1
- ---
-aclocal.m4
- - new check for FNM_EXTMATCH being defined in <fnmatch.h>, as Ullrich
- Drepper intends to do for new versions of GNU libc
-
-config.h.in
- - new definition for HAVE_LIBC_FNM_EXTMATCH
-
-configure.in
- - check for fnmatch, but don't define anything in config.h
- - call BASH_FUNC_FNMATCH_EXTMATCH to check for FNM_EXTMATCH
-
- 8/2
- ---
-alias.h
- - remove bogus extern declaration for xmalloc()
- - include "stdc.h"
- - add prototype declarations for all extern function declarations
-
-xmalloc.c,lib/readline/xmalloc.c
- - fix xmalloc to return a PTR_T
- - fix xrealloc to return a PTR_T and take a PTR_T as first argument
-
-include/ansi_stdlib.h
- - extern declarations for malloc and realloc have them return PTR_T
-
-xmalloc.h
- - new file, with extern declarations for functions in xmalloc.c
-
-general.h
- - removed extern declarations for functions in xmalloc.c
- - include xmalloc.h
-
-Makefile.in,builtins/Makefile.in
- - update dependencies to include xmalloc.h
-
-parse.y,{alias,array,bashline,bracecomp,execute_cmd,findcmd,flags,general,
-hashcmd,locale,mailcheck,make_cmd,pathexp,pcomplete,print_cmd,stringlib,
-subst,unwind_prot,variables}.c
-builtins/{common,evalfile}.c
-builtins/{cd,command,enable,exec,printf,read,set}.def
-lib/sh/{makepath,netopen,pathphys,setlinebuf,shquote,snprintf,stringlist,
-strtrans,tmpfile}.c
-lib/readline/{util,terminal,shell,readline,macro,kill,isearch,input,
-histfile,histexpand,display,complete,bind}.c
- - make sure all calls to xmalloc are cast to the right return value
-
-siglist.c
- - include xmalloc.h
-
-parse.y,{alias,bashline,bracecomp,expr,make_cmd,nojobs,print_cmd,subst}.c
-builtins/{fc,printf,read}.def
-lib/sh/snprintf.c, lib/tilde/tilde.c
-lib/readline/{bind,display,histexpand,isearch,macro,util,vi_mode}.c
- - make sure all calls to xrealloc are cast to the right return value
-
-lib/sh/{netopen,setlinebuf,shquote,snprintf}.c, lib/tilde/tilde.c
- - include xmalloc.h, remove extern declaration of xmalloc
-
-lib/readline/xmalloc.h
- - xmalloc and xrealloc should return PTR_T
-
-lib/readline/rldefs.h
- - don't include an extern declaration for xmalloc
-
- 8/7
- ---
-support/shobj-conf
- - fixed up commented-out stanzas for HP's unbundled C compiler on
- HP/UX
-
-support/bashbug.sh
- - force the subject to be changed from the default
-
-lib/readline/doc/{rluser.texinfo,readline.3}, doc/bash.1
- - document that transpose-words swaps the last two words on the line
- if point is at the end of the line
-
- 8/9
- ---
-stringlib.c
- - fix possible infinite recursion problem with null pattern in
- strsub()
-
-hashlib.c
- - new function copy_hash_table to copy a hash table using a caller-
- supplied function to copy item data (defaults to savestring())
-
-hashlib.h
- - new extern declaration for copy_hash_table
-
-builtins/declare.def
- - changes so that declare [-a] var=value assigns `value' to element 0
- of array variable `var' like ksh93
- - change so that declare [-a] var[N]=value assigns `value' to element
- N of array variable `var' like ksh93
-
- 8/13
- ----
-arrayfunc.c
- - new file, for miscellaneous array functions
-
-arrayfunc.h
- - new file, extern declarations for functions in arrayfunc.c
-
-variables.c
- - move convert_var_to_array, bind_array_variable,
- assign_array_from_string, assign_array_var_from_word_list,
- assign_array_var_from_string, quote_array_assignment_chars,
- skipsubscript, unbind_array_element, print_array_assignment
- to arrayfunc.c
-
-shell.h
- - include arrayfunc.h after variables.h
-
-variables.h
- - remove above extern function declarations moved to arrayfunc.h
- - add extern declaration for var_lookup
-
-Makefile.in
- - add arrayfunc.c, arrayfunc.h in appropriate places
- - add arrayfunc.h to dependencies
-
-subst.c
- - move valid_array_reference, array_expand_index, array_variable_part,
- array_value_internal, array_value (now global), get_array_value,
- do_array_element_assignment to arrayfunc.c
-
-subst.h
- - extern declarations for functions above moved to arrayfunc.h
-
-arrayfunc.h
- - extern declarations for above functions from subst.c
-
-subst.[ch]
- - string_list_dollar_star and string_list_dollar_at are now global
- functions
- - quote_escapes is now a global function
-
-subst.c
- - maybe_expand_string -> expand_string_if_necessary
- - expand_string_to_string -> expand_string_to_string_internal
- - new functions: expand_string_to_string and
- expand_string_unsplit_to_string, which call
- expand_string_to_string_internal with expand_string and
- expand_string_unsplit as the FUNC arguments, respectively
-
-arrayfunc.c
- - change array_expand_index to call expand_string_to_string instead
- of maybe_expand_string
-
- 8/14
- ----
-shell.c
- - in execute_env_file, call expand_string_unsplit_to_string
-
-mailcheck.c
- - in check_mail, call expand_string_to_string
-
-variables.c
- - in assign_in_env, call expand_string_unsplit_to_string
-
-arrayfunc.c
- - new function, array_variable_name, splits an array reference into
- a name (which is returned as a new string) and subscript
- - change array_variable_part to just call array_variable_name and
- look up the string returned with find_variable
- - new function, find_or_make_array_variable (name, flags) which will
- look up an array variable and convert a string variable to an
- array if necessary. The FLAGS argument, if non-zero, says to
- check the readonly and noassign attributes and fail if either is set
-
-builtins/read.def
- - make `read -a aname' honor any readonly status of `aname'
- - read -a now calls find_or_make_array_variable with FLAGS value 1
-
-arrayfunc.[ch], subst.c, builtins/{declare,read}.def
- - do_array_element_assignment -> assign_array_element
-
- 8/20
- ----
-parse.y
- - changed `for' command grammar to allow missing word list after `IN'
- token, like latest POSIX drafts require
-
-lib/sh/tmpfile.c
- - in sh_mktmpname(), check for filenum == 0 and init to non-zero number
- in this case. it can happen on arithmetic overflow
-
-support/mkversion.sh
- - added `[0-9].[0-9][0-9][a-z]' as an acceptable value for a
- distribution to allow for intermediate versions, like 2.05a
-
-support/config.guess
- - removed the addition of the output of `/usr/bin/objformat' when
- creating the canonical name on FreeBSD machines, so the canonical
- name is once again `freebsd4.2' instead of `freebsdelf4.2'
-
- 8/22
- ----
-lib/readline/{rlstdc,history,keymaps,readline,rldefs,rlprivate,rlshell,
-rltypedefs,xmalloc}.h
-lib/readline/{bind,compat,complete,display,funmap,histexpand,histsearch,
-input,isearch,kill,nls,parens,readline,rltty,search,shell,signals,vi_mode
- - changed __P to PARAMS
-
-lib/tilde/tilde.[ch]
- - changed __P to PARAMS
-
-{Makefile,configure}.in
- - changed the version number to 2.05a
- - changed the release status to `alpha1'
-
- 8/23
- ----
-support/shobj-conf
- - support for building shared libraries on Darwin/MacOS X
-
-siglist.h
- - extern declaration for strsignal() to compensate for lack of
- a definition in some system include files
-
-jobs.c
- - remove casts from strsignal() calls
-
-[bash-2.05a-alpha1 frozen]
-
- 8/27
- ----
-[bash-2.05a-alpha1 released]
-
- 8/27
- ----
-execute_cmd.c
- - fix eval_arith_for_expr to handle the case where the expanded
- word list is NULL, returning 0 in this case
-
-print_cmd.c
- - in print_function_def, make sure that func_redirects is assigned
- a value before being used
-
- 8/28
- ----
-alias.c
- - include <ctype.h> for definition of isalpha()
-
-bashhist.h
- - add prototypes for extern function declarations
-
-flags.c
- - include bashhist.h for extern function declarations
-
-mksyntax.c
- - include <unistd.h> if HAVE_UNISTD_H is defined in config.h
-
-parse.y
- - include test.h for extern function declarations
-
-externs.h
- - change extern declaration for setlinebuf to sh_setlinebuf
-
-stringlib.c
- - include <glob/glob.h> for extern function declarations
-
-variables.h
- - add function prototypes for all of the sv_* functions
-
-builtins/common.h
- - add extern declarations for set_shellopts() and parse_shellopts()
- from builtins/set.def
-
-variables.c
- - include "hashcmd.h" for extern declaration for flush_hashed_filenames
- - include "pathexp.h" for extern declaration for setup_glob_ignore
-
-lib/malloc/malloc.c
- - cast to `long' instead of `int' in memalign for 64-bit machines
-
-{pcomplete,trap}.c
- - changed printf escape sequences used to print pointers to %p
-
-lib/readline/undo.c
- - include "xmalloc.h" for extern function declaration
-
-input.h
- - add function prototypes to extern declarations for getc_with_restart
- and ungetc_with_restart
-
-variables.[ch]
- - changed type of `function' member of `struct name_and_function' to
- `sv_func_t', which is defined and prototyped in variables.h
- - map_over now takes an `sh_var_map_func_t *'
-
-shell.h
- - start of a set of function pointer typedefs like those in
- lib/readline/rltypedefs.h
-
-hashlib.[ch]
- - second paramter to flush_hash_table is now an `sh_free_func_t *'
-
-trap.c
- - parameter to reset_or_restore_signal_handlers is now an
- `sh_resetsig_func_t *'
-
-pcomplete.h, pcomplib.c
- - function pointer argument to print_all_compspecs is now an
- `sh_csprint_func_t *'
- - function pointer `list_getter' element of an `ITEMLIST' is now
- prototyped with __P((...)) instead of using `Function *'
-
-jobs.[ch]
- - `j_cleanup' member of a JOB is now an `sh_vptrfunc_t *'
-
-alias.c
- - map_over_aliases now takes an `sh_alias_map_func_t *'
- - free_alias_data now takes a `PTR_T'
-
-pathexp.c
- - function pointer argument to ignore_globbed_names is now an
- `sh_ignore_func_t *'
-
-bashline.c
- - function pointer argument to _ignore_completion_names is now an
- `sh_ignore_func_t *'
-
-pathexp.h,{bashhist,bashline.c
- - `item_func' member of a `struct ignorevar' is now an
- `sh_iv_item_func_t *'
-
-builtins/evalfile.c
- - `errfunc' is now an `sh_vmsg_func_t *'
-
-jobs.c
- - map_over_job now takes an `sh_job_map_func_t *' as its first argument
-
-array.[ch]
- - function pointer argument to array_walk is now an
- `sh_ae_map_func_t *'
-
-general.c
- - tilde_expansion_preexpansion_hook has type `tilde_hook_func_t *',
- and so the assignment in tilde_initialize doesn't need a cast
-
-list.c
- - map_over_words now takes an `sh_icpfunc_t *' as its second argument
-
-input.h
- - the `getter' and `ungetter' function pointer members of a
- BASH_INPUT are now of types `sh_cget_func_t *' and
- `sh_cunget_func_t *' respectively
- - init_yy_io now takes an `sh_cget_func_t *' as its first argument and
- an `sh_cunget_func_t *' as its second
-
-parse.y
- - init_yy_io now takes an `sh_cget_func_t *' as its first argument and
- an `sh_cunget_func_t *' as its second
- - initialize_bash_input casts bash_input.getter and bash_input.ungetter
- appropriately
-
-builtins/mkbuiltins.c
- - make the extern function definitions written to builtext.h have
- prototypes with __P((...))
- - include "stdc.h"
- - change Function to mk_handler_func_t
- - fixed comment_handler to take the right number of args
- - prototyped all the handler functions with __P((...))
-
-builtins.h
- - the `function' member of a struct builtin is now of type
- `sh_builtin_func_t *'
-
-builtins/common.[ch]
- - last_shell_builtin, this_shell_builtin are now of type
- `sh_builtin_func_t *'
- - find_shell_builtin, builtin_address, find_special_builtin now return
- `sh_builtin_func_t *'
-
-builtins/exit.def, {execute_cmd,jobs,nojobs,variables}.c, parse.y
- - changed all declarations of last_shell_builtin and this_shell_builtin
-
-execute_cmd.c
- - execute_builtin, execute_builtin_or_function,
- execute_subshell_builtin_or_function now take an
- `sh_builtin_func_t *' instead of a `Function *' for argument
- - changed appropriate variables from `Function *' to
- `sh_builtin_func_t *'
-
-builtins/{bind,builtin,enable,read,setattr}.def
- - replaced uses of `Function *' in variable declarations with
- appropriate types (sh_builtin_func_t * or rl_command_func_t *)
-
-builtins/set.def
- - set_func and get_func members of binary_o_options are now of types
- `setopt_set_func_t *' and `setopt_get_func_t *', which are
- prototyped
-
-builtins/shopt.def
- - set_func member of shopt_vars is now of type `shopt_set_func_t *'
-
-bashline.c
- - enable_hostname_completion now returns `int' (the old value of
- perform_hostname_completion)
-
-[The only use of Function and VFunction now is for unwind-protects]
-
- 9/4
- ---
-lib/sh/getcwd.c
- - use const define from config.h rather than `CONST'
- - use PTR_T define from xmalloc.h rather than `PTR'
- - include xmalloc.h for PTR_T
- - remove PATH_MAX define, rely on value from maxpath.h
-
-{general,mailcheck}.c, lib/sh/{pathcanon,pathphys}.c
- - don't include maxpath.h directly; it's already included by shell.h
-
-lib/sh/mailstat.c
- - new `mailstat()' implementation, to stat a mailbox file for
- mail checking. handles maildir-style mail directories with one
- file per message and creates a dummy stat struct from them
-
-lib/sh/Makefile.in
- - add mailstat.c and mailstat.o in the appropriate places
-
-lib/malloc/malloc.c
- - augmented implementation with wrapper functions that pass in file
- and line number information from cpp. currently unused, but a
- placeholder for future debugging and use tracking
-
-lib/malloc/shmalloc.h
- - new file, extern declarations for allocation wrapper functions for
- use by the shell (and others, I guess)
-
-xmalloc.[ch]
- - wrapper functions for xmalloc, xfree, xrealloc (sh_ prefixed) that
- pass cpp line number information through to the malloc functions,
- if USING_BASH_MALLOC is defined
-
- 9/5
- ---
-lib/malloc/gmalloc.c
- - removed; no longer part of distribution
-
-lib/malloc/Makefile.in
- - removed references to gmalloc.[co]
-
-configure.in, doc/bashref.texi
- - removed references to `--with-glibc-malloc' configure option
-
-{configure,Makefile}.in
- - changed the way bash malloc is configured into the Makefile, making
- it more like how readline is configured. If the bash malloc is
- not configured in, nothing in lib/malloc will be built
-
- 9/6
- ---
-lib/malloc/imalloc.h
- - new file, some internal malloc definitions
-
-lib/malloc/mstats.h
- - new file, definitions for malloc statistics structs and functions
-
-lib/malloc/trace.c
- - new file, malloc tracing functions (currently just print messages
- to stderr), code is #ifdef MALLOC_TRACE
-
-lib/malloc/stats.c
- - new file, moved malloc stats code from malloc.c to here
-
-lib/malloc/malloc.c
- - moved some definitions to imalloc.h
- - moved stats code to stats.c
- - malloc tracing calls added to internal_{malloc,realloc,free}, all
- #ifdef MALLOC_TRACE
-
-lib/malloc/Makefile.in, Makefile.in
- - added {imalloc,mstats}.h, {trace,stats}.c
-
-parse.y
- - changed decode_prompt_string to save and restore $?
- (last_command_exit_value) around calls to expand_prompt_string(),
- so command substitutions in PS1, etc. don't change $?
-
-{array,subst}.c
- - a couple more arrayind_t fixes from Paul Eggert
-
-configure.in
- - remove redundant check for wait3(2)
-
-redir.h
- - fixed a typo (stdin_redirs -> stdin_redirects)
-
- 9/10
- ----
-execute_cmd.c
- - remove check for \n and \r from WHITESPACE macro, since those
- chars are not whitespace as returned by the whitespace(c) macro
- - getinterp now takes a `char *' as first arg, not unsigned char *
- - execute_shell_script now takes a `char *' as first arg, not
- unsigned char *
- - fix typo in forward declaration for `initialize_subshell'
-
-general.[ch]
- - check_binary_file now takes a (char *) argument, not unsigned char *
- - pass unsigned char to isspace and isprint because of ISO C fuckup
- - bash_tilde_expand now takes a `const char *' as its argument
-
-builtins/evalfile.c, shell.c
- - buffer passed to check_binary_file is char, not unsigned char
-
-parse.y
- - fix extern declaration for yyerror()
- - yyerror now takes a `const char *' as first arg
-
-{error,jobs}.c
- - fixes to printf-style functions to handle pids wider than an int
-
-lib/readline/{isearch,vi_mode}.c
- - fix call to rl_message in rl_display_search (remove extra arg)
-
-variables.c
- - fix missing argument to builtin_error in make_local_variable
-
-builtins/getopts.def
- - since getopts takes no options, change while loop calling
- internal_getopts to a simple `if' check
-
-builtins/printf.def
- - since printf takes no options, change while loop calling
- internal_getopts to a simple `if' check
-
-lib/readline/bind.c
- - remove _SET_BELL macro, expand code inline
-
-lib/readline/input.c
- - change _rl_input_available to use either select or FIONREAD,
- but not both
-
-lib/readline/readline.c
- - fix rl_digit_loop to remove unreachable code at end of loop
-
-{bashhist,bashline,expr,jobs,redir,shell}.c, builtins/fc.def, lib/sh/snprintf.c
- - bracket unused functions with #ifdef INCLUDE_UNUSED/#endif
- - remove some unused variables
-
-execute_cmd.c
- - remove #ifdef'd code that allowed `return' to terminate a select
- statement
-
-expr.c
- - remove some extraneous tests from strlong()
-
-array.h
- - arrayind_t is now a long, since shell arithmetic is performed as
- longs
- - remove second declaration of new_array_element
-
-builtins/printf.def
- - in mklong, xrealloc cannot return NULL, so don't check for it
- - remove some #if 0 code
- - fix core dump triggered by a format specification with more than
- one `*'
- - remove `foundmod', since its value mirrors `modchar != 0'
- - include "common.h" for builtin_{error,usage} declarations
-
-Makefile.in,builtins/Makefile.in
- - updated some dependencies due to new include files
-
-pcomplete.c
- - include "execute_cmd.h" for declaration of execute_shell_function
-
-arrayfunc.c
- - include <stdio.h> for printf
- - include "builtins/common.h" for builtin_error declaration
-
-builtins/evalstring.c
- - include "../trap.h" for run_trap_cleanup declaration
-
-builtins/help.def
- - include "common.h" instead of locally declaring builtin_error
- and builtin_usage
-
-error.h
- - add extern declaration for itrace()
- - add prototype to extern declaration of get_name_for_error
- - file_error now takes a `const char *' as first argument
-
-externs.h
- - added prototype for sh_setlinebuf declaration, bracketed with
- NEED_SH_SETLINEBUF_DECL so we don't need stdio.h everywhere
- - add extern declaration for parse.y:return_EOF()
-
-shell.c
- - add NEED_SH_SETLINEBUF_DECL before including shell.h
-
-lib/readline/callback.c
- - include <stdlib.h> or "ansi_stdlib.h" for abort declaration
-
-quit.h
- - remove declaration of throw_to_top_level
-
-subst.c
- - remove unused extern declaration for getopts_reset
-
-lib/sh/netopen.c
- - include <shell.h> for legal_number, etc.
- - add prototype for inet_aton extern declaration
-
-lib/sh/clock.c
- - include <stdc.h> for __P declaration
- - add extern declaration for get_clk_tck
-
-support/mkversion.sh
- - changed so that extern function declarations for functions in
- version.c (moved from externs.h) are in the generated version.h
-
-shell.h
- - include version.h
-
-version.c
- - various `char *' version variables are now `const char *'
-
-general.h
- - add prototype for same_file, bracketed with _POSIXSTAT_H
- #ifdef, since that's what include/posixstat.h defines
-
-builtins/common.[ch]
- - _evalfile, maybe_execute_file, source_file, and fc_execute_file
- now take a `const char *' as their first argument
-
-eval.c
- - removed extern declaration of yyparse; it's in externs.h
-
-parse.y
- - added prototypes to static forward function declarations
- - changed local `all_digits' variable in read_token_word () to
- all_digit_token to avoid clash with all_digits() function in
- general.c
-
-{bashhist,copy_cmd,make_cmd,hashlib,mailcheck}.c
- - added prototypes for static function declarations
-
-shell.h
- - add extern declarations for interactive, interactive_shell,
- changed c files with extern declarations
-
-pcomplete.c
- - changed it_init_aliases to avoid shadowing global variable
- `aliases'
-
-bashline.c,pathexp.c,general.h
- - sh_ignore_func_t is now a pointer to a function taking a
- `const char *'; users changed
-
-configure.in
- - test for <strings.h>
-
-config.h.in
- - add #undef HAVE_STRINGS_H
-
-bashansi.h
- - change like recommended in autoconf manual
-
- 9/11
- ----
-[a date which will live in infamy. prayers for the victims.]
-
-execute_cmd.c
- - don't use an absolute index into abuf in mkfmt, use
- sizeof(abuf) to compute last index
-
-builtins/common.c
- - fix read_octal to do a better job of detecting overflow while
- iterating through the string
-
-builtins/umask.def
- - change octal-print mode to print 4 digits, like other shells
- - cast umask to unsigned long to avoid problems on systems where
- it's wider than an int (POSIX doesn't guarantee that mode_t is
- no wider than an int, but real-world systems use int)
-
-builtins/printf.def
- - mklong can never return NULL (it uses xrealloc), so the mainline
- doesn't need to check for NULL returns
- - new function, getldouble (long double *), to get long doubles
- - mklong now takes a `char *' as its second argument, the modifier(s)
- to use
- - changed use of `modchar' to handle more than a single modifier
- character
- - changed to handle `long double' and `L' formats better, rather
- than discarding long double information
- - since printf now follows the POSIX.2 rules for conversion errors,
- we can dispense with the status returns from the get* functions
- - make the get* functions as similar in structure as possible,
- removing type casts, etc.
-
-lib/sh/timeval.c,execute_cmd.c
- - change some instances of `long' to `time_t', for systems where
- a time_t is bigger than a long
-
-jobs.c
- - include "posixtime.h" instead of <sys/time.h>
-
-config.h.in
- - add defines for HAVE_DECL_CONFSTR, HAVE_DECL_STRTOLD,
- HAVE_DECL_SBRK, HAVE_DECL_PRINTF
- - remove defines for SBRK_DECLARED and PRINTF_DECLARED
- - add _GNU_SOURCE define
-
-configure.in
- - add AC_CHECK_DECLS for strtold, confstr, sbrk, printf
- - remove call to BASH_FUNC_SBRK_DECLARED
- - remove call to BASH_FUNC_PRINTF
-
-xmalloc.c, lib/malloc/malloc.c
- - change check of SBRK_DECLARED to HAVE_SBRK_DECL
-
-print_cmd.c
- - change PRINTF_DECLARED to HAVE_DECL_PRINTF
-
-builtins/evalstring.c, builtins/common.h
- - parse_and_execute now takes a `const char *' as its second argument
-
-input.h,parse.y
- - with_input_from_* functions now take a `const char *' as their
- second argument
- - init_yy_io now takes a `const char *' as its fourth argument
-
-parse.y,externs.h
- - parse_string_to_word_list now takes a `const char *' as its second
- argument
-
-tests/builtins.right
- - change output to account for extra digit in umask output
-
-pcomplib.c
- - free_progcomp now takes a PTR_T argument
-
-builtins/bashgetopt.h
- - include <stdc.h>
- - add prototypes to extern declarations
-
-builtins/shopt.def
- - add prototypes to static function declarations
-
-builtins/{fc,umask,wait}.def, builtins/{bashgetopt,common}.c
- - include <ctype.h> for isdigit macro (referenced by `digit(x)')
-
-lib/readline/complete.c
- - added more static function declarations with prototypes
-
- 9/12
- ----
-lib/sh/tmpfile.c
- - use `^' instead of `*' in sh_mktmpname to make filenames a bit
- more random
-
-include/stdc.h,lib/readline/rldstdc.h
- - add __attribute__ definition
-
-builtins/common.h
- - add printf __attribute__ to declaration of builtin_error
-
-error.h
- - add printf __attribute__ to declaration of programming_error,
- report_error, parser_error, fatal_error, sys_error, internal_error,
- internal_warning
-
-lib/readline/readline.h
- - add printf __attribute__ to declaration of rl_message
-
-pcomplete.c
- - add printf __attribute__ to declaration of debug_printf
-
-print_cmd.c
- - add printf __attribute__ to declarations of cprintf, xprintf
-
-include/chartypes.h
- - new file, includes <ctype.h> and defines macros that check for
- safe (ascii) arguments before calling the regular ctype macros
-
-{alias,bashline,execute_cmd,expr,findcmd,general,locale,mksyntax,stringlib,subst,variables}.c
-parse.y
-builtins/{bashgetopt,common}.c
-builtins/{fc,printf,umask,wait}.def
-lib/glob/strmatch.c
-lib/sh/{oslib,pathcanon,pathphys,snprintf,strcasecmp,strindex,stringvec,strtod,strtol,strtrans}.c
-examples/loadables/{head,sleep}.c
- - include "chartypes.h" or <chartypes.h> instead of <ctype.h>
-
-Makefile.in,{builtins,lib/{glob,sh}}/Makefile.in
- - update dependencies to include chartypes.h
-
-lib/sh/inet_aton.c
- - use `unsigned char' instead of `char' to pass to ctype.h functions
-
-lib/sh/netopen.c
- - check for '0' <= host[0] <= '9' in _getaddr instead of using
- isdigit
-
-subst.c,lib/sh/shquote.c
- - change array subscripts into sh_syntaxtab from `char' to
- `unsigned char'
-
-{alias,bashline,execute_cmd,expr,general,subst}.c, parse.y
-builtins/{fc,printf,umask,wait}.def builtins/{bashgetopt,common}.c
-lib/sh/{pathcanon,pathphys,snprintf,strcasecmp,strindex,strtod,strtol,strtrans}.c
-examples/loadables/{head,sleep}.c
- - change to use some of the new macros in chartypes.h
- - remove old local macro definitions now provided by chartypes.h
-
-general.h
- - remove definition of isletter, ISOCTAL, digit, digit_value
- - change legal_variable_starter and legal_variable_char to use
- chartypes.h macros
- - change ABSPATH to use chartypes.h macros
-
-lib/readline/util.c
- - change to use Paul Eggert's FUNCTION_FOR_MACRO define to define
- function replacements for macros in chardefs.h
-
-lib/readline/chardefs.h
- - added some of the same macros as in chartypes.h
- - change _rl_lowercase_p, _rl_uppercase_p, _rl_digit_p,
- _rl_to_upper, _rl_to_lower to use new IS* macros
- - added _rl_isident macro from vi_mode.c:isident
-
-lib/readline/{bind,complete,nls}.c
- - change to use some of the new macros from chardefs.h
-
-lib/readline/vi_mode.c
- - isident -> _rl_isident
- - remove local defines of macros in chardefs.h
-
-lib/sh/strtol.c
- - updated to new version, modified from glibc 2.2.4 and sh-utils-2.0.
- This one can do strtoll and strtoull, if necessary
-
- 9/13
- ----
-builtins/ulimit.def
- - changed get_limit so it retrieves both hard and soft limits
- instead of one or the other
- - changed callers of get_limit
- - changed getmaxvm to take soft limit, hard limit as arguments
- - changed getmaxuprc to just take a single argument, the value
- - changed calls to printone() to pass soft limit or hard limit
- depending on `mode' instead of using old current_limit variable
- - moved check for out-of-range limits in ulimit_internal into the
- block that converts a string argument to a value of type rlim_t
- - changed RESOURCE_LIMITS struct to break the description into a
- description string and separate scale factor string
- - changed print_all_limits to print a single error message if
- get_limit fails, including limits[i].description now that the
- scale factor has been removed from the description string
- - removed DESCFMT define, since it's now used only in printone()
- - changed printone to print the option character associated with a
- particular limit if we're printing multiple limits
- - changed calls to builtin_error to print the description associated
- with a limit if setting or getting the limit fails
- - added support for new POSIX 1003.1-200x rlim_t values:
- RLIM_SAVED_CUR and RLIM_SAVED_MAX, which expand to the current
- soft and hard limits, whatever they are
- - changed printone to print `hard' or `soft' if the current limit is
- RLIM_SAVED_MAX or RLIM_SAVED_CUR, respectively
- - changed ulimit_internal to handle new `hard' and `soft' arguments
- - changed help text do describe the special limit arguments `hard',
- `soft', and `unlimited'
-
-doc/{bash.1,bashref.texi}
- - documented new `hard' and `soft' limit arguments to `ulimit'
-
-hashlib.[ch]
- - find_hash_item now takes a `const char *' is its first argument
- - hash_string now takes a `const char *' is its first argument
- - remove_hash_item now takes a `const char *' as its first argument
-
-pcomplib.c
- - removed cast from first argument to find_hash_item in find_compspec
-
-general.[ch]
- - absolute_program now takes a `const char *' as its argument
- - absolute_pathname now takes a `const char *' as its argument
-
-lib/glob/glob.[ch]
- - glob_pattern_p now takes a `const char *' as its argument
-
-bashline.c
- - removed cast from first argument to absolute_program in
- command_word_completion_function
- - removed cast from first argument to glob_pattern_p in
- attempt_shell_completion
-
-findcmd.[ch]
- - find_absolute_program, find_user_command, find_path_file,
- search_for_command, user_command_matches now take a
- `const char *' as their first argument
- - file_status, executable_file, is_directory, executable_or_directory
- now take a `const char *' as their argument
- - _find_user_command_internal, find_user_command_internal,
- find_user_command_in_path
-
-lib/sh/makepath.c, externs.h
- - changed sh_makepath so it takes `const char *' for its first
- two arguments
-
-hashcmd.[ch]
- - find_hashed_filename now takes a `const char *' as its first arg
- - remove_hashed_filename now takes a `const char *' as its first arg
-
-variables.[ch]
- - new_shell_variable, var_lookup, shell_var_from_env_string,
- find_name_in_env_array, bind_function, makunbound,
- bind_name_in_env_array, bind_tempenv_variable, bind_variable
- now take a `const char *' as their first arg
- - find_function, make_new_variable, find_tempenv_variable,
- find_variable_internal, find_variable, set_func_read_only,
- set_func_auto_export, all_variables_matching_prefix, assign_in_env,
- assignment, kill_local_variable, make_local_variable, unbind_variable
- now take a `const char *' as their arg
- - mk_env_string now takes `const char *' arguments
-
-arrayfunc.[ch]
- - skipsubscript now takes a `const char *' as its argument
-
- 9/17
- ----
-lib/readline/complete.c
- - attempt to preserve case of what the user typed in
- compute_lcd_of_matches if we're ignoring case in completion
-
-builtins/{let,pushd}.def,{execute_cmd,expr}.c
- - change some 0L constants to 0 and let the compiler sort it out
-
- 9/18
- ----
-lib/malloc/alloca.c
- - alloca now takes a `size_t' argument
-
-include/memalloc.h
- - if we're providing an extern function declaration for alloca,
- use `void *' and prototype if __STDC__ is defined
- - if HAVE_ALLOCA_H is defined, but C_ALLOCA is defined, don't
- define HAVE_ALLOCA
-
- 9/19
- ----
-subst.c
- - do_assignment_internal, do_assignment, and do_assignment_no_expand
- now take a `const char *' as their first argument
-
-general.h
- - a `sh_assign_func_t' is now a function taking a `const char *' and
- returning int
-
-hashcmd.c
- - free_filename_data now takes a `PTR_T' argument to agree with the
- typedef for `sh_free_func_t'
-
-lib/sh/snprintf.c
- - use TYPE_MAXIMUM define like strtol.c instead of huge constants
-
- 9/20
- ----
-lib/sh/snprintf.c
- - don't bother to compile the bulk of the body unless HAVE_SNPRINTF
- or HAVE_ASPRINTF is not defined
-
- 9/24
- ----
-flags.c
- - ignore `set -n' if the shell was started interactively
-
-lib/readline/readline.c
- - initialize readline_echoing_p to 0; let the terminal-specific code
- in rltty.c set it appropriately
-
-lib/malloc/malloc.c
- - changed internal_memalign() slightly to avoid compiler warnings about
- negating an unsigned variable (-alignment -> (~alignment + 1))
-
- 9/27
- ----
-lib/readline/readline.c
- - changed rl_newline to set _rl_history_saved_point appropriately
- for the {previous,next}_history code
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_history_preserve_point
-
-lib/readline/bind.c
- - new bindable variable, `history-preserve-point', sets value of
- _rl_history_preserve_point
-
- 10/1
- ----
-lib/malloc/table.c
- - new file, with a map of allocated (and freed) memory for debugging
- multiple frees, etc. Indexed by hash on values returned by
- malloc(); holds size, file and line number info for last alloc or
- free and a couple of statistics pointers
-
-lib/malloc/malloc.c
- - a few cleanups; added calls for registering allocations and frees
- if MALLOC_REGISTER is defined
- - replaced MALLOC_RETURN with explicit MALLOC_NOTRACE define
- - reordered fields in `struct...minfo' in `union mhead' to restore
- eight-byte alignment
- - added explicit checks for underflow in free and realloc since
- checking mh_magic2 is not sufficient to detect everything (it's
- no longer the last field in the struct, and thus not the bytes
- immediately preceding what's returned to the user)
- - new function, xbotch, for printing file and line number info for
- the failed assertion before calling botch() (programming_error())
-
-configure.in
- - replaced call to BASH_C_LONG_LONG with call to
- AC_CHECK_TYPES([long long])
- - moved the C compiler tests before the tests for various
- system types, so we can know whether we have `long long'
- before testing for 64-bit types
- - if we have `long long', check for sizeof(long long) and save value
-
-aclocal.m4
- - changed BASH_TYPE_BITS64_T to check `long long' before `long', but
- after `double'
-
- 10/2
- ----
-lib/malloc/malloc.c
- - made malloc and realloc both agree on the rounding for a request of
- size N (round up to nearest multiple of 8 after adjusting for
- malloc overhead); uses new ALLOCATED_BYTES macro
- - realloc and free now use new IN_BUCKET macro for underflow checks
-
-execute_cmd.c
- - fixed time_command() to use `time_t' instead of `long' to hold
- time stamps
-
-lib/sh/clock.c
- - clock_t_to_secs now takes a `time_t *' second argument
- - fixed print_clock_t to call clock_t_to_secs with right arguments
-
-lib/sh/timeval.c
- - fixed print_timeval to make `minutes' a `long' and make its
- structure identical to print_clock_t
-
-redir.c
- - changed redirection_error to check for EBADF and use the file
- descriptor being redirected from in the error message if it
- is >= 0
-
-Makefile.in
- - changed release status to `beta1'
-
-lib/glob/collsyms.h
- - added a few ASCII symbols to the posix_collsyms array
-
- 10/3
- ----
-aclocal.m4
- - fixed typo in BASH_TYPE_BITS64_T
-
-configure.in
- - added check for unsigned chars with AC_C_CHAR_UNSIGNED
-
-config.h.in
- - added PROTOTYPES and __CHAR_UNSIGNED__ #defines
-
-general.h
- - if CHAR_MAX is not define by <limits.h>, provide a definition
-
-builtins/printf.def
- - change tescape() to mask \0 and \x escape sequences with 0xFF
- - change tescape() to process at most two hex digits after a `\x'
-
-lib/sh/strtrans.c
- - change strtrans() to mask \0 and \x escape sequences with 0xFF
- - change strtrans() to process at most two hex digits after a `\x'.
- This affects `echo -e' and $'...' processing
-
-lib/readline/bind.c
- - changed rl_translate_keyseq() to process at most two hex digits
- after a `\x'
-
-lib/readline/doc/{rluser.texinfo,readline.3}, doc/bash.1
- - changed documentation for key binding escape sequences to specify
- that at most two hex digits after \x are translated
- - changed documentation for key binding to specify that the result
- of \nnn or \xhh escapes is an eight-bit value, not just ASCII
-
-doc/{bash.1,bashref.texi}
- - changed documentation of $'...' to specify that at most two hex
- digits after \x are translated
- - changed `echo' documentation to specify that at most two hex
- digits after \x are translated
- - changed documentation for `echo' and $'...' to specify that the
- result of \nnn or \xhh escapes is an eight-bit value, not just ASCII
-
- 10/4
- ----
-lib/malloc/malloc.c
- - changed interface for xbotch to pass memory address and error code
- as two additional arguments
- - call mregister_describe_mem from xbotch to get the last allocation
- or free before the botch
-
-configure.in
- - call AC_CHECK_DECLS([strsignal])
-
-config.h.in
- - add HAVE_DECL_STRSIGNAL
-
-siglist.h
- - make declaration of strsignal() dependent on !HAVE_DECL_STRSIGNAL
-
- 10/5
- ----
-support/texi2html
- - upgraded to version 1.64
-
- 10/9
- ----
-aclocal.m4
- - added check for `long long' to BASH_TYPE_PTRDIFF_T
-
-configure.in
- - replaced call to BASH_HAVE_TIOCGWINSZ with AC_HEADER_TIOCGWINSZ
-
-aclocal.m4
- - replaced body of BASH_STRUCT_TERMIOS_LDISC with call to
- AC_CHECK_MEMBER(struct termios.c_line, ...)
- - replaced body of BASH_STRUCT_TERMIO_LDISC with call to
- AC_CHECK_MEMBER(struct termios.c_line, ...)
-
-[bash-2.05a-beta1 frozen]
-
- 10/10
- -----
-lib/sh/snprintf.c
- - fixed exponent() to not smash the trailing zeros in the fraction
- when using %g or %G with an `alternate form'
- - fixed exponent() to handle the optional precision with %g and %G
- correctly (number of significant digits before the exponent)
-
- 10/11
- -----
-expr.c
- - fixed strlong() to correct the values of `@' and `_' when
- translating base-64 constants (64#@ == 62 and 64#_ == 64), for
- compatibility with ksh
-
-lib/sh/itos.c
- - added a slightly more flexible fmtlong() function that takes a
- base argument and flags (for future use)
- - rewrote itos and inttostr in terms of fmtlong
-
-lib/sh/fmtulong.c
- - new file, converts unsigned long to string. hooks for `unsigned
- long long' in the future. unused as yet
-
- 10/15
- -----
-lib/readline/rltty.c
- - change the SET_SPECIAL macro to avoid possible (but highly
- unlikely) negative array subscripts
-
-error.h
- - add __attribute__ to extern declaration of itrace (even though the
- function isn't defined in released versions of bash)
-
-bashansi.h
- - include <strings.h> if HAVE_STRINGS_H is defined, to get any extra
- function declarations provided therein
-
-copy_cmd.c
- - fix typo in forward declaration for copy_arith_for_command
-
-lib/malloc/stats.c
- - make the accumulators in _print_malloc_stats be `unsigned long'
- instead of `int'
-
-externs.h, sig.h
- - add `__noreturn__' gcc attribute to exit_shell and jump_to_top_level
- declarations
-
-lib/sh/mailstat.c, support/bashversion.c
- - include <bashansi.h> for some string function declarations
-
-lib/malloc/shmalloc.h
- - added extern declarations of functions that do malloc debugging
-
-lib/readline/{isearch,readline,vi_mode}.c
- - make sure we index into _rl_keymap with a non-negative index
-
-parse.y
- - make sure we index into sh_syntaxtab with a non-negative index
-
-lib/readline/vi_mode.c
- - bound the vi_mark_chars array with the number of characters between
- 'a' and 'z' rather than using a fixed amount
- - don't use _rl_lowercase_p when deciding whether the char read by
- rl_vi_set_mark is a valid mark; just use 'a' <= char <= 'z'
-
-lib/readline/chardefs.h
- - conditionally include memory.h and strings.h as in general.h
- - replace ISASCII with IN_CTYPE_DOMAIN like other GNU software
- - add defines for ISPRINT(c), ISLOWER(c) and ISUPPER(c)
- - fix defines for _rl_lowercase_p, _rl_uppercase_p, _rl_digit_p,
- _rl_pure_alphabetic, ALPHABETIC, _rl_to_upper, _rl_to_lower,
- and _rl_isident to work on systems with signed chars
-
-include/chartypes.h
- - replace ISASCII with IN_CTYPE_DOMAIN like other GNU software
-
-lib/sh/{strcasecmp,strtod,strtol}.c
- - don't pass possibly-negative characters to tolower() or toupper()
-
-lib/glob/strmatch.c
- - don't bother testing for isupper in FOLD; rely on TOLOWER macro
- from <chartypes.h> to do it
- - don't use local definitions of isblank, et al.; rely on macros
- from <chartypes.h>
-
-lib/readline/{display,readline}.c, mksyntax.c
- - use new ISPRINT macro instead of isprint()
-
-builtins/{kill.def,mkbuiltins.c},{error,execute_cmd,jobs,nojobs,subst}.c
- - don't assume that a pid_t fits into an int for printing and other
- uses
-
-variables.[ch]
- - the unused put_gnu_argv_flags_into_env now takes a `long' pid
- argument
-
-configure.in, config.h.in
- - call AC_STRUCT_ST_BLOCKS, define HAVE_STRUCT_STAT_ST_BLOCKS if found
- - check for strtoull(), define HAVE_STRTOULL if found
- - check for uintmax_t, define to `unsigned long' if not found
-
-lib/sh/mailstat.c
- - don't use st_blocks member of struct stat unless
- HAVE_STRUCT_STAT_ST_BLOCKS is defined; otherwise use the st_nlink
- field to return the total number of messages in a maildir-style
- mail directory
-
-general.h,{alias,expr,general,subst,variables}.c
-builtins/{printf,read}.def
-lib/readline/{bind,complete,nls}.c
-lib/sh/{pathcanon,pathphys,shquote,snprintf,strindex,strtod,strtol,strtrans}.c
- - cast args to ctype macros to unsigned char for systems with signed
- chars; other fixes for signed chars
-
-lib/sh/{fmtullong,strtoull.c}
- - new files, more support for `long long'
-
-Makefile.in, lib/sh/Makefile.in
- - make fmtullong.o and strtoull.o part of libsh
-
-lib/sh/itos.c
- - remove local copy of fmtlong; use fmtulong instead
- - new functions: uitos, uinttostr work on `unsigned long'
-
-lib/sh/snprintf.c
- - fixes to make `unsigned long long' work (%llu)
- - fixes to make unsigned formats not print the sign when given
- an unsigned long that is greater than LONG_MAX
-
-externs.h
- - extern declarations for fmtulong, fmtulloing, strtoull
- - extern declarations for uitos, uinttostr
-
- 10/16
- -----
-configure.in
- - move header checks before function checks
- - move c compiler tests before header checks
- - check for <inttypes.h> with BASH_HEADER_INTTYPES
- - change type checks for intmax_t, uintmax_t to not attempt to
- include <stdint.h>
- - check for strtoimax, strtoumax, strtoll, strtol, strtoull, strtoul
- with BASH_CHECK_DECL (for declarations in header files) and
- AC_REPLACE_FUNCS (for availability and LIBOBJS substitution)
- - remove check for have_long_long around sizeof check for long long
- (since autoconf will give it a size of 0 if the type isn't found)
-
-config.h.in
- - add a define for HAVE_INTTYPES_H
- - add a define for HAVE_UNSIGNED_LONG_LONG
- - add defines for HAVE_STRTOIMAX, HAVE_STRTOUMAX, HAVE_STRTOLL
-
-aclocal.m4
- - new func, BASH_HEADER_INTTYPES, which just calls AC_CHECK_HEADERS
- on <inttypes.h>; separate so it can be AC_REQUIREd
- - AC_REQUIRE([BASH_HEADER_INTTYPES]) in BASH_CHECK_TYPE
- - include <inttypes.h> in BASH_CHECK_TYPE if HAVE_INTTYPES_H is
- defined
- - change AC_DEFINE to AC_DEFINE_UNQUOTED in BASH_CHECK_TYPE
- - new `long long' checking macros: BASH_TYPE_LONG_LONG and
- BASH_TYPE_UNSIGNED_LONG_LONG
- - new BASH_CHECK_DECL
-
-lib/sh/{strto[iu]max,strtoll}.c, lib/sh/Makefile.in, Makefile.in
- - new files
-
-externs.h
- - extern declarations for strtoll, strtoimax, strtoumax
-
-lib/malloc/alloca.c
- - include <bashtypes.h> for size_t
-
-builtins/printf.def
- - new functions: getllong, getullong, getintmax, getuintmax; return
- long long, unsigned long long, intmax_t, uintmax_t respectively
- - builtin printf now handles `ll' and `j' length modifiers directly
-
-lib/sh/Makefile.in
- - use LIBOBJS to decide whether or not the strto* functions are
- needed
-
- 10/17
- -----
-configure.in
- - call AC_REPLACE_FUNCS(rename)
- - move getcwd, strpbrk, strcasecmp, strerror, strtod
- from AC_CHECK_FUNCS to AC_REPLACE_FUNCS
- - only call BASH_FUNC_GETCWD if $ac_func_getcwd == "yes"
- - call BASH_CHECK_SYS_SIGLIST
- - if we don't have vprintf but have _doprnt, call AC_LIBOBJ(vprint)
-
-lib/sh/Makefile.in
- - remove rename, getcwd, inet_aton, strpbrk, strcasecmp, strerror,
- strtod, vprint from OBJECTS; picked up from LIBOBJS
-
-aclocal.m4
- - change BASH_FUNC_GETCWD to call AC_LIBOBJ(getcwd) if the libc
- getcwd(3) calls popen(3)
- - change BASH_FUNC_INET_ATON to call AC_LIBOBJ(inet_aton) if it's
- not found in libc or as a #define even with the special includes
- - BASH_KERNEL_RLIMIT_CHECK -> BASH_CHECK_KERNEL_RLIMIT
- - BASH_DEFAULT_MAILDIR -> BASH_SYS_DEFAULT_MAILDIR
- - BASH_JOB_CONTROL_MISSING -> BASH_SYS_JOB_CONTROL_MISSING
- - BASH_REINSTALL_SIGHANDLERS -> BASH_SYS_REINSTALL_SIGHANDLERS
- - BASH_SIGNAL_CHECK -> BASH_SYS_SIGNAL_VINTAGE
- - BASH_DUP2_CLOEXEC_CHECK -> BASH_FUNC_DUP2_CLOEXEC_CHECK
- - BASH_PGRP_SYNC -> BASH_SYS_PGRP_SYNC
- - BASH_RLIMIT_TYPE -> BASH_TYPE_RLIMIT
- - BASH_FUNC_PRINTF -> BASH_DECL_PRINTF
- - BASH_FUNC_SBRK_DECLARED -> BASH_DECL_SBRK
- - BASH_MISC_SPEED_T -> BASH_CHECK_SPEED_T
- - BASH_CHECK_SOCKLIB -> BASH_CHECK_LIB_SOCKET
- - new macro, BASH_CHECK_SYS_SIGLIST, encapsulates all the checks for
- sys_siglist, _sys_siglist, and strsignal(), sets SIGLIST_O to
- siglist.o if appropriate
-
-Makefile.in
- - use SIGLIST_O variable to decide whether or not we need siglist.o
-
-{execute_cmd,subst}.c
- - change a couple of instances of ISDIGIT to DIGIT, where we really,
- really only want ascii digits
-
-ansi_stdlib.h
- - don't need a declaration for atol()
-
- 10/18
- -----
-
-aclocal.m4
- - new macro, BASH_FUNC_PRINTF_A_FORMAT, checks for printf support
- for %a, %A conversion specifiers, defines HAVE_PRINTF_A_FORMAT
- if successful
-
-configure.in
- - call AC_CHECK_FUNCS for isascii
- - call BASH_FUNC_PRINTF_A_FORMAT
-
-config.h.in
- - add a define for HAVE_ISASCII
- - add a define for HAVE_PRINTF_A_FORMAT
-
-lib/sh/snprintf.c
- - for long double output, fall back to sprintf using ldfallback()
- function for floating point formats
- - support %a, %A using dfallback() or ldfallback() if
- HAVE_PRINTF_A_FORMAT is defined
- - fix bug in vasprintf that returned wrong value in its first
- argument if the buffer holding the result string got reallocated
- - fixed PUT_CHAR macro to increment the counter even if we've
- exceeded the buffer size, for the return value from
- vsnprintf/snprintf
- - fix vsnprintf_internal to not use counter < length as a loop
- condition, but always process the entire format string (for
- the return value from vsnprintf/snprintf)
-
-builtins/printf.def
- - support %a, %A if HAVE_PRINTF_A_FORMAT is defined
-
-include/typemax.h
- - new file, with the TYPE_MAXIMUM stuff that's duplicated in several
- files in lib/sh
-
-lib/sh/{fmtulong,strtol,snprintf}.c
- - include <typemax.h> instead of having the definitions in each file
-
-lib/sh/Makefile.in
- - updated dependencies for typemax.h
-
- 10/22
- -----
-configure.in
- - call AC_CHECK_FUNCS on ctype.h functions/macros that bash redefines
- in chartypes.h
-
-config.h.in
- - defines for HAVE_IS{ASCII,BLANK,GRAPH,PRINT,SPACE,XDIGIT}
-
-include/chartypes.h, lib/glob/strmatch.c, lib/readline/chardefs.h
- - don't redefine some is* ctype macros/functions if HAVE_ISXXX is
- defined (meaning that an appropriate function, but not a macro,
- exists)
-
-lib/sh/strtrans.c
- - new function, ansic_shouldquote, returns 1 if argument string
- contains non-printing chars that should be quoted with $'...'
-
-externs.h
- - new declaration for ansic_shouldquote()
-
-variables.c
- - change print_var_value to ansi C quote the string if we're not in
- posix mode and the variable's value contains non-printing chars,
- to use the regular shell single quoting if the value contains
- shell meta-characters, and to just output the string otherwise
-
-lib/sh/shquote.c
- - add `break' to `case '~':' to avoid fallthrough and extra test
-
-doc/bashref.texi
- - note that in POSIX mode, `set' displays variable values that
- include nonprinting characters without quoting, unless they
- contain shell metacharacters
-
-builtins/printf.def, lib/sh/snprintf.c
- - handle `F' conversion specifier as equivalent to 'f'
-
-parse.y, {nojobs,variables}.c
- - a couple of cleanups for when building a minimal configuration
-
-nojobs.c
- - new function: stop_making_children(), just sets
- already_making_children to 0 (like stop_pipeline)
-
-subst.c
- - call stop_making_children from subst.c:command_substitute if
- JOB_CONTROL is not defined. This fixes the bug where the wrong
- process is waited for (and its status returned) when using
- command substitution in a null command in a shell function
-
-builtins/printf.def
- - new variable `tw' used to keep track of the total number of
- characters written by a single call to `printf' -- to be
- used for the `%n' conversion, which will be added later. It
- gets reset each time we reuse the format string, which is what
- ksh93 seems to do
-
- 10/23
- -----
-variables.c
- - new function, bind_var_to_int (char *var, long val)
-
-variables.h
- - extern declaration for bind_var_to_int
-
-lib/sh/netopen.c
- - use gai_strerror() for error messages when getaddrinfo() fails
- - use PF_INET if DEBUG is defined, since IPv6 doesn't work for me
-
-Makefile.in
- - pass DEBUG=${DEBUG} down to makes in some subdirectories
-
-{builtins,lib/{glob,sh}}/Makefile.in
- - append ${DEBUG} to LOCAL_CFLAGS value, passed by top-level Makefile
-
-builtins/printf.def
- - added support for %n format conversion char (number of chars printed
- so far from current format string)
-
- 10/24
- -----
-variables.c
- - if posixly_correct is set, the default value of $MAILCHECK is 600
- - use legal_number instead of atoi in adjust_shell_level
- - treat non-numeric assignments to SECONDS as 0 in assign_seconds
- - new function, init_funcname_var; sets FUNCNAME as a dynamic variable
- if it's not set in the initial environment
- - new function, init_groups_var; sets GROUPS as a dynamic array
- variable if it's not set in the initial environment
- - new function, init_dirstack_var; sets DIRSTACK as a dynamic array
- variable if it's not set in the initial environment
- - new function, init_seconds_var; sets SECONDS as a dynamic
- variable using any valid integer value in the initial environment
- as the initial value, as if an assignment had been performed
- - call init_funcname_var, init_groups_var, init_dirstack_var,
- init_seconds_var from initialize_dynamic_variables
- - non-numeric values assigned to LINENO are treated as 0
- - change initialize_shell_variables to not auto-export PATH or TERM
- - change set_home_var to not auto-export HOME
- - change set_shell_var to not auto-export SHELL
- - broke the code that sets HOSTNAME, HOSTTYPE, MACHTYPE, OSTYPE
- out into a separate function, set_machine_vars; none of those
- variables are auto-exported
- - bash no longer un-exports SSH_CLIENT or SSH2_CLIENT
-
-shell.c
- - changed isnetconn() to check SSH_CLIENT and SSH2_CLIENT only if
- SSH_SOURCE_BASHRC is defined in config-top.h
-
-config-top.h
- - added a commented-out definition for SSH_SOURCE_BASHRC
-
- 10/25
- -----
-
-Makefile.in
- - changed RELSTATUS to `rc1' (release candidate 1)
-
- 10/29
- -----
-locale.c
- - fixed an `=' vs. `==' typo in set_locale_var when parsing
- LC_NUMERIC
-
-doc/{bash.1,bashref.texi}
- - document what bash does with $POSIXLY_CORRECT
-
-doc/builtins.1
- - some updates
-
-builtins/psize.sh
- - some mktemp(1) changes
-
-lib/readline/readline.c
- - change rl_backward to check for rl_point < 0 and reset to 0 if so
-
-lib/readline/util.c
- - don't compile in _rl_strpbrk if HAVE_STRPBRK is defined
-
-lib/readline/rlprivate.h
- - remove extern declaration of _rl_strpbrk
-
-lib/readline/rldefs.h
- - #define _rl_strpbrk as strpbrk if HAVE_STRPBRK is define, otherwise
- add extern declaration of _rl_strpbrk from rlprivate.h
-
-{mailcheck,shell,variables}.c
- - make sure to include posixtime.h to get any prototype for time(3)
- in scope
-
-{array,eval,execute_cmd,mksyntax,subst}.c, parse.y
-builtins/common.c
-lib/sh/pathcanon.c
- - a few changes as the result of `gcc -Wall' patches from solar
- designer
-
-builtins/read.def, parse.y
- - change some calls to free() to xfree()
-
-builtins/set.def
- - make sure unset_builtin() resets unset_array to 0 each time through
- the loop, because it's set (and used) depending on the current
- argument
-
-shell.h
- - new define, USE_VAR, to force the compiler to not put a particular
- variable in a register -- helpful if registers are not restored
- by setjmp/longjmp
-
-builtins/{evalfile.c,{read,wait}.def}, {eval,execute_cmd,shell,test}.c
- - use USE_VAR for some variables
-
-subst.c
- - fixed a case in expand_word_internal where a NULL pointer could
- have been passed to free() (though free() should ignore it)
- - fixed a case at the end of expand_word_internal where LIST could
- have been used uninitialized (it makes gcc happy, though it
- doesn't happen in practice)
-
-test.c
- - give test_syntax_error(), beyond(), and integer_expected_error()
- the `__noreturn__' attribute for gcc
-
-unwind_prot.c
- - in clear_unwind_protect_list(), convert `flags' to `long' (via
- assignment to a `long' variable) before casting to `char *', in
- case pointers and longs are 64 bits and ints are 32 (makes no
- difference on 32-bit machines)
-
- 10/30
- -----
-print_cmd.c
- - fixed cprintf to avoid gcc warning about assigning const pointer
- to non-const (discarding type qualifier)
-
-{make_cmd,pcomplete,test}.c,parse.y
- - some minor changes to shut up gcc warnings
-
-lib/sh/tmpfile.c
- - fixed sh_mktmpfp to avoid file descriptor leaks in the case that
- sh_mktmpfd succeeds but fdopen fails for some reason
- - change sh_mktmpfd to use the same scheme for computing `filenum'
- as sh_mktmpname
- - change get_sys_tmpdir to prefer P_tmpdir if P_tmpdir is defined
- - changed sh_mktmpname and sh_mktmpfd to avoid trying to assign to
- `nameroot' if `nameroot == 0' (duh)
- - add code to sh_mktmpfd to use mkstemp(3) if USE_MKSTEMP is defined
- - add code to sh_mktmpname to use mktemp(3) if USE_MKTEMP is defined
-
-support/{fixlinks,mkclone}
- - use mktemp if it's available for the symlink test
- - use $TMPDIR instead of hardcoding /tmp; default to /tmp
- - use a better filename for the symlink test instead of `z'
-
-support/bashbug.sh
- - more changes inspired by a patch from solar designer
-
-lib/malloc/Makefile.in
- - new target `alloca', which builds libmalloc.a with alloca.o only
- (for systems without alloca that are configured --without-bash-malloc)
-
-configure.in
- - if we don't have a working alloca and are not configured to build
- the bash malloc library, make a malloc library containing only
- alloca.o
-
-aclocal.m4
- - slight change to RL_LIB_READLINE_VERSION to deal with minor version
- numbers with a letter appended (like 4.2a)
-
- 10/31
- -----
-doc/{bash.1,bashref.texi}
- - slight change to note that only interactive shells resend a SIGHUP
- to all jobs before exiting
-
-externs.h
- - declare strto[ui]max only if NEED_STRTOIMAX_DECL is defined. This
- keeps picky compilers from choking because intmax_t is not defined
- (MacOS X 10.1)
-
-builtins/printf.def
- - #define NEED_STRTOIMAX_DECL before including shell.h
-
- 11/1
- ----
-general.c
- - check in bash_tilde_expand() for an unquoted tilde-prefix; don't
- bother passing the string to tilde_expand unless the prefix is
- unquoted
-
-shell.c
- - fix a problem with $LINENO when executing commands supplied with
- the -c invocation option when ONESHOT is defined
-
-[bash-2.05a-rc1 frozen]
-
-builtins/printf.def
- - fix the %n conversion to require that the variable name supplied
- be a valid shell identifier
-
-variables.c
- - improve random number generator slightly by using the upper 16
- bits of the running random number instead of the lower 16, which
- are incrementally more random
-
- 11/2
- ----
-configure.in
- - if RL_INCLUDEDIR ends up being /usr/include, don't put
- -I$(RL_INCLUDEDIR) into CFLAGS
-
- 11/5
- ----
-doc/{bash.1,bashref.texi}
- - correct description of POSIXLY_CORRECT to note that the shell enters
- posix mode *before* the startup files are read if POSIXLY_CORRECT
- is in the initial environment
-
-variables.c
- - fix function prologues for init_dirstack_var and init_groups_var
- to agree with caller (no arguments)
-
-jobs.c
- - fix forward function declarations for pipe_read and pipe_close
-
-subst.c
- - removed `inline' attribute from skip_double_quoted because it can
- potentially be called recursively
-
-bashline.c
- - quick fix to bashline.c:attempt_shell_completion programmable
- completion code to just punt if the end of the command word found
- by find_cmd_end is <= the start found by find_cmd_start (the bug
- is probably in find_cmd_start -- fix later)
-
-pcomplete.c
- - fix gen_matches_from_itemlist to return if the stringlist is null
- after any cleaning or initialization, before trying to use it
- - fix GEN_COMPS to only bother to try to append the STRINGLIST
- returned by gen_matches_from_itemlist to `glist' if it's non-NULL
-
-lib/sh/stringlist.c
- - make copy_stringlist return NULL if the STRINGLIST * passed as an
- argument is NULL
- - make append_stringlist call copy_stringlist only if M2 is non-NULL;
- otherwise just return NULL if m1 is NULL
- - make word_list_to_stringlist return 0 immediately if the passed
- LIST argument is NULL
- - make realloc_stringlist call alloc_stringlist if the passed
- STRINGLIST argument (`sl') is 0, just like realloc calls malloc
-
-subst.c
- - in skip_to_delim(), if we have an unclosed ${, and it's at the end
- of the string (string[i] == '{', string[i+1] == '{' and
- string[i+2] == 0, return si (i + 2) immediately without bothering
- to call extract_dollar_brace_string or extract_delimited_string
- - in skip_to_delim(), if string[i] is 0 after a call to
- extract_dollar_brace_string or extract_delimited_string (meaning we
- have an unclosed ${ or other expansion, return i immediately without
- doing a `continue' (which will increment i past the end of string)
- - in split_at_delims, don't increment te by 1 if it's pointing to a
- delimiter. this has the effect of skipping the first delimiter
- char in a possibly multi-character delimiter, and ignoring
- single-char delimiters like `>'
-
-configure.in
- - use AC_CHECK_MEMBERS([struct stat.st_blocks]) instead of a call to
- AC_STRUCT_ST_BLOCKS to avoid configure changing LIBOBJS if the test
- fails
-
-general.c
- - introduce two new variables: bash_tilde_{prefixes,suffixes}, set
- to the additional prefixes and suffixes bash wants to pass to the
- tilde expansion code (reserved for post-bash-2.05a fix)
-
-aclocal.m4
- - add missing `test' in BASH_CHECK_SYS_SIGLIST
-
- 11/7
- ----
-lib/readline/vi_mode.c
- - fix rl_vi_goto_mark to explicitly check that the desired mark is
- between 'a' and 'z', since some locales have lowercase letters
- outside that range, which could cause a negative subscript
-
-include/chartypes.h
- - remove superfluous `#undef ISASCII'
-
-lib/sh/strto[iu]max.c
- - changes from Paul Eggert to work around buggy compilers and catch
- configuration errors at compile time
-
-aclocal.m4
- - new macro, BASH_C_LONG_DOUBLE, identical to AC_C_LONG_DOUBLE but
- with a fix for Irix 5.3 (not called, since I'm not sure it's the
- right thing to do -- the C standard allows double and long double
- to be the same size)
-
-lib/sh/snprintf.c
- - only try to write the trailing NUL in vsnprintf_internal if
- data->length is >= 0, since if it's not, we probably don't have
- a buffer
-
-Makefile.in
- - changed RELSTATUS to `release'
-
- 11/8
- ----
-lib/sh/strtol.c
- - make sure chars passed to toupper are cast to unsigned
-
-unwind_prot.c
- - change clear_unwind_protect_list to not require a cast from `int'
- to `char *'
-
-lib/readline/chardefs.h
- - make _rl_digit_p succeed only for ascii digits, since that's what
- most callers assume
-
- 11/13
- -----
-doc/bashref.texi
- - added `ERR' trap and [-+]O invocation option to section listing
- differences from the Bourne shell
-
- 11/15
- -----
-[bash-2.05a released]
-
- 11/19
- -----
-include/stdc.h
- - new define, INLINE, defined as `inline' for gcc and empty otherwise
-
-subst.c
- - make skip_double_quoted, sub_append_string have INLINE attribute
-
-trap.c
- - use BASH_NSIG as upper limit for signal names in signal_name()
-
-lib/readline/bind.c
- - use RL_COMMENT_BEGIN_DEFAULT in output for rl-comment-begin value
-
-error.c
- - fix sys_error to save value of errno around calls to fprintf
-
-doc/Makefile.in
- - added rules to create PDF files from postscript and dvi input
-
-MANIFEST.doc
- - added {article,bash,bashref,rose94}.pdf
-
-doc/bash.1
- - rearranged some `.PD 0' and `.TP' directives so man2html will
- handle them better (shouldn't affect groff output)
-
-support/man2html.c
- - small fix to handle quoted string arguments to directives like
- `.BR' without mangling the output
-
- 11/20
- -----
-{arrayfunc,variables}.c
- - changed calling sequence for dynamic array variable `assign'
- functions to (SHELL_VAR *self, char *value, arrayind_t ind)
- - changed calling sequence for dynamic variable assign functions
- to the same as array variable assign_func. Now this can be
- prototyped
-
-variables.h
- - the assign_func member of a `struct variable' is now of type
- `sh_var_assign_func_t', which is prototyped
- - the dynamic_value member of a `struct variable' is now of type
- `sh_var_value_func_t', which is prototyped
-
-variables.c
- - changed to use `sh_var_assign_func_t' and `sh_var_value_func_t'
-
-builtins/cd.def
- - when in posix mode, if the new directory name formed by PWD and
- the argument passed by the user cannot be canonicalized, and the
- -P option has not been supplied, return failure immediately
- - if canonicalization failed, but the fallback to the directory
- name specified by the user succeeds, reset the current working
- directory
-
-lib/readline/{input.c,rlprivate.h}
- - renamed rl_unget_char to _rl_unget_char; made library global
-
-lib/readline/{{bind,readline}.c,{keymaps,rlprivate}.h}
- - support for `key subsequences'; allows a key sequence and a function
- mapped to a subsequence of that key sequence. Primarily to allow
- arrow keys to be bound in readline vi insert mode, while preserving
- the ESC function to switch to command mode.
-
-lib/readline/{input.c,rlprivate.h}
- - new function, _rl_input_queued(T), does a check with select or
- FIONREAD with a timeout of `T' (which is generally 0)
-
-lib/readline/readline.c
- - change _rl_dispatch_subseq to test for input in the queue if we
- get ESC while in vi insertion mode if the keymap entry type for
- ESC is ISKMAP. If _rl_input_queued returns non-zero, we assume
- that an arrow key sequence has been pressed and go ahead with the
- subsequence. If it returns zero, we assume that the user pressed
- ESC to switch into command mode, and dispatch to that right away.
- This avoids forcing the user to press another key before switching
- into command mode
-
- 11/21
- -----
-lib/readline/readline.c
- - bind common arrow key sequences in vi insertion keymap
-
-lib/readline/terminal.c
- - bind termcap definition's arrow keys in vi insertion keymap
-
-lib/readline/bind.c
- - check for rl_vi_movement_mode in _rl_bind_if_unbound, so
- binding the arrow keys can work
-
-lib/readline/readline.c
- - since _rl_bind_if_unbound does the check of what's currently
- bound to the key sequence, the check in bind_arrow_keys_internal
- was redundant
- - bind_arrow_keys_internal now takes a Keymap argument and handles
- saving and restoring _rl_keymap; changed bind_arrow_keys
- accordingly
-
-builtins/fc.def
- - fix from Paul Eggert to substitute the nearest history number in
- range if an out-of-range value is supplied. POSIX requires this
-
-lib/sh/pathcanon.c
- - fix from Corrina Vinschen for the special `cygdrive' prefix on
- Cygwin
-
-bashhist.c
- - split the history adding code into more pieces:
- check_history_control (char *line) checks LINE against the value
- of HISTCONTROL, returning 1 if LINE should be saved and 0 if not
-
- check_add_history (char *line) calls check_history_control and
- history_should_ignore (line) and saves the line with
- bash_add_history if the checks indicate that it should be saved
-
- maybe_add_history just calls check_add_history to set the value
- of first_line_saved
-
-bashhist.h
- - extern declaration for check_add_history()
-
-shell.c
- - don't call load_history() from the interactive shell startup
- code if history_lines_this_session is > 0, indicating that we've
- already saved some lines in the history and that we probably
- don't want to overwrite them
-
-builtins/history.def
- - call check_add_history from push_history, so `history -s xx'
- works even when in a compound command whose first line has not
- been saved. (Caveat: in a compound command when the first
- line has been saved, the line supplied to history -s will become
- part of the compound command's history entry. Of course, the
- delete_history call could remove the compound command from the
- history entirely)
-
-bashline.c
- - use sh_makepath instead of xmalloc/sprintf in
- command_word_completion_function
-
-lib/readline/complete.c
- - get_y_or_n now takes an int FOR_PAGER argument; caller changed
- If FOR_PAGER is non-zero, get_y_or_n returns appropriate values
- for a more-like pager: `newline' or `return' return 2; `q' or
- `Q' return 0
- - there is now a mini internal more-like pager for displaying a
- list of completions that exceeds the screen height (new function
- _rl_internal_pager, called from rl_display_match_list)
-
- 11/24
- -----
-command.h
- - new flag, W_TILDEEXP, says to do tilde expansion on an
- assignment word
-
-execute_cmd.c
- - fix_assignment_words now sets W_TILDEEXP for assignment word
- arguments to `assignment builtins'
-
-general.c
- - bash_tilde_expand now takes a second argument indicating whether
- or not it's being invoked in an `assignment context'
-
-general.h
- - change extern declaration for bash_tilde_expand
-
-{bashline,execute_cmd,findcmd,general,variables}.c
-builtins/evalfile.c
-lib/sh/makepath.c
- - fix callers of bash_tilde_expand appropriately
-
-subst.c
- - fix callers of bash_tilde_expansion appropriately
- - add (currently commented-out) code that would tilde expand assignment
- statement arguments to assignment builtins (W_TILDEEXP flag set)
- even when the shell is in posix mode
-
-bashline.c
- - fix attempt_shell_completion to turn off
- rl_filename_completion_desired when doing command name completion,
- so no slash gets appended to the name if there happens to be a
- directory with the same name in the current directory
-
- 11/26
- -----
-lib/readline/rltech.texinfo
- - a couple of additions to the rl_stuff_char description
-
-parse.y
- - turn off echo_input_at_read in parse_string_to_word_list, so `set -v'
- doesn't give extra lines of output when doing compound array
- assignment
-
-subst.c
- - fix split_at_delims to handle skipping over a `\n' if it's a
- delimiter (use spctabnl(c) instead of whitespace(c))
-
- 11/27
- -----
-support/config.{guess,sub}
- - updated (with bash changes) to latest version from gnu.org
-
-sig.h
- - add prototype for set_signal_handler declaration
-
-builtins/setattr.def
- - add prototype to extern declaration of declare_builtin
-
-builtins/times.def
- - add no_options call, since times takes no options
-
-lib/sh/spell.c
- - add prototypes to forward declarations for midist and spdist
-
-lib/sh/strtrans.c
- - add explicit int return type to ansic_shouldquote declaration
-
-lib/readline/rldefs.h, lib/readline/{macro,readline,util,undo}.c
- - move define for SWAP to rldefs.h, removed from various C files
-
-lib/readline/vi_mode.c
- - removed define for exchange(), changed to use SWAP instead
-
-lib/readline/bind.c
- - added some static forward function declarations
- - find_boolean_var, find_string_var now take a `const char *' argument
-
-lib/readline/signals.c
- - added static forward declaration for rl_maybe_set_sighandler
-
-lib/readline/readline.c
- - add some common key bindings for the HOME and END keys in
- bind_arrow_keys_internal
-
-lib/readline/terminal.c
- - fetch the `@7' termcap string; it's sent by the END key
- - attempt to bind the terminal's END key to rl_end_of_line in
- bind_termcap_arrow_keys; I don't know why I was using `kH'
- instead of `@7'
-
-doc/builtins.1
- - remove `case', `for', `if', `until', `while' from NAME section;
- those are not shell builtins
-
- 11/28
- -----
-stringlib.c
- - new function, find_token_in_alist, takes a token value and an
- ALIST argument, and returns the string correspoinding to the
- token if found in the alist
-
-externs.h
- - new extern declaration for find_token_in_alist()
-
-subst.c
- - string_list_internal is no longer static
-
-subst.h
- - new extern declaration for string_list_internal()
-
-parse.y
- - new alist array of other tokens returned by read_token which are
- not reserved words in word_token_alist[]
- - reworked error reporting: new functions print_offending_line,
- which prints the line containing the syntax error,
- error_token_from_token, which takes the current token and tries to
- figure out its textual representation, and error_token_from_text,
- which does the old job of finding the bad token by analyzing the
- text of shell_input_line at the current index
- - report_syntax_error now tries to figure out the token that caused
- the syntax error by first looking at current_token and falling
- back to the old method of textual analysis if that fails
- - report_syntax_error doesn't say the token resulting from the textual
- analysis of the input line is an `unexpected token'; it just
- says there is a `syntax error near xxx'
- - changed conditional command error reporting to use the value
- returned by error_token_from_token if it's not null instead of
- just using the token value in the message, since current_token
- ends up being set to -1, and the text of the message from
- report_syntax_error might not be exactly right
- - change parse_string_to_word_list to set current_token to the
- offending token returned by read_token before calling yyerror()
- to make the error reporting do the right thing
-
-aclocal.m4
- - fixed typo in BASH_CHECK_LIB_TERMCAP
-
-configure.in
- - add check for isinf(3); define HAVE_ISINF_IN_LIBC if found
-
-config.h.in
- - add define for HAVE_ISINF_IN_LIBC
-
-lib/sh/snprintf.c
- - check for Inf and NaN, using isinf and isnan if they're found in
- libc
- - use the current locale for thousands separator and decimal point
- - recognize "'" flag; not implemented yet
- - fix for snprintf/vsnprintf with length of 0 and string argument of
- 0 with non-zero length
-
-builtins/read.def
- - TMOUT is now the default timeout for `read' (and select) if set,
- like ksh93 when reading from the terminal
- - edit_line (called by read -e) now just does readline's filename
- completion by setting rl_attempted_completion_function to NULL,
- since e.g., doing command completion for the first word on the
- line wasn't really useful
-
-execute_cmd.c
- - changed select_command to return failure status if select_query
- returns NULL, indicating that read_builtin returned
- EXECUTION_FAILURE
-
-doc/{bash.1,bashref.texi}
- - documented new TMOUT behavior
- - slight change to the description of the test `-ef' option
-
-doc/bashref.texi
- - added item to posix mode section describing failure behavior of
- cd when invoked in logical mode and the pathname formed by
- combining $PWD and the directory argument does not refer to an
- existing directory
-
- 11/29
- -----
-execute_cmd.c
- - fix execute_function to call dispose_function_env after
- merge_function_env if the shell is in posix mode (fixes debian
- bash bug #117673)
-
-lib/readline/readline.c
- - rl_forward -> rl_forward_char; rl_forward function for compatibility
- - rl_backward -> rl_backward_char; rl_forward function for
- compatibility
- - new functions, rl_forward_byte, rl_backward_byte, for future use
-
-lib/readline/readline.h
- - extern declarations for rl_forward_char, rl_backward_char,
- rl_forward_byte, rl_backward_byte
-
-lib/readline/{emacs_keymap,funmap,vi_keymap,vi_mode
- - rl_forward -> rl_forward_char
- - rl_backward -> rl_backward_char
-
-lib/readline/funmap.c
- - new bindable names, `backward-byte' and `forward-byte'
-
-aclocal.m4
- - new function, BASH_CHECK_MULTIBYTE, encapsulates checks for
- multibyte code
-
-config.h.in
- - add necessary defines for multibyte include files and functions
-
-configure.in
- - add call to BASH_CHECK_MULTIBYTE
-
-config-bot.h
- - add code to define HANDLE_MULTIBYTE if prerequisites are met
-
-lib/sh/xstrchr.c
- - new file, xstrchr() is strchr(3) that handles multibyte characters
-
-bashhist.c
- - first_line_saved -> current_command_first_line_saved; variable is
- now global
-
-bashhist.h
- - extern declaration for current_command_first_line_saved
-
- 11/30
- -----
-bashhist.c
- - break the code that actually calls add_history out of
- bash_add_history into a new function, really_add_history;
- bash_add_history now calls really_add_history
- - check_add_history takes a second `force' argument telling it
- whether to call bash_add_history (force == 0) or really_add_history
- (force != 0)
-
-builtins/history.def
- - in push_history, call delete_last_history if the current command
- has more than one line, the first line was saved, and
- command-oriented history is active. This takes care of deleting
- the right history element if `history -s' is used within a
- compound or multiline command
- - in push_history, call check_add_history with second argument of 1
- to skip check of current_command_line_count and add the arguments
- to history -s as a single separate history entry
-
- 12/3
- ----
-lib/readline/complete.c
- - append a slash to completed names which are symlinks to directories
- if the new variable _rl_complete_mark_symlink_dirs is non-zero
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_complete_mark_symlink_dirs
-
-lib/readline/bind.c
- - new bindable variable, `mark-symlinked-directories', mirrors the
- value of _rl_complete_mark_symlink_dirs
-
-doc/bash.1, lib/readline/doc/{readline.3,rluser.texinfo}
- - documented new `mark-symlinked-directories' variable
-
- 12/4
- ----
-variables.[ch]
- - set_pipestatus_array now takes a second argument with the number
- of processes in the array
- - changed set_pipestatus_array to just modify the value in place if
- the existing array has one element and the new array has one
- element, and to modify existing values in place if new array has
- more elements than existing array
-
-variables.c, jobs.c
- - changed set_pipestatus_array callers
-
-jobs.c
- - moved call to setjstatus() from set_job_status_and_cleanup to
- wait_for, since set_job_status_and_cleanup is part of the SIGCHLD
- signal handler call path, and race conditions accessing the
- PIPESTATUS array will result for things like
-
- while true; do date; done | cat > /dev/null
-
- 12/5
- ----
-xmalloc.h
- - don't redefine xmalloc, xrealloc, and xfree if DISABLE_MALLOC_WRAPPERS
- is #defined
-
-config.h.in
- - #undef for DISABLE_MALLOC_WRAPPERS
-
-configure.in
- - define DISABLE_MALLOC_WRAPPERS if the --with-purify option is
- supplied
-
-lib/malloc/trace.c
- - new function, malloc_trace_bin(N), traces allocations and frees
- to bucket N (uses the same type of bitmap as `busy')
-
-lib/malloc/table.c
- - fix wraparound search problem in find_entry when searching for a
- free entry when the table is full
-
- 12/6
- ----
-lib/malloc/table.c
- - keep an `overflow bucket' around to use when the table is full,
- so find_entry always returns a valid pointer when FIND_ALLOC
- is set
- - new static variable to keep a count of the number of MT_ALLOC
- entries in the mem_table
-
-lib/sh/{oslib,clktck}.c
- - if HAVE_LIMITS_H is defined, include <limits.h>
-
-lib/sh/oslib.c
- - new function, getmaxgroups() returns max number of simultaneous
- groups
- - new function, getmaxchild(), returns max number of simultaneous
- user processes
-
-general.c
- - removed forest of #defines for getmaxgroups()
-
-externs.h
- - new extern declaration for getmaxgroups()
- - new extern declaration for getmaxchild()
- - new extern declaration for isnetconn()
-
-lib/sh/netconn.c,shell.c
- - new file, isnetconn() from shell.c moved here
-
-Makefile.in, lib/sh/Makefile.in
- - necessary changes for netconn.c
-
-builtins/ulimit.def
- - changed getmaxuprc() to just call getmaxchild() and massage the
- return value appropriately
-
-{jobs,nojobs}.c
- - use the value returned by getmaxchild() in
- mark_dead_jobs_as_notified instead of static CHILD_MAX
-
-jobs.c
- - new function, compact_jobs_list, removes some number of jobs from
- the jobs table and reallocates the table, copying the jobs that
- are left from the old table to the new. Compaction happens from
- the beginning of the list and removes dead jobs, and we make sure
- to keep the last CHILD_MAX jobs as POSIX.2 requires
- - call compact_jobs_list from stop_pipeline if we're in a subshell,
- there are no free jobs in the jobs table, and the jobs table is
- at or above some maximum limit
-
-execute_cmd.c
- - change eval_arith_for_expr to set this_command_name to `((' before
- calling evalexp, since it might be changed by evaluating the
- loop body between evalexp calls
-
-trap.c
- - change reset_signal to turn off the SIG_TRAPPED flag for the
- given signal, so shell builtins and functions running in command
- substitutions don't run the signal handlers (traps are not supposed
- to be inherited by command substitutions)
-
-parse.y
- - changed parse_string_to_word_list to turn off alias expansion
- while parsing the array assignment
-
- 12/9
- ----
-alias.c
- - fix add_alias so that redefining an alias's value also resets the
- EXPANDNEXT flag
-
- 12/10
- -----
-parse.y
- - new function, token_is_assignment, called to check whether the text
- before `=' makes up a valid assignment token before trying to parse
- a compound assignment statement
- - new function, parse_compound_assignment, to parse a compound
- assignment statement instead of using parse_matched_pair; handles
- comments and error reporting in the parser instead of waiting until
- expansion time
- - changed parse_compound_assignment and parse_string_to_word_list to
- allow reserved words in compound array assignments
-
-lib/readline/doc/rltech.texinfo
- - changed the documentation for rl_callback_read_char and
- rl_callback_handler_remove to say what happens to the terminal
- settings and what needs to be done to reset them
-
- 12/11
- -----
-bashline.c
- - add emacs_edit_and_execute_command, bound to C-xC-e, like vi-mode
- `v' command
- - add bindable command name `edit-and-execute-command', bound to
- run emacs_edit_and_execute_command()
-
-lib/glob/strmatch.c
- - add support for ksh93-like [:word:] character class (isalnum + `_')
-
-doc/{bash.1,bashref.texi}
- - add note to section describing lists to clarify that a sequence of
- one or more newlines may be used to delimit a command, equivalent
- to a semicolon
- - document new [:word:] pattern matching character class
-
-doc/bash.1, lib/readline/doc/rluser.texinfo
- - document `edit-and-execute-command' and its default emacs-mode
- binding
-
-include/chartypes.h
- - add defines for TOCTRL and UNCTRL if they're not already defined
-
-lib/readline/chardefs.h
- - #undef UNCTRL if it's defined to avoid cpp redefinition warnings
-
-lib/sh/strtrans.c
- - add \cX (Control-X) escape for $'...' to ansicstr()
- - change ansic_quote() to allocate at least four chars for each char
- in the string argument, to account for \0xx octal values
- - change ansic_quote() to no longer call sprintf for non-printable
- characters; just translate the string to octal directly
-
-print_cmd.c
- - change xtrace_print_word_list to call ansic_quote() if
- ansic_shouldquote() indicates that there are nonprinting characters
- in a word
-
-builtins/type.def
- - changed deprecated long option parsing to just replace the word
- in the list with the equivalent short option (-type -> -t) instead
- of removing words from the list
- - changed describe_command to take a single flags argument instead
- of two int args; changed caller
- - type now has two new options: -f suppresses function lookup (like
- command), and -P forces a PATH search for the name(s)
-
-builtins/common.h
- - flags for describe_command are here
- - changed extern declaration of describe_command
-
-builtins/command.def
- - changed call to describe_command to use flags from common.h, and
- the right number of arguments
-
-doc/{bash.1,bashref.texi}
- - documented new -f and -P options to `type'
-
- 12/12
- -----
-lib/readline/rldefs.h
- - fixed prototype for _rl_strnicmp
-
-execute_cmd.c
- - select_query now takes a new argument, an int flag saying whether
- or not to print the menu the first time through the loop. An
- empty line in response to the prompt will always cause the menu
- to be reprinted
- - changed execute_select_command to cause select_query to reprint
- the menu only if REPLY is set to NULL, if KSH_COMPATIBLE_SELECT
- is defined
-
-config-top.h
- - define KSH_COMPATIBLE_SELECT, with a comment about its meaning
-
-lib/readline/readline.c
- - change rl_insert_comment to toggle if given an explicit numeric
- argument: if the first characters on the line don't specify a
- comment, insert one; if they do, delete the comment text
-
-doc/bash.1, lib/readline/doc/{readline.3,rluser.texinfo}
- - documented new behavior of insert-comment with a numeric argument
-
- 12/13
- -----
-lib/malloc/watch.c
- - new file, implements watchpoint functions
-
-lib/malloc/watch.h
- - new file, define some `events' for watchpoints and extern function
- and variable declarations for watchpoint code
-
-lib/malloc/imalloc.h
- - #define MALLOC_WATCH if MALLOC_DEBUG is defined
- - add __P define as in include/stdc.h if not already defined
-
-lib/malloc/malloc.c
- - remove __P define, now in imalloc.h
- - include watch.h if MALLOC_WATCH is defined
- - added calls to _malloc_ckwatch in internal_malloc, internal_free,
- and internal_realloc
-
-include/stdc.h
- - augment __P define to allow prototypes if PROTOTYPES is defined
-
-lib/readline/rlstdc.h
- - augment PARAMS define to allow prototypes if PROTOTYPES is defined
-
-lib/malloc/Makefile.in, Makefile.in
- necessary changes to include watch.c in libmalloc
-
-lib/readline/readline.c
- - fix rl_delete_text to make sure that the starting position is >= 0
- - _rl_init_line_state (called by readline via readline_initialize)
- now sets rl_mark to 0
- - rl_get_{next,previous}_history set rl_mark to 0 if rl_point is at
- the end of the line and rl_end otherwise in emacs mode
-
-lib/readline/kill.c
- - rl_yank_nth_arg_internal and rl_paste_clipboard now set the mark
- at point before calling rl_insert_text, like rl_yank
- - rl_kill_full_line now resets rl_mark to 0
- - rl_kill_line and rl_backward_kill_line now set rl_mark to the
- point after the kill in emacs mode
- - rl_kill_word and rl_backward_kill_word now set rl_mark to the
- point after the kill in emacs mode
- - rl_unix_word_rubout and rl_unix_line_discard now set rl_mark to
- the point after the kill in emacs mode
-
-lib/readline/search.c
- - noninc_search saves and restores the mark, since it can be changed
- while reading the search string
- - noninc_dosearch sets the mark at the end of the line, making the
- region bound the `inserted' text since rl_point is set to 0
- - rl_history_search_internal sets the mark at the end of the line,
- for the same reason
-
-lib/readline/isearch.c
- - rl_search_history now saves and restores the mark
- - if no matching lines are found at all when doing an isearch, leave
- point where it was instead of moving it to the end of the line
-
- 12/17
- -----
-lib/readline/rlmbutil.h
- - new file, place for multi-byte character defines and extern
- declarations
-
-lib/readline/{bind.c,readline.c,rlprivate.h}
- - new bindable variable, `byte-oriented', tracks value of
- rl_byte_oriented variable
-
-lib/readline/mbutil.c
- - new file, with multibyte char utility functions
-
-lib/readline/{complete,display,readline,util,vi_mode}.c
- - new code for multibyte characters, derived from IBM patch
-
- 12/18
- -----
-lib/sh/tmpfile.c
- - include posixtime.h for time() extern declaration
-
-support/bashversion.c
- - include <unistd.h> if it's available
-
-lib/readline/{histexpand,input,isearch,search}.c
- - new code for multibyte characters, derived from IBM patch
-
-lib/readline/readline.h
- - include rltypedefs.h
-
- 12/19
- -----
-lib/readline/complete.c
- - slight change to mark-directories code to avoid adding a slash if
- point is at the end of the line (rl_line_buffer[rl_point] == '\0')
- and the previous character was a slash
- - change printable_part to not return empty pathnames, which could
- happen when completing filenames and a filename with a trailing
- slash was passed as the argument. If the portion following the
- trailing slash is NULL, ignore it and look for a previous slash.
- If there's no previous slash, just return the filename argument
- - new variable, rl_completion_mark_symlink_dirs, mirrors the value
- of (user-settable with a variable) _rl_complete_mark_symlink_dirs
- but may be modified by application-specific completion functions
- when appropriate (set in rl_complete_internal and rl_menu_complete)
-
-lib/readline/readline.h
- - extern declaration for rl_completion_mark_symlink_dirs
-
-pcomplete.c
- - if one of the actions is CA_DIRECTORY, set
- rl_completion_mark_symlink_dirs to indicate that we want the
- trailing slash (might have to relax this)
-
-lib/readline/doc/rltech.texinfo
- - documented rl_completion_mark_symlink_dirs variable
-
-lib/readline/doc/rluser.texinfo, doc/bash.1
- - documented the fact that `complete -d' and `complete -o dirnames'
- force readline to append a slash to symlinks to directories
-
-builtins/enable.def
- - changed enable_shell_builtin to disallow enabling disabled
- builtins in a restricted shell
-
-doc/{bash.1,bashref.texi}
- - documented new enable behavior in restricted shells
-
-doc/Makefile.in
- - new rule to make an `RBASH' file documenting the restrictions
- imposed by a restricted shell
-
-expr.c
- - broke the code that evaluates variables and returns results out
- of readtok() into a new function: expr_streval()
- - expr_streval() now performs the standard unset variable error
- behavior if `set -u' has been executed and it's asked to look
- up an unset variable
- - broke the code that frees up the expression context stack into
- a new function: expr_unwind()
-
-variables.c
- - fixed bind_int_variable so it handles array element assignment,
- so expressions like `b[7]++' and `b[0] = 42' work right
- - new function, get_variable_value, returns the string value of
- the SHELL_VAR * passed as an argument
- - get_string_value now calls get_variable_value with a non-null
- result from find_variable
-
- 12/20
- -----
-lib/readline/rlmbutil.h, mbutil.c
- - combined _rl_find_next_mbchar and _rl_find_next_nonzero_mbchar into
- a single function
- - combined _rl_find_prev_mbchar and _rl_find_prev_nonzero_mbchar into
- a single function
-
-lib/readline/{display,readline,vi_mode}.c
- - changed callers of _rl_find_next_mbchar and
- _rl_find_next_nonzero_mbchar
-
-lib/readline/{complete,display,histexpand,readline,vi_mode}.c
- - changed callers of _rl_find_prev_mbchar and
- _rl_find_prev_nonzero_mbchar
-
- 12/20
- -----
-lib/sh/mktime.c
- - new file, from glibc/gawk, compiled in if system doesn't have a
- working mktime(3)
-
-lib/sh/strftime.c
- - new file, from gawk, compiled in if system doesn't have a
- working strftime(3)
-
-lib/sh/Makefile.in, Makefile.in
- - changes for mktime.c, strftime.c
-
-configure.in
- - call AC_FUNC_MKTIME, AC_STRUCT_TM, AC_STRUCT_TIMEZONE
- - call AC_REPLACE_FUNC(strftime)
-
-config.h.in
- - add defines for TM_IN_SYS_TIME, HAVE_TZSET, HAVE_TM_ZONE,
- HAVE_STRUCT_TM_TM_ZONE, HAVE_STRFTIME
-
-externs.h
- - provide an extern declaration for strftime if HAVE_STRFTIME is
- not defined and NEED_STRFTIME_DECL is
-
-lib/tilde/tilde.h
- - header files should not include <config.h>
-
-parse.y
- - replace code in decode_prompt_string that chops up value returned
- by ctime(3) with calls to strftime -- as a result, the expansion
- of \@ has changed slightly (since it depends on the locale)
- - added new \D{format} prompt string escape; `format' is passed to
- strftime(3). Empty format is the same as `%X' (locale-specific
- representation of the current time)
- - combined cases for '\\', '\a', '\e', and '\r' in same case branch
- in decode_prompt_string
-
-doc/{bash.1,bashref.texi}
- - documented new \D{format} prompt string expansion
-
-builtins/printf.def
- - use ISO C PRIdMAX instead of INTMAX_CONV
- - pass length of format modifiers to mklong instead of computing it
- with strlen()
-
-lib/sh/{fmtulong,fmtullong}.c
- - changes from Paul Eggert to make more general
-
-arrayfunc.c
- - when converting a variable to an array, make sure to unset the
- dynamic_value and assign_func members of the struct variable,
- since they're not valid anymore
-
- 12/27
- -----
-configure.in
- - use AC_HELP_STRING in AC_ARG_WITH and AC_ARG_ENABLE
- - remove AC_ARG_ENABLE for largefile, since AC_SYS_LARGEFILE adds
- one
-
- 1/2/2002
- --------
-{alias,bashline,execute_cmd,general,shell,subst,variables,arrayfunc}.c,general.h
- - changed some calls to strchr to calls to xstrchr for multibyte
- characters
-
-include/shmbutil.h
- - add extern declaration for xstrchr to avoid including externs.h
- where it's not appropriate
-
-{braces,make_cmd,pathexp,subst,arrayfunc}.c, lib/sh/xstrchr.c
- - include shmbutil.h
-
-{stringlib,subst}.c, {externs,subst}.h
- - moved substring() from subst.c to stringlib.c, moved declaration
- from subst.h to externs.h
-
-lib/sh/xmbsrtowcs.c
- - new file, replacement function for mbsrtowcs
-
-lib/sh/Makefile.in
- - add entries for xmbsrtowcs.c
-
-Makefile.in
- - add dependencies on shmbutil.h to appropriate object files
-
-lib/glob/strmatch.c
- - break character-class testing out into separate function:
- is_cclass, in prep for multibyte changes
-
-{braces,make_cmd}.c
- - changes for multibyte characters
-
-builtins/printf.def
- - changes from Paul Eggert to just use intmax_t everywhere an
- int/long/quad is needed and print with "%ld" if the number
- fits in a long and %PRIdMAX otherwise
- - remove getlong, getulong, getllong, getullong, since they're
- no longer needed
- - use a new type `floatmax_t' to print floating point numbers, the
- widest-available floating point type (like `intmax_t'); new
- function `getfloatmax' that calls strtold or strtod as appropriate
- - remove getdouble, getldouble, since they're no longer needed
-
-lib/sh/fmtumax.c
- - new file, string-to-[u]intmax_t conversion, just includes
- fmtulong.c with the right defines
-
-Makefile.in, lib/sh/Makefile.in
- - additions for fmtumax.c
-
-bashtypes.h
- - include <inttypes.h> if it's available
-
-expr.c
- - arithmetic is now in intmax_t instead of long
-
-externs.h
- - extern declaration for fmtumax
- - change extern declarations for evalexp, itos, inttostr,
- uitos, uinttostr since they now return or use intmax_t instead
- of long
-
-{execute_cmd,general,mailcheck,subst,variables}.c, parse.y
-{array,general,subst,test,variables}.h
-lib/sh/{itos,netopen}.c
-builtins/{bashgetopt,common}.c, builtins/common.h
-builtins/{break,fc,history,jobs,let,printf,pushd,read,shift,wait}.def
- - changes for intmax_t shell arithmetic conversion
-
-doc/{bashref.texi,bash.1}
- - documented long->intmax_t shell arithmetic conversion
-
-sig.c
- - in initialize_terminating_signals, if we've already trapped a
- terminating signal, don't reset the signal handler for it
-
- 1/3
- ---
-{arrayfunc,pathexp}.c, parse.y
- - changes for multibyte chars
-
-parse.y, lib/sh/strtrans.c
- - moved ansiexpand from parse.y to lib/sh/strtrans.c
-
-parse.y, locale.c
- - moved mk_msgstr and localeexpand from parse.y to locale.c
-
-parse.y
- - new function, yy_input_name, returns name of input file from
- bash_input.name
- - broke the code that parses ((...)) constructs out of read_token
- into a new function, parse_dparen()
-
-externs.h
- - new extern declaration for ansiexpand(), mk_msgstr(), and
- localeexpand()
-
-input.h
- - new extern declaration for yy_input_name()
-
-{error,locale}.c
- - use yy_input_name for error and other messages
-
-execute_cmd.c
- - change shell_execve to make sure that the file is executable
- before looking at the interpreter to find out why the execve()
- failed (avoids misleading error message)
-
-lib/glob/glob.c
- - move code that matches leading `.' and skips those filenames into
- a separate function: skipname(), so there can be unibyte and
- multibyte versions of that function
-
- 1/7
- ---
-subst.c
- - more changes for multibyte characters
-
-print_cmd.c
- - change semicolon() so it doesn't output a `;' immediately after a
- newline, since that results in a null command, which is a syntax
- error
-
-variables.c
- - fix indirection_level_string to turn off set -x while evaluating
- PS4
-
- 1/8
- ---
-builtins/set.def
- - make -o options into one struct, instead of separate structs for
- option names corresponding to flags and non-flag option names.
- This has the side effect of sorting the option names in output
-
-lib/glob/glob.c
- - new function, mbskipname(), multibyte char version of skipname()
- - removed all #ifndef SHELL code, this will never be used outside
- the shell
-
-include/posixdir.h
- - move REAL_DIR_ENTRY define here from lib/glob/glob.c
-
-lib/glob/glob_loop.c
- - new file, included in glob.c for unibyte and multibyte versions of
- glob_pattern_p
- - added some forward static function declarations with prototypes
- - more changes for multibyte character handling
-
-lib/glob/Makefile.in
- - make glob.c depend on glob_loop.c
- - changes for xmbsrtowcs.[co]
-
-lib/glob/xmbsrtowcs.c
- - moved here from lib/sh, since the matching functions use it, and
- libglob.a is linked after libsh.a
-
- 1/9
- ---
-lib/glob/smatch.c
- - new file, with strmatch (now xstrmatch) and associated functions,
- with changes for multibyte chars
-
-lib/glob/sm_loop.c
- - new file, included by smatch.c, with `generic' versions of matching
- functions that are compiled twice: once each for single-byte and
- multibyte characters
-
-lib/glob/strmatch.c
- - strip out everything except strmatch(), which either calls fnmatch
- (if HAVE_LIBC_FNM_EXTMATCH is defined) or xstrmatch
-
-lib/glob/collsyms.c
- - changes for multibyte chars
-
-lib/glob/Makefile.in, Makefile.in
- - changes for new source files
-
- 1/10
- ----
-lib/readline/complete.c
- - new function, rl_completion_mode (rl_command_func_t *func), returns
- the appropriate value to pass to rl_complete_internal depending on
- FUNC and the value of `show-all-if-ambiguous'. This allows
- application completion functions to present the same interface as
- rl_complete
-
-lib/readline/readline.h
- - new extern declaration for rl_completion_mode()
-
-lib/readline/doc/rltech.texinfo
- - documented rl_completion_mode
-
-lib/readline/readline.[ch]
- - bumped the version number to 4.3, changing the relevant cpp defines
-
-configure.in
- - require that an installed readline version be at least readline-4.3
-
-bashline.c
- - converted bash-specific completion functions to use
- rl_completion_mode instead of passing TAB unconditionally
-
-builtins/bashgetopt.c
- - the `#' option specifier now means a required numeric argument,
- not an optional one
-
-builtins/type.def
- - when converting [-]-{path,type,all} to -[pta], don't bother
- freeing and reallocating the option string; just change opt[1]
- and null opt[2]
-
-lib/sh/snprintf.c
- - support %ls/%S and %lc/%C for wide strings and characters,
- respectively, if HANDLE_MULTIBYTE is defined
-
-mailcheck.c
- - don't print a message about new mail if the file has not grown,
- even if the access time is less than the modification time
-
- 1/14
- ----
-lib/readline/readline.c
- - new function, rl_replace_line, to replace the readline line buffer
- with the text supplied as an argument
- - new function, rl_replace_from_history, replaces readline line
- buffer with text from history entry passed as argument (undocumented,
- not in readline.h because it requires a definition of
- HIST_ENTRY for the prototype)
-
-lib/readline/readlne.h
- - new extern declaration for rl_replace_line
-
-lib/readline/doc/rltech.texinfo
- - documented rl_replace_line
-
-lib/readline/{isearch,readline,search}.c
- - use rl_replace_line and rl_replace_from_history where appropriate
-
-lib/readline/readline.c
- - broke the code that sets point after moving through the history
- (_rl_history_preserve_point and _rl_history_saved_point) out
- into a separate function, _rl_history_set_point()
-
-lib/readline/{complete.c,rlprivate.h}
- - find_completion_word -> _rl_find_completion_word
- - free_match_list -> _rl_free_match_list
-
-lib/readline/complete.c
- - postprocess_matches and _rl_free_match_list now return immediately
- if passed a null match list
-
-variables.c
- - new function, find_local_variable, finds a local variable by name
- at the current variable context
- - in find_variable_internal, call find_local_variable before searching
- any of the temporary environments if variable_context > 0 (meaning
- we're in a shell function). This lets a local variable
- override a variable whose value was passed in the `function
- environment'
-
- 1/15
- ----
-variables.h, execute_cmd.c
- - declare variables describing the temporary environments in
- variables.h instead of in C files
-
-findcmd.c, builtins/setattr.def
- - instead of calling find_tempenv_variable, use find_variable_internal
- and check whether the returned SHELL_VAR * has the tempvar
- attribute
-
-variables.c
- - tentative change to lookup order in find_variable_internal so that
- function local variables are found before variables in
- function_env when executing a shell function
- - change make_local_variable to handle making a local variable when
- a variable with the same name already appears in one of the
- temporary environments
- - broke the body of make_var_array out into a new function:
- static char **make_env_array_from_var_list (SHELL_VAR **vars)
- - new function, make_var_array_internal, takes a hash table to look
- in and a pointer to a mapping function and returns a char **
- environment-style list
- - make_var_array now just calls make_var_array_internal
- - new mapping function, local_and_exported, returns all local variables
- in the current variable context with the export attribute set
- - new function, make_local_export_array, returns an environment-style
- char ** array of exported local variables in current context
- - change environment creation order in maybe_make_export_env to
- add variables to the environment in opposite order that
- find_variable_internal uses. This means that local variables in
- shell functions override variables with the same name in the
- function_env
- - change make_local_variable to set the initial value of the
- variable it creates to NULL to make the `is set' and `is null'
- tests that the expansion code does work right
- - change make_local_variable to inherit the value of a variable with
- the same name from the temporary enviroment
-
- 1/16
- ----
-Makefile.in
- - link bashversion with buildversion.o instead of version.o, for
- cross-compiling. version.o is for the target system;
- buildversion.o is for the build system
-
-error.c
- - add line numbers to internal_error() messages if the shell is
- not interactive and running a shell script or a -c command
- - report_error now prints non-zero line numbers for non-interactive
- shells
-
-test.c
- - test_syntax_error now calls builtin_error() instead of printing
- its own messages
-
-builtins/common.c
- - builtin_error now prints line numbers if a non-interactive shell
- is running a shell script or a -c command
-
-print_cmd.c
- - in cprintf, remove free_argp, since it's not used
-
-builtins/history.def
- - make `history -n' increment the number of history lines in this
- session by the number of lines read from the history file
-
-arrayfunc.c
- - fix array_value_internal to expand the subscript even if the
- variable is unset, so side effects produced by the arithmetic
- evaluation will take place
-
-lib/readline/doc/{rluser,rltech}.texinfo
- - some fixes for printing in @smallbook format from Brian
- Youmans
-
- 1/17
- ----
-jobs.h
- - new PRUNNING, PSTOPPED, PDEADPROC defines for PROCESSes, analogous
- to RUNNING, STOPPED, and DEADJOB defines for jobs
-
-jobs.c
- - use PS_RUNNING, PS_DONE, PS_STOPPED values for `running' field
- of a PROCESS
- - find_pipeline and find_job now take an additional flags argument
- that, if non-zero, means to find only running processes; changed
- all callers
- - changed calls to find_pipeline and find_job made from waitchld
- to find only running processes
- - find_pipeline takes a third argument: an int *. If it looks in
- the jobs list to find the pid, and the arg is non-null, it passes
- the job index back to the caller. Used to avoid calls to
- find_pipeline immediately followed by find_job with the same PID
-
-nojobs.c
- - a couple of changes to make sure that set_pid_status is never
- called with a pid argument of 0 or -1
-
-trap.c
- - change trap_handler to longjmp to wait_intr_buf (set by wait_builtin)
- if a signal is received for which a trap has been set during
- execution of the wait builtin (need to include builtins.h and
- builtins/builtext.h and declare some extern variables for the
- right things to check)
- - new variable to keep track of which signal caused the longjmp to
- wait_intr_buf, set by trap_handler (wait_signal_received)
-
-builtins/wait.def
- - set the return value of wait when a longjmp(wait_intr_buf, 1) is
- done to 128 + wait_signal_received
-
-{jobs,nojobs}.c
- - set wait_signal_received to SIGINT in wait_sigint_handler before
- the longjmp(wait_intr_buf, 1)
-
- 1/18
- ----
-bashline.c
- - turn off rl_filename_completion_desired when completing a command
- name with a single match only if the first char of that match is
- not a `/'
- - if there are multiple identical matches for a command name in
- attempt_shell_completion, turn off rl_filename_completion_desired
- if the first char is not a `/' to avoid readline appending a
- slash if there's a directory with the same name in the current
- directory
-
- 1/22
- ----
-lib/readline/complete.c
- - new variable, _rl_page_completions, to control whether we want to
- run the internal pager when listing completions (defaults to 1)
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_page_completions
-
-lib/readline/bind.c
- - new bindable variable, `page-completions', controls value of
- _rl_page_completions
-
-lib/readline/doc/{rluser.texinfo,readline.3}, doc/bash.1
- - documented `page-completions' variable
-
-Makefile.in
- - use $(INSTALL_SCRIPT) instead of $(INSTALL_PROGRAM) to install
- `bashbug'
-
-aclocal.m4
- - fix small quoting problem in RL_LIB_READLINE_VERSION macro
-
-lib/readline/terminal.c
- - fetch and save terminal's `vs' and `ve' cursor control attributes
- - fetch and save terminal's `kI' attribute (string sent by Insert)
- - new function, _rl_set_cursor, sets cursor to normal (insert mode)
- or very visible (overwrite mode)
-
-lib/readline/readline.c
- - new global variable, rl_insert_mode
- - new function to toggle overwrite mode, rl_overwrite_mode
- - each new line starts in insert mode
- - switching to vi mode or emacs mode resets to insert mode
- - reset cursor to normal before returning line
- - _rl_replace_text now returns the number of characters inserted,
- the return value from rl_insert_text
- - new function, _rl_insert_or_replace_text (const char *string, int insert),
- either inserts STRING or replaces the number of chars in STRING
- with STRING starting at rl_point, depending on value of INSERT
- - renamed rl_insert to _rl_insert_char, rl_insert just calls
- _rl_insert_char with the same arguments when in insert mode
- - new function, _rl_overwrite_char, handles self-insert in overwrite
- mode. Does multibyte chars by reading an entire multibyte character
- before entering overwrite loop
- - new function, _rl_overwrite_rubout, handles RUBOUT when in
- overwrite mode, called from rl_rubout
- - new function, _rl_rubout_char, old body of rl_rubout; rl_rubout
- calls this when not in overwrite mode
-
-lib/readline/readline.h
- - extern declarations for rl_insert_mode and rl_overwrite_mode()
-
-lib/readline/rldefs.h
- - define constants for values of rl_insert_mode
-
-lib/readline/rlprivate.h
- - extern declarations for _rl_set_cursor and _rl_set_insert_mode
- - change type of _rl_replace_text to return int
- - extern declarations for _rl_insert_char, _rl_rubout_char
-
-lib/readline/funmap.c
- - new bindable name `overwrite-mode', bound to rl_overwrite_mode
-
-lib/readline/rlconf.h
- - define CURSOR_MODE if you want the cursor to show insert or
- overwrite mode (only available if both `vs' and `ve' capabilities
- are present)
-
-lib/readline/{complete,parens,readline,search,vi_mode}.c
- - change calls to rl_insert to _rl_insert_char
-
-lib/readline/{readline,search}.c
- - change calls to rl_rubout to _rl_rubout_char to avoid overwrite
- mode problems
-
-lib/readline/vi_mode.c
- - fix rl_vi_overstrike to just call _rl_overwrite_char, which
- handles multibyte chars
-
-lib/readline/doc/{rluser.texinfo,readline.3}, doc/bash.1
- - document new `overwrite-mode' command
-
- 1/23
- ----
-lib/readline/readline.c
- - return 0 immediately from rl_insert_text if the string to insert
- is NULL or ""
-
-bashline.c
- - if a numeric argument is given to one of the bash-specific glob
- pattern completion functions (including TAB), append a `*' to
- the word before generating matches
- - in attempt_shell_completion, when doing glob completion, only
- set the match list to NULL if rl_completion_type == TAB and
- there is more than one completion. This permits listing completions
- with double tabs and displaying ambiguous completions
- - new function, bash_glob_complete_word, appends a `*' to the word
- to be completed and then globs it. It uses a new filename
- quoting function (bash_glob_quote_filename) to avoid quoting
- globbing characters in the filename if there are no matches or
- multiple matches
-
-lib/readline/complete.c
- - set completion_changed_buffer to 0 in rl_complete_internal if
- no matches were produced by the completion generator function
- - new variable, rl_completion_suppress_append, suppresses appending
- of rl_completion_append_character. Settable by application
- completion functions, always 0 when application completion
- functions are called (set to 0 by rl_complete_internal and
- rl_menu_complete)
- - broke the code that assigns default values to readline completion
- variables out of rl_complete_internal and rl_menu_complete into
- a new function, set_completion_defaults (int what_to_do)
-
-lib/readline/readline.h
- - extern declaration for rl_completion_suppress_append
-
-lib/readline/doc/rluser.texinfo, doc/bash.1
- - documented behavior of glob-expand-word and glob-list-expansions
- when supplied a numeric argument
- - documented glob-complete-word
-
-lib/readline/doc/rltech.texinfo
- - documented rl_completion_suppress_append
-
- 1/24
- ----
-lib/readline/text.c
- - new file, text and character handling functions from readline.c
-
-lib/readline/misc.c
- - new file, miscellanous bindable functions and their supporting
- code from readline.c
-
-Makefile.in, lib/readline/Makefile.in
- - changes for text.c, misc.c
-
-lib/readline/bind.c
- - change ISKMAP case of rl_invoking_keyseqs_in_map to output
- ESC as "\M-" instead of "\e" -- it's closer to the documentation
- - change _rl_get_keyname to output ESC as \e instead of \C-[
- (it's easier to understand)
-
-pcomplete.h
- - new flag, COPT_NOSPACE
-
-builtins/complete.def
- - new `-o nospace' option for complete and compgen (though it doesn't
- really do anything for compgen, since that doesn't hand anything
- off to readline)
-
-bashline.c
- - if a programmable completion specifies COPT_NOSPACE, set
- rl_completion_suppress_append = 1
-
-lib/readline/doc/rluser.texinfo
- - documented new `-o nospace' option to complete and compgen
-
-doc/{bash.1,bashref.texi}
- - documented $'\cX' escape sequence (forgot to before)
-
- 1/28
- ----
-variables.c
- - make_new_variable now takes the HASH_TABLE * as its second
- argument; changed callers
- - new function, bind_variable_in_table, takes the HASH_TABLE * as
- its third paramter; bind_variable calls bind_variable_in_table
- with shell_variables as third argument
-
-variables.h
- - new struct var_context, variable context (per-scope -- global,
- function local, etc.)
-
-variables.[ch],builtins/common.[ch]
- - moved functions that push and pop a variable context from
- builtins/common.c to variables.c; move extern function
- declarations to variables.h
- - new function, all_local_variables
- - variable_in_context is now static, used only by all_local_variables
-
-variables.[ch],execute_cmd.c
- - push_context now takes the function name as an argument for
- future use
- - push_context takes an indication of whether or not the function is
- executing in a subshell and saves the positional parameters only
- if not in a subshell
- - new functions for managing a stack of variable contexts and
- scopes: new_var_context, dispose_var_context, push_var_context,
- pop_var_context, push_scope, pop_scope
-
-builtins/declare.def
- - call all_local_variables instead of map_over (...) in declare_internal
- - don't call make_local_variable if we're looking at functions
- ((flags_on & att_function) != 0), since it's wasted
- - make sure VAR is set to NULL if check for variable_context fails
- and we didn't just create or fetch a local variable in
- declare_internal
- - in non-function branch of declare_internal, only call find_variable
- if VAR is NULL -- if it's not null, we just created or fetched a
- local variable and don't need to do it again
-
- 1/29
- ----
-variables.[ch]
- - the temporary environments (temporary_env, builtin_env, function_env)
- are now HASH_TABLEs instead of argv-style arrays of strings (this
- is an intermediate step on the way to the new lcc-inspired symbol
- table scope structure)
- - new internal attribute for variables: att_propagate. This means
- to propagate the value out of the temporary environment up the
- (for now implicit) chain of variable scopes when the containing
- temporary environment is deleted
-
-variables.c
- - assign_in_env now adds to the HASH_TABLE temporary_env instead
- of making environment-style strings in an array of strings
- - changed the way the temporary environments are merged into the
- shell variable table to account for the new HASH_TABLE temp
- environments
- - changed the way the export environment is created due to the new
- structure of the temporary environments
- - new function, bind_variable_internal (name, value, table), binds
- NAME to have VALUE in TABLE without searching the temporary
- environments
- - removed: shell_var_from_env_string, bind_name_in_env_array
- - variable_in_context now checks the att_local attribute and makes
- sure the variable is not invisible
- - local_and_exported now makes sure the variable is not invisible
-
-execute_cmd.c
- - we no longer need to copy the temporary environment to function_env
- or builtin_env, we can simply use variable assignments
-
-{findcmd,subst,variables}.c, builtins/{declare,setattr}.def
- - since variables from the temporary environments are no longer turned
- into SHELL_VARs on the fly, don't dispose the SHELL_VAR returned
- by find_variable or find_variable_internal
- - need to savestring() the value returned by find_variable if it has
- the tempvar attribute before calling bind_variable on it, because
- bind_variable will search and bind into the temporary environments
- and will free the old value before binding the new. For temporary
- environments, these two pointers will be the same, and
- bind_tempenv_variable will end up using freed memory
-
-builtins/{declare,setattr}.def
- - set the att_propagate attribute when exporting or making readonly
- variables from the temp environment (i.e., `var=value declare -x var'
- or `var=value export var' sets the propagate attribute on the entry
- for `var' in the temporary environment HASH_TABLE)
-
-lib/readline/isearch.c
- - ^W when reading isearch string yanks the current word out of the
- current line into the search string, skipping the portion already
- matched
- - ^Y when reading isearch string yanks the rest of the current line
- into the search string, skipping the portion already matched
-
- 1/30
- ----
-{print_cmd,variables}.c
- - moved indirection_level_string() from variables.c to print_cmd.c
-
-{externs,variables}.h
- - moved extern declaration of indirection_level_string to externs.h
-
-{general,variables}.c
- - moved assignment() from variables.c to general.c
-
-{general,variables}.h
- - moved extern declaration of assignment() to general.h
-
-{externs,input}.h
- - moved extern declaration of decode_prompt_string to externs.h
-
-print_cmd.c
- - include flags.h, don't include stdc.h
-
-variables.c
- - moved some functions around to group functions better
- - changed new_shell_variable to explicitly initialize each member
- of the created struct variable instead of calling bzero()
- - make_new_variable now just calls new_shell_variable instead
- of duplicating what it does
- - removed some code in bind_function that duplicated what
- new_variable does on the newly-created SHELL_VAR
- - since there are no local function variables (functions are always
- made at the global scope), kill_all_local_variables() doesn't
- need to consider functions
-
- 1/31
- ----
-variables.c
- - sort the array of special variables
- - short-circuit the search in stupidly_hack_special_variables if
- the passed name can't be found in the rest of the array
- (that is, if name[0] < special_vars[i].name[0])
-
-lib/readline/history.c
- - unstifle_history() was returning values exactly opposite of
- the documentation
-
-lib/readline/doc/{hsuser.texinfo,history.3}
- - clarified the unstifle_history() documentation a little
-
- 2/4
- ---
-variables.c
- - in bind_variable, don't call bind_tempenv_variable after a
- find_tempenv_variable succeeds -- just change the value inline.
- There's no reason to look it up twice
- - change makunbound to only call stupidly_hack_special_variables
- if we're not unsetting a function
-
-variables.[ch]
- - new function, unbind_function, like makunbound but doesn't mess
- with previous contexts or calling stupidly_hack_special_variables
-
-builtins/set.def
- - change unset_builtin to call either unbind_func or unbind_variable
-
-builtins/getopts.def
- - call unbind_variable(name) instead of makunbound(name, shell_variables)
-
- 2/5
- ---
-lib/glob/sm_loop.c
- - use malloc instead of xmalloc in BRACKMATCH and handle failures
-
-error.c
- - add extern declaration of executing_line_number with prototype,
- since execute_cmd.h can't be included without including other
- files
-
-lib/readline/parens.c
- - include <unistd.h>
-
-lib/malloc/stats.c
- - include <unistd.h>
- - add extern declaration of malloc_free_blocks() with prototype
-
-pathexp.c
- - added some forward declarations with prototypes for static functions
-
-lib/readline/rlprivate.h
- - removed declarations of rl_untranslate_keyseq, rl_discard_argument,
- rl_stop_output, rl_alphabetic since they appear in readline.h
-
- 2/6
- ---
-{arrayfunc,execute_cmd,pcomplete,shell}.c
- - change calls to makunbound(name, shell_variables) to
- unbind_variable (name)
-
- 2/7
- ---
-builtins/getopt.c
- - don't defer incrementing of OPTIND when an invalid option is
- encountered until the next call to sh_getopt() -- what if OPTIND
- is reset before that next call? This means that OPTIND is always
- incremented to the next option to be handled when an option is
- returned, whether it's valid or not. This is what POSIX-2002
- says to do.
-
-syntax.h
- - new #define, CSUBSTOP
-
-mksyntax.c
- - add "-=?+" with value CSUBSTOP to the syntax table. These are the
- valid expansion operators OP in ${param[:]OPword}
-
-subst.c
- - use table lookup for CSUBSTOP in VALID_PARAM_EXPAND_CHAR
- - new flags for the string extraction functions: EX_NOALLOC. This
- indicates that the functions are being used only to skip over
- strings and the result won't be used, so the substring shouldn't
- be allocated, copied, and freed
- - new flag for string_extract: EX_VARNAME. This serves the same
- purpose as the old `varname' parameter. parameter_brace_expand()
- changed appropriately
- - extract_delimited_string and extract_dollar_brace_string now take
- an additional `flags' argument, which may include EX_NOALLOC
- - changed callers of extract_delimited_string and
- extract_dollar_brace_string appropriately
- - string_extract now understands EX_NOALLOC; callers changed
- - some smaller code cleanups
- - converted char_is_quoted(), unclosed_pair(), and skip_to_delim()
- to understand multibyte characters
-
- 2/11
- ----
-variables.[ch]
- - moved to a symbol organization inspired by lcc. The basic structure
- is no longer a HASH_TABLE, but a VAR_CONTEXT, which includes a hash
- table as one of its members. VAR_CONTEXTs are linked together to do
- variable scoping. One nice thing about this is that the entire
- symbol table doesn't need to be searched at function scope exit to
- remove local variables. Fixes problems with only one instance of
- builtin_env and function_env, even though it really is a stack
- - shell_variables is now a VAR_CONTEXT *, with a global_variables
- variable that points to the bottom of the stack for fast access
- - function-scope local variables (assignments specified on the command
- line before a function call) and function-local variables (declared
- with the `local' builtin) have been unified in the same variable
- context, replacing function_env
- - assignment statements preceding the `.' and `eval' builtins are now
- a separate variable scope VAR_CONTEXT, replacing builtin_env
- - temporary_env (a HASH_TABLE) is now the only separate environment
- - changes to export environment creation, variable binding, variable
- lookup, local variable propagation all changed to work with the
- new symbol table/scope structure
- - a SHELL_VAR no longer has a `prev_context' member; it's not needed
-
-execute_cmd.c
- - changes to push_context calls to include any temporary variables in
- temporary_env; pop_context takes care of propagating any temporary
- variables if necessary
- - calls to push_scope if `eval' or `.' is called with a list of
- preceding variable assignments, and pop_scope called at end of
- builtin's execution. pop_scope takes care of merging temporary
- variables into the shell environment when appropriate
-
-builtins/{setattr,declare}.def
- - changes to account for variable assignments preceding `local',
- `export', `readonly', `declare', etc. to work with the new
- variable scoping implementation
-
-shell.c
- - since shell_variables is now a VAR_CONTEXT, call
- delete_all_contexts() when the shell is reinitializing instead of
- delete_all_variables()
-
-builtins/common.c
- - new function, get_job_by_name(), used by execute_simple_command()
- for the `auto_resume' stuff and get_job_spec()
-
-builtins/common.h
- - new set of #defined constants for flags argument to
- get_job_by_name()
-
- 2/12
- ----
-command.h
- - new redirection operator: r_reading_string for `here strings'
-
-parse.y
- - new token, LESS_LESS_LESS, for new redirection `here string'
- operator: [N]<<< word
- - recognize LESS_LESS_LESS and create the appropriate redirection
-
-{dispose_cmd,copy_cmd,make_cmd,print_cmd}.c
- - recognize r_reading_string and do the right thing (dispose_redirects,
- copy_redirect, print_redirection, and make_redirection, respectively)
-
-redir.c
- - here_document_to_fd now takes the redirection operator as its
- second argument
- - new function, write_here_string, expands a here string and writes it
- to the here document file descriptor
- - here_document_to_fd calls write_here_string for r_reading_string
- operator
- - handle r_reading_string in do_redirection_internal() and
- stdin_redirection()
-
- 2/18
- ----
-doc/{bash.1,bashref.texi}
- - documented here strings
-
-{configure,Makefile}.in
- - bumped version number up to bash-2.05b and the release status
- to alpha1
-
-expr.c
- - make expr_streval understand that variables with the `invisible'
- attribute are really unset, and accessing such a variable when
- `set -u' is set should be an error
-
-variables.h
- - new accessor macros: var_isset(var) and var_isnull(var), test
- whether var->value is NULL
-
-{eval,subst,variables}.c, builtins/{declare,setattr}.def
- - be more consistent about using value_cell(var) instead of
- directly referencing var->value
- - use var_isset and var_isnull where appropriate
-
-builtins/help.def
- - augmented a couple of help strings with pointers to `info' and
- `man -k'
-
- 2/14
- ----
-variables.h
- - new macros to use when setting variable values directly instead of
- through bind_variable and its siblings
-
-{arrayfunc,variables}.c
- - use var_setarray and other lvalue macros instead of assigning to
- var->value directly
-
-builtins/setattr.def
- - change show_var_attributes to show function definitions separately
- from function attributes. This allows the output of `declare -f'
- (with other flags), `export -f', and `readonly -f' to be reused as
- shell input, instead of the old
-
- declare -f[flags] func()
- {
- foo
- }
-
- which has syntax errors. When in posix mode, `export -fp' and
- `readonly -fp' still don't print function definitions
-
- 2/16
- ----
-parse.y
- - comment out calls to discard_parser_constructs; no need to call
- empty functions
-
- 2/18
- ----
-lib/sh/memset.c
- - replacement function for memset(3)
-
-lib/sh/Makefile.in, Makefile.in
- - additions for memset.c
-
-configure.in,config.h.in
- - check for memset, define HAVE_MEMSET if found, add memset.o to
- LIBOBJS if not
-
-lib/malloc/malloc.c
- - removed zmemset(), replaced with calls to memset(3)
-
-{subst,execute_cmd,lib/sh/netopen}.c
- - replaced calls to bzero with calls to memset
-
-subst.c
- - word_split() now takes a second argument: the value of $IFS, so
- it doesn't have to look up IFS every time
- - word_list_split() now calls getifs() and passes the result to
- each call to word_split() as its second arg
- - do a quick scan for CTLNUL in remove_quoted_nulls before allocating
- new string, copying old string to it, copying over original string
- and freeing new string
-
-eval.c
- - don't bother calling dispose_used_env_vars if temporary_env is NULL
-
-execute_cmd.c
- - fix fix_assignment_words to only look up the builtin corresponding
- to the first word if one of the words in the list is marked as
- W_ASSIGNMENT
-
-hashlib.c
- - renamed hash_string to hash_bucket, which better reflects what it
- does
- - extracted the portion of hash_bucket that computes the hash out
- into a new hash_string()
- - made new body of hash_bucket into a macro HASH_BUCKET; function
- just calls the macro
- - calls to hash_bucket in this file now call HASH_BUCKET macro
- - in add_hash_item, just add a new item at the front of the appropriate
- bucket list instead of at the end
-
-hashcmd.h
- - reduced FILENAME_HASH_BUCKETS to 53 from 107
-
- 2/19
- ----
-hashlib.[ch]
- - find_hash_item, remove_hash_item, add_hash_item all take a new
- third `flags' argument
- - add_hash_item doesn't call find_hash_item if HASH_NOSRCH passed in
- flags arg
- - find_hash_item will create a new hash table entry if HASH_CREATE is
- passed in flags arg
- - new function, hash_walk, takes a pointer to a function and a table
- and calls the function for each item in the table. If the function
- returns < 0, the walk is terminated
- - fixed flush_hash_table to set table->nentries to 0 after freeing
- all entries
- - BUCKET_CONTENTS now has a new `khash' member, what key hashes to;
- set by HASH_BUCKET macro (which calls hash_string), assigned in
- find_hash_item (HASH_CREATE) and add_hash_item
- - find_hash_item and remove_hash_item check `khash' against the
- hash of the string argument before calling strcmp
-
-{alias,hashlib,hashcmd,pcomplib,variables}.c
- - changed all calls to {find,remove,add}_hash_item
-
-builtins/hash.def
- - return immediately from print_hashed_commands if there are no
- entries in the hash table (this eliminates need for `any_printed'
- variable)
- - change print_hashed_commands to use hash_walk
-
-alias.c
- - short-circuit all_aliases and map_over_aliases if
- HASH_ENTRIES(aliases) == 0
- - simplify map_over_aliases by just allocating enough room in the
- returned list for all entries in the aliases hash table, instead
- of doing the check and xrealloc
- - add_alias now calls add_hash_item with HASH_NOSRCH argument
-
-pcomplete.h
- - sh_csprint_func_t is no more; use hash_wfunc instead
-
-pcomplib.c
- - short-circuit print_all_compspecs if HASH_ENTRIES(prog_completes)
- is 0
- - print_all_compspecs now takes a `hash_wfunc *' argument
- - print_all_compspecs now just calls hash_walk
-
-builtins/complete.def
- - new function, print_compitem, takes a BUCKET_CONTENTS *, extracts
- the right info, and calls print_one_completion
-
-variables.c
- - short-circuit map_over_funcs if HASH_ENTRIES(shell_functions) == 0
- - short-circuit flatten if the passed table has no entries
- - bind_variable_internal takes a new fourth argument: `hflags',
- to pass to hash table functions
- - make_new_variable now passes HASH_NOSRCH flag to add_hash_item
- - set_if_not now calls bind_variable_internal and passes
- HASH_NOSRCH as flags argument
- - bind_function now calls add_hash_item with HASH_NOSRCH argument
- - fixed make_local_variable: old_var == 0 && was_tmpvar can never
- be true
- - if we didn't find an old variable in make_local_variable, call
- bind_variable_internal with HASH_NOSRCH argument
- - fix push_temp_var to reset variable context to 0 if binding into
- global_variables->table
-
-parse.y
- - fix to parse_compound_assignment to avoid core dumps on empty
- compound array assignments
-
-subst.c
- - getifs() is now global so read_builtin can call it
-
-subst.h
- - extern declaration for getifs()
-
- 2/20
- ----
-hashlib.c
- - changed hash_string to use a better hash function
- - changed HASH_BUCKET to use masking rather than modulus to hash a
- string to a bucket -- HASH TABLES MUST NOW BE SIZED BY POWERS
- OF TWO
-
-hashlib.h
- - DEFAULT_HASH_BUCKETS is now 64
-
-hashcmd.h
- - FILENAME_HASH_BUCKETS is now 64
-
-pcomplib.c
- - COMPLETE_HASH_BUCKETS is now 32
-
-variables.c
- - TEMPENV_HASH_BUCKETS is now 4
-
-alias.c
- - new define, ALIAS_HASH_BUCKETS, set to 16, used to size alias table
-
-hashlib.c
- - removed initialize_hash_table; folded code into make_hash_table
- - fixed copy_bucket_array to copy the `khash' member of an item
- - renamed functions to be more systematic and easier for me:
- make_hash_table -> hash_create
- hash_table_nentries -> hash_size
- copy_hash_table -> hash_copy
- find_hash_item -> hash_search
- remove_hash_item -> hash_remove
- add_hash_item -> hash_insert
- flush_hash_table -> hash_flush
- dispose_hash_table -> hash_dispose
- print_table_stats -> hash_pstats
- get_hash_bucket -> hash_items
- - changed hash_search to short-circuit if table->nentries == 0 and
- HASH_CREATE has not been passed in the flags argument
-
-{alias,variables,hashcmd,pcomplib}.c
- - renamed calls to all renamed functions from hashlib.c
-
-builtins/kill.def
- - don't drop a leading `-' in a pid argument
- - call kill_pid with an explicit third argument of 1 if the pid
- argument to kill is < -1, rather than rely on the behavior of
- kill(2)
-
- 2/21
- ----
-subst.c
- - quoted_strchr is no longer declared `inline'
- - skip_double_quoted is no longer declared `inline'
- - string_extract_double_quoted is no longer declared `inline'
-
-lib/readline/input.c
- - rl_gather_tyi is now an `int' valued function; returns the number
- of characters read (0 or 1) or -1 on error
- - if rl_gather_tyi() returns -1 to rl_read_key(), set rl_done to 1
- and return a newline; something is wrong with the input fd
-
- 2/25
- ----
-variables.[ch]
- - IFS is now a special variable
- - new special var function, sv_ifs(), called when IFS is set or unset
- - call setifs() when IFS is first set in initialize_shell_variables
- - call setifs() from make_local_variable and assign_in_env if
- appropriate
- - if assign_in_env() is called with a var assignment like `VAR=',
- make the value in the new SHELL_VAR created be "" like
- do_assignment_internal does, since certain parts of the shell use
- a NULL value as evidence that the variable is unset (though
- attributes may have been assigned)
- - if push_temp_var pushes something up to the global_variables table,
- make sure that the context is set to 0
- - new function dispose_temporary_env, called by both
- dispose_used_env_vars and merge_temporary_env with different `free
- func' function pointers; calls sv_ifs after disposing the temporary
- environment
- - push_exported_var now calls bind_variable_internal instead of
- bind_variable
- - pop_scope and pop_context now call sv_ifs
-
-subst.[ch]
- - new global variables used to keep track of IFS state, to avoid
- having to call find_variable("IFS") all the time:
-
- ifs_var the SHELL_VAR for IFS
- ifs_value ifs_var ? value_cell (ifs_var) : " \t\n"
- ifs_cmap bitmap of characters in ifs_value
- ifs_firstc first character in ifs_value
-
- - new function setifs(), sets the aforementioned ifs variables each
- time IFS is set or unset, and at nested scope exit
- - instead of calling getifs() from inside subst.c, use ifs_value
- - getifs() now just returns ifs_value
- - use ifs_firstc in string_list_dollar_star()
- - only call member() in issep() if separators is more than one char
- - don't cache a bitmap every time expand_word_internal() is called;
- use ifs_cmap instead
- - new macro, isifs(c), checks whether C is in ifs_cmap
-
-builtins/read.def
- - use issep() and isifs() macros instead of looking at $IFS directly
-
-syntax.h
- - make sure macros that access sh_syntaxtab cast the argument to
- `unsigned char' before array access
- - new macros: issyntype(c, type) and notsyntype(c, type), check
- sh_syntaxtab[c] for a particular flag value `type'
-
- 2/26
- ----
-hashlib.h
- - the `data' member of a `BUCKET_CONTENTS' is now a PTR_T
-
-{hashlib,alias,variables,hashcmd,pcomplib}.c
- - removed some casts when assigning to and using `data' member of a
- `BUCKET_CONTENTS'
-
-subst.c
- - in split_at_delims, call make_word_list instead of allocating and
- initializing a WORD_LIST * directly
-
-make_cmd.[ch]
- - add_string_to_list is now just a macro that calls make_word_list
- - make_simple_command now calls make_word_list instead of allocating
- a WORD_LIST * directly
-
- 2/27
- ----
-copy_cmd.c
- - copy_word now calls make_bare_word to allocate the copy
- - copy_word_list now calls make_word_list to allocate the copy
-
-shell.h
- - include `ocache.h' for simple object caching
- - call cmd_init() to initialize the WORD_DESC and WORD_LIST object
- caches
-
-{make,dispose}_cmd.c
- - allocate WORD_DESC * and WORD_LIST * vars from their respective
- ocaches, and return them to the cache when disposing
-
-jobs.c
- - renamed old `waiting_for_job' variable to `queue_sigchld', which
- better reflects its intent: sigchld_handler does not call waitchld
- if `queue_sigchld' is non-zero, it simply increments the count of
- waiting children
- - cleanup_dead_jobs now just sets and clears queue_sigchld instead of
- blocking and unblocking SIGCHLD; it calls waitchld at the end if
- `sigchld' is non-zero, but that's not really necessary
- - in setjstatus, only call xrealloc if `statsize' is less than the
- number of processes passed -- no reason to do it if they're the
- same
-
- 2/28
- ----
-sig.[ch]
- - reinitialize_signals is no more; initialize_signals takes an
- argument saying whether or not we are reinitializing
-
-builtins/exec.def
- - reinitialize_signals() -> initialize_signals(1)
-
-test.c
- - fix filecomp() to work right when one file has a non-positive
- timestamp and the other file does not exist
-
-doc/{bash.1,bashref.texi}
- - document what happens for test's -nt and -ot operators when one
- file operand exists and the other does not
-
-jobs.c
- - if we haven't messed with SIGTTOU, just manipulate queue_sigchld
- in notify_of_job_status instead of calling sigprocmask()
- - list_one_job now calls pretty_print_job directly instead of going
- through print_job
- - pretty_print_job now must be called with SIGCHLD blocked or held
- instead of blocking SIGCHLD itself
- - changed start_job so that it doesn't call UNBLOCK_CHILD and then
- immediately call BLOCK_CHILD again (explicitly or via last_pid()),
- call find_last_pid instead of last_pid and then UNBLOCK_CHILD
- - changed wait_for_job the same way
- - find_last_pid now takes a second argument: block; uses BLOCK_CHILD
- if `block' is 1, not otherwise. Changed existing calls:
- find_last_pid(j) -> find_last_pid(j, 0)
- last_pid(j) -> find_last_pid(j, 1)
- `last_pid()' is now gone
- - rewrote wait_for_background_pids(); it was a little strange
-
-copy_cmd.c
- - copy_if_command: don't copy null false_case commands
- - copy_simple_command: don't copy a null redirection list
-
-subst.c
- - in get_word_from_string and list_string, just check for " \t\n"
- directly rather than calling strcmp
- - in get_word_from_string and strip_trailing_ifs_whitespace, use
- isifs() instead of issep(), since they're never called with
- separators != $IFS
- - change issep() to call isifs if separators is longer than one
- character, since it's never called with anything but "", " ",
- or $IFS
-
- 3/1
- ---
-sig.h
- - enclose the BLOCK_SIGNAL macro in a do {...} while (0) loop, at it
- should have been all along
-
-lib/readline/doc/rltech.texinfo
- - document that readline defaults to stdin/stdout if rl_instream/
- rl_outstream are NULL
-
-lib/readline/terminal.c
- - if an application is using a custom redisplay function,
- rl_resize_terminal just calls rl_forced_update_display to tell
- (*rl_redisplay_func) to update the display, otherwise call
- _rl_redisplay_after_sigwinch
-
-lib/readline/readline.c
- - change readline_internal_setup() so the change to vi insertion mode
- happens even if readline_echoing_p is 0
- - don't print the prompt to rl_outstream in readline_internal_setup
- if we're not echoing and the caller has defined a custom redisplay
- function -- let the redisplay function deal with it
-
-configure.in
- - new option: --enable-mem-scramble, controls memory scrambling on
- free() (on by default; only affects use of bash malloc)
-
-config.h.in
- - new option MEMSCRAMBLE, controlled by --enable-mem-scramble
-
- 3/5
- ---
-parse.y
- - added ksh-like behavior of [...] to read_token_word: if a `[' is
- seen in an assignment context and the previous characters in the
- token form a valid identifier, parse the [...] with
- parse_matched_pair to allow spaces (and newlines) in the subscript
-
-bashline.c
- - new function bash_servicename_completion_function, for completing
- service names from /etc/services
-
-bashline.h
- - new extern declaration for bash_servicename_completion_function
-
-builtins/complete.def
- - allow new `-s/-A service' option to complete and compgen builtins
-
-pcomplete.h
- - new CA_SERVICE define, new ITEMLIST variable it_services
-
-pcomplete.c
- - add callback to bash_servicename_completion_function to generate
- list of matching service names for completion
-
-doc/bash.1,lib/readline/doc/rluser.texinfo
- - documented new `-s/-A service' option to complete and compgen
-
- 3/6
- ---
-builtins/read.def
- - change hard-coded `0' to new variable `fd' (initially 0) in
- preparation for adding `-u fd' option
-
-bashline.c
- - bash_directory_completion_hook calls expand_prompt_string instead
- of expand_string (it does the right thing). This keeps expansion
- errors from causing a longjmp, which shouldn't happen because of
- completion
- - command_subst_completion_function was augmented very slightly to
- do filename completion on a non-command-word in a command
- substitution
- - command_subst_completion_function now skips over the lcd that
- rl_completion_matches puts in matches[0] if there is more than
- one possible completion
-
- 3/7
- ---
-builtins/read.def
- - only add the unwind_protect to free `rlbuf' if `edit' is non-zero,
- since we won't be using readline otherwise
-
-lib/sh/zread.c
- - renamed zread1 -> zreadintr
-
-redir.c
- - small change to redirection_error() to make a slightly better
- guess about the invalid file descriptor if the redirection op is
- r_duplicating_input or r_duplicating_output
-
-include/stdc.h
- - new macro, SH_VA_START, to encapsulate the difference between
- stdarg va_start and varargs va_start
-
-{error,pcomplete,print_cmd}.c,builtins/common.c,lib/sh/snprintf.c
- - use SH_VA_START
-
- 3/8
- ---
-builtins/read.def
- - support for the ksh-like `-u fd' option
-
-general.c
- - new function sh_validfd(fd), returns 1 if fd is a valid open file
- descriptor
-
-general.h
- - extern decl for sh_validfd
-
-bashline.c
- - don't call posix_readline_initialize() from initialize_readline();
- sv_strict_posix() should already have taken care of it
-
- 3/11
- ----
-{error,pcomplete,print_cmd}.c, builtins/common.c
- - removed non-varargs versions of functions
-
-builtins/printf.def
- - if the string argument to %q has non-printing characters, call
- ansic_quote to quote it rather than sh_backslash_quote
-
-variables.h
- - new attribute: att_trace (and corresponding trace_p() macro).
- Functions with this attribute will inherit the DEBUG trap.
- Currently ignored for variables
-
-builtins/declare.def
- - new `-t' option to declare/typeset toggle the `att_trace' attribute
-
-builtins/setattr.def
- - check for att_trace and output `-t' flag in show_var_attributes
-
-execute_cmd.c
- - if a function is being traced (it has the `-t' attribute set),
- don't turn off the DEBUG trap when it executes
-
-doc/{bash.1,bashref.texi}
- - document the new `-t' option to declare/typeset
-
- 3/12
- ----
-execute_cmd.c
- - don't execute the debug trap in the `cm_simple:' case of
- execute_command_internal; run it in execute_simple_command so we
- get the line number information right when executing in a shell
- function
- - run a DEBUG trap before executing ((...)) arithmetic commands,
- like ksh93
- - run a DEBUG trap before executing [[...]] conditional commands,
- like ksh93
-
-eval.c
- - add a static forward declaration for alrm_catcher()
-
-general.c
- - add static forward declarations for bash_special_tilde_expansions,
- unquoted_tilde_word, initialize_group_array
-
-variables.h
- - add extern declarations for sh_get_env_value, map_over_funcs,
- local_exported_variables
-
-variables.c
- - add static forward declarations for dispose_temporary_env,
- make_func_export_array
-
-bashhist.c
- - add static forward declaration for check_history_control
-
-configure.in
- - add a call to AC_CHECK_DECLS for strcpy
-
-config.h.in
- - add placeholder for HAVE_DECL_STRCPY define, set by configure
-
-general.h
- - don't declare strcpy if HAVE_DECL_STRCPY is defined with a non-zero
- value
-
-sig.h
- - add prototype to typedef of SigHandler
-
-lib/readline/histlib.h
- - removed extern declaration of strcpy()
- - include string.h/strings.h directly in histlib.h instead of source
- files
-
-lib/readline/{histexpand,histfile,history,histsearch}.c
- - don't include string.h/strings.h now that histlib.h includes it
-
-lib/tilde/tilde.c
- - removed extern declaration of strcpy(), rely on string.h/strings.h
-
-command.h
- - four new redirection types: r_move_input, r_move_output,
- r_move_input_word, r_move_output_word, for
- [N]<&word- and [N]>&word- from ksh93
-
-print_cmd.c
- - changes to print r_move_input[_word] and r_move_output[_word]
-
-copy_cmd.c
- - changes to copy r_move_input[_word] and r_move_output[_word]
-
-dispose_cmd.c
- - changes to dispose r_move_input_word and r_move_output_word
-
-make_cmd.c
- - changes to make r_move_input[_word] and r_move_output[_word] from
- r_duplicating_{input,output}_word, which is how the new redirs
- are passed by the parser
-
-redir.c
- - changes to make r_move_input[_word] and r_move_output[_word] do
- the right thing when executed
-
-builtins/read.def
- - print an error message and return failure immediately if zread/zreadc
- return < 0
-
-doc/{bash.1,bashref.texi}
- - documented new [n]<&word- and [n]>&word- redirections
-
- 3/13
- ----
-lib/readline/isearch.c
- - enabled code to allow chars bound to rl_rubout to delete characters
- from the incremental search string
-
-shell.c
- - add `-l' invocation option to parse_shell_options; equivalent to
- `--login'
- - fixed set_login_shell to check first char of base pathname of argv0
- for `-', like other shells
- - move the check for make_login_shell after the call to
- parse_shell_options because the `-l' option might set it
-
-doc/{bash.1,bashref.texi}
- - documented new `-l' invocation option
-
-array.c
- - new function, array_shift, shifts an array left by a specified
- number of elements
- - array_walk is now compiled in by default
- - array_to_assignment_string now takes a second argument: int quoted.
- If non-zero, the result is single-quoted before being returned
- - quoted_array_assignment_string has been removed
-
-array.[ch]
- - renamed most of the array functions so that all have an array_
- prefix and are more systematically named
- - array_slice now preserves the indicies from the original array
- - change array_to_assign to use a static buffer for expanding the
- array indices, instead of malloc/free
-
-{arrayfunc,subst,variables}.c, builtins/read.def
- - changed calls to various array functions to use new names
-
-lib/sh/stringvec.c, externs.h
- - renamed all of the functions to have a strvec_ prefix and to have
- a more sensible name scheme
- - strvec_search's arguments are now supplied in reverse order, so
- the char **array is first, like the other functions
- - new function, strvec_resize, xrealloc for strvecs
-
-{alias,array,bracecomp,braces,bashline,execute_cmd,findcmd,general,pathexp,
-pcomplete,variables}.c
-lib/sh/stringlist.c
-builtins/{bind,complete,exec,getopts,pushd,set}.def
- - change calls to all functions from lib/sh/stringvec.c
- - use strvec_resize where appropriate
-
-externs.h
- - only declare dup2() if HAVE_DUP2 is undefined or DUP2_BROKEN is
- defined
-
-lib/readline/{macro,readline,util}.c, lib/readline/rlprivate.h
- - _rl_defining_kbd_macro is gone, use RL_ISSTATE(RL_STATE_MACRODEF)
-
-lib/readline/readline.h
- - new struct readline_state, encapsulates most of readline's internal
- state in case you need reentrancy or nested calls to readline()
- - extern declarations for rl_save_state, rl_restore_state
-
-lib/readline/readline.c
- - add (undocumented) int rl_save_state (struct readline_state *),
- int rl_restore_state (struct readline_state *)
-
- 3/14
- ----
-array.[ch]
- - new function, array_rshift, shifts an array right by a specified
- number of elements, optionally inserting a new element 0
-
-examples/bashdb/bashdb
- - new single-file version of bash debugger, originally modified from
- version in bash-2.04 by Gary Vaughan (the old debugger still
- appears in examples/obashdb). This version has a more gdb-like
- command set
-
-examples/bashdb/bashdb.el
- - new emacs bashdb debugger mode from Masatake YAMATO <jet@gyve.org>
-
-execute_cmd.c
- - don't make $LINENO relative to function start unless the shell is
- currently interactive -- this is what ksh93 does and what I
- believe to be the intent of POSIX.2 (this required changing some
- of the test checks because the output has changed)
- - run the debug trap for each command in an arithmetic for expression,
- like ksh93 does
-
-lib/readline/vi_mode.c
- - redid rl_vi_subst (binding func for `s' and `S') in terms of
- rl_vi_change_to: `S' == `cc' and `s' == `c '. This makes undo
- work right
-
- 3/18
- ----
-hashlib.c
- - fixed hash_walk to return if the item function returns < 0, instead
- of breaking out of the current hash chain
-
-array.c
- - fixed array_walk to return if the item function returns < 0, like
- hash_walk
-
-lib/sh/stringlist.c, externs.h
- - new function: strlist_walk, takes a stringlist and a pointer to an
- item func. Like other _walk funcs, if item func returns < 0 the
- walk is cancelled
- - new function: strlist_flush, frees items in the contained list
- with strvec_flush
- - renamed functions to have a strlist_ prefix and be more systematic
-
-pcomplib.c,pcomplete.h
- - removed redundant `progcomp_initialized' variable
- - renamed functions to have `progcomp_' or `compspec_' prefixes
- like the hash library
-
-{bashline,pcomplete}.c,builtins/complete.def
- - fixed calls to stringlist functions to use new names
- - fixed calls to functions in pcomplib.c to use new names
-
-pcomplete.c
- - made the debugging code #ifdef DEBUG -- it should be mature enough
-
-builtins/hash.def,parse.y
- - use REVERSE_LIST(x, t) instead of (t)reverse_list(x)
-
-list.c,{externs,general}.h
- - renamed the list functions to have a list_ prefix, changed callers
-
-externs.h,{execute_cmd,stringlib,subst}.c,builtins/common.c,lib/sh/stringvec.c
- - word_list_to_argv -> strvec_from_word_list
- - argv_to_word_list -> strvec_to_word_list
- - moved functions to lib/sh/stringvec.c
-
-lib/sh/stringvec.c
- - changed name of second argument to strvec_from_word_list from `copy'
- to `alloc' so the use of `copy' between strvec_from_word_list and
- strvec_to_word_list isn't as confusing
- - changed name and sense of second argument to
- strvec_to_word_list from `copy' to `alloc' for the same reason --
- now both functions agree on semantics of second argument
-
-lib/sh/stringlist.c
- - ditto for strlist_from_word_list and strlist_to_word_list
-
-subst.c
- - changed callers of strvec_to_word_list
-
- 3/19
- ----
-builtins/hash.def
- - added `-l' option to list table or individual targets in reusable
- format
- - added `-d' option to remove one or more names from the table of
- hashed commands (provides `unhash' or `unalias -t' functionality)
-
-doc/{bash.1,bashref.texi}
- - documented new `-l' and `-d' options to `hash'
-
-hashcmd.[ch]
- - renamed functions to have a `phash_' prefix and follow new naming
- convention
- - phash_remove now returns an int: 1 if command not in hash table,
- 0 if filename removed OK
-
-{findcmd,variables}.c, builtins/{hash,type}.def
- - changed callers to use new names from hashcmd.c
-
-builtins/common.[ch]
- - new function, sh_notfound(s), prints standard `not found' message
- - new function, sh_invalidid(s), prints standard `invalid identifier'
- message
- - new function, sh_restricted(s), prints standard `restricted' message
- for restricted shells
- - new function, sh_invalidnum(s), prints standard `invalid number'
- message
- - renamed bad_option to sh_invalidopt, changed to print
- `invalid option' instead of `unknown option'
- - new function, sh_invalidoptname, prints standard `invalid option
- name' for long options
- - new function, sh_badjob (s), prints standard `no such job' message
- - new function, sh_invalidsig (s), prints standard `invalid signal
- specification' message
- - new function, sh_nojobs (s), prints standard `no job control' message
- - new function, sh_needarg (s), prints standard `option requires an
- argument' message
- - new function, sh_neednumarg (s), prints standard `numeric
- argument required' message
- - new function, sh_badpid(s), prints standard `not a pid...' message
- - new function, sh_erange (s, desc) prints standard `out of range'
- message, optionally using `desc' to say what the argument is
-
-builtins/{alias,command,declare,exec,hash,type}.def
- - call sh_notfound() instead of calling builtin_error directly
-
-builtins/{declare,getopts,read,set,setattr}.def
- - call sh_invalidid() instead of calling builtin_error directly
-
-builtins/{cd,command,enable,exec,hash,source}.def
- - call sh_restricted() instead of calling builtin_error directly
-
-builtins/{printf,read,ulimit}.def, builtins/common.c
- - call sh_invalidnum instead of calling builtin_error directly
-
-builtins/{complete,declare,pushd,set}.def, builtins/bashgetopt.c
- - call sh_invalidopt instead of bad_option or builtin_error directly
-
-builtins/{complete,set,shopt}.def
- - call sh_invalidoptname instead of builtin_error directly
-
-builtins/{fg_bg,jobs,kill,wait}.def
- - call sh_badjob instead of calling builtin_error directly
-
-builtins/common.c, builtins/{kill,signal}.def
- - call sh_invalidsig instead of calling builtin_error directly
-
-builtins/{fg_bg,suspend,wait}.def
- - call sh_nojobs instead of calling builtin_error directly
-
-builtins/{common,bashgetopt}.c, builtins/{hash,kill}.def
- - call sh_neednumarg and sh_needarg where required
-
-builtins/{kill,wait}.def
- - call sh_badpid where required
-
-builtins/{break,fc,history,pushd,shift,ulimit,umask}.def
- - call sh_erange where appropriate
-
-builtins/printf.def
- - new static function, printf_erange, prints standard out-of-range
- warning message
-
-builtins/set.def
- - changed so that calls to sh_invalidopt always include the leading
- `+' or `-'
-
-builtins/shopt.def
- - changed SHOPT_ERROR macro to shopt_error function
-
-builtins/bind.def
- - regularized error messages to `bind: object: error string' like
- other error messages
-
-builtins.h
- - the `short_doc' member of a `struct builtin' is now of type
- `const char *'
- - the strings in `long_doc' array of a struct builtin are now const
-
-builtins/mkbuiltins.c
- - changes for new `const' members of struct builtin
-
- 3/20
- ----
-lib/readline/histfile.c
- - use pointers instead of indexing into buffer when reading the
- contents of the history file in read_history_range and
- history_truncate_file
-
- 3/21
- ----
-lib/readline/histfile.c
- - new file, with code to mmap the history file for reading and
- writing (depends on HAVE_MMAP, currently nothing checks for that)
-
- 3/25
- ----
-error.[ch]
- - new function, err_badarraysub(s), calls report_error with standard
- `bad array subscript' message
- - new function, err_unboundvar(s), calls report_error with standard
- `unbound variable' message
- - new function, err_readonly(s), calls report_error with standard
- `readonly variable' message
-
-{arrayfunc,subst}.c
- - call err_badarraysub where appropriate
-
-{expr,subst}.c
- - call err_unboundvar where appropriate
-
-{arrayfunc,variables}.c
- - call err_readonly where appropriate
-
-shell.c
- - changed text of bad option error messages to be the same as that
- printed for builtin errors
-
-builtins/common.c
- - changed sh_invalidopt to print the invalid option before the rest
- of the error message (required some tests to be modified)
- - new function, sh_readonly, calls builtin_error with standard
- `readonly variable' message
-
-variables.c,builtins/declare.def
- - call sh_readonly where appropriate
-
-lib/sh/stringvec.c
- - added strvec_remove (sv, s), removes S from SV and shuffles rest of
- elements down 1
-
-lib/sh/stringlist.c
- - added strlist_remove(sl, s), just calls strvec_remove on the
- component list
-
-externs.h
- - new extern declarations for strvec_remove and strlist_remove
- - fixed extern declaration for strvec_search; the arguments were
- reversed (unimportant, it's not compiled into the shell)
-
-subst.c
- - change param_expand to call quote_escapes on values retrieved when
- expanding the positional parameters
- - change parameter_brace_expand_word to quote escapes on values
- retrieved when expanding the positional parameters
- - fix parameter_brace_substring to quote escape characters on unquoted
- substrings extracted from variable values (needed to separate case
- VT_VARIABLE from VT_ARRAYMEMBER for this, since, because
- get_var_and_type calls array_value for VT_ARRAYMEMBER, we need to
- skip over quoted characters in an already-appropriately-quoted
- string to find the substring we want)
- - fix parameter_brace_substring to quote escape characters in the
- value returned by pos_params when expanding subsets of the
- positional parameters and not within double quotes (in which case
- pos_params() quotes the string for us)
- - fix parameter_brace_substring to quote escape characters in the
- value returned by array_subrange when expanding subsets of an
- array and not within double quotes (in which case
- array_subrange() quotes the string for us)
- - new function, quoted_strlen(s), does strlen(s) while skipping over
- characters quoted with CTLESC (#ifdef INCLUDE_UNUSED, since it's
- not used yet)
- - changed pos_params() so it always returns a list whose members are
- quoted strings if (quoted&(Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) != 0
-
-arrayfunc.c
- - fix array_value to consistently call quote_escapes, even when a
- non-array variable is being subscripted with element 0, in which
- case we return the variable value
-
-lib/sh/strtrans.c
- - make the for_echo parameter to ansicstr a `flags' parameter that
- has its old `for echo' meaning if flags&1 is non-zero (which is
- consistent with the old code)
- - Added code to the `flags' parameter to ansicstr so that if flags&2
- is non-zero, CTLESC and CTLNUL are escaped with CTLESC in the
- expanded string
- - change ansiexpand() to call ansicstr with a `flags' parameter of 2
-
- 3/26
- ----
-lib/readline/histfile.c
- - when reading and writing the history file, use malloc instead of
- xmalloc and handle failures gracefully, so the application doesn't
- abort if the history file or history list is too big
-
- 3/27
- ----
-arrayfunc.c
- - changed array_value_internal to take an additional `int *'
- parameter, in which is returned the type of array indexing
- performed (array[@] vs. array or array[index])
- - changed array_value and get_array_value to take a corresponding
- extra parameter and pass it to array_value_internal
- - changed array_value_internal to no longer return newly-allocated
- memory or quote CTLESC and CTLNUL in the returned string if
- `simple' array indexing (subscript not `@' or `*') is being
- performed. This makes it more like a variable lookup
-
-arrayfunc.h
- - changed prototypes for array_value and get_array_value
-
-expr.c
- - added new parameter to call to get_array_value in expr_streval
- - don't need to free memory returned by get_array_value any more
-
-subst.c
- - quote_escapes now works with multibyte characters
- - dequote_string now works with multibyte characters
- - dequote_escapes is now needed, so it's compiled in, and it
- now works with multibyte characters
- - remove_quoted_escapes now just calls dequote_escapes and copies the
- result over the argument string
- - remove_quoted_nulls now returns its char * argument, parallels
- remove_quoted_escapes
- - parameter_brace_expand_word now passes the new argument to
- array_value and quotes CTLESC and CTLNUL in the result if it's a
- `simple' array expansion by calling quote_escapes
- - get_var_and_type now returns VT_ARRAYMEMBER for references like
- ${array} where `array' is an array variable (just like ${array[0]}).
- Documented (in comment) that a VT_VARIABLE return value means that
- quote_escapes has been called at some point
- - changed callers of get_var_and_type to no longer free value if
- VT_ARRAYMEMBER is returned as type
- - changed parameter_brace_substring and parameter_brace_patsub to
- call dequote_escapes on the value from get_var_and_type if the
- type is VT_VARIABLE, since the substring and pattern substitution
- code doesn't understand CTLESC quoting
- - parameter_brace_substring no longer needs to call quoted_substring
- for the VT_ARRAYMEMBER case
- - changed parameter_brace_patsub to call quote_escapes on the result
- of pat_subst for the VT_VARIABLE and VT_ARRAYMEMBER cases, and to
- quote the returned string in the VT_ARRAYVAR and VT_POSPARAMS cases
- if the `MATCH_QUOTED' flag isn't set (if it is, the pattern
- substitution functions perform any necessary quoting)
- - quoted_substring is no longer used; it's now #ifdef INCLUDE_UNUSED
-
-lib/malloc/mstats.h
- - new member in _malstats: u_bits32_t bytesreq, the total number of
- bytes requested by the caller via calls to malloc() and realloc()
-
-lib/malloc/stats.c
- - print bytesreq member in _print_malloc_stats
- - don't print statistics for buckets for which nmal == 0 (no mallocs)
-
-lib/malloc/malloc.c
- - modified internal_malloc, internal_realloc to keep running total of
- number of bytes requested by calling application
-
-shell.c
- - sh_exit is now compiled in; exit_shell calls sh_exit
-
-error.c
- - changed fatal_error, report_error, parser_error to call sh_exit
-
- 3/28
- ----
-subst.[ch]
- - changed Q_NOQUOTE to Q_PATQUOTE; it makes the intent more clear
-
-subst.c
- - moved code from parameter_brace_expand into a new function that
- dispatches for pattern substitution: parameter_brace_remove_pattern
- - changed structure of parameter_brace_remove_pattern to be like
- parameter_brace_patsub and its ilk: call get_var_and_type to
- isolate the variable name, move the pattern isolation code out of
- the various *_remove_pattern functions into
- parameter_brace_remove_pattern and pass the results to the various
- functions, use a switch on the return value from get_var_and_type
- to decide which function to call, regularized the arguments to the
- separate pattern removal functions
- - parameter_brace_remove_pattern now properly quotes escape chars in
- the returned value
- - changed get_var_and_type to call dequote_escapes on the `value'
- parameter for case VT_VARIABLE and return the result in *valp,
- so the calling functions don't have to do it themselves; changed
- callers appropriately
- - fixed getpattern() where it broke posix compliance: if you enclose
- a pattern removal spec in double quotes, the outer double quotes
- have no effect on the pattern (POSIX.1-200x 2.6.2). This uncovered
- a bug in the test suite (!)
-
-pathexp.c
- - fixed a problem with quote_string_for_globbing where it would change
- consecutive CTLESC chars all to \ instead of changing every other
- quoted char
-
- 3/31
- ----
-lib/malloc/{malloc,stats}.c
- - moved declaration of _mstats to malloc.c so stats.o doesn't get
- linked into the shell if the stats functions aren't called
-
- 4/2
- ---
-lib/glob/smatch.c
- - introduce `XCHAR' define, which is the type of arguments passed to
- strcoll/strcmp/strlen and their wide-character equivalents, added
- appropriate casts
- - static arrays in single-byte version of rangecmp() are `char', not
- `unsigned char', so compilers don't complain about calls to strcoll
-
-lib/glob/sm_loop.c
- - casts for `XCHAR' and `XCHAR *' arguments to libc functions
- - use prototype declaration for BRACKMATCH if `PROTOTYPES' is defined
- to avoid problems with type promotion (unsigned char -> int)
-
-lib/glob/collsyms.h
- - `name' member of struct _COLLSYM is now of type `XCHAR *', since
- some compilers don't like `unsigned char *' initializers from
- constant strings
-
-[bash-2.05b-alpha1 released]
-
- 4/3
- ---
-builtins/{evalstring.c,common.h}
- - new flag for parse_and_execute, SEVAL_NOFREE, means to not free
- the argument string when finished
-
-lib/readline/text.c
- - fixed a trivial typo in _rl_insert_char when reading multibyte
- char sequences
- - replace calls to ding() with rl_ding()
-
-include/chartypes.h
- - remove SIGN_EXTEND_CHAR and TOASCII macros; they're unused
-
-make_cmd.c
- - include dispose_cmd.h for extern function declarations
-
-lib/glob/glob.c
- - include `shmbutil.h' and `xmalloc.h' for extern function declarations
-
-lib/glob/smatch.c
- - include `xmalloc.h' for extern function declarations
-
-shell.c
- - fix maybe_make_restricted to use its argument instead of global
- `shell_name'
-
-version.c
- - update copyright message to include this year
-
-lib/readline/display.c
- - fixes from Jiro SEKIBA <jir@yamato.ibm.com> to fix autowrapping
- when using multibyte characters
-
-lib/glob/sm_loop.c
- - fixed a problem in BRACKMATCH where not enough memory was allocated
- to hold a multibyte character when parsing POSIX.2 char class names
-
-support/config.{guess,sub}
- - updated via patch from Paul Eggert with latest GNU additions
-
-variables.c
- - var_lookup should use its `vcontext' argument instead of
- unconditionally using `shell_variables'
-
- 4/4
- ---
-builtins/bind.def,doc/{bash.1,bashref.texi}
- - changed the usage summary and help text to make it clear that any
- readline command that may appear in ~/.inputrc may be supplied as
- one of the non-option arguments to `bind'
-
-builtins/mkbuiltins.c
- - added support for `-H' option, which means to write long documentation
- for each builtin to a separate file in the `helpfiles' directory
-
-builtins/Makefile.in
- - new target `helpdoc', just creates long doc files in helpfiles
- directory
-
-lib/sh/zcatfd.c
- - new file, with zcatfd(int fd, int ofd, char *fn); dumps data from
- FD to OFD
-
-Makefile.in,lib/sh/Makefile.in
- - added zcatfd.c, zcatfd.o member of libsh.a
-
-builtins/evalstring.c
- - changed cat_file to call zcatfd(fd, 1, fn)
-
-builtins/{shopt,colon}.def
- - removed the $DOCNAME directive for `shopt', `true', and `false';
- just use the names
- - changed $DOCNAME for `:' to just be `colon' instead of
- `colon_builtin'
-
-builtins/reserved.def
- - added help entries for ((, [[, `for (('
-
-builtins/let.def
- - add id++, id--, ++id, --id, ** to help text
-
- 4/8
- ---
-builtins/bashgetopt.[ch]
- - changed to allow options beginning with `+', enabled by a leading
- `+' in the option string
- - new variable, list_opttype, set to `-' or `+'
-
-builtins/{common.c,{builtin,eval,exit,fg_bg,let,printf,pushd,return,source,wait}.def
- - changes to allow a `--' option for every builtin that accepts
- operands but not options, as per posix.1-2001
-
-builtins/{declare,setattr}.def
- - use internal_getopt for parsing options, now that it supports `+'
-
-builtins/set.def
- - use internal_getopt for initial option parse, now that it supports
- a leading `+'
-
-
-{configure,Makefile}.in, builtins/{Makefile.in,help.def,mkbuiltins.c}
- - support for a new configure option, ``--enable-separate-helpfiles'',
- moves the `long' help text to separate help files, installed by
- default into ${datadir}/bash, one file per builtin. Off by
- default -- it saves 47K, but it's only 47K, and it's in the text
- segment
-
-flags.c
- - build internal_getopt() option string argument from flags array at
- runtime in shell.c
-
-shell.c
- - new variable to control writing malloc stats at exit:
- malloc_trace_at_exit, 0 by default
-
-lib/malloc/malloc.c
- - heavily updated:
- o partial page allocated on first call to malloc to make
- subsequent sbrks page-aligned no longer wasted
- o begin and end range guards are now the same value: the chunk
- requested
- o coalescing code was changed to attempt to coalesce first two
- adjacent blocks on the free list; enabled by default
- o blocks of size 32 are now candidates for larger block
- splitting, since 32 is the most popular size
- o blocks of size 32 are now candidates for smaller block
- coalescing
- o the IN_BUCKET check was changed to just make sure that the
- size isn't too big for the bucket, since the `busy block'
- checking code may increase the bucket by one or more,
- meaning that the old check would fail and cause a panic when
- a chunk allocated in such a way was freed
- o bin sizes are now precomputed and looked up in an array
- rather than being computed at runtime
- o moved the _mstats declaration here to avoid the stats code
- being linked in even when no stats functions were called
- (only matters if MALLOC_DEBUG is defined)
- o malloc now keeps track of the address of the top of the heap
- and will return large chunks to the system with calls to
- sbrk with a negative argument when freeing the top chunk.
- Two thresholds: LESSCORE_FRC means to unconditionally return
- memory to the system; LESSCORE_MIN means to return memory if
- there's at least one block already on the free list
-
-lib/malloc/mstats.h
- - stats struct now keeps track of number of block coalesces by bin,
- and the number of times memory was returned to the system by bin
-
-lib/malloc/stats.c
- - trace_malloc_stats now takes a second argument: the name of the file
- to write to. The first `%p' in the template file name is replaced
- by the pid
-
- 4/9
- ---
-lib/malloc/imalloc.h
- - added some macros derived from dlmalloc and glibc malloc to inline
- memcpy and memset if the requested size is <= 32 bytes
-
-lib/malloc/malloc.c
- - use MALLOC_MEMSET instead of memset in internal_{malloc,free}
-
-include/ocache.h
- - use OC_MEMSET (variant of MALLOC_MEMSET) in ocache_free
-
-configure.in, config.h.in
- - check for getservent(), define HAVE_GETSERVENT if found
-
-bashline.c
- - punt immediately from bash_servicename_completion_function if
- HAVE_GETSERVENT is not defined (cygwin seems to not define it)
- - include "input.h" for extern save_token_state() and
- restore_token_state() declarations
- - change bash_execute_unix_command to call parse_and_execute with
- SEVAL_NOHIST flag so the command doesn't get saved on the history
- list
- - change bash_execute_unix_command to save and restore the current
- command line count and the token state (last_read_token, etc.).
- Everything else is saved by either parse_and_execute directly or
- the call it makes to push_stream(). The shell_input_line stuff
- doesn't need to be saved and restored; it's not computed until
- readline() returns
-
- 4/10
- ----
-lib/glob/glob.[ch]
- - glob_filename and glob_vector now take an additional `flags' arg
- - define GX_MARKDIRS as possible flag value for glob_filename and
- glob_vector
-
-lib/sh/snprintf.c
- - fixed some bugs with handling of `g' and `G' formats
- - make sure numtoa returns the fractional part correctly when passed 0
- - implemented thousands grouping for `'' flag character
-
-lib/sh/rename.c
- - a few changes to make it more bulletproof
-
- 4/11
- ----
-lib/glob/glob.c
- - added the couple of dozen lines of code to glob_dir_to_array to
- finish implementing GX_MARKDIRS
-
-builtins/set.def
- - changed unset builtin so that it no longer considers unsetting an
- unset variable or function to be an error
-
-lib/readline/display.c
- - fix to rl_redisplay for a problem which caused display to be messed
- up when the last line of a multi-line prompt (possibly containing
- invisible characters) was longer than the screen width
-
- 4/15
- ----
-aclocal.m4
- - use AC_DEFINE_UNQUOTED in BASH_SYS_DEFAULT_MAIL_DIR instead of
- enumerating all of the possible values and using AC_DEFINE
-
- 4/16
- ----
-Makefile.in, {builtins,support}/Makefile.in
- - new variables, CFLAGS_FOR_BUILD and CPPFLAGS_FOR_BUILD, substituted
- by `configure'
- - changed CCFLAGS_FOR_BUILD to BASE_CCFLAGS, removing $(CPPFLAGS);
- CCFLAGS and CCFLAGS_FOR_BUILD now include $(BASE_CCFLAGS) with
- (possibly) different values for CPPFLAGS and CFLAGS
- - GCC_LINT_CFLAGS now includes $(BASE_CCFLAGS) and $(CPPFLAGS)
- instead of CCFLAGS_FOR_BUILD
- - new variable, LDFLAGS_FOR_BUILD, right now equivalent to LDFLAGS
- - remove $(CPPFLAGS) from recipes for buildversion, mksignames, and
- mksyntax
-
-configure.in
- - compute and substitute CFLAGS_FOR_BUILD, CPPFLAGS_FOR_BUILD, and
- LDFLAGS_FOR_BUILD
- - changed qnx to use LOCAL_LDFLAGS and LOCAL_LIBS instead of putting
- everything in LOCAL_LDFLAGS
-
-builtins/Makefile.in
- - remove $(PROFILE_FLAGS) from recipe for building `mkbuiltins'
- - use LDFLAGS_FOR_BUILD instead of LDFLAGS in recipe for building
- `mkbuiltins'
-
-Makefile.in
- - use $(CC_FOR_BUILD) and $(CCFLAGS_FOR_BUILD) to build auxiliary
- test programs (printenv, recho, zecho)
-
-support/Makefile.in
- - use CC_FOR_BUILD and CCFLAGS_FOR_BUILD in recipe for building
- `man2html'
-
-lib/tilde/Makefile.in
- - substitute PROFILE_FLAGS, use PROFILE_FLAGS in $(CCFLAGS)
-
- 4/25
- ----
-Makefile.in, configure.in
- - moved RELSTATUS to configure.in; configure substitutes it into
- the generated Makefile
-
-lib/sh/snprintf.c
- - fix wchars() to deal with systems where MB_CUR_MAX is not a
- constant expression
-
- 5/2
- ---
-lib/sh/shquote.c
- - add `,' to list of chars that are backslash-quoted. It doesn't
- hurt normal usage and prevents filenames with commas from being
- inappropriately split by brace expansion after using
- complete-into-braces
-
- 5/6
- ---
-lib/sh/xstrchr.c
- - we only need the check of MB_CUR_MAX and the slow code for a
- few encodings, and even then only for a subset of the charset
-
-arrayfunc.c
- - some speedups for skipsubscript and multibyte chars from Bruno Haible
-
-locale.c
- - changed set_lang to call setlocale(LC_ALL, ...) if LC_ALL doesn't
- already have a value, but doesn't change any shell variables
-
-include/shmbutil.h
- - major speedups from Bruno Haible, mostly concerned with reducing
- the number of strlen(3) calls
-
-subst.c
- - change callers of macros in shmbutil.h to add extra argument as
- necessary
- - skip_single_quoted and skip_double_quoted take another argument:
- the length of the string; mostly useful when using multibyte chars
- - many speedups from precomputing string lengths at function start
- - fixed a small bug in de_backslash in the midst of rewriting for
- better efficiency
-
-{braces,make_cmd,pathexp}.c
- - change callers of macros in shmbutil.h to add extra argument as
- necessary
-
-pathexp.c
- - fix a one-too-far problem with multibyte chars in
- unquoted_glob_pattern_p
-
-braces.c
- - brace_gobbler takes a new argument, the length of the passed string
- - expand_amble takes a new argument, the length of the passed string
-
- 5/7
- ---
-subst.c
- - modified remove_quoted_nulls to eliminate the memory allocation and
- do the copy in place using the same strategy as de_backslash
-
-lib/readline/{rldefs.h,complete.c}
- - new define RL_QF_OTHER_QUOTE, so _rl_find_completion_word can note
- that it found a quoting character other than \'" that appears in
- rl_completer_quote_characters
-
- 5/9
- ---
-jobs.c
- - save and restore old value of jobs_list_frozen when calling trap
- handlers from set_job_status_and_cleanup to avoid seg faults when
- running recursive trap handlers
-
- 5/10
- ----
-builtins/common.h
- - new #defines to use for value of changed_dollar_vars (provides
- information about the caller who wants to blow away the old dollar
- variables)
-
-builtins/common.c
- - changed set_dollar_vars_changed to set changed_dollar_vars to one
- of the ARGS_* values depending on the caller and environment
-
-builtins/source.def
- - source restores the positional parameters unless the `set' builtin
- was called to specify a new set while not executing a shell function
-
- 5/13
- ----
-POSIX
- - new file, was in CWRU/POSIX.NOTES
-
-doc/{Makefile.in,Makefile}
- - changed `posix' rule to modify ../POSIX
-
-doc/mkposix
- - write to `POSIX' by default
-
-lib/sh/strtrans.c
- - when ansicstr is parsing a format string for `echo -e' (or the
- equivalent xpg_echo option is enabled), obey the POSIX-2001/SUSv3
- standard and accept 0-3 octal digits after a leading `0'
-
-doc/{bash.1,bashref.texi}
- - updated `echo' description to note that up to three octal digits
- are now accepted following `\0'
-
- 5/16
- ----
-doc/Makefile.in
- - remove the generated documentation on `make distclean' if the
- build directory and source directory are not the same
-
-Makefile.in
- - descend into `support' subdirectory on a `make clean' and
- `make distclean'
- - remove parser-built, y.tab[ch] on a `make distclean' if the build
- directory and source directory are not the same
-
-support/Makefile.in
- - support various `clean' targets and remove man2html.o and man2html
-
-{configure,Makefile}.in
- - move values for DEBUG and MALLOC_DEBUG into configure.in; on by
- default for development versions; off by default for releases
- (off for profiling, too)
-
- 5/21
- ----
-parse.y
- - modified the grammar to allow a simple_list followed by yacc_EOF
- to terminate a command. This fixes problems with things like
- a backslash-newline at the end of an `eval'd string
- - change handle_eof_input_unit() to reset the token state before
- calling prompt_again(), in case the prompt to be evaluated contains
- a command substitution
-
- 5/23
- ----
-lib/readline/vi_mode.c
- - fix `r' command (rl_vi_change_char) when HANDLE_MULTIBYTE is defined
- but MB_CUR_MAX == 1
-
- 5/24
- ----
-lib/malloc/watch.c
- - don't try to print `file' argument to _watch_warn if it's null
-
-lib/malloc/malloc.c
- - changed guard checking code in internal_{malloc,free,realloc} to
- access memory as (char *) and copy into a union instead of
- casting and dereferencing a pointer to u_bits32_t, since that
- results in unaligned accesses which will cause Sparcs to upchuck
-
- 5/30
- ----
-[bash-2.05b-beta1 released]
-
-lib/readline/text.c
- - fixed a problem with rl_transpose_chars on systems supporting
- multibyte characters with a locale that doesn't have any multibyte
- chars
-
- 6/4
- ---
-expr.c
- - fix a/=0 and a%=0 to throw evaluation errors rather than core dumps
-
-lib/readline/display.c
- - fix core dump when line wrapping a multibyte character (line
- accidentally dropped from the original patch)
-
-lib/readline/mbutil.c
- - fix reversed return value from _rl_is_mbchar_matched; fixes problem
- with backward-char-search
-
- 6/10
- ----
-lib/sh/getenv.c
- - fix getenv to not free value returned by find_tempenv_variable
- - add setenv, putenv, unsetenv for completeness
-
- 6/12
- ----
-shell.c
- - change init_noninteractive to init expand_aliases to the value of
- posixly_correct
- - don't initialize expand_aliases to posixly_correct anywhere else.
- This allows the -O expand_aliases invocation option to work correctly
-
-general.c
- - fix move_to_high_fd to not try the dup2 unless the fd loop results
- in an fd > 3; just return the passed file descriptor otherwise
- - use HIGH_FD_MAX, defined in general.h, instead of hard-coded 256
- as highest file descriptor to try
-
-subst.c
- - in process_substitute, call move_to_high_fd with `maxfd' parameter
- of -1 instead of 64, so move_to_high_fd will use its maximum
-
- 6/21
- ----
-lib/malloc/malloc.c
- - don't bother calling MALLOC_MEMSET if the requested size is 0
-
-builtins/setattr.def
- - note in short doc that export and readonly can take assignment
- statements as arguments
-
-error.c
- - new function, error_prolog(), to capture common error message
- prefix code (except for parser errors)
-
- 6/25
- ----
-aclocal.m4
- - add tests for standard-conforming declarations for putenv and
- unsetenv in system header files
-
-{configure,config.h}.in
- - call BASH_FUNC_STD_PUTENV and BASH_FUNC_STD_UNSETENV, define
- HAVE_STD_GETENV and HAVE_STD_UNSETENV, respectively, if they
- succeed
-
-lib/sh/getenv.c
- - change putenv and unsetenv to take differing prototypes in
- stdlib.h into account
-
- 6/27
- ----
-[bash-2.05b-beta2 released]
-
- 6/28
- ----
-builtins/common.c
- - fix get_job_spec so that %N works when N is the size of the jobs
- list (%8 means job 8, but the 7th member of the jobs array, so
- it's OK if N == job_slots because the function returns N-1)
-
- 7/1
- ---
-shell.c
- - turn off line editing if $EMACS is set to `t'
-
- 7/10
- ----
-builtins/set.def
- - remove mention of `-i' from long help doc, since it has no effect
-
- 7/17
- ----
-[bash-2.05b released]
-
- 7/18
- ----
-
-lib/malloc/malloc.c
- - make sure that the `free_return' label has a non-empty statement
- to branch to
-
- 7/19
- ----
-locale.c
- - only call setlocale() from set_lang() if HAVE_SETLOCALE is defined;
- otherwise just return 0
-
-lib/readline/mbutil.c
- - only try to memset `ps' in _rl_get_char_len if it's non-NULL. Ditto
- for _rl_adjust_point
-
- 7/23
- ----
-execute_cmd.c
- - fix for executing_line_number() when compiling without conditional
- commands, dparen arithmetic or the arithmetic for command
-
-
- 7/24
- ----
-support/Makefile.in
- - fix maintainer-clean, distclean, mostlyclean targets
-
-builtins/common.c
- - fix bug in sh_nojobs where it doesn't pass the right number of args
- to builtin_error
-
-bashline.c
- - when using command completion and trying to avoid appending a slash
- if there's a directory with the same name in the current directory,
- use absolute_pathname() instead of just checking whether the first
- char of the match is a slash to catch things like ./ and ../
-
-examples/complete/bashcc-1.0.1.tar.gz
- - a package of completions for Clear Case, from Richard S. Smith
- (http://www.rssnet.org/bashcc.html)
-
-input.c
- - fix check_bash_input to call sync_buffered_stream if the passed fd
- is 0 and the shell is currently reading input from fd 0 -- all it
- should cost is maybe an additional read system call, and it fixes
- the bug where an input redirection to a builtin inside a script
- which is being read from stdin causes the already-read-and-buffered
- part of the script to be thrown away, e.g.:
-
- bash < x1
-
- where x1 is
-
- hostname
- read Input < t.in
- echo $Input
- echo xxx
-
-execute_cmd.c
- - in initialize_subshell(), call unset_bash_input (0) to not mess with
- fd 0 if that's where bash thinks it's reading input from. Fixes
- bug reported by jg@cs.tu-berlin.de on 17 July 2002. Should be a way
- to check whether or not the current fd 0 at the time of the call has
- not been redirected, like in the bug report. Also might eventually
- want to throw in a sync_buffered_stream if bash is reading input
- from fd 0 in a non-interactive shell into a buffered stream, so the
- stream is sync'd -- might be necessary for some uses
-
- 7/25
- ----
-lib/readline/signals.c
- - make sure rl_catch_sigwinch is declared even if SIGWINCH is not
- defined, so the readline state saving and restoring functions in
- readline.c are always the same size even if SIGWINCH is not defined,
- and undefined references don't occur when SIGWINCH is not defined
-
- 7/30
- ----
-bashline.c
- - augment patch from 7/24 to not disable rl_filename_completion_desired
- if the first char of the match is `~'
-
-lib/readline/bind.c
- - when creating `shadow' keymaps `bound' to ANYOTHERKEY, don't bind
- a key whose type is ISFUNC but whose function is the `fake'
- rl_do_lowercase_version (fixes debian bash bug #154123)
-
-lib/readline/readline.c
- - don't call _rl_vi_set_last from _rl_dispatch_subseq if
- key == ANYOTHERKEY (when truncated to `sizeof(char)', it will be 0,
- which strchr will find in `vi_textmod')
-
- 7/31
- ----
-lib/readline/input.c
- - fix rl_gather_tyi to only slurp up one line of available input, even
- if more than one line is available (fixes debian bash bug #144585)
-
- 8/3
- ---
-bashline.c
- - better fix for command completion problem -- test for directory
- explicitly with test_for_directory before turning off
- rl_filename_completion_desired, since that's the case we're trying
- to protect against
-
- 8/5
- ---
-include/shmbutil.h
- - fix ADVANCE_CHAR macro to advance the string pointer if mbrlen
- returns 0, indicating that the null wide character (wide string
- terminator) was found (debian bash bug #155436)
-
-lib/readline/mbutil.c
- - fix _rl_adjust_point to increment the string pointer if mbrlen
- returns 0
-
-support/shobj-conf
- - fix for the `-install_name' value in SHLIB_XLDFLAGS assignment for
- Darwin from the fink folks
-
- 8/6
- ---
-builtins/exit.def
- - broke code that runs ~/.bash_logout out into a separate function:
- bash_logout()
-
-builtins/common.h
- - extern declaration for bash_logout()
-
-eval.c
- - call bash_logout() from alrm_catcher(), so timed-out login shells
- run ~/.bash_logout before processing the exit trap
-
-lib/sh/strtrans.c
- - implemented $'\x{hexdigits}' expansion from ksh93
-
-configure.in
- - define RECYCLES_PIDS in LOCAL_CFLAGS for cygwin; don't bother to
- link with -luser32
-
-examples/loadables/strftime.c
- - new loadable builtin, interface to strftime(3)
-
- 8/7
- ---
-parse.y
- - parse_arith_cmd now takes a second argument, a flag saying whether
- or not to add double quotes to a parsed arithmetic command; changed
- callers
- - changed parse_dparen so it tells parse_arith_cmd to not add the
- double quotes and therefore doesn't need to remove them
- - change parse_dparen to add W_NOGLOB|W_NOSPLIT|W_QUOTED flags to word
- created when parsing (( ... )) arithmetic command, since the double
- quotes are no longer added
-
-make_cmd.c
- - in make_arith_for_expr, set the flags on the created word to
- W_NOGLOB|W_NOSPLIT|W_QUOTED
-
-execute_cmd.c
- - change execute_arith_command to expand the expression with
- expand_words_no_vars, like the arithmetic for command code does
- - fix execute_arith_command to handle the case where the expanded
- expression results in a NULL word without crashing
-
-tests/{arith-for,cprint}.tests
- - change expected output to account for no longer adding quotes to
- ((...)) commands
-
- 8/8
- ---
-print_cmd.c
- - take out the space after printing the `((' and before printing the
- `))' in print_arith_command, print_arith_for_command, and
- xtrace_print_arith_cmd
-
-tests/{arith-for,cprint}.tests
- - change expected output to account for no longer adding leading and
- trailing spaces when printing ((...)) and arithmetic for commands
-
- 8/17
- ----
-subst.c
- - fix issep() define to handle case where separators[0] == '\0', in
- which case it always returns false
-
-lib/readline/histexpand.c
- - fix off-by-one error in history_expand_internal when using the `g'
- modifier that causes it to skip every other match when matching a
- single character (reported by gjyun90@resl.auto.inha.ac.kr)
-
-doc/{bash.1,bashref.texi}
- - make sure that the name=word form of argument to declare/typeset,
- export, and readonly is documented in the description
-
- 8/30
- ----
-lib/readline/histexpand.c
- - make history_expand_internal understand double quotes, because
- single quotes are not special inside double quotes, according to
- our shell-like quoting conventions. We don't want unmatched
- single quotes inside double-quoted strings inhibiting history
- expansion
- - make `a' modifier equivalent to `g' modifier for compatibility with
- the BSD csh
- - add a `G' modifier that performs a given substitution once per word
- (tokenized as the shell would do it) like the BSD csh `g' modifier
-
- 8/31
- ----
-braces.c
- - when compiling for the shell, treat ${...} like \{...} instead of
- trying to peek backward when we see a `{'. This makes it easier
- to handle things like \${, which should be brace expanded because
- the $ is quoted
-
- 9/7
- ---
-aclocal.m4
- - redirect stdin from /dev/null in BASH_CHECK_DEV_FD before testing
- the readability of /dev/fd/0, so we're dealing with a known quantity
-
- 9/11
- ----
-[prayers for the victims of 9/11/01]
-
-shell.c
- - fix maybe_make_restricted to handle a restricted login shell with a
- base pathname of `-rbash' and skip over any leading `-'
-
- 9/13
- ----
-builtins/evalstring.c
- - in parse_and_execute, make sure we don't try to run unwind-protects
- back to `pe_dispose' after a longjmp back to top_level if the
- pe_dispose frame hasn't been initialized
-
-lib/readline/display.c
- - fix problem with prompt overwriting previous output when the output
- doesn't contain a newline in a multi-byte locale. This also should
- fix the problem of bash slowing down drastically on long lines when
- using a multi-byte locale, because it no longer tries to rewrite the
- entire line each time. Patch from Jiro SEKIBA <jir@yamato.ibm.com>
-
-parse.y
- - move the typedef for alias_t that is compiled in if ALIAS is not
- defined up before the prototype for push_string, since that takes
- an alias_t * parameter
-
-lib/readline/terminal.c
- - bind the termcap description's left and right arrow keys to
- rl_backward_char and rl_forward_char, respectively, instead of
- rl_forward and rl_backward (which are just there for backwards
- compatibility)
-
-aclocal.m4
- - when testing readability of /dev/stdin, redirect stdin from /dev/null
- to make sure it's a readable file
-
- 9/17
- ----
-config-bot.h
- - don't test __STDC__ when deciding whether or not to use stdarg.h;
- just use it if it's present
-
-tests/read2.sub
- - redirect from /dev/tty when using `read -t'
-
- 9/20
- ----
-builtins/history.def
- - when reading `new' entries from the history file with `history -n',
- fix increment of history_lines_this_session by taking any change
- in history_base into account
-
-lib/sh/pathphys.c
- - changes to sh_physpath to deal with pathnames that end up being
- longer than PATH_MAX without dumping core
-
-lib/readline/doc/{history.3,hsuser.texinfo},doc/ bash.1
- - documented new `a' and `G' history modifiers
-
- 9/25
- ----
-lib/readline/misc.c
- - when traversing the history list with arrow keys in vi insertion
- mode, put the cursor at the end of the line (like in emacs mode)
-
-mksyntax.c
- - don't try to use \a and \v unless __STDC__ is defined; use the
- ascii integer equivalents otherwise
- - include "config.h" in the generated syntax.c file for a possible
- definition of `const'
-
-doc/{bash.1,bashref.texi}
- - document the meaning of a null directory in $PATH
-
- 9/26
- ----
-parse.y
- - fix set_line_mbstate to handle case where mbrlen() returns 0,
- indicating the null wide character
- - fix set_line_mbstate so we don't directly compare a char variable
- to EOF, since char can (and is) unsigned on some machines
-
-bashline.c
- - change bash_execute_unix_command to save a little bit more state:
- last_shell_builtin, this_shell_builtin, last_command_exit_value
-
- 9/27
- ----
-execute_cmd.c
- - tentative change to execute_simple_command to avoid freeing freed
- memory in the case where bash forks early but still ends up calling
- execute_disk_command, without passing newly-allocated memory to
- make_child. This may fix the core dumps with the linux-from-scratch
- folks
-
- 9/28
- ----
-Makefile.in,{builtins,lib/sh}/Makefile.in
- - fix up dependencies, mostly on ${BUILD_DIR}/version.h, so that
- parallel makes work with GNU and BSD makes
-
-shell.h
- - new struct to save partial parsing state when doing things like
- bash_execute_unix_command and other operations that execute
- commands while a line is being entered and parsed
-
-parse.y
- - new functions, save_parser_state() and restore_parser_state(), to
- save and restore partial parsing state
-
-bashline.c
- - change bash_execute_unix_command to call {save,restore}_parser_state
-
-builtins/jobs.def
- - change execute_list_with_replacements to eliminate a run_unwind_frame
- in favor of calling the cleanup explicitly and discarding the frame
-
-execute_cmd.c
- - change execute_for_command to avoid a run_unwind_frame in the case
- where the loop variable is readonly or otherwise not assignable
- - change execute_select_command and execute_simple_command to use
- discard_unwind_frame by running the cleanup code explicitly, instead
- of using run_unwind_frame
- - make sure execute_select_command decreases loop_level even on error
-
- 9/30
- ----
-doc/{bash.1,bashref.texi}
- - fixed description of `unset' now that unsetting a previously-unset
- variable is no longer an error
-
- 10/3
- ----
-{configure,config.h}.in
- - augment check for strtold with additional check to detect the
- horribly broken hp/ux 11.x implementation that returns `long_double';
- defines STRTOLD_BROKEN if so
-
-builtins/printf.def
- - define floatmax_t as `double' if STRTOLD_BROKEN is defined
-
- 10/5
- ----
-lib/readline/keymaps.c
- - don't automatically bind uppercase keys to rl_do_lowercase_version
- in rl_make_bare_keymap
-
-lib/readline/readline.c
- - explicitly check for ANYOTHERKEY binding to rl_do_lowercase_version
- and dispatch to lowercase of key when a prefix is not matched
-
- 10/12
- -----
-bashline.c
- - set COMP_WORDBREAKS in enable_hostname_completion to the value
- of rl_completer_word_break_characters
-
-variables.c
- - new special variable COMP_WORDBREAKS, controls the value of
- rl_completer_word_break_characters
-
-variables.h
- - new extern declaration for sv_comp_wordbreaks()
-
-subst.c
- - change split_at_delims to behave more like shell word splitting if
- the passed value for the delimiters is NULL, indicating that the
- function is to use $IFS to split
-
-{execute_cmd,jobs,test,findcmd,input,make_cmd,redir,shell}.c
-builtins/mkbuiltins.c,builtins/{fc,history,source,umask}.def
-lib/sh/netconn.c
-lib/termcap/termcap.c
-lib/readline/histfile.c
- - make sure all inclusions of <sys/file.h> are protected by
- HAVE_SYS_FILE_H
-
-bashline.c
- - don't turn off rl_filename_completion_desired in
- attempt_shell_completion if the partial pathname contains a slash.
- This still doesn't solve the problem of partial pathname completion
- starting with a directory in the current directory without a
- leading `./'. There's no way to tell the difference between that
- and a file found in $PATH (which may contain `.') at the point that
- attempt_shell_completion acts
-
- 10/18
- -----
-locale.c
- - don't set lc_all to the default locale when LC_ALL is being unset
- - new function, reset_locale_vars(), called to recompute the correct
- locale variable values when LC_ALL is unset
- - changed set_lang to not set LC_ALL, which it never should have been
- doing in the first place, and to maintain a local variable `lang'
- corresponding to $LANG
- - change get_locale_var to use the precedence posix.2 specifies:
- LC_ALL overrides individual variables; LANG, if set, is the default
- - change set_locale_var to call get_locale_var to get the appropriate
- value for the variable being set or unset
- - call get_locale_var instead of using passed value in set_locale_var
- to get the defaulting and precedence right
-
-lib/readline/nls.c
- - new function, _rl_get_locale_var(), which does the same thing as
- locale.c:get_locale_var(), with the right precedence and defaulting,
- using sh_get_env_value to get the right bash variable values
- - if HAVE_SETLOCALE is defined, _rl_init_eightbit first calls
- _rl_get_locale_var to get the right value for LC_CTYPE, and uses
- that in the call to setlocale. If _rl_get_locale_var returns NULL,
- call setlocale() to get the current international environment, and,
- finally, if that returns null, call setlocale with a second argument
- of "" to force the implementation's `native' environment
-
-pcomplete.c
- - change gen_wordlist_completions to dequote the text before comparing
- it against the expanded word list
- - changed gen_matches_from_itemlist to do the same thing
-
-bashline.c
- - new global function, bash_dequote_word, calls bash_dequote_filename
- on the text passed. Used by the programmable completion code
-
-lib/readline/histfile.c
- - make sure that whenever read_history_range returns a non-zero value
- that it sets errno to some useful value
-
- 10/19
- -----
-variables.c
- - COMP_WORDBREAKS is now a dynamic variable, mirroring value of
- rl_completer_word_break_characters. Makes sure that the variable
- always points to dynamic memory if it's not null or the readline
- default
-
-bashline.c
- - change enable_hostname_completion to manage a dynamic value of
- rl_completer_word_break_characters, since assignments to
- COMP_WORDBREAKS can change its value unpredictably
-
-lib/readline/{complete.c,readline.h}
- - rl_completer_word_break_characters no longer has `const' attribute
-
-bashline.c
- - clean up necessary places due to rl_completer_word_break_characters
- no longer being `const'
-
-doc/{bash.1,bashref.texi}
- - document new COMP_WORDBREAKS variable
-
- 10/21
- -----
-print_cmd.c
- - fix indirection_level_string to handle the case where the decoded
- $PS4 is null without seg faulting
-
- 10/22
- -----
-builtins/shift.def
- - make sure that there is actually an argument when reporting a shift
- count that exceeds the number of positional paramters and
- shift_verbose is enabled
-
-lib/readline/rltty.c
- - change SET_SPECIAL to call a new function, set_special_char, since
- it contains a block. It's called infrequently, so the performance
- impact of making it a function should be negligible, and it helps
- debugging
-
- 10/29
- -----
-bashline.c
- - make sure the editor in VI_EDIT_COMMAND and EMACS_EDIT_COMMAND is
- quoted; it might contain spaces (e.g., `emacs -nw')
-
-aclocal.m4
- - cache ac_cv_rl_version in RL_LIB_READLINE_VERSION macro
-
-configure.in
- - change logic that sets RL_INCLUDEDIR so that it doesn't try to set
- a bogus include path if the argument to --with-installed-readline
- is `yes' -- helps with cross-compiling
-
-lib/readline/histexpand.c
- - fix history_tokenize_word so that it handles <( and >( better
-
- 10/30
- -----
-redir.c
- - fix write_here_string so it handles the case where `herestr' expands
- to NULL without seg faulting
-
- 10/31
- -----
-mailcheck.c
- - reverse logic flip from bash-2.05 that handled systems that don't
- change the atime when the mailbox is accessed; make sure the file
- is bigger before we report new mail. This is the case in the vast
- majority of cases. Reported by jim@jtan.com
-
- 11/5
- ----
-parse.y
- - change action for `for x; { list; }' and corresponding `select'
- production to use \"$@\" instead of just $@, as it is with all the
- other actions
-
- 11/9
- ----
-parse.y
- - new flag for parse_matched_pair: P_DQUOTE, indicating that the
- pair of characters being matched is between double quotes
- - parse_matched_pair now passes P_DQUOTE down to recursive calls:
- if the open char to be matched is a `"' or the passed-in flags
- include P_DQUOTE, set the local `rflags' variable to P_DQUOTE and
- pass `rflags' down to recursive calls
- - if `rflags' includes P_DQUOTE, don't try to ansiexpand $'...' or
- locale expand $"..."; consistent with other quoting constructs
-
- 11/11
- -----
-doc/{bash.1,bashref.texi}
- - explicitly note that variables referenced in arithmetic expressions
- without using `$' evaluate to 0 if they are null or unset
- - note that a null variable value evaluates to 0 when used in an
- arithmetic context, like when a variable with the `-i' attribute is
- assigned a null value
- - document the ${!prefix@} expansion as equivalent to ${!prefix*}
-
- 11/12
- -----
-doc/{bash.1,bashref.texi}
- - note that the value of an arithmetic expression is as in C
- - change the wording to note that `arithmetic evaluation' (not
- arithmetic expansion, which has a different meaning) is performed
- on the value assigned to a variable whose integer attribute is set
-
- 11/13
- -----
-execute_cmd.c
- - fix execute_disk_command so it calls exit() after printing the error
- message in a restricted shell context if the shell has already forked
- (nofork != 0 && there are no pipes)
-
- 11/19
- -----
-builtins/type.def
- - don't report on aliases unless expand_aliases is set and the parser
- is performing alias expansion; changed tests/type.tests and
- tests/type.right accordingly
-
- 11/25
- -----
-general.c
- - fix for full pathnames including drive letters on cygwin from
- Corinna (convert to posix-style paths, which the rest of the
- code handles much better)
-
-lib/readline/text.c
- - fixes to overwrite mode from jimmy@is-vn.bg:
- o in _rl_overwrite_char, do the overwrite mode self-insert
- as one group, even when overwriting more than 1 char
- o in _rl_overwrite_char, do the insert before the delete so
- that an undo positions the cursor on the character restored,
- not to the right of it
- o in _rl_overwrite_rubout, don't do rl_insert_char(' ') unless
- rl_point < rl_end. Since overwrite-mode self-insert acts as
- in insert-mode when at eol, make rubout behave like
- insert-mode rubout
-
- 11/30
- -----
-lib/readline/misc.c
- - call rl_replace_line with `1' as second parameter if we're going to
- immediately overwrite the undo list
-
-lib/readline/search.c
- - in make_history_line_current, use _rl_replace_text to make the line
- replacement an undoable operation. Affects all non-incremental
- search functions.
-
-parse.y
- - make behavior introduced on 11/9 dependent on extended_quote
- variable, controllable by extquote shopt option. Default setting is
- on for backwards compatibility
-
-builtins/shopt.def
- - new `extquote' option to control extended_quote variable
-
- 12/3
- ----
-jobs.c
- - change message printed when attempting to put a background job in
- the background with `bg' to include the job id and make the
- statement declarative
-
- 12/10
- -----
-bashhist.h
- - define explicit flag values for history_control
-
-variables.c
- - change sv_history_control to use new flag values
- - change sv_history_control to parse $HISTCONTROL as a colon-separated
- list of values for the history_control variable
-
-bashhist.c
- - change check_history_control to use new flag values and restructure
- to remove case statement
- - new function hc_erasedups(line); removes all entries matching LINE
- from the history list
- - call hc_erasedups() from check_add_history after we've determined
- that we're saving the line
-
-doc/{bash.1,bashref.texi}
- - documented new options available for $HISTCONTROL and that it can
- be a colon-separated list of history control options
-
- 12/11
- -----
-subst.c
- - fix pat_subst() to not increment `e' (pointer to the end of the
- matched portion of the string) until after we're sure we're going
- around the loop again; fixes problem with empty replacements for
- a pattern that doesn't match (bug reported by Don Coleman
- <don@coleman.org>)
-
- 12/17
- -----
-lib/readline/display.c
- - fixes to multibyte redisplay from jir@yamato.ibm.com (Jiro SEKIBA):
- o speed up calculation of first difference between old and new
- lines in the common case
- o don't try to see if we're in the middle of a multbyte char
- in update_line (we'll see how this one works out)
-
- 12/18
- -----
-doc/bashref.texi
- - make it clear that the `command-list' function definition may be
- terminated by an ampersand before the closing brace
-
- 12/28
- -----
-redir.c
- - set `expanding_redir' flag when expanding words in a redirection
-
-subst.c
- - new function, exp_jump_to_top_level(), to do any word expansion
- cleanup before a call to jump_to_top_level from within that file;
- sets expanding_redir back to 0 before jump_to_top_level
-
-variables.c
- - in find_variable(), don't call find_variable_internal with a second
- parameter of 1 if expanding_redir is non-zero
- - in find_variable_internal(), don't search the temporary env if
- subshell_environment includes SUBSHELL_FORK (indicating a simple
- command) and expanding_redir is non-zero
-
-parse.y
- - increment line_number when we read a \<newline> pair
-
-array.c
- - added array_unshift_element and array_shift_element (which just call
- array_shift and array_rshift, respectively), for bash debugger
- support
-
- 1/4/2003
- --------
-doc/{bash.1,bashref.texi}
- - note in the section describing the execution environment passed to
- children that subshells inherit shell functions marked for export
- - note in the section describing shell functions the possibility
- that exported functions may result in two entries in the environment
- with the same name
-
-parse.y
- - when pushing an alias expansion onto the pushed_string list, append
- a space to the expanded definition to make the parser's lookahead
- work without using the `mustpop' hack in shell_getc
-
- 1/8
- ---
-shell.c
- - change calls to exit() with EX_USAGE as a parameter to use
- EX_BADUSAGE instead, since EX_USAGE is defined as 258 and is
- technically out of range
-
- 1/14
- ----
-aclocal.m4
- - check for the termcap functions in libc first: if we don't have
- to link in another library, let's not do it
- - change the test for mbstate_t to use AC_TRY_COMPILE instead of
- AC_TRY_RUN
-
-doc/{bash.1,bashref.texi}
- - document that bash turns line editing off if environment variable
- EMACS is set to `t' when it starts up
-
-doc/bash.1
- - minor change to give the ftp url for the latest version of bash in
- the bug reports section
-
-lib/readline/histexpand.c
- - in get_history_event, cast a couple of `const char *' variables to
- `char *' in function call parameter lists to avoid compiler warnings
-
- 1/21
- ----
-builtins/cd.def
- - change `cd -' so it prints the current working directory after a
- successful chdir even when the shell is not interactive
-
- 1/31
- ----
-lib/readline/doc/rltech.texinfo
- - clarified exactly what is meant by the term `application-specific
- completion function', made its use consistent, and documented
- what variables are changed before such a function is called
-
-lib/readline/input.c
- - new function, _rl_pushed_input_available(), returns non-zero if
- there are characters in the input queue managed by rl_get_char
- and _rl_unget_char
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_pushed_input_available
-
-lib/readline/callback.c
- - change rl_callback_read_char to check _rl_pushed_input_available
- and loop if there's something there, so characters don't languish
- until more keyboard input is read
-
-execute_cmd.c
- - new variable, last_command_exit_signal, non-zero if
- last_command_exit_value result from wait_for was result of a signal
-
-nojobs.c
- - keep track of whether or not a given pid was killed by a signal with
- a new flag in the pid_list array
- - new function int find_termsig_by_pid(pid_t pid) to get the
- terminating signal, if any, for a particular pid
- - new function int get_termsig(WAIT status) returns the terminating
- signal corresponding to status
- - set last_command_exit_signal in wait_for and the various wait_for_xx
- functions
-
-jobs.c
- - new functions, process_exit_signal and job_exit_signal, return the
- signal that killed a given process or job, if a signal caused its
- death
- - set last_command_exit_signal in wait_for by calling job_exit_signal
- or process_exit_signal appropriately
-
-subst.c
- - don't resend SIGINT to ourselves unless last_command_exit_signal is
- SIGINT and last_command_exit_value == 128 + SIGINT. This fixes the
- $(exit 130) bug reported by Paul Jarc
-
-expr.c
- - new function, expr_bind_variable, calls bind_int_variable and
- then stupidly_hack_special_variables. This fixes the
- `let OPTIND=1' bug
-
-bashline.c
- - change history_and_alias_expand_line and shell_expand_line to call
- history_expand_line_internal so calls to pre_process_line are
- localized
- - change history_expand_line_internal and cleanup_expansion_error to
- temporarily turn off hist_verify before calling pre_process_line
- to avoid the effects described by teirllm@dms.auburn.edu
-
-parse.y
- - don't unconditionally turn off PST_ALEXPNEXT in push_string. This
- fixes the multiple alias expansion bug reported by Paul Jarc.
-
-lib/readline/vi_mode.c
- - change rl_vi_subst to push `l' instead of ` ' -- it should be
- equivalent, but this has been reported to fix a problem in multibyte
- locales
-
-lib/readline/readline.h
- - new state flag value RL_STATE_TTYCSAVED, indicates that save_tty_chars
- has been called. Since it's only used and visible internally, it's
- undocumented
-
-lib/readline/rltty.h
- - changed all of the members of _rl_tty_chars struct to `unsigned char'
-
-lib/readline/rltty.c
- - set the RL_STATE_TTYCSAVED after save_tty_chars is called
- - new function, rl_tty_unset_default_bindings(), resets bindings for
- everything rl_tty_set_default_bindings() messes with back to
- rl_insert, so rl_tty_set_default_bindings can be called again with
- possible changes
- - new function that does the bulk of the work for
- rltty_set_default_bindings: _rl_bind_tty_special_chars()
- - change prepare_terminal_settings so that it can track changes to the
- terminal special chars made by stty(1): unset the bindings with
- rl_tty_unset_default_bindings before calling save_tty_chars, and
- _rl_tty_set_default_bindings after, with the new values from
- get_tty_settings(). This implements a long-standing request, most
- recently made by Tim Waugh of Red Hat.
-
-lib/readline/readline.h
- - extern declaration for rl_tty_unset_default_bindings()
-
-lib/readline/readline.c
- - new function, reset_default_bindings, calls
- rl_tty_unset_default_bindings() to reset the terminal special chars
- back to rl_insert and then read the new ones
-
-lib/readline/doc/rltech.texinfo
- - documented rl_tty_unset_default_bindings()
-
- 2/1
- ---
-[prayers and condolences to the families of the space shuttle crew members]
-
-aclocal.m4
- - add checks for mbrtowc and mbrlen in BASH_CHECK_MULTIBYTE
- - new check, BASH_FUNC_CTYPE_NONASCII, checks whether or not the ctype
- functions handle non-ascii characters correctly
-
-config.h.in
- - add HAVE_MBRTOWC and HAVE_MBRLEN
- - add NO_MULTIBYTE_SUPPORT for new configure argument
- - add CTYPE_NON_ASCII
-
-config-bot.h, lib/readline/rlmbutil.h
- - make sure that mbrtowc, mbrlen, and wcwidth are all present before
- turning on HANDLE_MULTIBYTE
- - turn off multibyte chars if NO_MULTIBYTE_SUPPORT is defined
-
-configure.in
- - new argument --enable-multibyte (enabled by default), allows
- multibyte support to be turned off even on systems that support it
-
-lib/readline/chardefs.h
- - define NON_NEGATIVE as 1 if CTYPE_NON_ASCII is defined
-
- 2/3
- ---
-config.h.in
- - add HAVE_WCTOMB
-
-aclocal.m4
- - check for wctomb in BASH_CHECK_MULTIBYTE
-
- 2/4
- ---
-lib/readline/vi_mode.c
- - in _rl_vi_change_mbchar_case, make sure the result from wctomb()
- is NULL-terminated before trying to insert it with rl_insert_text()
-
- 2/5
- ---
-lib/readline/display.c
- - fix to update_line to avoid problems on systems with multibyte
- characters when moving between history lines when the new line
- has more glyphs but fewer bytes (twaugh@redhat.com)
-
-lib/readline/vi_mode.c
- - use wcrtomb() instead of wctomb() in _rl_vi_change_mbchar_case
-
-pcomplete.c
- - fix init_itemlist_from_varlist to handle the case where the
- `varlist' is NULL
-
-doc/{bash.1,bashref.texi}
- - clarified when a simple command may fail without the shell exiting
- when -e is set
-
- 2/13
- ----
-parse.y
- - when bash is started with --nolineediting, ignore \[ and \] when
- decoding the prompt string
-
-subst.c
- - fix remove_quoted_nulls so that a string with a CTLESC appearing
- after a CTLNUL (which was removed) does not leave characters in
- the string inappropriately
-
- 2/14
- ----
-builtins/common.h
- - new flag value for parse_and_execute(): SEVAL_RESETLINE, which
- allows the caller to specify whether or not the internal idea
- of the line number should be reset to 1
-
-builtins/evalstring.c
- - parse_and_execute() now tells push_string to reset the line
- number only if the SEVAL_RESETLINE flag is set by the caller
-
- 2/15
- ----
-builtins/evalfile.c
- - pass SEVAL_RESETLINE from _evalfile() to parse_and_execute()
-
-subst.c
- - if the shell is currently interactive, pass SEVAL_RESETLINE to
- parse_and_execute() when doing command substitution
-
-jobs.c
- - add SEVAL_RESETLINE to parse_and_execute while running SIGCHLD trap
-
-command.h
- - add `line' members to case_com, for_com, select_com
- - rearranged order of members in some of the command structs, so
- `flags' and `line' are first
- - added a `source_file' member to the function_def struct; keeps
- track of where the function was defined
-
-doc/Makefile.in
- - add some new suffix rules: .dvi.ps
-
-doc/{bash.1,bashref.texi}
- - added text to the description of the `trap' builtin tightening up
- the language describing when the ERR trap will be run
-
-error.c
- - if $BASH_SOURCE (internally-maintained) exists, use BASH_SOURCE[0]
- in get_name_for_error if the shell is not interactive
-
-array.h
- - new convenience defines: array_push and array_pop
-
-variables.c
- - change get_funcname to return this_shell_function->name only if
- arrays have not been compiled into the shell
- - change init_funcname_var to initialize FUNCNAME as an array variable
- if we have arrays
- - new function: get_self(SHELL_VAR *self), a degenerate `dynamic_value'
- function for dynamic variables
- - new function: init_dynamic_array_var(), a generic dynamic array
- variable initializer to handle the common case
- - use init_dynamic_array_var() instead of explicit init_dirstack_var()
- - use init_dynamic_array_var() instead of explicit init_groups_var()
- - new dynamic array variables: BASH_ARGC, BASH_ARGV, BASH_SOURCE,
- BASH_LINENO, initialized with init_dynamic_array_var
-
-shell.c
- - initialize BASH_LINENO, BASH_SOURCE, FUNCNAME in open_shell_script
-
-{execute_cmd,trap}.c
- - take out trap_line_number, since parse_and_execute doesn't reset the
- line number any more when running the trap commands
-
-make_cmd.c
- - augment make_function_def to get source file name and call
- bind_function_def to save the entire FUNCTION_DEF
-
-variables.c
- - new hash table: shell_function_defs, keeps table of shell function
- definitions including source file and line number info corresponding
- to shell_functions table
- - new functions: find_function_def and bind_function_def to manage
- the shell_function_defs hash table
- - new function: unbind_function_def to remove a function definition
- from the shell_function_defs table (right now uncalled)
-
-variables.h
- - extern declaration for bind_function_def, find_function_def
- - new extern declaration for unbind_function_def
-
-execute_cmd.c
- - in function prologue and epilogue, push and pop FUNCNAME,
- BASH_SOURCE, and BASH_LINENO information
-
-dispose_cmd.c
- - broke the code that disposes a FUNCTION_DEF out into two new
- functions: dispose_function_def and dispose_function_def_contents
-
-dispose_cmd.h
- - new extern declarations for dispose_function_def_contents and
- dispose_function_def
-
-copy_cmd.c
- - move body of copy_function_def (other than allocating a new
- FUNCTION_DEF) to copy_function_def_contents
- - make sure to copy the new source_file member of a function_def in
- copy_function_def_contents
- - copy_function_def is no longer static, copy_function_def_contents
- is not either
-
-command.h
- - new extern declaration for copy_function_def_contents and
- copy_function_def
-
-parse.y
- - keep a stack of line numbers where case, select, and for commands
- start, with a maximum nesting level of 128; increment when reading
- word after `for', `select' or `case' in read_token_word; decrement
- in grammar actions after parsing a complete for, arith_for, select,
- or case command
- - create for, case, arith_for, and select commands with an extra
- line number (word_lineno[word_top]) argument
-
-make_cmd.c
- - make_for_or_select, make_for_command, make_case_command, and
- make_select_command all take an extra `line_number' argument
-
-make_cmd.h
- - corresponding changes to extern declarations for those functions
-
- 2/16
- ----
-{execute_cmd,shell,variables}.c
- - follow each call to remember_args with a call to push_args or
- pop_args to manage the BASH_ARGV and BASH_ARGC arrays. Only set
- when the shell is started to run shell script or runs a shell
- function. Doesn't handle `set' or `shift' yet, nor `source'.
-
-execute_cmd.c
- - keep track of the level of subshells with a new variable, manipulated
- in execute_in_subshell
- - set currently_executing_command in execute_command_internal(),
- even if we're running a trap
- - better line number management when executing simple commands,
- conditional commands, for commands in execute_command_internal()
- and the various functions that implement the commands
- (execute_cond_command, execute_for_command, execute_etc.)
-
-variables.c
- - new dynamic variable BASH_SUBSHELL, with new get_subshell and
- assign_subshell functions to manipulate it
- - new functions push_args (WORD_LIST *list) and pop_args (void) to
- manage the BASH_ARGC and BASH_ARGV dynamic array variables
-
-variables.h
- - new extern declarations for push_args and pop_args
-
-builtins/evalfile.c
- - in _evalfile, do appropriate things to the FUNCNAME, BASH_ARGV,
- BASH_ARGC, BASH_SOURCE, and BASH_LINENO variables
-
-support/mksignames.c
- - add another fake signal for `trap'; make NSIG+2 == `RETURN'
-
-trap.c
- - _run_trap_internal now returns an int: the exit value of the command
- run as the result of the trap
- - run_debug_trap now returns an int: the exit value of the command
- run as the result of the trap
- - RETURN is a new special trap
- - new function: set_return_trap(char *command) interface for the rest
- of the shell, like set_{debug,error}_trap
- - new function: run_return_trap()
- - command substitution and other child processes don't inherit the
- return trap
-
-trap.h
- - new extern declaration for set_return_trap() and run_return_trap
- - new defines for RETURN_TRAP; increment BASH_NSIG
- - change extern declaration for run_debug_trap() since it now returns
- an int
-
-shell.c
- - new invocation long option: --debugger, turns on debugging and
- sets internal `debugging_mode' variable
-
-execute_cmd.c
- - new code to save return trap when executing a shell function, so
- shell functions don't inherit it
- - run debug trap before binding the variable and running the action
- list in a `for' command
- - run debug trap before binding the selection variable and running
- the query in a `select' command
- - run debug trap before running matcher in a `case' command
-
-builtins/set.def
- - new `set -o functrace' (set -T), causes DEBUG trap to be inherited
- by shell functions
- - new `set -o errtrace' (set -E), causes ERR trap to be inherited
- by shell functions
-
-flags.c
- - new flags -E and -T, control error_trace_mode and
- function_trace_mode respectively
-
-flags.h
- - new extern declarations for error_trace_mode and function_trace_mode
-
- 2/17
- ----
-doc/bashref.texi
- - changed the `dircategory' as per Karl Berry's suggestion
-
-doc/texinfo.tex
- - update to version of 2003/02/04 from texinfo.org
-
-support/texi2dvi
- - update to version 1.14 from texinfo-4.5 distribution
-
- 2/20
- ----
-support/config.{guess,sub}
- - update to versions of 2002/11/30
-
-lib/readline/doc/manvers.texinfo
- - renamed to version.texi to match other GNU software
- - UPDATE-MONTH variable is now `UPDATED-MONTH'
-
-lib/readline/doc/{hist,rlman,rluserman}.texinfo
- - include version.texi
-
-doc/version.texi
- - new file, with standard stuff matching other GNU distributions
-
-{doc,lib/readline/doc}/Makefile.in
- - include right stuff for `version.texi'
-
-lib/readline/doc/{rluserman,rlman,hist}.texinfo
- - use @copying and @insertcopying and @ifnottex instead of @ifinfo
- - add FDL as an appendix entitled `Copying This Manual'
-
-lib/readline/doc/{rltech,rluser,hstech,hsuser}.texi
- - changed the suffix from `texinfo' to `texi'
-
-lib/readline/doc/{rlman,rluserman}.texinfo, doc/bashref.texi
- - include rltech.texi,rluser.texi,hstech.texi, and hsuser.texi
-
-lib/readline/doc/Makefile.in,doc/Makefile.in
- - made appropriate changes for {{rl,hs}tech,{rl,hs}user}.texi
-
-lib/readline/doc/{rlman,rluserman}.texinfo
- - changed the suffix from `texinfo' to `texi'
-
-lib/readline/doc/hist.texinfo
- - renamed to history.texi
-
- 2/25
- ----
-pathnames.h.in
- - moved pathnames.h here so value of DEBUGGER_START_FILE can be
- substituted by configure
-
-aclocal.m4
- - added AM_PATH_LISPDIR for debugger
-
-configure.in
- - added some variables: `bashvers', `relstatus' to use info in more
- than one place
- - call AM_PATH_LISPDIR
- - new option: --enable-debugger, sets DEBUGGER cpp option
- - new option with AC_ARG_VAR: DEBUGGER_START_FILE
- - make `pathnames.h' a file generated by configure
-
-Makefile.in
- - add rule to create pathnames.h
-
-builtins/declare.def
- - added extra line number and source file name to `declare -F' output
- if `--debugger' is used at startup
-
-builtins/evalfile.c
- - call run_return_trap from source_file before returning the result
- from _evalfile()
-
-execute_cmd.c
- - call run_return_trap in execute_function before restoring the old
- context
-
-builtins/source.def
- - arrange to save and restore DEBUG traps when sourcing files if
- function_trace_mode (set -o functrace) is not set
-
-print_cmd.c
- - broke print_for_command, print_select_command, print_case_command
- into two functions each: one to print the `header' and one for
- the body
- - print_cond_command is no longer static
- - print_arith_command now takes a WORD_LIST *, since it doesn't
- actually do anything with the ARITH_COM it's passed except print
- the enclosed WORD_LIST
- - print_arith_command is no longer static
-
-externs.h
- - extern declarations for print_{for,select,case}_command_head,
- print_cond_command, print_arith_command
-
-{.,builtins,lib/sh}/Makefile.in
- - corrected dependencies on pathnames.h, since it's now created in
- the build directory
-
- 3/5
- ---
-lib/glob/glob.c
- - handle alloca() failing (it's supposed to return NULL)
- - use malloc() (with its attendent bookkeeping) instead of alloca()
- in glob_filename()
-
-subst.c
- - check whether shell_glob_filename returns NULL in
- glob_expand_word_list
- - change parameter_brace_expand_rhs to handle cases like
- ${a[2]:=value} by properly creating the array element instead of a
- variable named `a[2]' (reported by <opengeometry@yahoo.ca>)
-
-variables.c
- - change bind_int_variable to use valid_array_reference instead
- of looking for `['
-
-lib/readline/vi_mode.c
- - check for `a' in _rl_vi_done_inserting so the text inserted by an
- `a' command can be reinserted with a `.'
-
-lib/readline/readline.c
- - when entering vi insertion mode in readline_internal_setup(), make
- sure that _rl_vi_last_key_before_insert is set to `i' so that undo
- groups and redo work better (reported by <opengeometry@yahoo.ca>)
-
-lib/glob/sm_loop.c
- - handle ?(...) in a pattern immediately following a `*', instead of
- ignoring the `(' and treating the `?' as a single-char match, as
- long as FNM_EXTFLAG is set (reported by <anderson110@poptop.llnl.gov>)
-
-aclocal.m4
- - new test for presence of struct timezone, BASH_STRUCT_TIMEZONE
-
-config.h.in
- - add HAVE_STRUCT_TIMEZONE
-
-configure.in
- - call BASH_STRUCT_TIMEZONE
-
-execute_cmd.c
- - don't try to use `struct timezone' in calls to gettimeofday unless
- HAVE_STRUCT_TIMEZONE is defined; use (void *)NULL otherwise
-
- 3/20
- ----
-execute_cmd.c
- - new variable, the_printed_command_except_trap, saves the command
- being executed before a trap is executed, for the debugger
-
-trap.c
- - if in debugging mode, let command substitutions and other child
- processes inherit the DEBUG and ERR traps if the `functrace'
- (which is really a bad name, given this semantic) or `errtrace'
- options, respectively, have been set
-
-shell.c
- - local_pending_command renamed to command_execution_string; no longer
- static
-
-variables.c
- - new dynamic variable, BASH_COMMAND, set to the command string
- currently executing, or the one that caused a trap to execute
- (mapped to the_printed_command_except_trap)
- - new variable, BASH_EXECUTION_STRING, set to the argument to the
- -c invocation option, if the shell was started that way
-
- 3/22
- ----
-execute_cmd.c
- - changed execute_for_command, eval_arith_for_expr,
- execute_select_command, execute_arith_command, execute_cond_command,
- execute_simple_command to implement new DEBUG trap semantics
- for the debugger: if the DEBUG trap commands return a non-zero
- status and debugging_mode is non-zero, we skip the command to be
- executed
-
-trap.c
- - change run_debug_trap for the 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'
-
-shell.c
- - new function, start_debugger(), that sources the debugger start file
- and turns the debugger on
-
-builtins/shopt.def
- - new settable option, `extdebug', turns on debugging_mode, as if
- --debugger had been supplied at invocation (but does not source
- debugger startup file)
-
-trap.c
- - make sure that run_exit_trap arranges for `returns' to come back
- there, too, so a `return' executed by an `exit' invoked within a
- shell function behaves correctly
-
-support/shobj-conf
- - change darwin/MacOS X stanza based on advice from mac os x developers
-
-lib/sh/mailstat.c
- - set the atime member of the synthesized stat struct to 0 if `cur/'
- is empty, rather than leaving it undefined
-
- 3/24
- ----
-builtins/caller.def
- - new builtin to provide a call stack for the debugger
-
-builtins/evalfile.c
- - added a second `flags' argument to source_file()
- - new flag value for flags argument to _evalfile(): FEVAL_NOPUSHARGS.
- If included in flags arg, it means to not manipulate the BASH_ARGV
- and BASH_ARGC arrays
-
-builtins/common.h
- - change prototype for source_file()
-
-builtins/source.def
- - add flag value to call to source_file(): set to 1 if we replaced
- the positional parameters
- - add call to push_args if additional arguments supplied to the
- source builtin
- - add call to pop_args in maybe_pop_dollar_vars
-
-execute_cmd.c
- - run the debug trap in execute_function so the debugger can stop
- before the first command in a function body is executed
- - modify subshell_level before executing a builtin or function in a
- subshell
- - print `for', `select', `case' command heads when set -x is enabled
-
-print_cmd.c
- - `xtrace_print_word_list' now takes an additional flags argument,
- which, if non-zero, says to print indirection_level_string()
- - new functions to print for, select, and case command heads when
- set -x is enabled
- - add spaces after `((' and before `))' in xtrace_print_arith_command
-
-externs.h
- - changed extern declaration for xtrace_print_word_list
- - new declarations for xtrace_print_{for,case,select}_command_head()
-
-subst.c
- - modify subshell_level when executing a command substitution
-
- 3/25
- ----
-execute_cmd.c
- - use `line_number' in executing_line_number instead of looking into
- the current command if it's a simple command; rearrange code to
- make this simpler to compile in and out
- - need to save and restore value of currently_executing_command around
- calls to debug trap and return trap in execute_function
-
-make_cmd.c
- - make sure make_arith_for_command() disposes the WORD_LIST * it is
- passed, since nothing else does and it's not used directly
-
- 3/28
- ----
-Makefile.in
- - fixed dependencies for `error.o' on shell.h and version.h -- makes
- parallel makes (gmake -j 4) work correctly
-
-doc/{bash.1,bashref.texi}
- - documented all new features added to support the debugger
-
- 4/1
- ---
-lib/sh/shquote.c
- - make sure CTLESC and CTLNUL characters are escaped with CTLESC
- by sh_double_quote, sh_backslash_quote and
- sh_backslash_quote_for_double_quotes
- Fixes vulnerability reported by svdb@stack.nl
-
-shell.h
- - new `pipestatus' member of sh_parser_state_t, to save and restore
- $PIPESTATUS
-
-parse.y
- - changes to save_parser_state and restore_parser_state to save and
- restore $PIPESTATUS
-
-builtins/read.def
- - add a call to word_list_remove_quoted_nulls before assigning the
- word list read from standard input to an array variable. Fixes
- bug reported by holzhey@ppprs1.phy.tu-dresden.de
-
- 4/3
- ---
-execute_cmd.c
- - in execute_null_command, if redirections are supplied, make sure
- things like 3</etc/passwd are undone immediately, since they're
- being done in the current shell
- - functions now inherit the RETURN trap only if function tracing is
- on for that function or globally
-
-lib/readline/misc.c
- - in rl_replace_from_history, don't force rl_replace_line to clear
- the undo_list, since it might point directly at an undo list
- from a history entry (to which we have no handle)
-
- 4/4
- ---
-trap.c
- - initialize RETURN_TRAP stuff appropriately in initialize_traps()
- - let command substitutions inherit the RETURN trap if we're in
- the debugger and function tracing has been enabled
-
-redir.c
- - do_redirections and do_redirection_internal now take a single
- flags argument instead of multiple boolean flags
-
-redir.h
- - new #defines for flags argument to do_redirection{s,_internal}
-
-execute_cmd.c
- - change all calls to do_redirection to use new flag values
-
-parse.y
- - new function, free_pushed_string_input(), an external interface to
- clear the pushed_string list (alias expansion)
- - new define SHOULD_PROMPT to say when it's OK to call prompt_again
- (if the shell is currently interactive and is reading input from
- the terminal or readline)
- - make sure shell_getc and read_secondary_line only call prompt_again
- if SHOULD_PROMPT evaluates to true
- - prompt_again shouldn't do anything if the shell is currently in the
- middle of expanding a multiline alias, since we won't be printing a
- prompt anyway
-
-externs.h
- - new extern declaration for free_pushed_string_input()
-
-execute_cmd.c
- - command_substitute and process_substitute now call
- free_pushed_string_input because they shouldn't deal with any
- partial alias expansion the parent shell may have started
-
- 4/5
- ---
-braces.c
- - added {x..y} brace expansion, shorthand for {x,x+1,x+2,...,y}:
- x, y can be integers or single characters; the sequence can be
- ascending or descending; increment is always 1. Beware that
- something like {a..A} can lead to non-letters.
-
- 4/7
- ---
-subst.c
- - change extract_delimited_string and extract_dollar_brace_string to
- return NULL on an expansion error when no_longjmp_on_fatal_error
- is set, so the calling functions don't assume that the expansion
- was successful (primarily the prompt expansion and completion code)
-
-doc/{bash.1,bashref.texi}
- - documented new sequence generation feature of brace expansion
-
- 4/8
- ---
-lib/sh/strstr.c
- - replacement for strstr(3), in case the C library doesn't provide it
-
-configure.in
- - check for strstr, add to LIBOBJS if not found
-
-array.c
- - array_walk now takes a third void * argument; it's passed to `func'
- as its second argument
-
-array.h
- - change sh_ae_map_func_t prototype to add void * second argument
-
- 4/10
- ----
-array.c
- - new function: array_keys_to_word_list, returns a list of indices for
- a given array
-
-array.h
- - new extern declaration for array_keys_to_word_list
-
-arrayfunc.c
-3 - new function: char *array_keys(), returns a string with keys for a
- given array, with the appropriate quoting
-
-arrayfunc.h
- - new extern declaration for array_keys
-
-subst.c
- - code to implement ksh93-like ${!array[@]} expansion (array[*] works,
- too), which expands to all the keys (indices) of ARRAY
-
-doc/{bash.1,bashref.texi}
- - documented new ${!array[@]} expansion
-
- 4/19
- ----
-builtins/setattr.def
- - remove any mention of the `-n' option from readonly builtin's short
- and long documentation
-
-pcomplib.c
- - fix progcomp_insert to increase the refcount on the `cs' argument
- before calling hash_insert -- fixes the problem of multiple calls
- to progcomp_insert with the same compspec
-
-doc/bash.1
- - add mention of characters that inhibit history expansion when found
- immediately following an unquoted `!'
-
-bashline.c
- - convert the code conditionally compiled in by the NO_FORCE_FIGNORE
- #define to something runtime-tunable with the `force_fignore'
- variable (opposite sense). force_fignore is 1 by default
-
-builtins/shopt.def
- - new tunable `shopt' option: `force_fignore', controls force_fignore
- variable and behavior of FIGNORE handling
-
-lib/readline/complete.c
- - new variable, _rl_complete_show_unmodified, causes completer to list
- possible completions if more than one completion and partial
- completion cannot be done
- - new value for what_to_do argument to rl_complete_internal, `@',
- indicating that we want the show-unmodified behavior
- - change rl_completion_type to return `@' when appropriate
-
-lib/readline/bind.c
- - new bindable variable, show-all-if-unmodified, which controls value
- of _rl_complete_show_unmodified
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_complete_show_unmodified
-
-lib/readline/doc/rluser.texi
- - documented show-all-if-unmodified
-
-lib/readline/doc/rltech.texi
- - documented new `@' value for second argument to rl_complete_internal
- - documented new return value from rl_completion_type
-
- 4/22
- ----
-lib/readline/signals.c
- - in rl_set_signal, set sa_flags to SA_RESTART for SIGWINCH, if we
- have POSIX signals -- this is what most applications expect, and
- they're not prepared to deal with EINTR
-
- 4/25
- ----
-bashline.c
- - take out attempts to suppress readline filename completion when
- attempting command completion and there is a directory with the
- same name in the current directory. #if 0'd for now; maybe make
- it conditional later
-
-error.c
- - new variable, gnu_error_format, causes non-interactive errors with
- line numbers to be printed in the `gnu style' (filename:lineno:)
- instead of the `shell style' (filename: line lineno:) by
- error_prolog and parser_error
-
-version.h,support/mkversion
- - don't put extern function declarations into created version.h any
- more
-
-version.c,externs.h
- - add extern declarations for show_shell_version() and
- shell_version_string(), since they're no longer in version.h
- (this backs out change from 9/10/2001)
-
-shell.h
- - don't include version.h
-
-Makefile.in
- - remove unneeded dependencies on version.h -- only version.o
- needs it now
-
-builtins/shopt.def
- - new option `gnu_errfmt', changes error messages with line numbers
- to use the `standard' gnu format
-
-pcomplete.h
- - new COPT_BASHDEFAULT and COPT_PLUSDIRS defines
-
-bashline.c
- - if the COPT_BASHDEFAULT flag is set, try the rest of the bash
- default completions if a compspec with that flag set generates
- no matches
- - broke bash completions out into separate function:
- bash_default_completion(const char *text, int start, int end,
- int qc, int in_command_position); change attempt_shell_completion
- to call it
-
-bashline.h
- - new extern declaration for bash_default_completion
-
-builtins/complete.def
- - added code to compgen to call bash_default_completion if a compspec
- with the COPT_BASHDEFAULT flag set generates no matches from the
- programmable completion options
-
-doc/{bash.1,bashref.texi}
- - document new `gnu_errfmt' shopt option
-
-doc/bash.1,lib/readline/doc/rluser.texi
- - document new `-o bashdefault' option to complete and compgen
-
- 4/26
- ----
-pcomplete.c
- - if a compspec has the COPT_PLUSDIRS flag set, generate any
- directory name completions and add them to the set of possible
- completions as the last thing in gen_compspec_completions
-
-builtins/complete.def
- - add new `-o plusdirs' option to complete and compgen; means to
- do directory name completion in addition to other actions
- specified by the compspec, and do it last
-
- 5/12
- ----
-copy_cmd.c
- - fix copy_{for,select,case}_command to copy the line member
-
- 5/13
- ----
-lib/readline/rlmbutil.h,include/shmbutil.h
- - new #define MB_INVALIDCH, evaluates to true if return value from
- mbrtowc or mbrlen denotes an invalid multibyte character
- - new #define MB_NULLWCH, evaluates to true if return value from
- mbrtowc or mbrlen denotes a null multibyte character
-
-lib/readline/complete.c
- - new function, fnwidth(), returns printed length of a filename,
- correctly handling multibyte characters
- - new function, fnprint(), displays a filename on rl_outstream
- correctly handling multibyte characters
- - use fnwidth() instead of simple strlen() for length calculations
- in display_matches
-
-lib/readline/{display,mbutil}.c
- - use MB_INVALIDCH and MB_NULLWCH as appropriate
-
- 5/21
- ----
-configure.in
- - turn off the builtin malloc on GNU/FreeBSD systems (GNU userland,
- FreeBSD kernel)
-
- 5/24
- ----
-pcomplete.c
- - in programmable_completions, copy the compspec before using it to
- generate the possible completions, allowing the completion for the
- command to be changed by the compspec itself without causing a
- core dump because the shell frees freed memory (reported by
- marcus.harnish@gmx.net)
-
-parse.y
- - in shell_getc, don't call notify_and_cleanup in an interactive shell
- unless the shell is currently reading from the terminal and would
- print a prompt. This fixes programmable completions printing job
- notifications (reported by r.d.green@lancaster.ac.uk)
- - use SHOULD_PROMPT macro consistently
-
-shell.c
- - use get_string_value instead of getenv when looking up $TERM and
- $EMACS to see whether the shell is running under emacs
- - check for `TERM=dumb' as well as `EMACS=t' to decide whether or
- not to turn off command-line editing in emacs shell windows
- (reported by jik@kamens.brookline.ma.us)
-
- 5/28
- ----
-expr.c
- - save and restore the `evalbuf' context, since evalexp can be
- called recursively (e.g. a[b[c]])
-
- 5/29
- ----
-builtins/common.c
- - in display_signal_list, when displaying for `kill -l' in posix mode,
- display signal names without the `SIG' prefix
-
-doc/bashref.texi
- - documented changed to posix mode behavior of kill -l
-
-builtins/kill.def
- - changed the error message printed when argument is not a pid or
- job id
-
-doc/{bash.1,bashref.texi}
- - fixed a slight inconsistency in the different sections describing
- the `promptvars' option
-
-doc/Makefile.in
- - new rule to create `bash.info' from `bashref.info' by running sed
- to change the internal references. This makes the installed
- bash.info work right
- - make the install target install bash.info after it's been modified
- from bashref.info
-
- 5/30
- ----
-builtins/cd.def
- - after testing with ferror(), call clearerr if ferror() evaluates
- to true
-
-execute_cmd.c
- - call clearerr(stdout) after executing a builtin or function,
- before restoring any redirections
-
-bashhist.c
- - initialize history_comment_char in bash_history_initialize
-
-builtins/alias.def
- - if posix mode is enabled, and the `-p' option is not supplied, don't
- list aliases with a preceding `alias ', as POSIX.2 specifies
-
-doc/bashref.texi
- - note new posix mode behavior of displaying alias names and values
- - note new posix mode behavior of trap builtin not checking first
- argument to be a possible signal specification
- - note new posix mode behavior of `kill' not accepting signal names
- with a leading `SIG'
-
-include/stdc.h,lib/readline/rlstdc.h
- - don't check the __STRICT_ANSI__ define when deciding whether or not
- to #undef __attribute__
-
-trap.[ch]
- - decode_signal and signal_object_p take an additional flags arg to
- satisfy POSIX.2 signal name translation requirements
- - change decode_signal to honor the new DSIG_NOCASE (match case-
- insensitively) and DSIG_SIGPREFIX (allow signal specifications
- with the `SIG' prefix) flags
-
-builtins/{common.c,{trap,kill}.def}
- - change calls to decode_signal to add the new argument with
- appropriate values. For kill, POSIX.2 says case-insensitive without
- the `SIG' prefix. For trap, POSIX.2 says applications may decode
- case-insensitively and with the SIG prefix
-
-builtins/trap.def
- - when in posix mode, don't check for the first argument being a
- possible signal spec and revert the signal handling to the
- original disposition
-
- 6/1
- ---
-shell.h
- - new MATCH_STARSUB define, to tell the callers of the various pattern
- substitution and removal functions that call string_list to treat
- "$*" and "${array[*]}" appropriately
-subst.c
- - if get_var_and_type encounters an array variable subscripted by `*'
- or `$*', return VT_STARSUB or'd into the variable type value
- - callers of get_var_and_type check for VT_STARSUB in the returned type
- this will fix problems with ${*...} not being separated with the
- first character of $IFS when double-quoted
- - in parameter_brace_patsub, set MATCH_STARSUB if VT_STARSUB is set by
- get_var_and_type
- - change pos_params_pat_subst to call string_list_dollar_star if
- the match flags include MATCH_STARSUB
- - change parameter_brace_substring to call array_subrange with an
- additional argument indicating the character indexing the array
-
-array.c
- - change array_patsub to join the modified array elements with the
- first character of $IFS if MATCH_STARSUB is set in the match flags
- passed in
- - array_subrange now takes an additional argument indicating the
- index type -- used to separate with first char of $IFS if the
- index char is `*' and the expression is double-quoted
-
-array.h
- - change prototype declaration of array_subrange to add additional arg
-
- 6/2
- ---
-doc/FAQ
- - merged in some updates about POSIX from Andrew Josey
-
- 6/3
- ---
-bashjmp.h
- - new value for jump_to_top_level: ERREXIT
-
-{eval,shell,subst,trap}.c,builtins/evalstring.c
- - ERREXIT is (for now) equivalent to EXITPROG as a value from
- jump_to_top_level
-
- 6/9
- ---
-doc/bash.1,lib/readline/doc/readline.3
- - documented new `show-all-if-unmodified' readline variable
-
- 6/14
- ----
-lib/readline/history.c
- - new function, histdata_t free_history_entry (HIST_ENTRY *h),
- frees H and its line, returning the application-specific data
- - use free_history_entry where appropriate
-
-lib/readline/history.h
- - extern declaration for free_history_entry()
-
-lib/readline/doc/{history.3,hstech.texi}
- - document free_history_entry
-
- 6/16
- ----
-lib/readline/readline.[ch]
- - changed varions defines for readline/history library versions to 5.0
-
-subst.c
- - pass information about whether or not an indirectly-expanded variable
- contains ${array[@]}, ${array[*]}, $@, or $*
- - new function, chk_atstar, performs checks for ${array[@]},
- ${array[*]}, $@, or $* for the parameter_brace_expand* functions and
- sets flags (passed as args) to the results
- - call chk_atstar from parameter_brace_expand_indir and
- parameter_brace_expand
-
- 6/28
- ----
-doc/{bash.1,bashref.texi}
- - clarified that (...) commands are executed in a subshell environment
-
- 6/30
- ----
-lib/readline/bind.c
- - fix a problem with parsing nested if statements in inputrc files
- (fix from dimakar@yahoo.com)
-
- 7/3
- ---
-{jobs,nojobs}.c
- - fix places that use the return value from strsignal() to check
- for NULL return values using a new function, j_strsignal()
-
-builtins/kill.def
- - removed JOB_CONTROL restriction; kill is now available as a builtin
- when the shell is built without job control
-
- 7/10
- ----
-jobs.c
- - some systems have WIFCONTINUED but not WCONTINUED; separate the
- #defines
-
- 7/14
- ----
-lib/readline/history.h
- - new `timestamp' member of a HIST_ENTRY
- - extern declarations for add_history_time and history_get_time
-
-lib/readline/doc/{history.3,hstech.texi}
- - document add_history_time and history_get_time
-
-lib/readline/history.c
- - implementations of history_get_time and add_history_time
- - change add_history to initialize the timestamp information
- - change free_history_entry to free the timestamp
- - change replace_history_entry to duplicate the timestamp
- - change history_total_bytes to add the memory taken by the time
- stamps
-
-bashhist.c,builtins/history.def
- - use free_history_entry where appropriate
-
-lib/readline/histfile.c
- - changes to read_history_range to deal with new history file format
- including timestamps
- - changes to history_do_write to write out the timestamp information
- - changes to history_truncate_file to understand the timestamp
- information
-
- 7/22
- ----
-doc/{bash.1,bashref.texi}
- - fixed function declaration documentation to specify that any compound
- command may be used as the function body, not just a group command
-
- 7/23
- ----
-lib/readline/histfile.c
- - don't allocate space for null timestamps in history_do_write, and
- don't write out null timestamp entries
-
-parse.y
- - fix CHECK_FOR_RESERVED_WORD to call time_command_acceptable() and
- return TIME if the token is "time" and `time' is legal in that
- context
-
- 7/29
- ----
-lib/sh/fmtulong.c
- - include <inttypes.h> for possible definitions of intmax_t, uintmax_t
- (reported by ro@techfak.uni-bielefeld.de)
-
- 7/30
- ----
-parse.y
- - remove checking for `time' reserved word from special_case_tokens();
- use regular mechanism in CHECK_FOR_RESERVED_WORD. This allows `time'
- to be aliased. (Reported by Glenn Morris
- <gmorris+gmane@ast.cam.ac.uk>)
-
- 7/31
- ----
-lib/readline/history.h
- - extern declaration for history_write_timestamps
-
-lib/readline/histfile.c
- - don't write timestamps to the history file in history_do_write
- unless history_write_timestamps is set to non-zero by the application
- (set to 0 by default)
-
-lib/readline/doc/{hstech.texi,history.3}
- - document history_write_timestamps
-
-variables.[ch]
- - new special variable function, HISTTIMEFORMAT; special function
- sets history_write_timestamps to 1 if HISTTIMEFORMAT is set
-
- 8/4
- ---
-builtins/history.def
- - added support for printing time stamps based on the value of the
- HISTTIMEFORMAT variable when displaying history entries
-
-doc/{bash.1,bashref.texi}
- - added description of new HISTTIMEFORMAT variable
-
- 8/5
- ---
-config-top.h
- - remove /usr/ucb from any default paths
-
-mailcheck.c
- - make_default_mailpath now returns NULL if DEFAULT_MAIL_DIRECTORY
- is not defined
- - remember_mail_dates now returns if make_default_mailpath returns
- NULL
-
-config-bot.h
- - reorganized the sections; provide an explicit placeholder for
- builders to #undef any feature defines they don't want that
- configure creates for them, like the default mail path
-
- 8/9
- ---
-config.h.in
- - add HAVE_REGEX_H, HAVE_REGCOMP, HAVE_REGEXEC for detection of POSIX.2
- regular expression functions
- - add COND_REGEXP define to enable and disable the =~ operator for
- matching extended regular expressions in [[...]] commands
-
-configure.in
- - new option, --enable-cond-regexp, enables =~ and code to perform
- regular expression matching in [[...]]
-
-config-bot.h
- - undef COND_REGEXP if the OS doesn't provide posix regexp support
-
-doc/bashref.texi
- - documnent new --enable-cond-regexp option to configure
-
- 8/18
- ----
-support/shobj-conf
- - support for shared objects on FreeBSD-gnu (from Robert Millan)
-
- 8/25
- ----
-lib/sh/shmatch.c
- - new file, shell interface to posix extended regular expression
- matching
-
-externs.h
- - new extern declarations for functions in shmatch.c
-
-execute_cmd.c
- - incorporate code into execute_cond_node that does extended regular
- expression matching for the =~ operator
-
-parse.y
- - add `=~' to the list of binary operators accepted by the conditional
- command parser
-
-doc/{bash.1,bashref.texi}
- - documented =~ conditional binary operator and the BASH_REMATCH
- variable
-
- 8/27
- ----
-lib/readline/display.c
- - take multibyte characters into account when looking for quoted
- substrings on which to do completion (fix from jir@yamato.ibm.com)
-
-lib/readline/util.c
- - fix typo in _rl_strpbrk
-
-lib/readline/rldefs.h
- - use function version of _rl_strpbrk in multibyte locales, because
- it understands to skip over special characters in multibyte
- character sequences
-
- 8/28
- ----
-jobs.c
- - in wait_for, check for window size changes if a job that exits due
- to a signal or is stopped was in the foreground, not just if it's
- the current job
-
- 9/10
- ----
-support/config.{guess,sub}
- - add support to recognize FreeBSD running on the amd64
-
-subst.c
- - if the new `fail_glob_expansion' variable is non-zero, globbing that
- fails to match anything causes an expansion error
-
-builtins/shopt.def
- - new `failglob' expansion: if enabled, failed globs cause an error
-
-test/shopt.right
- - take `failglob' into account
-
-doc/{bash.1,bashref.texi}
- - documented new `failglob' option and its effects
-
- 9/12
- ----
-findcmd.c
- - fix file_status to treat the mode bits and uid right -- in particular,
- don't assume the `other' bits always apply. Bug reported by
- <moseley@hank.org>; fix inspired by <carlo@alinoe.com>
-
-command.h
- - new word flag: W_NOCOMSUB, meaning to not perform command
- substitution on a word
-
-subst.c
- - new flag for param_expand: PF_NOCOMSUB. If non-zero, $(...)
- command substitutions are not expanded, but returned unchanged
- - change expand_word_internal to pass through `` command substitutions
- unchanged if (word->flags & W_NOCOMSUB) != 0
- - change expand_word_internal to pass PF_NOCOMSUB to param_expand
- if (word->flags & W_NOCOMSUB) != 0
-
-builtins/shopt.def
- - rename set_interactive_comments to set_shellopts_after_change, which
- more accurately reflects its purpose
-
-syntax.h
- - add a define for isblank() in case the system doesn't provide one
-
-jobs.c
- - change raw_job_exit_status to understand `pipefail', using the new
- `pipefail_opt' variable
-
-flags.[ch]
- - declare pipefail_opt
- - reset pipefail_opt to 0 in reset_shell_flags
-
-builtins/set.def
- - add `set -o pipefail' and document it in help output
-
-doc/{bash.1,bashref.texi}
- - document `set -o pipefail' and the effect of the pipefail option
-
-mksyntax.c,syntax.h
- - sh_syntaxtab is no longer `const'
- - new generated variable, sh_syntabsiz, set to number of entries in
- sh_syntaxtab, written to generated syntax.c
-
-locale.c
- - new function, locale_setblanks(), sets each member of the current
- locale's <blank> class to have the CSHBRK flag in sh_syntaxtab
-
- 9/17
- ----
-arrayfunc.c
- - change convert_var_to_array to not set array[0] to a NULL value
- (if the scalar variable had no value; e.g., after being created
- with `local arrayvar')
-
-lib/readline/display.c
- - save and restore the value of prompt_invis_chars_first_line in
- rl_{save,restore}_prompt, and reinitialize it to 0 before printing
- something in the message area
-
-lib/readline/bind.c
- - new functions: rl_bind_keyseq_if_unbound_in_map(ks, func, kmap);
- binds key sequence KS to function FUNC in keymap KMAP, and
- rl_bind_keyseq_if_unbound (ks, func); binds key sequence KS to
- function FUNC in the current keymap
-
-lib/readline/readline.h
- - extern function declarations for rl_bind_keyseq_if_unbound_in_map and
- rl_bind_keyseq_if_unbound
-
-lib/readline/{readline,terminal}.c
- - _rl_bind_if_unbound -> rl_bind_keyseq_if_unbound
-
-lib/readline/{bind.c,rlprivate.h}
- - remove _rl_bind_if_unbound
-
- 9/18
- ----
-lib/readline/doc/rltech.texi
- - document rl_bind_keyseq_if_unbound and
- rl_bind_keyseq_if_unbound_in_map
-
- 9/19
- ----
-lib/readline/bind.c
- - new functions rl_bind_key_if_unbound_in_map and
- rl_bind_key_if_unbound; analogous to (and implemented in terms of)
- keyseq functions
- - rl_bind_keyseq_in_map: a new function, equivalent to rl_set_key
- (which remains for backwards compatibility); changed callers to
- use it
- - new function, rl_bind_keyseq, equivalent to rl_bind_keyseq_in_map
- with a third argument of _rl_keymap
-
-lib/readline/readline.h
- - extern declarations for rl_bind_key_if_unbound_in_map and
- rl_bind_key_if_unbound
- - extern declarations for rl_bind_keyseq_in_map and rl_bind_keyseq
-
-lib/readline/doc/rltech.texi
- - document rl_bind_keyseq and rl_bind_keyseq_in_map
-
-configure.in
- - require at least readline-5.0
-
-config-bot.h
- - define SYS_SIGLIST_DECLARED if it's not defined, but
- HAVE_DECL_SYS_SIGLIST is, to deal with differences between
- autoconf versions
-
-bashline.c
- - use rl_bind_key_if_unbound_in_map when binding bash keybindings in
- initialize_readline(), so inputrc files can override them
-
- 9/22
- ----
-lib/readline/histsearch.c
- - do better bounds checking for history_offset and history_length in
- history_search_internal
-
-builtins/history.def
- - in delete_last_history(), make sure we don't leave the history
- offset longer than the history length after calling delete_histent
-
- 9/23
- ----
-jobs.c
- - small change to notify_of_job_status so job status messages get
- printed even if the shell was started to run `-c command'. The
- old behavior was intentional, but I cannot remember why, so we'll
- try it the other way for a while (debian bash bug #211693)
-
- 9/24
- ----
-jobs.c
- - slightly modify change from 9/23 so that jobs started to run
- command substitutions don't print job status messages
-
- 9/25
- ----
-lib/readline/search.c
- - when reading a non-incremental search string from the terminal,
- use a separate undo list rather than chaining it to the undo list
- from the rest of the line, since the whole undo list will get
- freed when the search string is complete
-
-lib/readline/readline.h
- - changed the defines guarding the stdarg prototype for rl_message to
- match what's actually used in display.c, where it's defined
-
- 9/26
- ----
-[bash-3.0-alpha released]
-
- 9/29
- ----
-lib/sh/shmatch.c
- - fix to build correctly when arrays are not compiled into the shell
-
-subst.c
- - fix command substitution to run any exit trap defined in the
- command substitution before returning; the exit trap is not inherited
- from the calling shell
-
-lib/readline/shell.c
- - change sh_set_lines_and_columns to free the memory allocated and
- passed to setenv(), since setenv is specified by POSIX to allocate
- new memory and copy its arguments
-
-jobs.c
- - change logic in make_child so that every child process attempts to
- set the terminal's process group to the pipeline's process group
- when PGRP_PIPE is defined, just like when it's undefined. This is
- reported to fix some tricky synchronization problems on Red Hat
- Enterprise Linux 3. Fix from Ernie Petrides <petrides@redhat.com>.
-
- 9/30
- ----
-builtins/printf.def
- - tescape no longer needs a `trans_squote' argument, since it's the
- same as the `sawc' argument. The `sawc' argument now means to do
- the %b argument processing if non-null
- - fix processing of octal constants for %b arguments (\0 followed by
- up to three octal digits) and other escape sequences (\ followed by
- up to three octal digits)
- - hex constants `\xHHH' are now allowed to contain any positive
- number of digits; previously they were restricted to two [removed]
- - allow two new escape sequences: \" and \?, for compatibility with
- ksh93 and ANSI C
-
-doc/{bash.1,bashref.texi}
- - documented processing that printf performs for arguments to %b
- escape sequences
-
-lib/sh/strtrans.c
- - add \" and \? to escape sequences recognized by `echo -e'
-
- 10/1
- ----
-version.c
- - use snprintf instead of sprintf if configure tells us we have it
-
- 10/3
- ----
-subst.c
- - in list_remove_pattern, take into account the fact that one of the
- list elements may be NULL, and don't free the result of
- remove_pattern() without checking
- - in remove_pattern, return savestring(param) if *param == '\0',
- since callers expect to free() non-null return values
-
- 10/4
- ----
-subst.c
- - change verify_substring_values to make it clearer that the first
- offset deals with array indices and the second deals with numbers
- of elements, when doing array subranges with ${a[@]:e1:e2}
-
-array.c
- - change array_subrange to make it explicit that the second offset
- argument is a count of the desired number of elements, not an
- ending index. This deals with sparse arrays correctly.
-
- 10/6
- ----
-variables.c
- - fix memory leak in assign_in_env
-
- 10/8
- ----
-subst.c
- - in parameter_brace_expand, check that the last characters are `]}'
- before checking for ${!array[@]}
-
-execute_cmd.c,builtins/source.def
- - push and pop the args (BASH_ARGV and BASH_ARGC) when executing a
- shell function or sourcing a script only when in debugging mode
-
- 10/11
- -----
-arrayfunc.c
- - make sure array_variable_name returns values for the SUBP and LENP
- arguments if they're non-null, since callers expect to use them
- even if the array subscript is bad
-
-error.c
- - call exit_shell instead of sh_exit from parser_error and
- report_error so the right things happen (running exit trap, doing
- the right interactive cleanup, etc.)
-
-lib/readline/complete.c
- - new variable, rl_completion_quote_character, set to any quote char
- readline thinks it finds before any application completion
- function is called
- - new variable, rl_completion_suppress_quote, settable by an
- application-specific completion function. If set to non-zero, the
- completion code does not append a closing quote in append_to_match
-
-lib/readline/readline.h
- - extern declarations for rl_completion_quote_character and
- rl_completion_suppress_quote
-
-bashline.c
- - set rl_completion_suppress_quote in command_subst_completion_function
- because that would be inserted before any closing "`" or ")", which
- is somewhat disconcerting
-
-lib/readline/doc/rltech.texi
- - documented rl_completion_suppress_quote and
- rl_completion_quote_character
-
- 10/13
- -----
-bashhist.c
- - use sv_histchars instead of setting history_comment_char directly in
- bash_initialize_history so assignments to $histchars made in
- ~/.bashrc are honored
-
- 10/21
- -----
-trap.c
- - make sure run_exit_trap sets `running_trap' appropriately
- - new variable, trap_saved_exit_value, set to last_command_exit_value
- before running any trap commands; available to the rest of the
- shell; use trap_saved_exit_value to replace some function-local
- variables
-
-builtins/exit.def
- - if the shell is running the exit trap, and no argument is given
- to `exit', use trap_saved_exit_value as the exit status instead
- of the last command exit value (which could be the previous command
- run in the exit trap), as required by POSIX.2
-
- 10/25
- -----
-doc/{bash.1,bashref.texi}
- - add `alias' to the list of documented `assignment statement' builtins
-
- 11/1
- ----
-doc/bash.1
- - remove the `.' from the sample $PATH value
-
-parse.y
- - make sure parse_compound_assignment prompts with $PS2 if it reads
- a newline while parsing the compound assignment statement. Bug
- reported by Stephane Chazelas
- - parse_string_to_word_list now takes a new second argument: `int flags'
- - new parser state flag: PST_COMPASSIGN; indicates that the shell is
- parsing a compound assignment statement
- - parse_string_to_word_list turns on PST_COMPASSIGN if `flags' arg
- has low bit set
- - turn PST_COMPASSIGN on and off in parse_compound_assignment
-
-externs.h
- - change prototype declaration for parse_string_to_word_list
-
-arrayfunc.c
- - change call to parse_string_to_word_list to add new flags arg
-
-general.c
- - assignment() takes a new `flags' second argument
- - if `flags' is non-zero, accept `[' as a legal assignment statement
- starter character (for parsing compound array assignments)
-
-general.h
- - add new argument to prototype declaration for assignment()
-
-parse.y,{subst,variables}.c, builtins/{setattr,declare}.def
- - change calls to assignment() (parse.y calls with flags == 1 when
- parser_state inlcudes PST_COMPASSIGN)
-
-arrayfunc.c
- - in assign_array_var_from_string(), don't treat an expanded word
- of the form [ind]=value specially unless the W_ASSIGNMENT flag is
- set. This means that words that are the result of expansions but
- happen to have the same format as compound assignment statement
- words will not be treated as such. For instance
-
- v='[12]=foobar'
- a=( $v )
-
- will result in a[0]='[12]=foobar' instead of a[12]=foobar. This
- is closer to how `regular' assignment statements are treated and
- compatible with ksh93. Bug reported by Stephane Chazelas
-
-shell.c
- - new --protected argument, disables command substitution when used
- with --wordexp (like --wordexp, it remains undocumented)
- - change run_wordexp to turn on the W_NOCOMSUB flag in each word
- to be expanded if protected_mode is set
-
- 11/7
- ----
-doc/{bash.1,bashref.texi}
- - clarified the language concerning inherited signal dispositions and
- when traps are run
-
-support/shobj-conf
- - slight changes to the darwin (Mac OS X) stanza for MacOS X 10.3
- (for the readline shared library builds, which shares this script)
-
-lib/readline/histexpand.c
- - change to make `^' behave as equivalent to word one, as csh does,
- and as the documentation states
-
-lib/readline/display.c
- - in update_line, make sure to use col_lendiff in all calculations
- where the cursor position is concerned (like when calculating
- the value of _rl_last_c_pos). Fixes bug reported by Andreas
- Schwab
-
- 11/12
- -----
-trap.c
- - make _run_trap_internal catch `return' builtin longjmps and clean
- up before longjmping on to where the return was intended to go
- (fixes bug with not turning off SIG_INPROGRESS flag when `return'
- executed in trap command)
-
- 11/18
- -----
-builtins/cd.def
- - in posix mode, set errno to ENOTDIR if canonicalization fails,
- unless the canonicalization functions leave it set to ENOENT
-
- 11/25
- -----
-make_cmd.c
- - in make_simple_command, don't blindly dereference element.redirect
-
-parse.y
- - the list_terminator production now has an `int' value so it can be
- used in other grammar productions
- - add a rule that makes `time' on a line by itself time a null
- command (this is iffy)
-
- 11/28
- -----
-subst.c
- - change the pattern substitution code (${var//pat/rep}) to use the
- same pattern expansion function (getpattern()) as the pattern
- removal expansions. This has the effect of no longer performing
- quote removal on the pattern before trying to match it. This
- fixes an incompatibility with ksh93 reported on comp.unix.shell
-
-nojobs.c
- - add replacement function for siginterrupt on the off chance that a
- system has posix signals but lacks siginterrrupt
-
-lib/readline/display.c
- - fix from Tim Waugh at Red Hat to speed up inserting characters into
- long lines in a UTF-8 environment by optimizing the calculation of
- the first difference between old and new lines by checking to see
- whether the old line is a subset of the new
-
- 11/29
- -----
-lib/malloc/stats.c
- - break code that opens file (and interprets %p) into separate function
- _imalloc_fopen(char *s, char *fn, char *def, char *defbuf, size_t defsiz)
- for use by rest of library
- - default stats file is now `stats.PID'
-
-lib/malloc/trace.c
- - new function, malloc_set_tracefn (char *s, char *fn), sets tracing
- to the file named by FN (with %p interpolated as the pid), using
- some default if FN is NULL
-
-lib/malloc/shmalloc.h
- - new extern declaration for malloc_set_tracefn
-
- 12/4
- ----
-execute_cmd.c
- - combined several common strings from do_piping() into one
- dup_error() function
-
-builtins/common.[ch]
- - new function, `sh_notbuiltin(s)' prints error message about s not
- being a shell builtin
-
-builtins/{builtin,enable}.def
- - call sh_notbuiltin instead of using literal string
-
-{arrayfunc,expr,error}.c
- - use one string variable for `bad array subscript' error message; use
- in calls to various error reporting functions
-
-Makefile.in
- - add variables for localedir and the PACKAGE_* variables, auto-set
- by configure
-
-configure.in
- - un-cache values for gettext, textdomain, and bindtextdomain if they're
- not in libc but in libintl so the right variables get set
-
-bashintl.h
- - add necessary defines for marking strings to be translated using
- gettext
-
-locale.c
- - set textdomain and directory in set_default_locale
- - don't call textdomain with the value of $TEXTDOMAIN, since we don't
- want to override the default domain ("bash")
- - don't call bindtextdomain unless default_domain already has a value
- - when translating $"..." strings, use dgettext with the script's
- default domain (value of $TEXTDOMAIN)
-
- 12/9
- ----
-builtins/mkbuiltins.c
- - include "bashintl.h" in the generated "builtins.c"
-
-support/{config.rpath,mkinstalldirs}
- - new files to support gettext i18n
-
-ABOUT-NLS
- - new readme file for gettext internationalization
-
-po/{Makefile.in.in,Rules-quot,boldquot.sed,en@boldquot.header,en@quot.header,insert-header.sin,quot.sed,remove-potcdate.sin}
-po/{POTFILES.in,bash.pot}
- - new files for gettext
-
-lib/intl
- - new directory, with libintl stuff from gettext
-
-aclocal.m4
- - add m4 files from gettext distribution needed by libintl
-
-configure.in
- - create po/Makefile.in and lib/intl/Makefile in AC_OUTPUT
- - add call to AM_GNU_GETTEXT to initialize gettext stuff
-
-Makefile.in
- - use mkinstalldirs instead of mkdirs in the `installdirs' target
- - changes for intl/ and po/ subdirectories in build and install
- - changes to have libintl linked in, as determined by configure
- - changes to have libintl built, just in case it's used (though I'd
- rather not)
-
- 12/10
- -----
-config.h.in
- - additional #defines required by the libintl library
- - add ENABLE_NLS define for AM_GNU_GETTEXT
- - take out defines for HAVE_{BINDTEXTDOMAIN,GETTEXT,TEXTDOMAIN}
-
-configure.in
- - removed old tests for libintl and gettext/textdomain/bindtextdomain
-
-locale.c
- - remove HAVE_GETTEXT code; we have gettext unconditionally now
-
-bashintl.h
- - change to include "gettext.h" and remove the conditional code based
- on whether or not gettext is present
-
- 12/16
- -----
-lib/readline/vi_mode.c
- - fix problem with rl_vi_eWord that caused it to skip over the last
- character of a word if invoked while point was on the next-to-last
- character
-
- 12/18
- -----
-{arrayfunc,bashhist,bashline,error,eval,execute_cmd,expr,general,input,jobs}.c
-{mailcheck,make_cmd,nojobs,pcomplete,pcomplib,print_cmd,redir,shell,sig}.c
-{subst,test,trap,variables,version,xmalloc}.c
-parse.y
-builtins/{common,evalfile,getopt}.c
-builtins/{bind,break,caller,cd,complete,declare,enable,exec,exit,fc,fg_bg}.def
-builtins/{hash,help,history,jobs,kill,printf,pushd,read,return,set,setattr}.def
-builtins/{shift,shopt,source,suspend,type,ulimit,umask}.def
-lib/sh/{fmtulong,netopen}.c
- - include "bashintl.h" for gettext defines
-
-Makefile.in
- - add `-DBUILDTOOL' to CFLAGS for buildversion.o
-
-bashintl.h
- - if `BUILDTOOL' is defined, define ENABLE_NLS to 0 so we don't have
- to compile and link in the gettext stuff
-
-Makefile.in,lib/sh/Makefile.in,builtins/Makefile.in
- - update dependencies on bashintl.h and include/gettext.h
-
- 12/19
- -----
-{arrayfunc,bashhist,bashline,error,eval,execute_cmd,expr,general,input,jobs}.c
-{mailcheck,make_cmd,nojobs,pcomplete,pcomplib,print_cmd,redir,shell,sig}.c
-{subst,test,trap,variables,version,xmalloc}.c
-builtins/{common,evalfile,getopt}.c
-builtins/{bind,break,caller,cd,complete,declare,enable,exec,exit,fc,fg_bg}.def
-builtins/{hash,help,history,jobs,kill,let,printf,pushd,read,return,set}.def
-builtins/{setattr,shift,shopt,source,suspend,type,ulimit,umask}.def
-lib/sh/{fmtulong,netopen}.c
-lib/malloc/{malloc,stats,table,watch}.c
- - mark up strings in source files for gettext processing
-
-lib/malloc/imalloc.h
- - include "bashintl.h" if SHELL is defined, otherwise make _(x) an
- identity define
-
-lib/malloc/Makefile.in
- - add dependencies on ${topdir}/bashintl.h and ${BASHINCDIR}/gettext.h
-
- 12/21
- -----
-bashline.c
- - make sure we index into rl_line_buffer with indexes > 0 in
- attempt_shell_completion
-
- 12/31
- -----
-Makefile.in
- - descend into `po' and run make recursively for the various clean
- targets
-
- 1/4
- ---
-include/shmbutil.h
- - two new macros: BACKUP_CHAR(str, strsize, i), which backs up one
- multibyte character in STR starting at index I, and
- BACKUP_CHAR_P(str, strsize, p), which backs up one multibyte
- character in STR starting at P, which is a char *
-
- 1/6
- ---
-pcomplete.c
- - in pcomp_filename_completion_function, use the quote character
- readline found (and assigned to rl_complete_quote_character) when
- dequoting the filename by a completion call from readline (when
- rl_dispatching != 0)
-
-bashline.c
- - ditto for bash_directory_completion_matches
-
- 1/7
- ---
-lib/readline/complete.c
- - new variable, rl_completion_found_quote, set to non-zero value if
- readline finds what it thinks is quoting in the word to be completed
-
-lib/readline/readline.h
- - extern declaration for rl_completion_found_quote
-
- 1/8
- ---
-lib/readline/doc/rltech.texi
- - documented rl_completion_found_quote
-
-lib/readline/complete.c
- - in compute_lcd_of_matches, if it looks like what the user typed was
- dequoted before generating filename matches, dequote the user's
- text again before figuring out the case-insensitive lcd
-
- 1/9
- ---
-lib/readline/display.c
- - fix from Edward Catmur <ed@catmur.co.uk> to logic that handles
- invisible characters in prompt string. Original code was wrong
- about local_prompt_prefix; it gave incorrect results when prompt
- contained invisible characters after a line break
-
- 1/10
- ----
-subst.c
- - new function, mb_substring(), does character (possibly multibyte)
- oriented rather than strictly byte-oriented substring extraction.
- The passed indices, rather than strictly indexing into the string,
- indicate character positions that need to be calculated. From
- Tim Waugh <twaugh@redhat.com>
- - change parameter_brace_substring to use mb_substring if necessary
-
-included/shmbutil.h
- - new define SADD_MBQCHAR_BODY, common code for adding a quoted
- (preceded by CTLESC) multibyte character to an accumulating string
- in the subst.c expansion code
-
-subst.c
- - use SADD_MBQCHAR_BODY in expand_word_internal
- - new static function, mb_getcharlens, allocates and returns an array
- of character lengths for (possibly multibyte) characters in the
- argument string
- - change pattern matching operations to use while loops instead of
- for loops to handle multibyte characters better (no more simple
- increment or decrement)
- - change pattern matching operations to use multibyte character
- operations instead of simple increments and decrements. Don't
- use BACKUP_CHAR_P -- use the mblen array instead, because that
- avoids the N**2 behavior of having to count from the beginning
- of the string each time you want to back up one character. Changes
- to remove_pattern and match_pattern
-
- 1/12
- ----
-lib/readline/display.c
- - make expand_prompt count multbyte characters in the prompt string
- by using _rl_find_next_mbchar (and copying possibly more than one
- byte) instead of a simple increment and single byte copy
-
- 1/13
- ----
-lib/readline/display.c
- - expand_prompt takes a new reference argument -- it returns
- the actual count of (possibly multibyte) characters displayed
- on the screen
- - don't short-circuit in expand_prompt unless we're not going to
- be using any multibyte characters
- - change calls to expand_prompt to pass an argument for the
- number of physical characters the prompt occupies
- (prompt_physical_chars)
- - initialize `lpos' (the physical cursor position) from
- prompt_physical_chars in rl_redisplay
-
-lib/readline/mbutil.c
- - in _rl_find_prev_mbchar_internal, if mbrtowc returns -1 or -2, and
- we assume that the character is a single-byte char, make sure we
- update `prev' so it doesn't get lost. Fixes problems encountered
- when a non-ascii char is the last char on the line and we're moving
- back past it with ^B, and other display problems caused by the same
- situation
-
- 1/15
- ----
-lib/readline/doc/rltech.texi
- - document RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE in the
- description of rl_expand_prompt()
-
- 1/20
- ----
-bashline.c
- - in initialize_readline, make sure M-C-j and M-C-m are still bound to
- vi-editing-mode before unbinding them -- they may have been rebound
- in an inputrc
-
-variables.c
- - in unbind_variable, unset attributes other than `local' and exported
- (if the variable came from a temporary environment) when unsetting a
- local variable inside a function
-
- 1/21
- ----
-configure.in
- - add libintl build directory to the list of include directories if
- it's being built (using INTL_BUILDDIR)
-
-Makefile.in,{builtins,lib/{sh,malloc}}/Makefile.in
- - substitute LIBBUILD as ${BUILD_DIR}/${LIBSUBDIR}
- - define INTL_BUILDDIR as ${LIBBUILD}/intl
-
-{builtins,lib/sh}/Makefile.in
- - make sure INTL_INC is added to the list of include directories
- - make sure INTL_LIBSRC is defined with the correct value
-
-{configure,Makefile,{builtins,lib/sh}/Makefile}.in
- - substitute LIBINTL_H as ${INTL_BUILDDIR}/libintl.h
-
-Makefile.in,builtins/Makefile.iin
- - all files depending on bashintl.h also depend on ${LIBINTL_H}
- (which may be empty)
-
-Makefile.in
- - make a rule telling how to build lib/intl/libintl.h if necessary
-
- 1/24
- ----
-builtins/read.def
- - make sure that the array name supplied as an argument to -a is a
- valid identifier
-
-parse.y
- - make the \W expansion abbreviate $HOME with a ~ (seems to be more
- useful)
-
-doc/{bash.1,bashref.texi}
- - document new behavior of \W
-
-subst.c
- - make sure parameter_brace_expand_rhs uses the first character of
- $IFS when making the string to return from the expanded word
- (which, in the case of "$@" or $@, contains multiple words that
- need to be separated)
-
- 1/25
- ----
-builtins/common.c
- - change get_job_spec to make `%' by itself or an empty argument
- return NO_JOB
-
-jobs.h
- - new possible value for a job spec return value: BAD_JOBSPEC
- (for syntactically invalid specs, like the empty string)
-
-shell.c
- - in open_shell_script, check to see whether or not we can find and
- open the filename argument before setting dollar_vars[0] or
- manipulating BASH_SOURCE, so the error messages come out better
-
-subst.c
- - in string_list_internal, short-circuit right away to savestring()
- if the list only has a single element
-
- 1/28
- ----
-lib/readline/rltypedefs.h
- - new set of typedefs for functions returning char * with various
- arguments (standard set)
-
-lib/readline/complete.c
- - new function pointer, rl_completion_word_break_hook, called by
- _rl_find_completion_word, used to set word break characters at
- completion time, allowing them to be position-based
-
-lib/readline/doc/rltech.texi
- - documented rl_completion_word_break_hook
-
-lib/readline/kill.c
- - added new rl_unix_filename_rubout, which deletes one filename
- component in a Unix pathname backward (delimiters are whitespace
- and `/')
-
-lib/readline/readline.h
- - extern declaration for rl_unix_filename_rubout
-
-lib/readline/funmap.c
- - new bindable readline command `unix-filename-rubout'
-
-lib/readline/doc/{readline.3,rluser.texi},doc/bash.1
- - documented `unix-filename-rubout'
-
- 1/29
- ----
-lib/readline/histexpand.c
- - change history_tokenize_internal to handle non-whitespace delimiter
- characters by creating separate fields (like the shell does when
- splitting on $IFS)
-
- 1/30
- ----
-lib/glob/xmbsrtowcs.c
- - new function, xdupmbstowcs, for convenience: calls xmbsrtowcs
- while allocating memory for the new wide character string
- - some small efficiency improvments to xmbsrtowcs
-
-include/shmbutil.h
- - extern declaration for xdupmbstowcs
-
-lib/glob/strmatch.h
- - include config.h for definition of HANDLE_MULTIBYTE
- - remove the HAVE_LIBC_FNM_EXTMATCH tests
- - new extern declaration for wcsmatch(whchar_t *, wchar_t *, int)
-
-configure.in
- - remove call to BASH_FUNC_FNMATCH_EXTMATCH; it's no longer used
-
-lib/glob/smatch.c
- - simplify xstrmatch() by using xdupmbstowcs() instead of inline code
-
-lib/glob/glob.c
- - modify mbskipname() to avoid the use of alloca
- - simplify mbskipname() by using xdupmbstowcs() instead of inline code
- - simplify glob_pattern_p() by using xdupmbstowcs() instead of
- inline code
- - fix memory leak in wdequote_pathname
- - simplify wdequote_pathname() by using xdupmbstowcs() instead of
- inline code
-
-lib/glob/strmatch.c
- - new function, wcsmatch(), `exported' wide-character equivalent of
- strmatch()
-
-subst.c
- - old match_pattern is now match_upattern
- - match_pattern now either calls match_upattern or converts
- mbstrings to wide chars and calls match_wpattern
- - match_upattern reverted to old non-multibyte code
- - new function: match_pattern_wchar, wide character version of
- match_pattern_char
-
- 2/1
- ---
-subst.c
- - old remove_pattern is now remove_upattern
- - remove_upattern reverted to old non-multibyte code (pre-Waugh patch)
- - new multibyte version of remove_pattern: remove_wpattern
- - remove_pattern now calls either remove_upattern or converts a
- multibyte string to a wide character string and calls
- remove_wpattern
- - new function, wcsdup, wide-character version of strdup(3)
-
- 2/4
- ---
-print_cmd.c
- - temporarily translate a >&filename redirection from
- r_duplicating_output_word to r_err_and_out (as the expansion code
- in redir.c does) so it prints without a leading `1' (file
- descriptor)
-
- 2/5
- ---
-aclocal.m4
- - add a check for wcsdup to BASH_CHECK_MULTIBYTE
-
-config.h.in
- - add HAVE_WCSDUP define
-
- 2/9
- ---
-builtins/shift.def
- - fix a call to sh_erange that possibly dereferences a NULL pointer
-
- 2/12
- ----
-general.c
- - start at a general set of file property checking functions:
- file_isdir(), file_iswdir() (is writable directory)
-
-general.h
- - extern declarations for new functions
-
-lib/sh/tmpfile.c
- - use file_iswdir() to make sure the temporary directory used for
- here documents and other temp files is writable in get_sys_tmpdir()
-
- 2/17
- ----
-bashline.c
- - fix conditional binding of emacs-mode M-~ -- there is a default
- binding for it (rl_tilde_expand), so a straight call to
- rl_bind_key_if_unbound_in_map doesn't do the right thing
-
- 2/27
- ----
-[bash-3.0-beta1 released]
-
- 2/29
- ----
-subst.c
- - fixed expansion so referencing $a, when a is an array variable
- without an element assigned to index 0, exits the shell when
- `-u' is enabled
-
-expr.c
- - make the exponentiation operator (**) associative, so things like
- 2**3**4 work right (change `if' to `while')
-
- 3/3
- ---
-lib/sh/strftime.c
- - SCO Unix 3.2, like Solaris, requires that the system's `timezone'
- variable be declared as long
-
-lib/readline/{bind,histfile,input,parens}.c
- - changes for Tandem (including `floss.h' (?))
-
- 3/4
- ---
-subst.c
- - change param_expand to quote the entire expanded string instead
- of just the escape characters if the expansion appears between
- double quotes or in a here-document (for simple variable expansions
- or expansions of positional parameters)
-
- 3/8
- ---
-subst.c
- - analogous changes to parameter_brace_expand_word to fix the same
- quoting problem as on 3/4; fix callers to understand that the
- value returned might be quoted now and should be dequoted if
- necessary
- - add a `quoted' argument to get_var_and_type, change callers
- - change today's fix and fix from 3/4 to not call quote_string if the
- value is "" (because quote_string turns that into CTLNUL\0)
-
- 3/9
- ---
-builtins/cd.def
- - resetpwd() now takes a `caller' argument so it can be used by pwd
- as well as cd
- - change pwd_builtin to call resetpwd() if sh_physpath() fails to
- return a valid pathname
-
- 3/14
- ----
-expr.c
- - reworked exp0 and readtok() to make post-increment and post-decrement
- into real tokens, which may be separated from their accompanying
- variables by whitesapce
- - made analogous changes to readtok() to make pre-increment and
- pre-decrement work when separated from their accompanying identifier
- by whitespace
-
- 3/18
- ----
-lib/readline/misc.c
- - in rl_maybe_unsave_line, don't force rl_replace_line to clear
- the undo_list, since it might point directly at an undo list
- from a history entry (to which we have no handle)
-
- 3/19
- ----
-lib/readline/display.c
- - rl_save_prompt and rl_restore_prompt now save and restore the value
- of prompt_physical_chars
- - set prompt_physical_chars in rl_redisplay when expand_prompt has
- not been called (e.g., when rl_display_prompt is set and is not
- equal to rl_prompt, like when searching)
-
-lib/readline/histexpand.c
- - don't call add_history in history_expand if the `:p' modifier is
- supplied; leave that to the calling application. This means that
- `history -p', for example, will not add anything to the history
- list (as documented), nor will history expansions invoked by
- emacs-mode M-C-e line editing
-
-config-bot.h
- - check whether HAVE_DECL_SYS_SIGLIST is defined to 1 rather than just
- defined, to work around newer versions of autoconf defining it to 0
-
-config.h.in
- - change default status of HAVE_MALLOC to #undef instead of #define
-
-bashhist.c
- - extern declarations for rl_done and rl_dispatching
- - don't call re_edit from pre_process_line unless rl_dispatcing is zero,
- so we don't call it from something like shell-expand-line
- - change pre_process_line to add an expanded history specification
- that returned `print only' to the history list, since history_expand
- no longer does it (and, when using readline, do it only when
- rl_dispatching is zero)
-
- 3/22
- ----
-config.h.in,aclocal.m4
- - change bash-specific functions that look in struct dirent to define
- HAVE_STRUCT_DIRENT_xxx, like AC_CHECK_MEMBERS does (though the
- functions are otherwise the same)
- - new function, BASH_STRUCT_DIRENT_D_NAMLEN, define
- HAVE_STRUCT_DIRENT_D_NAMLEN if struct dirent has a `d_namlen' member
-
-configure.in
- - call BASH_STRUCT_DIRENT_D_NAMLEN
-
-include/posixdir.h
- - use new and renamed HAVE_STRUCT_DIRENT_D_xxx defines
-
- 4/7
- ---
-builtins/cd.def
- - ensure that we print out a non-null pathname after getting a
- directory from CDPATH and canonicalizing it (e.g., if the result
- exceeds PATH_MAX in length and the_current_working_directory is
- set to NULL)
-
- 4/12
- ----
-print_cmd.c
- - new function to print out assignment statements when `set -x' has
- been enabled: xtrace_print_assignment
-
-externs.h
- - extern declaration for xtrace_print_assignment
-
- 4/13
- ----
-{subst,variables}.c
- - call xtrace_print_assignment instead of using inline code
-
-jobs.c
- - if turning on job control when it was previously off, set
- pipeline_pgrp to 0 in set_job_control so make_child puts
- subsequent children in their own process group
-
- 4/14
- ----
-general.c
- - new function, legal_alias_name, called to decide whether an
- argument to add_alias is a valid alias name -- essentially any
- character except one which must be quoted to the shell parser
- and `/'
-
-general.h
- - new extern declaration for legal_alias_name
-
-builtins/alias.def
- - `unalias' now returns failure status if no NAME arguments are
- supplied and -a is not given
- - call legal_alias_name to make sure alias name is valid before
- calling add_alias from alias_builtin
-
- 4/19
- ----
-include/shmbutil.h
- - include <config.h> for definition of HANDLE_MULTIBYTE rather than
- duplicating logic
-
- 4/20
- ----
-
-doc/{bash.1,bashref.texi}
- - make sure $0 is consistently referred to as a `special parameter'
- - document which characters are now not allowed in alias names
-
- 4/23
- ----
-
-builtins/{jobs,kill,wait}.def
- - removed requirement that job control be enabled to use job control
- notation, as SUSv3 implies
-
-subst.c
- - based on a message from David Korn, change param_expand to not call
- string_list_dollar_star if the only quoting is Q_HERE_DOCUMENT --
- quoted here documents are like double quoting, but not exactly
- - analogous changes to list_remove_pattern and pos_params
-
- 4/24
- ----
-lib/readline/doc/rluser.texi
- - fix error in description of emacs-mode C-xC-e command (uses $VISUAL
- instead of $FCEDIT)
-
- 4/28
- ----
-support/bashbug.sh
- - integrate a patch from Stefan Nordhausen
- <nordhaus@informatik.hu-berlin.de> that reduces race conditions
- by using a temporary directory inside $TMPDIR and creating the
- temp files in that
-
- 4/30
- ----
-builtins/common.c
- - use pathconf(".", _PC_PATH_MAX) where available to size the argument
- to getcwd() rather than using a straight PATH_MAX
-
-builtins/cd.def
- - if get_working_directory fails and returns null (causing resetpwd
- to return NULL), use set_working_directory to set $PWD to the
- absolute pathname for which chdir just succeeded
-
- 5/1
- ---
-lib/readline/vi_mode.c
- - in rl_vi_change_to, call _rl_vi_set_last with rl_numeric_arg instead
- of `last', since they're equal at call time and rl_vi_domove can
- change rl_numeric_arg (which vi apparently updates). Fixes redo bug
- of `c2....' reported by Marion Berryman <mwberryman@copper.net>
-
- 5/4
- ---
-parse.y
- - fix decode_prompt_string to properly deal with strftime() returning 0
-
- 5/6
- ---
-variables.c
- - in make_local_array_variable, return an already-existing local array
- variable immediately rather than creating a new array (causing a
- memory leak)
-
- 5/8
- ---
-lib/readline/vi_mode.c
- - change rl_vi_domove to set rl_explicit_arg before calling
- rl_digit_loop1 so that multi-digit numeric arguments work right
- - _rl_vi_last_command is no longer static
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_vi_last_command
-
-lib/readline/text.c
- - change rl_newline to only call _rl_vi_reset_last if the last command
- (_rl_vi_last_command) is not a text modification command. This lets
- the last-command and last-argument work across command lines
-
- 5/13
- ----
-builtins/common.c
- - use getcwd(0,0) rather than providing a fixed pathname with a fixed
- length (PATH_MAX) so getcwd() will allocate sufficient memory
-
-aclocal.m4
- - change BASH_FUNC_GETCWD to check whether or not getcwd(0,0) will
- allocate memory for the returned value -- nobody implements that
- and getcwd-via-popen, so it should capture the old test as well
-
- 5/27
- ----
-
-builtins/trap.def
- - the historical behavior of assuming that a signal's handling should
- be set to its original disposition is only in effect if a single
- argument is given, otherwise the first argument is assumed to be a
- command to execute
- - when in posix mode, if trap gets a single argument, display an
- error message and return EX_USAGE
- - change the help message and usage string to better explain trap's
- behavior
-
-doc/{bash.1,bashref.texi}
- - describe the new default behavior when the first argument is a
- signal spec
- - note that signal names are case insensitive and the SIG prefix is
- optional in arguments to `trap'
- - note that signal name arguments to `kill' are case-insensitive
-
-lib/readline/display.c
- - make sure rl_on_new_line_with_prompt sets rl_display_prompt to
- rl_prompt (just to make sure it's set)
- - have rl_on_new_line_with_prompt use local_prompt if it's set
-
- 6/2
- ---
-subst.c
- - in string_extract_double_quoted, cope with extract_delimited_string
- returning NULL, as it can when attempting completion on an unclosed
- command substitution
-
- 6/24
- ----
-lib/readline/complete.c
- - change print_filename to add a `/' to listed directory names if
- `mark-directories' has been enabled
-
-builtins/umask.def
- - make sure that the mask passed to parse_symbolic_mode has all but
- the operative low eight bits masked off, to avoid complementing
- all 0s to -1, which is the error return code. This makes things
- like `a=rwx' and `ugo=rwx' work and turn off the umask
-
- 6/26
- ----
-builtins/getopts.def
- - when `getopts' reaches the end of options, unset OPTARG before
- returning EOF. In response to a bug report from Apple
-
-configure.in
- - when cross-compiling, don't set CPPFLAGS_FOR_BUILD and
- LDFLAGS_FOR_BUILD from CPPFLAGS and LDFLAGS, respectively, since
- those are for the target instead of the build platform (report
- from robert@schwebel.de)
-
-shell.c
- - a shell whose standard error (but not standard output) is directed
- to a terminal should be interactive, according to POSIX/SUS. This
- means that sh > sh.out will start an interactive shell. Bug report
- from llattanzi@apple.com
-
-doc/{bash.1,bashref.texi}
- - change mention of standard output to standard error in definition
- of interactive shell
-
-lib/readline/vi_mode.c
- - new convenience function, rl_vi_start_inserting, calls
- _rl_vi_set_last to save the last textmod command state and then calls
- rl_vi_insertion_mode to enter insert mode
- - change functions to use rl_vi_start_inserting
-
-lib/readline/readline.h
- - extern declaration for rl_vi_start_inserting
-
-bashline.c
- - new function for vi-mode completion, bash_vi_complete. Does
- filename expansion as POSIX specifies, unlike the default readline
- bindings (which don't know about globbing). Bound to `\', `*',
- and `=' in vi command keymap. Internals very similar to
- rl_vi_complete; just calls bash glob expansion functions
-
-lib/readline/vi_mode.c
- - change rl_vi_change_char so that an entire change is a single
- undoable event, rather than each individual change in a [count]r
- command
- - fix rl_vi_change_char so that replacing characters up to EOL works
- rather than generating rl_ding
- - fix rl_vi_change_case so that replacing characters up to EOL works
- rather than generating rl_ding
-
- 6/28
- ----
-builtins/echo.def
- - call clearerr(stdout) before writing anything and testing its
- failure or success
-
- 6/29
- ----
-bashline.c
- - only set rl_explicit_arg in bash_glob_complete_word if readline is
- in emacs mode; let bash_vi_complete take care of setting it in vi
- mode
- - fix bash_vi_complete to only set rl_explicit_arg unless the posix
- conditions are met: no globbing characters in the vi `bigword'
- being completed
-
- 6/30
- ----
-[bash-3.0-rc1 released]
-
- 7/1
- ---
-lib/readline/complete.c
- - make sure `extension_char' is initialized before deciding whether
- or not the append a `/' to a possible completion when visible-stats
- is not enabled
-
- 7/2
- ---
-subst.c
- - fix a boundary overrun in string_extract_double_quoted that could
- occur when the word completion code attempts to expand an incomplete
- construct (like a quoted unclosed command substitution)
-
- 7/4
- ---
-subst.c
- - set tempenv_assign_error to non-zero if an assignment to the
- temporary environment fails for some reason (e.g., attempted
- assignment to a readonly variable)
-
-execute_cmd.c
- - fix execute_simple_command to force a non-interactive shell in
- POSIX mode to exit if an assignment to the temporary environment
- preceding a special builtin fails (bug report from
- llattanzi@apple.com)
-
- 7/5
- ---
-bashline.c
- - in bash_directory_completion_hook, don't perform word expansions
- if the filename appears to have been completed from the file
- system rather than typed in by the user. Bug reported by Tim
- Waugh <twaugh@redhat.com>
-
- 7/7
- ---
-lib/readline/misc.c
- - if _rl_maybe_save_line is being asked to save a line other than
- what's already saved, free up the current saved line and save the
- current contents of rl_line_buffer. Bug reported by
- llattanzi@apple.com
-
- 7/12
- ----
-lib/readline/input.c
- - do better EOF detection in rl_gather_tyi -- if a read returns 0 when
- the fd is in non-blocking mode, stuff an EOF into the input stream
- (reported by mattias@virtutech.se)
-
- 7/13
- ----
-lib/readline/vi_mode.c
- - make sure rl_vi_put honors `count' arguments and yanks things
- multiple times if requested
-
- 7/16
- ----
-builtins/umask.def
- - make sure that the `who' part of the umask symbolic mode argument
- defaults to `a' if it's missing
-
-flags.c
- - make sure that maybe_make_restricted only gets called after the
- shell is initialized, so `bash -r' doesn't result in inappropriate
- error messages
-
-[bash-3.0 frozen]
-
- 7/27
- ----
-doc/Makefile.in
- - small fixes
-
-[bash-3.0-released]
-
- 7/28
- ----
-array.c
- - in array_insert(), make sure the value to be added is non-NULL before
- calling savestring() on it
-
-builtins/reserved.def
- - fix description of `CDPATH'
-
-lib/readline/display.c
- - when expanding a prompt that spans multiple lines with embedded
- newlines, set prompt_physical_chars from the portion after the
- final newline, not the preceding portion. Bug reported by
- "Ralf S. Engelschall" <rse@engelschall.com>
-
-make_cmd.c
- - explicitly declare `lineno' in function prologue for make_case_command
-
-builtins/evalfile.c
- - include `trap.h' for declaration for run_return_trap
-
-bashline.c
- - fix a `return' without a value in enable_hostname_completion
-
-general.c
- - include test.h for extern declaration for test_eaccess
-
-externs.h
- - add declaration for zcatfd
-
-tests/{history,histexp}.tests
- - unset HISTFILESIZE to avoid problems if a value of 0 is inherited
- from the environment
-
- 7/30
- ----
-bashline.c
- - small changes to glob_expand_word to perform tilde expansion before
- attempting globbing
-
-builtins/Makefile.in
- - fix the install-help target to not cd into the `helpfiles'
- subdirectory, so a value of $INSTALL_DATA containing a relative
- pathname (e.g., .././support/install.sh) remains valid
-
- 7/31
- ----
-subst.c
- - new function, mbstrlen(s), returns length of a multibyte character
- string
-
-include/shmbutil.h
- - new macro, MB_STRLEN(s), calls mbstrlen or STRLEN as appropriate
-
-builtins/trap.def
- - small change so that a first argument that's a valid signal number
- (digits only -- no symbolic names) will be treated as a signal and
- reverted back to the original handling disposition. Fixes debian
- complaints
-
-subst.c
- - call MB_STRLEN instead of STRLEN where appropriate in
- parameter_brace_expand_length to handle multibyte characters properly
- - call MB_STRLEN instead of strlen in verify_substring_values so that
- negative substrings of strings with multibyte chars work properly
-
- 8/1
- ---
-jobs.c
- - describe_pid needs to write to stderr, not stdout (POSIX)
- - start_job, since it's only used by builtins (fg/bg), needs to write
- its output to stdout, not stderr (POSIX)
-
-sig.c
- - add an `orig_flags' member to struct terminating_signal so the
- original signal handling flags (SA_RESTART, etc.) can be preserved
- on POSIX systems
- - make sure to preserve the signal flags state in
- initialize_terminating_signals and reset them for child processes
- in reset_terminating_signals
-
-builtins/fc.def
- - fixed an off-by-one error that caused `fc -l' to list one too many
- history entries
- - in posix mode, `fc' should not list any indication as to whether or
- not history lines have been modified (POSIX)
- - when in posix mode, the default editor for `fc' should be `ed' (POSIX)
-
-doc/bashref.texi
- - updated the description of `trap' behavior when given a first
- argument that is a valid signal number
- - noted that `fc -l' won't indicate whether a history entry has been
- modified if the shell is in posix mode
-
-builtins/command.def
- - fixed bug: `command -v' is supposed to be silent if a command is not
- found
-
-builtins/hash.def
- - `hash' should print its `hash table empty' message to stderr
-
-lib/readline/misc.c
- - back out 7/7 change to _rl_maybe_save_line; it breaks emacs-mode ^P
-
-general.c
- - changed base_pathname so that it will return reasonable results for
- non-absolute pathnames -- this is what is intended by all of its
- callers
-
-arrayfunc.c
- - fix array_variable_part to return NULL if it finds an invisible
- variable in the hash table. Fixes seg fault caused by referring to
- unset local variable using array notation
-
-{locale,variables}.c
- - support LC_TIME as a special locale variable so HISTTIMEFORMAT tracks
- the current locale
-
- 8/2
- ---
-variables.c
- - fixed small memory leak in makunbound() when a local array variable
- is unset. Fix from William Park
-
-lib/readline/display.c
- - fixed a problem when computing the number of invisible characters on
- the first line of a prompt whose length exceeds the screen width
- (should only happen when invisible characters occur after the
- line wrap). Bug reported by agriffis@gentoo.org
-
-builtins/command.def
- - `command -V' passes a new flag, CDESC_ABSPATH, which means to convert
- to an absolute path
-
-builtins/type.def
- - in posix mode, `type' and `command -v/-V' should not report
- non-executable files, even if the execution code will attempt to
- run them. Other posix shells do this
-
-doc/bashref.texi
- - add note to POSIX Mode section describing behavior of type and command
- when finding a non-executable file
-
-execute_cmd.c
- - force extended_glob to 1 before calling binary_test in
- execute_cond_node so that the right extended pattern matching gets
- performed
-
- 8/3
- ---
-braces.c
- - make sure lhs[0] and rhs[0] are cast to `unsigned char' so chars
- with values > 128 are handled correctly
-
-builtins/printf.def
- - change bexpand() and printstr() to handle strings with a leading
- '\0' whose length is non-zero, since that's valid input for the
- `%b' format specifier
-
-subst.c
- - fix a couple of instances of find_variable that didn't check the
- result for an invisible variable
-
-variables.c
- - BASH_ARGC, BASH_ARGV, BASH_SOURCE, BASH_LINENO no longer created as
- invisible vars
-
-pcomplete.c
- - make sure COMP_WORDS is not invisible when bind_comp_words returns
- - ditto for COMPREPLY in gen_shell_function_matches
-
- 8/4
- ---
-braces.c
- - fix problem where ${ was ignored but did not increment the open
- brace count. Bug reported by Tim Waugh <twaugh@redhat.com>
-
-variables.c
- - if make_local_variable finds a variable in the correct context in
- the right variable scope, make sure it's not invisible before
- returning it
-
- 8/5
- ---
-builtins/trap.def
- - fixed usage message to show `action' as not optional, though it
- actually is when not in posix mode (for a single argument)
-
- 8/7
- ---
-configure.in
- - kfreebsd-gnu has had its sbrk() problems fixed, and no longer needs
- to be configured --without-gnu-malloc
-
-lib/readline/vi_mode.c
- - in rl_vi_search, free any saved history line before starting the
- search, so failure leaves you at that line, not the last line in
- the history (assuming the current line is not the last history line).
- Fix from llattanzi@apple.com to replace fix of 7/7
-
- 8/9
- ---
-support/Makefile.in
- - renamed `mostly-clean' target to `mostlyclean'
-
- 8/11
- ----
-lib/readline/vi_mode.c
- - make same change for EOL in multibyte character case of
- rl_vi_change_char
-
- 8/12
- ----
-subst.c
- - in verify_substring_values, fix off-by-one error checking bounds of
- `offset', esp. in array values (e.g., getting the highest element
- of an array)
-
- 8/16
- ----
-aclocal.m4
- - change BASH_CHECK_DEV_FD to make sure that file descriptors > 2 are
- accessible via /dev/fd, unlike FreeBSD 5.x
-
-lib/sh/strftime.c
- - make sure `zone' is initialized with gettimeofday before it is used
- - work around HPUX lack of `altzone' and differing definitions of
- `timezone'
-
-lib/malloc/malloc.c
- - internal_memalign and memalign now take a `size_t' as their first
- argument, which seems to be the prevailing standard
-
-lib/malloc/{malloc.c,shmalloc.h}
- - change sh_memalign to take a `size_t' as its first argument
-
-builtins/echo.def
- - if posixly_correct and xpg_echo are both set, don't try to interpret
- any arguments at all, as POSIX/XOPEN requires (fix inspired by Paul
- Eggert)
-
-doc/bashref.texi
- - amend description of bash posix mode to include new echo behavior
-
-builtins/fg_bg.def
- - allow bg to take multiple job arguments, as posix seems to specify,
- placing them all in the background, returning the status of the last
- one as the status of `bg'
-
-lib/readline/vi_mode
- - fix _rl_vi_change_mbchar_case (multibyte-char version of `~'
- command) to have the right behavior at EOL -- handle case where vi
- mode backs up at the end of the line
-
- 8/18
- ----
-array.c
- - check for an empty array in array_rshift before shifting elements
- and adjusting max_index
- - check for null array in array_subrange
-
-jobs.c
- - fix raw_job_exit_status to not ignore exit status of the last
- process in the pipeline when `set -o pipefail' is enabled
-
- 8/19
- ----
-lib/readline/mbutil.c
- - make sure _rl_find_next_mbchar_internal has a valid multibyte
- character before it checks whether or not it's a zero-width
- wide character and adjusts point accordingly
-
- 8/24
- ----
-bashline.c
- - new function, bash_directory_expansion, duplicates the expansions
- performed on the directory name by rl_filename_completion_function
- - call bash_directory_expansion in command_word_completion_function
- if we decide we're doing tilde expansion (and any other
- canonicalization) on the directory name being completed
-
- 8/25
- ----
-configure.in
- - use new-style AC_CHECK_HEADER to check for sys/ptem.h (which requires
- sys/stream.h). The correct checks are in the code, but autoconf
- complains if sys/stream.h is not included, rather than simply
- checking for the header's presence
-
- 8/26
- ----
-builtins/hash.def
- - fix a bug that prevented `hash -d' from working right (as soon as
- hash removed a command from the table, the bug caused it to be added
- right back)
-
- 8/27
- ----
-doc/{bash.1,bashref.texi}
- - explicitly note that conditional primaries that operate on files
- operate on the targets of symbolic links rather than the links
- themselves
-
- 8/30
- ----
-lib/readline/display.c
- - fix multibyte calculation of `physchars' in prompt expansion, to
- handle double-width multibyte characters correctly
- - changes to rl_redisplay to handle prompts longer than the screenwidth
- that might contain double-width multibyte characters. Fixes from
- Tomohiro Kubota
-
- 9/6
- ---
-subst.c
- - change word_list_split to avoid really bad behavior caused by calling
- list_append for each split word -- as the list gets long, you have
- to traverse it every time. Keep a pointer to the end of the list and
- and just tack onto it
-
- 9/8
- ---
-lib/readline/complete.c
- - change fnprint to calculate the displayed width of a filename in
- the same way as fnwidth
-
-subst.c
- - in verify_substring_values, when expanding ${array[@]:offset}, make
- sure negative offsets count from one greater than the array's
- maximum index so things like ${x[@}: -1} work to give the last element
- (requires fixing array tests)
-
-builtins/common.c
- - new error function, sh_wrerror(), for builtins to call when a write
- error occurs
-
-builtins/common.h
- - extern declaration for sh_wrerror()
-
-builtins/cd.def
- - change builtin_error call to use sh_wrerror()
-
-builtins/echo.def
- - report write errors with sh_wrerror() instead of just returning
- failure
-
-builtins/printf.def
- - change printstr to return failure (-1) or success (0) indication
- rather than void
- - report write errors when printstr() fails, return failure
- - if any of the PF/printf calls fail, report write error and return
- failure
-
-execute_cmd.c
- - change execute_in_subshell so the subshell command inherits the
- command timing flags from the enclosing COMMAND *
-
- 9/11
- ----
-[prayers for the victims of 9/11/2001]
-
-lib/sh/strnlen.c
- - new file, implementation of GNU libc extension function strnlen
-
-lib/sh/Makefile.in, {config.h,configure,Makefile}.in, MANIFEST
- - changes for strnlen
-
-configure.in
- - version changed to 3.1-devel
-
-doc/bash.1, lib/readline/doc/rluser.texi
- - added description of `-o plusdirs' to complete/compgen (thanks,
- Arnold)
-
-parse.y
- - new parser_state flag, PST_ASSIGNOK, if set indicates we're parsing
- arguments to a builtin that accepts assignment statement arguments
- - turn on PST_ASSIGNOK in read_token_word when appropriate
- - turn off PST_ASSIGNOK in read_token when appropriate
- - don't attempt to parse a compound assignment specially unless we're
- in a position where an assignment statement is acceptable, or
- PST_ASSIGNOK is set
-
- 9/13
- ----
-variables.c
- - make BASH_ARGC, BASH_ARGV, BASH_LINENO, and BASH_SOURCE
- non-unsettable, since the shell uses those values internally
-
-expr.c
- - make exponentiation right-associative, as is apparently correct
-
- 9/16
- ----
-arrayfunc.c
- - make sure convert_var_to_array marks the environment as needing
- recreation if the converted variable was exported
-
- 9/17
- ----
-braces.c
- - mark ${ as introducing an additional level of braces only if it's
- not in a quoted string -- quoted strings are handled before brace
- matching is done
-
-parse.y
- - fixed an obscure problem in history_delimiting_chars where the `in'
- in a case statement could have a semicolon added after it, if the
- `case word' was on a previous line
-
-support/config.guess
- - support for newest versions of tandem non-stop kernel
-
-lib/readline/display.c
- - in compute_lcd_of_matches, explicitly cast `text' to `char *' before
- passing it to rl_filename_dequoting_function
-
-lib/readline/terminal.c
- - bind the key sequence sent by the keypad `delete' key to delete-char
- (same as ^D in emacs mode)
-
-builtins/ulimit.def
- - in print_all_limits, don't print anything if get_limit returns
- -1/EINVAL, indicating that the kernel doesn't support that particular
- limit
- - add -i (max number of pending signals), -q (max size of posix msg
- queues), -x (max number of file locks) for systems (Linux) that
- support them
-
-doc/{bash.1,bashref.texi}
- - fix description of correspondence between FUNCNAME, BASH_LINENO,
- and BASH_SOURCE indices in description of BASH_LINENO
-
- 9/18
- ----
-lib/sh/shquote.c
- - don't quote CTLESC and CTLNUL with CTLESC in sh_backslash_quote, as
- long as the resultant string never gets sent to the word expansion
- functions without going through the shell parser
-
-externs.h
- - add extern declarations for strnlen and strpbkrk from lib/sh
-
-subst.[ch]
- - changes to handle case where IFS consists of multibyte characters.
- Changed: string_extract_verbatim, split_at_delims,
- string_list_dollar_star, string_list_dollar_at, list_string,
- get_word_from_string, setifs
-
- 9/19
- ----
-mailcheck.c
- - change file_mod_date_changed to reset the cached mail file data if
- the file size drops to zero
-
-lib/readline/complete.c
- - change append_to_match so that a non-zero value for
- rl_completion_suppress_append will cause no `/' to be appended to a
- directory name
-
-bashline.c
- - experimental change to suppress appending a slash for a completed
- filename that is found in PATH as well as a directory in the current
- directory under certain circumstances: a single instance found in
- $PATH when `.' is not in $PATH, and multiple instances found in the
- $PATH, even when `.' is in the $PATH
-
- 9/24
- ----
-command.h
- - new word flag: W_ASSIGNRHS, means word is rhs of assignment statement
- - new word flag: W_NOTILDE, means word is not to be tilde expanded
- - new word flag (internal): W_ITILDE, means the next character is a
- tilde that should be expanded
-
-general.c
- - new set of tilde suffixes for use when parsing the RHS of an
- assignment statement and =~ should not be subject to tilde expansion
- - if ASSIGN_P argument to bash_tilde_expand is 2, use tilde prefixes
- for parsing RHS of assignment statement
-
-general.[ch]
- - new function bash_tilde_find_word, drop-in replacement for
- tilde_find_word
-
-subst.c
- - call bash_tilde_expand with secord argument of 2 when expanding rhs
- of an assignment statement, so tildes after second and subsequent
- `=' in an assignment are not expanded
- - new function, expand_string_assignment, to expand the rhs of an
- assignment statement
- - add `~' to EXP_CHAR, the characters that will cause the word
- expansion functions to be called
- - move tilde expansion into expand_word_internal instead of many
- different calls to bash_tilde_expand scattered across different
- functions. NOTE: This means that double quotes surrounding a
- {paramOPword} expansion will cause tilde expansion to NOT be
- performed on `word'. I think this is right, what POSIX specifies,
- and consistent with the behavior of other characters in the rhs
-
-execute_cmd.c
- - take out calls to bash_tilde_expand before calling word expansion
- functions
-
- 9/26
- ----
-execute_cmd.c
- - make sure to call UNBLOCK_CHILD before returning on a pipe creation
- failure in execute_pipeline
-
- 9/27
- ----
-variables.c
- - change get_bash_command to deal with the_printed_command_except_trap
- being NULL
-
-execute_cmd.c
- - fix execute_simple_command to deal with the_printed_command being
- NULL when assigning to the_printed_command_except_trap -- fixes
- seg fault in savestring()
-
-parse.y
- - change the parser so that the closing `)' in a compound variable
- assignment delimits a token -- ksh93 does it this way
-
-doc/{bash.1,bashref.texi}
- - change description of tilde expansion to note that expansion is
- attempted only after the first =~ in an assignment statement
-
-builtins/declare.def
- - when assigning to an array variable with declare -a x=(...), make
- sure the last character in the rhs of the variable assignment is
- `)', not just that it appears somewhere
-
- 9/28
- ----
-command.h
- - add a `W_NOEXPAND' flag to inhibit all expansion except quote removal
- - add a `W_COMPASSIGN' flag to denote a word is a compound assignment
- statement
-
-parse.y
- - set W_COMPASSIGN on words that appear to be compound assignments
-
-subst.c
- - pass W_NOXPAND and W_COMPASSIGN through end of expand_word_internal
-
-subst.[ch]
- - new function, expand_assignment_string_to_string, calls
- expand_string_assignment and then string_list on the result
-
-variables.c
- - assign_in_env now calls expand_assignment_string_to_string
-
- 9/30
- ----
-builtins/common.c
- - change get_job_spec so the null job `%' once again means the current
- job
-
- 10/1
- ----
-subst.c
- - do_assignment_internal now takes a WORD_DESC * as its first
- argument, and uses its `word' member as the assignment string
- - change expand_word_list_internal to call do_word_assignment instead
- of do_assignment, passing it `word' instead of, e.g., `word->word'
- - change extract_array_assignment_list to just return the passed
- string minus a trailing `)' if the last character is a right
- paren
- - change do_assignment_internal to call extract_array_assignment_list
-
-subst.[ch]
- - change do_assignment and do_assignment_no_expand to take a `char *'
- instead of `const char *' first argument; change extern prototypes
- - new function, do_word_assignment, takes a WORD_DESC * and calls
- do_assignment_internal on it; add extern declaration with prototype
-
-general.h
- - new typedef, sh_wassign_func_t, like sh_assign_func_t but takes a
- WORD_DESC * as its first argument
-
-variables.[ch]
- - assign_in_env now takes a WORD_DESC * as its first argument
-
- 10/2
- ----
-command.h
- - new word flag, W_ASSNBLTIN, denotes that the word is a builtin
- command (in a command position) that takes assignment statements
- as arguments, like `declare'
- - new word flags, W_ASSIGNARG, denotes that word is an assignment
- statement given as argument to assignment builtin
-
-execute_cmd.c
- - set W_ASSNBLTIN flag in fix_assignment_words if necessary (if there
- are any arguments that are assignment statements)
- - set W_ASSIGNARG flag in fix_assignment_words if necessary
-
-subst.c
- - new function, do_compound_assignment, encapsulates the necessary
- code to perform a compound array assignment (including creation of
- local variables); called from do_assignment_internal
- - to fix the double-expansion problem with compound array assignments
- that are arguments to builtins like `declare', changed
- shell_expand_word_list to treat those arguments like assignment
- statements (with proper creation of local variables inside shell
- functions) and pass the attribute-setting portion of the statement
- onto the builtin. This is what ksh93 appears to do, from inspection
- of the `ksh93 -x' output
-
-execute_cmd.c
- - fix execute_simple_command: in case of pipeline or async command,
- when forking early, set `subshell_environment' so that it can contain
- both SUBSHELL_PIPE and SUBSHELL_ASYNC -- the two should not be
- mutually exclusive. Fixes bug reported by pierre.humblet@ieee.org
- - remove references to last_pid, old_command_subst_pid; use NO_PID as
- a sentinel value to decide whether or not a child process has been
- created and needs to be waited for. Submitted by
- pierre.humblet@ieee.org to fix recycling-pid problem on cygwin
-
-doc/{bash.1,bashref.texi}
- - fixed documentation of `@(pattern)' extended globbing operator --
- it succeeds if the string matches one of the patterns, not exactly
- one. This is what ksh93 does, too
-
-lib/readline/complete.c
- - fixed rl_menu_complete so that a negative argument cycles backwards
- through the list
-
- 10/3
- ----
-subst.c
- - use W_COMPASSIGN flag in do_assignment_internal instead of deciding
- lexically which assignments are compound array assignments
-
- 10/6
- ----
-support/shobj-conf
- - additions for System V.5 from Boyd Gerber <gerberb@zenez.com>
-
-subst.c
- - in command_substitute, if subshell_environment includes
- SUBSHELL_ASYNC, call make_child with the `async_p' argument set to
- non-zero. This keeps command substitutions for async commands or
- pipelines from trying to give the terminal back to the shell's
- pgrp. make sure to save and restore last_asynchronous_pid. Fix
- suggested by <pierre.humblet@ieee.org>
-
- 10/7
- ----
-config.h.in
- - add a placeholder definition for WCONTINUED_BROKEN
-
- 10/9
- ----
-aclocal.m4
- - add BASH_CHECK_WCONTINUED, checks for glibc bug where WCONTINUED is
- defined but rejected as invalid by waitpid(2)
-
-configure.in
- - add call to BASH_CHECK_WCONTINUED, defines WCONTINUED_BROKEN
-
-redir.c
- - experimental change to add_undo_redirect to save manipulations to
- file descriptors >= SHELL_FD_BASE (10) on the list of redirections
- to be undone even if `exec' causes the list to be discarded
-
-doc/{bash.1,bashref.texi}
- - note that redirections using file descriptors > 9 should be used
- carefully, because they might conflict with file descriptors the
- shell uses internally
-
- 10/11
- -----
-parse.y
- - fix pipeline_command production to handle case where `pipeline'
- as `argument' of `!' or `time' is null (e.g., a syntax error not
- handled by the grammar)
-
- 10/13
- -----
-lib/readline/readline.c
- - new internal variable, _rl_bind_stty_chars; if non-zero, bind the
- terminal special characters to readline equivalents at startup
- - change readline_default_bindings() and reset_default_bindings() to
- understand _rl_bind_stty_chars
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_bind_stty_chars
-
-lib/readline/rltty.c
- - change rl_prep_terminal to add support for _rl_bind_stty_chars
-
- 10/15
- -----
-lib/readline/bind.c
- - new bindable variable, `bind-tty-special-chars', bound to value of
- _rl_bind_stty_chars
-
-doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
- - documented new readline variable `bind-tty-special-chars'
-
-builtins/pushd.def
- - make the first check for option `--' skip the rest of option
- checking
-
- 10/16
- -----
-lib/readline/shell.c
- - change sh_set_lines_and_columns to prefer setenv, which has
- predictable memory allocation behavior, to putenv, which does not
-
- 10/19
- -----
-variables.c
- - change push_exported_var so that a tempenv variable has to have the
- export attribute set (which they all do -- something to look at) and
- the `propagate' attribute set to be propagated down to the next
- scope
-
-execute_cmd.c
- - change execute_builtin so that if CMD_COMMAND_BUILTIN is set in the
- passed flags argument, call pop_scope with a value that says the
- builtin is not special, since `command' means that preceding variable
- assignments don't persist in the environment. Fixes problem with
- variable assignments preceding command preceding special builtin
- keeping those variable assignments around (when in posix mode)
-
- 10/20
- -----
-lib/sh/shquote.c
- - new function, sh_mkdoublequoted, brackets a given string with
- double quotes and returns a new string. Flags argument, if non-
- zero, means to quote embedded double quotes with backslashes
-
-externs.h
- - new extern declaration for sh_mkdoublequoted
-
-parse.y
- - use sh_mkdoublequoted after calling localeexpand()
-
-lib/sh/strtrans.c
- - change ansicstr to understand that (flags & 4) != 0 means to remove
- backslash from unrecognized escape sequences
-
-general.c
- - fix logic problem in assignment() that caused non-variable-starter
- characters to be allowed, resulting in things like `1=xxx' creating
- a variable `1' in the hash table
-
- 10/21
- -----
-bashline.c
- - don't call programmable_completions with an assignment statement
- argument
-
- 10/22
- -----
-lib/readline/rltty.c
- - in prepare_terminal_settings, turn echoing on (readline_echoing_p)
- if get_tty_settings fails because the input is not a terminal
-
- 10/24
- -----
-lib/readline/util.c
- - include rlmbutil.h for multibyte definitions
- - new function, _rl_walphabetic, wide char version of rl_alphabetic
-
-lib/readline/mbutil.c
- - new function, _rl_char_value(buf, ind), returns value of (possibly
- multibyte) character at buf[ind]
-
-lib/readline/rlmbutil.h
- - extern defines for _rl_walphabetic and _rl_char_value for when
- multibyte chars are not being used
- - new wrapper definitions for _rl_find_next_mbchar (MB_NEXTCHAR) and
- _rl_find_prev_mbchar (MB_PREVCHAR) that try to avoid unneeded
- function calls
-
-lib/readline/text.c
- - fix rl_foward_word to work with multibyte characters (or in a
- multibyte locale) using above utility functions
- - fix rl_backward_word to work with multibyte characters (or in a
- multibyte locale) using above utility functions
-
- 10/26
- -----
-parse.y
- - fix parse_matched_pair so that it doesn't swallow \<newline> when
- parsing a $'...' construct (call shell_getc with different arg)
-
- 10/28
- -----
-lib/glob/glob.c
- - after some (compiled-in) threshold, glob_vector will stop using
- alloca to allocate `struct globval's and will switch to using
- malloc, with appropriate cleanup before returning
-
-subst.c
- - don't expand tildes after `=' in expand_word_internal, even if the
- W_TILDEEXP flag is set, unless it's the first tilde in a word
- marked W_ASSIGNMENT
-
- 10/31
- -----
-lib/readline/text.c
- - make sure rl_point doesn't go below 0 in rl_delete_horizontal_space
- (from SUSE, but not sent in)
-
-shell.c
- - make sure shell_is_restricted skips over a single leading `-' in
- the shell name (from SUSE, but not sent in)
-
-lib/readline/display.c
- - disable `fast redisplay' at the end of the line if in a locale that
- supports multibyte characters (from SUSE, but not sent in)
-
-lib/readline/histexpand.c
- - fix a problem with finding the delimiter of a `?' substring when
- compiled for multibyte characters (from SUSE, but not sent in)
-
- 11/1
- ----
-lib/readline/display.c
- - correct some assignments to _rl_last_c_pos: when in a multibyte
- locale, it's used as an absolute cursor position; when not using
- multibyte characters, it's a buffer offset. I should have caught
- this when the multibyte character support was donated
-
- 11/5
- ----
-general.c
- - change `assignment()' to accept `+=' assignment operator
-
-arrayfunc.[ch]
- - bind_array_variable and assign_array_element both take a new `flags'
- argument
- - assign_array_var_from_string, assign_array_from_string, and
- assign_array_var_from_word_list now all take a new `flags' argument
- - change assign_array_var_from_word_list to understand how to append
- to an array variable
- - change assign_array_var_from_string to understand how to append
- to an array variable. It does not unset the previous value if
- appending, allowing both old values to be changed and new ones to
- be added
-
-subst.h
- - new flag #defines to use for evaluating assignment statements
-
-{subst,variables}.c, builtins/{declare,read}.def
- - change callers of assign_array_element and bind_array_variable
- - change do_compound_assignment to understand assignment flags
- - change do_assignment_internal to set assignment flags and pass them
- to underlying functions
-
-pcomplete.c,builtins/{declare,read}.def
- - fix callers of assign_array_var_from_string, assign_array_var_from_word_list
-
-variables.[ch]
- - make_variable_value now takes a new `flags' argument
- - make_variable_value now understands how to append to a particular
- variable, using the old value
- - bind_variable_value now takes a new `flags' argument
- - change make_variable_value to understand ASS_APPEND flag
- - bind_variable now takes a new `flags' argument
- - bind_variable_internal now takes a new `flags' argument
-
-arrayfunc.c
- - change callers of make_variable_value to add flags arg
-
-builtins/declare.def
- - change callers of bind_variable_value to add flags arg
-
-{execute_cmd,mailcheck,pcomplete,shell,subst,variables}.c,parse.y
-builtins/{cd,command,declare,getopts,read,set,setattr}.def
- - change callers of bind_variable to add flags arg
-
-variables.c
- - change callers of bind_variable_internal
- - change bind_variable_internal to pass assignment flags on to
- make_variable_value
- - change assign_in_env to treat `var+=value' like `var=value'
-
-arrayfunc.c
- - break code that actually constructs the new value and assigns it
- to a particular array index out into a new functions:
- bind_array_var_internal. This fakes out make_variable_value by
- passing a dummy SHELL_VAR * so it can do proper appending and other
- += processing
- - changes to assign_array_var_from_string to accept and process as if
- they were `standalone' assignment statements array assignment words
- of the form [ind]+=val
-
- 11/7
- ----
-builtins/declare.def
- - added support for `declare [flags] var+=value'. `Flags' are applied
- before the assignment is performed, which has implications for things
- like `-i' -- if -i is supplied, arithmetic evaluation and increment
- will be performed
-
-builtins/setattr.def
- - add support for `+=' assignment for rest of `assignment builtins':
- export, readonly
-
- 11/12
- -----
-lib/readline/display.c
- - make sure prompt_physical_chars and prompt_invis_chars_first_line
- are reset to 0 if the prompt string passed to rl_expand_prompt is
- NULL or empty
-
- 11/14
- -----
-{configure,config.h}.in
- - check for `raise', define HAVE_RAISE if available
-
-lib/intl/dcigettext.c
- - make sure `raise' is defined if HAVE_RAISE is not before
- eval-plurah.h is included
-
-lib/malloc/trace.c
- - put extern declaration for imalloc_fopen inside the MALLOC_TRACE
- #ifdef
-
- 11/16
- -----
-lib/intl/Makefile.in
- - make sure SHELL is defined to cpp
-
-lib/intl/dcigettext.c
- - make sure we use getcwd() even if HAVE_GETCWD is not defined after
- including config.h; if SHELL is defined, #define HAVE_GETCWD
-
- 11/18
- -----
-trap.[ch]
- - new function, int signal_in_progress(int sig), returns TRUE if the
- trap handler for signal SIG is currently executing
-
- 11/19
- -----
-redir.c
- - slightly change do_redirection_internal to set the close-on-exec
- flag for file descriptors > 2 used to save file descriptors < 2
- using explicit redirections (e.g., `exec 3>&1'). This keeps file
- descriptors pointing to pipes from being left open but doesn't
- change the shell's file descriptor semantics
-
- 11/20
- -----
-doc/{bash.1,bashref.texi}
- - correct some minor typos, forwarded from doko@debian.org
-
- 11/22
- -----
-doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
- - documented detail that yank-last-arg and yank-nth-arg use the history
- arg expansion code (and, as a result, are subject to restrictions
- of the history-comment character)
-
- 11/23
- -----
-execute_cmd.c
- - changes so that BASH_COMMAND preserves its value into a DEBUG trap:
- for commands, arithmetic for command expressions, select commands,
- case commands, (( commands, [[ commands, simple commands
-
- 11/24
- -----
-doc/{bash.1,bashref.texi}
- - changed description of `set' builtin slightly so that it is clear
- that only variables are displayed in posix mode and that read-only
- variables can't be reset by simply sourcing the output of `set'
-
-lib/sh/strftime.c
- - don't try to redefine `inline' if it's already defined
-
- 11/26
- -----
-execute_cmd.c
- - fix execute_function to check funcname_a after function execution,
- since FUNCNAME can be changed or unset within a function
-
- 11/27
- -----
-builtins/evalfile.c
- - make same changes as 11/26, this time to _evalfile
-
-execute_cmd.c
- - change execute_function to run the return trap after a function
- completes execution even if the shell is compiled without DEBUGGER
- defined
-
-trap.c
- - change reset_or_restore_signal_handlers so that the RETURN trap is
- not inherited by command substitution when DEBUGGER is not defined
-
- 11/30
- -----
-lib/readline/misc.c
- - fix memory leaks in _rl_free_history_entry and rl_maybe_replace_line
- caused by not freeing `timestamp' member of history entry
- - make sure timestamp is initialized to NULL in rl_maybe_save_line
-
- 12/1
- ----
-execute_cmd.c
- - fix execute_function so a function calling `return' will run the
- RETURN trap, if one's defined
-
-doc/{bash.1,bashref.texi}
- - fix description of RETURN trap in various places to indicate that it's
- only inherited by shell functions if function tracing is on globally
- or has been enabled for that function
- - fix documentation to indicate that the DEBUG and RETURN traps are
- inherited under the same conditions
-
-execute_cmd.c
- - a function does not inherit the RETURN trap if a DEBUG trap is
- currently running
-
- 12/2
- ----
-lib/glob/xmbsrtowcs.c
- - change xmbsrtowcs to handle the one case where malloc can fail
- (though it should not matter) -- don't try to free a null pointer
-
- 12/9
- ----
-subst.c
- - fix get_var_and_type to handle var[@], where `var' is a scalar
- variable, identically to var -- all calling expansions can now
- handle var[@] like var. Bug reported by agriffis@gentoo.org
-
- 12/10
- -----
-lib/readline/bind.c
- - make new-style "\M-x" keybindings obey `convert-meta' settings
- (bug reported by twaugh@redhat.com)
-
- 12/14
- -----
-builtins/set.def
- - added description of `-' option to help text
-
-builtins/shopt.def
- - fix bug that caused `gnu_errfmt' to not be compiled in unless
- READLINE is defined
-
- 12/16
- -----
-subst.c
- - fixed a typo in string_extract_verbatim in first call to MBLEN
- (used `slen - 1' instead of `slen - i')
-
- 12/17
- -----
-subst.c
- - avoid some calls to strlen if the value is only being used for
- ADVANCE_CHAR and MB_CUR_MAX == 1 (since ADVANCE_CHAR doesn't need
- it unless multibyte characters are possible)
- - change string_extract_verbatim so it takes the length of the string
- as a parameter, so we don't have to recompute the length of the same
- string over and over again when doing word splitting (that kills if
- it's a long string)
-
- 12/18
- -----
-subst.c
- - in string_list_dollar_star, make sure to null-terminate the
- separator if the character is longer than one byte
-
- 12/22
- -----
-doc/{bash.1,bashref.texi}
- - changed text in quoting section explaining that double quotes do
- not prevent history expansion from taking place, and that backslashes
- escaping ! are not removed
-
- 12/28
- -----
-shell.c
- - set gnu_error_format to 1 if running under emacs. This should allow
- the emacs `next-error' stuff to work, at least for interactive shells
-
-parse.y
- - change yy_stream_get to set interrupt_immediately before calling
- getc_with_restart when the shell is interactive. This avoids the
- synchronization problem caused by the call to QUIT in read_a_line,
- which results in the first character after a SIGINT/^C to be
- dropped
-
- 12/30
- -----
-builtins/mkbuiltins.c
- - changes to write long documentation to arrays as a single string by
- default, rather than an array of strings -- enabled by default
- - new option, -S, to restore old behavior of writing multiple strings
- for long documentation
- - changes to avoid filenames written when the separate-filenames option
- (-H) has been supplied being run through gettext
-
-configure.in
- - new cofiguration option, --enable-single-help-strings (on by default),
- causes help text to be stored as a single string (or smaller set than
- one string per line)
-
-builtins/Makefile.in
- - pass `-S' to mkbuiltins if single-help-strings is turned off
-
-doc/bashref.texi
- - documented new `single-help-strings' configure option
-
- 1/3/2005
- --------
-jobs.c
- - make wait_for return a non-zero status if the job or processed
- waited for is suspended. Returns 128 + stop signal. This fixes
- the problem with `echo one && sleep 5 && echo two' displaying
- `two' after the sleep is suspended
-
- 1/5
- ---
-print_cmd.c
- - change indirection_level_string so the code duplicates the first
- character of $PS4 to indicate the indirection level, rather than
- the first byte
-
- 1/8
- ---
-variables.c
- - new special variable hook function for COMP_WORDBREAKS; sets
- rl_completer_word_break_characters back to NULL when the variable
- is unset
- - change bind_variable_value to understand dynamic variables with
- assign_function set, and handle them correctly. If the variable is
- being appended to, use make_variable_value to create the new
- value
- - change bind_variable_internal to understand dynamic variables with
- assign_function set, and handle them the same way
- - RANDOM and LINENO now get the integer attribute, so appending works
- as expected
- - ditto for HISTCMD, MAILCHECK, OPTIND
-
-lib/readline/display.c
- - change _rl_make_prompt_for_search to set prompt_physical_chars
- appropriately
- - rl_save_prompt and rl_restore_prompt save and restore
- prompt_prefix_length
- - change redraw_prompt to use rl_save_prompt and rl_restore_prompt
- - change rl_restore_prompt to set the `save' variables back to
- NULL/0 so code can check whether or not the prompt has been saved
- - change rl_message and rl_clear_message to save and restore the
- prompt if the caller has not already done it (using a simple
- semaphore-like variable)
- - change rl_message to call expand_prompt, so that local_prompt and
- local_prompt prefix are set before calling the redisplay functions,
- in case the prompt is longer than a screenwidth (fixes bug
- reported to debian by epl@unimelb.edu.au)
-
-lib/readline/doc/rltech.texi
- - make sure to note that rl_save_prompt should be called before
- rl_message, and rl_restore_prompt before rl_clear_message
-
-pcomplete.c
- - make sure to save and restore the parser state around the call to
- execute_shell_function in gen_shell_function_matches. Fixes bug
- reported by a050106.1.keeLae3x@captaincrumb.com (cute)
-
-lib/readline/readline.c
- - fix _rl_dispatch_subseq in the case where we're recursing back up
- the chain (r == -2) and we encounter a key shadowed by a keymap,
- but originally bound to self-insert. Calling rl_dispatch with
- ANYOTHERKEY as the first argument will call rl_insert, but with
- ANYOTHERKEY (256) as the char to insert. Use the shadow keymap
- and set things up to dispatch to rl_insert with the shadowed key
- as the argument. Fixes the bug reported by Thomas Glanzmann
- (sithglan@stud.uni-erlangen.de)
-
- 1/13
- ----
-command.h
- - new word flag: W_HASQUOTEDNULL
-
-make_cmd.c
- - new function to allocate a WORD_DESC * without doing anything with a
- containing string: alloc_word_desc
-
-make_cmd.h
- - extern declaration for alloc_word_desc
-
-dispose_cmd.c
- - new function to just free a WORD_DESC * without freeing the contained
- string: dispose_word_desc
-
-dispose_cmd.h
- - extern declaration for dispose_word_desc
-
-subst.c
- - change some places to use alloc_word_desc
- - make same changes to word_list_quote_removal as were made to
- word_list_split
- - set W_HASQUOTEDNULL when a word is created with w->word[0] ==
- CTLNUL and w->word[1] == '\0'
-
-subst.c
- - parameter_brace_expand_word now returns a WORD_DESC * -- changed
- callers to understand
- - parameter_brace_expand_indir now returns a WORD_DESC * -- changed
- callers to understand
- - parameter_brace_expand_rhs now returns a WORD_DESC * -- changed
- callers to understand
- - remove W_HASQUOTEDNULL from a word's flags when remove_quoted_nulls
- is called on the word's enclosed string
-
- 1/15
- ----
-subst.c
- - param_expand now returns a WORD_DESC * -- changed callers to
- understand
- - parameter_brace_expand now returns a WORD_DESC * -- changed
- callers to understand
- - in expand_word_internal, only call remove_quoted_nulls after a word
- is returned with W_HASQUOTEDNULL
- - changes to pass W_HASQUOTEDNULL flag out of expand_word_internal;
- changed callers to call remove_quoted_nulls only if return value has
- W_HASQUOTEDNULL set. This is a mostly-complete fix for the
- long-standing CTLNUL confusion between a quoted null expansion and
- the expansion of a variable with a literal '\177' in its value
- - change string_list_dollar_at to compute the separator character the
- same way as string_list_dollar_star: using the already-computed
- values generated in setifs()
- - when expanding unquoted $*, if $IFS is empty, check whether or not
- we're eventually going to split the results (e.g., on the rhs of an
- assignment statement) and concatenate the positional parameters as
- if the expansion were within double quotes if we're not going to
- split
-
-tests/iquote.tests
- - test cases based on old bug reports about the quoted-null vs. 0177
- problem the recent code fixes
-
- 1/16
- ----
-dispose_cmd.c
- - set w->word to 0 before putting a WORD_DESC * back in the cache in
- dispose_word_desc; changed callers to delete those assignments
-
-variables.c
- - change assign_random and get_random_value so that the random number
- generator only gets re-seeded once in a subshell environment, and
- assigning a value to RANDOM counts as seeding the generator. This
- makes the sequences a little more predictable
-
- 1/20
- ----
-lib/readline/history.c
- - fix replace_history_entry, remove_history to return NULL if
- passed index is < 0
-
- 1/22
- ----
-lib/sh/netconn.c
- - fix isnetconn() to understand that getpeername can return ENOTCONN
- to indicate that an fd is not a socket
-
-configure.in
- - set BUILD_DIR to contain backslashes to escape any spaces in the
- directory name -- this is what make will accept in targets and
- prerequisites, so it's better than trying to use double quotes
- - set SIZE to the appropriate value if some cross-compiling tool
- chain is being used; `size' by default (can be overridden by
- SIZE environment variable)
-
-Makefile.in
- - use $(SIZE) instead of size; set SIZE from configure
-
- 1/31
- ----
-arrayfunc.c
- - in array_value_internal, return NULL right away if the variable's
- value is NULL, instead of passing a null string to add_string_to_list
-
- 2/1
- ---
-jobs.h
- - new struct to hold stats and counters for child processes and jobs
- - change some uses of global and static variables to use members of
- new struct (struct jobstats)
-
- 2/2
- ---
-
-jobs.[ch]
- - change PRUNNING to PALIVE
- - new define INVALID_JOB
- - new macro get_job_by_jid(ind), currently expands to jobs[ind]
- - new define J_JOBSTATE, operates on a JOB * like JOBSTATE operates on
- a job index
- - new function, reset_job_indices, called from delete_job if
- js.j_lastj or js.j_firstj are removed
- - change various functions to keep counters and stats in struct jobstats
-
-pcomplete.c, builtins/common.c, builtins/{exit,fg_bg,jobs,kill,wait}.def
- - change global variables (e.g., job_slots) to struct members
- (e.g., js.j_jobslots)
- - use INVALID_JOB define where appropriate
- - use get_job_by_jid and J_JOBSTATE where appropriate
-
-trap.c
- - change reset_or_restore_signal_handler to not free the exit trap
- string if the function pointer is reset_signal, which is used when
- the trap strings shouldn't be freed, like in command substitution
-
- 2/4
- ---
-jobs.c
- - new function, realloc_jobs_list, copies jobs array to newly-allocated
- memory shrinking (or growing) size to have next multiple of JOB_SLOTS
- greater than js.j_njobs
- - change compact_jobs_list to just call reap_dead_jobs and then
- realloc_jobs_list, simplifying it considerably
- - discard_pipeline now returns `int': the number of processes freed
- - slightly changed the logic deciding whether or not to call
- compact_jobs_list: now non-interactive shells will compact the
- list if it reaches MAX_JOBS_IN_ARRAY in size
-
-parse.y
- - move test for backslash-newline after pop_string in shell_getc so
- that things like
-
- ((echo 5) \
- (echo 6))
-
- work right
-
- 2/8
- ---
-jobs.h
- - new structs for holding status of exited background processes, as
- POSIX specifies
- - new job flag: J_ASYNC
-
-jobs.c
- - new functions to manipulate struct holding status of exited
- background processes
- - new members in struct jobstats to hold pointer to last created job
- and last created asynchronous job
- - initialize js.c_childmax in initialize_job_control
- - if the `async' arg to stop_pipeline is non-null, set the J_ASYNC
- flag in the job struct
- - set js.j_last_made_job and js.j_last_asynchronous_job in
- stop_pipeline
- - new function: find_last_proc, returns the PROCESS * to the last proc
- in a job's pipeline
- - changed find_last_pid to call find_last_proc
- - change delete_job to call bgp_add on the last proc of the job being
- deleted
- - change delete_all_jobs and wait_for_background_pids to call bgp_clear
-
- 2/9
- ---
-jobs.c
- - change wait_for_single_pid to look for pid in bgpids.list (using
- bgp_search()) if find_pipeline returns NULL
-
- 2/10
- ----
-support/shobj-conf
- - change the solaris-gcc stanza so that it auto-selects the appropriate
- options for ld depending on which `ld' gcc says it's going to run
-
- 2/11
- ----
-jobs.h
- - add support for PS_RECYCLED as a process state, add PRECYCLED macro
- to test it. Change PALIVE and PRUNNING macros to not count processes
- in PS_RECYCLED state
-
-execute_cmd.c
- - restore use of last_pid as sentinel value; use NO_PID as sentinel
- only if RECYCLES_PIDS is defined
-
-jobs.c
- - change find_job to return a pointer to the PROCESS the desired pid
- belongs to, analogous to find_pipeline returning pointer to JOB
- - change find_job callers to add extra argument
- - change running_only arguments to find_pipeline and find_job to
- alive_only, since we don't want recycled pids returned here and it
- better describes the result
- - new function find_process, calls find_pipeline and searches the
- returned pipeline for the PROCESS * describing the desired pid
- - in make_child, if fork() returns the same pid as the value of
- last_asynchronous_pid when RECYCLES_PIDS is defined, avoid pid
- aliasing by resetting last_asynchronous_pid to 1
- - use PRUNNING instead of child->running, since we, for the most
- part, don't want to consider recycled pids (e.g., in make_child())
- - call find_process instead of find_pipeline in waitchld()
- - use PEXITED(p) instead of testing p->running == PS_DONE
- - in make_child, call bgp_delete to remove a just-created pid from the
- last of saved pid statuses
- - in add_process, check whether or not pid being added is already in
- the_pipeline or the jobs list (using find_process) and mark it as
- recycled if so
- - This set of fixes mostly came from Pierre Humblet
- <pierre.humblet@ieee.org> to fix pid aliasing and reuse problems on
- cygwin
-
-variables.c
- - set $_ from the environment if we get it there, set to $0 by
- default if not in env
-
-doc/{bashref.texi,bash.1}
- - a couple of clarifying changes to the description of $_ based on
- comments from Glenn Morris <gmorris+mail@ast.cam.ac.uk>
-
- 2/15
- ----
-shell.c
- - use strstr instead of strmatch when checking whether $EMACS contains
- `term' -- simpler and faster
-
- 2/18
- ----
-builtins/cd.def
- - implement posix requirement that `pwd -P' set $PWD to a directory
- name containing no symlinks
- - add new function, setpwd(), just sets (and changes exported value)
- of PWD
-
-doc/bashref.texi
- - add note to posix mode section about pwd -P setting $PWD
-
-doc{bash.1,bashref.texi}
- - added note that BASH_ARGC and BASH_ARGV are only set in extended
- debug mode
- - expand description of extdebug option to include everything changed
- by extended debug mode
-
- 2/19
- ----
-pathexp.h
- - new flag macro, FNMATCH_IGNCASE, evaluates to FNM_CASEFOLD if the
- match_ignore_case variable is non-zero
-
-execute_cmd.c
- - new variable, match_ignore_case
- - change call to strmatch() in execute_case_command so it includes
- FNMATCH_IGNCASE
-
-test.c
- - change call to strmatch() in patcomp() so that pattern matching
- calls for [[ ... ]] obey the match_ignore_case variable
-
-lib/sh/shmatch.c
- - if match_ignore_case is set, enable REG_ICASE in the regexp match
- flags
-
-builtins/shopt.def
- - new settable option, `nocasematch', controls the match_ignore_case
- variable. Currently alters pattern matching for case and [[ ... ]]
- commands (==, !=, and =~ operators)
-
-doc/{bashref.texi,bash.1}
- - updated descriptions of [[ and case to include reference to
- nocasematch option
-
- 2/22
- ----
-builtins/mkbuiltins.c
- - add `times' to the list of posix special builtins
-
- 2/23
- ----
-builtins/cd.def
- - posix mode no longer turns on effect of -P option on $PWD if a
- directory is chosen from CDPATH
-
-doc/bashref.texi
- - clarified that in posix mode, reserved words are not alias expanded
- only in a reserved word context
- - removed item about cd, $CDPATH, and -P from posix mode section
-
- 2/24
- ----
-builtins/reserved.def
- - minor cleanups to the description of `if'
-
- 3/2
- ---
-subst.c
- - change list_string and get_word_from_string to explicitly treat an
- IFS character that is not space, tab, or newline *and any adjacent
- IFS white space* as a single delimiter, as SUSv3/XPG6 says
-
-builtins/read.def
- - check whether or not the number of fields is exactly the same as
- the number of variables instead of just assigning the rest of the
- line (minus any trailing IFS white space) to the last variable.
- This parses a field and checks whether or not it consumes all of
- the input (including any trailing field delimiters), falling back
- to the previous behavior if it does not. This is what POSIX.2
- specifies, I believe (and the consensus of the austin-group list).
- This requires a few tests in read.tests to be changed: backslashes
- escaping IFS whitespace characters at the end of input cause the
- whitespace characters to be preserved in the value assigned to the
- variable, and the trailing non-whitespace field delimiter issue
-
- 3/7
- ---
-configure.in
- - add -D_POSIX_SOURCE to the LOCAL_CFLAGS for Interix
-
- 3/8
- ---
-bashline.c
- - make bash_directory_expansion a void function, since it doesn't have
- any return value
-
- 3/9
- ---
-builtins/read.def
- - when testing for a pipe, use `fd' instead of hard-coding 0, since we
- can read from other file descriptors now
-
-lib/sh/zread.c
- - in zsyncfd, only set lind and lused to 0 if the lseek succeeds.
- If the lseek fails, we might steal input from other programs, but
- a failed lseek won't cause us to erroneously discard input
-
- 3/11
- ----
-builtins/evalstring.c
- - don't allow parse_and_execute to short-circuit and call exec() if
- the command's return value is being inverted
-
- 3/15
- ----
-builtins/printf.def
- - new macro PC to call putchar and increment number of chars printed -
- fixes bug in computation of value for %n format char
- - `tw' is now a global var so printstr can modify it using PC()
- - convert PF macro to use asprintf into a local buffer
- Preparation for printf -v var
- - add code to add the text printed to a `variable buffer' if -v option
- supplied. The buffer grows as needed
- - printf now takes a `-v var' option to put the output into the variable
- VAR rather than sending it to stdout. It does not:
- print partial output on error (e.g., format string error)
- handle NULs in the variable value, as usual
-
- 3/16
- ----
-parse.y
- - fix bug in prompt string decoding that caused a core dump when PS1
- contained \W and PWD was unset (null pointer deref)
-
-builtins/printf.def
- - changed -v var behavior so it stores partial output into the named
- variable upon an error
-
- 3/24
- ----
-lib/readline/bind.c
- - bool_to_int now takes a `const char *' argument
-
-support/{printenv,recho,zecho}.c
- - include config.h
- - include "bashansi.h" for appropriate extern function declarations
-
-configure.in
- - on MacOS X 10.4, compensate for loader not allowing static library
- to override existing system dynamic library when compiling -dynamic
- (affects readline and history libraries); so use absolute pathname
- instead of -lreadline as library name
-
-lib/glob/{glob,sm_loop,smatch}.c
- - make sure to cast arguments to (char *) or (unsigned char *) as
- appropriate to avoid gcc4 warnings
-
-lib/glob/smatch.c
- - collsym (single-byte version) now takes a (CHAR *) first argument to
- match callers; cast argument to strncmp appropriately
-
-lib/sh/snprintf.c
- - fix ldfallback and dfallback to handle width and precision specs in
- the format passed to sprintf()
- - fix STAR_ARGS macro to deal with negative field widths and precisions
-
- 3/25
- ----
-builtins/printf.def
- - since a negative precision in a "x.x[fFgGeE]" format specifier should
- be allowed but treated as if the precision were missing, let it
- through
-
-lib/sh/snprintf.c
- - fix * code to deal with a negative precision by treating it as if
- the `.' and any digit string in the precision had not been specified
- - fix format parsing code to deal with a negative inline precision,
- e.g., "%4.-4f" by treating it as if the `'. and any digit string in
- the precision had not been specified
- - a `+' in a format specifier should only act as a flag if it comes
- before a `.' (otherwise it is ignored)
-
-lib/readline/vi_mode.c
- - new function, rl_vi_rubout, to rl_rubout as rl_vi_delete is to
- rl_delete; saves deleted text for possible reinsertion as with any
- vi-mode `text modification' command (fixes problem with `X' reported
- by beat.wieland@gmx.ch)
-
-lib/readline/vi_keymap.c
- - bind `X' in vi command mode to rl_vi_rubout
-
-lib/readline/funmap.c
- - add a bindable `vi-rubout' command, runs rl_vi_rubout
-
-lib/readline/text.c
- - rewrote internals of _rl_rubout_char to make structure cleaner
-
-lib/readline/{complete,text}.c
- - changed code to remove #ifdef HANDLE_MULTIBYTE where possible
-
- 3/28
- ----
-lib/readline/examples/rl.c
- - include <sys/stat.h> instead of posixstat.h if READLINE_LIBRARY not
- defined
-
-subst.c
- - fix mbstrlen to treat invalid multibyte sequences as sequences of
- single-byte characters
-
- 4/8
- ---
-configure.in
- - default SIZE to `:' if cross-compiling and an appropriate size for
- the target is not found
-
- 4/11
- ----
-subst.c
- - change match_upattern and match_wpattern to check whether or not the
- supplied pattern matches anywhere in the supplied string, prefixing
- and appending the pattern with `*' if necessary. If it doesn't we
- can short-circuit immediately rather than waste time doing up to
- N-1 unsuccessful calls to strmatch/wcsmatch (which kills for long
- strings, even if the pattern is short)
-
- 4/12
- ----
-configure.in
- - make sure the special case for MacOS X 10.4 only kicks in if the
- `--with-installed-readline' option isn't supplied
-
-lib/readline/{callback,readline,signals}.c
- - make sure rl_prep_term_function and rl_deprep_term_function aren't
- dereferenced if NULL (as the documentation says)
-
-builtins/mkbuiltins.c
- - don't bother with the special HAVE_BCOPY code; just use straight
- assignments
-
-builtins/ulimit.def
- - use _POSIX_PIPE_BUF in pipesize() if it's defined and PIPE_BUF is
- not
-
- 4/13
- ----
-execute_cmd.c
- - add cm_function_def to the list of control structures for which
- child processes are forked when pipes come in or out
-
- 4/14
- ----
-builtins/read.def
- - make sure the ^As added for internal quoting are not counted as
- characters read when -n is supplied
-
- 4/20
- ----
-redir.c
- - fix redir_open so that the repeat open on failure that AFS support
- adds restores the correct value of errno for any error message
-
- 4/26
- ----
-
-Makefile.in
- - make sure mksignames and mksyntax are invoked with the $(EXEEXT)
- extension
-
- 4/28
- ----
-lib/readline/readline.h
- - new state variable: RL_STATE_CALLBACK, means readline is using the
- callback interface
-
-lib/readline/callback.c
- - set RL_STATE_CALLBACK in rl_callback_handler_install, unset in
- rl_callback_handler_remove
-
- 4/29
- ----
-config-top.h
- - DONT_REPORT_SIGPIPE is now on by default, since it apparently
- interferes with scripts
-
-configure.in
- - arrange things so PGRP_PIPE is defined on Linux-2.4+ and version 3
- kernels (ones that apparently schedule children to run before their
- parent)
-
- 4/30
- ----
-builtins/caller.def
- - add call to no_options, so it can handle `--' option
-
-doc/{bash.1,bashref.texi}
- - note explicitly that test, :, true, and false don't understand --
- as meaning the end of options
-
- 5/7
- ---
-support/shobj-conf
- - darwin 8 needs the same LDFLAGS setting as darwin 7
-
-parse.y
- - in save_parser_state, make sure we cast the return value from
- xmalloc() to the right type
- - remove casts to (char *) in calls to yyerror()
-
-lib/readline/signals.c
- - make SIGQUIT and SIGALRM code conditional on their definition
- - use raise() to send a signal if we don't have kill()
-
-lib/readline/display.c
- - some MS-DOS and MINGW changes from the cygwin and mingw folks
-
-config.h.in
- - add HAVE_PWD_H for <pwd.h>
- - add HAVE_FCNTL, HAVE_KILL for respective system calls
- - add HAVE_GETPW{ENT,NAM,UID} for passwd functions
-
-configure.in
- - add check for <pwd.h>
- - add checks for fcntl, kill system calls
- - add checks for getpw{ent,nam,uid} C library functions
- - pass a flag indicating we're cross compiling through to
- CFLAGS_FOR_BUILD in Makefile.in
-
-lib/readline/complete.c
- - guard inclusion of <pwd.h> with HAVE_PWD_H
- - don't provide a missing declaration for getpwent if we don't have it
- - guard calls to {get,end}pwent with HAVE_GETPWENT
-
-lib/readline/shell.c
- - guard inclusion of <pwd.h> with HAVE_PWD_H
- - guard inclusion of <fcntl.h> with HAVE_FCNTL_H
- - don't provide a missing declaration for getpwuid if we don't have it
- - guard calls to getpwuid with HAVE_GETPWUID
- - don't bother with body of sh_unset_nodelay_mode if we don't have
- fcntl
-
-lib/tilde/tilde.c
- - guard inclusion of <pwd.h> with HAVE_PWD_H
- - guard calls to getpw{nam,uid} with HAVE_GETPW{NAM,UID}
- - guard calls to {get,end}pwent with HAVE_GETPWENT
-
-Makefile.in,builtins/Makefile.in
- - @CROSS_COMPILE@ is substituted into CFLAGS_FOR_BUILD (equal to
- -DCROSS_COMPILING if bash is being cross-compiled)
-
- 5/9
- ---
-aclocal.m4
- - print version as `0.0' in RL_LIB_READLINE_VERSION if the
- `rl_gnu_readline_p' variable isn't 1 (accept no imitations)
-
- 5/11
- ----
-lib/readline/rlprivate.h
- - definition of a readline `search context', to be use for incremental
- search initially and other types of search later. Original from
- Bob Rossi as part of work on incremental searching problems when
- using callback interface
-
-lib/readline/isearch.c
- - functions to allocate and free search contexts
- - function to take a search context and a character just read and
- `dispatch' on it: change search parameters, add to search string,
- search further, etc.
- - isearch is now completely context-driven: a search context is
- allocated and passed to the rest of the functions
-
- 5/12
- ----
-lib/readline/isearch.c
- - an additional `isearch cleanup' function that can be called from
- the callback interface functions when the search is to be terminated
- - an additional `isearch callback' function that can be called from
- rl_callback_read_char when input is available
- - short-circuit from rl_search_history after initialization if
- the callback interface is being used
-
-lib/readline/callback.c
- - in rl_callback_read_char(), if RL_STATE_ISEARCH is set, call
- _rl_isearch_callback to read the character and dispatch on it.
- If RL_STATE_ISEARCH is unset when that call returns, and there is
- input pending, call rl_callback_read_char() again so we don't
- have to wait for new input to pick it up
-
-support/shobj-conf,configure.in
- - add support for dragonfly bsd, the same as freebsd
-
- 5/13-5/15
- ---------
-lib/readline/callback.c
- - support for readline functions to `register' a function that will
- be called when more input is available, with a generic data
- structure to encapsulate the arguments and parameters. Primarily
- intended for functions that read a single additional character,
- like quoted-insert
- - support for callback code reading numeric arguments in a loop,
- using readline state and an auxiliary variable
- - support for callback code performing non-incremental searches using
- the same search context struct as the isearch code
-
-lib/readline/{callback,display}.c
- - if a callback function sets `_rl_redisplay_wanted', the redisplay
- function will be called as soon as it returns
-
-lib/readline/input.c
- - changes to _rl_read_mbchar to handle reading the null multibyte
- character and translating it into '\0'
-
-lib/readline/misc.c
- - break rl_digit_loop() into component functions that can be called
- individually from the callback code more easily
- - share some of the functions with rl_digit_loop1() in vi_mode.c
-
-lib/readline/readline.h
- - change the version #defines to reflect readline 5.1
-
-lib/readline/search.c
- - break code into smaller functions that can be composed to work with
- the callback code more easily
-
-lib/readline/text.c
- - in rl_quoted_insert(), don't mess around with the tty signals if
- running in `callback mode'
-
-lib/readline/vi_mode.c
- - changed set-mark, goto-mark, change-char, and char-search to work
- when called by callback functions
-
- 5/17
- ----
-
-lib/readline/rlprivate.h
- - new struct declaration for a `reading key sequence' context
-
-lib/readline/readline.c
- - new variable, _rl_dispatching_keymap, keeps track of which keymap
- we are currently searching
- - functions to allocate and deallocate contexts for reading multi-char
- key sequences
-
- 5/18
- ----
-lib/readline/rlprivate.h
- - new struct defining a context for multiple-key key sequences (the
- base case is escape-prefixed commands)
-
-lib/readline/readline.c
- - change structure of _rl_dispatch_subseq to allow for callback code
- to use it - rudimentary support for supporting the existing
- recursion using a stack of contexts, each with a reference to the
- previous
- - fix so that ^G works when in callback mode
-
-lib/readline/callback.c
- - call the appropriate multiple-key sequence callback if the state is
- set
-
- 5/19
- ----
-lib/readline/readline.c
- - broke code from _readline_internal_char after call to rl_dispatch
- out into separate function: _rl_internal_char_cleanup, callable by
- other parts of the code
- - change _rl_internal_char_cleanup to unset _rl_want_redisplay after
- it calls (*rl_redisplay_func)
-
-lib/readline/callback.c
- - call _rl_internal_char_cleanup from rl_callback_read_char when
- appropriate
-
- 5/24
- ----
-lib/readline/callback.c
- - use _rl_dispatch_callback and a chain of _rl_keyseq_contexts to
- simulate the recursion used to decode multicharacter key sequences
- (even things like ESC- as meta-prefix)
- - call setjmp in rl_callback_read_char to give things like rl_abort
- a place to jump, since the saved location in readline() will not
- be valid
- - keep calling _rl_dispatch_callback from rl_callback_read_char while
- we are still decoding a multi-key key sequence
- - keep calling readline_internal_char from rl_callback_read_char while
- we are reading characters from a macro
-
-lib/readline/macro.c
- - use a slightly different strategy upon encountering the end of a macro
- when using the callback interface: when the last character of a
- macro is read, and we are reading a command, pop the macro off the
- stack immediately so the loop in rl_callback_read_char terminates
- when it should
-
-lib/readline/readline.c
- - if longjmp() is called and we end up at the saved location while
- using the callback interface, just return -- don't go back into a
- blocking read
- - new function to dispose a chain of rl_keyseq_cxts
- - only read new input in _rl_dispatch_callback if the KSEQ_DISPATCHED
- flag is not set in the current keyseq context -- if it is, we are
- traversing the chain back up and should use what we already saved
- - use -3 as a magic value from _rl_dispatch_subseq to indicate that
- we're allocating a new context and moving downward in the chain
- (a special return value for the benefit of _rl_dispatch_callback)
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_keyseq_chain_dispose
-
- 6/1
- ---
-builtins/read.def
- - fixed a bug that occurred when reading a set number of chars and
- the nth char is a backslash (read one too many). Bug reported by
- Chris Morgan <chmorgan@gmail.com>
-
-execute_cmd.c
- - fix execute_builtin so the `unset' builtin also operates on the
- temporary environment in POSIX mode (as well as source and eval),
- so that unsetting variables in the temporary environment doesn't
- leave them set when unset completes. Report by Eric Blake
- <ebb9@byu.net>
-
-array.c
- - fix from William Park for array_rshift when shifting right on an
- empty array -- corrects calculation of array->max_index
-
-builtins/exec.def
- - if an exec fails and the execfail option is set, don't call
- restart_job_control unless the shell is interactive or job_control
- is set
-
-jobs.c
- - add a run-time check for WCONTINUED being defined in header files
- but rejected with EINVAL by waitpid(). Fix from Maciej Rozycki
- <macro@linux-mips.org>
-
- 6/20
- ----
-bashhist.c
- - make sure calls to sv_histchars are protected by #ifdef BANG_HISTORY
- - ditto for calls to history_expand_line_internal
-
- 6/23
- ----
-doc/bashref.texi
- - remove extra blank lines in @menu constructs
-
-variables.c
- - assign export_env to environ (extern char **) every time it changes
- (mostly in add_to_export_env define), so maybe getenv will work on
- systems that don't allow it to be replaced
-
- 6/29
- ----
-bashline.c
- - in bash_directory_completion_hook, be careful about not turning `/'
- into `//' and `//' into `///' for benefit of those systems that treat
- `//' as some sort of `network root'. Fix from Eric Blake
- <ebb9@byu.net>
-
-lib/readline/complete.c
- - in to_print, do the right thing after stripping the trailing slash
- from full_pathname: // doesn't turn into /, and /// doesn't become
- //. Fix from Eric Blake <ebb9@byu.net>
-
- 6/30
- ----
-lib/malloc/trace.c
- - include <unistd.h> if it's available for a definition of size_t
-
-jobs.c
- - in wait_for, if a child process is marked as running but waitpid()
- returns -1/ECHILD (e.g., when the bash process is being traced by
- strace), make sure to increment c_reaped when marking the child as
- dead
- - in without_job_control, make sure to close the pgrp pipe after
- calling start_pipeline
-
- 7/1
- ---
-Makefile.in
- - only remove pathnames.h when the other files created by running
- configure are removed (e.g., Makefile). Fix from William Park
-
-lib/sh/shquote.c
- - since backslash-newline disappears when within double quotes, don't
- add a backslash in front of a newline in sh_double_quote. Problem
- reported by William Park
-
-jobs.c
- - in notify_of_job_status, don't print status messages about
- terminated background processes unless job control is active
-
-bashhist.c
- - new variable, hist_last_line_pushed, set to 0 in really_add_history
- (used by `history -s' code)
-
-bashhist.h
- - new extern declaration for history -s
-
-builtins/history.def
- - don't remove last history entry in push_history if it was added by
- a call to push_history -- use hist_last_line_pushed as a sentinel
- and set it after adding history entry. This allows multiple
- calls to history -s to work right: adding all lines to the history
- rather than deleting all but the last. Bug reported by Matthias
- Schniedermeyer <ms@citd.de>
- - pay attention to hist_last_line_pushed in expand_and_print_history()
- so we don't delete an entry pushed by history -s
-
- 7/4
- ---
-print_cmd.c
- - fix print_arith_for_command to not print so many blanks between
- expressions in ((...))
-
-command.h
- - new word flag: W_DQUOTE. Means word should be treated as if double
- quoted
-
-make_cmd.c
- - add W_DQUOTE to word flags in make_arith_for_expr
-
-parse.y
- - add W_DQUOTE to word flags for (( ... )) arithmetic commands
-
-subst.c
- - don't perform tilde expansion on a word with W_DQUOTE flag set
- - don't perform process substitution on a word with W_DQUOTE flag set
-
-arrayfunc.c
- - expand an array index within [...] the same way as an arithmetic
- expansion between (( ... ))
-
-lib/readline/input.c
- - use getch() instead of read() on mingw
-
-lib/readline/readline.c
- - add a few key bindings for the arrow keys on mingw
-
-lib/readline/rldefs.h
- - if on mingw, define NO_TTY_DRIVER
-
-lib/readline/rltty.c
- - compile in the stub functions for _rl_{disable,restore}_tty_signals
- if on mingw
- - compile in stub function for rl_restart_output on mingw
- - make sure enough functions and macros are defined to compile if
- NO_TTY_DRIVER is defined (lightly tested - builds on MacOS X, at
- least)
-
- 7/7
- ---
-command.h
- - add a `flags' member to the PATTERN_LIST structure
-
-make_cmd.c
- - intialize the `flags' member of a PATTERN_LIST when it's created
-
-builtins/psize.c
- - protect extern declaration of errno with usual #ifdef errno
-
-configure.in, variables.c
- - changes for QNX 6.x
-
- 7/9
- ---
-parse.y
- - fix parse_matched_pair to handle single and double quoted strings
- inside old-style command substitution (``) since they can each
- quote the ` and embedded $-expansions. Report by Eric Blake
- <ebb9@byu.net>
-
-{configure,Makefile}.in
- - TILDE_LIB is now substituted into Makefile by configure
-
-configure.in
- - if configuring --with-installed-readline on cygwin, set TILDE_LIB
- to the empty string to avoid multiply-defined symbols. Cygwin
- doesn't allow undefined symbols in dynamic libraries. Report by
- Eric Blake <ebb9@byu.net>
-
- 7/11
- ----
-input.c
- - in duplicate_buffered_stream, don't call free_buffered_stream if the
- two buffered streams share the same b_buffer object (e.g., if they
- had already been duplicated with a previous call). Fixes Debian bug
- reported by eero17@bigfoot.com
-
- 7/12
- ----
-shell.c
- - make set_shell_name more resistant to a NULL argument
- - in bind_args, use < instead of != when counting the arguments and
- making the arg list
- - in main(), make sure arg_index is not initialized to a value greater
- than argc
-
- 7/14
- ----
-lib/readline/display.c
- - in expand_prompt, don't set the location of the last invisible
- char if the sequence is zero length (\[\])
-
- 7/15
- ----
-doc/{bash.1,bashref.texi}
- - document that the shell uses $TMPDIR when creating temporary files
-
- 7/20
- ----
-[bash-3.1-alpha1 frozen]
-
- 7/29
- ----
-builtins/evalstring.c
- - make sure that parse_and_execute saves and restores the value of
- loop_level, so loops in sourced scripts and eval'd strings don't
- mess up the shell's parser state
-
-bashline.c
- - change command_subst_completion_function to suppress appending
- any character to a unique completion, instead of a space, unless
- the last word in the quoted command substitution completes to a
- directory name. In that case we append the expected slash
-
- 8/1
- ---
-builtins/printf.def
- - make sure variables are initialized if their values are tested later
-
-[bash-3.1-alpha1 updated and re-frozen]
-
- 8/2
- ---
-variables.c
- - make sure to call stifle_history with an `int' instead of an intmax_t.
- Sometimes it makes a difference
-
- 8/3
- ---
-[bash-3.1-alpha1 released]
-
-support/mksignames.c
- - add `SIGSTKFLT' (RHE3)
- - add `SIGXRES' (Solaris 9)
-
- 8/4
- ---
-builtins/ulimit.def
- - fix typo to make `x' the right option for locks
- - add new options to short help synopsis
-
-variables.c
- - use get_variable_value instead of direct reference to value_cell
- in make_variable_value when appending to the current value, so
- references to array variables without subscripts will be equivalent
- to element 0
-
-lib/readline/text.c
- - rewrote rl_change_case to correctly change the case of multibyte
- characters where appropriate
-
- 8/5
- ---
-configure.in
- - remove call to obsolete macro AC_ACVERSION
- - remove special calls to AC_CYGWIN and AC_MINGW32; AC_CANONICAL_HOST
- takes care of those cases
-
-general.h
- - include `chartypes.h' for definition of ISALPHA
- - fix definitions of ABSPATH and RELPATH for cygwin
- - fix definition of ISDIRSEP for cygwin to allow backslash as a
- directory name separator
-
- 8/9
- ---
-builtins/setattr.def
- - when setting a variable from the temporary environment in
- set_var_attribute (e.g., `LC_ALL=C export LC_ALL'), make sure to
- call stupidly_hack_special_variables after binding the variable in
- the current context
-
-builtins/printf.def
- - make sure to call stupidly_hack_special_variables if using `printf -v'
- to put formatted output in a shell variable
-
- 8/11
- ----
-support/shobj-conf
- - new variable: SHLIB_LIBPREF, prefix for shared library name (defaults
- to `lib'
- - new variable: SHLIB_DLLVERSION, used on Cygwin to set the library
- version number
- - new variable: SHLIB_DOT, separator character between library name and
- suffix and version information (defaults to `.')
- - new stanza for cygwin to generate windows-compatible dll
-
- 8/14
- ----
-variables.c
- - new special variable function for Cygwin, so the export environment
- is remade when HOME is changed. The environment is the only way to
- get information from the shell to cygwin dlls, for instanace, when
- bash is compiled to use an already-installed libreadline
-
-variables.h
- - new extern declaration for sv_home
-
- 8/15
- ----
-lib/readline/display.c
- - call init_line_structures from rl_redisplay if vis_lbreaks == 0
- to avoid consequences of a poorly-timed SIGWINCH
-
- 8/16
- ----
-subst.c
- - fix logic for performing tilde expansion when in posix mode (don't
- rely on W_TILDEEXP flag always being set, because it won't be when
- expanding the RHS of assignment statement). Use W_TILDEEXP only
- when deciding to expand a word marked as W_ASSIGNMENT that doesn't
- precede a command name
-
- 8/17
- ----
-execute_cmd.c
- - in execute_function, when subshell == 1, don't short-cut by using
- the command contained in the group command -- if you do, any
- redirections attached to the group command (function) don't get
- executed
-
-general.h
- - new #define, FS_READABLE, indicates file is readable by current
- user
-
-findcmd.c
- - rewrote file_status to use S_xxx POSIX file mode bits and to add
- support for FS_READABLE (affects ./source and searching $PATH for
- scripts whose names are supplied as arguments on the command line)
- - change find_path_file to look for readable files -- source requires
- it
- - change find_in_path_element to do the right thing when FS_READABLE
- is supplied as a flag
-
-doc/bashref.texi
- - remove note about posix non-compliance in `.': we now require and
- look for readable files when searching $PATH
-
- 8/20
- ----
-subst.c
- - fix setifs to handle case where passed variable is non-zero but
- v->value == 0 (as in an unset local variable); treat IFS as unset
- in this case
-
-jobs.c
- - in kill_pid, if asked to killpg a process or pgrp whose pgrp is
- recorded as the same as the shell's, just call killpg and let the
- chips fall where they may -- there may be other processes in that
- pgrp that are not children of the shell, so killing each process
- in the pipeline will not do a complete job, and killpg'ing each
- such process will send too many signals in the majority of cases
-
-builtins/cd.def
- - in posix mode, pwd needs to check that the value it prints and `.'
- are the same file
-
-builtins/read.def
- - if reading input from stdin in a non-interactive shell and calling
- `read', call sync_buffered_stream to seek backward in the input
- stream if necessary (XXX - should we do this for all shell builtins?)
-
- 8/23
- ----
-builtins/cd.def
- - in posix mode, if canonicalization of the absolute pathname fails
- because the path length exceeds PATH_MAX, but the length of the passed
- (non-absolute) pathname does not, attempt the chdir, just as when
- not in posix mode
-
-builtins/type.def
- - don't have describe_command call sh_makepath if the full path found
- is already an absolute pathname (sh_makepath will stick $PWD onto the
- front of it)
-
- 8/24
- ----
-
-jobs.c
- - in posix mode, don't have start_job print out and indication of
- whether the job started by `bg' is the current or previous job
- - change start_job to return success if a job to be resumed in the
- background is already running. This means that bg won't fail when
- asked to bg a background job, as SUSv3/XPG6 requires
- - new function, init_job_stats, to zero out the global jobstats struct
-
-{jobs,nojobs}.c
- - change kill_pid to handle pids < -1 by killing process groups
-
-jobs.h
- - extern declaration for init_job_stats
-
-lib/readline/history.c
- - check whether or not the history list is null in remove_history
-
-builtins/history.def
- - delete_last_history is no longer static so fc builtin can use it
-
-builtins/fc.def
- - use free_history_entry in fc_replhist instead of freeing struct
- members individually
- - call delete_last_history from fc_replhist instead of using inline
- code
- - if editing (-l not specified), make sure the fc command that caused
- the editing is removed from the history list, as POSIX specifies
-
-builtins/kill.def
- - just call kill_pid with any pid argument and let it handle pids < -1
- This is the only way to let kill_pid know whether a negative pid or
- a job spec was supplied as an argument to kill
-
-builtins/fg_bg.def
- - force fg_bg to return EXECUTION_SUCCESS explicitly if called by bg
- and start_job returns successfully
- - bg now returns success only if all the specified jobs were resumed
- successfully
-
-execute_cmd.c
- - call init_job_stats from initialize_subshell to zero out the global
- job stats structure
-
- 8/25
- ----
-bashline.c
- - change vi_edit_and_execute_command to just call vi when in posix
- mode, instead of checking $FCEDIT and $EDITOR
-
-lib/readline/search.c
- - if in vi_mode, call rl_free_undo_list in make_history_line_current
- to dispose of undo list accumulated while reading the search string
- (if this isn't done, since vi mode leaves the current history
- position at the entry which matched the search, the call to
- rl_revert_line in rl_internal_teardown will mangle the matched
- history entry using a bogus rl_undo_list)
- - call rl_free_undo_list after reading a non-incremental search string
- into rl_line_buffer -- that undo list should be discarded
-
-lib/readline/rlprivate.h
- - add UNDO_LIST * member to search context struct
-
-lib/readline/isearch.c
- - initialize UNDO_LIST *save_undo_list member of search context struct
-
- 8/27
- ----
-lib/readline/bind.c
- - change rl_parse_and_bind to strip whitespace from the end of a
- variable value assignment before calling rl_variable_bind
-
-doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
- - clarified the language concerning parsing values for boolean
- variables in assignment statements
-
- 8/28
- ----
-lib/sh/pathphys.c
- - fix small memory leak in sh_realpath reported by Eric Blake
-
- 8/31
- ----
-doc/bashref.texi
- - add additional notes to posix mode section
-
- 9/3
- ---
-parse.y
- - if $'...' occurs within a ${...} parameter expansion within
- double quotes, don't single-quote the expanded result -- the double
- quotes will cause it to be expanded incorrectly
-
- 9/4
- ---
-builtins/fc.def
- - if STRICT_POSIX is defined, the posix mode default for the editor to
- use is $FCEDIT, then ed
-
-shell.c
- - if STRICT_POSIX is defined, initialize `posixly_correct' to 1
-
-config.h.in
- - add #undef STRICT_POSIX
-
- 9/5
- ---
-configure.in
- - add new option argument, --enable-strict-posix-default, configures
- bash to be posix-conformant (including defaulting echo to posix
- conformance) by default
-
-builtins/echo.def
- - if STRICT_POSIX is defined, default echo to xpg-style
-
-doc/bashref.texi
- - describe the --enable-strict-posix-default option to configure
-
- 9/10
- ----
-builtins/mkbuiltins.c
- - change to not generate N_(""), because the translated empty string is
- special to GNU gettext
-
- 9/13
- ----
-lib/readline/complete.c
- - a negative value for rl_completion_query_items means to not ask
-
-lib/readline/doc/{{rltech,rluser}.texi,readline.3}
- - documented new semantics for rl_completion_query_items/
- completion-query-items
-
- 9/14
- ----
-bashline.c
- - bind M-TAB in emacs mode to dynamic-complete-history even if the
- current binding is `tab-insert' (which is what it is by default),
- not just if it's unbound
-
- 9/15
- ----
-eval.c
- - call QUIT before calling dispose_command on current_command after
- the `exec_done' label. If we dispose current_command first, the
- longjmp might restore the value of current_command after we've
- disposed it, and the subsequent call to dispose_command from the
- DISCARD case will free memory twice
-
- 9/16
- ----
-lib/sh/strto[iu]max.c
- - make sure the function being declared is not a cpp define before
- defining it -- should fix problems on HP-UX
-
- 9/19
- ----
-Makefile.in
- - make sure the binaries for the tests are at the front of $PATH
-
- 9/22
- ----
-parse.y
- - new flag for parse_matched_pair: P_COMMAND, indicating that the
- text being parsed is a command (`...`, $(...))
- - change calls to parse_matched_pair to include P_COMMAND where
- appropriate
- - if P_COMMAND flag is set and the text is unquoted, check for comments
- and don't try to parse embedded quoted strings if in a comment (still
- not exactly right yet)
-
- 9/24
- ----
-builtins/history.def
- - if running history -n, don't count these new lines as history lines
- for the current session if the `histappend' shell option is set.
- If we're just appending to the history file, the issue that caused
- history_lines_this_session to be recalculated doesn't apply -- the
- history file won't be missing any entries
-
-lib/readline/isearch.c
- - fix C-w handler for isearch string reader to handle multibyte chars
-
-lib/readline/rlmbutil.h
- - new defines for _rl_to_wupper and _rl_to_wlower
-
-lib/readline/text.c
- - use _rl_to_wupper and _rl_to_wlower as appropriate
-
- 9/26
- ----
-execute_cmd.c
- - in shell_execve, if the exec fails due to E2BIG or ENOMEM, just print
- the appropriate error message instead of checking out any interpreter
- specified with #!
-
- 9/30
- ----
-bashhist.c
- - make $HISTCMD available anytime remember_on_history is non-zero,
- which indicates that we're saving commands to the history, and
- let it evaluate to 1 if we're not
-
- 10/4
- ----
-lib/sh/snprintf.c
- - in floating(), make sure d != 0 before calling chkinfnan -- gcc on the
- version of Solaris 9 I have translates 0 to -inf on the call
-
-[bash-3.1-beta1 frozen]
-
- 10/6
- ----
-jobs.c
- - set the_pipeline to NULL right away in cleanup_the_pipeline, and
- dispose a copy of the pointer so we don't mess with the_pipeline
- while we're in the process of destroying it
- - block and unblock SIGCHLD around manipulating the_pipeline in
- cleanup_the_pipeline
-
- 10/7
- ----
-[bash-3.1-beta1 released]
-
-lib/readline/isearch.c
- - when switching directions, make sure we turn off the SF_REVERSE
- flag in the search context's flags word if we're going from reverse
- to forward i-search
-
-lib/readline/bind.c
- - new function, rl_variable_value, returns a string representing a
- bindable readline variable's value
- - new auxiliary function, _rl_get_string_variable_value, encapsulates
- everything needed to get a bindable string variable's value
- - rewrote rl_variable_dumper to use _rl_get_string_variable_value
-
-lib/readline/readline.h
- - new extern declaration for rl_variable_value
-
-lib/readline/doc/rltech.texi
- - documented rl_variable_value
-
-bashline.c
- - in command_word_completion_function, if readline sets
- rl_completion_found_quote, but doesn't set rl_completion_quote_character,
- we have an embedded quoted string or backslash-escaped character in
- the passed text. We need to dequote that before calling
- filename_completion_function. So far, this is in place only for
- absolute program names (those containing a `/')
- - in command_word_completion_function, use rl_variable_value to decide
- whether or not we should ignore case, and use strncasecmp instead of
- strncmp where appropriate
-
- 10/11
- -----
-builtins/fc.def
- - fixed a typo when using POSIX_FC_EDIT_COMMAND
-
-redir.h
- - new flag values for redirections: RX_INTERNAL and RX_USER (currently
- unused)
-
-redir.c
- - add_undo_redirect and add_undo_close_redirect now set RX_INTERNAL
- flag when making new redirects
- - in do_redirection_internal, only set file descriptors > 2 to CLEXEC
- if they're marked as RX_INTERNAL
-
- 10/12
- -----
-jobs.c
- - in wait_for_single_pid, if in posix mode, remove the waited-for pid
- from the list of background pids, forgetting it entirely. POSIX
- conformance tests test for this.
-
-lib/readline/{readline.h,vi_mode.c}
- - new state flag, RL_STATE_VICMDONCE, set after entering vi command
- mode the first time; reset on each call to readline()
-
- 10/13
- -----
-lib/readline/undo.c
- - in rl_revert_line, make sure that revert-line in vi mode leaves
- rl_point set to 0 no matter the state of the line buffer
-
-lib/readline/vi_mode.c
- - when entering vi_command mode for the first time, free any existing
- undo list so the previous insertions won't be undone by the `U'
- command. This is how POSIX.2 says `U' should work (and the test
- suite tests for it)
-
-lib/readline/bind.c
- - change rl_parse_and_bind so only `set' commands involving boolean
- readline variables have trailing whitespace stripped from the value
- string
-
- 10/16
- -----
-lib/glob/sm_loop.c
- - fix patscan() to correctly scan backslash-escaped characters
-
- 10/18
- -----
-lib/sh/{winsize.c,Makefile.in},{jobs,nojobs}.c,Makefile.in,externs.h
- - moved get_new_window_size from jobs.c/nojobs.c to new file,
- lib/sh/winsize.c, made function global
-
-{jobs,nojobs,sig}.c,{jobs,sig}.h
- - moved SIGWINCH handling code to sig.c rather than duplicate it in
- jobs.c and nojobs.c
- - call set_sigwinch_handler from sig.c code rather than job control
- signal initialization
-
-sig.[ch]
- - new variable, sigwinch_received, acts like interrupt_state for
- SIGWINCH, set by sigwinch_sighandler. sigwinch_sighandler no longer
- calls get_new_window_size
-
-parse.y
- - add call to get_new_window_size if sigwinch_received at top of
- shell_getc
-
- 10/19
- -----
-lib/malloc/malloc.c
- - to avoid orphaning memory on free if the right bucket is busy, use a
- new function xplit(mem, bucket) to split the block into two or more
- smaller ones and add those to the right bucket (appropriately marking
- it as busy)
- - audit bsplit(), bcoalesce(), and xsplit() for proper use of busy[],
- since they're dealing with two separate buckets
-
- 10/22
- -----
-subst.c
- - new flag for string_extract: EX_REQMATCH, means to return an error
- if a matching/closing character is not found before EOS
- - new static flag variables: extract_string_error and extract_string_fatal
- - change expand_word_internal to check for new error returns from
- string_extract and return errors if appropriate
-
- 10/23
- -----
-builtins/cd.def
- - make sure we free TDIR in change_to_directory after calling
- set_working_directory (which allocates new memory) and other places
- we short-circuit and return
-
- 10/24
- -----
-subst.c
- - modified fix from 10/22 to allow bare ` to pass through (for
- some backwards compatibility and more correctness)
-
- 10/27
- -----
-conftypes.h
- - make MacOS X use the RHAPSODY code that gets HOSTTYPE, et al.
- at build rather than configure time, to support universal binaries
- (fix from llattanzi@apple.com)
-
- 10/30
- -----
-builtins/evalstring.c
- - make sure we don't turn on CMD_NO_FORK in parse_and_execute if
- we're running a trap command on signal receipt or exit
-
-execute_cmd.c
- - in shell_execve, improve the error message a little bit if the
- interpreter name in a #! exec header ends with a ^M (as in a DOS-
- format file)
-
- 11/1
- ----
-lib/readline/vi_mode.c
- - fix vi-mode `r' command to leave the cursor in the right place
-
-[bash-3.1-rc1 frozen]
-
- 11/5
- ----
-execute_cmd.c
- - make sure a DEBUG trap doesn't overwrite a command string passed to
- make_child in execute_simple_command
-
-bashline.c
- - rearrange some code in bash_quote_filename so filenames with leading
- tildes containing spaces aren't tilde-expanded before being
- returned to the caller
-
- 11/6
- ----
-lib/readline/display.c
- - when deciding where to move the cursor in rl_redisplay and needing
- to move the cursor back after moving it vertically and compensate
- for invisible characters in the prompt string, make sure that
- _rl_last_c_pos is treated as an absolute cursor position in a
- multibyte locale and the wrap offset (number of invisible characters)
- is added explicitly when deciding how many characters to backspace
-
- 11/10
- -----
-lib/readline/terminal.c
- - _rl_set_screen_size now interprets a lines or columns argument < 0
- as an indication not to change the current value
-
- 11/11
- -----
-
-lib/readline/terminal.c
- - new function, rl_reset_screen_size, calls _rl_get_screen_size to
- reset readline's idea of the terminal size
- - don't call _rl_get_screen_size in _rl_init_terminal_io if both
- _rl_screenheight and _rl_screenwidth are > 0
- - don't initialize _rl_screenheight and _rl_screenwidth to 0 in
- _rl_init_terminal_io; let caller take care of it
- - set _rl_screenheight and _rl_screenwidth to 0 before calling
- _rl_init_terminal_io
-
-lib/readline/readline.h
- - new extern declaration for rl_reset_screen_size
-
-lib/readline/doc/rltech.texi
- - documented rl_reset_screen_size
-
-variables.c
- - if readline is being used, compile in a special var function for
- assignments to LINES and COLUMNS that calls rl_set_screen_size or
- rl_reset_screen_size as appropriate. Only do this in posix mode
- and only when STRICT_POSIX is defined at compile time
- - new semaphore variable, winsize_assignment, set while doing an
- assignment to LINES or COLUMNS
- - new variable, winsize_assigned, says LINES or COLUMNS was assigned
- to or found in the environment
- - if in the middle of an assignment to LINES or COLUMNS, make
- sh_set_lines_and_columns a no-op
-
-lib/sh/winsize.c
- - get_new_window_size now takes two int * arguments, to return the
- screen dimensions
-
-externs.h
- - change extern declaration for get_new_window_size
-
-{jobs,nojobs}.c, parse.y
- - change callers of get_new_window_size
-
- 11/12
- -----
-lib/readline/terminal.c
- - new variable, rl_prefer_env_winsize, gives LINES and COLUMNS
- precedence over values from the kernel when computing window size
-
-lib/readline/readline.h
- - extern declaration for rl_prefer_env_winsize
-
-lib/readline/doc/rltech.texi
- - document rl_prefer_env_winsize
-
- 11/13
- -----
-lib/readline/rltty.c
- - change rl_prep_terminal to make sure we set and reset the tty
- special characters in the vi insertion keymap if in vi mode. This
- matters if we get accept-line for the previous line while in vi
- command mode
-
- 11/14
- -----
-builtins/pushd.def
- - make sure any call to cd_builtin includes a leading `--' from the
- argument list (or constructs one)
-
- 11/16
- -----
-pcomplete.c
- - fix small memory leak in gen_wordlist_matches
-
-[bash-3.1-rc2 frozen]
-
- 11/21
- -----
-[bash-3.1-rc2 released]
-
- 11/23
- -----
-lib/readline/display.c
- - changes to rl_redisplay to compensate for update_line updating
- _rl_last_c_pos without taking invisible characters in the line into
- account. Important in multibyte locales where _rl_last_c_pos is an
- absolute cursor position
- - changes to _rl_move_cursor_relative to account for _rl_last_c_pos
- being an absolute cursor position in a multibyte character locale
- - rewrote _rl_move_cursor_relative to make it a little simpler
-
- 11/29
- -----
-lib/readline/display.c
- - changes to rl_redisplay and update_line for update_line to communicate
- upward that it took the number of invisible characters on the current
- line into account when modifying _rl_last_c_pos
- - in update_line, adjust _rl_last_c_pos by wrap_offset before calling
- _rl_move_cursor_relative, so we pass correct information about the
- true cursor position
-
- 12/1
- ----
-configure.in
- - changed release status to `release'
-
-[bash-3.1 frozen]
-
- 12/8
- ----
-[bash-3.1 released]
-
- 12/9
- ----
-doc/{bash.1,version.texi},lib/readline/doc/version.texi
- - remove `beta1' from man page footer and texinfo documents
-
-variables.c
- - make sure winsize_assignment is protected by #ifdef READLINE, so
- minimal shell will compile
-
-builtins/read.def
- - make sure error cases free memory and run any unwind-protects to
- avoid memory leaks
-
- 12/10
- -----
-execute_cmd.c
- - change execute_command_internal to set $PIPESTATUS for ((...)) and
- [[ ... ]] commands
-
-doc/{bash.1,bashref.texi,version.texi}
- - add documentation for ulimit -[iqx] and bump revision date
-
- 12/12
- -----
-parse.y
- - make sure parse_compound_assignment saves and restores the
- PST_ASSIGNOK parser state flag around its calls to read_token.
- Fixes bug reported by Mike Frysinger
-
- 12/13
- -----
-parse.y
- - change parse_compound_assignment to save and restore the value of
- last_read_token. Not sure why it was set unconditionally in the
- first place after parsing the complete compound assignment
-
- 12/14
- -----
-lib/readline/text.c
- - don't use return value of rl_kill_text (which always succeeds and
- returns the number of characters killed) in rl_delete as an indication
- of success or failure
- - ditto for return value of rl_delete_text
-
-lib/readline/readline.c
- - don't return the value of the called readline function as the return
- value from _rl_dispatch_subseq; -1 means something different to the
- callers (return 0 all the time to indicate that a readline function
- was found and dispatched). Fix from Andreas Schwab for <DEL><DEL>
- bug in callback interface first reported by Mike Frysinger
-
-execute_cmd.c
- - fixed a typo in execute_case_command
-
- 12/15
- -----
-aclocal.m4
- - add check for wctype() to BASH_CHECK_MULTIBYTE, define HAVE_WCTYPE
-
-config.h.in
- - add HAVE_WCTYPE #define
-
-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
-
- 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
-
-jobs.c
- - change find_process to handle a NULL return value from find_pipeline
- - return immediately from delete_job if jobs[index] is already NULL or
- if it has a null pipeline associated with it
- - in delete_job, if find_last_proc returns NULL, don't try to call
- bgp_delete
-
- 1/7
- ---
-doc/bash.1
- - patch from Tim Waugh to replace some literal single quotes with
- \(aq, the groff special character for it
-
-jobs.c
- - in realloc_jobs_list, make sure to zero out slots after j_lastj
- in the new list
-
- 1/9
- ---
-support/mksignames.c
- - make sure to include <signal.h> to get right value of NSIG from
- (usually) <sys/signal.h>
-
- 1/10
- ----
-parse.y
- - when calling parse_matched_pair on a $(...) command substitution,
- don't pass the P_DQUOTE flag so that single quotes don't get
- stripped from $'...' inside the command substitution. Bug report
- and fix from Mike Stroyan <mike.stroyan@hp.com>
-
-jobs.c
- - start maintaining true count of living children in js.c_living
- - call reset_current in realloc_jobs_list, since old values for current
- and previous job are most likely incorrect
- - don't allocate a new list in realloc_jobs_list if the old size and
- new size are the same; just compact the existing list
- - make sure realloc_jobs_list updates value of js.j_njobs
- - add some more itrace messages about non-null jobs after j_lastj in
- jobs array
-
- 1/11
- ----
-bashjmp.h
- - new value for second argument to longjmp: SIGEXIT. Reserved for
- future use
-
- 1/12
- ----
-jobs.c
- - add logic to make_child to figure out when pids wrap around
- - turn second argument to delete_job into flags word, added flag to
- prevent adding proc to bgpids list
-
- 1/13
- ----
-lib/readline/vi_mode.c
- - move code that moves forward a character out of rl_vi_append_mode
- into a separate function, _rl_vi_append_forward
- - change _rl_vi_append_mode to save `a' as the last command, so it
- can be redone properly
- - new function _rl_vi_backup, moves point back a character taking
- multibyte locales into account
- - change rl_vi_redo to handle redoing an `a' command specially --
- it should be redone like `i' but after moving forward a character
- - change rl_vi_redo to use _rl_vi_backup to move point backward
- after redoing `i' or `a'
-
-jobs.c
- - new function, delete_old_job (pid), checks whether or not PID is in
- a job in the jobs list. If so, and the job is dead, it just removes
- the job from the list. If so, and the job is not dead, it zeros
- the pid in the appropriate PROCESS so pid aliasing doesn't occur
- - make_child calls delete_old_job to potentially remove an already-used
- instance of the pid just forked from the jobs list if pids have
- wrapped around. Finally fixes the bug reported by Tim Waugh
- <twaugh@redhat.com>
-
-trap.c
- - new define, GETORIGSIG(sig), gets the original handling for SIG and
- sets SIG_HARD_IGNORE if that handler is SIG_IGN
- - call GETORIGSIG from initialize_traps, get_original_signal, and
- set_signal
-
-jobs.c
- - in wait_for, if the original SIGINT handler is SIG_IGN, don't set
- the handler to wait_sigint_handler. This keeps scripts started in
- the background (and ignoring SIGINT) from dying due to SIGINT while
- they're waiting for a child to exit. Bug reported by Ingemar
- Nilsson <init@kth.se>
-
-lib/readline/vi_mode.c
- - don't save text to buffer unless undo pointer points to a record of
- type UNDO_INSERT; zero it out instead. This fixes bug reported by
- Craig Turner <craig@synect.com> with redoing `ctd[ESC]' (empty
- insert after change to)
-
-shell.c
- - change set_shell_name so invocations like "-/bin/bash" are marked as
- login shells
-
-doc/bash.1
- - add note about destroying functions with `unset -f' to the section
- on shell functions
-
-lib/readline/terminal.c
- - if readline hasn't been initialized (_rl_term_autowrap == -1, the
- value it's now initialized with), call _rl_init_terminal_io from
- _rl_set_screen_size before deciding whether or not to decrement
- _rl_screenwidth. Fixes bug from Mike Frysinger <vapier@gentoo.org>
-
- 1/14
- ----
-lib/readline/input.c
- - allow rl_set_keyboard_input_timeout to set the timeout to 0, for
- applications that want to use select() like a poll without any
- waiting
-
-lib/readline/doc/rltech.texi
- - documented valid values for timeout in rl_set_keyboard_input_timeout
-
-jobs.c
- - in stop_pipeline, don't have the parent shell call give_terminal_to
- if subshell_environment contains SUBSHELL_ASYNC (no background
- process should ever give the terminal to anything other than
- shell_pgrp)
- - in make_child, don't give the terminal away if subshell_environment
- contains SUBSHELL_ASYNC
-
- 1/15
- ----
-subst.c
- - in parameter_brace_expand, if extracting ${#varname}, only allow
- `}' to end the expansion, since none of the other expansions are
- valid. Fixes Debian bug reported by Jan Nordhorlz <jckn@gmx.net>
-
- 1/17
- ----
-parse.y
- - in parse_matched_pair, protect all character tests with the MBTEST
- macro
- - in parse_dparen, take out extra make_word after call to alloc_word_desc
- (mem leak)
-
- 1/18
- ----
-parse.y
- - in parse_matched_pair, add P_ALLOWESC to flags passed to recursive
- parse_matched_pair call when encountering a single or double quote
- inside a ``-style command substitution
-
-execute_cmd.c
- - add call to QUIT at beginning of execute_command_internal; better
- responsiveness to SIGINT
-
- 1/21
- ----
-lib/readline/bind.c
- - change rl_invoking_keyseqs_in_map to honor the setting of
- convert-meta when listing key bindings, since if convert-meta is off,
- using '\M-' as the prefix for bindings in, for instance,
- emacs-escape-keymap, is wrong. This affects `bind -p' output
- - change rl_untranslate_keyseq to add '\e' instead of '\C-[' for
- ESC
-
-execute_cmd.c
- - add call to QUIT at end of execute_command
-
- 1/23
- ----
-lib/readline/display.c
- - changed two places in update_line where a check of whether the cursor
- is before the last invisible character in the prompt string to
- differentiate between the multibyte character case (where
- _rl_last_c_pos is a physical cursor position) and the single-byte
- case (where it is a buffer index). This prevents many unnecessary
- \r-redraw the line sequences. Reported by Dan Jacobson.
-
- 1/24
- ----
-quit.h
- - wrap QUIT macro in do...while(0) like other compound statement
- macros
- - CHECK_TERMSIG define (placeholder for now); future use will be to
- handle any received signals that should cause the shell to
- terminate (e.g., SIGHUP)
-
-{input,jobs,nojobs}.c
- - add calls to CHECK_TERMSIG where appropriate (reading input and
- waiting for children)
- - include quit.h if necessary
-
- 1/25
- ----
-parse.y
- - undo change that makes `)' in a compound assignment delimit a token.
- It messes up arithmetic expressions in assignments to `let', among
- other things
-
-sig.h,{jobs,nojobs,sig,trap}.c,builtins/trap.def
- - rename termination_unwind_protect to termsig_sighandler
-
-sig.c
- - split termsig_sighandler into two functions: termsig_sighandler, which
- runs as a signal handler and sets a flag noting that a terminating
- signal was received, and termsig_handler, which runs when it is `safe'
- to handle the signal and exit
- - new terminate_immediately variable, similar to interrupt_immediately
- - termsig_sighandler calls termsig_handler immediately if
- terminate_immediately is non-zero
-
-quit.h
- - change CHECK_TERMSIG macro to check terminating_signal and call
- termsig_handler if it's non-zero
- - add same check of terminating_signal and call to termsig_handler to
- QUIT macro
-
-{jobs,nojobs}.c
- - change call to termsig_sighandler to call termsig_handler directly,
- as was intended
-
-parse.y,builtins/read.def
- - set terminate_immediately to non-zero value when reading interactive
- input, as is done with interrupt_immediately
-
- 1/26
- ----
-doc/{bash.1,bashref.texi}
- - reworded the POSIX standard references to remove mention of POSIX.2
- or 1003.2 -- it's all the 1003.1 standard now. Recommended by
- Arnold Robbins
-
- 1/27
- ----
-lib/readline/complete.c
- - move call to filename dequoting function into
- rl_filename_completion_function; call only if directory completion
- hook isn't set. This means that directory-completion-hook now needs
- to dequote the directory name. We don't want to dequote the directory
- name before calling the directory-completion-hook. Bug reported by
- Andrew Parker <andrewparker@bigfoot.com>
-
-bashline.c
- - add necessary directory name dequoting to bash_directory_completion_hook
- and bash_directory_expansion
-
-lib/readline/doc/rltech.texi
- - add note to description of rl_directory_completion_hook that it
- needs to dequote the directory name even if no other expansions are
- performed
-
- 1/28
- ----
-braces.c
- - make sure that we skip over braces that don't start a valid matched
- brace expansion construct in brace_expand -- there might be a valid
- brace expansion after the unmatched `{' later in the string
- - brace_gobbler now checks that when looking for a `}' to end a brace
- expansion word, there is an unquoted `,' or `..' that's not inside
- another pair of braces. Fixes the a{b{c,d}e}f problem reported by
- Tim Waugh
-
-builtins/declare.def
- - when not in posix mode, and operating on shell functions, typeset
- and declare do not require their variable operands to be valid
- shell identifiers. The other `attribute' builtins work this way.
- Fixes inconsistency reported by Mike Frysinger
-
-{configure,config.h}.in
- - add test for setregid, define HAVE_SETREGID and HAVE_DECL_SETREGID
- as appropriate
- - add test for eaccess, define HAVE_EACCESS if found
-
-lib/sh/eaccess.c
- - new file, with sh_stat and sh_eaccess functions, moved from test.c
- - renamed old sh_eaccess as sh_stataccess, since it uses the stat(2)
- information to determine file accessibility
- - new function, sh_euidaccess, to call when uid != euid or gid != egid;
- temporarily swaps uid/euid and gid/egid around call to access
- - rewrote sh_eaccess to call eaccess, access, sh_euidaccess or
- sh_stataccess as appropriate. access(2) will take into account
- things like ACLs, read-only file systems, file flags, and so on.
-
-lib/sh/Makefile.in,Makefile.in
- - add necessary entries for eaccess.[co]
-
-test.c
- - change calls to test_stat to call sh_stat
-
-{test,general}.c
- - change calls to test_eaccess to call sh_eaccess
-
-externs.h
- - new extern declaration for sh_eaccess
-
-test.[ch]
- - remove test_stat and test_eaccess
-
- 1/29
- ----
-braces.c
- - make change from 1/28 dependant on CSH_BRACE_COMPAT not being
- defined (since old bash behavior is what csh does, defining
- CSH_BRACE_COMPAT will produce old bash behavior)
-
- 1/30
- ----
-bashline.c
- - last argument of bash_default_completion is now a flags word:
- DEFCOMP_CMDPOS (in command position) is only current value
- - attempt_shell_completion now computes flags before calling
- bash_default_completion
- - if no_empty_command_completion is set, bash does not attempt command
- word completion even if not at the beginning of the line, as long
- as the word to be completed is empty and start == end (catches
- beginning of line and all whitespace preceding point)
-
- 2/4
- ---
-lib/readline/display.c
- - change _rl_make_prompt_for_search to use rl_prompt and append the
- search character to it, so the call to expand_prompt in rl_message
- will process the non-printing characters correctly. Bug reported
- by Mike Stroyan <mike.stroyan@hp.com>
-
- 2/5
- ---
-lib/readline/display.c
- - fix off-by-one error when comparing against PROMPT_ENDING_INDEX,
- which caused a prompt with invisible characters to be redrawn one
- extra time in a multibyte locale. Change from <= to < fixes
- multibyte locale, but I added 1 to single-byte definition of
- PROMPT_ENDING_INDEX (worth checking) to compensate. Bug reported
- by Egmont Koblinger <egmont@uhulinux.hu>
-
- 2/8
- ---
-lib/readline/terminal.c
- - call _emx_get_screensize with wr, wc like ioctl code for consistency
- - new function, _win_get_screensize, gets screen dimensions using
- standard Windows API for mingw32 (code from Denis Pilat)
- - call _win_get_screensize from _rl_get_screen_size on mingw32
-
-lib/readline/rlconf.h
- - define SYS_INPUTRC (/etc/inputrc) as system-wide default inputrc
- filename
-
-support/shobj-conf
- - changes to make loadable builtins work on MacOS X 10.[34]
-
-builtins/pushd.def
- - changes to make it work as a loadable builtin compiled with gcc4
-
- 2/9
- ---
-lib/readline/bind.c
- - add SYS_INPUTRC as last-ditch default (if DEFAULT_INPUTRC does not
- exist or can't be read) in rl_read_init_file
-
-lib/readline/doc/rluser.texi
- - add description of /etc/inputrc as ultimate default startup file
-
- 2/10
- ----
-lib/readline/bind.c
- - fix problem with rl_function_of_keyseq that returns a non-keymap
- bound to a portion of the passed key sequence without processing
- the entire thing. We can bind maps with existing non-map
- functions using the ANYOTHERKEY binding code.
-
-variables.c
- - shells running in posix mode do not set $HOME, as POSIX apparently
- requires
-
- 2/15
- ----
-braces.c
- - mkseq() now takes the increment as an argument; changed callers
-
- 2/16
- ----
-builtins/hash.def
- - print `hash table empty' message to stdout instead of stderr
-
- 2/17
- ----
-lib/readline/readline.c
- - when resetting rl_prompt in rl_set_prompt, make sure rl_display_prompt
- is set when the function returns
-
- 2/18
- ----
-lib/readline/display.c
- - further fixes to _rl_make_prompt_for_search from Eric Blake to deal
- with multiple calls to expand_prompt
-
- 2/21
- ----
-builtins/hash.def
- - don't print `hash table empty' message in posix mode
-
- 2/27
- ----
-lib/glob/sm_loop.c
- - change extmatch() to turn off FNM_PERIOD in flags passed to recursive
- calls to gmatch() when calling it with a substring after the start
- of the string it receives. Changed `+', `*', `?, `@', and `!' cases
- to do the right thing. Fixes bug reported by Benoit Vila
- <bvila@free.fr>
-
-braces.c
- - add QUIT; statements to mkseq to make large sequence generation
- interruptible
-
- 2/28
- ----
-lib/glob/glob.c
- - initialize nalloca in glob_vector
-
- 3/1
- ---
-lib/glob/glob.c
- - in glob_vector, when freeing up the linked list after some error,
- make sure to set `tmplink' to 0 if `firstlink' is set to 0, else we
- get multiple-free errors
-
- 3/5
- ---
-trap.c
- - inheritance of the DEBUG, RETURN, and ERR traps is now dependent
- only on the `functrace' and `errtrace' shell options, as the
- documentation says, rather than on whether or not the shell is in
- debugging mode. Reported by Philip Susi <psusi@cfl.rr.com>
-
-parse.y
- - in parse_matched_pair, don't recursively parse ${...} or other
- ${...} constructs inside ``
- - in parse_matched_pair, remove special code that recursively parses
- quoted strings inside `` constructs. For Bourne shell compatibility
-
- 3/6
- ---
-builtins/pushd.def
- - let get_directory_stack take take an `int flags' argument and convert
- $HOME to ~ if flags&1 is non-zero
-
-builtins/common.h
- - change extern declaration for get_directory_stack
-
-variables.c
- - call get_directory_stack with an arg of 0 to inhibit converting
- $HOME to ~ in the result. Fixes cd ${DIRSTACK[1]} problem
- reported by Len Lattanzi <llattanzi@apple.com> (cd fails because
- the tildes won't be expanded after variable expansion)
-
-jobs.c
- - changed hangup_all_jobs slightly so stopped jobs marked J_NOHUP
- won't get a SIGCONT
-
-general.c
- - changed check_binary_file() to check for a NUL byte instead of a
- non-printable character. Might at some point want to check
- entire (possibly multibyte) characters instead of just bytes. Hint
- from ksh via David Korn
-
- 3/7
- ---
-builtins/reserved.def
- - changed runs of spaces to tabs in variables help text to make
- indentation better when displayed
-
-builtins/mkbuiltins.c
- - changes to avoid the annoying extra space that keeps gettext from
- being passed an empty string
-
- 3/9
- ---
-lib/glob/glob.c
- - make sure globbing is interrupted if the shell receives a terminating
- signal
-
- 3/14
- ----
-lib/readline/search.c
- - call rl_message with format argument of "%" in _rl_nsearch_init
- to avoid `%' characters in the prompt string from being interpreted
- as format specifiers to vsnprintf/vsprintf
-
- 3/19
- ----
-parse.y, eval.c, input.h
- - change execute_prompt_command to execute_variable_command; takes the
- variable name as a new second argument
-
- 3/25
- ----
-bashline.c
- - command_word_completion_function keeps track of when it's searching
- $PATH and doesn't return directory names as matches in that case.
- Problem reported by Pascal Terjan <pterjan@mandriva.com>
- - command_word_completion_function returns what it's passed as a
- possible match if it's the name of a directory in the current
- directory (only non-absolute pathnames are so tested).
-
- 3/27
- ----
-subst.c
- - expand_arith_string takes a new argument: quoted. Either 0 (outside
- subst.c) or Q_DOUBLE_QUOTES (substitution functions); changed callers
-
-subst.h
- - changed extern declaration for expand_arith_string
-
-arrayfunc.c
- - changed call to expand_arith_string in array_expand_index
-
- 3/31
- ----
-lib/readline/histfile.c
- - change read_history_range to allow windows-like \r\n line endings
-
-execute_cmd.c
- - add new variable, line_number_for_err_trap, currently set but not
- used
-
- 4/2
- ---
-lib/sh/strtrans.c
- - add code to echo -e and echo with xpg_echo enabled to require
- a leading 0 to specify octal constants
-
- 4/3
- ---
-subst.c
- - slight change to wcsdup() replacement: use memcpy instead of wcscpy
-
-parse.y
- - before turning on W_COMPASSIGN, make sure the final character in the
- token is a `(' (avoids problems with things like a=(4*3)/2)
-
- 4/4
- ---
-lib/sh/snprintf.c
- - in number() and lnumber(), turn off PF_ZEROPAD if explicit precision
- supplied in format
- - change number() and lnumber() to correctly implement zero-padding
- specified by a non-zero `.precision' part of the format
-
-subst.c
- - new flag for extract_delimited_string: EX_COMMAND. For $(...), so
- we can do things like skip over delimiters in comments. Added to
- appropriate callers
- - changes to extract_delimited_string to skip over shell comments when
- extracting a command for $(...) (EX_COMMAND is contained in the
- flags argument)
-
- 4/5
- ---
-subst.c
- - first argument to skip_single_quoted is now a const char *
- - new function, chk_arithsub, checks for valid arithmetic expressions
- by balancing parentheses. Fix based on a patch from Len Lattanzi
-
- 4/6
- ---
-{configure,config.h}.in
- - add separate test for isnan in libc, instead of piggybacking on
- isinf-in-libc test
-
-lib/sh/snprintf.c
- - separate the isnan replacement function so it's guarded by its own
- HAVE_ISNAN_IN_LIBC define
-
-lib/sh/wcsdup.c
- - new file, contains replacement wcsdup library function from subst.c
- with change back to using wcscpy
-
-Makefile.in,lib/sh/Makefile.in
- - make sure wcsdup.c is compiled and linked in
-
-subst.c
- - wcsdup now found in libsh; removed static definition
-
- 4/10
- ----
-lib/readline/callback.c
- - loop over body of rl_callback_read_char as long as there is additional
- input rather than just calling readline_internal_char, which does
- not handle multi-character key sequences or escape-prefixed chars
-
-lib/readline/macro.c
- - make sure we turn off RL_STATE_MACROINPUT when the macro stack is
- empty if we are reading additional input with RL_STATE_MOREINPUT
-
-support/shobj-conf
- - Mac OS X no longer likes the `-bundle' option to gcc when creating a
- dynamic shared library
-
- 4/11
- ----
-lib/tilde/tilde.c
- - don't try to dereference user_entry if HAVE_GETPWENT isn't defined
-
-lib/readline/input.c
- - make sure chars_avail is not used without being assigned a value in
- rl_gather_tyi
- - use _kbhit() to check for available input on Windows consoles, in
- rl_gather_tyi and _rl_input_available
-
- 4/21
- ----
-lib/readline/display.c
- - calculate (in expand_prompt) and keep track of length of local_prompt
- in local_prompt_len; use where appropriate
- - when using o_pos to check whether or not we need to adjust
- _rl_last_c_pos after calling update_line, assume that it's correct
- (a buffer index in non-multibyte locales and a cursor position in
- multibyte locales) and adjust with wrap_offset as appropriate
- - in update_line, set cpos_adjusted to 1 after calling
- _rl_move_cursor_relative to move to the end of the displayed prompt
- string
- - in _rl_move_cursor_relative, check that the multibyte display
- position is after the last invisible character in the prompt string
- before offsetting it by the number of invisible characters in the
- prompt (woff)
-
- 4/26
- ----
-lib/readline/doc/{rluser.texi,readline.3}
- - make sure to note that key bindings don't allow any whitespace
- between the key name or sequence to be bound and the colon
-
- 4/28
- ----
-lib/readline/display.c
- - in update_line, make sure we compare _rl_last_c_pos as strictly less
- than PROMPT_ENDING_INDEX, since it's 0-based, to avoid multiple
- prompt redraws
-
- 5/4
- ---
-parse.y
- - in decode_prompt_string, only prefix the expansion of \[ or \]
- with CTLESC if the corresponding readline escape character is
- CTLESC (coincidentally the same as \[) or CTLNUL. Bug report sent
- by Mike Frysinger <vapier@gentoo.org> prompted the discovery
-
-aclocal.m4
- - slight change to test for /dev/fd to compensate for a linux
- failing; suggested by Mike Frysinger <vapier@gentoo.org>
-
- 5/9
- ---
-arrayfunc.c
- - broke assign_array_var_from_string into two functions:
- expand_compound_array_assignment and assign_compound_array_list;
- assign_array_var_from_string just calls those functions now
-
-arrayfunc.h
- - new extern declarations for expand_compound_array_assignment and
- assign_compound_array_list
-
-subst.c
- - in do_compound_assignment, call expand_compound_array_assignment
- before creating the local variable so a previous inherited
- value can be used when expanding the rhs of the compound assignment
- statement
-
- 5/11
- ----
-doc/{bash.1,bashref.texi}
- - clarifed `trap' description to make it clear that trapped signals
- that are not set to SIG_IGN are reset when a subshell is created
-
- 5/18
- ----
-locale.c
- - change reset_locale_vars to call setlocale (LC_ALL, "") if LANG
- is unset or NULL
- - if LANG is unset or NULL, reset the export environment before
- calling setlocale in reset_locale_vars, and trust that it will
- change the environment setlocale() inspects
-
- 5/21
- ----
-lib/readline/history.c
- - new function, HIST_ENTRY *alloc_history_entry (char *string, char *ts);
- creates a new history entry with text STRING and timestamp TS (both
- of which may be NULL)
- - new function, HIST_ENTRY *copy_history_entry (HIST_ENTRY *hist),
- which copies the line and timestamp entries to new memory but just
- copies the data member, since that's an opaque pointer
- - new function, void replace_history_data (int which, histdata_t *old, histdata_t *new)
- which replaces the `data' member of specified history entries with
- NEW, as long as it is OLD. WHICH says which history entries to
- modify
- - add calls to replace_history_data in rl_free_undo_list and
- rl_do_undo
-
-lib/readline/undo.c
- - new function, alloc_undo_entry (enum undo_code what, int start, int end, char *text)
- takes care of allocating and populating a struct for an individual
- undo list entry
- - new function: _rl_copy_undo_entry(UNDO_LIST *entry)
- - new function: _rl_copy_undo_list(UNDO_LIST *head)
-
-lib/readline/rlprivate.h
- - new extern declarations for _rl_copy_undo_{entry,list}
-
-execute_cmd.c
- - change execute_cond_node so that quoting the rhs of the =~
- operator forces string matching, like the == and != operators
-
- 5/23
- ----
-redir.c
- - add_undo_redirect now takes as an additional argument the type of
- redirection we're trying to undo
- - don't add a "preservation" redirection for fds > SHELL_FD_BASE if
- the redirection is closing the fd
-
- 5/24
- ----
-subst.c
- - make sure that parameter_brace_substring leaves this_command_name
- set to either NULL or its previous value after setting it so that
- arithmetic evaluation errors while expanding substring values
- contain meaningful information
-
- 6/9
- ---
-execute_cmd.c
- - make sure that SUBSHELL_ASYNC and SUBSHELL_PIPE are set as flag bits
- in subshell_environment, rather than setting only a single value
- - change execute_subshell_builtin_or_function to give the `return'
- builtin a place to longjmp to when executed in a subshell or pipeline
- (mostly as the last command in a pipeline). Bug reported by
- Oleg Verych <olecom@gmail.com>
- - in execute_simple_command, make sure to call execute_disk_command
- with the_printed_command_except_trap to keep DEBUG trap command
- strings from overwriting the command strings associated with jobs
- and printed in job control messages. Bug reported by Daniel Kahn
- Gillmor <dkg-debian.org@fifthhorseman.net>
-
-[bash-3.2-alpha frozen]
-
- 6/22
- ----
-syntax.h
- - add new CBLANK (for [:blank:] class) flag value for syntax table and
- shellblank(c) character test macro
-
-mksyntax.c
- - add support for setting CBLANK flag in the syntax table depending on
- whether or not isblank(x) returns true for character x
-
-locale.c
- - change locale_setblanks to set or unset CBLANK flag for each
- character when locale changes
-
-parse.y
- - change call to whitespace(c) in lexical analyzer (read_token()) to
- call shellblank(c) instead, so locale-specific blank characters are
- treated as white space. Fixes bug reported by Serge van deb Boom
- <svdb+bug-bash@stack.nl>
-
-print_cmd.c
- - when printing redirections, add a space between <, >, and <> and the
- following word, to avoid conflicts with process substitution. Bug
- reported by Ittay Dror <ittyad@qlusters.com>
-
- 6/26
- ----
-configure.in
- - set CROSS_COMPILE to the empty string by default, so we don't inherit
- a random value from the environment. Bug reported by
- Lee Revell <rlrevell@joe-job.com>
-
- 6/29
- ----
-lib/glob/xmbsrtowcs.c
- - make sure destp is non-null before assigning a 0 to *destp in
- xdupmbstowcs. Fix from Louiwa Salem <loulwas@us.ibm.com>
-
-execute_cmd.c
- - fix execute_in_subshell to make sure asynchronous isn't set to 0
- before subshell_environment is set appropriately and
- setup_async_signals is run. Based on report by Louiwa Salem
- <loulwas@us.ibm.com>
-
-lib/readline/bind.c
- - in rl_generic_bind(), make sure that the keys array is freed before
- an error return. Fix from Louiwa Salem <loulwas@us.ibm.com>
-
- 7/1
- ---
-builtins/read.def
- - make sure all editing code is protected with #ifdef READLINE, esp.
- unwind-protect that restores the default completion function
-
-lib/readline/display.c
- - make sure to set local_prompt_len in rl_message() [in bash-3.2-alpha]
-
- 7/5
- ---
-builtins/printf.def
- - add more of echo's write error handling to printf. Suggested by
- martin.wilck@fujitsu-siemens.com
-
- 7/7
- ---
-lib/readline/display.c
- - save and restore local_prompt_len in rl_{save,restore}_prompt
- [in bash-3.2-alpha]
-
- 7/8
- ---
-[bash-3.2-alpha released]
-
- 7/9
- ---
-lib/readline/display.c
- - make sure that _rl_move_cursor_relative sets cpos_adjusted when it
- offsets `dpos' by wrap_offset in a multi-byte locale. Bug reported
- by Andreas Schwab and Egmont Koblinger
-
-subst.c
- - make sure that the call to mbstowcs in string_extract_verbatim is
- passed a string with enough space for the closing NUL. Reported
- by Andreas Schwab
-
- 7/18
- ----
-lib/readline/{display,terminal}.c
- - remove #ifdefs for HACK_TERMCAP_MOTION so we can use
- _rl_term_forward_char in the redisplay code unconditionally
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_term_forward_char
-
-lib/readline/display.c
- - in _rl_move_cursor_relative, use `dpos' instead of `new' when
- deciding whether or not a CR is faster than moving the cursor from
- its current position
- - in _rl_move_cursor_relative, we can use _rl_term_forward_char to
- move the cursor forward in a multibyte locale, if it's available.
- Since that function doesn't have a handle on where the cursor is in
- the display buffer, it has to output a cr and print all the data.
- Fixes rest of problem reported by Egmont Koblinger
- - change variable denoting the position of the cursor in the line buffer
- from c_pos (variable local to rl_redisplay) to cpos_buffer_position
- (variable local to file) for future use by other functions
-
- 7/25
- ----
-lib/malloc/{stats,table}.h
- - include <string.h> for prototypes for memset, strlen
-
-lib/termcap/{termcap,tparam}.c
- - include <string.h> and provide macro replacement for bcopy if
- necessary
-
- 7/27
- ----
-lib/readline/histexpand.c
- - add support for `<<<' here-string redirection operator to
- history_tokenize_word. Bug reported by agriffis@gentoo.org
-
-externs.h
- - don't add prototype for strerror() if HAVE_STRERROR defined
-
- 7/29
- ----
-subst.c
- - in list_string, use `string' instead of `s' -- s is not initialized
-
- 8/9
- ---
-subst.c
- - fix parameter_brace_expand to set W_HASQUOTEDNULL in the WORD_DESC it
- returns if the result of parameter_brace_substring is a quoted null
- ("\177"). Fixes bug reported by Igor Peshansky <pechtcha@cs.nyu.edu>
-
- 8/16
- ----
-lib/readline/readline.h
- - new #define, READERR, intended to be used to denote read/input errors
-
-lib/readline/input.c
- - in rl_getc, if read() returns an error other than EINTR (after the
- EWOULDBLOCK/EAGAIN cases are handled), return READERR rather than
- converting return value to EOF if readline is reading a top-level
- command (RL_STATE_READCMD)
-
-lib/readline/readline.c
- - if rl_read_key returns READERR to readline_internal_char[loop],
- abort as if it had read EOF on an empty line, without any conversion
- to newline, which would cause a partial line to be executed. This
- fixes the bug reported by Mathieu Bonnet <mathieu.bonnet@nalkym.org>
-
-aclocal.m4
- - when testing for validity of /dev/fd/3, use /dev/null instead of
- standard input, since the standard input fails with linux and `su'.
- Bug reported by Greg Shafer <gschafer@zip.com.au>
-
- 8/17
- ----
-Makefile.in
- - switch the TAGS and tags targets so TAGS is the output of `etags' and
- tags is the output of `ctags'. Suggested by Masatake YAMATO
-
- 8/25
- ----
-execute_cmd.c
- - change code to match documentation: set BASH_COMMAND (which takes its
- value from the_printed_command_except_trap) only when not running a
- trap. Rocky says the debugger is ok with this, and this is what his
- original diffs did
-
- 8/29
- ----
-variables.c
- - change set_if_not to create shell_variables if it is NULL, since
- -o invocation options can cause variables to be set before the
- environment is scanned
-
-[bash-3.2-beta frozen]
-
- 9/5
- ---
-variables.c
- - change dispose_used_env_vars to call maybe_make_export_env
- immediately if we're disposing a temporary environment, since
- `environ' points to the export environment and getenv() will use
- that on systems that don't allow getenv() to be replaced. This
- could cause the temporary environment to affect the shell. Bug
- reported by Vasco Pedro <vp@di.uevora.pt>
diff --git a/CWRU/POSIX.NOTES.old b/CWRU/POSIX.NOTES.old
deleted file mode 100644
index 1707ab10..00000000
--- a/CWRU/POSIX.NOTES.old
+++ /dev/null
@@ -1,82 +0,0 @@
-Starting bash with the `--posix' command-line option or executing
-`set -o posix' while bash is running will cause bash to conform more
-closely to the Posix.2 standard by changing the behavior to match that
-specified by Posix.2 in areas where the bash default differs.
-
-The following list is what's changed when `posix mode' is in effect:
-
-1. When a command in the hash table no longer exists, bash will re-search
- $PATH to find the new location. This is also available with
- `shopt -s checkhash'.
-
-2. The >& redirection does not redirect stdout and stderr.
-
-3. The message printed by the job control code and builtins when a job
- exits with a non-zero status is `Done(status)'.
-
-4. Reserved words may not be aliased.
-
-5. The Posix.2 PS1 and PS2 expansions of `!' -> history number and
- `!!' -> `!' are enabled, and parameter expansion is performed on
- the value regardless of the setting of the `promptvars' option.
-
-6. Interactive comments are enabled by default. (Note that bash has
- them on by default anyway.)
-
-7. The Posix.2 startup files are executed ($ENV) rather than the normal
- bash files.
-
-8. Tilde expansion is only performed on assignments preceding a command
- name, rather than on all assignment statements on the line.
-
-9. The default history file is ~/.sh_history (default value of $HISTFILE).
-
-10. The output of `kill -l' prints all the signal names on a single line,
- separated by spaces.
-
-11. Non-interactive shells exit if `file' in `. file' is not found.
-
-12. Redirection operators do not perform pathname expansion on the word
- in the redirection unless the shell is interactive
-
-13. Function names must be valid shell identifiers. That is, they may not
- contain characters other than letters, digits, and underscores, and
- may not start with a digit. Declaring a function with an illegal name
- causes a fatal syntax error in non-interactive shells.
-
-14. Posix.2 `special' builtins are found before shell functions during command
- lookup.
-
-15. If a Posix.2 special builtin returns an error status, a non-interactive
- shell exits. The fatal errors are those listed in the POSIX.2 standard,
- and include things like passing incorrect options, redirection errors,
- variable assignment errors for assignments preceding the command name,
- and so on.
-
-16. The environment passed to executed commands is not sorted. Neither is
- the output of `set'. This is not strictly Posix.2 behavior, but sh
- does it this way. Ksh does not. It's not necessary to sort the
- environment; no program should rely on it being sorted.
-
-17. If the `cd' builtin finds a directory to change to using $CDPATH, the
- value it assigns to $PWD does not contain any symbolic links, as if
- `cd -P' had been executed.
-
-18. A non-interactive shell exits with an error status if a variable
- assignment error occurs when no command name follows the assignment
- statements. A variable assignment error occurs, for example, when
- trying to assign a value to a read-only variable.
-
-19. A non-interactive shell exits with an error status if the iteration
- variable in a for statement or the selection variable in a select
- statement is a read-only variable.
-
-20. Process substitution is not available.
-
-21. Assignment statements preceding POSIX.2 `special' builtins persist in
- the shell environment after the builtin completes.
-
-There is other Posix.2 behavior that bash does not implement. Specifically:
-
-1. Assignment statements affect the execution environment of all builtins,
- not just special ones.
diff --git a/CWRU/old/set.def.save b/CWRU/old/set.def.save
deleted file mode 100644
index 87b78d7c..00000000
--- a/CWRU/old/set.def.save
+++ /dev/null
@@ -1,544 +0,0 @@
-This file is set.def, from which is created set.c.
-It implements the "set" and "unset" builtins in Bash.
-
-Copyright (C) 1987, 1989, 1991 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.
-
-$PRODUCES set.c
-
-#include <stdio.h>
-#include "../shell.h"
-#include "../flags.h"
-
-#include "bashgetopt.h"
-
-extern int interactive;
-extern int noclobber, posixly_correct;
-#if defined (READLINE)
-extern int rl_editing_mode, no_line_editing;
-#endif /* READLINE */
-
-$BUILTIN set
-$FUNCTION set_builtin
-$SHORT_DOC set [--abefhkmnptuvxldBCHP] [-o option] [arg ...]
- -a Mark variables which are modified or created for export.
- -b Notify of job termination immediately.
- -e Exit immediately if a command exits with a non-zero status.
- -f Disable file name generation (globbing).
- -h Locate and remember function commands as functions are
- defined. Function commands are normally looked up when
- the function is executed.
- -i Force the shell to be an "interactive" one. Interactive shells
- always read `~/.bashrc' on startup.
- -k All keyword arguments are placed in the environment for a
- command, not just those that precede the command name.
- -m Job control is enabled.
- -n Read commands but do not execute them.
- -o option-name
- Set the variable corresponding to option-name:
- allexport same as -a
- braceexpand same as -B
-#if defined (READLINE)
- emacs use an emacs-style line editing interface
-#endif /* READLINE */
- errexit same as -e
- histexpand same as -H
- ignoreeof the shell will not exit upon reading EOF
- interactive-comments
- allow comments to appear in interactive commands
- monitor same as -m
- noclobber disallow redirection to existing files
- noexec same as -n
- noglob same as -f
- nohash same as -d
- notify save as -b
- nounset same as -u
- physical same as -P
- posix change the behavior of bash where the default
- operation differs from the 1003.2 standard to
- match the standard
- privileged same as -p
- verbose same as -v
-#if defined (READLINE)
- vi use a vi-style line editing interface
-#endif /* READLINE */
- xtrace same as -x
- -p Turned on whenever the real and effective user ids do not match.
- Disables processing of the $ENV file and importing of shell
- functions. Turning this option off causes the effective uid and
- gid to be set to the real uid and gid.
- -t Exit after reading and executing one command.
- -u Treat unset variables as an error when substituting.
- -v Print shell input lines as they are read.
- -x Print commands and their arguments as they are executed.
- -l Save and restore the binding of the NAME in a FOR command.
- -d Disable the hashing of commands that are looked up for execution.
- Normally, commands are remembered in a hash table, and once
- found, do not have to be looked up again.
-#if defined (BRACE_EXPANSION)
- -B the shell will perform brace expansion
-#endif /* BRACE_EXPANSION */
-#if defined (BANG_HISTORY)
- -H Enable ! style history substitution. This flag is on
- by default.
-#endif /* BANG_HISTORY */
- -C If set, disallow existing regular files to be overwritten
- by redirection of output.
- -P If set, do not follow symbolic links when executing commands
- such as cd which change the current directory.
-
-Using + rather than - causes these flags to be turned off. The
-flags can also be used upon invocation of the shell. The current
-set of flags may be found in $-. The remaining n ARGs are positional
-parameters and are assigned, in order, to $1, $2, .. $n. If no
-ARGs are given, all shell variables are printed.
-$END
-
-/* An a-list used to match long options for set -o to the corresponding
- option letter. */
-struct {
- char *name;
- int letter;
-} o_options[] = {
- { "allexport", 'a' },
-#if defined (BRACE_EXPANSION)
- { "braceexpand",'B' },
-#endif
- { "errexit", 'e' },
- { "histexpand", 'H' },
- { "monitor", 'm' },
- { "noexec", 'n' },
- { "noglob", 'f' },
- { "nohash", 'd' },
-#if defined (JOB_CONTROL)
- { "notify", 'b' },
-#endif /* JOB_CONTROL */
- {"nounset", 'u' },
- {"physical", 'P' },
- {"privileged", 'p' },
- {"verbose", 'v' },
- {"xtrace", 'x' },
- {(char *)NULL, 0},
-};
-
-#define MINUS_O_FORMAT "%-15s\t%s\n"
-
-void
-list_minus_o_opts ()
-{
- register int i;
- char *on = "on", *off = "off";
-
- printf (MINUS_O_FORMAT, "noclobber", (noclobber == 1) ? on : off);
-
- if (find_variable ("ignoreeof") || find_variable ("IGNOREEOF"))
- printf (MINUS_O_FORMAT, "ignoreeof", on);
- else
- printf (MINUS_O_FORMAT, "ignoreeof", off);
-
- printf (MINUS_O_FORMAT, "interactive-comments",
- interactive_comments ? on : off);
-
- printf (MINUS_O_FORMAT, "posix", posixly_correct ? on : off);
-
-#if defined (READLINE)
- if (no_line_editing)
- {
- printf (MINUS_O_FORMAT, "emacs", off);
- printf (MINUS_O_FORMAT, "vi", off);
- }
- else
- {
- /* Magic. This code `knows' how readline handles rl_editing_mode. */
- printf (MINUS_O_FORMAT, "emacs", (rl_editing_mode == 1) ? on : off);
- printf (MINUS_O_FORMAT, "vi", (rl_editing_mode == 0) ? on : off);
- }
-#endif /* READLINE */
-
- for (i = 0; o_options[i].name; i++)
- {
- int *on_or_off, zero = 0;
-
- on_or_off = find_flag (o_options[i].letter);
- if (on_or_off == FLAG_UNKNOWN)
- on_or_off = &zero;
- printf (MINUS_O_FORMAT, o_options[i].name, (*on_or_off == 1) ? on : off);
- }
-}
-
-set_minus_o_option (on_or_off, option_name)
- int on_or_off;
- char *option_name;
-{
- int option_char = -1;
-
- if (STREQ (option_name, "noclobber"))
- {
- if (on_or_off == FLAG_ON)
- bind_variable ("noclobber", "");
- else
- unbind_variable ("noclobber");
- stupidly_hack_special_variables ("noclobber");
- }
- else if (STREQ (option_name, "ignoreeof"))
- {
- unbind_variable ("ignoreeof");
- unbind_variable ("IGNOREEOF");
- if (on_or_off == FLAG_ON)
- bind_variable ("IGNOREEOF", "10");
- stupidly_hack_special_variables ("IGNOREEOF");
- }
-
-#if defined (READLINE)
- else if ((STREQ (option_name, "emacs")) || (STREQ (option_name, "vi")))
- {
- if (on_or_off == FLAG_ON)
- {
- rl_variable_bind ("editing-mode", option_name);
-
- if (interactive)
- with_input_from_stdin ();
- no_line_editing = 0;
- }
- else
- {
- int isemacs = (rl_editing_mode == 1);
- if ((isemacs && STREQ (option_name, "emacs")) ||
- (!isemacs && STREQ (option_name, "vi")))
- {
- if (interactive)
- with_input_from_stream (stdin, "stdin");
- no_line_editing = 1;
- }
- else
- builtin_error ("not in %s editing mode", option_name);
- }
- }
-#endif /* READLINE */
- else if (STREQ (option_name, "interactive-comments"))
- interactive_comments = (on_or_off == FLAG_ON);
- else if (STREQ (option_name, "posix"))
- {
- posixly_correct = (on_or_off == FLAG_ON);
- unbind_variable ("POSIXLY_CORRECT");
- unbind_variable ("POSIX_PEDANTIC");
- if (on_or_off == FLAG_ON)
- {
- bind_variable ("POSIXLY_CORRECT", "");
- stupidly_hack_special_variables ("POSIXLY_CORRECT");
- }
- }
- else
- {
- register int i;
- for (i = 0; o_options[i].name; i++)
- {
- if (STREQ (option_name, o_options[i].name))
- {
- option_char = o_options[i].letter;
- break;
- }
- }
- if (option_char == -1)
- {
- builtin_error ("%s: unknown option name", option_name);
- return (EXECUTION_FAILURE);
- }
- if (change_flag (option_char, on_or_off) == FLAG_ERROR)
- {
- bad_option (option_name);
- return (EXECUTION_FAILURE);
- }
- }
- return (EXECUTION_SUCCESS);
-}
-
-/* Set some flags from the word values in the input list. If LIST is empty,
- then print out the values of the variables instead. If LIST contains
- non-flags, then set $1 - $9 to the successive words of LIST. */
-set_builtin (list)
- WORD_LIST *list;
-{
- int on_or_off, flag_name, force_assignment = 0;
-
- if (!list)
- {
- SHELL_VAR **vars;
-
- vars = all_shell_variables ();
- if (vars)
- {
- print_var_list (vars);
- free (vars);
- }
-
- vars = all_shell_functions ();
- if (vars)
- {
- print_var_list (vars);
- free (vars);
- }
-
- return (EXECUTION_SUCCESS);
- }
-
- /* Check validity of flag arguments. */
- if (*list->word->word == '-' || *list->word->word == '+')
- {
- register char *arg;
- WORD_LIST *save_list = list;
-
- while (list && (arg = list->word->word))
- {
- char c;
-
- if (arg[0] != '-' && arg[0] != '+')
- break;
-
- /* `-' or `--' signifies end of flag arguments. */
- if (arg[0] == '-' &&
- (!arg[1] || (arg[1] == '-' && !arg[2])))
- break;
-
- while (c = *++arg)
- {
- if (find_flag (c) == FLAG_UNKNOWN && c != 'o')
- {
- char s[2];
- s[0] = c; s[1] = '\0';
- bad_option (s);
- if (c == '?')
- builtin_usage ();
- return (c == '?' ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
- }
- }
- list = list->next;
- }
- list = save_list;
- }
-
- /* Do the set command. While the list consists of words starting with
- '-' or '+' treat them as flags, otherwise, start assigning them to
- $1 ... $n. */
- while (list)
- {
- char *string = list->word->word;
-
- /* If the argument is `--' or `-' then signal the end of the list
- and remember the remaining arguments. */
- if (string[0] == '-' && (!string[1] || (string[1] == '-' && !string[2])))
- {
- list = list->next;
-
- /* `set --' unsets the positional parameters. */
- if (string[1] == '-')
- force_assignment = 1;
-
- /* Until told differently, the old shell behaviour of
- `set - [arg ...]' being equivalent to `set +xv [arg ...]'
- stands. Posix.2 says the behaviour is marked as obsolescent. */
- else
- {
- change_flag ('x', '+');
- change_flag ('v', '+');
- }
-
- break;
- }
-
- if ((on_or_off = *string) &&
- (on_or_off == '-' || on_or_off == '+'))
- {
- int i = 1;
- while (flag_name = string[i++])
- {
- if (flag_name == '?')
- {
- builtin_usage ();
- return (EXECUTION_SUCCESS);
- }
- else if (flag_name == 'o') /* -+o option-name */
- {
- char *option_name;
- WORD_LIST *opt;
-
- opt = list->next;
-
- if (!opt)
- {
- list_minus_o_opts ();
- continue;
- }
-
- option_name = opt->word->word;
-
- if (!option_name || !*option_name || (*option_name == '-'))
- {
- list_minus_o_opts ();
- continue;
- }
- list = list->next; /* Skip over option name. */
-
- if (set_minus_o_option (on_or_off, option_name) != EXECUTION_SUCCESS)
- return (EXECUTION_FAILURE);
- }
- else
- {
- if (change_flag (flag_name, on_or_off) == FLAG_ERROR)
- {
- char opt[3];
- opt[0] = on_or_off;
- opt[1] = flag_name;
- opt[2] = '\0';
- bad_option (opt);
- builtin_usage ();
- return (EXECUTION_FAILURE);
- }
- }
- }
- }
- else
- {
- break;
- }
- list = list->next;
- }
-
- /* Assigning $1 ... $n */
- if (list || force_assignment)
- remember_args (list, 1);
- return (EXECUTION_SUCCESS);
-}
-
-$BUILTIN unset
-$FUNCTION unset_builtin
-$SHORT_DOC unset [-f] [-v] [name ...]
-For each NAME, remove the corresponding variable or function. Given
-the `-v', unset will only act on variables. Given the `-f' flag,
-unset will only act on functions. With neither flag, unset first
-tries to unset a variable, and if that fails, then tries to unset a
-function. Some variables (such as PATH and IFS) cannot be unset; also
-see readonly.
-$END
-
-#define NEXT_VARIABLE() any_failed++; list = list->next; continue;
-
-unset_builtin (list)
- WORD_LIST *list;
-{
- int unset_function, unset_variable, unset_array, opt, any_failed;
- char *name;
-
- unset_function = unset_variable = unset_array = any_failed = 0;
-
- reset_internal_getopt ();
- while ((opt = internal_getopt (list, "fv")) != -1)
- {
- switch (opt)
- {
- case 'f':
- unset_function = 1;
- break;
- case 'v':
- unset_variable = 1;
- break;
- default:
- builtin_usage ();
- return (EXECUTION_FAILURE);
- }
- }
-
- list = loptend;
-
- if (unset_function && unset_variable)
- {
- builtin_error ("cannot simultaneously unset a function and a variable");
- return (EXECUTION_FAILURE);
- }
-
- while (list)
- {
- SHELL_VAR *var;
- int tem;
-#if defined (ARRAY_VARS)
- char *t;
-#endif
-
- name = list->word->word;
-
-#if defined (ARRAY_VARS)
- if (!unset_function && valid_array_reference (name))
- {
- t = strchr (name, '[');
- *t++ = '\0';
- unset_array++;
- }
-#endif
-
- var = unset_function ? find_function (name) : find_variable (name);
-
- if (var && !unset_function && non_unsettable_p (var))
- {
- builtin_error ("%s: cannot unset", name);
- NEXT_VARIABLE ();
- }
-
- /* Posix.2 says that unsetting readonly variables is an error. */
- if (var && readonly_p (var))
- {
- builtin_error ("%s: cannot unset: readonly %s",
- name, unset_function ? "function" : "variable");
- NEXT_VARIABLE ();
- }
-
- /* Unless the -f option is supplied, the name refers to a variable. */
-#if defined (ARRAY_VARS)
- if (var && unset_array)
- {
- if (array_p (var) == 0)
- {
- builtin_error ("%s: not an array variable", name);
- NEXT_VARIABLE ();
- }
- else
- tem = unbind_array_element (var, t);
- }
- else
-#endif /* ARRAY_VARS */
- tem = makunbound (name, unset_function ? shell_functions : shell_variables);
-
- /* This is what Posix.2 draft 11+ says. ``If neither -f nor -v
- is specified, the name refers to a variable; if a variable by
- that name does not exist, a function by that name, if any,
- shall be unset.'' */
- if ((tem == -1) && !unset_function && !unset_variable)
- tem = makunbound (name, shell_functions);
-
- if (tem == -1)
- any_failed++;
- else if (!unset_function)
- stupidly_hack_special_variables (name);
-
- list = list->next;
- }
-
- if (any_failed)
- return (EXECUTION_FAILURE);
- else
- return (EXECUTION_SUCCESS);
-}
diff --git a/CWRU/save/unwind_prot.h.save b/CWRU/save/unwind_prot.h.save
deleted file mode 100644
index 998fd72b..00000000
--- a/CWRU/save/unwind_prot.h.save
+++ /dev/null
@@ -1,50 +0,0 @@
-/* unwind_prot.h - Macros and functions for hacking unwind protection. */
-
-/* Copyright (C) 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#if !defined (_UNWIND_PROT_H)
-#define _UNWIND_PROT_H
-
-/* Run a function without interrupts. */
-extern void begin_unwind_frame ();
-extern void discard_unwind_frame ();
-extern void run_unwind_frame ();
-extern void add_unwind_protect ();
-extern void remove_unwind_protect ();
-extern void run_unwind_protects ();
-extern void unwind_protect_var ();
-
-/* Define for people who like their code to look a certain way. */
-#define end_unwind_frame()
-
-/* How to protect an integer. */
-#define unwind_protect_int(X) unwind_protect_var (&(X), (char *)(X), sizeof (int))
-
-/* How to protect a pointer to a string. */
-#define unwind_protect_string(X) \
- unwind_protect_var ((int *)&(X), (X), sizeof (char *))
-
-/* How to protect any old pointer. */
-#define unwind_protect_pointer(X) unwind_protect_string (X)
-
-/* How to protect the contents of a jmp_buf. */
-#define unwind_protect_jmp_buf(X) \
- unwind_protect_var ((int *)(X), (char *)(X), sizeof (procenv_t))
-
-#endif /* _UNWIND_PROT_H */
diff --git a/MANIFEST~ b/MANIFEST~
deleted file mode 100644
index 94343f89..00000000
--- a/MANIFEST~
+++ /dev/null
@@ -1,989 +0,0 @@
-#
-# 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/shaccess.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/ru.po f
-po/ru.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/INDEX.txt f
-examples/INDEX.html f
-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.save b/Makefile.in.save
deleted file mode 100644
index 7054cb40..00000000
--- a/Makefile.in.save
+++ /dev/null
@@ -1,1439 +0,0 @@
-# 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~
deleted file mode 100644
index 35cd448e..00000000
--- a/Makefile.in~
+++ /dev/null
@@ -1,1460 +0,0 @@
-# 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)
-
-# Maybe add: -Wextra
-GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wno-parentheses \
- -Wcast-align -Wstrict-prototypes -Wconversion -Wformat \
- -Wformat-nonliteral -Wmissing-braces -Wuninitialized \
- -Wmissing-declarations -Winline \
- -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 \
- ${SH_LIBSRC}/eaccess.c ${SH_LIBSRC}/wcsdup.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@
-SIGNAMES_O = @SIGNAMES_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 $(SIGNAMES_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 buildsignames.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/NOTES~ b/NOTES~
deleted file mode 100644
index c523752f..00000000
--- a/NOTES~
+++ /dev/null
@@ -1,333 +0,0 @@
-Platform-Specific Configuration and Operation Notes
-===================================================
-
-1. configure --without-gnu-malloc on:
-
- alpha running OSF/1, Linux, or NetBSD (malloc needs 8-byte alignment;
- bash malloc has 8-byte alignment now, but I have no alphas to test on)
-
- next running NeXT/OS
-
- all machines running SunOS YP code: SunOS4, SunOS5, HP/UX, if you
- have problems with username completion or tilde expansion for
- usernames found via YP/NIS
-
- linux (optional, but don't do it if you're using Doug Lea's malloc)
-
- QNX 4.2
- other OSF/1 machines (KSR/1, HP, IBM AIX/ESA)
- AIX
- sparc SVR4, SVR4.2 (ICL reference port)
- DG/UX
- Cray
-
- NetBSD/sparc (malloc needs 8-byte alignment; bash malloc has 8-byte
- alignment now, but I have no NetBSD machines to test on)
-
- BSD/OS 2.1, 3.x if you want to use loadable builtins
-
- Motorola m68k machines running System V.3. There is a file descriptor
- leak caused by using the bash malloc because closedir(3) needs to read
- freed memory to find the file descriptor to close
-
-2. Configure using shlicc2 on BSD/OS 2.1 and BSD/OS 3.x to use loadable
- builtins
-
-3. Bash cannot be built in a directory separate from the source directory
- using configure --srcdir=... unless the version of `make' you're using
- does $VPATH handling right. The script support/mkclone can be used to
- create a `build tree' using symlinks to get around this.
-
-4. I've had reports that username completion (as well as tilde expansion
- and \u prompt expansion) does not work on IRIX 5.3 when linking with
- -lnsl. This is only a problem when you're running NIS, since
- apparently -lnsl supports only /etc/passwd and not the NIS functions
- for retrieving usernames and passwords. Editing the Makefile after
- configure runs and removing the `-lnsl' from the assignment to `LIBS'
- fixes the problem.
-
-5. There is a problem with the `makewhatis' script in older (pre-7.0)
- versions of Red Hat Linux. Running `makewhatis' with bash-2.0 or
- later versions results in error messages like this:
-
- /usr/sbin/makewhatis: cd: manpath: No such file or directory
- /usr/sbin/makewhatis: manpath/whatis: No such file or directory
- chmod: manpath/whatis: No such file or directory
- /usr/sbin/makewhatis: cd: catpath: No such file or directory
- /usr/sbin/makewhatis: catpath/whatis: No such file or directory
- chmod: catpath/whatis: No such file or directory
-
- The problem is with `makewhatis'. Red Hat (and possibly other
- Linux distributors) uses a construct like this in the code:
-
- eval path=$"$pages"path
-
- to do indirect variable expansion. This `happened to work' in
- bash-1.14 and previous versions, but that was more an accident
- of implementation than anything else -- it was never supported
- and certainly is not portable.
-
- Bash-2.0 has a new feature that gives a new meaning to $"...".
- This is explained more completely in item 1 in the COMPAT file.
-
- The three lines in the `makewhatis' script that need to be changed
- look like this:
-
- eval $topath=$"$topath":$name
- [...]
- eval path=$"$pages"path
- [...]
- eval path=$"$pages"path
-
- The portable way to write this code is
-
- eval $topath="\$$topath":$name
- eval path="\$$pages"path
- eval path="\$$pages"path
-
- You could also experiment with another new bash feature: ${!var}.
- This does indirect variable expansion, making the use of eval
- unnecessary.
-
-6. There is a problem with syslogd on many Linux distributions (Red Hat
- and Slackware are two that I have received reports about). syslogd
- sends a SIGINT to its parent process, which is waiting for the daemon
- to finish its initialization. The parent process then dies due to
- the SIGINT, and bash reports it, causing unexpected console output
- while the system is booting that looks something like
-
- starting daemons: syslogd/etc/rc.d/rc.M: line 29: 38 Interrupt ${NET}/syslogd
-
- Bash-2.0 reports events such as processes dying in scripts due to
- signals when the standard output is a tty. Bash-1.14.x and previous
- versions did not report such events.
-
- This should probably be reported as a bug to whatever Linux distributor
- people see the problem on. In my opinion, syslogd should be changed to
- use some other method of communication, or the wrapper function (which
- appeared to be `daemon' when I looked at it some time ago) or script
- (which appeared to be `syslog') should catch SIGINT, since it's an
- expected event, and exit cleanly.
-
-7. Several people have reported that `dip' (a program for SLIP/PPP
- on Linux) does not work with bash-2.0 installed as /bin/sh.
-
- I don't run any Linux boxes myself, and do not have the dip
- code handy to look at, but the `problem' with bash-2.0, as
- it has been related to me, is that bash requires the `-p'
- option to be supplied at invocation if it is to run setuid
- or setgid.
-
- This means, among other things, that setuid or setgid programs
- which call system(3) (a horrendously bad practice in any case)
- relinquish their setuid/setgid status in the child that's forked
- to execute /bin/sh.
-
- The following is an *unofficial* patch to bash-2.0 that causes it
- to not require `-p' to run setuid or setgid if invoked as `sh'.
- It has been reported to work on Linux. It will make your system
- vulnerable to bogus system(3) calls in setuid executables.
-
---- ../bash-2.0.orig/shell.c Wed Dec 18 14:16:30 1996
-+++ shell.c Fri Mar 7 13:12:03 1997
-@@ -347,7 +347,7 @@
- if (posixly_correct)
- posix_initialize (posixly_correct);
-
-- if (running_setuid && privileged_mode == 0)
-+ if (running_setuid && privileged_mode == 0 && act_like_sh == 0)
- disable_priv_mode ();
-
- /* Need to get the argument to a -c option processed in the
-
-8. Some people have asked about binding all of the keys in a PC-keyboard-
- style numeric keypad to readline functions. Here's something I
- received from the gnu-win32 list that may help. Insert the following
- lines into ~/.inputrc:
-
-# home key
-"\e[1~":beginning-of-line
-# insert key
-"\e[2~":kill-whole-line
-# del key
-"\e[3~":delete-char
-# end key
-"\e[4~":end-of-line
-# pgup key
-"\e[5~":history-search-forward
-# pgdn key
-"\e[6~":history-search-backward
-
-9. Hints for building under Minix 2.0 (Contributed by Terry R. McConnell,
- <tmc@barnyard.syr.edu>)
-
- The version of /bin/sh distributed with Minix is not up to the job of
- running the configure script. The easiest solution is to swap /bin/sh
- with /usr/bin/ash. Then use chmem(1) to increase the memory allocated
- to /bin/sh. The following settings are known to work:
-
- text data bss stack memory
- 63552 9440 3304 65536 141832 /bin/sh
-
- If you have problems with make or yacc it may be worthwhile first to
- install the GNU versions of these utilities before attempting to build
- bash. (As of this writing, all of these utilities are available for the
- i386 as pre-built binaries via anonymous ftp at math.syr.edu in the
- pub/mcconnell/minix directory. Note that the GNU version of yacc is called
- bison.)
-
- Unless you want to see lots of warnings about old-style declarations,
- do LOCAL_CFLAGS=-wo; export LOCAL_CFLAGS before running configure.
- (These warnings are harmless, but annoying.)
-
- configure will insist that you supply a host type. For example, do
- ./configure --host=i386-pc-minix.
-
- Minix does not support the system calls required for a proper
- implementation of ulimit(). The `ulimit' builtin will not be available.
-
- Configure will fail to notice that many things like uid_t are indeed
- typedef'd in <sys/types.h>, because it uses egrep for this purpose
- and minix has no egrep. You could try making a link /usr/bin/egrep -->
- /usr/bin/grep. Better is to install the GNU version of grep in
- /usr/local/bin and make the link /usr/local/bin/egrep -->/usr/local/bin/grep.
- (These must be hard links, of course, since Minix does not support
- symbolic links.)
-
- You will see many warnings of the form:
- warning: unknown s_type: 98
- I have no idea what this means, but it doesn't seem to matter.
-
-10. If you do not have /usr/ccs/bin in your PATH when building on SunOS 5.x
- (Solaris 2), the configure script will be unable to find `ar' and
- `ranlib' (of course, ranlib is unnecessary). Make sure your $PATH
- includes /usr/ccs/bin on SunOS 5.x. This generally manifests itself
- with libraries not being built and make reporting errors like
- `cr: not found' when library construction is attempted.
-
-11. Building a statically-linked bash on Solaris 2.5.x, 2.6, 7, or 8 is
- complicated.
-
- It's not possible to build a completely statically-linked binary, since
- part of the C library depends on dynamic linking. The following recipe
- assumes that you're using gcc and the Solaris ld (/usr/ccs/bin/ld) on
- Solaris 2.5.x or 2.6:
-
- configure --enable-static-link
- make STATIC_LD= LOCAL_LIBS='-Wl,-B,dynamic -ldl -Wl,-B,static'
-
- This should result in a bash binary that depends only on libdl.so:
-
- thor(2)$ ldd bash
- libdl.so.1 => /usr/lib/libdl.so.1
-
- If you're using the Sun C Compiler (Sun WorkShop C Compiler version
- 4.2 was what I used), you should be able to get away with using
-
- configure --enable-static-link
- make STATIC_LD= LOCAL_LIBS='-B dynamic -ldl -B static'
-
- If you want to completely remove any dependence on /usr, perhaps
- to put a copy of bash in /sbin and have it available when /usr is
- not mounted, force the build process to use the shared dl.so library
- in /etc/lib.
-
- For gcc, this would be something like
-
- configure --enable-static-link
- make STATIC_LD= LOCAL_LIBS='-Wl,-B,dynamic -Wl,-R/etc/lib -ldl -Wl,-B,static'
-
- For Sun's WS4.2 cc
-
- configure --enable-static-link
- make STATIC_LD= LOCAL_LIBS='-B dynamic -R/etc/lib -ldl -B static'
-
- seems to work, at least on Solaris 2.5.1:
-
- thor(2)$ ldd bash
- libdl.so.1 => /etc/lib/libdl.so.1
-
- On Solaris 7 (Solaris 8, using the version of gcc on the free software
- CD-ROM), the following recipe appears to work for gcc:
-
- configure --enable-static-link
- make STATIC_LD='-Wl,-Bstatic' LOCAL_LIBS='-Wl,-Bdynamic -Wl,-R/etc/lib -ldl -Wl,-Bstatic'
-
- thor.ins.cwru.edu(2)$ ldd bash
- libdl.so.1 => /etc/lib/libdl.so.1
-
- Make the analogous changes if you are running Sun's C Compiler.
-
- I have received word that adding -L/etc/lib (or the equivalent
- -Wl,-L/etc/lib) might also be necessary, in addition to the -R/etc/lib.
-
-12. Configuring bash to build it in a cross environment. Currently only
- two native versions can be compiled this way, cygwin32 and x86 BeOS.
- For BeOS, you would configure it like this:
-
- export RANLIB=i586-beos-ranlib
- export AR=i586-beos-ar
- export CC=i586-beos-gcc
- configure i586-beos
-
- Similarly for cygwin32.
-
-13. Bash-2.05 has reverted to the bash-2.03 behavior of honoring the current
- locale setting when processing ranges within pattern matching bracket
- expressions ([A-Z]). This is what POSIX.2 and SUSv2 specify.
-
- The behavior of the matcher in bash-2.05 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'.
-
- 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.
-
-14. Building on Interix (nee OpenNT), which Microsoft bought from Softway
- Systems and has seemingly abandoned (thanks to Kevin Moore for this item).
-
- 1. cp cross-build/opennt.cache config.cache
-
- 2. If desired, edit pathnames.h to set the values of SYS_PROFILE and
- DEFAULT_HOSTS_FILE appropriately.
-
- 3. export CONFIG_SHELL=$INTERIX_ROOT/bin/sh
-
- 4. ./configure --prefix=$INTERIX_ROOT/usr/local (or wherever you
- want it).
-
- 5. make; make install; enjoy
-
-15. Configure with `CC=xlc' if you don't have gcc on AIX 4.2 and later
- versions. `xlc' running in `cc' mode has trouble compiling error.c.
-
-16. Configure --disable-multibyte on NetBSD versions (1.4 through at least
- 1.6.1) that include wctype.h but do not define wctype_t.
-
-17. Do NOT use bison-1.75. It builds a non-working parser. The most
- obvious effect is that constructs like "for i; do echo $i; done" don't
- loop over the positional parameters.
diff --git a/aclocal.m4~ b/aclocal.m4~
deleted file mode 100644
index ad08b239..00000000
--- a/aclocal.m4~
+++ /dev/null
@@ -1,3966 +0,0 @@
-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,
-[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<&-
-fi
-if test -z "$bash_cv_dev_fd" ; then
- if 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
-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.save b/arrayfunc.c.save
deleted file mode 100644
index 6073a343..00000000
--- a/arrayfunc.c.save
+++ /dev/null
@@ -1,817 +0,0 @@
-/* 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;
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
- memset (&state, '\0', sizeof (mbstate_t));
- slength = strlen (s + i);
-#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, 0);
- 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/arrayfunc.c~ b/arrayfunc.c~
deleted file mode 100644
index 43d13d64..00000000
--- a/arrayfunc.c~
+++ /dev/null
@@ -1,844 +0,0 @@
-/* arrayfunc.c -- High-level array functions used by other parts of the shell. */
-
-/* Copyright (C) 2001-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"
-
-#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;
-}
-
-static WORD_LIST empty_compound_list;
-
-WORD_LIST *
-expand_compound_array_assignment (value, flags)
- char *value;
- int flags;
-{
- WORD_LIST *list, *nlist;
- char *val;
- int ni;
- arrayind_t ind, last_ind;
-
- /* 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 &empty_compound_list;
- }
- 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);
-
- return nlist;
-}
-
-void
-assign_compound_array_list (var, nlist, flags)
- SHELL_VAR *var;
- WORD_LIST *nlist;
- int flags;
-{
- ARRAY *a;
- WORD_LIST *list;
- char *w, *val, *nval;
- int len, iflags;
- arrayind_t ind, last_ind;
-
- 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)
- {
- iflags = flags;
- 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);
-
- /* XXX - changes for `+=' */
- if (w[len] != ']' || (w[len+1] != '=' && (w[len+1] != '+' || w[len+2] != '=')))
- {
- 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 `+=' -- just accept the syntax. ksh93 doesn't do this */
- if (w[len + 1] == '+' && w[len + 2] == '=')
- {
- iflags |= 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, iflags);
- last_ind++;
- }
-}
-
-/* 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;
-{
- WORD_LIST *nlist;
-
- if (value == 0)
- return var;
-
- nlist = expand_compound_array_assignment (value, flags);
- if (nlist == &empty_compound_list)
- return var;
-
- assign_compound_array_list (var, nlist, flags);
-
- 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;
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
- memset (&state, '\0', sizeof (mbstate_t));
- slength = strlen (s + i);
-#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, 0);
- 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/arrayfunc.h.save b/arrayfunc.h.save
deleted file mode 100644
index 3c4f9a07..00000000
--- a/arrayfunc.h.save
+++ /dev/null
@@ -1,55 +0,0 @@
-/* arrayfunc.h -- declarations for miscellaneous array functions in arrayfunc.c */
-
-/* Copyright (C) 2001-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 (_ARRAYFUNC_H_)
-#define _ARRAYFUNC_H_
-
-/* Must include variables.h before including this file. */
-
-#if defined (ARRAY_VARS)
-
-extern SHELL_VAR *convert_var_to_array __P((SHELL_VAR *));
-
-extern SHELL_VAR *bind_array_variable __P((char *, arrayind_t, char *, int));
-extern SHELL_VAR *assign_array_element __P((char *, char *, int));
-
-extern SHELL_VAR *find_or_make_array_variable __P((char *, int));
-
-extern SHELL_VAR *assign_array_from_string __P((char *, char *, int));
-extern SHELL_VAR *assign_array_var_from_word_list __P((SHELL_VAR *, WORD_LIST *, int));
-extern SHELL_VAR *assign_array_var_from_string __P((SHELL_VAR *, char *, int));
-
-extern int unbind_array_element __P((SHELL_VAR *, char *));
-extern int skipsubscript __P((const char *, int));
-extern void print_array_assignment __P((SHELL_VAR *, int));
-
-extern arrayind_t array_expand_index __P((char *, int));
-extern int valid_array_reference __P((char *));
-extern char *array_value __P((char *, int, int *));
-extern char *get_array_value __P((char *, int, int *));
-
-extern char *array_keys __P((char *, int));
-
-extern char *array_variable_name __P((char *, char **, int *));
-extern SHELL_VAR *array_variable_part __P((char *, char **, int *));
-
-#endif
-
-#endif /* !_ARRAYFUNC_H_ */
diff --git a/arrayfunc.h~ b/arrayfunc.h~
deleted file mode 100644
index 8545d79e..00000000
--- a/arrayfunc.h~
+++ /dev/null
@@ -1,58 +0,0 @@
-/* arrayfunc.h -- declarations for miscellaneous array functions in arrayfunc.c */
-
-/* Copyright (C) 2001-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 (_ARRAYFUNC_H_)
-#define _ARRAYFUNC_H_
-
-/* Must include variables.h before including this file. */
-
-#if defined (ARRAY_VARS)
-
-extern SHELL_VAR *convert_var_to_array __P((SHELL_VAR *));
-
-extern SHELL_VAR *bind_array_variable __P((char *, arrayind_t, char *, int));
-extern SHELL_VAR *assign_array_element __P((char *, char *, int));
-
-extern SHELL_VAR *find_or_make_array_variable __P((char *, int));
-
-extern SHELL_VAR *assign_array_from_string __P((char *, char *, int));
-extern SHELL_VAR *assign_array_var_from_word_list __P((SHELL_VAR *, WORD_LIST *, int));
-
-extern WORD_LIST *expand_compound_array_assignment __P((char *, int))
-extern void assign_compound_array_list __P((SHELL_VAR *, WORD_LIST *, int));
-extern SHELL_VAR *assign_array_var_from_string __P((SHELL_VAR *, char *, int));
-
-extern int unbind_array_element __P((SHELL_VAR *, char *));
-extern int skipsubscript __P((const char *, int));
-extern void print_array_assignment __P((SHELL_VAR *, int));
-
-extern arrayind_t array_expand_index __P((char *, int));
-extern int valid_array_reference __P((char *));
-extern char *array_value __P((char *, int, int *));
-extern char *get_array_value __P((char *, int, int *));
-
-extern char *array_keys __P((char *, int));
-
-extern char *array_variable_name __P((char *, char **, int *));
-extern SHELL_VAR *array_variable_part __P((char *, char **, int *));
-
-#endif
-
-#endif /* !_ARRAYFUNC_H_ */
diff --git a/bashhist.c~ b/bashhist.c~
deleted file mode 100644
index 5d2b8174..00000000
--- a/bashhist.c~
+++ /dev/null
@@ -1,820 +0,0 @@
-/* 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/bashline.c~ b/bashline.c~
deleted file mode 100644
index 4b11de92..00000000
--- a/bashline.c~
+++ /dev/null
@@ -1,3198 +0,0 @@
-/* bashline.c -- Bash's interface to the readline library. */
-
-/* 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. */
-
-#include "config.h"
-
-#if defined (READLINE)
-
-#include "bashtypes.h"
-#include "posixstat.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_GRP_H)
-# include <grp.h>
-#endif
-
-#if defined (HAVE_NETDB_H)
-# include <netdb.h>
-#endif
-
-#include <stdio.h>
-#include "chartypes.h"
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include "shell.h"
-#include "input.h"
-#include "builtins.h"
-#include "bashhist.h"
-#include "bashline.h"
-#include "execute_cmd.h"
-#include "findcmd.h"
-#include "pathexp.h"
-#include "builtins/common.h"
-#include <readline/rlconf.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-
-#include <glob/glob.h>
-
-#if defined (ALIAS)
-# include "alias.h"
-#endif
-
-#if defined (PROGRAMMABLE_COMPLETION)
-# include "pcomplete.h"
-#endif
-
-/* These should agree with the defines for emacs_mode and vi_mode in
- rldefs.h, even though that's not a public readline header file. */
-#ifndef EMACS_EDITING_MODE
-# define NO_EDITING_MODE -1
-# define EMACS_EDITING_MODE 1
-# define VI_EDITING_MODE 0
-#endif
-
-#if defined (BRACE_COMPLETION)
-extern int bash_brace_completion __P((int, int));
-#endif /* BRACE_COMPLETION */
-
-/* Forward declarations */
-
-/* Functions bound to keys in Readline for Bash users. */
-static int shell_expand_line __P((int, int));
-static int display_shell_version __P((int, int));
-static int operate_and_get_next __P((int, int));
-
-static int bash_ignore_filenames __P((char **));
-static int bash_ignore_everything __P((char **));
-
-#if defined (BANG_HISTORY)
-static char *history_expand_line_internal __P((char *));
-static int history_expand_line __P((int, int));
-static int tcsh_magic_space __P((int, int));
-#endif /* BANG_HISTORY */
-#ifdef ALIAS
-static int alias_expand_line __P((int, int));
-#endif
-#if defined (BANG_HISTORY) && defined (ALIAS)
-static int history_and_alias_expand_line __P((int, int));
-#endif
-
-/* Helper functions for Readline. */
-static void bash_directory_expansion __P((char **));
-static int bash_directory_completion_hook __P((char **));
-static int filename_completion_ignore __P((char **));
-static int bash_push_line __P((void));
-
-static void cleanup_expansion_error __P((void));
-static void maybe_make_readline_line __P((char *));
-static void set_up_new_line __P((char *));
-
-static int check_redir __P((int));
-static char **attempt_shell_completion __P((const char *, int, int));
-static char *variable_completion_function __P((const char *, int));
-static char *hostname_completion_function __P((const char *, int));
-static char *command_subst_completion_function __P((const char *, int));
-
-static void build_history_completion_array __P((void));
-static char *history_completion_generator __P((const char *, int));
-static int dynamic_complete_history __P((int, int));
-
-static void initialize_hostname_list __P((void));
-static void add_host_name __P((char *));
-static void snarf_hosts_from_file __P((char *));
-static char **hostnames_matching __P((char *));
-
-static void _ignore_completion_names __P((char **, sh_ignore_func_t *));
-static int name_is_acceptable __P((const char *));
-static int test_for_directory __P((const char *));
-static int return_zero __P((const char *));
-
-static char *bash_dequote_filename __P((char *, int));
-static char *quote_word_break_chars __P((char *));
-static char *bash_quote_filename __P((char *, int, char *));
-
-static int bash_execute_unix_command __P((int, int));
-static void init_unix_command_map __P((void));
-static int isolate_sequence __P((char *, int, int, int *));
-
-static int set_saved_history __P((void));
-
-#if defined (ALIAS)
-static int posix_edit_macros __P((int, int));
-#endif
-
-#if defined (PROGRAMMABLE_COMPLETION)
-static int find_cmd_start __P((int));
-static int find_cmd_end __P((int));
-static char *find_cmd_name __P((int));
-static char *prog_complete_return __P((const char *, int));
-
-static char **prog_complete_matches;
-#endif
-
-/* Variables used here but defined in other files. */
-#if defined (BANG_HISTORY)
-extern int hist_verify;
-#endif
-
-extern int current_command_line_count, last_command_exit_value;
-extern int posixly_correct, no_symbolic_links;
-extern char *current_prompt_string, *ps1_prompt;
-extern STRING_INT_ALIST word_token_alist[];
-extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
-
-/* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
- completion functions which indicate what type of completion should be
- done (at or before point) that can be bound to key sequences with
- the readline library. */
-#define SPECIFIC_COMPLETION_FUNCTIONS
-
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
-static int bash_specific_completion __P((int, rl_compentry_func_t *));
-
-static int bash_complete_filename_internal __P((int));
-static int bash_complete_username_internal __P((int));
-static int bash_complete_hostname_internal __P((int));
-static int bash_complete_variable_internal __P((int));
-static int bash_complete_command_internal __P((int));
-
-static int bash_complete_filename __P((int, int));
-static int bash_possible_filename_completions __P((int, int));
-static int bash_complete_username __P((int, int));
-static int bash_possible_username_completions __P((int, int));
-static int bash_complete_hostname __P((int, int));
-static int bash_possible_hostname_completions __P((int, int));
-static int bash_complete_variable __P((int, int));
-static int bash_possible_variable_completions __P((int, int));
-static int bash_complete_command __P((int, int));
-static int bash_possible_command_completions __P((int, int));
-
-static char *glob_complete_word __P((const char *, int));
-static int bash_glob_completion_internal __P((int));
-static int bash_glob_complete_word __P((int, int));
-static int bash_glob_expand_word __P((int, int));
-static int bash_glob_list_expansions __P((int, int));
-
-#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
-
-static int edit_and_execute_command __P((int, int, int, char *));
-#if defined (VI_MODE)
-static int vi_edit_and_execute_command __P((int, int));
-static int bash_vi_complete __P((int, int));
-#endif
-static int emacs_edit_and_execute_command __P((int, int));
-
-/* Non-zero once initalize_readline () has been called. */
-int bash_readline_initialized = 0;
-
-/* If non-zero, we do hostname completion, breaking words at `@' and
- trying to complete the stuff after the `@' from our own internal
- host list. */
-int perform_hostname_completion = 1;
-
-/* If non-zero, we don't do command completion on an empty line. */
-int no_empty_command_completion;
-
-/* Set FORCE_FIGNORE if you want to honor FIGNORE even if it ignores the
- only possible matches. Set to 0 if you want to match filenames if they
- are the only possible matches, even if FIGNORE says to. */
-int force_fignore = 1;
-
-static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
-static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
-/* )) */
-
-static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
-
-static int dot_in_path = 0;
-
-/* What kind of quoting is performed by bash_quote_filename:
- COMPLETE_DQUOTE = double-quoting the filename
- COMPLETE_SQUOTE = single_quoting the filename
- COMPLETE_BSQUOTE = backslash-quoting special chars in the filename
-*/
-#define COMPLETE_DQUOTE 1
-#define COMPLETE_SQUOTE 2
-#define COMPLETE_BSQUOTE 3
-static int completion_quoting_style = COMPLETE_BSQUOTE;
-
-/* Flag values for the final argument to bash_default_completion */
-#define DEFCOMP_CMDPOS 1
-
-/* Change the readline VI-mode keymaps into or out of Posix.2 compliance.
- Called when the shell is put into or out of `posix' mode. */
-void
-posix_readline_initialize (on_or_off)
- int on_or_off;
-{
- if (on_or_off)
- rl_variable_bind ("comment-begin", "#");
-#if defined (VI_MODE)
- rl_bind_key_in_map (CTRL ('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap);
-#endif
-}
-
-/* When this function returns, rl_completer_word_break_characters points to
- dynamically allocated memory. */
-int
-enable_hostname_completion (on_or_off)
- int on_or_off;
-{
- int old_value;
- char *at, *nv, *nval;
-
- old_value = perform_hostname_completion;
-
- if (on_or_off)
- {
- perform_hostname_completion = 1;
- rl_special_prefixes = "$@";
- }
- else
- {
- perform_hostname_completion = 0;
- rl_special_prefixes = "$";
- }
-
- /* Now we need to figure out how to appropriately modify and assign
- rl_completer_word_break_characters depending on whether we want
- hostname completion on or off. */
-
- /* If this is the first time this has been called
- (bash_readline_initialized == 0), use the sames values as before, but
- allocate new memory for rl_completer_word_break_characters. */
-
- if (bash_readline_initialized == 0 &&
- (rl_completer_word_break_characters == 0 ||
- rl_completer_word_break_characters == rl_basic_word_break_characters))
- {
- if (on_or_off)
- rl_completer_word_break_characters = savestring (bash_completer_word_break_characters);
- else
- rl_completer_word_break_characters = savestring (bash_nohostname_word_break_characters);
- }
- else
- {
- /* See if we have anything to do. */
- at = strchr (rl_completer_word_break_characters, '@');
- if ((at == 0 && on_or_off == 0) || (at != 0 && on_or_off != 0))
- return old_value;
-
- /* We have something to do. Do it. */
- nval = (char *)xmalloc (strlen (rl_completer_word_break_characters) + 1 + on_or_off);
-
- if (on_or_off == 0)
- {
- /* Turn it off -- just remove `@' from word break chars. We want
- to remove all occurrences of `@' from the char list, so we loop
- rather than just copy the rest of the list over AT. */
- for (nv = nval, at = rl_completer_word_break_characters; *at; )
- if (*at != '@')
- *nv++ = *at++;
- else
- at++;
- *nv = '\0';
- }
- else
- {
- nval[0] = '@';
- strcpy (nval + 1, rl_completer_word_break_characters);
- }
-
- free (rl_completer_word_break_characters);
- rl_completer_word_break_characters = nval;
- }
-
- return (old_value);
-}
-
-/* Called once from parse.y if we are going to use readline. */
-void
-initialize_readline ()
-{
- rl_command_func_t *func;
- char kseq[2];
-
- if (bash_readline_initialized)
- return;
-
- rl_terminal_name = get_string_value ("TERM");
- rl_instream = stdin;
- rl_outstream = stderr;
-
- /* Allow conditional parsing of the ~/.inputrc file. */
- rl_readline_name = "Bash";
-
- /* Add bindable names before calling rl_initialize so they may be
- referenced in the various inputrc files. */
- rl_add_defun ("shell-expand-line", shell_expand_line, -1);
-#ifdef BANG_HISTORY
- rl_add_defun ("history-expand-line", history_expand_line, -1);
- rl_add_defun ("magic-space", tcsh_magic_space, -1);
-#endif
-
-#ifdef ALIAS
- rl_add_defun ("alias-expand-line", alias_expand_line, -1);
-# ifdef BANG_HISTORY
- rl_add_defun ("history-and-alias-expand-line", history_and_alias_expand_line, -1);
-# endif
-#endif
-
- /* Backwards compatibility. */
- rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
-
- rl_add_defun ("operate-and-get-next", operate_and_get_next, -1);
- rl_add_defun ("display-shell-version", display_shell_version, -1);
- rl_add_defun ("edit-and-execute-command", emacs_edit_and_execute_command, -1);
-
-#if defined (BRACE_COMPLETION)
- rl_add_defun ("complete-into-braces", bash_brace_completion, -1);
-#endif
-
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
- rl_add_defun ("complete-filename", bash_complete_filename, -1);
- rl_add_defun ("possible-filename-completions", bash_possible_filename_completions, -1);
- rl_add_defun ("complete-username", bash_complete_username, -1);
- rl_add_defun ("possible-username-completions", bash_possible_username_completions, -1);
- rl_add_defun ("complete-hostname", bash_complete_hostname, -1);
- rl_add_defun ("possible-hostname-completions", bash_possible_hostname_completions, -1);
- rl_add_defun ("complete-variable", bash_complete_variable, -1);
- rl_add_defun ("possible-variable-completions", bash_possible_variable_completions, -1);
- rl_add_defun ("complete-command", bash_complete_command, -1);
- rl_add_defun ("possible-command-completions", bash_possible_command_completions, -1);
- rl_add_defun ("glob-complete-word", bash_glob_complete_word, -1);
- rl_add_defun ("glob-expand-word", bash_glob_expand_word, -1);
- rl_add_defun ("glob-list-expansions", bash_glob_list_expansions, -1);
-#endif
-
- rl_add_defun ("dynamic-complete-history", dynamic_complete_history, -1);
-
- /* Bind defaults before binding our custom shell keybindings. */
- if (RL_ISSTATE(RL_STATE_INITIALIZED) == 0)
- rl_initialize ();
-
- /* Bind up our special shell functions. */
- rl_bind_key_if_unbound_in_map (CTRL('E'), shell_expand_line, emacs_meta_keymap);
-
-#ifdef BANG_HISTORY
- rl_bind_key_if_unbound_in_map ('^', history_expand_line, emacs_meta_keymap);
-#endif
-
- rl_bind_key_if_unbound_in_map (CTRL ('O'), operate_and_get_next, emacs_standard_keymap);
- rl_bind_key_if_unbound_in_map (CTRL ('V'), display_shell_version, emacs_ctlx_keymap);
-
- /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
- so it is not necessary to allow C-M-j for context switching. Turn
- off this occasionally confusing behaviour. */
- kseq[0] = CTRL('J');
- kseq[1] = '\0';
- func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
- if (func == rl_vi_editing_mode)
- rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
- kseq[0] = CTRL('M');
- func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
- if (func == rl_vi_editing_mode)
- rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
-#if defined (VI_MODE)
- rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);
-#endif
-
-#if defined (BRACE_COMPLETION)
- rl_bind_key_if_unbound_in_map ('{', bash_brace_completion, emacs_meta_keymap); /*}*/
-#endif /* BRACE_COMPLETION */
-
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
- rl_bind_key_if_unbound_in_map ('/', bash_complete_filename, emacs_meta_keymap);
- rl_bind_key_if_unbound_in_map ('/', bash_possible_filename_completions, emacs_ctlx_keymap);
-
- /* Have to jump through hoops here because there is a default binding for
- M-~ (rl_tilde_expand) */
- kseq[0] = '~';
- kseq[1] = '\0';
- func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
- if (func == 0 || func == rl_tilde_expand)
- rl_bind_keyseq_in_map (kseq, bash_complete_username, emacs_meta_keymap);
-
- rl_bind_key_if_unbound_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap);
-
- rl_bind_key_if_unbound_in_map ('@', bash_complete_hostname, emacs_meta_keymap);
- rl_bind_key_if_unbound_in_map ('@', bash_possible_hostname_completions, emacs_ctlx_keymap);
-
- rl_bind_key_if_unbound_in_map ('$', bash_complete_variable, emacs_meta_keymap);
- rl_bind_key_if_unbound_in_map ('$', bash_possible_variable_completions, emacs_ctlx_keymap);
-
- rl_bind_key_if_unbound_in_map ('!', bash_complete_command, emacs_meta_keymap);
- rl_bind_key_if_unbound_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap);
-
- rl_bind_key_if_unbound_in_map ('g', bash_glob_complete_word, emacs_meta_keymap);
- rl_bind_key_if_unbound_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap);
- rl_bind_key_if_unbound_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap);
-
-#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
-
- kseq[0] = TAB;
- kseq[1] = '\0';
- func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
- if (func == 0 || func == rl_tab_insert)
- rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap);
-
- /* Tell the completer that we want a crack first. */
- rl_attempted_completion_function = attempt_shell_completion;
-
- /* Tell the completer that we might want to follow symbolic links or
- do other expansion on directory names. */
- rl_directory_completion_hook = bash_directory_completion_hook;
-
- /* Tell the filename completer we want a chance to ignore some names. */
- rl_ignore_some_completions_function = filename_completion_ignore;
-
- /* Bind C-xC-e to invoke emacs and run result as commands. */
- rl_bind_key_if_unbound_in_map (CTRL ('E'), emacs_edit_and_execute_command, emacs_ctlx_keymap);
-#if defined (VI_MODE)
- rl_bind_key_if_unbound_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);
-# if defined (ALIAS)
- rl_bind_key_if_unbound_in_map ('@', posix_edit_macros, vi_movement_keymap);
-# endif
-
- rl_bind_key_in_map ('\\', bash_vi_complete, vi_movement_keymap);
- rl_bind_key_in_map ('*', bash_vi_complete, vi_movement_keymap);
- rl_bind_key_in_map ('=', bash_vi_complete, vi_movement_keymap);
-#endif
-
- rl_completer_quote_characters = "'\"";
-
- /* This sets rl_completer_word_break_characters and rl_special_prefixes
- to the appropriate values, depending on whether or not hostname
- completion is enabled. */
- enable_hostname_completion (perform_hostname_completion);
-
- /* characters that need to be quoted when appearing in filenames. */
- rl_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{"; /*}*/
- rl_filename_quoting_function = bash_quote_filename;
- rl_filename_dequoting_function = bash_dequote_filename;
- rl_char_is_quoted_p = char_is_quoted;
-
-#if 0
- /* This is superfluous and makes it impossible to use tab completion in
- vi mode even when explicitly binding it in ~/.inputrc. sv_strict_posix()
- should already have called posix_readline_initialize() when
- posixly_correct was set. */
- if (posixly_correct)
- posix_readline_initialize (1);
-#endif
-
- bash_readline_initialized = 1;
-}
-
-/* On Sun systems at least, rl_attempted_completion_function can end up
- getting set to NULL, and rl_completion_entry_function set to do command
- word completion if Bash is interrupted while trying to complete a command
- word. This just resets all the completion functions to the right thing.
- It's called from throw_to_top_level(). */
-void
-bashline_reinitialize ()
-{
- tilde_initialize ();
- rl_attempted_completion_function = attempt_shell_completion;
- rl_completion_entry_function = NULL;
- rl_directory_completion_hook = bash_directory_completion_hook;
- rl_ignore_some_completions_function = filename_completion_ignore;
-}
-
-/* Contains the line to push into readline. */
-static char *push_to_readline = (char *)NULL;
-
-/* Push the contents of push_to_readline into the
- readline buffer. */
-static int
-bash_push_line ()
-{
- if (push_to_readline)
- {
- rl_insert_text (push_to_readline);
- free (push_to_readline);
- push_to_readline = (char *)NULL;
- rl_startup_hook = old_rl_startup_hook;
- }
- return 0;
-}
-
-/* Call this to set the initial text for the next line to read
- from readline. */
-int
-bash_re_edit (line)
- char *line;
-{
- FREE (push_to_readline);
-
- push_to_readline = savestring (line);
- old_rl_startup_hook = rl_startup_hook;
- rl_startup_hook = bash_push_line;
-
- return (0);
-}
-
-static int
-display_shell_version (count, c)
- int count, c;
-{
- rl_crlf ();
- show_shell_version (0);
- putc ('\r', rl_outstream);
- fflush (rl_outstream);
- rl_on_new_line ();
- rl_redisplay ();
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* Readline Stuff */
-/* */
-/* **************************************************************** */
-
-/* If the user requests hostname completion, then simply build a list
- of hosts, and complete from that forever more, or at least until
- HOSTFILE is unset. */
-
-/* THIS SHOULD BE A STRINGLIST. */
-/* The kept list of hostnames. */
-static char **hostname_list = (char **)NULL;
-
-/* The physical size of the above list. */
-static int hostname_list_size;
-
-/* The number of hostnames in the above list. */
-static int hostname_list_length;
-
-/* Whether or not HOSTNAME_LIST has been initialized. */
-int hostname_list_initialized = 0;
-
-/* Initialize the hostname completion table. */
-static void
-initialize_hostname_list ()
-{
- char *temp;
-
- temp = get_string_value ("HOSTFILE");
- if (temp == 0)
- temp = get_string_value ("hostname_completion_file");
- if (temp == 0)
- temp = DEFAULT_HOSTS_FILE;
-
- snarf_hosts_from_file (temp);
-
- if (hostname_list)
- hostname_list_initialized++;
-}
-
-/* Add NAME to the list of hosts. */
-static void
-add_host_name (name)
- char *name;
-{
- if (hostname_list_length + 2 > hostname_list_size)
- {
- hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32);
- hostname_list = strvec_resize (hostname_list, hostname_list_size);
- }
-
- hostname_list[hostname_list_length++] = savestring (name);
- hostname_list[hostname_list_length] = (char *)NULL;
-}
-
-#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
-
-static void
-snarf_hosts_from_file (filename)
- char *filename;
-{
- FILE *file;
- char *temp, buffer[256], name[256];
- register int i, start;
-
- file = fopen (filename, "r");
- if (file == 0)
- return;
-
- while (temp = fgets (buffer, 255, file))
- {
- /* Skip to first character. */
- for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++)
- ;
-
- /* If comment or blank line, ignore. */
- if (buffer[i] == '\0' || buffer[i] == '#')
- continue;
-
- /* If `preprocessor' directive, do the include. */
- if (strncmp (buffer + i, "$include ", 9) == 0)
- {
- char *incfile, *t;
-
- /* Find start of filename. */
- for (incfile = buffer + i + 9; *incfile && whitespace (*incfile); incfile++)
- ;
-
- /* Find end of filename. */
- for (t = incfile; *t && cr_whitespace (*t) == 0; t++)
- ;
-
- *t = '\0';
-
- snarf_hosts_from_file (incfile);
- continue;
- }
-
- /* Skip internet address if present. */
- if (DIGIT (buffer[i]))
- for (; buffer[i] && cr_whitespace (buffer[i]) == 0; i++);
-
- /* Gobble up names. Each name is separated with whitespace. */
- while (buffer[i])
- {
- for (; cr_whitespace (buffer[i]); i++)
- ;
- if (buffer[i] == '\0' || buffer[i] == '#')
- break;
-
- /* Isolate the current word. */
- for (start = i; buffer[i] && cr_whitespace (buffer[i]) == 0; i++)
- ;
- if (i == start)
- continue;
- strncpy (name, buffer + start, i - start);
- name[i - start] = '\0';
- add_host_name (name);
- }
- }
- fclose (file);
-}
-
-/* Return the hostname list. */
-char **
-get_hostname_list ()
-{
- if (hostname_list_initialized == 0)
- initialize_hostname_list ();
- return (hostname_list);
-}
-
-void
-clear_hostname_list ()
-{
- register int i;
-
- if (hostname_list_initialized == 0)
- return;
- for (i = 0; i < hostname_list_length; i++)
- free (hostname_list[i]);
- hostname_list_length = 0;
-}
-
-/* Return a NULL terminated list of hostnames which begin with TEXT.
- Initialize the hostname list the first time if neccessary.
- The array is malloc ()'ed, but not the individual strings. */
-static char **
-hostnames_matching (text)
- char *text;
-{
- register int i, len, nmatch, rsize;
- char **result;
-
- if (hostname_list_initialized == 0)
- initialize_hostname_list ();
-
- if (hostname_list_initialized == 0)
- return ((char **)NULL);
-
- /* Special case. If TEXT consists of nothing, then the whole list is
- what is desired. */
- if (*text == '\0')
- {
- result = strvec_create (1 + hostname_list_length);
- for (i = 0; i < hostname_list_length; i++)
- result[i] = hostname_list[i];
- result[i] = (char *)NULL;
- return (result);
- }
-
- /* Scan until found, or failure. */
- len = strlen (text);
- result = (char **)NULL;
- for (i = nmatch = rsize = 0; i < hostname_list_length; i++)
- {
- if (STREQN (text, hostname_list[i], len) == 0)
- continue;
-
- /* OK, it matches. Add it to the list. */
- if (nmatch >= (rsize - 1))
- {
- rsize = (rsize + 16) - (rsize % 16);
- result = strvec_resize (result, rsize);
- }
-
- result[nmatch++] = hostname_list[i];
- }
- if (nmatch)
- result[nmatch] = (char *)NULL;
- return (result);
-}
-
-/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
- editing command. */
-static int saved_history_line_to_use = -1;
-
-static int
-set_saved_history ()
-{
- if (saved_history_line_to_use >= 0)
- rl_get_previous_history (history_length - saved_history_line_to_use, 0);
- saved_history_line_to_use = -1;
- rl_startup_hook = old_rl_startup_hook;
- return (0);
-}
-
-static int
-operate_and_get_next (count, c)
- int count, c;
-{
- int where;
-
- /* Accept the current line. */
- rl_newline (1, c);
-
- /* Find the current line, and find the next line to use. */
- where = where_history ();
-
- if ((history_is_stifled () && (history_length >= history_max_entries)) ||
- (where >= history_length - 1))
- saved_history_line_to_use = where;
- else
- saved_history_line_to_use = where + 1;
-
- old_rl_startup_hook = rl_startup_hook;
- rl_startup_hook = set_saved_history;
-
- return 0;
-}
-
-/* This vi mode command causes VI_EDIT_COMMAND to be run on the current
- command being entered (if no explicit argument is given), otherwise on
- a command from the history file. */
-
-#define VI_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-vi}}\""
-#define EMACS_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-emacs}}\""
-#define POSIX_VI_EDIT_COMMAND "fc -e vi"
-
-static int
-edit_and_execute_command (count, c, editing_mode, edit_command)
- int count, c, editing_mode;
- char *edit_command;
-{
- char *command;
- int r, cclc, rrs;
-
- rrs = rl_readline_state;
- cclc = current_command_line_count;
-
- /* Accept the current line. */
- rl_newline (1, c);
-
- if (rl_explicit_arg)
- {
- command = (char *)xmalloc (strlen (edit_command) + 8);
- sprintf (command, "%s %d", edit_command, count);
- }
- else
- {
- /* Take the command we were just editing, add it to the history file,
- then call fc to operate on it. We have to add a dummy command to
- the end of the history because fc ignores the last command (assumes
- it's supposed to deal with the command before the `fc'). */
- using_history ();
- bash_add_history (rl_line_buffer);
- bash_add_history ("");
- history_lines_this_session++;
- using_history ();
- command = savestring (edit_command);
- }
-
- /* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the
- temporary file should be placed into the history. We don't do that
- yet. */
- r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
-
- current_command_line_count = cclc;
-
- /* Now erase the contents of the current line and undo the effects of the
- rl_accept_line() above. We don't even want to make the text we just
- executed available for undoing. */
- rl_line_buffer[0] = '\0'; /* XXX */
- rl_point = rl_end = 0;
- rl_done = 0;
- rl_readline_state = rrs;
-
- rl_forced_update_display ();
-
- return r;
-}
-
-#if defined (VI_MODE)
-static int
-vi_edit_and_execute_command (count, c)
- int count, c;
-{
- if (posixly_correct)
- return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND));
- else
- return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND));
-}
-#endif /* VI_MODE */
-
-static int
-emacs_edit_and_execute_command (count, c)
- int count, c;
-{
- return (edit_and_execute_command (count, c, EMACS_EDITING_MODE, EMACS_EDIT_COMMAND));
-}
-
-#if defined (ALIAS)
-static int
-posix_edit_macros (count, key)
- int count, key;
-{
- int c;
- char alias_name[3], *alias_value, *macro;
-
- c = rl_read_key ();
- alias_name[0] = '_';
- alias_name[1] = c;
- alias_name[2] = '\0';
-
- alias_value = get_alias_value (alias_name);
- if (alias_value && *alias_value)
- {
- macro = savestring (alias_value);
- rl_push_macro_input (macro);
- }
- return 0;
-}
-#endif
-
-/* **************************************************************** */
-/* */
-/* How To Do Shell Completion */
-/* */
-/* **************************************************************** */
-
-#define COMMAND_SEPARATORS ";|&{(`"
-/* )} */
-
-static int
-check_redir (ti)
- int ti;
-{
- register int this_char, prev_char;
-
- /* Handle the two character tokens `>&', `<&', and `>|'.
- We are not in a command position after one of these. */
- this_char = rl_line_buffer[ti];
- prev_char = rl_line_buffer[ti - 1];
-
- if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
- (this_char == '|' && prev_char == '>'))
- return (1);
- else if ((this_char == '{' && prev_char == '$') || /* } */
- (char_is_quoted (rl_line_buffer, ti)))
- return (1);
- return (0);
-}
-
-#if defined (PROGRAMMABLE_COMPLETION)
-/*
- * XXX - because of the <= start test, and setting os = s+1, this can
- * potentially return os > start. This is probably not what we want to
- * happen, but fix later after 2.05a-release.
- */
-static int
-find_cmd_start (start)
- int start;
-{
- register int s, os;
-
- os = 0;
- while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS)) <= start) &&
- rl_line_buffer[s])
- os = s+1;
- return os;
-}
-
-static int
-find_cmd_end (end)
- int end;
-{
- register int e;
-
- e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS);
- return e;
-}
-
-static char *
-find_cmd_name (start)
- int start;
-{
- char *name;
- register int s, e;
-
- for (s = start; whitespace (rl_line_buffer[s]); s++)
- ;
-
- /* skip until a shell break character */
- e = skip_to_delim (rl_line_buffer, s, "()<>;&| \t\n");
-
- name = substring (rl_line_buffer, s, e);
-
- return (name);
-}
-
-static char *
-prog_complete_return (text, matchnum)
- const char *text;
- int matchnum;
-{
- static int ind;
-
- if (matchnum == 0)
- ind = 0;
-
- if (prog_complete_matches == 0 || prog_complete_matches[ind] == 0)
- return (char *)NULL;
- return (prog_complete_matches[ind++]);
-}
-
-#endif /* PROGRAMMABLE_COMPLETION */
-
-/* Do some completion on TEXT. The indices of TEXT in RL_LINE_BUFFER are
- at START and END. Return an array of matches, or NULL if none. */
-static char **
-attempt_shell_completion (text, start, end)
- const char *text;
- int start, end;
-{
- int in_command_position, ti, saveti, qc, dflags;
- char **matches, *command_separator_chars;
-
- command_separator_chars = COMMAND_SEPARATORS;
- matches = (char **)NULL;
- rl_ignore_some_completions_function = filename_completion_ignore;
-
- /* Determine if this could be a command word. It is if it appears at
- the start of the line (ignoring preceding whitespace), or if it
- appears after a character that separates commands. It cannot be a
- command word if we aren't at the top-level prompt. */
- ti = start - 1;
- saveti = qc = -1;
-
- while ((ti > -1) && (whitespace (rl_line_buffer[ti])))
- ti--;
-
-#if 1
- /* If this is an open quote, maybe we're trying to complete a quoted
- command name. */
- if (ti >= 0 && (rl_line_buffer[ti] == '"' || rl_line_buffer[ti] == '\''))
- {
- qc = rl_line_buffer[ti];
- saveti = ti--;
- while (ti > -1 && (whitespace (rl_line_buffer[ti])))
- ti--;
- }
-#endif
-
- in_command_position = 0;
- if (ti < 0)
- {
- /* Only do command completion at the start of a line when we
- are prompting at the top level. */
- if (current_prompt_string == ps1_prompt)
- in_command_position++;
- }
- else if (member (rl_line_buffer[ti], command_separator_chars))
- {
- in_command_position++;
-
- if (check_redir (ti) == 1)
- in_command_position = 0;
- }
- else
- {
- /* This still could be in command position. It is possible
- that all of the previous words on the line are variable
- assignments. */
- }
-
- /* Check that we haven't incorrectly flagged a closed command substitution
- as indicating we're in a command position. */
- if (in_command_position && ti >= 0 && rl_line_buffer[ti] == '`' &&
- *text != '`' && unclosed_pair (rl_line_buffer, end, "`") == 0)
- in_command_position = 0;
-
- /* Special handling for command substitution. If *TEXT is a backquote,
- it can be the start or end of an old-style command substitution, or
- unmatched. If it's unmatched, both calls to unclosed_pair will
- succeed. */
- if (*text == '`' &&
- (in_command_position || (unclosed_pair (rl_line_buffer, start, "`") &&
- unclosed_pair (rl_line_buffer, end, "`"))))
- matches = rl_completion_matches (text, command_subst_completion_function);
-
-#if defined (PROGRAMMABLE_COMPLETION)
- /* Attempt programmable completion. */
- if (!matches && in_command_position == 0 && prog_completion_enabled &&
- (progcomp_size () > 0) && current_prompt_string == ps1_prompt)
- {
- int s, e, foundcs;
- char *n;
-
- /* XXX - don't free the members */
- if (prog_complete_matches)
- free (prog_complete_matches);
- prog_complete_matches = (char **)NULL;
-
- s = find_cmd_start (start);
- e = find_cmd_end (end);
- n = find_cmd_name (s);
- if (e > s && assignment (n, 0) == 0)
- prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
- else
- foundcs = 0;
- FREE (n);
- /* XXX - if we found a COMPSPEC for the command, just return whatever
- the programmable completion code returns, and disable the default
- filename completion that readline will do unless the COPT_DEFAULT
- option has been set with the `-o default' option to complete. */
- if (foundcs)
- {
- /* If the user specified that the compspec returns filenames, make
- sure that readline knows it. */
- if (foundcs & COPT_FILENAMES)
- rl_filename_completion_desired = 1;
- /* If the user doesn't want a space appended, tell readline. */
- if (foundcs & COPT_NOSPACE)
- rl_completion_suppress_append = 1;
- /* Turn what the programmable completion code returns into what
- readline wants. I should have made compute_lcd_of_matches
- external... */
- matches = rl_completion_matches (text, prog_complete_return);
- if ((foundcs & COPT_DEFAULT) == 0)
- rl_attempted_completion_over = 1; /* no default */
- if (matches || ((foundcs & COPT_BASHDEFAULT) == 0))
- return (matches);
- }
- }
-#endif
-
- if (matches == 0)
- {
- dflags = 0;
- if (in_command_position)
- dflags |= DEFCOMP_CMDPOS;
- matches = bash_default_completion (text, start, end, qc, dflags);
- }
-
- return matches;
-}
-
-char **
-bash_default_completion (text, start, end, qc, compflags)
- const char *text;
- int start, end, qc, compflags;
-{
- char **matches;
-
- matches = (char **)NULL;
-
- /* New posix-style command substitution or variable name? */
- if (!matches && *text == '$')
- {
- if (qc != '\'' && text[1] == '(') /* ) */
- matches = rl_completion_matches (text, command_subst_completion_function);
- else
- matches = rl_completion_matches (text, variable_completion_function);
- }
-
- /* If the word starts in `~', and there is no slash in the word, then
- try completing this word as a username. */
- if (!matches && *text == '~' && !xstrchr (text, '/'))
- matches = rl_completion_matches (text, rl_username_completion_function);
-
- /* Another one. Why not? If the word starts in '@', then look through
- the world of known hostnames for completion first. */
- if (!matches && perform_hostname_completion && *text == '@')
- matches = rl_completion_matches (text, hostname_completion_function);
-
- /* And last, (but not least) if this word is in a command position, then
- complete over possible command names, including aliases, functions,
- and command names. */
- if (matches == 0 && (compflags & DEFCOMP_CMDPOS))
- {
- /* If END == START and text[0] == 0, we are trying to complete an empty
- command word. */
- if (no_empty_command_completion && end == start && text[0] == '\0')
- {
- matches = (char **)NULL;
- rl_ignore_some_completions_function = bash_ignore_everything;
- }
- else
- {
-#define CMD_IS_DIR(x) (absolute_pathname(x) == 0 && absolute_program(x) == 0 && *(x) != '~' && test_for_directory (x))
-
- dot_in_path = 0;
- matches = rl_completion_matches (text, command_word_completion_function);
-
- /* If we are attempting command completion and nothing matches, we
- do not want readline to perform filename completion for us. We
- still want to be able to complete partial pathnames, so set the
- completion ignore function to something which will remove
- filenames and leave directories in the match list. */
- if (matches == (char **)NULL)
- rl_ignore_some_completions_function = bash_ignore_filenames;
- else if (matches[1] == 0 && CMD_IS_DIR(matches[0]) && dot_in_path == 0)
- /* If we found a single match, without looking in the current
- directory (because it's not in $PATH), but the found name is
- also a command in the current directory, suppress appending any
- terminating character, since it's ambiguous. */
- {
- rl_completion_suppress_append = 1;
- rl_filename_completion_desired = 0;
- }
- else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
- /* There are multiple instances of the same match (duplicate
- completions haven't yet been removed). In this case, all of
- the matches will be the same, and the duplicate removal code
- will distill them all down to one. We turn on
- rl_completion_suppress_append for the same reason as above.
- Remember: we only care if there's eventually a single unique
- completion. If there are multiple completions this won't
- make a difference and the problem won't occur. */
- {
- rl_completion_suppress_append = 1;
- rl_filename_completion_desired = 0;
- }
- }
- }
-
- /* This could be a globbing pattern, so try to expand it using pathname
- expansion. */
- if (!matches && glob_pattern_p (text))
- {
- matches = rl_completion_matches (text, glob_complete_word);
- /* A glob expression that matches more than one filename is problematic.
- If we match more than one filename, punt. */
- if (matches && matches[1] && rl_completion_type == TAB)
- {
- strvec_dispose (matches);
- matches = (char **)0;
- }
- }
-
- return (matches);
-}
-
-/* This is the function to call when the word to complete is in a position
- where a command word can be found. It grovels $PATH, looking for commands
- that match. It also scans aliases, function names, and the shell_builtin
- table. */
-char *
-command_word_completion_function (hint_text, state)
- const char *hint_text;
- int state;
-{
- static char *hint = (char *)NULL;
- static char *path = (char *)NULL;
- static char *val = (char *)NULL;
- static char *filename_hint = (char *)NULL;
- static char *dequoted_hint = (char *)NULL;
- static int path_index, hint_len, dequoted_len, istate, igncase;
- static int mapping_over, local_index, searching_path, hint_is_dir;
- static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
-#if defined (ALIAS)
- static alias_t **alias_list = (alias_t **)NULL;
-#endif /* ALIAS */
- char *temp;
-
- /* We have to map over the possibilities for command words. If we have
- no state, then make one just for that purpose. */
- if (!state)
- {
- if (dequoted_hint && dequoted_hint != hint)
- free (dequoted_hint);
- if (hint)
- free (hint);
-
- mapping_over = searching_path = 0;
- hint_is_dir = CMD_IS_DIR (hint_text);
- val = (char *)NULL;
-
- temp = rl_variable_value ("completion-ignore-case");
- igncase = strcmp (temp, "on") == 0;
-
- /* If this is an absolute program name, do not check it against
- aliases, reserved words, functions or builtins. We must check
- whether or not it is unique, and, if so, whether that filename
- is executable. */
- if (absolute_program (hint_text))
- {
- /* Perform tilde expansion on what's passed, so we don't end up
- passing filenames with tildes directly to stat(). */
- if (*hint_text == '~')
- hint = bash_tilde_expand (hint_text, 0);
- else
- hint = savestring (hint_text);
-
- dequoted_hint = hint;
- /* If readline's completer found a quote character somewhere, but
- didn't set the quote character, there must have been a quote
- character embedded in the filename. It can't be at the start of
- the filename, so we need to dequote the filename before we look
- in the file system for it. */
- if (rl_completion_found_quote && rl_completion_quote_character == 0)
- {
- dequoted_hint = bash_dequote_filename (hint, 0);
- free (hint);
- hint = dequoted_hint;
- }
- dequoted_len = hint_len = strlen (hint);
-
- if (filename_hint)
- free (filename_hint);
-
- filename_hint = savestring (hint);
-
- mapping_over = 4;
- istate = 0;
- goto inner;
- }
-
- dequoted_hint = hint = savestring (hint_text);
- dequoted_len = hint_len = strlen (hint);
-
- if (rl_completion_found_quote && rl_completion_quote_character == 0)
- {
- dequoted_hint = bash_dequote_filename (hint, 0);
- dequoted_len = strlen (dequoted_hint);
- }
-
- path = get_string_value ("PATH");
- path_index = dot_in_path = 0;
-
- /* Initialize the variables for each type of command word. */
- local_index = 0;
-
- if (varlist)
- free (varlist);
-
- varlist = all_visible_functions ();
-
-#if defined (ALIAS)
- if (alias_list)
- free (alias_list);
-
- alias_list = all_aliases ();
-#endif /* ALIAS */
- }
-
- /* mapping_over says what we are currently hacking. Note that every case
- in this list must fall through when there are no more possibilities. */
-
- switch (mapping_over)
- {
- case 0: /* Aliases come first. */
-#if defined (ALIAS)
- while (alias_list && alias_list[local_index])
- {
- register char *alias;
-
- alias = alias_list[local_index++]->name;
-
- if (STREQN (alias, hint, hint_len))
- return (savestring (alias));
- }
-#endif /* ALIAS */
- local_index = 0;
- mapping_over++;
-
- case 1: /* Then shell reserved words. */
- {
- while (word_token_alist[local_index].word)
- {
- register char *reserved_word;
-
- reserved_word = word_token_alist[local_index++].word;
-
- if (STREQN (reserved_word, hint, hint_len))
- return (savestring (reserved_word));
- }
- local_index = 0;
- mapping_over++;
- }
-
- case 2: /* Then function names. */
- while (varlist && varlist[local_index])
- {
- register char *varname;
-
- varname = varlist[local_index++]->name;
-
- if (STREQN (varname, hint, hint_len))
- return (savestring (varname));
- }
- local_index = 0;
- mapping_over++;
-
- case 3: /* Then shell builtins. */
- for (; local_index < num_shell_builtins; local_index++)
- {
- /* Ignore it if it doesn't have a function pointer or if it
- is not currently enabled. */
- if (!shell_builtins[local_index].function ||
- (shell_builtins[local_index].flags & BUILTIN_ENABLED) == 0)
- continue;
-
- if (STREQN (shell_builtins[local_index].name, hint, hint_len))
- {
- int i = local_index++;
-
- return (savestring (shell_builtins[i].name));
- }
- }
- local_index = 0;
- mapping_over++;
- }
-
- /* If the text passed is a directory in the current directory, return it
- as a possible match. Executables in directories in the current
- directory can be specified using relative pathnames and successfully
- executed even when `.' is not in $PATH. */
- if (hint_is_dir)
- {
- hint_is_dir = 0; /* only return the hint text once */
- return (savestring (hint_text));
- }
-
- /* Repeatedly call filename_completion_function while we have
- members of PATH left. Question: should we stat each file?
- Answer: we call executable_file () on each file. */
- outer:
-
- istate = (val != (char *)NULL);
-
- if (!istate)
- {
- char *current_path;
-
- /* Get the next directory from the path. If there is none, then we
- are all done. */
- if (!path || !path[path_index] ||
- (current_path = extract_colon_unit (path, &path_index)) == 0)
- return ((char *)NULL);
-
- searching_path = 1;
- if (*current_path == 0)
- {
- free (current_path);
- current_path = savestring (".");
- }
-
- if (*current_path == '~')
- {
- char *t;
-
- t = bash_tilde_expand (current_path, 0);
- free (current_path);
- current_path = t;
- }
-
- if (current_path[0] == '.' && current_path[1] == '\0')
- dot_in_path = 1;
-
- if (filename_hint)
- free (filename_hint);
-
- filename_hint = sh_makepath (current_path, hint, 0);
- free (current_path);
- }
-
- inner:
- val = rl_filename_completion_function (filename_hint, istate);
- istate = 1;
-
- if (val == 0)
- {
- /* If the hint text is an absolute program, then don't bother
- searching through PATH. */
- if (absolute_program (hint))
- return ((char *)NULL);
-
- goto outer;
- }
- else
- {
- int match, freetemp;
-#if 0
- char *temp; /* shadows previous declaration */
-#endif
-
- if (absolute_program (hint))
- {
- if (igncase == 0)
- match = strncmp (val, hint, hint_len) == 0;
- else
- match = strncasecmp (val, hint, hint_len) == 0;
-
- /* If we performed tilde expansion, restore the original
- filename. */
- if (*hint_text == '~')
- {
- int l, tl, vl, dl;
- char *rd;
- vl = strlen (val);
- tl = strlen (hint_text);
-#if 0
- l = vl - hint_len; /* # of chars added */
-#else
- rd = savestring (filename_hint);
- bash_directory_expansion (&rd);
- dl = strlen (rd);
- l = vl - dl; /* # of chars added */
- free (rd);
-#endif
- temp = (char *)xmalloc (l + 2 + tl);
- strcpy (temp, hint_text);
- strcpy (temp + tl, val + vl - l);
- }
- else
- temp = savestring (val);
- freetemp = 1;
- }
- else
- {
- temp = strrchr (val, '/');
-
- if (temp)
- {
- temp++;
- if (igncase == 0)
- freetemp = match = strncmp (temp, hint, hint_len) == 0;
- else
- freetemp = match = strncasecmp (temp, hint, hint_len) == 0;
- if (match)
- temp = savestring (temp);
- }
- else
- freetemp = match = 0;
- }
-
-#if 0
- /* If we have found a match, and it is an executable file or a
- directory name, return it. */
- if (match && executable_or_directory (val))
-#else
- /* If we have found a match, and it is an executable file, return it.
- We don't return directory names when searching $PATH, since the
- bash execution code won't find executables in directories which
- appear in directories in $PATH when they're specified using
- relative pathnames. */
- if (match && (searching_path ? executable_file (val) : executable_or_directory (val)))
-#endif
- {
- free (val);
- val = ""; /* So it won't be NULL. */
- return (temp);
- }
- else
- {
- if (freetemp)
- free (temp);
- free (val);
- goto inner;
- }
- }
-}
-
-/* Completion inside an unterminated command substitution. */
-static char *
-command_subst_completion_function (text, state)
- const char *text;
- int state;
-{
- static char **matches = (char **)NULL;
- static const char *orig_start;
- static char *filename_text = (char *)NULL;
- static int cmd_index, start_len;
- char *value;
-
- if (state == 0)
- {
- if (filename_text)
- free (filename_text);
- orig_start = text;
- if (*text == '`')
- text++;
- else if (*text == '$' && text[1] == '(') /* ) */
- text += 2;
- /* If the text was quoted, suppress any quote character that the
- readline completion code would insert. */
- rl_completion_suppress_quote = 1;
- start_len = text - orig_start;
- filename_text = savestring (text);
- if (matches)
- free (matches);
-
- /*
- * At this point we can entertain the idea of re-parsing
- * `filename_text' into a (possibly incomplete) command name and
- * arguments, and doing completion based on that. This is
- * currently very rudimentary, but it is a small improvement.
- */
- for (value = filename_text + strlen (filename_text) - 1; value > filename_text; value--)
- if (whitespace (*value) || member (*value, COMMAND_SEPARATORS))
- break;
- if (value <= filename_text)
- matches = rl_completion_matches (filename_text, command_word_completion_function);
- else
- {
- value++;
- start_len += value - filename_text;
- if (whitespace (value[-1]))
- matches = rl_completion_matches (value, rl_filename_completion_function);
- else
- matches = rl_completion_matches (value, command_word_completion_function);
- }
-
- /* If there is more than one match, rl_completion_matches has already
- put the lcd in matches[0]. Skip over it. */
- cmd_index = matches && matches[0] && matches[1];
-
- /* If there's a single match and it's a directory, set the append char
- to the expected `/'. Otherwise, don't append anything. */
- if (matches && matches[0] && matches[1] == 0 && test_for_directory (matches[0]))
- rl_completion_append_character = '/';
- else
- rl_completion_suppress_append = 1;
- }
-
- if (!matches || !matches[cmd_index])
- {
- rl_filename_quoting_desired = 0; /* disable quoting */
- return ((char *)NULL);
- }
- else
- {
- value = (char *)xmalloc (1 + start_len + strlen (matches[cmd_index]));
-
- if (start_len == 1)
- value[0] = *orig_start;
- else
- strncpy (value, orig_start, start_len);
-
- strcpy (value + start_len, matches[cmd_index]);
-
- cmd_index++;
- return (value);
- }
-}
-
-/* Okay, now we write the entry_function for variable completion. */
-static char *
-variable_completion_function (text, state)
- const char *text;
- int state;
-{
- static char **varlist = (char **)NULL;
- static int varlist_index;
- static char *varname = (char *)NULL;
- static int namelen;
- static int first_char, first_char_loc;
-
- if (!state)
- {
- if (varname)
- free (varname);
-
- first_char_loc = 0;
- first_char = text[0];
-
- if (first_char == '$')
- first_char_loc++;
-
- if (text[first_char_loc] == '{')
- first_char_loc++;
-
- varname = savestring (text + first_char_loc);
-
- namelen = strlen (varname);
- if (varlist)
- strvec_dispose (varlist);
-
- varlist = all_variables_matching_prefix (varname);
- varlist_index = 0;
- }
-
- if (!varlist || !varlist[varlist_index])
- {
- return ((char *)NULL);
- }
- else
- {
- char *value;
-
- value = (char *)xmalloc (4 + strlen (varlist[varlist_index]));
-
- if (first_char_loc)
- {
- value[0] = first_char;
- if (first_char_loc == 2)
- value[1] = '{';
- }
-
- strcpy (value + first_char_loc, varlist[varlist_index]);
- if (first_char_loc == 2)
- strcat (value, "}");
-
- varlist_index++;
- return (value);
- }
-}
-
-/* How about a completion function for hostnames? */
-static char *
-hostname_completion_function (text, state)
- const char *text;
- int state;
-{
- static char **list = (char **)NULL;
- static int list_index = 0;
- static int first_char, first_char_loc;
-
- /* If we don't have any state, make some. */
- if (state == 0)
- {
- FREE (list);
-
- list = (char **)NULL;
-
- first_char_loc = 0;
- first_char = *text;
-
- if (first_char == '@')
- first_char_loc++;
-
- list = hostnames_matching ((char *)text+first_char_loc);
- list_index = 0;
- }
-
- if (list && list[list_index])
- {
- char *t;
-
- t = (char *)xmalloc (2 + strlen (list[list_index]));
- *t = first_char;
- strcpy (t + first_char_loc, list[list_index]);
- list_index++;
- return (t);
- }
-
- return ((char *)NULL);
-}
-
-/*
- * A completion function for service names from /etc/services (or wherever).
- */
-char *
-bash_servicename_completion_function (text, state)
- const char *text;
- int state;
-{
-#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GETSERVENT)
- return ((char *)NULL);
-#else
- static char *sname = (char *)NULL;
- static struct servent *srvent;
- static int snamelen, firstc;
- char *value;
- char **alist, *aentry;
- int afound;
-
- if (state == 0)
- {
- FREE (sname);
- firstc = *text;
-
- sname = savestring (text);
- snamelen = strlen (sname);
- setservent (0);
- }
-
- while (srvent = getservent ())
- {
- afound = 0;
- if (snamelen == 0 || (STREQN (sname, srvent->s_name, snamelen)))
- break;
- /* Not primary, check aliases */
- for (alist = srvent->s_aliases; aentry = *alist; alist++)
- {
- if (STREQN (sname, aentry, snamelen))
- {
- afound = 1;
- break;
- }
- }
-
- if (afound)
- break;
- }
-
- if (srvent == 0)
- {
- endservent ();
- return ((char *)NULL);
- }
-
- value = afound ? savestring (aentry) : savestring (srvent->s_name);
- return value;
-#endif
-}
-
-/*
- * A completion function for group names from /etc/group (or wherever).
- */
-char *
-bash_groupname_completion_function (text, state)
- const char *text;
- int state;
-{
-#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GRP_H)
- return ((char *)NULL);
-#else
- static char *gname = (char *)NULL;
- static struct group *grent;
- static int gnamelen;
- char *value;
-
- if (state == 0)
- {
- FREE (gname);
- gname = savestring (text);
- gnamelen = strlen (gname);
-
- setgrent ();
- }
-
- while (grent = getgrent ())
- {
- if (gnamelen == 0 || (STREQN (gname, grent->gr_name, gnamelen)))
- break;
- }
-
- if (grent == 0)
- {
- endgrent ();
- return ((char *)NULL);
- }
-
- value = savestring (grent->gr_name);
- return (value);
-#endif
-}
-
-/* Functions to perform history and alias expansions on the current line. */
-
-#if defined (BANG_HISTORY)
-/* Perform history expansion on the current line. If no history expansion
- is done, pre_process_line() returns what it was passed, so we need to
- allocate a new line here. */
-static char *
-history_expand_line_internal (line)
- char *line;
-{
- char *new_line;
- int old_verify;
-
- old_verify = hist_verify;
- hist_verify = 0;
- new_line = pre_process_line (line, 0, 0);
- hist_verify = old_verify;
-
- return (new_line == line) ? savestring (line) : new_line;
-}
-#endif
-
-/* There was an error in expansion. Let the preprocessor print
- the error here. */
-static void
-cleanup_expansion_error ()
-{
- char *to_free;
-#if defined (BANG_HISTORY)
- int old_verify;
-
- old_verify = hist_verify;
- hist_verify = 0;
-#endif
-
- fprintf (rl_outstream, "\r\n");
- to_free = pre_process_line (rl_line_buffer, 1, 0);
-#if defined (BANG_HISTORY)
- hist_verify = old_verify;
-#endif
- if (to_free != rl_line_buffer)
- FREE (to_free);
- putc ('\r', rl_outstream);
- rl_forced_update_display ();
-}
-
-/* If NEW_LINE differs from what is in the readline line buffer, add an
- undo record to get from the readline line buffer contents to the new
- line and make NEW_LINE the current readline line. */
-static void
-maybe_make_readline_line (new_line)
- char *new_line;
-{
- if (strcmp (new_line, rl_line_buffer) != 0)
- {
- rl_point = rl_end;
-
- rl_add_undo (UNDO_BEGIN, 0, 0, 0);
- rl_delete_text (0, rl_point);
- rl_point = rl_end = rl_mark = 0;
- rl_insert_text (new_line);
- rl_add_undo (UNDO_END, 0, 0, 0);
- }
-}
-
-/* Make NEW_LINE be the current readline line. This frees NEW_LINE. */
-static void
-set_up_new_line (new_line)
- char *new_line;
-{
- int old_point, at_end;
-
- old_point = rl_point;
- at_end = rl_point == rl_end;
-
- /* If the line was history and alias expanded, then make that
- be one thing to undo. */
- maybe_make_readline_line (new_line);
- free (new_line);
-
- /* Place rl_point where we think it should go. */
- if (at_end)
- rl_point = rl_end;
- else if (old_point < rl_end)
- {
- rl_point = old_point;
- if (!whitespace (rl_line_buffer[rl_point]))
- rl_forward_word (1, 0);
- }
-}
-
-#if defined (ALIAS)
-/* Expand aliases in the current readline line. */
-static int
-alias_expand_line (count, ignore)
- int count, ignore;
-{
- char *new_line;
-
- new_line = alias_expand (rl_line_buffer);
-
- if (new_line)
- {
- set_up_new_line (new_line);
- return (0);
- }
- else
- {
- cleanup_expansion_error ();
- return (1);
- }
-}
-#endif
-
-#if defined (BANG_HISTORY)
-/* History expand the line. */
-static int
-history_expand_line (count, ignore)
- int count, ignore;
-{
- char *new_line;
-
- new_line = history_expand_line_internal (rl_line_buffer);
-
- if (new_line)
- {
- set_up_new_line (new_line);
- return (0);
- }
- else
- {
- cleanup_expansion_error ();
- return (1);
- }
-}
-
-/* Expand history substitutions in the current line and then insert a
- space (hopefully close to where we were before). */
-static int
-tcsh_magic_space (count, ignore)
- int count, ignore;
-{
- int dist_from_end, old_point;
-
- old_point = rl_point;
- dist_from_end = rl_end - rl_point;
- if (history_expand_line (count, ignore) == 0)
- {
- /* Try a simple heuristic from Stephen Gildea <gildea@intouchsys.com>.
- This works if all expansions were before rl_point or if no expansions
- were performed. */
- rl_point = (old_point == 0) ? old_point : rl_end - dist_from_end;
- rl_insert (1, ' ');
- return (0);
- }
- else
- return (1);
-}
-#endif /* BANG_HISTORY */
-
-/* History and alias expand the line. */
-static int
-history_and_alias_expand_line (count, ignore)
- int count, ignore;
-{
- char *new_line;
-
- new_line = 0;
-#if defined (BANG_HISTORY)
- new_line = history_expand_line_internal (rl_line_buffer);
-#endif
-
-#if defined (ALIAS)
- if (new_line)
- {
- char *alias_line;
-
- alias_line = alias_expand (new_line);
- free (new_line);
- new_line = alias_line;
- }
-#endif /* ALIAS */
-
- if (new_line)
- {
- set_up_new_line (new_line);
- return (0);
- }
- else
- {
- cleanup_expansion_error ();
- return (1);
- }
-}
-
-/* History and alias expand the line, then perform the shell word
- expansions by calling expand_string. This can't use set_up_new_line()
- because we want the variable expansions as a separate undo'able
- set of operations. */
-static int
-shell_expand_line (count, ignore)
- int count, ignore;
-{
- char *new_line;
- WORD_LIST *expanded_string;
-
- new_line = 0;
-#if defined (BANG_HISTORY)
- new_line = history_expand_line_internal (rl_line_buffer);
-#endif
-
-#if defined (ALIAS)
- if (new_line)
- {
- char *alias_line;
-
- alias_line = alias_expand (new_line);
- free (new_line);
- new_line = alias_line;
- }
-#endif /* ALIAS */
-
- if (new_line)
- {
- int old_point = rl_point;
- int at_end = rl_point == rl_end;
-
- /* If the line was history and alias expanded, then make that
- be one thing to undo. */
- maybe_make_readline_line (new_line);
- free (new_line);
-
- /* If there is variable expansion to perform, do that as a separate
- operation to be undone. */
- new_line = savestring (rl_line_buffer);
- expanded_string = expand_string (new_line, 0);
- FREE (new_line);
- if (expanded_string == 0)
- {
- new_line = (char *)xmalloc (1);
- new_line[0] = '\0';
- }
- else
- {
- new_line = string_list (expanded_string);
- dispose_words (expanded_string);
- }
-
- maybe_make_readline_line (new_line);
- free (new_line);
-
- /* Place rl_point where we think it should go. */
- if (at_end)
- rl_point = rl_end;
- else if (old_point < rl_end)
- {
- rl_point = old_point;
- if (!whitespace (rl_line_buffer[rl_point]))
- rl_forward_word (1, 0);
- }
- return 0;
- }
- else
- {
- cleanup_expansion_error ();
- return 1;
- }
-}
-
-/* If FIGNORE is set, then don't match files with the given suffixes when
- completing filenames. If only one of the possibilities has an acceptable
- suffix, delete the others, else just return and let the completer
- signal an error. It is called by the completer when real
- completions are done on filenames by the completer's internal
- function, not for completion lists (M-?) and not on "other"
- completion types, such as hostnames or commands. */
-
-static struct ignorevar fignore =
-{
- "FIGNORE",
- (struct ign *)0,
- 0,
- (char *)0,
- (sh_iv_item_func_t *) 0,
-};
-
-static void
-_ignore_completion_names (names, name_func)
- char **names;
- sh_ignore_func_t *name_func;
-{
- char **newnames;
- int idx, nidx;
- char **oldnames;
- int oidx;
-
- /* If there is only one completion, see if it is acceptable. If it is
- not, free it up. In any case, short-circuit and return. This is a
- special case because names[0] is not the prefix of the list of names
- if there is only one completion; it is the completion itself. */
- if (names[1] == (char *)0)
- {
- if (force_fignore)
- if ((*name_func) (names[0]) == 0)
- {
- free (names[0]);
- names[0] = (char *)NULL;
- }
-
- return;
- }
-
- /* Allocate space for array to hold list of pointers to matching
- filenames. The pointers are copied back to NAMES when done. */
- for (nidx = 1; names[nidx]; nidx++)
- ;
- newnames = strvec_create (nidx + 1);
-
- if (force_fignore == 0)
- {
- oldnames = strvec_create (nidx - 1);
- oidx = 0;
- }
-
- newnames[0] = names[0];
- for (idx = nidx = 1; names[idx]; idx++)
- {
- if ((*name_func) (names[idx]))
- newnames[nidx++] = names[idx];
- else if (force_fignore == 0)
- oldnames[oidx++] = names[idx];
- else
- free (names[idx]);
- }
-
- newnames[nidx] = (char *)NULL;
-
- /* If none are acceptable then let the completer handle it. */
- if (nidx == 1)
- {
- if (force_fignore)
- {
- free (names[0]);
- names[0] = (char *)NULL;
- }
- else
- free (oldnames);
-
- free (newnames);
- return;
- }
-
- if (force_fignore == 0)
- {
- while (oidx)
- free (oldnames[--oidx]);
- free (oldnames);
- }
-
- /* If only one is acceptable, copy it to names[0] and return. */
- if (nidx == 2)
- {
- free (names[0]);
- names[0] = newnames[1];
- names[1] = (char *)NULL;
- free (newnames);
- return;
- }
-
- /* Copy the acceptable names back to NAMES, set the new array end,
- and return. */
- for (nidx = 1; newnames[nidx]; nidx++)
- names[nidx] = newnames[nidx];
- names[nidx] = (char *)NULL;
- free (newnames);
-}
-
-static int
-name_is_acceptable (name)
- const char *name;
-{
- struct ign *p;
- int nlen;
-
- for (nlen = strlen (name), p = fignore.ignores; p->val; p++)
- {
- if (nlen > p->len && p->len > 0 && STREQ (p->val, &name[nlen - p->len]))
- return (0);
- }
-
- return (1);
-}
-
-#if 0
-static int
-ignore_dot_names (name)
- char *name;
-{
- return (name[0] != '.');
-}
-#endif
-
-static int
-filename_completion_ignore (names)
- char **names;
-{
-#if 0
- if (glob_dot_filenames == 0)
- _ignore_completion_names (names, ignore_dot_names);
-#endif
-
- setup_ignore_patterns (&fignore);
-
- if (fignore.num_ignores == 0)
- return 0;
-
- _ignore_completion_names (names, name_is_acceptable);
-
- return 0;
-}
-
-/* Return 1 if NAME is a directory. */
-static int
-test_for_directory (name)
- const char *name;
-{
- struct stat finfo;
- char *fn;
-
- fn = bash_tilde_expand (name, 0);
- if (stat (fn, &finfo) != 0)
- {
- free (fn);
- return 0;
- }
- free (fn);
- return (S_ISDIR (finfo.st_mode));
-}
-
-/* Remove files from NAMES, leaving directories. */
-static int
-bash_ignore_filenames (names)
- char **names;
-{
- _ignore_completion_names (names, test_for_directory);
- return 0;
-}
-
-static int
-return_zero (name)
- const char *name;
-{
- return 0;
-}
-
-static int
-bash_ignore_everything (names)
- char **names;
-{
- _ignore_completion_names (names, return_zero);
- return 0;
-}
-
-/* Simulate the expansions that will be performed by
- rl_filename_completion_function. This must be called with the address of
- a pointer to malloc'd memory. */
-static void
-bash_directory_expansion (dirname)
- char **dirname;
-{
- char *d, *nd;
-
- d = savestring (*dirname);
-
- if (rl_directory_rewrite_hook)
- (*rl_directory_rewrite_hook) (&d);
-
- if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
- {
- free (*dirname);
- *dirname = d;
- }
- else if (rl_completion_found_quote)
- {
- nd = bash_dequote_filename (d, rl_completion_quote_character);
- free (*dirname);
- free (d);
- *dirname = nd;
- }
-}
-
-/* Handle symbolic link references and other directory name
- expansions while hacking completion. */
-static int
-bash_directory_completion_hook (dirname)
- char **dirname;
-{
- char *local_dirname, *new_dirname, *t;
- int return_value, should_expand_dirname;
- WORD_LIST *wl;
- struct stat sb;
-
- return_value = should_expand_dirname = 0;
- local_dirname = *dirname;
-
-#if 0
- should_expand_dirname = xstrchr (local_dirname, '$') || xstrchr (local_dirname, '`');
-#else
- if (xstrchr (local_dirname, '$'))
- should_expand_dirname = 1;
- else
- {
- t = xstrchr (local_dirname, '`');
- if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
- should_expand_dirname = 1;
- }
-#endif
-
-#if defined (HAVE_LSTAT)
- if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
-#else
- if (should_expand_dirname && stat (local_dirname, &sb) == 0)
-#endif
- should_expand_dirname = 0;
-
- if (should_expand_dirname)
- {
- new_dirname = savestring (local_dirname);
- wl = expand_prompt_string (new_dirname, 0); /* does the right thing */
- if (wl)
- {
- *dirname = string_list (wl);
- /* Tell the completer to replace the directory name only if we
- actually expanded something. */
- return_value = STREQ (local_dirname, *dirname) == 0;
- free (local_dirname);
- free (new_dirname);
- dispose_words (wl);
- local_dirname = *dirname;
- }
- else
- {
- free (new_dirname);
- free (local_dirname);
- *dirname = (char *)xmalloc (1);
- **dirname = '\0';
- return 1;
- }
- }
- else
- {
- /* Dequote the filename even if we don't expand it. */
- new_dirname = bash_dequote_filename (local_dirname, rl_completion_quote_character);
- free (local_dirname);
- local_dirname = *dirname = new_dirname;
- }
-
- if (!no_symbolic_links && (local_dirname[0] != '.' || local_dirname[1]))
- {
- char *temp1, *temp2;
- int len1, len2;
-
- t = get_working_directory ("symlink-hook");
- temp1 = make_absolute (local_dirname, t);
- free (t);
- temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
- /* If we can't canonicalize, bail. */
- if (temp2 == 0)
- {
- free (temp1);
- return 1;
- }
- len1 = strlen (temp1);
- if (temp1[len1 - 1] == '/')
- {
- len2 = strlen (temp2);
- if (len2 > 2) /* don't append `/' to `/' or `//' */
- {
- temp2 = (char *)xrealloc (temp2, len2 + 2);
- temp2[len2] = '/';
- temp2[len2 + 1] = '\0';
- }
- }
- free (local_dirname);
- *dirname = temp2;
- free (temp1);
- }
- return (return_value);
-}
-
-static char **history_completion_array = (char **)NULL;
-static int harry_size;
-static int harry_len;
-
-static void
-build_history_completion_array ()
-{
- register int i, j;
- HIST_ENTRY **hlist;
- char **tokens;
-
- /* First, clear out the current dynamic history completion list. */
- if (harry_size)
- {
- strvec_dispose (history_completion_array);
- history_completion_array = (char **)NULL;
- harry_size = 0;
- harry_len = 0;
- }
-
- /* Next, grovel each line of history, making each shell-sized token
- a separate entry in the history_completion_array. */
- hlist = history_list ();
-
- if (hlist)
- {
- for (i = 0; hlist[i]; i++)
- {
- /* Separate each token, and place into an array. */
- tokens = history_tokenize (hlist[i]->line);
-
- for (j = 0; tokens && tokens[j]; j++)
- {
- if (harry_len + 2 > harry_size)
- history_completion_array = strvec_resize (history_completion_array, harry_size += 10);
-
- history_completion_array[harry_len++] = tokens[j];
- history_completion_array[harry_len] = (char *)NULL;
- }
- free (tokens);
- }
-
- /* Sort the complete list of tokens. */
- qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp);
- }
-}
-
-static char *
-history_completion_generator (hint_text, state)
- const char *hint_text;
- int state;
-{
- static int local_index, len;
- static const char *text;
-
- /* If this is the first call to the generator, then initialize the
- list of strings to complete over. */
- if (state == 0)
- {
- local_index = 0;
- build_history_completion_array ();
- text = hint_text;
- len = strlen (text);
- }
-
- while (history_completion_array && history_completion_array[local_index])
- {
- if (strncmp (text, history_completion_array[local_index++], len) == 0)
- return (savestring (history_completion_array[local_index - 1]));
- }
- return ((char *)NULL);
-}
-
-static int
-dynamic_complete_history (count, key)
- int count, key;
-{
- int r;
-
- rl_compentry_func_t *orig_func;
- rl_completion_func_t *orig_attempt_func;
-
- orig_func = rl_completion_entry_function;
- orig_attempt_func = rl_attempted_completion_function;
- rl_completion_entry_function = history_completion_generator;
- rl_attempted_completion_function = (rl_completion_func_t *)NULL;
-
- /* XXX - use rl_completion_mode here? */
- if (rl_last_func == dynamic_complete_history)
- r = rl_complete_internal ('?');
- else
- r = rl_complete_internal (TAB);
-
- rl_completion_entry_function = orig_func;
- rl_attempted_completion_function = orig_attempt_func;
- return r;
-}
-
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
-static int
-bash_complete_username (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_username_internal (rl_completion_mode (bash_complete_username));
-}
-
-static int
-bash_possible_username_completions (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_username_internal ('?');
-}
-
-static int
-bash_complete_username_internal (what_to_do)
- int what_to_do;
-{
- return bash_specific_completion (what_to_do, rl_username_completion_function);
-}
-
-static int
-bash_complete_filename (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_filename_internal (rl_completion_mode (bash_complete_filename));
-}
-
-static int
-bash_possible_filename_completions (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_filename_internal ('?');
-}
-
-static int
-bash_complete_filename_internal (what_to_do)
- int what_to_do;
-{
- rl_compentry_func_t *orig_func;
- rl_completion_func_t *orig_attempt_func;
- rl_icppfunc_t *orig_dir_func;
- /*const*/ char *orig_rl_completer_word_break_characters;
- int r;
-
- orig_func = rl_completion_entry_function;
- orig_attempt_func = rl_attempted_completion_function;
- orig_dir_func = rl_directory_completion_hook;
- orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
- rl_completion_entry_function = rl_filename_completion_function;
- rl_attempted_completion_function = (rl_completion_func_t *)NULL;
- rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
- rl_completer_word_break_characters = " \t\n\"\'";
-
- r = rl_complete_internal (what_to_do);
-
- rl_completion_entry_function = orig_func;
- rl_attempted_completion_function = orig_attempt_func;
- rl_directory_completion_hook = orig_dir_func;
- rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
-
- return r;
-}
-
-static int
-bash_complete_hostname (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_hostname_internal (rl_completion_mode (bash_complete_hostname));
-}
-
-static int
-bash_possible_hostname_completions (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_hostname_internal ('?');
-}
-
-static int
-bash_complete_variable (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_variable_internal (rl_completion_mode (bash_complete_variable));
-}
-
-static int
-bash_possible_variable_completions (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_variable_internal ('?');
-}
-
-static int
-bash_complete_command (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_command_internal (rl_completion_mode (bash_complete_command));
-}
-
-static int
-bash_possible_command_completions (ignore, ignore2)
- int ignore, ignore2;
-{
- return bash_complete_command_internal ('?');
-}
-
-static int
-bash_complete_hostname_internal (what_to_do)
- int what_to_do;
-{
- return bash_specific_completion (what_to_do, hostname_completion_function);
-}
-
-static int
-bash_complete_variable_internal (what_to_do)
- int what_to_do;
-{
- return bash_specific_completion (what_to_do, variable_completion_function);
-}
-
-static int
-bash_complete_command_internal (what_to_do)
- int what_to_do;
-{
- return bash_specific_completion (what_to_do, command_word_completion_function);
-}
-
-static char *globtext;
-static char *globorig;
-
-static char *
-glob_complete_word (text, state)
- const char *text;
- int state;
-{
- static char **matches = (char **)NULL;
- static int ind;
- int glen;
- char *ret, *ttext;
-
- if (state == 0)
- {
- rl_filename_completion_desired = 1;
- FREE (matches);
- if (globorig != globtext)
- FREE (globorig);
- FREE (globtext);
-
- ttext = bash_tilde_expand (text, 0);
-
- if (rl_explicit_arg)
- {
- globorig = savestring (ttext);
- glen = strlen (ttext);
- globtext = (char *)xmalloc (glen + 2);
- strcpy (globtext, ttext);
- globtext[glen] = '*';
- globtext[glen+1] = '\0';
- }
- else
- globtext = globorig = savestring (ttext);
-
- if (ttext != text)
- free (ttext);
-
- matches = shell_glob_filename (globtext);
- if (GLOB_FAILED (matches))
- matches = (char **)NULL;
- ind = 0;
- }
-
- ret = matches ? matches[ind] : (char *)NULL;
- ind++;
- return ret;
-}
-
-static int
-bash_glob_completion_internal (what_to_do)
- int what_to_do;
-{
- return bash_specific_completion (what_to_do, glob_complete_word);
-}
-
-/* A special quoting function so we don't end up quoting globbing characters
- in the word if there are no matches or multiple matches. */
-static char *
-bash_glob_quote_filename (s, rtype, qcp)
- char *s;
- int rtype;
- char *qcp;
-{
- if (globorig && qcp && *qcp == '\0' && STREQ (s, globorig))
- return (savestring (s));
- else
- return (bash_quote_filename (s, rtype, qcp));
-}
-
-static int
-bash_glob_complete_word (count, key)
- int count, key;
-{
- int r;
- rl_quote_func_t *orig_quoting_function;
-
- if (rl_editing_mode == EMACS_EDITING_MODE)
- rl_explicit_arg = 1; /* force `*' append */
- orig_quoting_function = rl_filename_quoting_function;
- rl_filename_quoting_function = bash_glob_quote_filename;
-
- r = bash_glob_completion_internal (rl_completion_mode (bash_glob_complete_word));
-
- rl_filename_quoting_function = orig_quoting_function;
- return r;
-}
-
-static int
-bash_glob_expand_word (count, key)
- int count, key;
-{
- return bash_glob_completion_internal ('*');
-}
-
-static int
-bash_glob_list_expansions (count, key)
- int count, key;
-{
- return bash_glob_completion_internal ('?');
-}
-
-static int
-bash_specific_completion (what_to_do, generator)
- int what_to_do;
- rl_compentry_func_t *generator;
-{
- rl_compentry_func_t *orig_func;
- rl_completion_func_t *orig_attempt_func;
- int r;
-
- orig_func = rl_completion_entry_function;
- orig_attempt_func = rl_attempted_completion_function;
- rl_completion_entry_function = generator;
- rl_attempted_completion_function = NULL;
-
- r = rl_complete_internal (what_to_do);
-
- rl_completion_entry_function = orig_func;
- rl_attempted_completion_function = orig_attempt_func;
-
- return r;
-}
-
-#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
-
-#if defined (VI_MODE)
-/* Completion, from vi mode's point of view. This is a modified version of
- rl_vi_complete which uses the bash globbing code to implement what POSIX
- specifies, which is to append a `*' and attempt filename generation (which
- has the side effect of expanding any globbing characters in the word). */
-static int
-bash_vi_complete (count, key)
- int count, key;
-{
-#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
- int p, r;
- char *t;
-
- 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++;
- }
-
- /* Find boundaries of current word, according to vi definition of a
- `bigword'. */
- t = 0;
- if (rl_point > 0)
- {
- p = rl_point;
- rl_vi_bWord (1, 'B');
- r = rl_point;
- rl_point = p;
- p = r;
-
- t = substring (rl_line_buffer, p, rl_point);
- }
-
- if (t && glob_pattern_p (t) == 0)
- rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */
- FREE (t);
-
- if (key == '*') /* Expansion and replacement. */
- r = bash_glob_expand_word (count, key);
- else if (key == '=') /* List possible completions. */
- r = bash_glob_list_expansions (count, key);
- else if (key == '\\') /* Standard completion */
- r = bash_glob_complete_word (count, key);
- else
- r = rl_complete (0, key);
-
- if (key == '*' || key == '\\')
- rl_vi_start_inserting (key, 1, 1);
-
- return (r);
-#else
- return rl_vi_complete (count, key);
-#endif /* !SPECIFIC_COMPLETION_FUNCTIONS */
-}
-#endif /* VI_MODE */
-
-/* Filename quoting for completion. */
-/* A function to strip unquoted quote characters (single quotes, double
- quotes, and backslashes). It allows single quotes to appear
- within double quotes, and vice versa. It should be smarter. */
-static char *
-bash_dequote_filename (text, quote_char)
- char *text;
- int quote_char;
-{
- char *ret, *p, *r;
- int l, quoted;
-
- l = strlen (text);
- ret = (char *)xmalloc (l + 1);
- for (quoted = quote_char, p = text, r = ret; p && *p; p++)
- {
- /* Allow backslash-quoted characters to pass through unscathed. */
- if (*p == '\\')
- {
- *r++ = *++p;
- if (*p == '\0')
- break;
- continue;
- }
- /* Close quote. */
- if (quoted && *p == quoted)
- {
- quoted = 0;
- continue;
- }
- /* Open quote. */
- if (quoted == 0 && (*p == '\'' || *p == '"'))
- {
- quoted = *p;
- continue;
- }
- *r++ = *p;
- }
- *r = '\0';
- return ret;
-}
-
-/* Quote characters that the readline completion code would treat as
- word break characters with backslashes. Pass backslash-quoted
- characters through without examination. */
-static char *
-quote_word_break_chars (text)
- char *text;
-{
- char *ret, *r, *s;
- int l;
-
- l = strlen (text);
- ret = (char *)xmalloc ((2 * l) + 1);
- for (s = text, r = ret; *s; s++)
- {
- /* Pass backslash-quoted characters through, including the backslash. */
- if (*s == '\\')
- {
- *r++ = '\\';
- *r++ = *++s;
- if (*s == '\0')
- break;
- continue;
- }
- /* OK, we have an unquoted character. Check its presence in
- rl_completer_word_break_characters. */
- if (xstrchr (rl_completer_word_break_characters, *s))
- *r++ = '\\';
- *r++ = *s;
- }
- *r = '\0';
- return ret;
-}
-
-/* Quote a filename using double quotes, single quotes, or backslashes
- depending on the value of completion_quoting_style. If we're
- completing using backslashes, we need to quote some additional
- characters (those that readline treats as word breaks), so we call
- quote_word_break_chars on the result. This returns newly-allocated
- memory. */
-static char *
-bash_quote_filename (s, rtype, qcp)
- char *s;
- int rtype;
- char *qcp;
-{
- char *rtext, *mtext, *ret;
- int rlen, cs;
-
- rtext = (char *)NULL;
-
- /* If RTYPE == MULT_MATCH, it means that there is
- more than one match. In this case, we do not add
- the closing quote or attempt to perform tilde
- expansion. If RTYPE == SINGLE_MATCH, we try
- to perform tilde expansion, because single and double
- quotes inhibit tilde expansion by the shell. */
-
- cs = completion_quoting_style;
- /* Might need to modify the default completion style based on *qcp,
- since it's set to any user-provided opening quote. We also change
- to single-quoting if there is no user-provided opening quote and
- the word being completed contains newlines, since those are not
- quoted correctly using backslashes (a backslash-newline pair is
- special to the shell parser). */
- if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && xstrchr (s, '\n'))
- cs = COMPLETE_SQUOTE;
- else if (*qcp == '"')
- cs = COMPLETE_DQUOTE;
- else if (*qcp == '\'')
- cs = COMPLETE_SQUOTE;
-#if defined (BANG_HISTORY)
- else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
- history_expansion_inhibited == 0 && xstrchr (s, '!'))
- cs = COMPLETE_BSQUOTE;
-
- if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
- history_expansion_inhibited == 0 && xstrchr (s, '!'))
- {
- cs = COMPLETE_BSQUOTE;
- *qcp = '\0';
- }
-#endif
-
- /* Don't tilde-expand backslash-quoted filenames, since only single and
- double quotes inhibit tilde expansion. */
- mtext = s;
- if (mtext[0] == '~' && rtype == SINGLE_MATCH && cs != COMPLETE_BSQUOTE)
- mtext = bash_tilde_expand (s, 0);
-
- switch (cs)
- {
- case COMPLETE_DQUOTE:
- rtext = sh_double_quote (mtext);
- break;
- case COMPLETE_SQUOTE:
- rtext = sh_single_quote (mtext);
- break;
- case COMPLETE_BSQUOTE:
- rtext = sh_backslash_quote (mtext);
- break;
- }
-
- if (mtext != s)
- free (mtext);
-
- /* We may need to quote additional characters: those that readline treats
- as word breaks that are not quoted by backslash_quote. */
- if (rtext && cs == COMPLETE_BSQUOTE)
- {
- mtext = quote_word_break_chars (rtext);
- free (rtext);
- rtext = mtext;
- }
-
- /* Leave the opening quote intact. The readline completion code takes
- care of avoiding doubled opening quotes. */
- rlen = strlen (rtext);
- ret = (char *)xmalloc (rlen + 1);
- strcpy (ret, rtext);
-
- /* If there are multiple matches, cut off the closing quote. */
- if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE)
- ret[rlen - 1] = '\0';
- free (rtext);
- return ret;
-}
-
-/* Support for binding readline key sequences to Unix commands. */
-static Keymap cmd_xmap;
-
-static int
-bash_execute_unix_command (count, key)
- int count; /* ignored */
- int key;
-{
- Keymap ckmap; /* current keymap */
- Keymap xkmap; /* unix command executing keymap */
- register int i;
- char *cmd;
- sh_parser_state_t ps;
-
- /* First, we need to find the right command to execute. This is tricky,
- because we might have already indirected into another keymap. */
- ckmap = rl_get_keymap ();
- if (ckmap != rl_executing_keymap)
- {
- /* bogus. we have to search. only handle one level of indirection. */
- for (i = 0; i < KEYMAP_SIZE; i++)
- {
- if (ckmap[i].type == ISKMAP && (Keymap)ckmap[i].function == rl_executing_keymap)
- break;
- }
- if (i < KEYMAP_SIZE)
- xkmap = (Keymap)cmd_xmap[i].function;
- else
- {
- rl_crlf ();
- internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
- rl_forced_update_display ();
- return 1;
- }
- }
- else
- xkmap = cmd_xmap;
-
- cmd = (char *)xkmap[key].function;
-
- if (cmd == 0)
- {
- rl_ding ();
- return 1;
- }
-
- rl_crlf (); /* move to a new line */
-
- save_parser_state (&ps);
-
- cmd = savestring (cmd);
- parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST);
-
- restore_parser_state (&ps);
-
- /* and restore the readline buffer and display after command execution. */
- rl_forced_update_display ();
- return 0;
-}
-
-static void
-init_unix_command_map ()
-{
- cmd_xmap = rl_make_bare_keymap ();
-}
-
-static int
-isolate_sequence (string, ind, need_dquote, startp)
- char *string;
- int ind, need_dquote, *startp;
-{
- register int i;
- int c, passc, delim;
-
- for (i = ind; string[i] && whitespace (string[i]); i++)
- ;
- /* NEED_DQUOTE means that the first non-white character *must* be `"'. */
- if (need_dquote && string[i] != '"')
- {
- builtin_error (_("%s: first non-whitespace character is not `\"'"), string);
- return -1;
- }
-
- /* We can have delimited strings even if NEED_DQUOTE == 0, like the command
- string to bind the key sequence to. */
- delim = (string[i] == '"' || string[i] == '\'') ? string[i] : 0;
-
- if (startp)
- *startp = delim ? ++i : i;
-
- for (passc = 0; c = string[i]; i++)
- {
- if (passc)
- {
- passc = 0;
- continue;
- }
- if (c == '\\')
- {
- passc++;
- continue;
- }
- if (c == delim)
- break;
- }
-
- if (delim && string[i] != delim)
- {
- builtin_error (_("no closing `%c' in %s"), delim, string);
- return -1;
- }
-
- return i;
-}
-
-int
-bind_keyseq_to_unix_command (line)
- char *line;
-{
- Keymap kmap;
- char *kseq, *value;
- int i, kstart;
-
- if (cmd_xmap == 0)
- init_unix_command_map ();
-
- kmap = rl_get_keymap ();
-
- /* We duplicate some of the work done by rl_parse_and_bind here, but
- this code only has to handle `"keyseq": ["]command["]' and can
- generate an error for anything else. */
- i = isolate_sequence (line, 0, 1, &kstart);
- if (i < 0)
- return -1;
-
- /* Create the key sequence string to pass to rl_generic_bind */
- kseq = substring (line, kstart, i);
-
- for ( ; line[i] && line[i] != ':'; i++)
- ;
- if (line[i] != ':')
- {
- builtin_error (_("%s: missing colon separator"), line);
- return -1;
- }
-
- i = isolate_sequence (line, i + 1, 0, &kstart);
- if (i < 0)
- return -1;
-
- /* Create the value string containing the command to execute. */
- value = substring (line, kstart, i);
-
- /* Save the command to execute and the key sequence in the CMD_XMAP */
- rl_generic_bind (ISMACR, kseq, value, cmd_xmap);
-
- /* and bind the key sequence in the current keymap to a function that
- understands how to execute from CMD_XMAP */
- rl_bind_keyseq_in_map (kseq, bash_execute_unix_command, kmap);
-
- return 0;
-}
-
-/* Used by the programmable completion code. Complete TEXT as a filename,
- but return only directories as matches. Dequotes the filename before
- attempting to find matches. */
-char **
-bash_directory_completion_matches (text)
- const char *text;
-{
- char **m1;
- char *dfn;
- int qc;
-
- qc = rl_dispatching ? rl_completion_quote_character : 0;
- dfn = bash_dequote_filename ((char *)text, qc);
- m1 = rl_completion_matches (dfn, rl_filename_completion_function);
- free (dfn);
-
- if (m1 == 0 || m1[0] == 0)
- return m1;
- /* We don't bother recomputing the lcd of the matches, because it will just
- get thrown away by the programmable completion code and recomputed
- later. */
- (void)bash_ignore_filenames (m1);
- return m1;
-}
-
-char *
-bash_dequote_text (text)
- const char *text;
-{
- char *dtxt;
- int qc;
-
- qc = (text[0] == '"' || text[0] == '\'') ? text[0] : 0;
- dtxt = bash_dequote_filename ((char *)text, qc);
- return (dtxt);
-}
-#endif /* READLINE */
diff --git a/braces.c.orig b/braces.c.orig
deleted file mode 100644
index 4d229ca4..00000000
--- a/braces.c.orig
+++ /dev/null
@@ -1,561 +0,0 @@
-/* braces.c -- code for doing word expansion in curly braces. */
-
-/* Copyright (C) 1987-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. */
-
-/* Stuff in curly braces gets expanded before all other shell expansions. */
-
-#include "config.h"
-
-#if defined (BRACE_EXPANSION)
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include "bashansi.h"
-
-#if defined (SHELL)
-# include "shell.h"
-#endif /* SHELL */
-
-#include "general.h"
-#include "shmbutil.h"
-#include "chartypes.h"
-
-#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
-
-#define BRACE_SEQ_SPECIFIER ".."
-
-/* Basic idea:
-
- Segregate the text into 3 sections: preamble (stuff before an open brace),
- postamble (stuff after the matching close brace) and amble (stuff after
- preamble, and before postamble). Expand amble, and then tack on the
- expansions to preamble. Expand postamble, and tack on the expansions to
- the result so far.
- */
-
-/* The character which is used to separate arguments. */
-int brace_arg_separator = ',';
-
-#if defined (__P)
-static int brace_gobbler __P((char *, size_t, int *, int));
-static char **expand_amble __P((char *, size_t, int));
-static char **expand_seqterm __P((char *, size_t));
-static char **mkseq __P((int, int, int));
-static char **array_concat __P((char **, char **));
-#else
-static int brace_gobbler ();
-static char **expand_amble ();
-static char **expand_seqterm ();
-static char **mkseq();
-static char **array_concat ();
-#endif
-
-/* Return an array of strings; the brace expansion of TEXT. */
-char **
-brace_expand (text)
- char *text;
-{
- register int start;
- size_t tlen;
- char *preamble, *postamble, *amble;
- size_t alen;
- char **tack, **result;
- int i, j, c;
-
- DECLARE_MBSTATE;
-
- /* Find the text of the preamble. */
- tlen = strlen (text);
- i = 0;
- c = brace_gobbler (text, tlen, &i, '{');
-
- preamble = (char *)xmalloc (i + 1);
- strncpy (preamble, text, i);
- preamble[i] = '\0';
-
- result = (char **)xmalloc (2 * sizeof (char *));
- result[0] = preamble;
- result[1] = (char *)NULL;
-
- /* Special case. If we never found an exciting character, then
- the preamble is all of the text, so just return that. */
- if (c != '{')
- return (result);
-
- /* Find the amble. This is the stuff inside this set of braces. */
- start = ++i;
- c = brace_gobbler (text, tlen, &i, '}');
-
- /* What if there isn't a matching close brace? */
- if (c == 0)
- {
-#if defined (NOTDEF)
- /* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
- and I, then this should be an error. Otherwise, it isn't. */
- j = start;
- while (j < i)
- {
- if (text[j] == '\\')
- {
- j++;
- ADVANCE_CHAR (text, tlen, j);
- continue;
- }
-
- if (text[j] == brace_arg_separator)
- { /* { */
- strvec_dispose (result);
- report_error ("no closing `%c' in %s", '}', text);
- throw_to_top_level ();
- }
- ADVANCE_CHAR (text, tlen, j);
- }
-#endif
- free (preamble); /* Same as result[0]; see initialization. */
- result[0] = savestring (text);
- return (result);
- }
-
-#if defined (SHELL)
- amble = substring (text, start, i);
- alen = i - start;
-#else
- amble = (char *)xmalloc (1 + (i - start));
- strncpy (amble, &text[start], (i - start));
- alen = i - start;
- amble[alen] = '\0';
-#endif
-
-#if defined (SHELL)
- INITIALIZE_MBSTATE;
-
- /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
- just return without doing any expansion. */
- j = 0;
- while (amble[j])
- {
- if (amble[j] == '\\')
- {
- j++;
- ADVANCE_CHAR (amble, alen, j);
- continue;
- }
-
- if (amble[j] == brace_arg_separator)
- break;
-
- ADVANCE_CHAR (amble, alen, j);
- }
-
- if (amble[j] == 0)
- {
- tack = expand_seqterm (amble, alen);
- if (tack)
- goto add_tack;
- else
- {
- free (amble);
- free (preamble);
- result[0] = savestring (text);
- return (result);
- }
- }
-#endif /* SHELL */
-
- tack = expand_amble (amble, alen, 0);
-add_tack:
- result = array_concat (result, tack);
- free (amble);
- strvec_dispose (tack);
-
- postamble = text + i + 1;
-
- tack = brace_expand (postamble);
- result = array_concat (result, tack);
- strvec_dispose (tack);
-
- return (result);
-}
-
-/* Expand the text found inside of braces. We simply try to split the
- text at BRACE_ARG_SEPARATORs into separate strings. We then brace
- expand each slot which needs it, until there are no more slots which
- need it. */
-static char **
-expand_amble (text, tlen, flags)
- char *text;
- size_t tlen;
- int flags;
-{
- char **result, **partial;
- char *tem;
- int start, i, c;
-
- DECLARE_MBSTATE;
-
- result = (char **)NULL;
-
- start = i = 0;
- c = 1;
- while (c)
- {
- c = brace_gobbler (text, tlen, &i, brace_arg_separator);
-#if defined (SHELL)
- tem = substring (text, start, i);
-#else
- tem = (char *)xmalloc (1 + (i - start));
- strncpy (tem, &text[start], (i - start));
- tem[i- start] = '\0';
-#endif
-
- partial = brace_expand (tem);
-
- if (!result)
- result = partial;
- else
- {
- register int lr, lp, j;
-
- lr = strvec_len (result);
- lp = strvec_len (partial);
-
- result = strvec_resize (result, lp + lr + 1);
-
- for (j = 0; j < lp; j++)
- result[lr + j] = partial[j];
-
- result[lr + j] = (char *)NULL;
- free (partial);
- }
- free (tem);
- ADVANCE_CHAR (text, tlen, i);
- start = i;
- }
- return (result);
-}
-
-#define ST_BAD 0
-#define ST_INT 1
-#define ST_CHAR 2
-
-static char **
-mkseq (start, end, type)
- int start, end, type;
-{
- int n, incr, i;
- char **result, *t;
-
- n = abs (end - start) + 1;
- result = strvec_create (n + 1);
-
- incr = (start < end) ? 1 : -1;
-
- /* Make sure we go through the loop at least once, so {3..3} prints `3' */
- i = 0;
- n = start;
- do
- {
- if (type == ST_INT)
- result[i++] = itos (n);
- else
- {
- t = (char *)xmalloc (2);
- t[0] = n;
- t[1] = '\0';
- result[i++] = t;
- }
- if (n == end)
- break;
- n += incr;
- }
- while (1);
-
- result[i] = (char *)0;
- return (result);
-}
-
-static char **
-expand_seqterm (text, tlen)
- char *text;
- size_t tlen;
-{
- char *t, *lhs, *rhs;
- int i, lhs_t, rhs_t, lhs_v, rhs_v;
- intmax_t tl, tr;
- char **result;
-
- t = strstr (text, BRACE_SEQ_SPECIFIER);
- if (t == 0)
- return ((char **)NULL);
-
- i = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
- lhs = substring (text, 0, i);
- rhs = substring (text, i + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
-
- if (lhs[0] == 0 || rhs[0] == 0)
- {
- free (lhs);
- free (rhs);
- return ((char **)NULL);
- }
-
- /* Now figure out whether LHS and RHS are integers or letters. Both
- sides have to match. */
- lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
- ((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
- rhs_t = (legal_number (rhs, &tr)) ? ST_INT :
- ((ISALPHA (rhs[0]) && rhs[1] == 0) ? ST_CHAR : ST_BAD);
-
- if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
- {
- free (lhs);
- free (rhs);
- return ((char **)NULL);
- }
-
- /* OK, we have something. It's either a sequence of integers, ascending
- or descending, or a sequence or letters, ditto. Generate the sequence,
- put it into a string vector, and return it. */
-
- if (lhs_t == ST_CHAR)
- {
- lhs_v = (unsigned char)lhs[0];
- rhs_v = (unsigned char)rhs[0];
- }
- else
- {
- lhs_v = tl; /* integer truncation */
- rhs_v = tr;
- }
-
- result = mkseq (lhs_v, rhs_v, lhs_t);
-
- free (lhs);
- free (rhs);
-
- return (result);
-}
-
-/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
- index of the character matching SATISFY. This understands about
- quoting. Return the character that caused us to stop searching;
- this is either the same as SATISFY, or 0. */
-static int
-brace_gobbler (text, tlen, indx, satisfy)
- char *text;
- size_t tlen;
- int *indx;
- int satisfy;
-{
- register int i, c, quoted, level, pass_next;
-#if defined (SHELL)
- int si;
- char *t;
-#endif
- DECLARE_MBSTATE;
-
- level = quoted = pass_next = 0;
-
- i = *indx;
- while (c = text[i])
- {
- if (pass_next)
- {
- pass_next = 0;
- ADVANCE_CHAR (text, tlen, i);
- continue;
- }
-
- /* A backslash escapes the next character. This allows backslash to
- escape the quote character in a double-quoted string. */
- if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
- {
- pass_next = 1;
- i++;
- continue;
- }
-
-#if defined (SHELL)
- /* If compiling for the shell, treat ${...} like \{...} */
- if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
- {
- pass_next = 1;
- i++;
- if (quoted == 0)
- level++;
- continue;
- }
-#endif
-
- if (quoted)
- {
- if (c == quoted)
- quoted = 0;
- ADVANCE_CHAR (text, tlen, i);
- continue;
- }
-
- if (c == '"' || c == '\'' || c == '`')
- {
- quoted = c;
- i++;
- continue;
- }
-
-#if defined (SHELL)
- /* Pass new-style command substitutions through unchanged. */
- if (c == '$' && text[i+1] == '(') /* ) */
- {
- si = i + 2;
- t = extract_command_subst (text, &si);
- i = si;
- free (t);
- i++;
- continue;
- }
-#endif
-
- if (c == satisfy && level == 0 && quoted == 0)
- {
- /* We ignore an open brace surrounded by whitespace, and also
- an open brace followed immediately by a close brace preceded
- by whitespace. */
- if (c == '{' &&
- ((!i || brace_whitespace (text[i - 1])) &&
- (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
- {
- i++;
- continue;
- }
-
- break;
- }
-
- if (c == '{')
- level++;
- else if (c == '}' && level)
- level--;
-
- ADVANCE_CHAR (text, tlen, i);
- }
-
- *indx = i;
- return (c);
-}
-
-/* Return a new array of strings which is the result of appending each
- string in ARR2 to each string in ARR1. The resultant array is
- len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
- are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
- is returned. */
-static char **
-array_concat (arr1, arr2)
- char **arr1, **arr2;
-{
- register int i, j, len, len1, len2;
- register char **result;
-
- if (arr1 == 0)
- return (strvec_copy (arr2));
-
- if (arr2 == 0)
- return (strvec_copy (arr1));
-
- len1 = strvec_len (arr1);
- len2 = strvec_len (arr2);
-
- result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
-
- len = 0;
- for (i = 0; i < len1; i++)
- {
- int strlen_1 = strlen (arr1[i]);
-
- for (j = 0; j < len2; j++)
- {
- result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
- strcpy (result[len], arr1[i]);
- strcpy (result[len] + strlen_1, arr2[j]);
- len++;
- }
- free (arr1[i]);
- }
- free (arr1);
-
- result[len] = (char *)NULL;
- return (result);
-}
-
-#if defined (TEST)
-#include <stdio.h>
-
-fatal_error (format, arg1, arg2)
- char *format, *arg1, *arg2;
-{
- report_error (format, arg1, arg2);
- exit (1);
-}
-
-report_error (format, arg1, arg2)
- char *format, *arg1, *arg2;
-{
- fprintf (stderr, format, arg1, arg2);
- fprintf (stderr, "\n");
-}
-
-main ()
-{
- char example[256];
-
- for (;;)
- {
- char **result;
- int i;
-
- fprintf (stderr, "brace_expand> ");
-
- if ((!fgets (example, 256, stdin)) ||
- (strncmp (example, "quit", 4) == 0))
- break;
-
- if (strlen (example))
- example[strlen (example) - 1] = '\0';
-
- result = brace_expand (example);
-
- for (i = 0; result[i]; i++)
- printf ("%s\n", result[i]);
-
- free_array (result);
- }
-}
-
-/*
- * Local variables:
- * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
- * end:
- */
-
-#endif /* TEST */
-#endif /* BRACE_EXPANSION */
diff --git a/braces.c~ b/braces.c~
deleted file mode 100644
index c7a2d72e..00000000
--- a/braces.c~
+++ /dev/null
@@ -1,630 +0,0 @@
-/* braces.c -- code for doing word expansion in curly braces. */
-
-/* Copyright (C) 1987-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. */
-
-/* Stuff in curly braces gets expanded before all other shell expansions. */
-
-#include "config.h"
-
-#if defined (BRACE_EXPANSION)
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include "bashansi.h"
-
-#if defined (SHELL)
-# include "shell.h"
-#endif /* SHELL */
-
-#include "general.h"
-#include "shmbutil.h"
-#include "chartypes.h"
-
-#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
-
-#define BRACE_SEQ_SPECIFIER ".."
-
-/* Basic idea:
-
- Segregate the text into 3 sections: preamble (stuff before an open brace),
- postamble (stuff after the matching close brace) and amble (stuff after
- preamble, and before postamble). Expand amble, and then tack on the
- expansions to preamble. Expand postamble, and tack on the expansions to
- the result so far.
- */
-
-/* The character which is used to separate arguments. */
-int brace_arg_separator = ',';
-
-#if defined (__P)
-static int brace_gobbler __P((char *, size_t, int *, int));
-static char **expand_amble __P((char *, size_t, int));
-static char **expand_seqterm __P((char *, size_t));
-static char **mkseq __P((int, int, int, int));
-static char **array_concat __P((char **, char **));
-#else
-static int brace_gobbler ();
-static char **expand_amble ();
-static char **expand_seqterm ();
-static char **mkseq();
-static char **array_concat ();
-#endif
-
-static void
-dump_result (a)
- char **a;
-{
- int i;
-
- for (i = 0; a[i]; i++)
- printf ("dump_result: a[%d] = -%s-\n", i, a[i]);
-}
-
-/* Return an array of strings; the brace expansion of TEXT. */
-char **
-brace_expand (text)
- char *text;
-{
- register int start;
- size_t tlen;
- char *preamble, *postamble, *amble;
- size_t alen;
- char **tack, **result;
- int i, j, c, c1;
-
- DECLARE_MBSTATE;
-
- /* Find the text of the preamble. */
- tlen = strlen (text);
- i = 0;
-#if defined (CSH_BRACE_COMPAT)
- c = brace_gobbler (text, tlen, &i, '{'); /* } */
-#else
- /* Make sure that when we exit this loop, c == 0 or text[i] begins a
- valid brace expansion sequence. */
- do
- {
- c = brace_gobbler (text, tlen, &i, '{'); /* } */
- c1 = c;
- /* Verify that c begins a valid brace expansion word. If it doesn't, we
- go on. Loop stops when there are no more open braces in the word. */
- if (c)
- {
- start = j = i + 1; /* { */
- c = brace_gobbler (text, tlen, &j, '}');
- if (c == 0) /* it's not */
- {
- i++;
- c = c1;
- continue;
- }
- else /* it is */
- {
- c = c1;
- break;
- }
- }
- else
- break;
- }
- while (c);
-#endif /* !CSH_BRACE_COMPAT */
-
- preamble = (char *)xmalloc (i + 1);
- strncpy (preamble, text, i);
- preamble[i] = '\0';
-
- result = (char **)xmalloc (2 * sizeof (char *));
- result[0] = preamble;
- result[1] = (char *)NULL;
-
- /* Special case. If we never found an exciting character, then
- the preamble is all of the text, so just return that. */
- if (c != '{')
- return (result);
-
- /* Find the amble. This is the stuff inside this set of braces. */
- start = ++i;
- c = brace_gobbler (text, tlen, &i, '}');
-
- /* What if there isn't a matching close brace? */
- if (c == 0)
- {
-#if defined (NOTDEF)
- /* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
- and I, then this should be an error. Otherwise, it isn't. */
- j = start;
- while (j < i)
- {
- if (text[j] == '\\')
- {
- j++;
- ADVANCE_CHAR (text, tlen, j);
- continue;
- }
-
- if (text[j] == brace_arg_separator)
- { /* { */
- strvec_dispose (result);
- report_error ("no closing `%c' in %s", '}', text);
- throw_to_top_level ();
- }
- ADVANCE_CHAR (text, tlen, j);
- }
-#endif
- free (preamble); /* Same as result[0]; see initialization. */
- result[0] = savestring (text);
- return (result);
- }
-
-#if defined (SHELL)
- amble = substring (text, start, i);
- alen = i - start;
-#else
- amble = (char *)xmalloc (1 + (i - start));
- strncpy (amble, &text[start], (i - start));
- alen = i - start;
- amble[alen] = '\0';
-#endif
-
-#if defined (SHELL)
- INITIALIZE_MBSTATE;
-
- /* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
- just return without doing any expansion. */
- j = 0;
- while (amble[j])
- {
- if (amble[j] == '\\')
- {
- j++;
- ADVANCE_CHAR (amble, alen, j);
- continue;
- }
-
- if (amble[j] == brace_arg_separator)
- break;
-
- ADVANCE_CHAR (amble, alen, j);
- }
-
- if (amble[j] == 0)
- {
- tack = expand_seqterm (amble, alen);
- if (tack)
- goto add_tack;
- else
- {
- free (amble);
- free (preamble);
- result[0] = savestring (text);
- return (result);
- }
- }
-#endif /* SHELL */
-
- tack = expand_amble (amble, alen, 0);
-add_tack:
- result = array_concat (result, tack);
- free (amble);
- strvec_dispose (tack);
-
- postamble = text + i + 1;
-
- tack = brace_expand (postamble);
- result = array_concat (result, tack);
- strvec_dispose (tack);
-
-dump_result (result);
-
- return (result);
-}
-
-/* Expand the text found inside of braces. We simply try to split the
- text at BRACE_ARG_SEPARATORs into separate strings. We then brace
- expand each slot which needs it, until there are no more slots which
- need it. */
-static char **
-expand_amble (text, tlen, flags)
- char *text;
- size_t tlen;
- int flags;
-{
- char **result, **partial;
- char *tem;
- int start, i, c;
-
- DECLARE_MBSTATE;
-
- result = (char **)NULL;
-
- start = i = 0;
- c = 1;
- while (c)
- {
- c = brace_gobbler (text, tlen, &i, brace_arg_separator);
-#if defined (SHELL)
- tem = substring (text, start, i);
-#else
- tem = (char *)xmalloc (1 + (i - start));
- strncpy (tem, &text[start], (i - start));
- tem[i- start] = '\0';
-#endif
-
- partial = brace_expand (tem);
-
- if (!result)
- result = partial;
- else
- {
- register int lr, lp, j;
-
- lr = strvec_len (result);
- lp = strvec_len (partial);
-
- result = strvec_resize (result, lp + lr + 1);
-
- for (j = 0; j < lp; j++)
- result[lr + j] = partial[j];
-
- result[lr + j] = (char *)NULL;
- free (partial);
- }
- free (tem);
- ADVANCE_CHAR (text, tlen, i);
- start = i;
- }
- return (result);
-}
-
-#define ST_BAD 0
-#define ST_INT 1
-#define ST_CHAR 2
-
-static char **
-mkseq (start, end, incr, type)
- int start, end, incr, type;
-{
- int n, i;
- char **result, *t;
-
- n = abs (end - start) + 1;
- result = strvec_create (n + 1);
-
- if (incr == 0)
- incr = 1;
-
- if (start > end && incr > 0)
- incr = -incr;
- else if (start < end && incr < 0)
- incr = -incr;
-
- /* Make sure we go through the loop at least once, so {3..3} prints `3' */
- i = 0;
- n = start;
- do
- {
-#if defined (SHELL)
- QUIT; /* XXX - memory leak here */
-#endif
- if (type == ST_INT)
- result[i++] = itos (n);
- else
- {
- t = (char *)xmalloc (2);
- t[0] = n;
- t[1] = '\0';
- result[i++] = t;
- }
- if (n == end)
- break;
- n += incr;
- }
- while (1);
-
- result[i] = (char *)0;
- return (result);
-}
-
-static char **
-expand_seqterm (text, tlen)
- char *text;
- size_t tlen;
-{
- char *t, *lhs, *rhs;
- int i, lhs_t, rhs_t, lhs_v, rhs_v;
- intmax_t tl, tr;
- char **result;
-
- t = strstr (text, BRACE_SEQ_SPECIFIER);
- if (t == 0)
- return ((char **)NULL);
-
- i = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
- lhs = substring (text, 0, i);
- rhs = substring (text, i + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
-
- if (lhs[0] == 0 || rhs[0] == 0)
- {
- free (lhs);
- free (rhs);
- return ((char **)NULL);
- }
-
- /* Now figure out whether LHS and RHS are integers or letters. Both
- sides have to match. */
- lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
- ((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
- rhs_t = (legal_number (rhs, &tr)) ? ST_INT :
- ((ISALPHA (rhs[0]) && rhs[1] == 0) ? ST_CHAR : ST_BAD);
-
- if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
- {
- free (lhs);
- free (rhs);
- return ((char **)NULL);
- }
-
- /* OK, we have something. It's either a sequence of integers, ascending
- or descending, or a sequence or letters, ditto. Generate the sequence,
- put it into a string vector, and return it. */
-
- if (lhs_t == ST_CHAR)
- {
- lhs_v = (unsigned char)lhs[0];
- rhs_v = (unsigned char)rhs[0];
- }
- else
- {
- lhs_v = tl; /* integer truncation */
- rhs_v = tr;
- }
-
- result = mkseq (lhs_v, rhs_v, 1, lhs_t);
-
- free (lhs);
- free (rhs);
-
- return (result);
-}
-
-/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
- index of the character matching SATISFY. This understands about
- quoting. Return the character that caused us to stop searching;
- this is either the same as SATISFY, or 0. */
-/* If SATISFY is `}', we are looking for a brace expression, so we
- should enforce the rules that govern valid brace expansions:
- 1) to count as an arg separator, a comma or `..' has to be outside
- an inner set of braces.
-*/
-static int
-brace_gobbler (text, tlen, indx, satisfy)
- char *text;
- size_t tlen;
- int *indx;
- int satisfy;
-{
- register int i, c, quoted, level, commas, pass_next;
-#if defined (SHELL)
- int si;
- char *t;
-#endif
- DECLARE_MBSTATE;
-
- level = quoted = pass_next = 0;
-#if defined (CSH_BRACE_COMPAT)
- commas = 1;
-#else
- commas = (satisfy == '}') ? 0 : 1;
-#endif
-
- i = *indx;
- while (c = text[i])
- {
- if (pass_next)
- {
- pass_next = 0;
- ADVANCE_CHAR (text, tlen, i);
- continue;
- }
-
- /* A backslash escapes the next character. This allows backslash to
- escape the quote character in a double-quoted string. */
- if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
- {
- pass_next = 1;
- i++;
- continue;
- }
-
-#if defined (SHELL)
- /* If compiling for the shell, treat ${...} like \{...} */
- if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
- {
- pass_next = 1;
- i++;
- if (quoted == 0)
- level++;
- continue;
- }
-#endif
-
- if (quoted)
- {
- if (c == quoted)
- quoted = 0;
- ADVANCE_CHAR (text, tlen, i);
- continue;
- }
-
- if (c == '"' || c == '\'' || c == '`')
- {
- quoted = c;
- i++;
- continue;
- }
-
-#if defined (SHELL)
- /* Pass new-style command substitutions through unchanged. */
- if (c == '$' && text[i+1] == '(') /* ) */
- {
- si = i + 2;
- t = extract_command_subst (text, &si);
- i = si;
- free (t);
- i++;
- continue;
- }
-#endif
-
- if (c == satisfy && level == 0 && quoted == 0 && commas > 0)
- {
- /* We ignore an open brace surrounded by whitespace, and also
- an open brace followed immediately by a close brace preceded
- by whitespace. */
- if (c == '{' &&
- ((!i || brace_whitespace (text[i - 1])) &&
- (brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
- {
- i++;
- continue;
- }
-
- break;
- }
-
- if (c == '{')
- level++;
- else if (c == '}' && level)
- level--;
-#if !defined (CSH_BRACE_COMPAT)
- else if (satisfy == '}' && c == brace_arg_separator && level == 0)
- commas++;
- else if (satisfy == '}' && STREQN (text+i, BRACE_SEQ_SPECIFIER, 2) &&
- text[i+2] != satisfy && level == 0)
- commas++;
-#endif
-
- ADVANCE_CHAR (text, tlen, i);
- }
-
- *indx = i;
- return (c);
-}
-
-/* Return a new array of strings which is the result of appending each
- string in ARR2 to each string in ARR1. The resultant array is
- len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
- are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
- is returned. */
-static char **
-array_concat (arr1, arr2)
- char **arr1, **arr2;
-{
- register int i, j, len, len1, len2;
- register char **result;
-
- if (arr1 == 0)
- return (strvec_copy (arr2));
-
- if (arr2 == 0)
- return (strvec_copy (arr1));
-
- len1 = strvec_len (arr1);
- len2 = strvec_len (arr2);
-
- result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
-
- len = 0;
- for (i = 0; i < len1; i++)
- {
- int strlen_1 = strlen (arr1[i]);
-
- for (j = 0; j < len2; j++)
- {
- result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
- strcpy (result[len], arr1[i]);
- strcpy (result[len] + strlen_1, arr2[j]);
- len++;
- }
- free (arr1[i]);
- }
- free (arr1);
-
- result[len] = (char *)NULL;
- return (result);
-}
-
-#if defined (TEST)
-#include <stdio.h>
-
-fatal_error (format, arg1, arg2)
- char *format, *arg1, *arg2;
-{
- report_error (format, arg1, arg2);
- exit (1);
-}
-
-report_error (format, arg1, arg2)
- char *format, *arg1, *arg2;
-{
- fprintf (stderr, format, arg1, arg2);
- fprintf (stderr, "\n");
-}
-
-main ()
-{
- char example[256];
-
- for (;;)
- {
- char **result;
- int i;
-
- fprintf (stderr, "brace_expand> ");
-
- if ((!fgets (example, 256, stdin)) ||
- (strncmp (example, "quit", 4) == 0))
- break;
-
- if (strlen (example))
- example[strlen (example) - 1] = '\0';
-
- result = brace_expand (example);
-
- for (i = 0; result[i]; i++)
- printf ("%s\n", result[i]);
-
- free_array (result);
- }
-}
-
-/*
- * Local variables:
- * compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
- * end:
- */
-
-#endif /* TEST */
-#endif /* BRACE_EXPANSION */
diff --git a/builtins/cd.def~ b/builtins/cd.def~
deleted file mode 100644
index 025e4f5e..00000000
--- a/builtins/cd.def~
+++ /dev/null
@@ -1,525 +0,0 @@
-This file is cd.def, from which is created cd.c. It implements the
-builtins "cd" and "pwd" in Bash.
-
-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.
-
-$PRODUCES cd.c
-#include <config.h>
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include "../bashtypes.h"
-#include "posixdir.h"
-#include "posixstat.h"
-#ifndef _MINIX
-#include <sys/param.h>
-#endif
-
-#include <stdio.h>
-
-#include "../bashansi.h"
-#include "../bashintl.h"
-
-#include <errno.h>
-#include <tilde/tilde.h>
-
-#include "../shell.h"
-#include "../flags.h"
-#include "maxpath.h"
-#include "common.h"
-#include "bashgetopt.h"
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-extern int posixly_correct;
-extern int array_needs_making;
-extern char *bash_getcwd_errstr;
-
-static int bindpwd __P((int));
-static void setpwd __P((char *));
-static int change_to_directory __P((char *, int));
-
-static char *cdspell __P((char *));
-
-/* Change this to 1 to get cd spelling correction by default. */
-int cdspelling = 0;
-
-int cdable_vars;
-
-$BUILTIN cd
-$FUNCTION cd_builtin
-$SHORT_DOC cd [-L|-P] [dir]
-Change the current directory to DIR. The variable $HOME is the
-default DIR. The variable CDPATH defines the search path for
-the directory containing DIR. Alternative directory names in CDPATH
-are separated by a colon (:). A null directory name is the same as
-the current directory, i.e. `.'. If DIR begins with a slash (/),
-then CDPATH is not used. If the directory is not found, and the
-shell option `cdable_vars' is set, then try the word as a variable
-name. If that variable has a value, then cd to the value of that
-variable. The -P option says to use the physical directory structure
-instead of following symbolic links; the -L option forces symbolic links
-to be followed.
-$END
-
-/* Just set $PWD, don't change OLDPWD. Used by `pwd -P' in posix mode. */
-static void
-setpwd (dirname)
- char *dirname;
-{
- int old_anm;
- SHELL_VAR *tvar;
-
- old_anm = array_needs_making;
- tvar = bind_variable ("PWD", dirname ? dirname : "", 0);
- if (old_anm == 0 && array_needs_making && exported_p (tvar))
- {
- update_export_env_inplace ("PWD=", 4, dirname ? dirname : "");
- array_needs_making = 0;
- }
-}
-
-static int
-bindpwd (no_symlinks)
- int no_symlinks;
-{
- char *dirname, *pwdvar;
- int old_anm;
- SHELL_VAR *tvar;
-
-#define tcwd the_current_working_directory
- dirname = tcwd ? (no_symlinks ? sh_physpath (tcwd, 0) : tcwd)
- : get_working_directory ("cd");
-#undef tcwd
-
- old_anm = array_needs_making;
- pwdvar = get_string_value ("PWD");
-
- tvar = bind_variable ("OLDPWD", pwdvar, 0);
- if (old_anm == 0 && array_needs_making && exported_p (tvar))
- {
- update_export_env_inplace ("OLDPWD=", 7, pwdvar);
- array_needs_making = 0;
- }
-
- setpwd (dirname);
-
- if (dirname && dirname != the_current_working_directory)
- free (dirname);
-
- return (EXECUTION_SUCCESS);
-}
-
-/* Call get_working_directory to reset the value of
- the_current_working_directory () */
-static char *
-resetpwd (caller)
- char *caller;
-{
- char *tdir;
-
- FREE (the_current_working_directory);
- the_current_working_directory = (char *)NULL;
- tdir = get_working_directory (caller);
- return (tdir);
-}
-
-#define LCD_DOVARS 0x001
-#define LCD_DOSPELL 0x002
-#define LCD_PRINTPATH 0x004
-#define LCD_FREEDIRNAME 0x010
-
-/* This builtin is ultimately the way that all user-visible commands should
- change the current working directory. It is called by cd_to_string (),
- so the programming interface is simple, and it handles errors and
- restrictions properly. */
-int
-cd_builtin (list)
- WORD_LIST *list;
-{
- char *dirname, *cdpath, *path, *temp;
- int path_index, no_symlinks, opt, lflag;
-
-#if defined (RESTRICTED_SHELL)
- if (restricted)
- {
- sh_restricted ((char *)NULL);
- return (EXECUTION_FAILURE);
- }
-#endif /* RESTRICTED_SHELL */
-
- no_symlinks = no_symbolic_links;
- reset_internal_getopt ();
- while ((opt = internal_getopt (list, "LP")) != -1)
- {
- switch (opt)
- {
- case 'P':
- no_symlinks = 1;
- break;
- case 'L':
- no_symlinks = 0;
- break;
- default:
- builtin_usage ();
- return (EXECUTION_FAILURE);
- }
- }
- list = loptend;
-
- lflag = (cdable_vars ? LCD_DOVARS : 0) |
- ((interactive && cdspelling) ? LCD_DOSPELL : 0);
-
- if (list == 0)
- {
- /* `cd' without arguments is equivalent to `cd $HOME' */
- dirname = get_string_value ("HOME");
-
- if (dirname == 0)
- {
- builtin_error (_("HOME not set"));
- return (EXECUTION_FAILURE);
- }
- lflag = 0;
- }
- else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
- {
- /* This is `cd -', equivalent to `cd $OLDPWD' */
- dirname = get_string_value ("OLDPWD");
-
- if (dirname == 0)
- {
- builtin_error (_("OLDPWD not set"));
- return (EXECUTION_FAILURE);
- }
-#if 0
- lflag = interactive ? LCD_PRINTPATH : 0;
-#else
- lflag = LCD_PRINTPATH; /* According to SUSv3 */
-#endif
- }
- else if (absolute_pathname (list->word->word))
- dirname = list->word->word;
- else if (cdpath = get_string_value ("CDPATH"))
- {
- dirname = list->word->word;
-
- /* Find directory in $CDPATH. */
- path_index = 0;
- while (path = extract_colon_unit (cdpath, &path_index))
- {
- /* OPT is 1 if the path element is non-empty */
- opt = path[0] != '\0';
- temp = sh_makepath (path, dirname, MP_DOTILDE);
- free (path);
-
- if (change_to_directory (temp, no_symlinks))
- {
- /* POSIX.2 says that if a nonempty directory from CDPATH
- is used to find the directory to change to, the new
- directory name is echoed to stdout, whether or not
- the shell is interactive. */
- if (opt && (path = no_symlinks ? temp : the_current_working_directory))
- printf ("%s\n", path);
-
- free (temp);
-#if 0
- /* Posix.2 says that after using CDPATH, the resultant
- value of $PWD will not contain `.' or `..'. */
- return (bindpwd (posixly_correct || no_symlinks));
-#else
- return (bindpwd (no_symlinks));
-#endif
- }
- else
- free (temp);
- }
-
- /* POSIX.2 says that if `.' does not appear in $CDPATH, we don't
- try the current directory, so we just punt now with an error
- message if POSIXLY_CORRECT is non-zero. The check for cdpath[0]
- is so we don't mistakenly treat a CDPATH value of "" as not
- specifying the current directory. */
- if (posixly_correct && cdpath[0])
- {
- builtin_error ("%s: %s", dirname, strerror (ENOENT));
- return (EXECUTION_FAILURE);
- }
- }
- else
- dirname = list->word->word;
-
- /* When we get here, DIRNAME is the directory to change to. If we
- chdir successfully, just return. */
- if (change_to_directory (dirname, no_symlinks))
- {
- if (lflag & LCD_PRINTPATH)
- printf ("%s\n", dirname);
- return (bindpwd (no_symlinks));
- }
-
- /* If the user requests it, then perhaps this is the name of
- a shell variable, whose value contains the directory to
- change to. */
- if (lflag & LCD_DOVARS)
- {
- temp = get_string_value (dirname);
- if (temp && change_to_directory (temp, no_symlinks))
- {
- printf ("%s\n", temp);
- return (bindpwd (no_symlinks));
- }
- }
-
- /* If the user requests it, try to find a directory name similar in
- spelling to the one requested, in case the user made a simple
- typo. This is similar to the UNIX 8th and 9th Edition shells. */
- if (lflag & LCD_DOSPELL)
- {
- temp = cdspell (dirname);
- if (temp && change_to_directory (temp, no_symlinks))
- {
- printf ("%s\n", temp);
- return (bindpwd (no_symlinks));
- }
- else
- FREE (temp);
- }
-
- builtin_error ("%s: %s", dirname, strerror (errno));
- return (EXECUTION_FAILURE);
-}
-
-$BUILTIN pwd
-$FUNCTION pwd_builtin
-$SHORT_DOC pwd [-LP]
-Print the current working directory. With the -P option, pwd prints
-the physical directory, without any symbolic links; the -L option
-makes pwd follow symbolic links.
-$END
-
-/* Non-zero means that pwd always prints the physical directory, without
- symbolic links. */
-static int verbatim_pwd;
-
-/* Print the name of the current working directory. */
-int
-pwd_builtin (list)
- WORD_LIST *list;
-{
- char *directory;
- int opt, pflag;
-
- verbatim_pwd = no_symbolic_links;
- pflag = 0;
- reset_internal_getopt ();
- while ((opt = internal_getopt (list, "LP")) != -1)
- {
- switch (opt)
- {
- case 'P':
- verbatim_pwd = pflag = 1;
- break;
- case 'L':
- verbatim_pwd = 0;
- break;
- default:
- builtin_usage ();
- return (EXECUTION_FAILURE);
- }
- }
- list = loptend;
-
-#define tcwd the_current_working_directory
-
- directory = tcwd ? (verbatim_pwd ? sh_physpath (tcwd, 0) : tcwd)
- : get_working_directory ("pwd");
-
- /* Try again using getcwd() if canonicalization fails (for instance, if
- the file system has changed state underneath bash). */
- if ((tcwd && directory == 0) ||
- (posixly_correct && same_file (".", tcwd, (struct stat *)0, (struct stat *)0) == 0))
- directory = resetpwd ("pwd");
-
-#undef tcwd
-
- if (directory)
- {
- printf ("%s\n", directory);
- /* This is dumb but posix-mandated. */
- if (posixly_correct && pflag)
- setpwd (directory);
- if (directory != the_current_working_directory)
- free (directory);
- fflush (stdout);
- if (ferror (stdout))
- {
- sh_wrerror ();
- clearerr (stdout);
- return (EXECUTION_FAILURE);
- }
-
- return (EXECUTION_SUCCESS);
- }
- else
- return (EXECUTION_FAILURE);
-}
-
-/* Do the work of changing to the directory NEWDIR. Handle symbolic
- link following, etc. This function *must* return with
- the_current_working_directory either set to NULL (in which case
- getcwd() will eventually be called), or set to a string corresponding
- to the working directory. Return 1 on success, 0 on failure. */
-
-static int
-change_to_directory (newdir, nolinks)
- char *newdir;
- int nolinks;
-{
- char *t, *tdir;
- int err, canon_failed, r, ndlen, dlen;
-
- tdir = (char *)NULL;
-
- if (the_current_working_directory == 0)
- {
- t = get_working_directory ("chdir");
- FREE (t);
- }
-
- t = make_absolute (newdir, the_current_working_directory);
-
- /* TDIR is either the canonicalized absolute pathname of NEWDIR
- (nolinks == 0) or the absolute physical pathname of NEWDIR
- (nolinks != 0). */
- tdir = nolinks ? sh_physpath (t, 0)
- : sh_canonpath (t, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
-
- ndlen = strlen (newdir);
- dlen = strlen (t);
-
- /* Use the canonicalized version of NEWDIR, or, if canonicalization
- failed, use the non-canonical form. */
- canon_failed = 0;
- if (tdir && *tdir)
- free (t);
- else
- {
- FREE (tdir);
- tdir = t;
- canon_failed = 1;
- }
-
- /* In POSIX mode, if we're resolving symlinks logically and sh_canonpath
- returns NULL (because it checks the path, it will return NULL if the
- resolved path doesn't exist), fail immediately. */
- if (posixly_correct && nolinks == 0 && canon_failed && (errno != ENAMETOOLONG || ndlen > PATH_MAX))
- {
-#if defined ENAMETOOLONG
- if (errno != ENOENT && errno != ENAMETOOLONG)
-#else
- if (errno != ENOENT)
-#endif
- errno = ENOTDIR;
- free (tdir);
- return (0);
- }
-
- /* If the chdir succeeds, update the_current_working_directory. */
- if (chdir (nolinks ? newdir : tdir) == 0)
- {
- /* If canonicalization failed, but the chdir succeeded, reset the
- shell's idea of the_current_working_directory. */
- if (canon_failed)
- {
- t = resetpwd ("cd");
- if (t == 0)
- set_working_directory (tdir);
- }
- else
- set_working_directory (tdir);
-
- free (tdir);
- return (1);
- }
-
- /* We failed to change to the appropriate directory name. If we tried
- what the user passed (nolinks != 0), punt now. */
- if (nolinks)
- {
- free (tdir);
- return (0);
- }
-
- err = errno;
-
- /* We're not in physical mode (nolinks == 0), but we failed to change to
- the canonicalized directory name (TDIR). Try what the user passed
- verbatim. If we succeed, reinitialize the_current_working_directory. */
- if (chdir (newdir) == 0)
- {
- t = resetpwd ("cd");
- if (t == 0)
- set_working_directory (tdir);
- else
- free (t);
-
- r = 1;
- }
- else
- {
- errno = err;
- r = 0;
- }
-
- free (tdir);
- return r;
-}
-
-/* Code for cd spelling correction. Original patch submitted by
- Neil Russel (caret@c-side.com). */
-
-static char *
-cdspell (dirname)
- char *dirname;
-{
- int n;
- char *guess;
-
- n = (strlen (dirname) * 3 + 1) / 2 + 1;
- guess = (char *)xmalloc (n);
-
- switch (spname (dirname, guess))
- {
- case -1:
- default:
- free (guess);
- return (char *)NULL;
- case 0:
- case 1:
- return guess;
- }
-}
diff --git a/builtins/declare.def~ b/builtins/declare.def~
deleted file mode 100644
index 0db7cc4f..00000000
--- a/builtins/declare.def~
+++ /dev/null
@@ -1,475 +0,0 @@
-This file is declare.def, from which is created declare.c.
-It implements the builtins "declare" and "local" in Bash.
-
-Copyright (C) 1987-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.
-
-$PRODUCES declare.c
-
-$BUILTIN declare
-$FUNCTION declare_builtin
-$SHORT_DOC declare [-afFirtx] [-p] [name[=value] ...]
-Declare variables and/or give them attributes. If no NAMEs are
-given, then display the values of variables instead. The -p option
-will display the attributes and values of each NAME.
-
-The flags are:
-
- -a to make NAMEs arrays (if supported)
- -f to select from among function names only
- -F to display function names (and line number and source file name if
- debugging) without definitions
- -i to make NAMEs have the `integer' attribute
- -r to make NAMEs readonly
- -t to make NAMEs have the `trace' attribute
- -x to make NAMEs export
-
-Variables with the integer attribute have arithmetic evaluation (see
-`let') done when the variable is assigned to.
-
-When displaying values of variables, -f displays a function's name
-and definition. The -F option restricts the display to function
-name only.
-
-Using `+' instead of `-' turns off the given attribute instead. When
-used in a function, makes NAMEs local, as with the `local' command.
-$END
-
-$BUILTIN typeset
-$FUNCTION declare_builtin
-$SHORT_DOC typeset [-afFirtx] [-p] name[=value] ...
-Obsolete. See `declare'.
-$END
-
-#include <config.h>
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-
-#include "../bashansi.h"
-#include "../bashintl.h"
-
-#include "../shell.h"
-#include "common.h"
-#include "builtext.h"
-#include "bashgetopt.h"
-
-extern int array_needs_making;
-extern int posixly_correct;
-
-static int declare_internal __P((register WORD_LIST *, int));
-
-/* Declare or change variable attributes. */
-int
-declare_builtin (list)
- register WORD_LIST *list;
-{
- return (declare_internal (list, 0));
-}
-
-$BUILTIN local
-$FUNCTION local_builtin
-$SHORT_DOC local name[=value] ...
-Create a local variable called NAME, and give it VALUE. LOCAL
-can only be used within a function; it makes the variable NAME
-have a visible scope restricted to that function and its children.
-$END
-int
-local_builtin (list)
- register WORD_LIST *list;
-{
- if (variable_context)
- return (declare_internal (list, 1));
- else
- {
- builtin_error (_("can only be used in a function"));
- return (EXECUTION_FAILURE);
- }
-}
-
-#if defined (ARRAY_VARS)
-# define DECLARE_OPTS "+afiprtxF"
-#else
-# define DECLARE_OPTS "+fiprtxF"
-#endif
-
-/* The workhorse function. */
-static int
-declare_internal (list, local_var)
- register WORD_LIST *list;
- int local_var;
-{
- int flags_on, flags_off, *flags, any_failed, assign_error, pflag, nodefs, opt;
- char *t, *subscript_start;
- SHELL_VAR *var;
- FUNCTION_DEF *shell_fn;
-
- flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0;
- reset_internal_getopt ();
- while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF)
- {
- flags = list_opttype == '+' ? &flags_off : &flags_on;
-
- switch (opt)
- {
- case 'a':
-#if defined (ARRAY_VARS)
- *flags |= att_array;
-#endif
- break;
- case 'p':
- if (local_var == 0)
- pflag++;
- break;
- case 'F':
- nodefs++;
- *flags |= att_function;
- break;
- case 'f':
- *flags |= att_function;
- break;
- case 'i':
- *flags |= att_integer;
- break;
- case 'r':
- *flags |= att_readonly;
- break;
- case 't':
- *flags |= att_trace;
- break;
- case 'x':
- *flags |= att_exported;
- array_needs_making = 1;
- break;
- default:
- builtin_usage ();
- return (EX_USAGE);
- }
- }
-
- list = loptend;
-
- /* If there are no more arguments left, then we just want to show
- some variables. */
- if (list == 0) /* declare -[afFirtx] */
- {
- /* Show local variables defined at this context level if this is
- the `local' builtin. */
- if (local_var)
- {
- register SHELL_VAR **vlist;
- register int i;
-
- vlist = all_local_variables ();
-
- if (vlist)
- {
- for (i = 0; vlist[i]; i++)
- print_assignment (vlist[i]);
-
- free (vlist);
- }
- }
- else
- {
- if (flags_on == 0)
- set_builtin ((WORD_LIST *)NULL);
- else
- set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs);
- }
-
- fflush (stdout);
- return (EXECUTION_SUCCESS);
- }
-
- if (pflag) /* declare -p [-afFirtx] name [name...] */
- {
- for (any_failed = 0; list; list = list->next)
- {
- pflag = show_name_attributes (list->word->word, nodefs);
- if (pflag)
- {
- sh_notfound (list->word->word);
- any_failed++;
- }
- }
- return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
- }
-
-#define NEXT_VARIABLE() free (name); list = list->next; continue
-
- /* There are arguments left, so we are making variables. */
- while (list) /* declare [-afFirx] name [name ...] */
- {
- char *value, *name;
- int offset, aflags;
-#if defined (ARRAY_VARS)
- int making_array_special, compound_array_assign, simple_array_assign;
-#endif
-
- name = savestring (list->word->word);
- offset = assignment (name, 0);
- aflags = 0;
-
- if (offset) /* declare [-afFirx] name=value */
- {
- name[offset] = '\0';
- value = name + offset + 1;
- if (name[offset - 1] == '+')
- {
- aflags |= ASS_APPEND;
- name[offset - 1] = '\0';
- }
- }
- else
- value = "";
-
-#if defined (ARRAY_VARS)
- compound_array_assign = simple_array_assign = 0;
- subscript_start = (char *)NULL;
- if (t = strchr (name, '[')) /* ] */
- {
- subscript_start = t;
- *t = '\0';
- making_array_special = 1;
- }
- else
- making_array_special = 0;
-#endif
-
- /* If we're in posix mode or not looking for a shell function (since
- shell function names don't have to be valid identifiers when the
- shell's not in posix mode), check whether or not the argument is a
- valid, well-formed shell identifier. */
- if ((posixly_correct || (flags & att_function) == 0) && legal_identifier (name) == 0)
- {
- sh_invalidid (name);
- assign_error++;
- NEXT_VARIABLE ();
- }
-
- /* If VARIABLE_CONTEXT has a non-zero value, then we are executing
- inside of a function. This means we should make local variables,
- not global ones. */
-
- /* XXX - this has consequences when we're making a local copy of a
- variable that was in the temporary environment. Watch out
- for this. */
- if (variable_context && ((flags_on & att_function) == 0))
- {
-#if defined (ARRAY_VARS)
- if ((flags_on & att_array) || making_array_special)
- var = make_local_array_variable (name);
- else
-#endif
- var = make_local_variable (name);
- if (var == 0)
- {
- any_failed++;
- NEXT_VARIABLE ();
- }
- }
- else
- var = (SHELL_VAR *)NULL;
-
- /* If we are declaring a function, then complain about it in some way.
- We don't let people make functions by saying `typeset -f foo=bar'. */
-
- /* There should be a way, however, to let people look at a particular
- function definition by saying `typeset -f foo'. */
-
- if (flags_on & att_function)
- {
- if (offset) /* declare -f [-rix] foo=bar */
- {
- builtin_error (_("cannot use `-f' to make functions"));
- free (name);
- return (EXECUTION_FAILURE);
- }
- else /* declare -f [-rx] name [name...] */
- {
- var = find_function (name);
-
- if (var)
- {
- if (readonly_p (var) && (flags_off & att_readonly))
- {
- builtin_error (_("%s: readonly function"), name);
- any_failed++;
- NEXT_VARIABLE ();
- }
-
- /* declare -[Ff] name [name...] */
- if (flags_on == att_function && flags_off == 0)
- {
-#if defined (DEBUGGER)
- if (nodefs && debugging_mode)
- {
- shell_fn = find_function_def (var->name);
- if (shell_fn)
- printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file);
- else
- printf ("%s\n", var->name);
- }
- else
-#endif /* DEBUGGER */
- {
- t = nodefs ? var->name
- : named_function_string (name, function_cell (var), 1);
- printf ("%s\n", t);
- }
- }
- else /* declare -[fF] -[rx] name [name...] */
- {
- VSETATTR (var, flags_on);
- VUNSETATTR (var, flags_off);
- }
- }
- else
- any_failed++;
- NEXT_VARIABLE ();
- }
- }
- else /* declare -[airx] name [name...] */
- {
- /* Non-null if we just created or fetched a local variable. */
- if (var == 0)
- var = find_variable (name);
-
- if (var == 0)
- {
-#if defined (ARRAY_VARS)
- if ((flags_on & att_array) || making_array_special)
- var = make_new_array_variable (name);
- else
-#endif
- var = bind_variable (name, "", 0);
- }
-
- /* Cannot use declare +r to turn off readonly attribute. */
- if (readonly_p (var) && (flags_off & att_readonly))
- {
- sh_readonly (name);
- any_failed++;
- NEXT_VARIABLE ();
- }
-
- /* Cannot use declare to assign value to readonly or noassign
- variable. */
- if ((readonly_p (var) || noassign_p (var)) && offset)
- {
- if (readonly_p (var))
- sh_readonly (name);
- assign_error++;
- NEXT_VARIABLE ();
- }
-
-#if defined (ARRAY_VARS)
- if ((making_array_special || (flags_on & att_array) || array_p (var)) && offset)
- {
- int vlen;
- vlen = STRLEN (value);
-#if 0
- if (value[0] == '(' && strchr (value, ')'))
-#else
- if (value[0] == '(' && value[vlen-1] == ')')
-#endif
- compound_array_assign = 1;
- else
- simple_array_assign = 1;
- }
-
- /* Cannot use declare +a name to remove an array variable. */
- if ((flags_off & att_array) && array_p (var))
- {
- builtin_error (_("%s: cannot destroy array variables in this way"), name);
- any_failed++;
- NEXT_VARIABLE ();
- }
-
- /* declare -a name makes name an array variable. */
- if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0)
- var = convert_var_to_array (var);
-#endif /* ARRAY_VARS */
-
- VSETATTR (var, flags_on);
- VUNSETATTR (var, flags_off);
-
-#if defined (ARRAY_VARS)
- if (offset && compound_array_assign)
- assign_array_var_from_string (var, value, aflags);
- else if (simple_array_assign && subscript_start)
- {
- /* declare [-a] name[N]=value */
- *subscript_start = '['; /* ] */
- var = assign_array_element (name, value, 0); /* XXX - not aflags */
- *subscript_start = '\0';
- }
- else if (simple_array_assign)
- /* let bind_array_variable take care of this. */
- bind_array_variable (name, 0, value, aflags);
- else
-#endif
- /* bind_variable_value duplicates the essential internals of
- bind_variable() */
- if (offset)
- bind_variable_value (var, value, aflags);
-
- /* If we found this variable in the temporary environment, as with
- `var=value declare -x var', make sure it is treated identically
- to `var=value export var'. Do the same for `declare -r' and
- `readonly'. Preserve the attributes, except for att_tempvar. */
- /* XXX -- should this create a variable in the global scope, or
- modify the local variable flags? ksh93 has it modify the
- global scope.
- Need to handle case like in set_var_attribute where a temporary
- variable is in the same table as the function local vars. */
- if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var))
- {
- SHELL_VAR *tv;
- char *tvalue;
-
- tv = find_tempenv_variable (var->name);
- if (tv)
- {
- tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring ("");
- tv = bind_variable (var->name, tvalue, 0);
- tv->attributes |= var->attributes & ~att_tempvar;
- if (tv->context > 0)
- VSETATTR (tv, att_propagate);
- free (tvalue);
- }
- VSETATTR (var, att_propagate);
- }
- }
-
- stupidly_hack_special_variables (name);
-
- NEXT_VARIABLE ();
- }
-
- return (assign_error ? EX_BADASSIGN
- : ((any_failed == 0) ? EXECUTION_SUCCESS
- : EXECUTION_FAILURE));
-}
diff --git a/builtins/echo.def~ b/builtins/echo.def~
deleted file mode 100644
index 0effc894..00000000
--- a/builtins/echo.def~
+++ /dev/null
@@ -1,185 +0,0 @@
-This file is echo.def, from which is created echo.c.
-It implements the builtin "echo" in Bash.
-
-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.
-
-$PRODUCES echo.c
-#include <config.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "../bashansi.h"
-
-#include <stdio.h>
-#include "../shell.h"
-
-#include "common.h"
-
-$BUILTIN echo
-$FUNCTION echo_builtin
-$DEPENDS_ON V9_ECHO
-$SHORT_DOC echo [-neE] [arg ...]
-Output the ARGs. If -n is specified, the trailing newline is
-suppressed. If the -e option is given, interpretation of the
-following backslash-escaped characters is turned on:
- \a alert (bell)
- \b backspace
- \c suppress trailing newline
- \E escape character
- \f form feed
- \n new line
- \r carriage return
- \t horizontal tab
- \v vertical tab
- \\ backslash
- \num the character whose ASCII code is NUM (octal).
-
-You can explicitly turn off the interpretation of the above characters
-with the -E option.
-$END
-
-$BUILTIN echo
-$FUNCTION echo_builtin
-$DEPENDS_ON !V9_ECHO
-$SHORT_DOC echo [-n] [arg ...]
-Output the ARGs. If -n is specified, the trailing newline is suppressed.
-$END
-
-#if defined (V9_ECHO)
-# define VALID_ECHO_OPTIONS "neE"
-#else /* !V9_ECHO */
-# define VALID_ECHO_OPTIONS "n"
-#endif /* !V9_ECHO */
-
-/* System V machines already have a /bin/sh with a v9 behaviour. We
- give Bash the identical behaviour for these machines so that the
- existing system shells won't barf. Regrettably, the SUS v2 has
- standardized the Sys V echo behavior. This variable is external
- so that we can have a `shopt' variable to control it at runtime. */
-#if defined (DEFAULT_ECHO_TO_XPG) || defined (STRICT_POSIX)
-int xpg_echo = 1;
-#else
-int xpg_echo = 0;
-#endif /* DEFAULT_ECHO_TO_XPG */
-
-extern int posixly_correct;
-
-/* Print the words in LIST to standard output. If the first word is
- `-n', then don't print a trailing newline. We also support the
- echo syntax from Version 9 Unix systems. */
-int
-echo_builtin (list)
- WORD_LIST *list;
-{
- int display_return, do_v9, i, len;
- char *temp, *s;
-
- do_v9 = xpg_echo;
- display_return = 1;
-
- if (posixly_correct && xpg_echo)
- goto just_echo;
-
- for (; list && (temp = list->word->word) && *temp == '-'; list = list->next)
- {
- /* If it appears that we are handling options, then make sure that
- all of the options specified are actually valid. Otherwise, the
- string should just be echoed. */
- temp++;
-
- for (i = 0; temp[i]; i++)
- {
- if (strchr (VALID_ECHO_OPTIONS, temp[i]) == 0)
- break;
- }
-
- /* echo - and echo -<nonopt> both mean to just echo the arguments. */
- if (*temp == 0 || temp[i])
- break;
-
- /* All of the options in TEMP are valid options to ECHO.
- Handle them. */
- while (i = *temp++)
- {
- switch (i)
- {
- case 'n':
- display_return = 0;
- break;
-#if defined (V9_ECHO)
- case 'e':
- do_v9 = 1;
- break;
- case 'E':
- do_v9 = 0;
- break;
-#endif /* V9_ECHO */
- default:
- goto just_echo; /* XXX */
- }
- }
- }
-
-just_echo:
-
- clearerr (stdout); /* clear error before writing and testing success */
-
- while (list)
- {
- i = len = 0;
- temp = do_v9 ? ansicstr (list->word->word, STRLEN (list->word->word), 1, &i, &len)
- : list->word->word;
- if (temp)
- {
- if (do_v9)
- {
- for (s = temp; len > 0; len--)
- putchar (*s++);
- }
- else
- printf ("%s", temp);
-#if defined (SunOS5)
- fflush (stdout); /* Fix for bug in SunOS 5.5 printf(3) */
-#endif
- }
- if (do_v9 && temp)
- free (temp);
- list = list->next;
- if (i)
- {
- display_return = 0;
- break;
- }
- if (list)
- putchar(' ');
- }
-
- if (display_return)
- putchar ('\n');
- fflush (stdout);
- if (ferror (stdout))
- {
- sh_wrerror ();
- clearerr (stdout);
- return (EXECUTION_FAILURE);
- }
- return (EXECUTION_SUCCESS);
-}
diff --git a/builtins/evalfile.c~ b/builtins/evalfile.c~
deleted file mode 100644
index 81be017b..00000000
--- a/builtins/evalfile.c~
+++ /dev/null
@@ -1,320 +0,0 @@
-/* Copyright (C) 1996-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>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "../bashtypes.h"
-#include "posixstat.h"
-#include "filecntl.h"
-
-#include <stdio.h>
-#include <signal.h>
-#include <errno.h>
-
-#include "../bashansi.h"
-#include "../bashintl.h"
-
-#include "../shell.h"
-#include "../jobs.h"
-#include "../builtins.h"
-#include "../flags.h"
-#include "../input.h"
-#include "../execute_cmd.h"
-#include "../trap.h"
-
-#if defined (HISTORY)
-# include "../bashhist.h"
-#endif
-
-#include "common.h"
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-/* Flags for _evalfile() */
-#define FEVAL_ENOENTOK 0x001
-#define FEVAL_BUILTIN 0x002
-#define FEVAL_UNWINDPROT 0x004
-#define FEVAL_NONINT 0x008
-#define FEVAL_LONGJMP 0x010
-#define FEVAL_HISTORY 0x020
-#define FEVAL_CHECKBINARY 0x040
-#define FEVAL_REGFILE 0x080
-#define FEVAL_NOPUSHARGS 0x100
-
-extern int posixly_correct;
-extern int indirection_level, startup_state, subshell_environment;
-extern int return_catch_flag, return_catch_value;
-extern int last_command_exit_value;
-
-/* How many `levels' of sourced files we have. */
-int sourcelevel = 0;
-
-static int
-_evalfile (filename, flags)
- const char *filename;
- int flags;
-{
- volatile int old_interactive;
- procenv_t old_return_catch;
- int return_val, fd, result, pflags;
- char *string;
- struct stat finfo;
- size_t file_size;
- sh_vmsg_func_t *errfunc;
-#if defined (ARRAY_VARS)
- SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
- ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
-# if defined (DEBUGGER)
- SHELL_VAR *bash_argv_v, *bash_argc_v;
- ARRAY *bash_argv_a, *bash_argc_a;
-# endif
- char *t, tt[2];
-#endif
-
- USE_VAR(pflags);
-
-#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);
-# if defined (DEBUGGER)
- GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
- GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
-# endif
-#endif
-
- fd = open (filename, O_RDONLY);
-
- if (fd < 0 || (fstat (fd, &finfo) == -1))
- {
-file_error_and_exit:
- if (((flags & FEVAL_ENOENTOK) == 0) || errno != ENOENT)
- file_error (filename);
-
- if (flags & FEVAL_LONGJMP)
- {
- last_command_exit_value = 1;
- jump_to_top_level (EXITPROG);
- }
-
- return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE
- : ((errno == ENOENT) ? 0 : -1));
- }
-
- errfunc = ((flags & FEVAL_BUILTIN) ? builtin_error : internal_error);
-
- if (S_ISDIR (finfo.st_mode))
- {
- (*errfunc) (_("%s: is a directory"), filename);
- return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
- }
- else if ((flags & FEVAL_REGFILE) && S_ISREG (finfo.st_mode) == 0)
- {
- (*errfunc) (_("%s: not a regular file"), filename);
- return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
- }
-
- file_size = (size_t)finfo.st_size;
- /* Check for overflow with large files. */
- if (file_size != finfo.st_size || file_size + 1 < file_size)
- {
- (*errfunc) (_("%s: file is too large"), filename);
- return ((flags & FEVAL_BUILTIN) ? EXECUTION_FAILURE : -1);
- }
-
-#if defined (__CYGWIN__) && defined (O_TEXT)
- setmode (fd, O_TEXT);
-#endif
-
- string = (char *)xmalloc (1 + file_size);
- result = read (fd, string, file_size);
- string[result] = '\0';
-
- return_val = errno;
- close (fd);
- errno = return_val;
-
- if (result < 0) /* XXX was != file_size, not < 0 */
- {
- free (string);
- goto file_error_and_exit;
- }
-
- if (result == 0)
- {
- free (string);
- return ((flags & FEVAL_BUILTIN) ? EXECUTION_SUCCESS : 1);
- }
-
- if ((flags & FEVAL_CHECKBINARY) &&
- check_binary_file (string, (result > 80) ? 80 : result))
- {
- free (string);
- (*errfunc) ("%s: cannot execute binary file", filename);
- return ((flags & FEVAL_BUILTIN) ? EX_BINARY_FILE : -1);
- }
-
- if (flags & FEVAL_UNWINDPROT)
- {
- begin_unwind_frame ("_evalfile");
-
- unwind_protect_int (return_catch_flag);
- unwind_protect_jmp_buf (return_catch);
- if (flags & FEVAL_NONINT)
- unwind_protect_int (interactive);
- unwind_protect_int (sourcelevel);
- }
- else
- {
- COPY_PROCENV (return_catch, old_return_catch);
- if (flags & FEVAL_NONINT)
- old_interactive = interactive;
- }
-
- if (flags & FEVAL_NONINT)
- interactive = 0;
-
- return_catch_flag++;
- sourcelevel++;
-
-#if defined (ARRAY_VARS)
- array_push (bash_source_a, (char *)filename);
- t = itos (executing_line_number ());
- array_push (bash_lineno_a, t);
- free (t);
- array_push (funcname_a, "source"); /* not exactly right */
-# if defined (DEBUGGER)
- /* Have to figure out a better way to do this when `source' is supplied
- arguments */
- if ((flags & FEVAL_NOPUSHARGS) == 0)
- {
- array_push (bash_argv_a, (char *)filename);
- tt[0] = '1'; tt[1] = '\0';
- array_push (bash_argc_a, tt);
- }
-# endif
-#endif
-
- /* set the flags to be passed to parse_and_execute */
- pflags = SEVAL_RESETLINE;
- pflags |= (flags & FEVAL_HISTORY) ? 0 : SEVAL_NOHIST;
-
- if (flags & FEVAL_BUILTIN)
- result = EXECUTION_SUCCESS;
-
- return_val = setjmp (return_catch);
-
- /* If `return' was seen outside of a function, but in the script, then
- force parse_and_execute () to clean up. */
- if (return_val)
- {
- parse_and_execute_cleanup ();
- result = return_catch_value;
- }
- else
- result = parse_and_execute (string, filename, pflags);
-
- if (flags & FEVAL_UNWINDPROT)
- run_unwind_frame ("_evalfile");
- else
- {
- if (flags & FEVAL_NONINT)
- interactive = old_interactive;
- return_catch_flag--;
- sourcelevel--;
- COPY_PROCENV (old_return_catch, return_catch);
- }
-
-#if defined (ARRAY_VARS)
- /* These two variables cannot be unset, and cannot be affected by the
- sourced file. */
- array_pop (bash_source_a);
- array_pop (bash_lineno_a);
-
- /* FUNCNAME can be unset, and so can potentially be changed by the
- sourced file. */
- GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
- if (nfv == funcname_v)
- array_pop (funcname_a);
-# if defined (DEBUGGER)
- if ((flags & FEVAL_NOPUSHARGS) == 0)
- {
- array_pop (bash_argc_a);
- array_pop (bash_argv_a);
- }
-# endif
-#endif
-
- return ((flags & FEVAL_BUILTIN) ? result : 1);
-}
-
-int
-maybe_execute_file (fname, force_noninteractive)
- const char *fname;
- int force_noninteractive;
-{
- char *filename;
- int result, flags;
-
- filename = bash_tilde_expand (fname, 0);
- flags = FEVAL_ENOENTOK;
- if (force_noninteractive)
- flags |= FEVAL_NONINT;
- result = _evalfile (filename, flags);
- free (filename);
- return result;
-}
-
-#if defined (HISTORY)
-int
-fc_execute_file (filename)
- const char *filename;
-{
- int flags;
-
- /* We want these commands to show up in the history list if
- remember_on_history is set. */
- flags = FEVAL_ENOENTOK|FEVAL_HISTORY|FEVAL_REGFILE;
- return (_evalfile (filename, flags));
-}
-#endif /* HISTORY */
-
-int
-source_file (filename, sflags)
- const char *filename;
- int sflags;
-{
- int flags, rval;
-
- flags = FEVAL_BUILTIN|FEVAL_UNWINDPROT|FEVAL_NONINT;
- if (sflags)
- flags |= FEVAL_NOPUSHARGS;
- /* POSIX shells exit if non-interactive and file error. */
- if (posixly_correct && !interactive_shell)
- flags |= FEVAL_LONGJMP;
- rval = _evalfile (filename, flags);
-
- run_return_trap ();
- return rval;
-}
diff --git a/builtins/evalstring.c~ b/builtins/evalstring.c~
deleted file mode 100644
index 610fa9ca..00000000
--- a/builtins/evalstring.c~
+++ /dev/null
@@ -1,352 +0,0 @@
-/* Evaluate a string as one or more shell commands.
-
- Copyright (C) 1996-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)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <signal.h>
-
-#include <errno.h>
-
-#include "filecntl.h"
-#include "../bashansi.h"
-
-#include "../shell.h"
-#include "../jobs.h"
-#include "../builtins.h"
-#include "../flags.h"
-#include "../input.h"
-#include "../execute_cmd.h"
-#include "../redir.h"
-#include "../trap.h"
-
-#if defined (HISTORY)
-# include "../bashhist.h"
-#endif
-
-#include "common.h"
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
-
-extern int indirection_level, startup_state, subshell_environment;
-extern int line_number;
-extern int last_command_exit_value;
-extern int running_trap;
-extern int loop_level;
-extern int posixly_correct;
-
-int parse_and_execute_level = 0;
-
-static int cat_file __P((REDIRECT *));
-
-/* How to force parse_and_execute () to clean up after itself. */
-void
-parse_and_execute_cleanup ()
-{
- if (running_trap)
- {
- run_trap_cleanup (running_trap - 1);
- unfreeze_jobs_list ();
- }
- run_unwind_frame ("parse_and_execute_top");
-}
-
-/* Parse and execute the commands in STRING. Returns whatever
- execute_command () returns. This frees STRING. FLAGS is a
- flags word; look in common.h for the possible values. Actions
- are:
- (flags & SEVAL_NONINT) -> interactive = 0;
- (flags & SEVAL_INTERACT) -> interactive = 1;
- (flags & SEVAL_NOHIST) -> call bash_history_disable ()
- (flags & SEVAL_NOFREE) -> don't free STRING when finished
- (flags & SEVAL_RESETLINE) -> reset line_number to 1
-*/
-
-int
-parse_and_execute (string, from_file, flags)
- char *string;
- const char *from_file;
- int flags;
-{
- int code, x, lreset;
- volatile int should_jump_to_top_level, last_result;
- char *orig_string;
- COMMAND *volatile command;
-
- orig_string = string;
- /* Unwind protect this invocation of parse_and_execute (). */
- begin_unwind_frame ("parse_and_execute_top");
- unwind_protect_int (parse_and_execute_level);
- unwind_protect_jmp_buf (top_level);
- unwind_protect_int (indirection_level);
- unwind_protect_int (line_number);
- unwind_protect_int (loop_level);
- if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
- unwind_protect_int (interactive);
-
- lreset = flags & SEVAL_RESETLINE;
-
-#if defined (HISTORY)
- unwind_protect_int (remember_on_history); /* can be used in scripts */
-# if defined (BANG_HISTORY)
- if (interactive_shell)
- {
- unwind_protect_int (history_expansion_inhibited);
- }
-# endif /* BANG_HISTORY */
-#endif /* HISTORY */
-
- if (interactive_shell)
- {
- x = get_current_prompt_level ();
- add_unwind_protect (set_current_prompt_level, x);
- }
-
- add_unwind_protect (pop_stream, (char *)NULL);
- if (orig_string && ((flags & SEVAL_NOFREE) == 0))
- add_unwind_protect (xfree, orig_string);
- end_unwind_frame ();
-
- parse_and_execute_level++;
-
- /* Reset the line number if the caller wants us to. If we don't reset the
- line number, we have to subtract one, because we will add one just
- before executing the next command (resetting the line number sets it to
- 0; the first line number is 1). */
- push_stream (lreset);
- if (lreset == 0)
- line_number--;
-
- indirection_level++;
- if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
- interactive = (flags & SEVAL_NONINT) ? 0 : 1;
-
-#if defined (HISTORY)
- if (flags & SEVAL_NOHIST)
- bash_history_disable ();
-#endif /* HISTORY */
-
- code = should_jump_to_top_level = 0;
- last_result = EXECUTION_SUCCESS;
-
- with_input_from_string (string, from_file);
- while (*(bash_input.location.string))
- {
- command = (COMMAND *)NULL;
-
- if (interrupt_state)
- {
- last_result = EXECUTION_FAILURE;
- break;
- }
-
- /* Provide a location for functions which `longjmp (top_level)' to
- jump to. This prevents errors in substitution from restarting
- the reader loop directly, for example. */
- code = setjmp (top_level);
-
- if (code)
- {
- should_jump_to_top_level = 0;
- switch (code)
- {
- case FORCE_EOF:
- case ERREXIT:
- case EXITPROG:
- if (command)
- run_unwind_frame ("pe_dispose");
- /* Remember to call longjmp (top_level) after the old
- value for it is restored. */
- should_jump_to_top_level = 1;
- goto out;
-
- case DISCARD:
- if (command)
- run_unwind_frame ("pe_dispose");
- last_result = last_command_exit_value = EXECUTION_FAILURE; /* XXX */
- if (subshell_environment)
- {
- should_jump_to_top_level = 1;
- goto out;
- }
- else
- {
-#if 0
- dispose_command (command); /* pe_dispose does this */
-#endif
- continue;
- }
-
- default:
- command_error ("parse_and_execute", CMDERR_BADJUMP, code, 0);
- break;
- }
- }
-
- if (parse_command () == 0)
- {
- if (interactive_shell == 0 && read_but_dont_execute)
- {
- last_result = EXECUTION_SUCCESS;
- dispose_command (global_command);
- global_command = (COMMAND *)NULL;
- }
- else if (command = global_command)
- {
- struct fd_bitmap *bitmap;
-
- bitmap = new_fd_bitmap (FD_BITMAP_SIZE);
- begin_unwind_frame ("pe_dispose");
- add_unwind_protect (dispose_fd_bitmap, bitmap);
- add_unwind_protect (dispose_command, command); /* XXX */
-
- global_command = (COMMAND *)NULL;
-
-#if defined (ONESHOT)
- /*
- * IF
- * we were invoked as `bash -c' (startup_state == 2) AND
- * parse_and_execute has not been called recursively AND
- * we're not running a trap AND
- * we have parsed the full command (string == '\0') AND
- * we have a simple command without redirections AND
- * the command is not being timed AND
- * the command's return status is not being inverted
- * THEN
- * tell the execution code that we don't need to fork
- */
- if (startup_state == 2 && parse_and_execute_level == 1 &&
- running_trap == 0 &&
- *bash_input.location.string == '\0' &&
- command->type == cm_simple &&
- !command->redirects && !command->value.Simple->redirects &&
- ((command->flags & CMD_TIME_PIPELINE) == 0) &&
- ((command->flags & CMD_INVERT_RETURN) == 0))
- {
- command->flags |= CMD_NO_FORK;
- command->value.Simple->flags |= CMD_NO_FORK;
- }
-#endif /* ONESHOT */
-
- /* See if this is a candidate for $( <file ). */
- if (startup_state == 2 &&
- (subshell_environment & SUBSHELL_COMSUB) &&
- *bash_input.location.string == '\0' &&
- command->type == cm_simple && !command->redirects &&
- (command->flags & CMD_TIME_PIPELINE) == 0 &&
- command->value.Simple->words == 0 &&
- command->value.Simple->redirects &&
- command->value.Simple->redirects->next == 0 &&
- command->value.Simple->redirects->instruction == r_input_direction)
- {
- int r;
- r = cat_file (command->value.Simple->redirects);
- last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
- }
- else
- last_result = execute_command_internal
- (command, 0, NO_PIPE, NO_PIPE, bitmap);
-
- dispose_command (command);
- dispose_fd_bitmap (bitmap);
- discard_unwind_frame ("pe_dispose");
- }
- }
- else
- {
- last_result = EXECUTION_FAILURE;
-
- /* Since we are shell compatible, syntax errors in a script
- abort the execution of the script. Right? */
- break;
- }
- }
-
- out:
-
- run_unwind_frame ("parse_and_execute_top");
-
- if (interrupt_state && parse_and_execute_level == 0)
- {
- /* An interrupt during non-interactive execution in an
- interactive shell (e.g. via $PROMPT_COMMAND) should
- not cause the shell to exit. */
- interactive = interactive_shell;
- throw_to_top_level ();
- }
-
- if (should_jump_to_top_level)
- jump_to_top_level (code);
-
- return (last_result);
-}
-
-/* Handle a $( < file ) command substitution. This expands the filename,
- returning errors as appropriate, then just cats the file to the standard
- output. */
-static int
-cat_file (r)
- REDIRECT *r;
-{
- char *fn;
- int fd, rval;
-
- if (r->instruction != r_input_direction)
- return -1;
-
- /* Get the filename. */
- if (posixly_correct && !interactive_shell)
- disallow_filename_globbing++;
- fn = redirection_expand (r->redirectee.filename);
- if (posixly_correct && !interactive_shell)
- disallow_filename_globbing--;
-
- if (fn == 0)
- {
- redirection_error (r, AMBIGUOUS_REDIRECT);
- return -1;
- }
-
- fd = open(fn, O_RDONLY);
- if (fd < 0)
- {
- file_error (fn);
- free (fn);
- return -1;
- }
-
- rval = zcatfd (fd, 1, fn);
-
- free (fn);
- close (fd);
-
- return (rval);
-}
diff --git a/builtins/fc.def~ b/builtins/fc.def~
deleted file mode 100644
index ebe36832..00000000
--- a/builtins/fc.def~
+++ /dev/null
@@ -1,631 +0,0 @@
-This file is fc.def, from which is created fc.c.
-It implements the builtin "fc" in Bash.
-
-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.
-
-$PRODUCES fc.c
-
-$BUILTIN fc
-$FUNCTION fc_builtin
-$DEPENDS_ON HISTORY
-$SHORT_DOC fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
-fc is used to list or edit and re-execute commands from the history list.
-FIRST and LAST can be numbers specifying the range, or FIRST can be a
-string, which means the most recent command beginning with that
-string.
-
- -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
- then vi.
-
- -l means list lines instead of editing.
- -n means no line numbers listed.
- -r means reverse the order of the lines (making it newest listed first).
-
-With the `fc -s [pat=rep ...] [command]' format, the command is
-re-executed after the substitution OLD=NEW is performed.
-
-A useful alias to use with this is r='fc -s', so that typing `r cc'
-runs the last command beginning with `cc' and typing `r' re-executes
-the last command.
-$END
-
-#include <config.h>
-
-#if defined (HISTORY)
-#ifndef _MINIX
-# include <sys/param.h>
-#endif
-#include "../bashtypes.h"
-#include "posixstat.h"
-#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <chartypes.h>
-
-#include "../bashansi.h"
-#include "../bashintl.h"
-#include <errno.h>
-
-#include "../shell.h"
-#include "../builtins.h"
-#include "../flags.h"
-#include "../bashhist.h"
-#include "maxpath.h"
-#include <readline/history.h>
-#include "bashgetopt.h"
-#include "common.h"
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-extern int echo_input_at_read;
-extern int current_command_line_count;
-extern int literal_history;
-extern int posixly_correct;
-
-extern int unlink __P((const char *));
-
-extern FILE *sh_mktmpfp __P((char *, int, char **));
-extern int delete_last_history __P((void));
-
-/* **************************************************************** */
-/* */
-/* The K*rn shell style fc command (Fix Command) */
-/* */
-/* **************************************************************** */
-
-/* fc builtin command (fix command) for Bash for those who
- like K*rn-style history better than csh-style.
-
- fc [-e ename] [-nlr] [first] [last]
-
- FIRST and LAST can be numbers specifying the range, or FIRST can be
- a string, which means the most recent command beginning with that
- string.
-
- -e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
- then the editor which corresponds to the current readline editing
- mode, then vi.
-
- -l means list lines instead of editing.
- -n means no line numbers listed.
- -r means reverse the order of the lines (making it newest listed first).
-
- fc -e - [pat=rep ...] [command]
- fc -s [pat=rep ...] [command]
-
- Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
-*/
-
-/* Data structure describing a list of global replacements to perform. */
-typedef struct repl {
- struct repl *next;
- char *pat;
- char *rep;
-} REPL;
-
-/* Accessors for HIST_ENTRY lists that are called HLIST. */
-#define histline(i) (hlist[(i)]->line)
-#define histdata(i) (hlist[(i)]->data)
-
-#define FREE_RLIST() \
- do { \
- for (rl = rlist; rl; ) { \
- REPL *r; \
- r = rl->next; \
- if (rl->pat) \
- free (rl->pat); \
- if (rl->rep) \
- free (rl->rep); \
- free (rl); \
- rl = r; \
- } \
- } while (0)
-
-static char *fc_dosubs __P((char *, REPL *));
-static char *fc_gethist __P((char *, HIST_ENTRY **));
-static int fc_gethnum __P((char *, HIST_ENTRY **));
-static int fc_number __P((WORD_LIST *));
-static void fc_replhist __P((char *));
-#ifdef INCLUDE_UNUSED
-static char *fc_readline __P((FILE *));
-static void fc_addhist __P((char *));
-#endif
-
-/* String to execute on a file that we want to edit. */
-#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
-#if defined (STRICT_POSIX)
-# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}"
-#else
-# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
-#endif
-
-int
-fc_builtin (list)
- WORD_LIST *list;
-{
- register int i;
- register char *sep;
- int numbering, reverse, listing, execute;
- int histbeg, histend, last_hist, retval, opt;
- FILE *stream;
- REPL *rlist, *rl;
- char *ename, *command, *newcom, *fcedit;
- HIST_ENTRY **hlist;
- char *fn;
-
- numbering = 1;
- reverse = listing = execute = 0;
- ename = (char *)NULL;
-
- /* Parse out the options and set which of the two forms we're in. */
- reset_internal_getopt ();
- lcurrent = list; /* XXX */
- while (fc_number (loptend = lcurrent) == 0 &&
- (opt = internal_getopt (list, ":e:lnrs")) != -1)
- {
- switch (opt)
- {
- case 'n':
- numbering = 0;
- break;
-
- case 'l':
- listing = 1;
- break;
-
- case 'r':
- reverse = 1;
- break;
-
- case 's':
- execute = 1;
- break;
-
- case 'e':
- ename = list_optarg;
- break;
-
- default:
- builtin_usage ();
- return (EX_USAGE);
- }
- }
-
- list = loptend;
-
- if (ename && (*ename == '-') && (ename[1] == '\0'))
- execute = 1;
-
- /* The "execute" form of the command (re-run, with possible string
- substitutions). */
- if (execute)
- {
- rlist = (REPL *)NULL;
- while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
- {
- *sep++ = '\0';
- rl = (REPL *)xmalloc (sizeof (REPL));
- rl->next = (REPL *)NULL;
- rl->pat = savestring (list->word->word);
- rl->rep = savestring (sep);
-
- if (rlist == NULL)
- rlist = rl;
- else
- {
- rl->next = rlist;
- rlist = rl;
- }
- list = list->next;
- }
-
- /* If we have a list of substitutions to do, then reverse it
- to get the replacements in the proper order. */
-
- rlist = REVERSE_LIST (rlist, REPL *);
-
- hlist = history_list ();
-
- /* If we still have something in list, it is a command spec.
- Otherwise, we use the most recent command in time. */
- command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
-
- if (command == NULL)
- {
- builtin_error (_("no command found"));
- if (rlist)
- FREE_RLIST ();
-
- return (EXECUTION_FAILURE);
- }
-
- if (rlist)
- {
- newcom = fc_dosubs (command, rlist);
- free (command);
- FREE_RLIST ();
- command = newcom;
- }
-
- fprintf (stderr, "%s\n", command);
- fc_replhist (command); /* replace `fc -s' with command */
- return (parse_and_execute (command, "fc", SEVAL_NOHIST));
- }
-
- /* This is the second form of the command (the list-or-edit-and-rerun
- form). */
- hlist = history_list ();
- if (hlist == 0)
- return (EXECUTION_SUCCESS);
- for (i = 0; hlist[i]; i++);
-
- /* With the Bash implementation of history, the current command line
- ("fc blah..." and so on) is already part of the history list by
- the time we get to this point. This just skips over that command
- and makes the last command that this deals with be the last command
- the user entered before the fc. We need to check whether the
- line was actually added (HISTIGNORE may have caused it to not be),
- so we check hist_last_line_added. */
-
- /* "When not listing, he fc command that caused the editing shall not be
- entered into the history list." */
- if (listing == 0 && hist_last_line_added)
- delete_last_history ();
-
- last_hist = i - 1 - hist_last_line_added;
-
- if (list)
- {
- histbeg = fc_gethnum (list->word->word, hlist);
- list = list->next;
-
- if (list)
- histend = fc_gethnum (list->word->word, hlist);
- else
- histend = listing ? last_hist : histbeg;
- }
- else
- {
- /* The default for listing is the last 16 history items. */
- if (listing)
- {
- histend = last_hist;
- histbeg = histend - 16 + 1; /* +1 because loop below uses >= */
- if (histbeg < 0)
- histbeg = 0;
- }
- else
- /* For editing, it is the last history command. */
- histbeg = histend = last_hist;
- }
-
- /* We print error messages for line specifications out of range. */
- if ((histbeg < 0) || (histend < 0))
- {
- sh_erange ((char *)NULL, _("history specification"));
- return (EXECUTION_FAILURE);
- }
-
- if (histend < histbeg)
- {
- i = histend;
- histend = histbeg;
- histbeg = i;
-
- reverse = 1;
- }
-
- if (listing)
- stream = stdout;
- else
- {
- numbering = 0;
- stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
- if (stream == 0)
- {
- builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
- FREE (fn);
- return (EXECUTION_FAILURE);
- }
- }
-
- for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
- {
- QUIT;
- if (numbering)
- fprintf (stream, "%d", i + history_base);
- if (listing)
- {
- if (posixly_correct)
- fputs ("\t", stream);
- else
- fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
- }
- fprintf (stream, "%s\n", histline (i));
- }
-
- if (listing)
- return (EXECUTION_SUCCESS);
-
- fclose (stream);
-
- /* Now edit the file of commands. */
- if (ename)
- {
- command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
- sprintf (command, "%s %s", ename, fn);
- }
- else
- {
- fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
- command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
- sprintf (command, "%s %s", fcedit, fn);
- }
- retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
- if (retval != EXECUTION_SUCCESS)
- {
- unlink (fn);
- free (fn);
- return (EXECUTION_FAILURE);
- }
-
- /* Make sure parse_and_execute doesn't turn this off, even though a
- call to parse_and_execute farther up the function call stack (e.g.,
- if this is called by vi_edit_and_execute_command) may have already
- called bash_history_disable. */
- remember_on_history = 1;
-
- /* Turn on the `v' flag while fc_execute_file runs so the commands
- will be echoed as they are read by the parser. */
- begin_unwind_frame ("fc builtin");
- add_unwind_protect ((Function *)xfree, fn);
- add_unwind_protect (unlink, fn);
- unwind_protect_int (echo_input_at_read);
- echo_input_at_read = 1;
-
- retval = fc_execute_file (fn);
-
- run_unwind_frame ("fc builtin");
-
- return (retval);
-}
-
-/* Return 1 if LIST->word->word is a legal number for fc's use. */
-static int
-fc_number (list)
- WORD_LIST *list;
-{
- char *s;
-
- if (list == 0)
- return 0;
- s = list->word->word;
- if (*s == '-')
- s++;
- return (legal_number (s, (intmax_t *)NULL));
-}
-
-/* Return an absolute index into HLIST which corresponds to COMMAND. If
- COMMAND is a number, then it was specified in relative terms. If it
- is a string, then it is the start of a command line present in HLIST. */
-static int
-fc_gethnum (command, hlist)
- char *command;
- HIST_ENTRY **hlist;
-{
- int sign = 1, n, clen;
- register int i, j;
- register char *s;
-
- /* Count history elements. */
- for (i = 0; hlist[i]; i++);
-
- /* With the Bash implementation of history, the current command line
- ("fc blah..." and so on) is already part of the history list by
- the time we get to this point. This just skips over that command
- and makes the last command that this deals with be the last command
- the user entered before the fc. We need to check whether the
- line was actually added (HISTIGNORE may have caused it to not be),
- so we check hist_last_line_added. */
- i -= 1 + hist_last_line_added;
-
- /* No specification defaults to most recent command. */
- if (command == NULL)
- return (i);
-
- /* Otherwise, there is a specification. It can be a number relative to
- the current position, or an absolute history number. */
- s = command;
-
- /* Handle possible leading minus sign. */
- if (s && (*s == '-'))
- {
- sign = -1;
- s++;
- }
-
- if (s && DIGIT(*s))
- {
- n = atoi (s);
- n *= sign;
-
- /* If the value is negative or zero, then it is an offset from
- the current history item. */
- if (n < 0)
- {
- n += i + 1;
- return (n < 0 ? 0 : n);
- }
- else if (n == 0)
- return (i);
- else
- {
- n -= history_base;
- return (i < n ? i : n);
- }
- }
-
- clen = strlen (command);
- for (j = i; j >= 0; j--)
- {
- if (STREQN (command, histline (j), clen))
- return (j);
- }
- return (-1);
-}
-
-/* Locate the most recent history line which begins with
- COMMAND in HLIST, and return a malloc()'ed copy of it. */
-static char *
-fc_gethist (command, hlist)
- char *command;
- HIST_ENTRY **hlist;
-{
- int i;
-
- if (hlist == 0)
- return ((char *)NULL);
-
- i = fc_gethnum (command, hlist);
-
- if (i >= 0)
- return (savestring (histline (i)));
- else
- return ((char *)NULL);
-}
-
-#ifdef INCLUDE_UNUSED
-/* Read the edited history lines from STREAM and return them
- one at a time. This can read unlimited length lines. The
- caller should free the storage. */
-static char *
-fc_readline (stream)
- FILE *stream;
-{
- register int c;
- int line_len = 0, lindex = 0;
- char *line = (char *)NULL;
-
- while ((c = getc (stream)) != EOF)
- {
- if ((lindex + 2) >= line_len)
- line = (char *)xrealloc (line, (line_len += 128));
-
- if (c == '\n')
- {
- line[lindex++] = '\n';
- line[lindex++] = '\0';
- return (line);
- }
- else
- line[lindex++] = c;
- }
-
- if (!lindex)
- {
- if (line)
- free (line);
-
- return ((char *)NULL);
- }
-
- if (lindex + 2 >= line_len)
- line = (char *)xrealloc (line, lindex + 3);
-
- line[lindex++] = '\n'; /* Finish with newline if none in file */
- line[lindex++] = '\0';
- return (line);
-}
-#endif
-
-/* Perform the SUBS on COMMAND.
- SUBS is a list of substitutions, and COMMAND is a simple string.
- Return a pointer to a malloc'ed string which contains the substituted
- command. */
-static char *
-fc_dosubs (command, subs)
- char *command;
- REPL *subs;
-{
- register char *new, *t;
- register REPL *r;
-
- for (new = savestring (command), r = subs; r; r = r->next)
- {
- t = strsub (new, r->pat, r->rep, 1);
- free (new);
- new = t;
- }
- return (new);
-}
-
-/* Use `command' to replace the last entry in the history list, which,
- by this time, is `fc blah...'. The intent is that the new command
- become the history entry, and that `fc' should never appear in the
- history list. This way you can do `r' to your heart's content. */
-static void
-fc_replhist (command)
- char *command;
-{
- int n;
-
- if (command == 0 || *command == '\0')
- return;
-
- n = strlen (command);
- if (command[n - 1] == '\n')
- command[n - 1] = '\0';
-
- if (command && *command)
- {
- delete_last_history ();
- maybe_add_history (command); /* Obeys HISTCONTROL setting. */
- }
-}
-
-#ifdef INCLUDE_UNUSED
-/* Add LINE to the history, after removing a single trailing newline. */
-static void
-fc_addhist (line)
- char *line;
-{
- register int n;
-
- if (line == 0 || *line == 0)
- return;
-
- n = strlen (line);
-
- if (line[n - 1] == '\n')
- line[n - 1] = '\0';
-
- if (line && *line)
- maybe_add_history (line); /* Obeys HISTCONTROL setting. */
-}
-#endif
-
-#endif /* HISTORY */
diff --git a/builtins/hash.def~ b/builtins/hash.def~
deleted file mode 100644
index b2959521..00000000
--- a/builtins/hash.def~
+++ /dev/null
@@ -1,271 +0,0 @@
-This file is hash.def, from which is created hash.c.
-It implements the builtin "hash" in Bash.
-
-Copyright (C) 1987-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.
-
-$PRODUCES hash.c
-
-$BUILTIN hash
-$FUNCTION hash_builtin
-$SHORT_DOC hash [-lr] [-p pathname] [-dt] [name ...]
-For each NAME, the full pathname of the command is determined and
-remembered. If the -p option is supplied, PATHNAME is used as the
-full pathname of NAME, and no path search is performed. The -r
-option causes the shell to forget all remembered locations. The -d
-option causes the shell to forget the remembered location of each NAME.
-If the -t option is supplied the full pathname to which each NAME
-corresponds is printed. If multiple NAME arguments are supplied with
--t, the NAME is printed before the hashed full pathname. The -l option
-causes output to be displayed in a format that may be reused as input.
-If no arguments are given, information about remembered commands is displayed.
-$END
-
-#include <config.h>
-
-#include <stdio.h>
-
-#include "../bashtypes.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <errno.h>
-
-#include "../bashansi.h"
-#include "../bashintl.h"
-
-#include "../shell.h"
-#include "../builtins.h"
-#include "../flags.h"
-#include "../findcmd.h"
-#include "../hashcmd.h"
-#include "common.h"
-#include "bashgetopt.h"
-
-extern int dot_found_in_search;
-extern char *this_command_name;
-
-static int add_hashed_command __P((char *, int));
-static int print_hash_info __P((BUCKET_CONTENTS *));
-static int print_portable_hash_info __P((BUCKET_CONTENTS *));
-static int print_hashed_commands __P((int));
-static int list_hashed_filename_targets __P((WORD_LIST *, int));
-
-/* Print statistics on the current state of hashed commands. If LIST is
- not empty, then rehash (or hash in the first place) the specified
- commands. */
-int
-hash_builtin (list)
- WORD_LIST *list;
-{
- int expunge_hash_table, list_targets, list_portably, delete, opt;
- char *w, *pathname;
-
- if (hashing_enabled == 0)
- {
- builtin_error (_("hashing disabled"));
- return (EXECUTION_FAILURE);
- }
-
- expunge_hash_table = list_targets = list_portably = delete = 0;
- pathname = (char *)NULL;
- reset_internal_getopt ();
- while ((opt = internal_getopt (list, "dlp:rt")) != -1)
- {
- switch (opt)
- {
- case 'd':
- delete = 1;
- break;
- case 'l':
- list_portably = 1;
- break;
- case 'p':
- pathname = list_optarg;
- break;
- case 'r':
- expunge_hash_table = 1;
- break;
- case 't':
- list_targets = 1;
- break;
- default:
- builtin_usage ();
- return (EX_USAGE);
- }
- }
- list = loptend;
-
- /* hash -t requires at least one argument. */
- if (list == 0 && list_targets)
- {
- sh_needarg ("-t");
- return (EXECUTION_FAILURE);
- }
-
- /* We want hash -r to be silent, but hash -- to print hashing info, so
- we test expunge_hash_table. */
- if (list == 0 && expunge_hash_table == 0)
- {
- if (print_hashed_commands (list_portably) == 0)
- fprintf (stderr, _("%s: hash table empty\n"), this_command_name);
-
- return (EXECUTION_SUCCESS);
- }
-
- if (expunge_hash_table)
- phash_flush ();
-
- /* If someone runs `hash -r -t xyz' he will be disappointed. */
- if (list_targets)
- return (list_hashed_filename_targets (list, list_portably));
-
-#if defined (RESTRICTED_SHELL)
- if (restricted && pathname && strchr (pathname, '/'))
- {
- sh_restricted (pathname);
- return (EXECUTION_FAILURE);
- }
-#endif
-
- for (opt = EXECUTION_SUCCESS; list; list = list->next)
- {
- /* Add, remove or rehash the specified commands. */
- w = list->word->word;
- if (pathname)
- {
- if (is_directory (pathname))
- {
-#ifdef EISDIR
- builtin_error ("%s: %s", pathname, strerror (EISDIR));
-#else
- builtin_error ("%s: is a directory", pathname);
-#endif
- opt = EXECUTION_FAILURE;
- }
- else
- phash_insert (w, pathname, 0, 0);
- }
- else if (absolute_program (w))
- continue;
- else if (delete)
- {
- if (phash_remove (w))
- {
- sh_notfound (w);
- opt = EXECUTION_FAILURE;
- }
- }
- else if (add_hashed_command (w, 0))
- opt = EXECUTION_FAILURE;
- }
-
- fflush (stdout);
- return (opt);
-}
-
-static int
-add_hashed_command (w, quiet)
- char *w;
- int quiet;
-{
- int rv;
- char *full_path;
-
- rv = 0;
- if (find_function (w) == 0 && find_shell_builtin (w) == 0)
- {
- full_path = find_user_command (w);
- if (full_path && executable_file (full_path))
- phash_insert (w, full_path, dot_found_in_search, 0);
- else
- {
- if (quiet == 0)
- sh_notfound (w);
- rv++;
- }
- FREE (full_path);
- }
- return (rv);
-}
-
-/* Print information about current hashed info. */
-static int
-print_hash_info (item)
- BUCKET_CONTENTS *item;
-{
- printf ("%4d\t%s\n", item->times_found, pathdata(item)->path);
- return 0;
-}
-
-static int
-print_portable_hash_info (item)
- BUCKET_CONTENTS *item;
-{
- printf ("builtin hash -p %s %s\n", pathdata(item)->path, item->key);
- return 0;
-}
-
-static int
-print_hashed_commands (fmt)
- int fmt;
-{
- if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
- return (0);
-
- if (fmt == 0)
- printf ("hits\tcommand\n");
- hash_walk (hashed_filenames, fmt ? print_portable_hash_info : print_hash_info);
- return (1);
-}
-
-static int
-list_hashed_filename_targets (list, fmt)
- WORD_LIST *list;
- int fmt;
-{
- int all_found, multiple;
- char *target;
- WORD_LIST *l;
-
- all_found = 1;
- multiple = list->next != 0;
-
- for (l = list; l; l = l->next)
- {
- target = phash_search (l->word->word);
- if (target == 0)
- {
- all_found = 0;
- sh_notfound (l->word->word);
- continue;
- }
- if (fmt)
- printf ("builtin hash -p %s %s\n", target, l->word->word);
- else
- {
- if (multiple)
- printf ("%s\t", l->word->word);
- printf ("%s\n", target);
- }
- }
-
- return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
-}
diff --git a/builtins/mkbuiltins.c~ b/builtins/mkbuiltins.c~
deleted file mode 100644
index 632e42e7..00000000
--- a/builtins/mkbuiltins.c~
+++ /dev/null
@@ -1,1566 +0,0 @@
-/* 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/printf.def~ b/builtins/printf.def~
deleted file mode 100644
index 67e978eb..00000000
--- a/builtins/printf.def~
+++ /dev/null
@@ -1,1008 +0,0 @@
-This file is printf.def, from which is created printf.c.
-It implements the builtin "printf" in Bash.
-
-Copyright (C) 1997-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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
-
-$PRODUCES printf.c
-
-$BUILTIN printf
-$FUNCTION printf_builtin
-$SHORT_DOC printf [-v var] format [arguments]
-printf formats and prints ARGUMENTS under control of the FORMAT. FORMAT
-is a character string which contains three types of objects: plain
-characters, which are simply copied to standard output, character escape
-sequences which are converted and copied to the standard output, and
-format specifications, each of which causes printing of the next successive
-argument. In addition to the standard printf(1) formats, %b means to
-expand backslash escape sequences in the corresponding argument, and %q
-means to quote the argument in a way that can be reused as shell input.
-If the -v option is supplied, the output is placed into the value of the
-shell variable VAR rather than being sent to the standard output.
-$END
-
-#include <config.h>
-
-#include "../bashtypes.h"
-
-#include <errno.h>
-#if defined (HAVE_LIMITS_H)
-# include <limits.h>
-#else
- /* Assume 32-bit ints. */
-# define INT_MAX 2147483647
-# define INT_MIN (-2147483647-1)
-#endif
-
-#include <stdio.h>
-#include <chartypes.h>
-
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-
-#include "../bashansi.h"
-#include "../bashintl.h"
-
-#include "../shell.h"
-#include "stdc.h"
-#include "bashgetopt.h"
-#include "common.h"
-
-#if !defined (PRIdMAX)
-# if HAVE_LONG_LONG
-# define PRIdMAX "lld"
-# else
-# define PRIdMAX "ld"
-# endif
-#endif
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-#define PC(c) \
- do { \
- char b[2]; \
- tw++; \
- b[0] = c; b[1] = '\0'; \
- if (vflag) \
- vbadd (b, 1); \
- else \
- putchar (c); \
- } while (0)
-
-#define PF(f, func) \
- do { \
- char *b = 0; \
- int nw; \
- if (have_fieldwidth && have_precision) \
- nw = asprintf(&b, f, fieldwidth, precision, func); \
- else if (have_fieldwidth) \
- nw = asprintf(&b, f, fieldwidth, func); \
- else if (have_precision) \
- nw = asprintf(&b, f, precision, func); \
- else \
- nw = asprintf(&b, f, func); \
- tw += nw; \
- if (b) \
- { \
- if (vflag) \
- (void)vbadd (b, nw); \
- else \
- (void)fputs (b, stdout); \
- if (ferror (stdout)) \
- { \
- sh_wrerror (); \
- clearerr (stdout); \
- return (EXECUTION_FAILURE); \
- } \
- free (b); \
- } \
- } while (0)
-
-/* We free the buffer used by mklong() if it's `too big'. */
-#define PRETURN(value) \
- do \
- { \
- if (vflag) \
- { \
- bind_variable (vname, vbuf, 0); \
- stupidly_hack_special_variables (vname); \
- } \
- if (conv_bufsize > 4096 ) \
- { \
- free (conv_buf); \
- conv_bufsize = 0; \
- conv_buf = 0; \
- } \
- if (vbsize > 4096) \
- { \
- free (vbuf); \
- vbsize = 0; \
- vbuf = 0; \
- } \
- fflush (stdout); \
- if (ferror (stdout)) \
- { \
- clearerr (stdout); \
- return (EXECUTION_FAILURE); \
- } \
- return (value); \
- } \
- while (0)
-
-#define SKIP1 "#'-+ 0"
-#define LENMODS "hjlLtz"
-
-static void printf_erange __P((char *));
-static int printstr __P((char *, char *, int, int, int));
-static int tescape __P((char *, char *, int *));
-static char *bexpand __P((char *, int, int *, int *));
-static char *vbadd __P((char *, int));
-static char *mklong __P((char *, char *, size_t));
-static int getchr __P((void));
-static char *getstr __P((void));
-static int getint __P((void));
-static intmax_t getintmax __P((void));
-static uintmax_t getuintmax __P((void));
-
-#if defined (HAVE_LONG_DOUBLE) && HAVE_DECL_STRTOLD && !defined(STRTOLD_BROKEN)
-typedef long double floatmax_t;
-# define FLOATMAX_CONV "L"
-# define strtofltmax strtold
-#else
-typedef double floatmax_t;
-# define FLOATMAX_CONV ""
-# define strtofltmax strtod
-#endif
-static floatmax_t getfloatmax __P((void));
-
-static int asciicode __P((void));
-
-static WORD_LIST *garglist;
-static int retval;
-static int conversion_error;
-
-/* printf -v var support */
-static int vflag = 0;
-static char *vbuf, *vname;
-static size_t vbsize;
-static int vblen;
-
-static intmax_t tw;
-
-static char *conv_buf;
-static size_t conv_bufsize;
-
-int
-printf_builtin (list)
- WORD_LIST *list;
-{
- int ch, fieldwidth, precision;
- int have_fieldwidth, have_precision;
- char convch, thisch, nextch, *format, *modstart, *fmt, *start;
-
- conversion_error = 0;
- retval = EXECUTION_SUCCESS;
-
- vflag = 0;
-
- reset_internal_getopt ();
- while ((ch = internal_getopt (list, "v:")) != -1)
- {
- switch (ch)
- {
- case 'v':
- if (legal_identifier (vname = list_optarg))
- {
- vflag = 1;
- vblen = 0;
- }
- else
- {
- sh_invalidid (vname);
- return (EX_USAGE);
- }
- break;
- default:
- builtin_usage ();
- return (EX_USAGE);
- }
- }
- list = loptend; /* skip over possible `--' */
-
- if (list == 0)
- {
- builtin_usage ();
- return (EX_USAGE);
- }
-
- if (list->word->word == 0 || list->word->word[0] == '\0')
- return (EXECUTION_SUCCESS);
-
- format = list->word->word;
- tw = 0;
-
- garglist = list->next;
-
- /* If the format string is empty after preprocessing, return immediately. */
- if (format == 0 || *format == 0)
- return (EXECUTION_SUCCESS);
-
- /* Basic algorithm is to scan the format string for conversion
- specifications -- once one is found, find out if the field
- width or precision is a '*'; if it is, gather up value. Note,
- format strings are reused as necessary to use up the provided
- arguments, arguments of zero/null string are provided to use
- up the format string. */
- do
- {
- tw = 0;
- /* find next format specification */
- for (fmt = format; *fmt; fmt++)
- {
- precision = fieldwidth = 0;
- have_fieldwidth = have_precision = 0;
-
- if (*fmt == '\\')
- {
- fmt++;
- /* A NULL third argument to tescape means to bypass the
- special processing for arguments to %b. */
- fmt += tescape (fmt, &nextch, (int *)NULL);
- PC (nextch);
- fmt--; /* for loop will increment it for us again */
- continue;
- }
-
- if (*fmt != '%')
- {
- PC (*fmt);
- continue;
- }
-
- /* ASSERT(*fmt == '%') */
- start = fmt++;
-
- if (*fmt == '%') /* %% prints a % */
- {
- PC ('%');
- continue;
- }
-
- /* found format specification, skip to field width */
- for (; *fmt && strchr(SKIP1, *fmt); ++fmt)
- ;
-
- /* Skip optional field width. */
- if (*fmt == '*')
- {
- fmt++;
- have_fieldwidth = 1;
- fieldwidth = getint ();
- }
- else
- while (DIGIT (*fmt))
- fmt++;
-
- /* Skip optional '.' and precision */
- if (*fmt == '.')
- {
- ++fmt;
- if (*fmt == '*')
- {
- fmt++;
- have_precision = 1;
- precision = getint ();
- }
- else
- {
- /* Negative precisions are allowed but treated as if the
- precision were missing; I would like to allow a leading
- `+' in the precision number as an extension, but lots
- of asprintf/fprintf implementations get this wrong. */
-#if 0
- if (*fmt == '-' || *fmt == '+')
-#else
- if (*fmt == '-')
-#endif
- fmt++;
- while (DIGIT (*fmt))
- fmt++;
- }
- }
-
- /* skip possible format modifiers */
- modstart = fmt;
- while (*fmt && strchr (LENMODS, *fmt))
- fmt++;
-
- if (*fmt == 0)
- {
- builtin_error (_("`%s': missing format character"), start);
- PRETURN (EXECUTION_FAILURE);
- }
-
- convch = *fmt;
- thisch = modstart[0];
- nextch = modstart[1];
- modstart[0] = convch;
- modstart[1] = '\0';
-
- switch(convch)
- {
- case 'c':
- {
- char p;
-
- p = getchr ();
- PF(start, p);
- break;
- }
-
- case 's':
- {
- char *p;
-
- p = getstr ();
- PF(start, p);
- break;
- }
-
- case 'n':
- {
- char *var;
-
- var = getstr ();
- if (var && *var)
- {
- if (legal_identifier (var))
- bind_var_to_int (var, tw);
- else
- {
- sh_invalidid (var);
- PRETURN (EXECUTION_FAILURE);
- }
- }
- break;
- }
-
- case 'b': /* expand escapes in argument */
- {
- char *p, *xp;
- int rlen, r;
-
- p = getstr ();
- ch = rlen = r = 0;
- xp = bexpand (p, strlen (p), &ch, &rlen);
-
- if (xp)
- {
- /* Have to use printstr because of possible NUL bytes
- in XP -- printf does not handle that well. */
- r = printstr (start, xp, rlen, fieldwidth, precision);
- if (r < 0)
- {
- sh_wrerror ();
- clearerr (stdout);
- retval = EXECUTION_FAILURE;
- }
- free (xp);
- }
-
- if (ch || r < 0)
- PRETURN (retval);
- break;
- }
-
- case 'q': /* print with shell quoting */
- {
- char *p, *xp;
- int r;
-
- r = 0;
- p = getstr ();
- if (ansic_shouldquote (p))
- xp = ansic_quote (p, 0, (int *)0);
- else
- xp = sh_backslash_quote (p);
- if (xp)
- {
- /* Use printstr to get fieldwidth and precision right. */
- r = printstr (start, xp, strlen (xp), fieldwidth, precision);
- if (r < 0)
- {
- sh_wrerror ();
- clearerr (stdout);
- }
- free (xp);
- }
-
- if (r < 0)
- PRETURN (EXECUTION_FAILURE);
- break;
- }
-
- case 'd':
- case 'i':
- {
- char *f;
- long p;
- intmax_t pp;
-
- p = pp = getintmax ();
- if (p != pp)
- {
- f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
- PF (f, pp);
- }
- else
- {
- /* Optimize the common case where the integer fits
- in "long". This also works around some long
- long and/or intmax_t library bugs in the common
- case, e.g. glibc 2.2 x86. */
- f = mklong (start, "l", 1);
- PF (f, p);
- }
- break;
- }
-
- case 'o':
- case 'u':
- case 'x':
- case 'X':
- {
- char *f;
- unsigned long p;
- uintmax_t pp;
-
- p = pp = getuintmax ();
- if (p != pp)
- {
- f = mklong (start, PRIdMAX, sizeof (PRIdMAX) - 2);
- PF (f, pp);
- }
- else
- {
- f = mklong (start, "l", 1);
- PF (f, p);
- }
- break;
- }
-
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
-#if defined (HAVE_PRINTF_A_FORMAT)
- case 'a':
- case 'A':
-#endif
- {
- char *f;
- floatmax_t p;
-
- p = getfloatmax ();
- f = mklong (start, FLOATMAX_CONV, sizeof(FLOATMAX_CONV) - 1);
- PF (f, p);
- break;
- }
-
- /* We don't output unrecognized format characters; we print an
- error message and return a failure exit status. */
- default:
- builtin_error (_("`%c': invalid format character"), convch);
- PRETURN (EXECUTION_FAILURE);
- }
-
- modstart[0] = thisch;
- modstart[1] = nextch;
- }
-
- if (ferror (stdout))
- {
- sh_wrerror ();
- clearerr (stdout);
- PRETURN (EXECUTION_FAILURE);
- }
- }
- while (garglist && garglist != list->next);
-
- if (conversion_error)
- retval = EXECUTION_FAILURE;
-
- PRETURN (retval);
-}
-
-static void
-printf_erange (s)
- char *s;
-{
- builtin_error ("warning: %s: %s", s, strerror(ERANGE));
-}
-
-/* We duplicate a lot of what printf(3) does here. */
-static int
-printstr (fmt, string, len, fieldwidth, precision)
- char *fmt; /* format */
- char *string; /* expanded string argument */
- int len; /* length of expanded string */
- int fieldwidth; /* argument for width of `*' */
- int precision; /* argument for precision of `*' */
-{
-#if 0
- char *s;
-#endif
- int padlen, nc, ljust, i;
- int fw, pr; /* fieldwidth and precision */
-
-#if 0
- if (string == 0 || *string == '\0')
-#else
- if (string == 0 || len == 0)
-#endif
- return;
-
-#if 0
- s = fmt;
-#endif
- if (*fmt == '%')
- fmt++;
-
- ljust = fw = 0;
- pr = -1;
-
- /* skip flags */
- while (strchr (SKIP1, *fmt))
- {
- if (*fmt == '-')
- ljust = 1;
- fmt++;
- }
-
- /* get fieldwidth, if present */
- if (*fmt == '*')
- {
- fmt++;
- fw = fieldwidth;
- if (fw < 0)
- {
- fw = -fw;
- ljust = 1;
- }
- }
- else if (DIGIT (*fmt))
- {
- fw = *fmt++ - '0';
- while (DIGIT (*fmt))
- fw = (fw * 10) + (*fmt++ - '0');
- }
-
- /* get precision, if present */
- if (*fmt == '.')
- {
- fmt++;
- if (*fmt == '*')
- {
- fmt++;
- pr = precision;
- }
- else if (DIGIT (*fmt))
- {
- pr = *fmt++ - '0';
- while (DIGIT (*fmt))
- pr = (pr * 10) + (*fmt++ - '0');
- }
- }
-
-#if 0
- /* If we remove this, get rid of `s'. */
- if (*fmt != 'b' && *fmt != 'q')
- {
- internal_error ("format parsing problem: %s", s);
- fw = pr = 0;
- }
-#endif
-
- /* chars from string to print */
- nc = (pr >= 0 && pr <= len) ? pr : len;
-
- padlen = fw - nc;
- if (padlen < 0)
- padlen = 0;
- if (ljust)
- padlen = -padlen;
-
- /* leading pad characters */
- for (; padlen > 0; padlen--)
- PC (' ');
-
- /* output NC characters from STRING */
- for (i = 0; i < nc; i++)
- PC (string[i]);
-
- /* output any necessary trailing padding */
- for (; padlen < 0; padlen++)
- PC (' ');
-
- return (ferror (stdout) ? -1 : 0);
-}
-
-/* Convert STRING by expanding the escape sequences specified by the
- POSIX standard for printf's `%b' format string. If SAWC is non-null,
- perform the processing appropriate for %b arguments. In particular,
- recognize `\c' and use that as a string terminator. If we see \c, set
- *SAWC to 1 before returning. LEN is the length of STRING. */
-
-/* Translate a single backslash-escape sequence starting at ESTART (the
- character after the backslash) and return the number of characters
- consumed by the sequence. CP is the place to return the translated
- value. *SAWC is set to 1 if the escape sequence was \c, since that means
- to short-circuit the rest of the processing. If SAWC is null, we don't
- do the \c short-circuiting, and \c is treated as an unrecognized escape
- sequence; we also bypass the other processing specific to %b arguments. */
-static int
-tescape (estart, cp, sawc)
- char *estart;
- char *cp;
- int *sawc;
-{
- register char *p;
- int temp, c, evalue;
-
- p = estart;
-
- switch (c = *p++)
- {
-#if defined (__STDC__)
- case 'a': *cp = '\a'; break;
-#else
- case 'a': *cp = '\007'; break;
-#endif
-
- case 'b': *cp = '\b'; break;
-
- case 'e':
- case 'E': *cp = '\033'; break; /* ESC -- non-ANSI */
-
- case 'f': *cp = '\f'; break;
-
- case 'n': *cp = '\n'; break;
-
- case 'r': *cp = '\r'; break;
-
- case 't': *cp = '\t'; break;
-
- case 'v': *cp = '\v'; break;
-
- /* The octal escape sequences are `\0' followed by up to three octal
- digits (if SAWC), or `\' followed by up to three octal digits (if
- !SAWC). As an extension, we allow the latter form even if SAWC. */
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- evalue = OCTVALUE (c);
- for (temp = 2 + (!evalue && !!sawc); ISOCTAL (*p) && temp--; p++)
- evalue = (evalue * 8) + OCTVALUE (*p);
- *cp = evalue & 0xFF;
- break;
-
- /* And, as another extension, we allow \xNNN, where each N is a
- hex digit. */
- case 'x':
-#if 0
- for (evalue = 0; ISXDIGIT ((unsigned char)*p); p++)
-#else
- for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
-#endif
- evalue = (evalue * 16) + HEXVALUE (*p);
- if (p == estart + 1)
- {
- builtin_error (_("missing hex digit for \\x"));
- *cp = '\\';
- return 0;
- }
- *cp = evalue & 0xFF;
- break;
-
- case '\\': /* \\ -> \ */
- *cp = c;
- break;
-
- /* SAWC == 0 means that \', \", and \? are recognized as escape
- sequences, though the only processing performed is backslash
- removal. */
- case '\'': case '"': case '?':
- if (!sawc)
- *cp = c;
- else
- {
- *cp = '\\';
- return 0;
- }
- break;
-
- case 'c':
- if (sawc)
- {
- *sawc = 1;
- break;
- }
- /* other backslash escapes are passed through unaltered */
- default:
- *cp = '\\';
- return 0;
- }
- return (p - estart);
-}
-
-static char *
-bexpand (string, len, sawc, lenp)
- char *string;
- int len, *sawc, *lenp;
-{
- int temp;
- char *ret, *r, *s, c;
-
-#if 0
- if (string == 0 || *string == '\0')
-#else
- if (string == 0 || len == 0)
-#endif
- {
- if (sawc)
- *sawc = 0;
- if (lenp)
- *lenp = 0;
- return ((char *)NULL);
- }
-
- ret = (char *)xmalloc (len + 1);
- for (r = ret, s = string; s && *s; )
- {
- c = *s++;
- if (c != '\\' || *s == '\0')
- {
- *r++ = c;
- continue;
- }
- temp = 0;
- s += tescape (s, &c, &temp);
- if (temp)
- {
- if (sawc)
- *sawc = 1;
- break;
- }
-
- *r++ = c;
- }
-
- *r = '\0';
- if (lenp)
- *lenp = r - ret;
- return ret;
-}
-
-static char *
-vbadd (buf, blen)
- char *buf;
- int blen;
-{
- size_t nlen;
-
- nlen = vblen + blen + 1;
- if (nlen >= vbsize)
- {
- vbsize = ((nlen + 63) >> 6) << 6;
- vbuf = (char *)xrealloc (vbuf, vbsize);
- }
-
- if (blen == 1)
- vbuf[vblen++] = buf[0];
- else
- {
- FASTCOPY (buf, vbuf + vblen, blen);
- vblen += blen;
- }
- vbuf[vblen] = '\0';
-
-#ifdef DEBUG
- if (strlen (vbuf) != vblen)
- internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, strlen (vbuf));
-#endif
-
- return vbuf;
-}
-
-static char *
-mklong (str, modifiers, mlen)
- char *str;
- char *modifiers;
- size_t mlen;
-{
- size_t len, slen;
-
- slen = strlen (str);
- len = slen + mlen + 1;
-
- if (len > conv_bufsize)
- {
- conv_bufsize = (((len + 1023) >> 10) << 10);
- conv_buf = (char *)xrealloc (conv_buf, conv_bufsize);
- }
-
- FASTCOPY (str, conv_buf, slen - 1);
- FASTCOPY (modifiers, conv_buf + slen - 1, mlen);
-
- conv_buf[len - 2] = str[slen - 1];
- conv_buf[len - 1] = '\0';
- return (conv_buf);
-}
-
-static int
-getchr ()
-{
- int ret;
-
- if (garglist == 0)
- return ('\0');
-
- ret = (int)garglist->word->word[0];
- garglist = garglist->next;
- return ret;
-}
-
-static char *
-getstr ()
-{
- char *ret;
-
- if (garglist == 0)
- return ("");
-
- ret = garglist->word->word;
- garglist = garglist->next;
- return ret;
-}
-
-static int
-getint ()
-{
- intmax_t ret;
-
- ret = getintmax ();
-
- if (ret > INT_MAX)
- {
- printf_erange (garglist->word->word);
- ret = INT_MAX;
- }
- else if (ret < INT_MIN)
- {
- printf_erange (garglist->word->word);
- ret = INT_MIN;
- }
-
- return ((int)ret);
-}
-
-static intmax_t
-getintmax ()
-{
- intmax_t ret;
- char *ep;
-
- if (garglist == 0)
- return (0);
-
- if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
- return asciicode ();
-
- errno = 0;
- ret = strtoimax (garglist->word->word, &ep, 0);
-
- if (*ep)
- {
- sh_invalidnum (garglist->word->word);
- /* POSIX.2 says ``...a diagnostic message shall be written to standard
- error, and the utility shall not exit with a zero exit status, but
- shall continue processing any remaining operands and shall write the
- value accumulated at the time the error was detected to standard
- output.'' Yecch. */
- ret = 0;
- conversion_error = 1;
- }
- else if (errno == ERANGE)
- printf_erange (garglist->word->word);
-
- garglist = garglist->next;
- return (ret);
-}
-
-static uintmax_t
-getuintmax ()
-{
- uintmax_t ret;
- char *ep;
-
- if (garglist == 0)
- return (0);
-
- if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
- return asciicode ();
-
- errno = 0;
- ret = strtoumax (garglist->word->word, &ep, 0);
-
- if (*ep)
- {
- sh_invalidnum (garglist->word->word);
- /* Same POSIX.2 conversion error requirements as getintmax(). */
- ret = 0;
- conversion_error = 1;
- }
- else if (errno == ERANGE)
- printf_erange (garglist->word->word);
-
- garglist = garglist->next;
- return (ret);
-}
-
-static floatmax_t
-getfloatmax ()
-{
- floatmax_t ret;
- char *ep;
-
- if (garglist == 0)
- return (0);
-
- if (garglist->word->word[0] == '\'' || garglist->word->word[0] == '"')
- return asciicode ();
-
- errno = 0;
- ret = strtofltmax (garglist->word->word, &ep);
-
- if (*ep)
- {
- sh_invalidnum (garglist->word->word);
- /* Same thing about POSIX.2 conversion error requirements. */
- ret = 0;
- conversion_error = 1;
- }
- else if (errno == ERANGE)
- printf_erange (garglist->word->word);
-
- garglist = garglist->next;
- return (ret);
-}
-
-/* NO check is needed for garglist here. */
-static int
-asciicode ()
-{
- register int ch;
-
- ch = garglist->word->word[1];
- garglist = garglist->next;
- return (ch);
-}
diff --git a/builtins/read.def~ b/builtins/read.def~
deleted file mode 100644
index 29ddf8ae..00000000
--- a/builtins/read.def~
+++ /dev/null
@@ -1,779 +0,0 @@
-This file is read.def, from which is created read.c.
-It implements the builtin "read" in Bash.
-
-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.
-
-$PRODUCES read.c
-
-$BUILTIN read
-$FUNCTION read_builtin
-$SHORT_DOC read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...]
-One line is read from the standard input, or from file descriptor FD if the
--u option is supplied, and the first word is assigned to the first NAME,
-the second word to the second NAME, and so on, with leftover words assigned
-to the last NAME. Only the characters found in $IFS are recognized as word
-delimiters. If no NAMEs are supplied, the line read is stored in the REPLY
-variable. If the -r option is given, this signifies `raw' input, and
-backslash escaping is disabled. The -d option causes read to continue
-until the first character of DELIM is read, rather than newline. If the -p
-option is supplied, the string PROMPT is output without a trailing newline
-before attempting to read. If -a is supplied, the words read are assigned
-to sequential indices of ARRAY, starting at zero. If -e is supplied and
-the shell is interactive, readline is used to obtain the line. If -n is
-supplied with a non-zero NCHARS argument, read returns after NCHARS
-characters have been read. The -s option causes input coming from a
-terminal to not be echoed.
-
-The -t option causes read to time out and return failure if a complete line
-of input is not read within TIMEOUT seconds. If the TMOUT variable is set,
-its value is the default timeout. The return code is zero, unless end-of-file
-is encountered, read times out, or an invalid file descriptor is supplied as
-the argument to -u.
-$END
-
-#include <config.h>
-
-#include "bashtypes.h"
-#include "posixstat.h"
-
-#include <stdio.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <signal.h>
-#include <errno.h>
-
-#ifdef __CYGWIN__
-# include <fcntl.h>
-# include <io.h>
-#endif
-
-#include "../bashintl.h"
-
-#include "../shell.h"
-#include "common.h"
-#include "bashgetopt.h"
-
-#include <shtty.h>
-
-#if defined (READLINE)
-#include "../bashline.h"
-#include <readline/readline.h>
-#endif
-
-#if defined (BUFFERED_INPUT)
-# include "input.h"
-#endif
-
-#if !defined(errno)
-extern int errno;
-#endif
-
-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 *));
-#endif
-static SHELL_VAR *bind_read_variable __P((char *, char *));
-
-static sighandler sigalrm __P((int));
-static void reset_alarm __P((void));
-
-static procenv_t alrmbuf;
-static SigHandler *old_alrm;
-static unsigned char delim;
-
-static sighandler
-sigalrm (s)
- int s;
-{
- longjmp (alrmbuf, 1);
-}
-
-static void
-reset_alarm ()
-{
- set_signal_handler (SIGALRM, old_alrm);
- alarm (0);
-}
-
-/* Read the value of the shell variables whose names follow.
- The reading is done from the current input stream, whatever
- that may be. Successive words of the input line are assigned
- to the variables mentioned in LIST. The last variable in LIST
- gets the remainder of the words on the line. If no variables
- are mentioned in LIST, then the default variable is $REPLY. */
-int
-read_builtin (list)
- WORD_LIST *list;
-{
- register char *varname;
- int size, i, nr, pass_next, saw_escape, eof, opt, retval, code;
- int input_is_tty, input_is_pipe, unbuffered_read;
- int raw, edit, nchars, silent, have_timeout, fd;
- unsigned int tmout;
- intmax_t intval;
- char c;
- char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
- char *e, *t, *t1;
- struct stat tsb;
- SHELL_VAR *var;
-#if defined (ARRAY_VARS)
- WORD_LIST *alist;
-#endif
-#if defined (READLINE)
- char *rlbuf;
- int rlind;
-#endif
-
- USE_VAR(size);
- USE_VAR(i);
- USE_VAR(pass_next);
- USE_VAR(saw_escape);
- USE_VAR(input_is_pipe);
-/* USE_VAR(raw); */
- USE_VAR(edit);
- USE_VAR(tmout);
- USE_VAR(nchars);
- USE_VAR(silent);
- USE_VAR(ifs_chars);
- USE_VAR(prompt);
- USE_VAR(arrayname);
-#if defined (READLINE)
- USE_VAR(rlbuf);
- USE_VAR(rlind);
-#endif
- USE_VAR(list);
-
- i = 0; /* Index into the string that we are reading. */
- raw = edit = 0; /* Not reading raw input by default. */
- silent = 0;
- arrayname = prompt = (char *)NULL;
- fd = 0; /* file descriptor to read from */
-
-#if defined (READLINE)
- rlbuf = (char *)0;
- rlind = 0;
-#endif
-
- tmout = 0; /* no timeout */
- nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0;
- delim = '\n'; /* read until newline */
-
- reset_internal_getopt ();
- while ((opt = internal_getopt (list, "ersa:d:n:p:t:u:")) != -1)
- {
- switch (opt)
- {
- case 'r':
- raw = 1;
- break;
- case 'p':
- prompt = list_optarg;
- break;
- case 's':
- silent = 1;
- break;
- case 'e':
-#if defined (READLINE)
- edit = 1;
-#endif
- break;
-#if defined (ARRAY_VARS)
- case 'a':
- arrayname = list_optarg;
- break;
-#endif
- case 't':
- code = legal_number (list_optarg, &intval);
- if (code == 0 || intval < 0 || intval != (unsigned int)intval)
- {
- builtin_error (_("%s: invalid timeout specification"), list_optarg);
- return (EXECUTION_FAILURE);
- }
- else
- {
- have_timeout = 1;
- tmout = intval;
- }
- break;
- case 'n':
- code = legal_number (list_optarg, &intval);
- if (code == 0 || intval < 0 || intval != (int)intval)
- {
- sh_invalidnum (list_optarg);
- return (EXECUTION_FAILURE);
- }
- else
- nchars = intval;
- break;
- case 'u':
- code = legal_number (list_optarg, &intval);
- if (code == 0 || intval < 0 || intval != (int)intval)
- {
- builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
- return (EXECUTION_FAILURE);
- }
- else
- fd = intval;
- if (sh_validfd (fd) == 0)
- {
- builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
- return (EXECUTION_FAILURE);
- }
- break;
- case 'd':
- delim = *list_optarg;
- break;
- default:
- builtin_usage ();
- return (EX_USAGE);
- }
- }
- list = loptend;
-
- /* `read -t 0 var' returns failure immediately. XXX - should it test
- whether input is available with select/FIONREAD, and fail if those
- are unavailable? */
- if (have_timeout && tmout == 0)
- return (EXECUTION_FAILURE);
-
- /* IF IFS is unset, we use the default of " \t\n". */
- ifs_chars = getifs ();
- if (ifs_chars == 0) /* XXX - shouldn't happen */
- ifs_chars = "";
-
- input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
-
- /* $TMOUT, if set, is the default timeout for read. */
- if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
- {
- code = legal_number (e, &intval);
- if (code == 0 || intval < 0 || intval != (unsigned int)intval)
- tmout = 0;
- else
- tmout = intval;
- }
-
- begin_unwind_frame ("read_builtin");
-
-#if defined (BUFFERED_INPUT)
- if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
- sync_buffered_stream (default_buffered_input);
-#endif
-
- input_is_tty = isatty (fd);
- if (input_is_tty == 0)
-#ifndef __CYGWIN__
- input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
-#else
- input_is_pipe = 1;
-#endif
-
- /* If the -p, -e or -s flags were given, but input is not coming from the
- terminal, turn them off. */
- if ((prompt || edit || silent) && input_is_tty == 0)
- {
- prompt = (char *)NULL;
- edit = silent = 0;
- }
-
-#if defined (READLINE)
- if (edit)
- add_unwind_protect (xfree, rlbuf);
-#endif
-
- if (prompt && edit == 0)
- {
- fprintf (stderr, "%s", prompt);
- fflush (stderr);
- }
-
- pass_next = 0; /* Non-zero signifies last char was backslash. */
- saw_escape = 0; /* Non-zero signifies that we saw an escape char */
-
- if (tmout > 0)
- {
- /* Turn off the timeout if stdin is a regular file (e.g. from
- input redirection). */
- if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
- tmout = 0;
- }
-
- if (tmout > 0)
- {
- code = setjmp (alrmbuf);
- if (code)
- {
- run_unwind_frame ("read_builtin");
- return (EXECUTION_FAILURE);
- }
- 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);
- }
-
- /* If we've been asked to read only NCHARS chars, or we're using some
- character other than newline to terminate the line, do the right
- thing to readline or the tty. */
- if (nchars > 0 || delim != '\n')
- {
-#if defined (READLINE)
- if (edit)
- {
- if (nchars > 0)
- {
- unwind_protect_int (rl_num_chars_to_read);
- rl_num_chars_to_read = nchars;
- }
- if (delim != '\n')
- {
- set_eol_delim (delim);
- add_unwind_protect (reset_eol_delim, (char *)NULL);
- }
- }
- else
-#endif
- if (input_is_tty)
- {
- ttsave ();
- if (silent)
- ttcbreak ();
- else
- ttonechar ();
- add_unwind_protect ((Function *)ttrestore, (char *)NULL);
- }
- }
- else if (silent) /* turn off echo but leave term in canonical mode */
- {
- ttsave ();
- ttnoecho ();
- add_unwind_protect ((Function *)ttrestore, (char *)NULL);
- }
-
- /* This *must* be the top unwind-protect on the stack, so the manipulation
- of the unwind-protect stack after the realloc() works right. */
- add_unwind_protect (xfree, input_string);
- interrupt_immediately++;
-
- unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe;
-
-#if defined (__CYGWIN__) && defined (O_TEXT)
- setmode (0, O_TEXT);
-#endif
-
- for (eof = retval = 0;;)
- {
-#if defined (READLINE)
- if (edit)
- {
- if (rlbuf && rlbuf[rlind] == '\0')
- {
- xfree (rlbuf);
- rlbuf = (char *)0;
- }
- if (rlbuf == 0)
- {
- rlbuf = edit_line (prompt ? prompt : "");
- rlind = 0;
- }
- if (rlbuf == 0)
- {
- eof = 1;
- break;
- }
- c = rlbuf[rlind++];
- }
- else
- {
-#endif
-
- if (unbuffered_read)
- retval = zread (fd, &c, 1);
- else
- retval = zreadc (fd, &c);
-
- if (retval <= 0)
- {
- eof = 1;
- break;
- }
-
-#if defined (READLINE)
- }
-#endif
-
- if (i + 2 >= size)
- {
- input_string = (char *)xrealloc (input_string, size += 128);
- remove_unwind_protect ();
- add_unwind_protect (xfree, input_string);
- }
-
- /* If the next character is to be accepted verbatim, a backslash
- newline pair still disappears from the input. */
- if (pass_next)
- {
- pass_next = 0;
- if (c == '\n')
- i--; /* back up over the CTLESC */
- else
- goto add_char;
- continue;
- }
-
- if (c == '\\' && raw == 0)
- {
- pass_next++;
- saw_escape++;
- input_string[i++] = CTLESC;
- continue;
- }
-
- if ((unsigned char)c == delim)
- break;
-
- if (c == CTLESC || c == CTLNUL)
- {
- saw_escape++;
- input_string[i++] = CTLESC;
- }
-
-add_char:
- input_string[i++] = c;
- nr++;
-
- if (nchars > 0 && nr >= nchars)
- break;
- }
- input_string[i] = '\0';
-
-#if 1
- if (retval < 0)
- {
- builtin_error (_("read error: %d: %s"), fd, strerror (errno));
- run_unwind_frame ("read_builtin");
- return (EXECUTION_FAILURE);
- }
-#endif
-
- if (tmout > 0)
- reset_alarm ();
-
- if (nchars > 0 || delim != '\n')
- {
-#if defined (READLINE)
- if (edit)
- {
- if (nchars > 0)
- rl_num_chars_to_read = 0;
- if (delim != '\n')
- reset_eol_delim ((char *)NULL);
- }
- else
-#endif
- if (input_is_tty)
- ttrestore ();
- }
- else if (silent)
- ttrestore ();
-
- if (unbuffered_read == 0)
- zsyncfd (fd);
-
- interrupt_immediately--;
- discard_unwind_frame ("read_builtin");
-
- retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
-
-#if defined (ARRAY_VARS)
- /* If -a was given, take the string read, break it into a list of words,
- an assign them to `arrayname' in turn. */
- if (arrayname)
- {
- if (legal_identifier (arrayname) == 0)
- {
- sh_invalidid (arrayname);
- xfree (input_string);
- return (EXECUTION_FAILURE);
- }
-
- var = find_or_make_array_variable (arrayname, 1);
- if (var == 0)
- {
- xfree (input_string);
- return EXECUTION_FAILURE; /* readonly or noassign */
- }
- array_flush (array_cell (var));
-
- alist = list_string (input_string, ifs_chars, 0);
- if (alist)
- {
- word_list_remove_quoted_nulls (alist);
- assign_array_var_from_word_list (var, alist, 0);
- dispose_words (alist);
- }
- xfree (input_string);
- return (retval);
- }
-#endif /* ARRAY_VARS */
-
- /* If there are no variables, save the text of the line read to the
- variable $REPLY. ksh93 strips leading and trailing IFS whitespace,
- so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
- same way, but I believe that the difference in behaviors is useful
- enough to not do it. Without the bash behavior, there is no way
- to read a line completely without interpretation or modification
- unless you mess with $IFS (e.g., setting it to the empty string).
- If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
- if (list == 0)
- {
-#if 0
- orig_input_string = input_string;
- for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
- ;
- input_string = t;
- input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
-#endif
-
- if (saw_escape)
- {
- t = dequote_string (input_string);
- var = bind_variable ("REPLY", t, 0);
- free (t);
- }
- else
- var = bind_variable ("REPLY", input_string, 0);
- VUNSETATTR (var, att_invisible);
-
- free (input_string);
- return (retval);
- }
-
- /* This code implements the Posix.2 spec for splitting the words
- read and assigning them to variables. */
- orig_input_string = input_string;
-
- /* Remove IFS white space at the beginning of the input string. If
- $IFS is null, no field splitting is performed. */
- for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
- ;
- input_string = t;
-
- for (; list->next; list = list->next)
- {
- varname = list->word->word;
-#if defined (ARRAY_VARS)
- if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
-#else
- if (legal_identifier (varname) == 0)
-#endif
- {
- sh_invalidid (varname);
- xfree (orig_input_string);
- return (EXECUTION_FAILURE);
- }
-
- /* If there are more variables than words read from the input,
- the remaining variables are set to the empty string. */
- if (*input_string)
- {
- /* This call updates INPUT_STRING. */
- t = get_word_from_string (&input_string, ifs_chars, &e);
- if (t)
- *e = '\0';
- /* Don't bother to remove the CTLESC unless we added one
- somewhere while reading the string. */
- if (t && saw_escape)
- {
- t1 = dequote_string (t);
- var = bind_read_variable (varname, t1);
- xfree (t1);
- }
- else
- var = bind_read_variable (varname, t);
- }
- else
- {
- t = (char *)0;
- var = bind_read_variable (varname, "");
- }
-
- FREE (t);
- if (var == 0)
- {
- xfree (orig_input_string);
- return (EXECUTION_FAILURE);
- }
-
- stupidly_hack_special_variables (varname);
- VUNSETATTR (var, att_invisible);
- }
-
- /* Now assign the rest of the line to the last variable argument. */
-#if defined (ARRAY_VARS)
- if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
-#else
- if (legal_identifier (list->word->word) == 0)
-#endif
- {
- sh_invalidid (list->word->word);
- xfree (orig_input_string);
- return (EXECUTION_FAILURE);
- }
-
-#if 0
- /* This has to be done this way rather than using string_list
- and list_string because Posix.2 says that the last variable gets the
- remaining words and their intervening separators. */
- input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
-#else
- /* Check whether or not the number of fields is exactly the same as the
- number of variables. */
- if (*input_string)
- {
- t1 = input_string;
- t = get_word_from_string (&input_string, ifs_chars, &e);
- if (*input_string == 0)
- input_string = t;
- else
- input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
- }
-#endif
-
- if (saw_escape)
- {
- t = dequote_string (input_string);
- var = bind_read_variable (list->word->word, t);
- xfree (t);
- }
- else
- var = bind_read_variable (list->word->word, input_string);
- stupidly_hack_special_variables (list->word->word);
- if (var)
- VUNSETATTR (var, att_invisible);
- xfree (orig_input_string);
-
- return (retval);
-}
-
-static SHELL_VAR *
-bind_read_variable (name, value)
- char *name, *value;
-{
-#if defined (ARRAY_VARS)
- if (valid_array_reference (name) == 0)
- return (bind_variable (name, value, 0));
- else
- return (assign_array_element (name, value, 0));
-#else /* !ARRAY_VARS */
- return bind_variable (name, value, 0);
-#endif /* !ARRAY_VARS */
-}
-
-#if defined (READLINE)
-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)
- char *p;
-{
- char *ret;
- int len;
-
- 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 = 0;
- if (ret == 0)
- return ret;
- len = strlen (ret);
- ret = (char *)xrealloc (ret, len + 2);
- ret[len++] = delim;
- ret[len] = '\0';
- return ret;
-}
-
-static int old_delim_ctype;
-static rl_command_func_t *old_delim_func;
-static int old_newline_ctype;
-static rl_command_func_t *old_newline_func;
-
-static unsigned char delim_char;
-
-static void
-set_eol_delim (c)
- int c;
-{
- Keymap cmap;
-
- if (bash_readline_initialized == 0)
- initialize_readline ();
- cmap = rl_get_keymap ();
-
- /* Change newline to self-insert */
- old_newline_ctype = cmap[RETURN].type;
- old_newline_func = cmap[RETURN].function;
- cmap[RETURN].type = ISFUNC;
- cmap[RETURN].function = rl_insert;
-
- /* Bind the delimiter character to accept-line. */
- old_delim_ctype = cmap[c].type;
- old_delim_func = cmap[c].function;
- cmap[c].type = ISFUNC;
- cmap[c].function = rl_newline;
-
- delim_char = c;
-}
-
-static void
-reset_eol_delim (cp)
- char *cp;
-{
- Keymap cmap;
-
- cmap = rl_get_keymap ();
-
- cmap[RETURN].type = old_newline_ctype;
- cmap[RETURN].function = old_newline_func;
-
- cmap[delim_char].type = old_delim_ctype;
- cmap[delim_char].function = old_delim_func;
-}
-#endif
diff --git a/builtins/source.def~ b/builtins/source.def~
deleted file mode 100644
index f9f812f8..00000000
--- a/builtins/source.def~
+++ /dev/null
@@ -1,174 +0,0 @@
-This file is source.def, from which is created source.c.
-It implements the builtins "." and "source" in Bash.
-
-Copyright (C) 1987-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.
-
-$PRODUCES source.c
-
-$BUILTIN source
-$FUNCTION source_builtin
-$SHORT_DOC source filename [arguments]
-Read and execute commands from FILENAME and return. The pathnames
-in $PATH are used to find the directory containing FILENAME. If any
-ARGUMENTS are supplied, they become the positional parameters when
-FILENAME is executed.
-$END
-$BUILTIN .
-$DOCNAME dot
-$FUNCTION source_builtin
-$SHORT_DOC . filename [arguments]
-Read and execute commands from FILENAME and return. The pathnames
-in $PATH are used to find the directory containing FILENAME. If any
-ARGUMENTS are supplied, they become the positional parameters when
-FILENAME is executed.
-$END
-/* source.c - Implements the `.' and `source' builtins. */
-
-#include <config.h>
-
-#include "../bashtypes.h"
-#include "posixstat.h"
-#include "filecntl.h"
-#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-#include <errno.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "../bashansi.h"
-#include "../bashintl.h"
-
-#include "../shell.h"
-#include "../flags.h"
-#include "../findcmd.h"
-#include "common.h"
-#include "bashgetopt.h"
-#include "../trap.h"
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#if defined (RESTRICTED_SHELL)
-extern int restricted;
-#endif
-
-/* If non-zero, `.' uses $PATH to look up the script to be sourced. */
-int source_uses_path = 1;
-
-/* If non-zero, `.' looks in the current directory if the filename argument
- is not found in the $PATH. */
-int source_searches_cwd = 1;
-
-/* If this . script is supplied arguments, we save the dollar vars and
- replace them with the script arguments for the duration of the script's
- execution. If the script does not change the dollar vars, we restore
- what we saved. If the dollar vars are changed in the script, and we are
- not executing a shell function, we leave the new values alone and free
- the saved values. */
-static void
-maybe_pop_dollar_vars ()
-{
- if (variable_context == 0 && (dollar_vars_changed () & ARGS_SETBLTIN))
- dispose_saved_dollar_vars ();
- else
- pop_dollar_vars ();
- if (debugging_mode)
- pop_args (); /* restore BASH_ARGC and BASH_ARGV */
- set_dollar_vars_unchanged ();
-}
-
-/* Read and execute commands from the file passed as argument. Guess what.
- This cannot be done in a subshell, since things like variable assignments
- take place in there. So, I open the file, place it into a large string,
- close the file, and then execute the string. */
-int
-source_builtin (list)
- WORD_LIST *list;
-{
- int result;
- char *filename, *debug_trap;
-
- if (no_options (list))
- return (EX_USAGE);
- list = loptend;
-
- if (list == 0)
- {
- builtin_error (_("filename argument required"));
- builtin_usage ();
- return (EX_USAGE);
- }
-
-#if defined (RESTRICTED_SHELL)
- if (restricted && strchr (list->word->word, '/'))
- {
- sh_restricted (list->word->word);
- return (EXECUTION_FAILURE);
- }
-#endif
-
- filename = (char *)NULL;
- if (source_uses_path)
- filename = find_path_file (list->word->word);
- if (filename == 0)
- {
- if (source_searches_cwd == 0)
- {
- builtin_error (_("%s: file not found"), list->word->word);
- return (EXECUTION_FAILURE);
- }
- else
- filename = savestring (list->word->word);
- }
-
- begin_unwind_frame ("source");
- add_unwind_protect ((Function *)xfree, filename);
-
- if (list->next)
- {
- push_dollar_vars ();
- add_unwind_protect ((Function *)maybe_pop_dollar_vars, (char *)NULL);
- remember_args (list->next, 1);
- if (debugging_mode)
- push_args (list->next); /* Update BASH_ARGV and BASH_ARGC */
- }
- set_dollar_vars_unchanged ();
-
- /* Don't inherit the DEBUG trap unless function_trace_mode (overloaded)
- is set. XXX - should sourced files inherit the RETURN trap? Functions
- don't. */
- debug_trap = TRAP_STRING (DEBUG_TRAP);
- if (debug_trap && function_trace_mode == 0)
- {
- debug_trap = savestring (debug_trap);
- add_unwind_protect (xfree, debug_trap);
- add_unwind_protect (set_debug_trap, debug_trap);
- restore_default_signal (DEBUG_TRAP);
- }
-
- result = source_file (filename, (list && list->next));
-
- run_unwind_frame ("source");
-
- return (result);
-}
diff --git a/builtins/suspend.def~ b/builtins/suspend.def~
deleted file mode 100644
index d616d775..00000000
--- a/builtins/suspend.def~
+++ /dev/null
@@ -1,119 +0,0 @@
-This file is suspend.def, from which is created suspend.c.
-It implements the builtin "suspend" in Bash.
-
-Copyright (C) 1987-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.
-
-$PRODUCES suspend.c
-
-$BUILTIN suspend
-$DEPENDS_ON JOB_CONTROL
-$FUNCTION suspend_builtin
-$SHORT_DOC suspend [-f]
-Suspend the execution of this shell until it receives a SIGCONT
-signal. The `-f' if specified says not to complain about this
-being a login shell if it is; just suspend anyway.
-$END
-
-#include <config.h>
-
-#if defined (JOB_CONTROL)
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include "../bashtypes.h"
-#include <signal.h>
-#include "../bashintl.h"
-#include "../shell.h"
-#include "../jobs.h"
-#include "common.h"
-#include "bashgetopt.h"
-
-static SigHandler *old_cont;
-#if 0
-static SigHandler *old_stop;
-#endif
-
-/* Continue handler. */
-sighandler
-suspend_continue (sig)
- int sig;
-{
- set_signal_handler (SIGCONT, old_cont);
-#if 0
- set_signal_handler (SIGSTOP, old_stop);
-#endif
- SIGRETURN (0);
-}
-
-/* Suspending the shell. If -f is the arg, then do the suspend
- no matter what. Otherwise, complain if a login shell. */
-int
-suspend_builtin (list)
- WORD_LIST *list;
-{
- int opt, force;
-
- reset_internal_getopt ();
- force = 0;
- while ((opt = internal_getopt (list, "f")) != -1)
- switch (opt)
- {
- case 'f':
- force++;
- break;
- default:
- builtin_usage ();
- return (EX_USAGE);
- }
-
- list = loptend;
-
- if (job_control == 0)
- {
- sh_nojobs (_("cannot suspend"));
- return (EXECUTION_FAILURE);
- }
-
- if (force == 0)
- {
- no_args (list);
-
- if (login_shell)
- {
- builtin_error (_("cannot suspend a login shell"));
- return (EXECUTION_FAILURE);
- }
- }
-
- /* XXX - should we put ourselves back into the original pgrp now? If so,
- call end_job_control() here and do the right thing in suspend_continue
- (that is, call restart_job_control()). */
- old_cont = (SigHandler *)set_signal_handler (SIGCONT, suspend_continue);
-#if 0
- old_stop = (SigHandler *)set_signal_handler (SIGSTOP, SIG_DFL);
-#endif
- killpg (shell_pgrp, SIGSTOP);
- return (EXECUTION_SUCCESS);
-}
-
-#endif /* JOB_CONTROL */
diff --git a/builtins/trap.def~ b/builtins/trap.def~
deleted file mode 100644
index a9d1be37..00000000
--- a/builtins/trap.def~
+++ /dev/null
@@ -1,265 +0,0 @@
-This file is trap.def, from which is created trap.c.
-It implements the builtin "trap" in Bash.
-
-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.
-
-$PRODUCES trap.c
-
-$BUILTIN trap
-$FUNCTION trap_builtin
-$SHORT_DOC trap [-lp] [arg signal_spec ...]
-The command ARG is to be read and executed when the shell receives
-signal(s) SIGNAL_SPEC. If ARG is absent (and a single SIGNAL_SPEC
-is supplied) or `-', each specified signal is reset to its original
-value. If ARG is the null string each SIGNAL_SPEC is ignored by the
-shell and by the commands it invokes. If a SIGNAL_SPEC is EXIT (0)
-the command ARG is executed on exit from the shell. If a SIGNAL_SPEC
-is DEBUG, ARG is executed after every simple command. If the`-p' option
-is supplied then the trap commands associated with each SIGNAL_SPEC are
-displayed. If no arguments are supplied or if only `-p' is given, trap
-prints the list of commands associated with each signal. Each SIGNAL_SPEC
-is either a signal name in <signal.h> or a signal number. Signal names
-are case insensitive and the SIG prefix is optional. `trap -l' prints
-a list of signal names and their corresponding numbers. Note that a
-signal can be sent to the shell with "kill -signal $$".
-$END
-
-#include <config.h>
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include "../bashtypes.h"
-#include <signal.h>
-#include <stdio.h>
-#include "../bashansi.h"
-
-#include "../shell.h"
-#include "../trap.h"
-#include "common.h"
-#include "bashgetopt.h"
-
-static void showtrap __P((int));
-static int display_traps __P((WORD_LIST *));
-
-/* The trap command:
-
- trap <arg> <signal ...>
- trap <signal ...>
- trap -l
- trap -p [sigspec ...]
- trap [--]
-
- Set things up so that ARG is executed when SIGNAL(s) N is recieved.
- If ARG is the empty string, then ignore the SIGNAL(s). If there is
- no ARG, then set the trap for SIGNAL(s) to its original value. Just
- plain "trap" means to print out the list of commands associated with
- each signal number. Single arg of "-l" means list the signal names. */
-
-/* Possible operations to perform on the list of signals.*/
-#define SET 0 /* Set this signal to first_arg. */
-#define REVERT 1 /* Revert to this signals original value. */
-#define IGNORE 2 /* Ignore this signal. */
-
-extern int posixly_correct;
-
-int
-trap_builtin (list)
- WORD_LIST *list;
-{
- int list_signal_names, display, result, opt, first_signal;
-
- list_signal_names = display = 0;
- result = EXECUTION_SUCCESS;
- reset_internal_getopt ();
- while ((opt = internal_getopt (list, "lp")) != -1)
- {
- switch (opt)
- {
- case 'l':
- list_signal_names++;
- break;
- case 'p':
- display++;
- break;
- default:
- builtin_usage ();
- return (EX_USAGE);
- }
- }
- list = loptend;
-
- opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */
-
- if (list_signal_names)
- return (display_signal_list ((WORD_LIST *)NULL, 1));
- else if (display || list == 0)
- return (display_traps (list));
- else
- {
- char *first_arg;
- int operation, sig, first_signal;
-
- operation = SET;
- first_arg = list->word->word;
- first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt);
-
- /* Backwards compatibility */
- if (first_signal)
- operation = REVERT;
- /* When in posix mode, the historical behavior of looking for a
- missing first argument is disabled. To revert to the original
- signal handling disposition, use `-' as the first argument. */
- else if (posixly_correct == 0 && first_arg && *first_arg &&
- (*first_arg != '-' || first_arg[1]) &&
- signal_object_p (first_arg, opt) && list->next == 0)
- operation = REVERT;
- else
- {
- list = list->next;
- if (list == 0)
- {
- builtin_usage ();
- return (EX_USAGE);
- }
- else if (*first_arg == '\0')
- operation = IGNORE;
- else if (first_arg[0] == '-' && !first_arg[1])
- operation = REVERT;
- }
-
- while (list)
- {
- sig = decode_signal (list->word->word, opt);
-
- if (sig == NO_SIG)
- {
- sh_invalidsig (list->word->word);
- result = EXECUTION_FAILURE;
- }
- else
- {
- switch (operation)
- {
- case SET:
- set_signal (sig, first_arg);
- break;
-
- case REVERT:
- restore_default_signal (sig);
-
- /* Signals that the shell treats specially need special
- handling. */
- switch (sig)
- {
- case SIGINT:
- if (interactive)
- set_signal_handler (SIGINT, sigint_sighandler);
- else
- set_signal_handler (SIGINT, termsig_sighandler);
- break;
-
- case SIGQUIT:
- /* Always ignore SIGQUIT. */
- set_signal_handler (SIGQUIT, SIG_IGN);
- break;
- case SIGTERM:
-#if defined (JOB_CONTROL)
- case SIGTTIN:
- case SIGTTOU:
- case SIGTSTP:
-#endif /* JOB_CONTROL */
- if (interactive)
- set_signal_handler (sig, SIG_IGN);
- break;
- }
- break;
-
- case IGNORE:
- ignore_signal (sig);
- break;
- }
- }
- list = list->next;
- }
- }
-
- return (result);
-}
-
-static void
-showtrap (i)
- int i;
-{
- char *t, *p, *sn;
-
- p = trap_list[i];
- if (p == (char *)DEFAULT_SIG)
- return;
-
- t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
- sn = signal_name (i);
- /* Make sure that signals whose names are unknown (for whatever reason)
- are printed as signal numbers. */
- if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
- printf ("trap -- %s %d\n", t ? t : "''", i);
- else if (posixly_correct)
- {
- if (STREQN (sn, "SIG", 3))
- printf ("trap -- %s %s\n", t ? t : "''", sn+3);
- else
- printf ("trap -- %s %s\n", t ? t : "''", sn);
- }
- else
- printf ("trap -- %s %s\n", t ? t : "''", sn);
-
- FREE (t);
-}
-
-static int
-display_traps (list)
- WORD_LIST *list;
-{
- int result, i;
-
- if (list == 0)
- {
- for (i = 0; i < BASH_NSIG; i++)
- showtrap (i);
- return (EXECUTION_SUCCESS);
- }
-
- for (result = EXECUTION_SUCCESS; list; list = list->next)
- {
- i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX);
- if (i == NO_SIG)
- {
- sh_invalidsig (list->word->word);
- result = EXECUTION_FAILURE;
- }
- else
- showtrap (i);
- }
-
- return (result);
-}
diff --git a/builtins/ulimit.def~ b/builtins/ulimit.def~
deleted file mode 100644
index 17898699..00000000
--- a/builtins/ulimit.def~
+++ /dev/null
@@ -1,750 +0,0 @@
-This file is ulimit.def, from which is created ulimit.c.
-It implements the builtin "ulimit" in Bash.
-
-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.
-
-$PRODUCES ulimit.c
-
-$BUILTIN ulimit
-$FUNCTION ulimit_builtin
-$DEPENDS_ON !_MINIX
-$SHORT_DOC ulimit [-SHacdfilmnpqstuvx] [limit]
-Ulimit provides control over the resources available to processes
-started by the shell, on systems that allow such control. If an
-option is given, it is interpreted as follows:
-
- -S use the `soft' resource limit
- -H use the `hard' resource limit
- -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
- -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
- -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
-
-If LIMIT is given, it is the new value of the specified resource;
-the special LIMIT values `soft', `hard', and `unlimited' stand for
-the current soft limit, the current hard limit, and no limit, respectively.
-Otherwise, the current value of the specified resource is printed.
-If no option is given, then -f is assumed. Values are in 1024-byte
-increments, except for -t, which is in seconds, -p, which is in
-increments of 512 bytes, and -u, which is an unscaled number of
-processes.
-$END
-
-#if !defined (_MINIX)
-
-#include <config.h>
-
-#include "../bashtypes.h"
-#ifndef _MINIX
-# include <sys/param.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-
-#include "../bashintl.h"
-
-#include "../shell.h"
-#include "common.h"
-#include "bashgetopt.h"
-#include "pipesize.h"
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-/* For some reason, HPUX chose to make these definitions visible only if
- _KERNEL is defined, so we define _KERNEL before including <sys/resource.h>
- and #undef it afterward. */
-#if defined (HAVE_RESOURCE)
-# include <sys/time.h>
-# if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
-# define _KERNEL
-# endif
-# include <sys/resource.h>
-# if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
-# undef _KERNEL
-# endif
-#else
-# include <sys/times.h>
-#endif
-
-#if defined (HAVE_LIMITS_H)
-# include <limits.h>
-#endif
-
-/* Check for the most basic symbols. If they aren't present, this
- system's <sys/resource.h> isn't very useful to us. */
-#if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT)
-# undef HAVE_RESOURCE
-#endif
-
-#if !defined (RLIMTYPE)
-# define RLIMTYPE long
-# define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
-# define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
-#endif
-
-/* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
-#if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
-# define RLIMIT_NOFILE RLIMIT_OFILE
-#endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
-
-/* Some systems have these, some do not. */
-#ifdef RLIMIT_FSIZE
-# define RLIMIT_FILESIZE RLIMIT_FSIZE
-#else
-# define RLIMIT_FILESIZE 256
-#endif
-
-#define RLIMIT_PIPESIZE 257
-
-#ifdef RLIMIT_NOFILE
-# define RLIMIT_OPENFILES RLIMIT_NOFILE
-#else
-# define RLIMIT_OPENFILES 258
-#endif
-
-#ifdef RLIMIT_VMEM
-# define RLIMIT_VIRTMEM RLIMIT_VMEM
-# define RLIMIT_VMBLKSZ 1024
-#else
-# ifdef RLIMIT_AS
-# define RLIMIT_VIRTMEM RLIMIT_AS
-# define RLIMIT_VMBLKSZ 1024
-# else
-# define RLIMIT_VIRTMEM 259
-# define RLIMIT_VMBLKSZ 1
-# endif
-#endif
-
-#ifdef RLIMIT_NPROC
-# define RLIMIT_MAXUPROC RLIMIT_NPROC
-#else
-# define RLIMIT_MAXUPROC 260
-#endif
-
-#if !defined (RLIM_INFINITY)
-# define RLIM_INFINITY 0x7fffffff
-#endif
-
-#if !defined (RLIM_SAVED_CUR)
-# define RLIM_SAVED_CUR RLIM_INFINITY
-#endif
-
-#if !defined (RLIM_SAVED_MAX)
-# define RLIM_SAVED_MAX RLIM_INFINITY
-#endif
-
-#define LIMIT_HARD 0x01
-#define LIMIT_SOFT 0x02
-
-static int _findlim __P((int));
-
-static int ulimit_internal __P((int, char *, int, int));
-
-static int get_limit __P((int, RLIMTYPE *, RLIMTYPE *));
-static int set_limit __P((int, RLIMTYPE, int));
-
-static void printone __P((int, RLIMTYPE, int));
-static void print_all_limits __P((int));
-
-static int set_all_limits __P((int, RLIMTYPE));
-
-static int filesize __P((RLIMTYPE *));
-static int pipesize __P((RLIMTYPE *));
-static int getmaxuprc __P((RLIMTYPE *));
-static int getmaxvm __P((RLIMTYPE *, RLIMTYPE *));
-
-typedef struct {
- int option; /* The ulimit option for this limit. */
- int parameter; /* Parameter to pass to get_limit (). */
- int block_factor; /* Blocking factor for specific limit. */
- char *description; /* Descriptive string to output. */
- char *units; /* scale */
-} RESOURCE_LIMITS;
-
-static RESOURCE_LIMITS limits[] = {
-#ifdef RLIMIT_CORE
- { 'c', RLIMIT_CORE, 1024, "core file size", "blocks" },
-#endif
-#ifdef RLIMIT_DATA
- { 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
-#endif
-#ifdef RLIMIT_NICE
- { 'e', RLIMIT_NICE, 1, "scheduling priority", (char *)NULL },
-#endif
- { 'f', RLIMIT_FILESIZE, 1024, "file size", "blocks" },
-#ifdef RLIMIT_SIGPENDING
- { 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL },
-#endif
-#ifdef RLIMIT_MEMLOCK
- { 'l', RLIMIT_MEMLOCK, 1024, "max locked memory", "kbytes" },
-#endif
-#ifdef RLIMIT_RSS
- { 'm', RLIMIT_RSS, 1024, "max memory size", "kbytes" },
-#endif /* RLIMIT_RSS */
- { 'n', RLIMIT_OPENFILES, 1, "open files", (char *)NULL},
- { 'p', RLIMIT_PIPESIZE, 512, "pipe size", "512 bytes" },
-#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
-#ifdef RLIMIT_CPU
- { 't', RLIMIT_CPU, 1, "cpu time", "seconds" },
-#endif /* RLIMIT_CPU */
- { 'u', RLIMIT_MAXUPROC, 1, "max user processes", (char *)NULL },
-#if defined (HAVE_RESOURCE)
- { 'v', RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory", "kbytes" },
-#endif
-#ifdef RLIMIT_SWAP
- { 'w', RLIMIT_SWAP, 1024, "swap size", "kbytes" },
-#endif
-#ifdef RLIMIT_LOCKS
- { 'x', RLIMIT_LOCKS, 1, "file locks", (char *)NULL },
-#endif
- { -1, -1, -1, (char *)NULL, (char *)NULL }
-};
-#define NCMDS (sizeof(limits) / sizeof(limits[0]))
-
-typedef struct _cmd {
- int cmd;
- char *arg;
-} ULCMD;
-
-static ULCMD *cmdlist;
-static int ncmd;
-static int cmdlistsz;
-
-#if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT)
-long
-ulimit (cmd, newlim)
- int cmd;
- long newlim;
-{
- errno = EINVAL;
- return -1;
-}
-#endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */
-
-static int
-_findlim (opt)
- int opt;
-{
- register int i;
-
- for (i = 0; limits[i].option > 0; i++)
- if (limits[i].option == opt)
- return i;
- return -1;
-}
-
-static char optstring[4 + 2 * NCMDS];
-
-/* Report or set limits associated with certain per-process resources.
- See the help documentation in builtins.c for a full description. */
-int
-ulimit_builtin (list)
- register WORD_LIST *list;
-{
- register char *s;
- int c, limind, mode, opt, all_limits;
-
- mode = 0;
-
- all_limits = 0;
-
- /* Idea stolen from pdksh -- build option string the first time called. */
- if (optstring[0] == 0)
- {
- s = optstring;
- *s++ = 'a'; *s++ = 'S'; *s++ = 'H';
- for (c = 0; limits[c].option > 0; c++)
- {
- *s++ = limits[c].option;
- *s++ = ';';
- }
- *s = '\0';
- }
-
- /* Initialize the command list. */
- if (cmdlistsz == 0)
- cmdlist = (ULCMD *)xmalloc ((cmdlistsz = 16) * sizeof (ULCMD));
- ncmd = 0;
-
- reset_internal_getopt ();
- while ((opt = internal_getopt (list, optstring)) != -1)
- {
- switch (opt)
- {
- case 'a':
- all_limits++;
- break;
-
- /* -S and -H are modifiers, not real options. */
- case 'S':
- mode |= LIMIT_SOFT;
- break;
-
- case 'H':
- mode |= LIMIT_HARD;
- break;
-
- case '?':
- builtin_usage ();
- return (EX_USAGE);
-
- default:
- if (ncmd >= cmdlistsz)
- cmdlist = (ULCMD *)xrealloc (cmdlist, (cmdlistsz *= 2) * sizeof (ULCMD));
- cmdlist[ncmd].cmd = opt;
- cmdlist[ncmd++].arg = list_optarg;
- break;
- }
- }
- list = loptend;
-
- if (all_limits)
- {
-#ifdef NOTYET
- if (list) /* setting */
- {
- if (STREQ (list->word->word, "unlimited") == 0)
- {
- builtin_error (_("%s: invalid limit argument"), list->word->word);
- return (EXECUTION_FAILURE);
- }
- return (set_all_limits (mode == 0 ? LIMIT_SOFT|LIMIT_HARD : mode, RLIM_INFINITY));
- }
-#endif
- print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
- return (EXECUTION_SUCCESS);
- }
-
- /* default is `ulimit -f' */
- if (ncmd == 0)
- {
- cmdlist[ncmd].cmd = 'f';
- /* `ulimit something' is same as `ulimit -f something' */
- cmdlist[ncmd++].arg = list ? list->word->word : (char *)NULL;
- if (list)
- list = list->next;
- }
-
- /* verify each command in the list. */
- for (c = 0; c < ncmd; c++)
- {
- limind = _findlim (cmdlist[c].cmd);
- if (limind == -1)
- {
- builtin_error (_("`%c': bad command"), cmdlist[c].cmd);
- return (EX_USAGE);
- }
- }
-
- for (c = 0; c < ncmd; c++)
- if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE)
- return (EXECUTION_FAILURE);
-
- return (EXECUTION_SUCCESS);
-}
-
-static int
-ulimit_internal (cmd, cmdarg, mode, multiple)
- int cmd;
- char *cmdarg;
- int mode, multiple;
-{
- int opt, limind, setting;
- int block_factor;
- RLIMTYPE soft_limit, hard_limit, real_limit, limit;
-
- setting = cmdarg != 0;
- limind = _findlim (cmd);
- if (mode == 0)
- mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT;
- opt = get_limit (limind, &soft_limit, &hard_limit);
- if (opt < 0)
- {
- builtin_error (_("%s: cannot get limit: %s"), limits[limind].description,
- strerror (errno));
- return (EXECUTION_FAILURE);
- }
-
- if (setting == 0) /* print the value of the specified limit */
- {
- printone (limind, (mode & LIMIT_SOFT) ? soft_limit : hard_limit, multiple);
- return (EXECUTION_SUCCESS);
- }
-
- /* Setting the limit. */
- if (STREQ (cmdarg, "hard"))
- real_limit = hard_limit;
- else if (STREQ (cmdarg, "soft"))
- real_limit = soft_limit;
- else if (STREQ (cmdarg, "unlimited"))
- real_limit = RLIM_INFINITY;
- else if (all_digits (cmdarg))
- {
- limit = string_to_rlimtype (cmdarg);
- block_factor = limits[limind].block_factor;
- real_limit = limit * block_factor;
-
- if ((real_limit / block_factor) != limit)
- {
- sh_erange (cmdarg, "limit");
- return (EXECUTION_FAILURE);
- }
- }
- else
- {
- sh_invalidnum (cmdarg);
- return (EXECUTION_FAILURE);
- }
-
- if (set_limit (limind, real_limit, mode) < 0)
- {
- builtin_error (_("%s: cannot modify limit: %s"), limits[limind].description,
- strerror (errno));
- return (EXECUTION_FAILURE);
- }
-
- return (EXECUTION_SUCCESS);
-}
-
-static int
-get_limit (ind, softlim, hardlim)
- int ind;
- RLIMTYPE *softlim, *hardlim;
-{
- RLIMTYPE value;
-#if defined (HAVE_RESOURCE)
- struct rlimit limit;
-#endif
-
- if (limits[ind].parameter >= 256)
- {
- switch (limits[ind].parameter)
- {
- case RLIMIT_FILESIZE:
- if (filesize (&value) < 0)
- return -1;
- break;
- case RLIMIT_PIPESIZE:
- if (pipesize (&value) < 0)
- return -1;
- break;
- case RLIMIT_OPENFILES:
- value = (RLIMTYPE)getdtablesize ();
- break;
- case RLIMIT_VIRTMEM:
- return (getmaxvm (softlim, hardlim));
- case RLIMIT_MAXUPROC:
- if (getmaxuprc (&value) < 0)
- return -1;
- break;
- default:
- errno = EINVAL;
- return -1;
- }
- *softlim = *hardlim = value;
- return (0);
- }
- else
- {
-#if defined (HAVE_RESOURCE)
- if (getrlimit (limits[ind].parameter, &limit) < 0)
- return -1;
- *softlim = limit.rlim_cur;
- *hardlim = limit.rlim_max;
-# if defined (HPUX9)
- if (limits[ind].parameter == RLIMIT_FILESIZE)
- {
- *softlim *= 512;
- *hardlim *= 512; /* Ugh. */
- }
- else
-# endif /* HPUX9 */
- return 0;
-#else
- errno = EINVAL;
- return -1;
-#endif
- }
-}
-
-static int
-set_limit (ind, newlim, mode)
- int ind;
- RLIMTYPE newlim;
- int mode;
-{
-#if defined (HAVE_RESOURCE)
- struct rlimit limit;
- RLIMTYPE val;
-#endif
-
- if (limits[ind].parameter >= 256)
- switch (limits[ind].parameter)
- {
- case RLIMIT_FILESIZE:
-#if !defined (HAVE_RESOURCE)
- return (ulimit (2, newlim / 512L));
-#else
- errno = EINVAL;
- return -1;
-#endif
-
- case RLIMIT_OPENFILES:
-#if defined (HAVE_SETDTABLESIZE)
-# if defined (__CYGWIN__)
- /* Grrr... Cygwin declares setdtablesize as void. */
- setdtablesize (newlim);
- return 0;
-# else
- return (setdtablesize (newlim));
-# endif
-#endif
- case RLIMIT_PIPESIZE:
- case RLIMIT_VIRTMEM:
- case RLIMIT_MAXUPROC:
- default:
- errno = EINVAL;
- return -1;
- }
- else
- {
-#if defined (HAVE_RESOURCE)
- if (getrlimit (limits[ind].parameter, &limit) < 0)
- return -1;
-# if defined (HPUX9)
- if (limits[ind].parameter == RLIMIT_FILESIZE)
- newlim /= 512; /* Ugh. */
-# endif /* HPUX9 */
- val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
- (mode & LIMIT_HARD) == 0 && /* XXX -- test */
- (limit.rlim_cur <= limit.rlim_max))
- ? limit.rlim_max : newlim;
- if (mode & LIMIT_SOFT)
- limit.rlim_cur = val;
- if (mode & LIMIT_HARD)
- limit.rlim_max = val;
-
- return (setrlimit (limits[ind].parameter, &limit));
-#else
- errno = EINVAL;
- return -1;
-#endif
- }
-}
-
-static int
-getmaxvm (softlim, hardlim)
- RLIMTYPE *softlim, *hardlim;
-{
-#if defined (HAVE_RESOURCE)
- struct rlimit datalim, stacklim;
-
- if (getrlimit (RLIMIT_DATA, &datalim) < 0)
- return -1;
-
- if (getrlimit (RLIMIT_STACK, &stacklim) < 0)
- return -1;
-
- /* Protect against overflow. */
- *softlim = (datalim.rlim_cur / 1024L) + (stacklim.rlim_cur / 1024L);
- *hardlim = (datalim.rlim_max / 1024L) + (stacklim.rlim_max / 1024L);
- return 0;
-#else
- errno = EINVAL;
- return -1;
-#endif /* HAVE_RESOURCE */
-}
-
-static int
-filesize(valuep)
- RLIMTYPE *valuep;
-{
-#if !defined (HAVE_RESOURCE)
- long result;
- if ((result = ulimit (1, 0L)) < 0)
- return -1;
- else
- *valuep = (RLIMTYPE) result * 512;
- return 0;
-#else
- errno = EINVAL;
- return -1;
-#endif
-}
-
-static int
-pipesize (valuep)
- RLIMTYPE *valuep;
-{
-#if defined (PIPE_BUF)
- /* This is defined on Posix systems. */
- *valuep = (RLIMTYPE) PIPE_BUF;
- return 0;
-#else
-# if defined (_POSIX_PIPE_BUF)
- *valuep = (RLIMTYPE) _POSIX_PIPE_BUF;
- return 0;
-# else
-# if defined (PIPESIZE)
- /* This is defined by running a program from the Makefile. */
- *valuep = (RLIMTYPE) PIPESIZE;
- return 0;
-# else
- errno = EINVAL;
- return -1;
-# endif /* PIPESIZE */
-# endif /* _POSIX_PIPE_BUF */
-#endif /* PIPE_BUF */
-}
-
-static int
-getmaxuprc (valuep)
- RLIMTYPE *valuep;
-{
- long maxchild;
-
- maxchild = getmaxchild ();
- if (maxchild < 0)
- {
- errno = EINVAL;
- return -1;
- }
- else
- {
- *valuep = (RLIMTYPE) maxchild;
- return 0;
- }
-}
-
-static void
-print_all_limits (mode)
- int mode;
-{
- register int i;
- RLIMTYPE softlim, hardlim;
-
- if (mode == 0)
- mode |= LIMIT_SOFT;
-
- for (i = 0; limits[i].option > 0; i++)
- {
- if (get_limit (i, &softlim, &hardlim) == 0)
- printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
- else if (errno != EINVAL)
- builtin_error ("%s: cannot get limit: %s", limits[i].description,
- strerror (errno));
- }
-}
-
-static void
-printone (limind, curlim, pdesc)
- int limind;
- RLIMTYPE curlim;
- int pdesc;
-{
- char unitstr[64];
-
- if (pdesc)
- {
- if (limits[limind].units)
- sprintf (unitstr, "(%s, -%c) ", limits[limind].units, limits[limind].option);
- else
- sprintf (unitstr, "(-%c) ", limits[limind].option);
-
- printf ("%-20s %16s", limits[limind].description, unitstr);
- }
- if (curlim == RLIM_INFINITY)
- puts ("unlimited");
- else if (curlim == RLIM_SAVED_MAX)
- puts ("hard");
- else if (curlim == RLIM_SAVED_CUR)
- puts ("soft");
- else
- print_rlimtype ((curlim / limits[limind].block_factor), 1);
-}
-
-/* Set all limits to NEWLIM. NEWLIM currently must be RLIM_INFINITY, which
- causes all limits to be set as high as possible depending on mode (like
- csh `unlimit'). Returns -1 if NEWLIM is invalid, 0 if all limits
- were set successfully, and 1 if at least one limit could not be set.
-
- To raise all soft limits to their corresponding hard limits, use
- ulimit -S -a unlimited
- To attempt to raise all hard limits to infinity (superuser-only), use
- ulimit -H -a unlimited
- To attempt to raise all soft and hard limits to infinity, use
- ulimit -a unlimited
-*/
-
-static int
-set_all_limits (mode, newlim)
- int mode;
- RLIMTYPE newlim;
-{
- register int i;
- int retval = 0;
-
- if (newlim != RLIM_INFINITY)
- {
- errno = EINVAL;
- return -1;
- }
-
- if (mode == 0)
- mode = LIMIT_SOFT|LIMIT_HARD;
-
- for (retval = i = 0; limits[i].option > 0; i++)
- if (set_limit (i, newlim, mode) < 0)
- {
- builtin_error ("%s: cannot modify limit: %s", limits[i].description,
- strerror (errno));
- retval = 1;
- }
- return retval;
-}
-
-#endif /* !_MINIX */
diff --git a/builtins/wait.def~ b/builtins/wait.def~
deleted file mode 100644
index 22a92bea..00000000
--- a/builtins/wait.def~
+++ /dev/null
@@ -1,177 +0,0 @@
-This file is wait.def, from which is created wait.c.
-It implements the builtin "wait" in Bash.
-
-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.
-
-$BUILTIN wait
-$FUNCTION wait_builtin
-$DEPENDS_ON JOB_CONTROL
-$PRODUCES wait.c
-$SHORT_DOC wait [n]
-Wait for the specified process and report its termination status. If
-N is not given, all currently active child processes are waited for,
-and the return code is zero. N may be a process ID or a job
-specification; if a job spec is given, all processes in the job's
-pipeline are waited for.
-$END
-
-$BUILTIN wait
-$FUNCTION wait_builtin
-$DEPENDS_ON !JOB_CONTROL
-$SHORT_DOC wait [n]
-Wait for the specified process and report its termination status. If
-N is not given, all currently active child processes are waited for,
-and the return code is zero. N is a process ID; if it is not given,
-all child processes of the shell are waited for.
-$END
-
-#include <config.h>
-
-#include "../bashtypes.h"
-#include <signal.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <chartypes.h>
-
-#include "../bashansi.h"
-
-#include "../shell.h"
-#include "../jobs.h"
-#include "common.h"
-#include "bashgetopt.h"
-
-extern int interrupt_immediately;
-extern int wait_signal_received;
-
-procenv_t wait_intr_buf;
-
-/* Wait for the pid in LIST to stop or die. If no arguments are given, then
- wait for all of the active background processes of the shell and return
- 0. If a list of pids or job specs are given, return the exit status of
- the last one waited for. */
-
-#define WAIT_RETURN(s) \
- do \
- { \
- interrupt_immediately = old_interrupt_immediately;\
- return (s);\
- } \
- while (0)
-
-int
-wait_builtin (list)
- WORD_LIST *list;
-{
- int status, code;
- volatile int old_interrupt_immediately;
-
- USE_VAR(list);
-
- if (no_options (list))
- return (EX_USAGE);
- list = loptend;
-
- old_interrupt_immediately = interrupt_immediately;
- interrupt_immediately++;
-
- /* POSIX.2 says: When the shell is waiting (by means of the wait utility)
- for asynchronous commands to complete, the reception of a signal for
- which a trap has been set shall cause the wait utility to return
- immediately with an exit status greater than 128, after which the trap
- associated with the signal shall be taken.
-
- We handle SIGINT here; it's the only one that needs to be treated
- specially (I think), since it's handled specially in {no,}jobs.c. */
- code = setjmp (wait_intr_buf);
- if (code)
- {
- status = 128 + wait_signal_received;
- WAIT_RETURN (status);
- }
-
- /* We support jobs or pids.
- wait <pid-or-job> [pid-or-job ...] */
-
- /* But wait without any arguments means to wait for all of the shell's
- currently active background processes. */
- if (list == 0)
- {
- wait_for_background_pids ();
- WAIT_RETURN (EXECUTION_SUCCESS);
- }
-
- status = EXECUTION_SUCCESS;
- while (list)
- {
- pid_t pid;
- char *w;
- intmax_t pid_value;
-
- w = list->word->word;
- if (DIGIT (*w))
- {
- if (legal_number (w, &pid_value) && pid_value == (pid_t)pid_value)
- {
- pid = (pid_t)pid_value;
- status = wait_for_single_pid (pid);
- }
- else
- {
- sh_badpid (w);
- WAIT_RETURN (EXECUTION_FAILURE);
- }
- }
-#if defined (JOB_CONTROL)
- else if (*w && *w == '%')
- /* Must be a job spec. Check it out. */
- {
- int job;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
- job = get_job_spec (list);
-
- if (INVALID_JOB (job))
- {
- if (job != DUP_JOB)
- sh_badjob (list->word->word);
- UNBLOCK_CHILD (oset);
- status = 127; /* As per Posix.2, section 4.70.2 */
- list = list->next;
- continue;
- }
-
- /* Job spec used. Wait for the last pid in the pipeline. */
- UNBLOCK_CHILD (oset);
- status = wait_for_job (job);
- }
-#endif /* JOB_CONTROL */
- else
- {
- sh_badpid (w);
- status = EXECUTION_FAILURE;
- }
- list = list->next;
- }
-
- WAIT_RETURN (status);
-}
diff --git a/command.h~ b/command.h~
deleted file mode 100644
index a5bac0b6..00000000
--- a/command.h~
+++ /dev/null
@@ -1,345 +0,0 @@
-/* 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/config.h.in~ b/config.h.in~
deleted file mode 100644
index 7031bde7..00000000
--- a/config.h.in~
+++ /dev/null
@@ -1,1013 +0,0 @@
-/* config.h -- Configuration file for bash. */
-
-/* Copyright (C) 1987-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. */
-
-#ifndef _CONFIG_H_
-#define _CONFIG_H_
-
-/* Configuration feature settings controllable by autoconf. */
-
-/* Define JOB_CONTROL if your operating system supports
- BSD-like job control. */
-#undef JOB_CONTROL
-
-/* Define ALIAS if you want the alias features. */
-#undef ALIAS
-
-/* Define PUSHD_AND_POPD if you want those commands to be compiled in.
- (Also the `dirs' commands.) */
-#undef PUSHD_AND_POPD
-
-/* Define BRACE_EXPANSION if you want curly brace expansion a la Csh:
- foo{a,b} -> fooa foob. Even if this is compiled in (the default) you
- can turn it off at shell startup with `-nobraceexpansion', or during
- shell execution with `set +o braceexpand'. */
-#undef BRACE_EXPANSION
-
-/* Define READLINE to get the nifty/glitzy editing features.
- This is on by default. You can turn it off interactively
- with the -nolineediting flag. */
-#undef READLINE
-
-/* Define BANG_HISTORY if you want to have Csh style "!" history expansion.
- This is unrelated to READLINE. */
-#undef BANG_HISTORY
-
-/* Define HISTORY if you want to have access to previously typed commands.
-
- If both HISTORY and READLINE are defined, you can get at the commands
- with line editing commands, and you can directly manipulate the history
- from the command line.
-
- If only HISTORY is defined, the `fc' and `history' builtins are
- available. */
-#undef HISTORY
-
-/* Define this if you want completion that puts all alternatives into
- a brace expansion shell expression. */
-#if defined (BRACE_EXPANSION) && defined (READLINE)
-# define BRACE_COMPLETION
-#endif /* BRACE_EXPANSION */
-
-/* Define DEFAULT_ECHO_TO_XPG if you want the echo builtin to interpret
- the backslash-escape characters by default, like the XPG Single Unix
- Specification V2 for echo.
- This requires that V9_ECHO be defined. */
-#undef DEFAULT_ECHO_TO_XPG
-
-/* Define HELP_BUILTIN if you want the `help' shell builtin and the long
- documentation strings compiled into the shell. */
-#undef HELP_BUILTIN
-
-/* Define RESTRICTED_SHELL if you want the generated shell to have the
- ability to be a restricted one. The shell thus generated can become
- restricted by being run with the name "rbash", or by setting the -r
- flag. */
-#undef RESTRICTED_SHELL
-
-/* Define DISABLED_BUILTINS if you want "builtin foo" to always run the
- shell builtin "foo", even if it has been disabled with "enable -n foo". */
-#undef DISABLED_BUILTINS
-
-/* Define PROCESS_SUBSTITUTION if you want the K*rn shell-like process
- substitution features "<(file)". */
-/* Right now, you cannot do this on machines without fully operational
- FIFO support. This currently include NeXT and Alliant. */
-#undef PROCESS_SUBSTITUTION
-
-/* Define PROMPT_STRING_DECODE if you want the backslash-escaped special
- characters in PS1 and PS2 expanded. Variable expansion will still be
- performed. */
-#undef PROMPT_STRING_DECODE
-
-/* Define SELECT_COMMAND if you want the Korn-shell style `select' command:
- select word in word_list; do command_list; done */
-#undef SELECT_COMMAND
-
-/* Define COMMAND_TIMING of you want the ksh-style `time' reserved word and
- the ability to time pipelines, functions, and builtins. */
-#undef COMMAND_TIMING
-
-/* Define ARRAY_VARS if you want ksh-style one-dimensional array variables. */
-#undef ARRAY_VARS
-
-/* Define DPAREN_ARITHMETIC if you want the ksh-style ((...)) arithmetic
- evaluation command. */
-#undef DPAREN_ARITHMETIC
-
-/* Define EXTENDED_GLOB if you want the ksh-style [*+@?!](patlist) extended
- pattern matching. */
-#undef EXTENDED_GLOB
-
-/* Define COND_COMMAND if you want the ksh-style [[...]] conditional
- command. */
-#undef COND_COMMAND
-
-/* Define COND_REGEXP if you want extended regular expression matching and the
- =~ binary operator in the [[...]] conditional command. */
-#define COND_REGEXP
-
-/* Define ARITH_FOR_COMMAND if you want the ksh93-style
- for (( init; test; step )) do list; done
- arithmetic for command. */
-#undef ARITH_FOR_COMMAND
-
-/* Define NETWORK_REDIRECTIONS if you want /dev/(tcp|udp)/host/port to open
- socket connections when used in redirections */
-#undef NETWORK_REDIRECTIONS
-
-/* Define PROGRAMMABLE_COMPLETION for the programmable completion features
- and the complete builtin. */
-#undef PROGRAMMABLE_COMPLETION
-
-/* Define NO_MULTIBYTE_SUPPORT to not compile in support for multibyte
- characters, even if the OS supports them. */
-#undef NO_MULTIBYTE_SUPPORT
-
-/* Define DEBUGGER if you want to compile in some features used only by the
- bash debugger. */
-#undef DEBUGGER
-
-/* Define STRICT_POSIX if you want bash to be strictly posix.2 conformant by
- default (except for echo; that is controlled separately). */
-#undef STRICT_POSIX
-
-/* Define MEMSCRAMBLE if you want the bash malloc and free to scramble
- memory contents on malloc() and free(). */
-#undef MEMSCRAMBLE
-
-/* Define AFS if you are using Transarc's AFS. */
-#undef AFS
-
-#undef ENABLE_NLS
-
-/* End of configuration settings controllable by autoconf. */
-/* Other settable options appear in config-top.h. */
-
-#include "config-top.h"
-
-/* Beginning of autoconf additions. */
-
-/* Characteristics of the C compiler */
-#undef const
-
-#undef inline
-
-/* Define if cpp supports the ANSI-C stringizing `#' operator */
-#undef HAVE_STRINGIZE
-
-/* Define if the compiler supports `long double' variables. */
-#undef HAVE_LONG_DOUBLE
-
-#undef PROTOTYPES
-
-#undef __CHAR_UNSIGNED__
-
-/* Define if the compiler supports `long long' variables. */
-#undef HAVE_LONG_LONG
-
-#undef HAVE_UNSIGNED_LONG_LONG
-
-/* The number of bytes in a int. */
-#undef SIZEOF_INT
-
-/* The number of bytes in a long. */
-#undef SIZEOF_LONG
-
-/* The number of bytes in a pointer to char. */
-#undef SIZEOF_CHAR_P
-
-/* The number of bytes in a double (hopefully 8). */
-#undef SIZEOF_DOUBLE
-
-/* The number of bytes in a `long long', if we have one. */
-#undef SIZEOF_LONG_LONG
-
-/* System paths */
-
-#define DEFAULT_MAIL_DIRECTORY "/usr/spool/mail"
-
-/* Characteristics of the system's header files and libraries that affect
- the compilation environment. */
-
-/* Define if the system does not provide POSIX.1 features except
- with this defined. */
-#undef _POSIX_1_SOURCE
-
-/* Define if you need to in order for stat and other things to work. */
-#undef _POSIX_SOURCE
-
-/* Define to use GNU libc extensions */
-#undef _GNU_SOURCE
-
-/* Define if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Memory management functions. */
-
-/* Define if using the bash version of malloc in lib/malloc/malloc.c */
-#undef USING_BASH_MALLOC
-
-#undef DISABLE_MALLOC_WRAPPERS
-
-/* Define if using alloca.c. */
-#undef C_ALLOCA
-
-/* 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
-
-/* Define if you have alloca, as a function or macro. */
-#undef HAVE_ALLOCA
-
-/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
-#undef HAVE_ALLOCA_H
-
-
-/* SYSTEM TYPES */
-
-/* Define to `long' if <sys/types.h> doesn't define. */
-#undef off_t
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef mode_t
-
-/* Define to `int' if <signal.h> doesn't define. */
-#undef sigset_t
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef pid_t
-
-/* Define to `short' if <sys/types.h> doesn't define. */
-#undef bits16_t
-
-/* Define to `unsigned short' if <sys/types.h> doesn't define. */
-#undef u_bits16_t
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef bits32_t
-
-/* Define to `unsigned int' if <sys/types.h> doesn't define. */
-#undef u_bits32_t
-
-/* Define to `double' if <sys/types.h> doesn't define. */
-#undef bits64_t
-
-/* Define to `unsigned int' if <sys/types.h> doesn't define. */
-#undef u_int
-
-/* Define to `unsigned long' if <sys/types.h> doesn't define. */
-#undef u_long
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef ptrdiff_t
-
-/* Define to `unsigned' if <sys/types.h> doesn't define. */
-#undef size_t
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef ssize_t
-
-/* Define to `long' if <stdint.h> doesn't define. */
-#undef intmax_t
-
-/* Define to `unsigned long' if <stdint.h> doesn't define. */
-#undef uintmax_t
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef uid_t
-
-/* Define to `long' if <sys/types.h> doesn't define. */
-#undef clock_t
-
-/* Define to `long' if <sys/types.h> doesn't define. */
-#undef time_t
-
-/* Define to `int' if <sys/types.h> doesn't define. */
-#undef gid_t
-
-/* Define to `unsigned int' if <sys/socket.h> doesn't define. */
-#undef socklen_t
-
-/* Define if you have quad_t in <sys/types.h>. */
-#undef HAVE_QUAD_T
-
-#undef RLIMTYPE
-
-/* Define to the type of elements in the array set by `getgroups'.
- Usually this is either `int' or `gid_t'. */
-#undef GETGROUPS_T
-
-/* Characteristics of the machine archictecture. */
-
-/* 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
-
-/* Define if the machine architecture is big-endian. */
-#undef WORDS_BIGENDIAN
-
-/* Check for the presence of certain non-function symbols in the system
- libraries. */
-
-/* Define if `sys_siglist' is declared by <signal.h> or <unistd.h>. */
-#undef HAVE_DECL_SYS_SIGLIST
-#undef SYS_SIGLIST_DECLARED
-
-/* Define if `_sys_siglist' is declared by <signal.h> or <unistd.h>. */
-#undef UNDER_SYS_SIGLIST_DECLARED
-
-#undef HAVE_SYS_SIGLIST
-
-#undef HAVE_UNDER_SYS_SIGLIST
-
-#undef HAVE_SYS_ERRLIST
-
-#undef HAVE_TZNAME
-
-
-/* Characteristics of some of the system structures. */
-
-#undef HAVE_STRUCT_DIRENT_D_INO
-
-#undef HAVE_STRUCT_DIRENT_D_FILENO
-
-#undef HAVE_STRUCT_DIRENT_D_NAMLEN
-
-#undef TIOCSTAT_IN_SYS_IOCTL
-
-#undef FIONREAD_IN_SYS_IOCTL
-
-#undef GWINSZ_IN_SYS_IOCTL
-
-#undef STRUCT_WINSIZE_IN_SYS_IOCTL
-
-#undef TM_IN_SYS_TIME
-
-#undef STRUCT_WINSIZE_IN_TERMIOS
-
-#undef SPEED_T_IN_SYS_TYPES
-
-#undef TERMIOS_LDISC
-
-#undef TERMIO_LDISC
-
-#undef HAVE_STRUCT_STAT_ST_BLOCKS
-
-#undef HAVE_STRUCT_TM_TM_ZONE
-#undef HAVE_TM_ZONE
-
-#undef HAVE_TIMEVAL
-
-#undef HAVE_STRUCT_TIMEZONE
-
-/* Characteristics of definitions in the system header files. */
-
-#undef HAVE_GETPW_DECLS
-
-#undef HAVE_RESOURCE
-
-#undef HAVE_LIBC_FNM_EXTMATCH
-
-#undef HAVE_DECL_CONFSTR
-
-#undef HAVE_DECL_PRINTF
-
-#undef HAVE_DECL_SBRK
-
-#undef HAVE_DECL_STRCPY
-
-#undef HAVE_DECL_STRSIGNAL
-
-#undef HAVE_DECL_STRTOLD
-
-#undef STRTOLD_BROKEN
-
-#undef HAVE_MBSTATE_T
-
-/* Define if WCONTINUED is defined in system headers, but rejected by waitpid */
-#undef WCONTINUED_BROKEN
-
-/* These are checked with BASH_CHECK_DECL */
-
-#undef HAVE_DECL_STRTOIMAX
-#undef HAVE_DECL_STRTOL
-#undef HAVE_DECL_STRTOLL
-#undef HAVE_DECL_STRTOUL
-#undef HAVE_DECL_STRTOULL
-#undef HAVE_DECL_STRTOUMAX
-
-/* Characteristics of system calls and C library functions. */
-
-/* Define if the `getpgrp' function takes no argument. */
-#undef GETPGRP_VOID
-
-#undef NAMED_PIPES_MISSING
-
-#undef OPENDIR_NOT_ROBUST
-
-#undef PGRP_PIPE
-
-/* Define 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
-
-#undef STAT_MACROS_BROKEN
-
-#undef ULIMIT_MAXFDS
-
-#undef CAN_REDEFINE_GETENV
-
-#undef HAVE_STD_PUTENV
-
-#undef HAVE_STD_UNSETENV
-
-#undef HAVE_PRINTF_A_FORMAT
-
-#undef CTYPE_NON_ASCII
-
-/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
-#undef HAVE_LANGINFO_CODESET
-
-/* Characteristics of properties exported by the kernel. */
-
-/* Define if the kernel can exec files beginning with #! */
-#undef HAVE_HASH_BANG_EXEC
-
-/* Define if you have the /dev/fd devices to map open files into the file system. */
-#undef HAVE_DEV_FD
-
-/* Defined to /dev/fd or /proc/self/fd (linux). */
-#undef DEV_FD_PREFIX
-
-/* Define if you have the /dev/stdin device. */
-#undef HAVE_DEV_STDIN
-
-
-/* Type and behavior of signal handling functions. */
-
-/* Define as the return type of signal handlers (int or void). */
-#undef RETSIGTYPE
-
-/* Define if return type of signal handlers is void */
-#undef VOID_SIGHANDLER
-
-#undef MUST_REINSTALL_SIGHANDLERS
-
-#undef HAVE_BSD_SIGNALS
-
-#undef HAVE_POSIX_SIGNALS
-
-#undef HAVE_USG_SIGHOLD
-
-#undef UNUSABLE_RT_SIGNALS
-
-
-/* Presence of system and C library functions. */
-
-/* Define if you have the asprintf function. */
-#undef HAVE_ASPRINTF
-
-/* Define if you have the bcopy function. */
-#undef HAVE_BCOPY
-
-/* Define if you have the bzero function. */
-#undef HAVE_BZERO
-
-/* Define if you have the confstr function. */
-#undef HAVE_CONFSTR
-
-/* Define if you have the dlclose function. */
-#undef HAVE_DLCLOSE
-
-/* Define if you have the dlopen function. */
-#undef HAVE_DLOPEN
-
-/* Define if you have the dlsym function. */
-#undef HAVE_DLSYM
-
-/* Define if you don't have vprintf but do have _doprnt. */
-#undef HAVE_DOPRNT
-
-/* Define if you have the dup2 function. */
-#undef HAVE_DUP2
-
-/* Define if you have the fcntl function. */
-#undef HAVE_FCNTL
-
-/* Define if you have the getaddrinfo function. */
-#undef HAVE_GETADDRINFO
-
-/* Define if you have the getcwd function. */
-#undef HAVE_GETCWD
-
-/* Define if you have the getdtablesize function. */
-#undef HAVE_GETDTABLESIZE
-
-/* Define if you have the getgroups function. */
-#undef HAVE_GETGROUPS
-
-/* Define if you have the gethostbyname function. */
-#undef HAVE_GETHOSTBYNAME
-
-/* Define if you have the gethostname function. */
-#undef HAVE_GETHOSTNAME
-
-/* Define if you have the getpagesize function. */
-#undef HAVE_GETPAGESIZE
-
-/* Define if you have the getpeername function. */
-#undef HAVE_GETPEERNAME
-
-/* Define if you have the getpwent function. */
-#undef HAVE_GETPWENT
-
-/* Define if you have the getpwnam function. */
-#undef HAVE_GETPWNAM
-
-/* Define if you have the getpwuid function. */
-#undef HAVE_GETPWUID
-
-/* Define if you have the getrlimit function. */
-#undef HAVE_GETRLIMIT
-
-/* Define if you have the getrusage function. */
-#undef HAVE_GETRUSAGE
-
-/* Define if you have the getservbyname function. */
-#undef HAVE_GETSERVBYNAME
-
-/* Define if you have the getservent function. */
-#undef HAVE_GETSERVENT
-
-/* Define if you have the gettimeofday function. */
-#undef HAVE_GETTIMEOFDAY
-
-/* Define if you have the getwd function. */
-#undef HAVE_GETWD
-
-/* Define if you have the inet_aton function. */
-#undef HAVE_INET_ATON
-
-/* Define if you have the isascii function. */
-#undef HAVE_ISASCII
-
-/* Define if you have the isblank function. */
-#undef HAVE_ISBLANK
-
-/* Define if you have the isgraph function. */
-#undef HAVE_ISGRAPH
-
-/* Define if you have the isint function in libc */
-#undef HAVE_ISINF_IN_LIBC
-
-/* Define if you have the isprint function. */
-#undef HAVE_ISPRINT
-
-/* Define if you have the isspace function. */
-#undef HAVE_ISSPACE
-
-/* Define if you have the isxdigit function. */
-#undef HAVE_ISXDIGIT
-
-/* Define if you have the kill function. */
-#undef HAVE_KILL
-
-/* Define if you have the killpg function. */
-#undef HAVE_KILLPG
-
-/* Define if you have the lstat function. */
-#undef HAVE_LSTAT
-
-/* Define if you have the mbrlen function. */
-#undef HAVE_MBRLEN
-
-/* Define if you have the mbrtowc function. */
-#undef HAVE_MBRTOWC
-
-/* Define if you have the mbsrtowcs function. */
-#undef HAVE_MBSRTOWCS
-
-/* Define if you have the memmove function. */
-#undef HAVE_MEMMOVE
-
-/* Define if you have the memset function. */
-#undef HAVE_MEMSET
-
-/* Define if you have the mkfifo function. */
-#undef HAVE_MKFIFO
-
-/* Define if you have the pathconf function. */
-#undef HAVE_PATHCONF
-
-/* Define if you have the putenv function. */
-#undef HAVE_PUTENV
-
-/* Define if you have the raise function. */
-#undef HAVE_RAISE
-
-/* Define if you have the readlink function. */
-#undef HAVE_READLINK
-
-/* Define if you have the regcomp function. */
-#undef HAVE_REGCOMP
-
-/* Define if you have the regexec function. */
-#undef HAVE_REGEXEC
-
-/* Define if you have the rename function. */
-#undef HAVE_RENAME
-
-/* Define if you have the sbrk function. */
-#undef HAVE_SBRK
-
-/* Define if you have the select function. */
-#undef HAVE_SELECT
-
-/* Define if you have the setdtablesize function. */
-#undef HAVE_SETDTABLESIZE
-
-/* Define if you have the setenv function. */
-#undef HAVE_SETENV
-
-/* Define if you have the setlinebuf function. */
-#undef HAVE_SETLINEBUF
-
-/* Define if you have the setlocale function. */
-#undef HAVE_SETLOCALE
-
-/* Define if you have the setostype function. */
-#undef HAVE_SETOSTYPE
-
-/* Define if you have the setregid function. */
-#undef HAVE_SETREGID
-#undef HAVE_DECL_SETREGID
-
-/* Define if you have the setvbuf function. */
-#undef HAVE_SETVBUF
-
-/* Define if you have the siginterrupt function. */
-#undef HAVE_SIGINTERRUPT
-
-/* Define if you have the POSIX.1-style sigsetjmp function. */
-#undef HAVE_POSIX_SIGSETJMP
-
-/* Define if you have the snprintf function. */
-#undef HAVE_SNPRINTF
-
-/* Define if you have the strcasecmp function. */
-#undef HAVE_STRCASECMP
-
-/* Define if you have the strchr function. */
-#undef HAVE_STRCHR
-
-/* Define if you have the strcoll function. */
-#undef HAVE_STRCOLL
-
-/* Define if you have the strerror function. */
-#undef HAVE_STRERROR
-
-/* Define if you have the strftime function. */
-#undef HAVE_STRFTIME
-
-/* Define if you have the strnlen function. */
-#undef HAVE_STRNLEN
-
-/* Define if you have the strpbrk function. */
-#undef HAVE_STRPBRK
-
-/* Define if you have the strstr function. */
-#undef HAVE_STRSTR
-
-/* Define if you have the strtod function. */
-#undef HAVE_STRTOD
-
-/* Define if you have the strtoimax function. */
-#undef HAVE_STRTOIMAX
-
-/* Define if you have the strtol function. */
-#undef HAVE_STRTOL
-
-/* Define if you have the strtoll function. */
-#undef HAVE_STRTOLL
-
-/* Define if you have the strtoul function. */
-#undef HAVE_STRTOUL
-
-/* Define if you have the strtoull function. */
-#undef HAVE_STRTOULL
-
-/* Define if you have the strtoumax function. */
-#undef HAVE_STRTOUMAX
-
-/* Define if you have the strsignal function or macro. */
-#undef HAVE_STRSIGNAL
-
-/* Define if you have the sysconf function. */
-#undef HAVE_SYSCONF
-
-/* Define if you have the tcgetattr function. */
-#undef HAVE_TCGETATTR
-
-/* Define if you have the tcgetpgrp function. */
-#undef HAVE_TCGETPGRP
-
-/* Define if you have the times function. */
-#undef HAVE_TIMES
-
-/* Define if you have the ttyname function. */
-#undef HAVE_TTYNAME
-
-/* Define if you have the tzset function. */
-#undef HAVE_TZSET
-
-/* Define if you have the ulimit function. */
-#undef HAVE_ULIMIT
-
-/* Define if you have the uname function. */
-#undef HAVE_UNAME
-
-/* Define if you have the unsetenv function. */
-#undef HAVE_UNSETENV
-
-/* Define if you have the vasprintf function. */
-#undef HAVE_VASPRINTF
-
-/* Define if you have the vprintf function. */
-#undef HAVE_VPRINTF
-
-/* Define if you have the vsnprintf function. */
-#undef HAVE_VSNPRINTF
-
-/* Define if you have the waitpid function. */
-#undef HAVE_WAITPID
-
-/* Define if you have the wait3 function. */
-#undef HAVE_WAIT3
-
-/* Define if you have the wcsdup function. */
-#undef HAVE_WCSDUP
-
-/* Define if you have the wctomb function. */
-#undef HAVE_WCTOMB
-
-/* Define if you have the wctype function. */
-#undef HAVE_WCTYPE
-
-/* Define if you have the wcwidth function. */
-#undef HAVE_WCWIDTH
-
-/* Presence of certain system include files. */
-
-/* Define if you have the <arpa/inet.h> header file. */
-#undef HAVE_ARPA_INET_H
-
-/* Define if you have the <dirent.h> header file. */
-#undef HAVE_DIRENT_H
-
-/* Define if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define if you have the <grp.h> header file. */
-#undef HAVE_GRP_H
-
-/* Define if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* Define if you have the <langinfo.h> header file. */
-#undef HAVE_LANGINFO_H
-
-/* Define if you have the <libintl.h> header file. */
-#undef HAVE_LIBINTL_H
-
-/* Define if you have the <limits.h> header file. */
-#undef HAVE_LIMITS_H
-
-/* Define if you have the <locale.h> header file. */
-#undef HAVE_LOCALE_H
-
-/* Define if you have the <ndir.h> header file. */
-#undef HAVE_NDIR_H
-
-/* Define if you have the <netdh.h> header file. */
-#undef HAVE_NETDB_H
-
-/* Define if you have the <netinet/in.h> header file. */
-#undef HAVE_NETINET_IN_H
-
-/* Define if you have the <pwd.h> header file. */
-#undef HAVE_PWD_H
-
-/* Define if you have the <regex.h> header file. */
-#undef HAVE_REGEX_H
-
-/* Define if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define if you have the <stdarg.h> header file. */
-#undef HAVE_STDARG_H
-
-/* Define if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define if you have the <stddef.h> header file. */
-#undef HAVE_STDDEF_H
-
-/* Define if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define if you have the <sys/dir.h> header file. */
-#undef HAVE_SYS_DIR_H
-
-/* Define if you have the <sys/file.h> header file. */
-#undef HAVE_SYS_FILE_H
-
-/* Define if you have the <sys/ndir.h> header file. */
-#undef HAVE_SYS_NDIR_H
-
-/* Define if you have the <sys/param.h> header file. */
-#undef HAVE_SYS_PARAM_H
-
-/* Define if you have the <sys/pte.h> header file. */
-#undef HAVE_SYS_PTE_H
-
-/* Define if you have the <sys/ptem.h> header file. */
-#undef HAVE_SYS_PTEM_H
-
-/* Define if you have the <sys/resource.h> header file. */
-#undef HAVE_SYS_RESOURCE_H
-
-/* Define if you have the <sys/select.h> header file. */
-#undef HAVE_SYS_SELECT_H
-
-/* Define if you have the <sys/socket.h> header file. */
-#undef HAVE_SYS_SOCKET_H
-
-/* Define if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define if you have the <sys/stream.h> header file. */
-#undef HAVE_SYS_STREAM_H
-
-/* Define if you have <sys/time.h> */
-#undef HAVE_SYS_TIME_H
-
-#undef TIME_WITH_SYS_TIME
-
-/* Define if you have <sys/times.h> */
-#undef HAVE_SYS_TIMES_H
-
-/* Define if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
-#undef HAVE_SYS_WAIT_H
-
-/* Define if you have the <termcap.h> header file. */
-#undef HAVE_TERMCAP_H
-
-/* Define if you have the <termio.h> header file. */
-#undef HAVE_TERMIO_H
-
-/* Define if you have the <termios.h> header file. */
-#undef HAVE_TERMIOS_H
-
-/* Define if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define if you have the <varargs.h> header file. */
-#undef HAVE_VARARGS_H
-
-/* Define if you have the <wchar.h> header file. */
-#undef HAVE_WCHAR_H
-
-/* Define if you have the <varargs.h> header file. */
-#undef HAVE_WCTYPE_H
-
-/* Presence of certain system libraries. */
-
-#undef HAVE_LIBDL
-
-#undef HAVE_LIBSUN
-
-#undef HAVE_LIBSOCKET
-
-
-/* Define if on MINIX. */
-#undef _MINIX
-
-/* Are we running SVR5 (UnixWare 7)? */
-#undef SVR5
-
-/* Are we running SVR4.2? */
-#undef SVR4_2
-
-/* Are we running some version of SVR4? */
-#undef SVR4
-
-/* Define if job control is unusable or unsupported. */
-#undef JOB_CONTROL_MISSING
-
-/* Do we need to define _KERNEL to get the RLIMIT_* defines from
- <sys/resource.h>? */
-#undef RLIMIT_NEEDS_KERNEL
-
-/* Number of bits in a file offset, on hosts where this is settable. */
-#undef _FILE_OFFSET_BITS
-
-/* Define for large files on AIX-style hosts. */
-#undef _LARGE_FILES
-
-/* Do strcoll(3) and strcmp(3) give different results in the default locale? */
-#undef STRCOLL_BROKEN
-
-#undef DUP2_BROKEN
-
-#undef GETCWD_BROKEN
-
-/* Additional defines for configuring lib/intl, maintained by autoscan/autoheader */
-
-/* Define if you have the <argz.h> header file. */
-#undef HAVE_ARGZ_H
-
-/* Define if you have the <errno.h> header file. */
-#undef HAVE_ERRNO_H
-
-/* Define if you have the <fcntl.h> header file. */
-#undef HAVE_FCNTL_H
-
-/* Define if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
-
-/* Define if you have the <stdio_ext.h> header file. */
-#undef HAVE_STDIO_EXT_H
-
-/* Define if you have the `dcgettext' function. */
-#undef HAVE_DCGETTEXT
-
-/* Define if your system has a working `malloc' function. */
-/* #undef HAVE_MALLOC */
-
-/* Define if you have the `mempcpy' function. */
-#undef HAVE_MEMPCPY
-
-/* Define if you have a working `mmap' system call. */
-#undef HAVE_MMAP
-
-/* Define if you have the `munmap' function. */
-#undef HAVE_MUNMAP
-
-/* Define if you have the `nl_langinfo' function. */
-#undef HAVE_NL_LANGINFO
-
-/* Define if you have the `stpcpy' function. */
-#undef HAVE_STPCPY
-
-/* Define if you have the `strcspn' function. */
-#undef HAVE_STRCSPN
-
-/* Define if you have the `strdup' function. */
-#undef HAVE_STRDUP
-
-/* Define if you have the `__argz_count' function. */
-#undef HAVE___ARGZ_COUNT
-
-/* Define if you have the `__argz_next' function. */
-#undef HAVE___ARGZ_NEXT
-
-/* Define if you have the `__argz_stringify' function. */
-#undef HAVE___ARGZ_STRINGIFY
-
-/* End additions for lib/intl */
-
-#include "config-bot.h"
-
-#endif /* _CONFIG_H_ */
diff --git a/configure.in~ b/configure.in~
deleted file mode 100644
index c3681653..00000000
--- a/configure.in~
+++ /dev/null
@@ -1,1111 +0,0 @@
-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-2006 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.190])dnl
-
-define(bashvers, 3.2)
-define(relstatus, beta)
-
-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)
-
-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.
-
-CROSS_COMPILE=
-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)
-
-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))
-AC_CHECK_FUNC(isnan, AC_DEFINE(HAVE_ISNAN_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 eaccess 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([setregid])
-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/cross-build/cygwin32.cache.old b/cross-build/cygwin32.cache.old
deleted file mode 100644
index 640390fb..00000000
--- a/cross-build/cygwin32.cache.old
+++ /dev/null
@@ -1,42 +0,0 @@
-# This file is a shell script that caches the results of configure
-# tests for CYGWIN32 so they don't need to be done when cross-compiling.
-
-# AC_FUNC_GETPGRP should also define GETPGRP_VOID
-ac_cv_func_getpgrp_void=${ac_cv_func_getpgrp_void='yes'}
-# AC_FUNC_SETVBUF_REVERSED should not define anything else
-ac_cv_func_setvbuf_reversed=${ac_cv_func_setvbuf_reversed='no'}
-# on CYGWIN32, system calls do not restart
-ac_cv_sys_restartable_syscalls=${ac_cv_sys_restartable_syscalls='no'}
-bash_cv_sys_restartable_syscalls=${bash_cv_sys_restartable_syscalls='no'}
-
-# these may be necessary, but they are currently commented out
-#ac_cv_c_bigendian=${ac_cv_c_bigendian='no'}
-ac_cv_sizeof_char_p=${ac_cv_sizeof_char_p='4'}
-ac_cv_sizeof_int=${ac_cv_sizeof_int='4'}
-ac_cv_sizeof_long=${ac_cv_sizeof_long='4'}
-ac_cv_sizeof_double=${ac_cv_sizeof_double='8'}
-
-bash_cv_dup2_broken=${bash_cv_dup2_broken='no'}
-bash_cv_pgrp_pipe=${bash_cv_pgrp_pipe='no'}
-bash_cv_type_rlimit=${bash_cv_type_rlimit='long'}
-bash_cv_decl_under_sys_siglist=${bash_cv_decl_under_sys_siglist='no'}
-bash_cv_under_sys_siglist=${bash_cv_under_sys_siglist='no'}
-bash_cv_sys_siglist=${bash_cv_sys_siglist='no'}
-bash_cv_opendir_not_robust=${bash_cv_opendir_not_robust='no'}
-bash_cv_getenv_redef=${bash_cv_getenv_redef='yes'}
-bash_cv_printf_declared=${bash_cv_printf_declared='yes'}
-bash_cv_ulimit_maxfds=${bash_cv_ulimit_maxfds='no'}
-bash_cv_getcwd_calls_popen=${bash_cv_getcwd_calls_popen='no'}
-bash_cv_must_reinstall_sighandlers=${bash_cv_must_reinstall_sighandlers='no'}
-bash_cv_job_control_missing=${bash_cv_job_control_missing='present'}
-bash_cv_sys_named_pipes=${bash_cv_sys_named_pipes='missing'}
-bash_cv_func_sigsetjmp=${bash_cv_func_sigsetjmp='missing'}
-bash_cv_mail_dir=${bash_cv_mail_dir='unknown'}
-bash_cv_func_strcoll_broken=${bash_cv_func_strcoll_broken='no'}
-
-bash_cv_type_int32_t=${bash_cv_type_int32_t='int'}
-bash_cv_type_u_int32_t=${bash_cv_type_u_int32_t='int'}
-
-ac_cv_type_bits64_t=${ac_cv_type_bits64_t='no'}
-
-# end of cross-build/cygwin32.cache
diff --git a/dd~ b/dd~
deleted file mode 100644
index 9f4e2d00..00000000
--- a/dd~
+++ /dev/null
@@ -1,152 +0,0 @@
-*** ../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.orig b/doc/FAQ.orig
deleted file mode 100644
index 1cff3c8e..00000000
--- a/doc/FAQ.orig
+++ /dev/null
@@ -1,1745 +0,0 @@
-This is the Bash FAQ, version 3.24, for Bash version 2.05b.
-
-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 1003.2 standard'?
-A10) What is the bash `posix mode'?
-
-Section B: The latest version
-
-B1) What's new in version 2.05b?
-B2) Are there any user-visible incompatibilities between bash-2.05b and
- bash-1.14.7?
-
-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?
-
-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 2.05b, first made available on Wednesday, 17
-July, 2002.
-
-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 2.05b:
-
-ftp://ftp.gnu.org/pub/gnu/bash/bash-2.05b.tar.gz
-ftp://ftp.cwru.edu/pub/bash/bash-2.05b.tar.gz
-
-Formatted versions of the documentation are available with the URLs:
-
-ftp://ftp.gnu.org/pub/gnu/bash/bash-doc-2.05b.tar.gz
-ftp://ftp.cwru.edu/pub/bash/bash-doc-2.05b.tar.gz
-
-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 as part of their CYGWIN
-project. For more information about the project, look at the URLs
-
-http://www.cygwin.com/
-http://sourceware.cygnus.com/cygwin
-
-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 a
-port of bash-2.05 to the CYGWIN environment, and it is available as
-part of their current release.
-
-Bash-2.05b should require no local Cygnus changes to build and run under
-CYGWIN.
-
-The Cygnus port works only on Intel machines. There is a port of bash
-(I don't know which version) to the alpha/NT environment available from
-
-ftp://ftp.gnustep.org//pub/win32/bash-alpha-nt-1.01.tar.gz
-
-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 has begun to work with bash-2.05, but I don't know the status.
-
-Ports of bash-1.12 and bash-2.0 are available for OS/2 from
-
-ftp://hobbes.nmsu.edu/pub/os2/util/shell/bash_112.zip
-ftp://hobbes.nmsu.edu/pub/os2/util/shell/bash-2.0(253).zip
-
-I haven't looked at either, but the second appears to be a binary-only
-distribution. Beware.
-
-I have received word that Bash (I'm not sure which version, but I
-believe that it's at least bash-2.02.1) is the standard shell on
-BeOS.
-
-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 1003.2 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 has been developed by IEEE
-Working Group 1003.2 (POSIX.2). It concentrates on the command
-interpreter interface and utility programs commonly executed from
-the command line or by other programs. An initial version of the
-standard has been approved and published by the IEEE, and work is
-currently underway to update it.
-
-Bash is concerned with the aspects of the shell's behavior
-defined by POSIX.2. 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.2 not
-devoted to the shell which are commonly (and in some cases must
-be) implemented as builtin commands, such as `read' and `test'.
-POSIX.2 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 Open Group has made an older version of its Single Unix
-Specification (version 2), which is very similar to POSIX.2,
-available on the web at
-
-http://www.opengroup.org/onlinepubs/007908799/
-
-The Single Unix Specification, version 3, is available on the web at
-
-http://www.opengroup.org/onlinepubs/007904975/
-
-A10) What is the bash `posix mode'?
-
-Although bash is an implementation of the POSIX.2 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 2.05b?
-
-The raison d'etre for bash-2.05b is to make a second intermediate
-release containing the first of the new features to be available
-in bash-3.0 and get feedback on those features before proceeding.
-The major new feature is multibyte character support in both Bash
-and Readline.
-
-Bash-2.05b contains the following new features (see the manual page for
-complete descriptions and the CHANGES and NEWS files in the bash-2.05b
-distribution):
-
-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
-
-
-A short feature history dating from Bash-2.0:
-
-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-2.05b and
- bash-1.14.7?
-
-There are a few incompatibilities between version 1.14.7 and version 2.05b.
-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 -m/-p/-u,
- 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
- redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr,
- /dev/tcp/host/port, /dev/udp/host/port
-
-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 -u, 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'
-
-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, fc -e -, newgrp, print,
- read -p/-s/var?prompt, set -A/-o gmacs/
- -o bgnice/-o markdirs/-o nolog/-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-2.05b:
- 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
- set -o pipefail
- `+=' variable assignment operator
- FPATH and PATH mixing
- getopts -a
- -I invocation option
- DEBUG trap now executed before each simple command, instead of after
- 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-2.05b:
- [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
-
-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.
-
-You can build a version of bash that will not report SIGPIPE errors
-by uncommenting the definition of DONT_REPORT_SIGPIPE in the file
-config-top.h.
-
-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 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 drafts of the updated POSIX standard have 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'.
-
-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-2.05a 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
-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.
-
-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.
-
-H3) What's coming in future versions?
-
-These are features I hope to include in a future version of bash.
-
-a better bash debugger (a minimally-tested version is included with bash-2.05b)
-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
-better internationalization using GNU `gettext'
-date-stamped command history
-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 `+=' variable assignment operator
-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 2002. Never make predictions.
-
-
-This document is Copyright 1995-2003 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/FAQ.save b/doc/FAQ.save
deleted file mode 100644
index 1cff3c8e..00000000
--- a/doc/FAQ.save
+++ /dev/null
@@ -1,1745 +0,0 @@
-This is the Bash FAQ, version 3.24, for Bash version 2.05b.
-
-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 1003.2 standard'?
-A10) What is the bash `posix mode'?
-
-Section B: The latest version
-
-B1) What's new in version 2.05b?
-B2) Are there any user-visible incompatibilities between bash-2.05b and
- bash-1.14.7?
-
-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?
-
-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 2.05b, first made available on Wednesday, 17
-July, 2002.
-
-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 2.05b:
-
-ftp://ftp.gnu.org/pub/gnu/bash/bash-2.05b.tar.gz
-ftp://ftp.cwru.edu/pub/bash/bash-2.05b.tar.gz
-
-Formatted versions of the documentation are available with the URLs:
-
-ftp://ftp.gnu.org/pub/gnu/bash/bash-doc-2.05b.tar.gz
-ftp://ftp.cwru.edu/pub/bash/bash-doc-2.05b.tar.gz
-
-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 as part of their CYGWIN
-project. For more information about the project, look at the URLs
-
-http://www.cygwin.com/
-http://sourceware.cygnus.com/cygwin
-
-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 a
-port of bash-2.05 to the CYGWIN environment, and it is available as
-part of their current release.
-
-Bash-2.05b should require no local Cygnus changes to build and run under
-CYGWIN.
-
-The Cygnus port works only on Intel machines. There is a port of bash
-(I don't know which version) to the alpha/NT environment available from
-
-ftp://ftp.gnustep.org//pub/win32/bash-alpha-nt-1.01.tar.gz
-
-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 has begun to work with bash-2.05, but I don't know the status.
-
-Ports of bash-1.12 and bash-2.0 are available for OS/2 from
-
-ftp://hobbes.nmsu.edu/pub/os2/util/shell/bash_112.zip
-ftp://hobbes.nmsu.edu/pub/os2/util/shell/bash-2.0(253).zip
-
-I haven't looked at either, but the second appears to be a binary-only
-distribution. Beware.
-
-I have received word that Bash (I'm not sure which version, but I
-believe that it's at least bash-2.02.1) is the standard shell on
-BeOS.
-
-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 1003.2 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 has been developed by IEEE
-Working Group 1003.2 (POSIX.2). It concentrates on the command
-interpreter interface and utility programs commonly executed from
-the command line or by other programs. An initial version of the
-standard has been approved and published by the IEEE, and work is
-currently underway to update it.
-
-Bash is concerned with the aspects of the shell's behavior
-defined by POSIX.2. 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.2 not
-devoted to the shell which are commonly (and in some cases must
-be) implemented as builtin commands, such as `read' and `test'.
-POSIX.2 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 Open Group has made an older version of its Single Unix
-Specification (version 2), which is very similar to POSIX.2,
-available on the web at
-
-http://www.opengroup.org/onlinepubs/007908799/
-
-The Single Unix Specification, version 3, is available on the web at
-
-http://www.opengroup.org/onlinepubs/007904975/
-
-A10) What is the bash `posix mode'?
-
-Although bash is an implementation of the POSIX.2 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 2.05b?
-
-The raison d'etre for bash-2.05b is to make a second intermediate
-release containing the first of the new features to be available
-in bash-3.0 and get feedback on those features before proceeding.
-The major new feature is multibyte character support in both Bash
-and Readline.
-
-Bash-2.05b contains the following new features (see the manual page for
-complete descriptions and the CHANGES and NEWS files in the bash-2.05b
-distribution):
-
-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
-
-
-A short feature history dating from Bash-2.0:
-
-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-2.05b and
- bash-1.14.7?
-
-There are a few incompatibilities between version 1.14.7 and version 2.05b.
-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 -m/-p/-u,
- 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
- redirection to /dev/fd/N, /dev/stdin, /dev/stdout, /dev/stderr,
- /dev/tcp/host/port, /dev/udp/host/port
-
-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 -u, 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'
-
-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, fc -e -, newgrp, print,
- read -p/-s/var?prompt, set -A/-o gmacs/
- -o bgnice/-o markdirs/-o nolog/-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-2.05b:
- 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
- set -o pipefail
- `+=' variable assignment operator
- FPATH and PATH mixing
- getopts -a
- -I invocation option
- DEBUG trap now executed before each simple command, instead of after
- 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-2.05b:
- [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
-
-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.
-
-You can build a version of bash that will not report SIGPIPE errors
-by uncommenting the definition of DONT_REPORT_SIGPIPE in the file
-config-top.h.
-
-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 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 drafts of the updated POSIX standard have 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'.
-
-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-2.05a 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
-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.
-
-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.
-
-H3) What's coming in future versions?
-
-These are features I hope to include in a future version of bash.
-
-a better bash debugger (a minimally-tested version is included with bash-2.05b)
-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
-better internationalization using GNU `gettext'
-date-stamped command history
-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 `+=' variable assignment operator
-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 2002. Never make predictions.
-
-
-This document is Copyright 1995-2003 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/FAQ~ b/doc/FAQ~
deleted file mode 100644
index 0fa10b5b..00000000
--- a/doc/FAQ~
+++ /dev/null
@@ -1,1803 +0,0 @@
-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.orig b/doc/bash.1.orig
deleted file mode 100644
index 828ec966..00000000
--- a/doc/bash.1.orig
+++ /dev/null
@@ -1,8583 +0,0 @@
-.\"
-.\" MAN PAGE COMMENTS to
-.\"
-.\" Chet Ramey
-.\" Information Network Services
-.\" Case Western Reserve University
-.\" chet@po.CWRU.Edu
-.\"
-.\" Last Change: Mon Apr 14 17:57:24 EDT 2003
-.\"
-.\" bash_builtins, strip all but Built-Ins section
-.if \n(zZ=1 .ig zZ
-.if \n(zY=1 .ig zY
-.TH BASH 1 "2003 April 14" "GNU Bash-3.0"
-.\"
-.\" There's some problem with having a `@'
-.\" in a tagged paragraph with the BSD man macros.
-.\" It has to do with `@' appearing in the }1 macro.
-.\" This is a problem on 4.3 BSD and Ultrix, but Sun
-.\" appears to have fixed it.
-.\" If you're seeing the characters
-.\" `@u-3p' appearing before the lines reading
-.\" `possible-hostname-completions
-.\" and `complete-hostname' down in READLINE,
-.\" then uncomment this redefinition.
-.\"
-.de }1
-.ds ]X \&\\*(]B\\
-.nr )E 0
-.if !"\\$1"" .nr )I \\$1n
-.}f
-.ll \\n(LLu
-.in \\n()Ru+\\n(INu+\\n()Iu
-.ti \\n(INu
-.ie !\\n()Iu+\\n()Ru-\w\\*(]Xu-3p \{\\*(]X
-.br\}
-.el \\*(]X\h|\\n()Iu+\\n()Ru\c
-.}f
-..
-.\"
-.\" File Name macro. This used to be `.PN', for Path Name,
-.\" but Sun doesn't seem to like that very much.
-.\"
-.de FN
-\fI\|\\$1\|\fP
-..
-.SH NAME
-bash \- GNU Bourne-Again SHell
-.SH SYNOPSIS
-.B bash
-[options]
-[file]
-.SH COPYRIGHT
-.if n Bash is Copyright (C) 1989-2002 by the Free Software Foundation, Inc.
-.if t Bash is Copyright \(co 1989-2002 by the Free Software Foundation, Inc.
-.SH DESCRIPTION
-.B Bash
-is an \fBsh\fR-compatible command language interpreter that
-executes commands read from the standard input or from a file.
-.B Bash
-also incorporates useful features from the \fIKorn\fP and \fIC\fP
-shells (\fBksh\fP and \fBcsh\fP).
-.PP
-.B Bash
-is intended to be a conformant implementation of the IEEE
-POSIX Shell and Tools specification (IEEE Working Group 1003\.2).
-.SH OPTIONS
-In addition to the single-character shell options documented in the
-description of the \fBset\fR builtin command, \fBbash\fR
-interprets the following options when it is invoked:
-.PP
-.PD 0
-.TP 10
-.BI \-c "\| string\^"
-If the
-.B \-c
-option is present, then commands are read from
-.IR string .
-If there are arguments after the
-.IR string ,
-they are assigned to the positional parameters, starting with
-.BR $0 .
-.TP
-.B \-i
-If the
-.B \-i
-option is present, the shell is
-.IR interactive .
-.TP
-.B \-l
-Make
-.B bash
-act as if it had been invoked as a login shell (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-r
-If the
-.B \-r
-option is present, the shell becomes
-.I restricted
-(see
-.SM
-.B "RESTRICTED SHELL"
-below).
-.TP
-.B \-s
-If the
-.B \-s
-option is present, or if no arguments remain after option
-processing, then commands are read from the standard input.
-This option allows the positional parameters to be set
-when invoking an interactive shell.
-.TP
-.B \-D
-A list of all double-quoted strings preceded by \fB$\fP
-is printed on the standard ouput.
-These are the strings that
-are subject to language translation when the current locale
-is not \fBC\fP or \fBPOSIX\fP.
-This implies the \fB\-n\fP option; no commands will be executed.
-.TP
-.B [\-+]O [\fIshopt_option\fP]
-\fIshopt_option\fP is one of the shell options accepted by the
-\fBshopt\fP builtin (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-If \fIshopt_option\fP is present, \fB\-O\fP sets the value of that option;
-\fB+O\fP unsets it.
-If \fIshopt_option\fP is not supplied, the names and values of the shell
-options accepted by \fBshopt\fP are printed on the standard output.
-If the invocation option is \fB+O\fP, the output is displayed in a format
-that may be reused as input.
-.TP
-.B \-\-
-A
-.B \-\-
-signals the end of options and disables further option processing.
-Any arguments after the
-.B \-\-
-are treated as filenames and arguments. An argument of
-.B \-
-is equivalent to \fB\-\-\fP.
-.PD
-.PP
-.B Bash
-also interprets a number of multi-character options.
-These options must appear on the command line before the
-single-character options to be recognized.
-.PP
-.PD 0
-.TP
-.B \-\-debugger
-Arrange for the debugger profile to be executed before the shell
-starts. Turns on extended debugging mode (see the description of the
-.B extdebug
-option to the
-.B shopt
-builtin below) and shell function tracing (see the description of the
-\fB\-o functrace\fP option to the
-.B set
-builtin below).
-.TP
-.B \-\-dump\-po\-strings
-Equivalent to \fB\-D\fP, but the output is in the GNU \fIgettext\fP
-\fBpo\fP (portable object) file format.
-.TP
-.B \-\-dump\-strings
-Equivalent to \fB\-D\fP.
-.TP
-.B \-\-help
-Display a usage message on standard output and exit successfully.
-.TP
-\fB\-\-init\-file\fP \fIfile\fP
-.PD 0
-.TP
-\fB\-\-rcfile\fP \fIfile\fP
-.PD
-Execute commands from
-.I file
-instead of the standard personal initialization file
-.I ~/.bashrc
-if the shell is interactive (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-\-login
-Equivalent to \fB\-l\fP.
-.TP
-.B \-\-noediting
-Do not use the GNU
-.B readline
-library to read command lines when the shell is interactive.
-.TP
-.B \-\-noprofile
-Do not read either the system-wide startup file
-.FN /etc/profile
-or any of the personal initialization files
-.IR ~/.bash_profile ,
-.IR ~/.bash_login ,
-or
-.IR ~/.profile .
-By default,
-.B bash
-reads these files when it is invoked as a login shell (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-\-norc
-Do not read and execute the personal initialization file
-.I ~/.bashrc
-if the shell is interactive.
-This option is on by default if the shell is invoked as
-.BR sh .
-.TP
-.B \-\-posix
-Change the behavior of \fBbash\fP where the default operation differs
-from the POSIX 1003.2 standard to match the standard (\fIposix mode\fP).
-.TP
-.B \-\-restricted
-The shell becomes restricted (see
-.SM
-.B "RESTRICTED SHELL"
-below).
-.TP
-.B \-\-verbose
-Equivalent to \fB\-v\fP.
-.TP
-.B \-\-version
-Show version information for this instance of
-.B bash
-on the standard output and exit successfully.
-.PD
-.SH ARGUMENTS
-If arguments remain after option processing, and neither the
-.B \-c
-nor the
-.B \-s
-option has been supplied, the first argument is assumed to
-be the name of a file containing shell commands.
-If
-.B bash
-is invoked in this fashion,
-.B $0
-is set to the name of the file, and the positional parameters
-are set to the remaining arguments.
-.B Bash
-reads and executes commands from this file, then exits.
-\fBBash\fP's exit status is the exit status of the last command
-executed in the script.
-If no commands are executed, the exit status is 0.
-An attempt is first made to open the file in the current directory, and,
-if no file is found, then the shell searches the directories in
-.SM
-.B PATH
-for the script.
-.SH INVOCATION
-A \fIlogin shell\fP is one whose first character of argument zero is a
-.BR \- ,
-or one started with the
-.B \-\-login
-option.
-.PP
-An \fIinteractive\fP shell is one started without non-option arguments
-and without the
-.B \-c
-option
-whose standard input and output are
-both connected to terminals (as determined by
-.IR isatty (3)),
-or one started with the
-.B \-i
-option.
-.SM
-.B PS1
-is set and
-.B $\-
-includes
-.B i
-if
-.B bash
-is interactive,
-allowing a shell script or a startup file to test this state.
-.PP
-The following paragraphs describe how
-.B bash
-executes its startup files.
-If any of the files exist but cannot be read,
-.B bash
-reports an error.
-Tildes are expanded in file names as described below under
-.B "Tilde Expansion"
-in the
-.SM
-.B EXPANSION
-section.
-.PP
-When
-.B bash
-is invoked as an interactive login shell, or as a non-interactive shell
-with the \fB\-\-login\fP option, it first reads and
-executes commands from the file \fI/etc/profile\fP, if that
-file exists.
-After reading that file, it looks for \fI~/.bash_profile\fP,
-\fI~/.bash_login\fP, and \fI~/.profile\fP, in that order, and reads
-and executes commands from the first one that exists and is readable.
-The
-.B \-\-noprofile
-option may be used when the shell is started to inhibit this behavior.
-.PP
-When a login shell exits,
-.B bash
-reads and executes commands from the file \fI~/.bash_logout\fP, if it
-exists.
-.PP
-When an interactive shell that is not a login shell is started,
-.B bash
-reads and executes commands from \fI~/.bashrc\fP, if that file exists.
-This may be inhibited by using the
-.B \-\-norc
-option.
-The \fB\-\-rcfile\fP \fIfile\fP option will force
-.B bash
-to read and execute commands from \fIfile\fP instead of \fI~/.bashrc\fP.
-.PP
-When
-.B bash
-is started non-interactively, to run a shell script, for example, it
-looks for the variable
-.SM
-.B BASH_ENV
-in the environment, expands its value if it appears there, and uses the
-expanded value as the name of a file to read and execute.
-.B Bash
-behaves as if the following command were executed:
-.sp .5
-.RS
-.if t \f(CWif [ \-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi\fP
-.if n if [ \-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
-.RE
-.sp .5
-but the value of the
-.SM
-.B PATH
-variable is not used to search for the file name.
-.PP
-If
-.B bash
-is invoked with the name
-.BR sh ,
-it tries to mimic the startup behavior of historical versions of
-.B sh
-as closely as possible,
-while conforming to the POSIX standard as well.
-When invoked as an interactive login shell, or a non-interactive
-shell with the \fB\-\-login\fP option, it first attempts to
-read and execute commands from
-.I /etc/profile
-and
-.IR ~/.profile ,
-in that order.
-The
-.B \-\-noprofile
-option may be used to inhibit this behavior.
-When invoked as an interactive shell with the name
-.BR sh ,
-.B bash
-looks for the variable
-.SM
-.BR ENV ,
-expands its value if it is defined, and uses the
-expanded value as the name of a file to read and execute.
-Since a shell invoked as
-.B sh
-does not attempt to read and execute commands from any other startup
-files, the
-.B \-\-rcfile
-option has no effect.
-A non-interactive shell invoked with the name
-.B sh
-does not attempt to read any other startup files.
-When invoked as
-.BR sh ,
-.B bash
-enters
-.I posix
-mode after the startup files are read.
-.PP
-When
-.B bash
-is started in
-.I posix
-mode, as with the
-.B \-\-posix
-command line option, it follows the POSIX standard for startup files.
-In this mode, interactive shells expand the
-.SM
-.B ENV
-variable and commands are read and executed from the file
-whose name is the expanded value.
-No other startup files are read.
-.PP
-.B Bash
-attempts to determine when it is being run by the remote shell
-daemon, usually \fIrshd\fP.
-If
-.B bash
-determines it is being run by \fIrshd\fP, it reads and executes
-commands from \fI~/.bashrc\fP, if that file exists and is readable.
-It will not do this if invoked as \fBsh\fP.
-The
-.B \-\-norc
-option may be used to inhibit this behavior, and the
-.B \-\-rcfile
-option may be used to force another file to be read, but
-\fIrshd\fP does not generally invoke the shell with those options
-or allow them to be specified.
-.PP
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the \fB\-p\fP option is not supplied, no startup
-files are read, shell functions are not inherited from the environment, the
-.SM
-.B SHELLOPTS
-variable, if it appears in the environment, is ignored,
-and the effective user id is set to the real user id.
-If the \fB\-p\fP option is supplied at invocation, the startup behavior is
-the same, but the effective user id is not reset.
-.SH DEFINITIONS
-.PP
-The following definitions are used throughout the rest of this
-document.
-.PD 0
-.TP
-.B blank
-A space or tab.
-.TP
-.B word
-A sequence of characters considered as a single unit by the shell.
-Also known as a
-.BR token .
-.TP
-.B name
-A
-.I word
-consisting only of alphanumeric characters and underscores, and
-beginning with an alphabetic character or an underscore. Also
-referred to as an
-.BR identifier .
-.TP
-.B metacharacter
-A character that, when unquoted, separates words. One of the following:
-.br
-.RS
-.PP
-.if t \fB| & ; ( ) < > space tab\fP
-.if n \fB| & ; ( ) < > space tab\fP
-.RE
-.PP
-.TP
-.B control operator
-A \fItoken\fP that performs a control function. It is one of the following
-symbols:
-.RS
-.PP
-.if t \fB\(bv\(bv & && ; ;; ( ) | <newline>\fP
-.if n \fB|| & && ; ;; ( ) | <newline>\fP
-.RE
-.PD
-.SH "RESERVED WORDS"
-\fIReserved words\fP are words that have a special meaning to the shell.
-The following words are recognized as reserved when unquoted and either
-the first word of a simple command (see
-.SM
-.B SHELL GRAMMAR
-below) or the third word of a
-.B case
-or
-.B for
-command:
-.if t .RS
-.PP
-.B
-.if n ! case do done elif else esac fi for function if in select then until while { } time [[ ]]
-.if t ! case do done elif else esac fi for function if in select then until while { } time [[ ]]
-.if t .RE
-.RE
-.SH "SHELL GRAMMAR"
-.SS Simple Commands
-.PP
-A \fIsimple command\fP is a sequence of optional variable assignments
-followed by \fBblank\fP-separated words and redirections, and
-terminated by a \fIcontrol operator\fP. The first word
-specifies the command to be executed, and is passed as argument zero.
-The remaining words are passed as arguments to the invoked command.
-.PP
-The return value of a \fIsimple command\fP is its exit status, or
-128+\fIn\^\fP if the command is terminated by signal
-.IR n .
-.SS Pipelines
-.PP
-A \fIpipeline\fP is a sequence of one or more commands separated by
-the character
-.BR | .
-The format for a pipeline is:
-.RS
-.PP
-[\fBtime\fP [\fB\-p\fP]] [ ! ] \fIcommand\fP [ \fB|\fP \fIcommand2\fP ... ]
-.RE
-.PP
-The standard output of
-.I command
-is connected via a pipe to the standard input of
-.IR command2 .
-This connection is performed before any redirections specified by the
-command (see
-.SM
-.B REDIRECTION
-below).
-.PP
-If the reserved word
-.B !
-precedes a pipeline, the exit status of that
-pipeline is the logical NOT of the exit status of the last command.
-Otherwise, the status of the pipeline is the exit status of the last
-command.
-The shell waits for all commands in the pipeline to
-terminate before returning a value.
-.PP
-If the
-.B time
-reserved word precedes a pipeline, the elapsed as well as user and
-system time consumed by its execution are reported when the pipeline
-terminates.
-The \fB\-p\fP option changes the output format to that specified by POSIX.
-The
-.SM
-.B TIMEFORMAT
-variable may be set to a format string that specifies how the timing
-information should be displayed; see the description of
-.SM
-.B TIMEFORMAT
-under
-.B "Shell Variables"
-below.
-.PP
-Each command in a pipeline is executed as a separate process (i.e., in a
-subshell).
-.SS Lists
-.PP
-A \fIlist\fP is a sequence of one or more pipelines separated by one
-of the operators
-.BR ; ,
-.BR & ,
-.BR && ,
-or
-.BR \(bv\(bv ,
-and optionally terminated by one of
-.BR ; ,
-.BR & ,
-or
-.BR <newline> .
-.PP
-Of these list operators,
-.B &&
-and
-.B \(bv\(bv
-have equal precedence, followed by
-.B ;
-and
-.BR &,
-which have equal precedence.
-.PP
-A sequence of one or more newlines may appear in a \fIlist\fP instead
-of a semicolon to delimit commands.
-.PP
-If a command is terminated by the control operator
-.BR & ,
-the shell executes the command in the \fIbackground\fP
-in a subshell. The shell does not wait for the command to
-finish, and the return status is 0. Commands separated by a
-.B ;
-are executed sequentially; the shell waits for each
-command to terminate in turn. The return status is the
-exit status of the last command executed.
-.PP
-The control operators
-.B &&
-and
-.B \(bv\(bv
-denote AND lists and OR lists, respectively.
-An AND list has the form
-.RS
-.PP
-\fIcommand1\fP \fB&&\fP \fIcommand2\fP
-.RE
-.PP
-.I command2
-is executed if, and only if,
-.I command1
-returns an exit status of zero.
-.PP
-An OR list has the form
-.RS
-.PP
-\fIcommand1\fP \fB\(bv\(bv\fP \fIcommand2\fP
-.PP
-.RE
-.PP
-.I command2
-is executed if and only if
-.I command1
-returns a non-zero exit status. The return status of
-AND and OR lists is the exit status of the last command
-executed in the list.
-.SS Compound Commands
-.PP
-A \fIcompound command\fP is one of the following:
-.TP
-(\fIlist\fP)
-\fIlist\fP is executed in a subshell. Variable assignments and builtin
-commands that affect the shell's environment do not remain in effect
-after the command completes. The return status is the exit status of
-\fIlist\fP.
-.TP
-{ \fIlist\fP; }
-\fIlist\fP is simply executed in the current shell environment.
-\fIlist\fP must be terminated with a newline or semicolon.
-This is known as a \fIgroup command\fP.
-The return status is the exit status of
-\fIlist\fP.
-Note that unlike the metacharacters \fB(\fP and \fB)\fP, \fB{\fP and
-\fB}\fP are \fIreserved words\fP and must occur where a reserved
-word is permitted to be recognized. Since they do not cause a word
-break, they must be separated from \fIlist\fP by whitespace.
-.TP
-((\fIexpression\fP))
-The \fIexpression\fP is evaluated according to the rules described
-below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-If the value of the expression is non-zero, the return status is 0;
-otherwise the return status is 1. This is exactly equivalent to
-\fBlet "\fIexpression\fP"\fR.
-.TP
-\fB[[\fP \fIexpression\fP \fB]]\fP
-Return a status of 0 or 1 depending on the evaluation of
-the conditional expression \fIexpression\fP.
-Expressions are composed of the primaries described below under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" .
-Word splitting and pathname expansion are not performed on the words
-between the \fB[[\fP and \fB]]\fP; tilde expansion, parameter and
-variable expansion, arithmetic expansion, command substitution, process
-substitution, and quote removal are performed.
-Conditional operators such as \fB\-f\fP must be unquoted to be recognized
-as primaries.
-.if t .sp 0.5
-.if n .sp 1
-When the \fB==\fP and \fB!=\fP operators are used, the string to the
-right of the operator is considered a pattern and matched according
-to the rules described below under \fBPattern Matching\fP.
-The return value is 0 if the string matches or does not match
-the pattern, respectively, 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
-.if n .sp 1
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence:
-.if t .sp 0.5
-.if n .sp 1
-.RS
-.PD 0
-.TP
-.B ( \fIexpression\fP )
-Returns the value of \fIexpression\fP.
-This may be used to override the normal precedence of operators.
-.TP
-.B ! \fIexpression\fP
-True if
-.I expression
-is false.
-.TP
-\fIexpression1\fP \fB&&\fP \fIexpression2\fP
-True if both
-.I expression1
-and
-.I expression2
-are true.
-.TP
-.if t \fIexpression1\fP \fB\(bv\(bv\fP \fIexpression2\fP
-.if n \fIexpression1\fP \fB||\fP \fIexpression2\fP
-True if either
-.I expression1
-or
-.I expression2
-is true.
-.PD
-.LP
-The \fB&&\fP and
-.if t \fB\(bv\(bv\fP
-.if n \fB||\fP
-operators do not evaluate \fIexpression2\fP if the value of
-\fIexpression1\fP is sufficient to determine the return value of
-the entire conditional expression.
-.RE
-.TP
-\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ] ; \fBdo\fP \fIlist\fP ; \fBdone\fP
-The list of words following \fBin\fP is expanded, generating a list
-of items.
-The variable \fIname\fP is set to each element of this list
-in turn, and \fIlist\fP is executed each time.
-If the \fBin\fP \fIword\fP is omitted, the \fBfor\fP command executes
-\fIlist\fP once for each positional parameter that is set (see
-.SM
-.B PARAMETERS
-below).
-The return status is the exit status of the last command that executes.
-If the expansion of the items following \fBin\fP results in an empty
-list, no commands are executed, and the return status is 0.
-.TP
-\fBfor\fP (( \fIexpr1\fP ; \fIexpr2\fP ; \fIexpr3\fP )) ; \fBdo\fP \fIlist\fP ; \fBdone\fP
-First, the arithmetic expression \fIexpr1\fP is evaluated according
-to the rules described below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-The arithmetic expression \fIexpr2\fP is then evaluated repeatedly
-until it evaluates to zero.
-Each time \fIexpr2\fP evaluates to a non-zero value, \fIlist\fP is
-executed and the arithmetic expression \fIexpr3\fP is evaluated.
-If any expression is omitted, it behaves as if it evaluates to 1.
-The return value is the exit status of the last command in \fIlist\fP
-that is executed, or false if any of the expressions is invalid.
-.TP
-\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ] ; \fBdo\fP \fIlist\fP ; \fBdone\fP
-The list of words following \fBin\fP is expanded, generating a list
-of items. The set of expanded words is printed on the standard
-error, each preceded by a number. If the \fBin\fP
-\fIword\fP is omitted, the positional parameters are printed (see
-.SM
-.B PARAMETERS
-below). The
-.B PS3
-prompt is then displayed and a line read from the standard input.
-If the line consists of a number corresponding to one of
-the displayed words, then the value of
-.I name
-is set to that word. If the line is empty, the words and prompt
-are displayed again. If EOF is read, the command completes. Any
-other value read causes
-.I name
-to be set to null. The line read is saved in the variable
-.BR REPLY .
-The
-.I list
-is executed after each selection until a
-.B break
-command is executed.
-The exit status of
-.B select
-is the exit status of the last command executed in
-.IR list ,
-or zero if no commands were executed.
-.TP
-\fBcase\fP \fIword\fP \fBin\fP [ [(] \fIpattern\fP [ \fB|\fP \fIpattern\fP ] \
-... ) \fIlist\fP ;; ] ... \fBesac\fP
-A \fBcase\fP command first expands \fIword\fP, and tries to match
-it against each \fIpattern\fP in turn, using the same matching rules
-as for pathname expansion (see
-.B Pathname Expansion
-below). When a match is found, the
-corresponding \fIlist\fP is executed. After the first match, no
-subsequent matches are attempted. The exit status is zero if no
-pattern matches. Otherwise, it is the exit status of the
-last command executed in \fIlist\fP.
-.TP
-\fBif\fP \fIlist\fP; \fBthen\fP \fIlist;\fP \
-[ \fBelif\fP \fIlist\fP; \fBthen\fP \fIlist\fP; ] ... \
-[ \fBelse\fP \fIlist\fP; ] \fBfi\fP
-The
-.B if
-.I list
-is executed. If its exit status is zero, the
-\fBthen\fP \fIlist\fP is executed. Otherwise, each \fBelif\fP
-\fIlist\fP is executed in turn, and if its exit status is zero,
-the corresponding \fBthen\fP \fIlist\fP is executed and the
-command completes. Otherwise, the \fBelse\fP \fIlist\fP is
-executed, if present. The exit status is the exit status of the
-last command executed, or zero if no condition tested true.
-.TP
-\fBwhile\fP \fIlist\fP; \fBdo\fP \fIlist\fP; \fBdone\fP
-.PD 0
-.TP
-\fBuntil\fP \fIlist\fP; \fBdo\fP \fIlist\fP; \fBdone\fP
-.PD
-The \fBwhile\fP command continuously executes the \fBdo\fP
-\fIlist\fP as long as the last command in \fIlist\fP returns
-an exit status of zero. The \fBuntil\fP command is identical
-to the \fBwhile\fP command, except that the test is negated;
-the
-.B do
-.I list
-is executed as long as the last command in
-.I list
-returns a non-zero exit status.
-The exit status of the \fBwhile\fP and \fBuntil\fP commands
-is the exit status
-of the last \fBdo\fP \fIlist\fP command executed, or zero if
-none was executed.
-.TP
-[ \fBfunction\fP ] \fIname\fP () { \fIlist\fP; }
-This defines a function named \fIname\fP. The \fIbody\fP of the
-function is the
-.I list
-of commands between { and }. This list
-is executed whenever \fIname\fP is specified as the
-name of a simple command. The exit status of a function is
-the exit status of the last command executed in the body. (See
-.SM
-.B FUNCTIONS
-below.)
-.SH COMMENTS
-In a non-interactive shell, or an interactive shell in which the
-.B interactive_comments
-option to the
-.B shopt
-builtin is enabled (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), a word beginning with
-.B #
-causes that word and all remaining characters on that line to
-be ignored. An interactive shell without the
-.B interactive_comments
-option enabled does not allow comments. The
-.B interactive_comments
-option is on by default in interactive shells.
-.SH QUOTING
-\fIQuoting\fP is used to remove the special meaning of certain
-characters or words to the shell. Quoting can be used to
-disable special treatment for special characters, to prevent
-reserved words from being recognized as such, and to prevent
-parameter expansion.
-.PP
-Each of the \fImetacharacters\fP listed above under
-.SM
-.B DEFINITIONS
-has special meaning to the shell and must be quoted if it is to
-represent itself.
-.PP
-When the command history expansion facilities are being used, the
-\fIhistory expansion\fP character, usually \fB!\fP, must be quoted
-to prevent history expansion.
-.PP
-There are three quoting mechanisms: the
-.IR "escape character" ,
-single quotes, and double quotes.
-.PP
-A non-quoted backslash (\fB\e\fP) is the
-.IR "escape character" .
-It preserves the literal value of the next character that follows,
-with the exception of <newline>. If a \fB\e\fP<newline> pair
-appears, and the backslash is not itself quoted, the \fB\e\fP<newline>
-is treated as a line continuation (that is, it is removed from the
-input stream and effectively ignored).
-.PP
-Enclosing characters in single quotes preserves the literal value
-of each character within the quotes. A single quote may not occur
-between single quotes, even when preceded by a backslash.
-.PP
-Enclosing characters in double quotes preserves the literal value
-of all characters within the quotes, with the exception of
-.BR $ ,
-.BR ` ,
-and
-.BR \e .
-The characters
-.B $
-and
-.B `
-retain their special meaning within double quotes. The backslash
-retains its special meaning only when followed by one of the following
-characters:
-.BR $ ,
-.BR ` ,
-\^\fB"\fP\^,
-.BR \e ,
-or
-.BR <newline> .
-A double quote may be quoted within double quotes by preceding it with
-a backslash.
-When command history is being used, the double quote may not be used to
-quote the history expansion character.
-.PP
-The special parameters
-.B *
-and
-.B @
-have special meaning when in double
-quotes (see
-.SM
-.B PARAMETERS
-below).
-.PP
-Words of the form \fB$\fP'\fIstring\fP' are treated specially. The
-word expands to \fIstring\fP, with backslash-escaped characters replaced
-as specifed by the ANSI C standard. Backslash escape sequences, if
-present, are decoded as follows:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ee
-an escape character
-.TP
-.B \ef
-form feed
-.TP
-.B \en
-new line
-.TP
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP
-.B \ev
-vertical tab
-.TP
-.B \e\e
-backslash
-.TP
-.B \e'
-single quote
-.TP
-.B \e\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(one to three digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.TP
-.B \ec\fIx\fP
-a control-\fIx\fP character
-.PD
-.RE
-.LP
-The expanded result is single-quoted, as if the dollar sign had
-not been present.
-.PP
-A double-quoted string preceded by a dollar sign (\fB$\fP) will cause
-the string to be translated according to the current locale.
-If the current locale is \fBC\fP or \fBPOSIX\fP, the dollar sign
-is ignored.
-If the string is translated and replaced, the replacement is
-double-quoted.
-.SH PARAMETERS
-A
-.I parameter
-is an entity that stores values.
-It can be a
-.IR name ,
-a number, or one of the special characters listed below under
-.BR "Special Parameters" .
-A
-.I variable
-is a parameter denoted by a
-.IR name .
-A variable has a \fIvalue\fP and zero or more \fIattributes\fP.
-Attributes are assigned using the
-.B declare
-builtin command (see
-.B declare
-below in
-.SM
-.BR "SHELL BUILTIN COMMANDS" ).
-.PP
-A parameter is set if it has been assigned a value. The null string is
-a valid value. Once a variable is set, it may be unset only by using
-the
-.B unset
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.PP
-A
-.I variable
-may be assigned to by a statement of the form
-.RS
-.PP
-\fIname\fP=[\fIvalue\fP]
-.RE
-.PP
-If
-.I value
-is not given, the variable is assigned the null string. All
-.I values
-undergo tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote
-removal (see
-.SM
-.B EXPANSION
-below). If the variable has its
-.B integer
-attribute set, then
-.I value
-is evaluated as an arithmetic expression even if the $((...)) expansion is
-not used (see
-.B "Arithmetic Expansion"
-below).
-Word splitting is not performed, with the exception
-of \fB"$@"\fP as explained below under
-.BR "Special Parameters" .
-Pathname expansion is not performed.
-Assignment statements may also appear as arguments to the
-.BR declare ,
-.BR typeset ,
-.BR export ,
-.BR readonly ,
-and
-.B local
-builtin commands.
-.SS Positional Parameters
-.PP
-A
-.I positional parameter
-is a parameter denoted by one or more
-digits, other than the single digit 0. Positional parameters are
-assigned from the shell's arguments when it is invoked,
-and may be reassigned using the
-.B set
-builtin command. Positional parameters may not be assigned to
-with assignment statements. The positional parameters are
-temporarily replaced when a shell function is executed (see
-.SM
-.B FUNCTIONS
-below).
-.PP
-When a positional parameter consisting of more than a single
-digit is expanded, it must be enclosed in braces (see
-.SM
-.B EXPANSION
-below).
-.SS Special Parameters
-.PP
-The shell treats several parameters specially. These parameters may
-only be referenced; assignment to them is not allowed.
-.PD 0
-.TP
-.B *
-Expands to the positional parameters, starting from one. When the
-expansion occurs within double quotes, it expands to a single word
-with the value of each parameter separated by the first character
-of the
-.SM
-.B IFS
-special variable. That is, "\fB$*\fP" is equivalent
-to "\fB$1\fP\fIc\fP\fB$2\fP\fIc\fP\fB...\fP", where
-.I c
-is the first character of the value of the
-.SM
-.B IFS
-variable. If
-.SM
-.B IFS
-is unset, the parameters are separated by spaces.
-If
-.SM
-.B IFS
-is null, the parameters are joined without intervening separators.
-.TP
-.B @
-Expands to the positional parameters, starting from one. When the
-expansion occurs within double quotes, each parameter expands to a
-separate word. That is, "\fB$@\fP" is equivalent to
-"\fB$1\fP" "\fB$2\fP" ...
-When there are no positional parameters, "\fB$@\fP" and
-.B $@
-expand to nothing (i.e., they are removed).
-.TP
-.B #
-Expands to the number of positional parameters in decimal.
-.TP
-.B ?
-Expands to the status of the most recently executed foreground
-pipeline.
-.TP
-.B \-
-Expands to the current option flags as specified upon invocation,
-by the
-.B set
-builtin command, or those set by the shell itself
-(such as the
-.B \-i
-option).
-.TP
-.B $
-Expands to the process ID of the shell. In a () subshell, it
-expands to the process ID of the current shell, not the
-subshell.
-.TP
-.B !
-Expands to the process ID of the most recently executed background
-(asynchronous) command.
-.TP
-.B 0
-Expands to the name of the shell or shell script. This is set at
-shell initialization. If
-.B bash
-is invoked with a file of commands,
-.B $0
-is set to the name of that file. If
-.B bash
-is started with the
-.B \-c
-option, then
-.B $0
-is set to the first argument after the string to be
-executed, if one is present. Otherwise, it is set
-to the file name used to invoke
-.BR bash ,
-as given by argument zero.
-.TP
-.B _
-At shell startup, set to the absolute file name of the shell or shell
-script being executed as passed in the argument list.
-Subsequently, expands to the last argument to the previous command,
-after expansion.
-Also set to the full file name of each command executed and placed in
-the environment exported to that command.
-When checking mail, this parameter holds the name of the mail file
-currently being checked.
-.PD
-.SS Shell Variables
-.PP
-The following variables are set by the shell:
-.PP
-.PD 0
-.TP
-.B BASH
-Expands to the full file name used to invoke this instance of
-.BR bash .
-.TP
-.B BASH_ARGC
-An array variable whose values are the number of parameters in each
-frame of the current bash execution call stack. The number of
-parameters to the current subroutine (shell function or script executed
-with \fB.\fP or \fBsource\fP) is at the top of the stack. When a
-subroutine is executed, the number of parameters passed is pushed onto
-\fBBASH_ARGC\fP.
-.TP
-.B BASH_ARGV
-An array variable containing all of the parameters in the current bash
-execution call stack. The final parameter of the last subroutine call
-is at the top of the stack; the first parameter of the initial call is
-at the bottom. When a subroutine is executed, the parameters supplied
-are pushed onto \fBBASH_ARGV\fP.
-.TP
-.B BASH_COMMAND
-The command currently being executed or about to be executed, unless the
-shell is executing a command as the result of a trap,
-in which case it is the command executing at the time of the trap.
-.TP
-.B BASH_EXECUTION_STRING
-The command argument to the \fB\-c\fP invocation option.
-.TP
-.B BASH_LINENO
-An array variable whose members are the line numbers in source files
-corresponding to each member of @var{FUNCNAME}.
-\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP is the line number in the source
-file where \fB${FUNCNAME[\fP\fI$i + 1\fP\fB]}\fP was called.
-The corresponding source file name is \fB${BASH_SOURCE[\fP\fI$i + 1\fP\fB]}\fB.
-Use \fBLINENO\fP to obtain the current line number.
-.TP
-.B BASH_SOURCE
-An array variable whose members are the source filenames corresponding
-to the elements in the \fBFUNCNAME\fP array variable.
-.TP
-.B BASH_SUBSHELL
-Incremented by one each time a subshell or subshell environment is spawned.
-The initial value is 0.
-.TP
-.B BASH_VERSINFO
-A readonly array variable whose members hold version information for
-this instance of
-.BR bash .
-The values assigned to the array members are as follows:
-.sp .5
-.RS
-.PD 0
-.TP 24
-.B BASH_VERSINFO[\fR0\fP]
-The major version number (the \fIrelease\fP).
-.TP
-.B BASH_VERSINFO[\fR1\fP]
-The minor version number (the \fIversion\fP).
-.TP
-.B BASH_VERSINFO[\fR2\fP]
-The patch level.
-.TP
-.B BASH_VERSINFO[\fR3\fP]
-The build version.
-.TP
-.B BASH_VERSINFO[\fR4\fP]
-The release status (e.g., \fIbeta1\fP).
-.TP
-.B BASH_VERSINFO[\fR5\fP]
-The value of \fBMACHTYPE\fP.
-.PD
-.RE
-.TP
-.B BASH_VERSION
-Expands to a string describing the version of this instance of
-.BR bash .
-.TP
-.B COMP_CWORD
-An index into \fB${COMP_WORDS}\fP of the word containing the current
-cursor position.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_LINE
-The current command line.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_POINT
-The index of the current cursor position relative to the beginning of
-the current command.
-If the current cursor position is at the end of the current command,
-the value of this variable is equal to \fB${#COMP_LINE}\fP.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_WORDBREAKS
-The set of characters that the Readline library treats as word
-separators when performing word completion.
-If
-.SM
-.B COMP_WORDBREAKS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B COMP_WORDS
-An array variable (see \fBArrays\fP below) consisting of the individual
-words in the current command line.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B DIRSTACK
-An array variable (see
-.B Arrays
-below) containing the current contents of the directory stack.
-Directories appear in the stack in the order they are displayed by the
-.B dirs
-builtin.
-Assigning to members of this array variable may be used to modify
-directories already in the stack, but the
-.B pushd
-and
-.B popd
-builtins must be used to add and remove directories.
-Assignment to this variable will not change the current directory.
-If
-.SM
-.B DIRSTACK
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B EUID
-Expands to the effective user ID of the current user, initialized at
-shell startup. This variable is readonly.
-.TP
-.B FUNCNAME
-An array variable containing the names of all shell functions
-currently in the execution call stack.
-The element with index 0 is the name of any currently-executing
-shell function.
-The bottom-most element is "main".
-This variable exists only when a shell function is executing.
-Assignments to
-.SM
-.B FUNCNAME
-have no effect and return an error status.
-If
-.SM
-.B FUNCNAME
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B GROUPS
-An array variable containing the list of groups of which the current
-user is a member.
-Assignments to
-.SM
-.B GROUPS
-have no effect and return an error status.
-If
-.SM
-.B GROUPS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B HISTCMD
-The history number, or index in the history list, of the current
-command.
-If
-.SM
-.B HISTCMD
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B HOSTNAME
-Automatically set to the name of the current host.
-.TP
-.B HOSTTYPE
-Automatically set to a string that uniquely
-describes the type of machine on which
-.B bash
-is executing.
-The default is system-dependent.
-.TP
-.B LINENO
-Each time this parameter is referenced, the shell substitutes
-a decimal number representing the current sequential line number
-(starting with 1) within a script or function. When not in a
-script or function, the value substituted is not guaranteed to
-be meaningful.
-If
-.SM
-.B LINENO
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B MACHTYPE
-Automatically set to a string that fully describes the system
-type on which
-.B bash
-is executing, in the standard GNU \fIcpu-company-system\fP format.
-The default is system-dependent.
-.TP
-.B OLDPWD
-The previous working directory as set by the
-.B cd
-command.
-.TP
-.B OPTARG
-The value of the last option argument processed by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.TP
-.B OPTIND
-The index of the next argument to be processed by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.TP
-.B OSTYPE
-Automatically set to a string that
-describes the operating system on which
-.B bash
-is executing.
-The default is system-dependent.
-.TP
-.B PIPESTATUS
-An array variable (see
-.B Arrays
-below) containing a list of exit status values from the processes
-in the most-recently-executed foreground pipeline (which may
-contain only a single command).
-.TP
-.B PPID
-The process ID of the shell's parent. This variable is readonly.
-.TP
-.B PWD
-The current working directory as set by the
-.B cd
-command.
-.TP
-.B RANDOM
-Each time this parameter is referenced, a random integer between
-0 and 32767 is
-generated. The sequence of random numbers may be initialized by assigning
-a value to
-.SM
-.BR RANDOM .
-If
-.SM
-.B RANDOM
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B REPLY
-Set to the line of input read by the
-.B read
-builtin command when no arguments are supplied.
-.TP
-.B SECONDS
-Each time this parameter is
-referenced, the number of seconds since shell invocation is returned. If a
-value is assigned to
-.SM
-.BR SECONDS ,
-the value returned upon subsequent
-references is
-the number of seconds since the assignment plus the value assigned.
-If
-.SM
-.B SECONDS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B SHELLOPTS
-A colon-separated list of enabled shell options. Each word in
-the list is a valid argument for the
-.B \-o
-option to the
-.B set
-builtin command (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below). The options appearing in
-.SM
-.B SHELLOPTS
-are those reported as
-.I on
-by \fBset \-o\fP.
-If this variable is in the environment when
-.B bash
-starts up, each shell option in the list will be enabled before
-reading any startup files.
-This variable is read-only.
-.TP
-.B SHLVL
-Incremented by one each time an instance of
-.B bash
-is started.
-.TP
-.B UID
-Expands to the user ID of the current user, initialized at shell startup.
-This variable is readonly.
-.PD
-.PP
-The following variables are used by the shell. In some cases,
-.B bash
-assigns a default value to a variable; these cases are noted
-below.
-.PP
-.PD 0
-.TP
-.B BASH_ENV
-If this parameter is set when \fBbash\fP is executing a shell script,
-its value is interpreted as a filename containing commands to
-initialize the shell, as in
-.IR ~/.bashrc .
-The value of
-.SM
-.B BASH_ENV
-is subjected to parameter expansion, command substitution, and arithmetic
-expansion before being interpreted as a file name.
-.SM
-.B PATH
-is not used to search for the resultant file name.
-.TP
-.B CDPATH
-The search path for the
-.B cd
-command.
-This is a colon-separated list of directories in which the shell looks
-for destination directories specified by the
-.B cd
-command.
-A sample value is
-.if t \f(CW".:~:/usr"\fP.
-.if n ".:~:/usr".
-.TP
-.B COLUMNS
-Used by the \fBselect\fP builtin command to determine the terminal width
-when printing selection lists. Automatically set upon receipt of a SIGWINCH.
-.TP
-.B COMPREPLY
-An array variable from which \fBbash\fP reads the possible completions
-generated by a shell function invoked by the programmable completion
-facility (see \fBProgrammable Completion\fP below).
-.TP
-.B EMACS
-If \fBbash\fP finds this variable in the environment when the shell starts
-with value
-.if t \f(CWt\fP,
-.if n "t",
-it assumes that the shell is running in an emacs shell buffer and disables
-line editing.
-.TP
-.B FCEDIT
-The default editor for the
-.B fc
-builtin command.
-.TP
-.B FIGNORE
-A colon-separated list of suffixes to ignore when performing
-filename completion (see
-.SM
-.B READLINE
-below).
-A filename whose suffix matches one of the entries in
-.SM
-.B FIGNORE
-is excluded from the list of matched filenames.
-A sample value is
-.if t \f(CW".o:~"\fP.
-.if n ".o:~".
-.TP
-.B GLOBIGNORE
-A colon-separated list of patterns defining the set of filenames to
-be ignored by pathname expansion.
-If a filename matched by a pathname expansion pattern also matches one
-of the patterns in
-.SM
-.BR GLOBIGNORE ,
-it is removed from the list of matches.
-.TP
-.B HISTCONTROL
-A colon-separated list of values controlling how commands are saved on
-the history list.
-If the list of values includes
-.IR ignorespace ,
-lines which begin with a
-.B space
-character are not saved in the history list.
-A value of
-.I ignoredups
-causes lines matching the previous history entry to not be saved.
-A value of
-.I ignoreboth
-is shorthand for \fIignorespace\fP and \fIignoredups\fP.
-A value of
-.IR erasedups
-causes all previous lines matching the current line to be removed from
-the history list before that line is saved.
-Any value not in the above list is ignored.
-If \fBHISTCONTROL\fP is unset, or does not include a valid value,
-all lines read by the shell parser are saved on the history list,
-subject to the value of
-.BR HISTIGNORE .
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-.BR HISTCONTROL .
-.TP
-.B HISTFILE
-The name of the file in which command history is saved (see
-.SM
-.B HISTORY
-below). The default value is \fI~/.bash_history\fP. If unset, the
-command history is not saved when an interactive shell exits.
-.TP
-.B HISTFILESIZE
-The maximum number of lines contained in the history file. When this
-variable is assigned a value, the history file is truncated, if
-necessary, to contain no more than that number of lines. The default
-value is 500. The history file is also truncated to this size after
-writing it when an interactive shell exits.
-.TP
-.B HISTIGNORE
-A colon-separated list of patterns used to decide which command lines
-should be saved on the history list. Each pattern is anchored at the
-beginning of the line and must match the complete line (no implicit
-`\fB*\fP' is appended). Each pattern is tested against the line
-after the checks specified by
-.B HISTCONTROL
-are applied.
-In addition to the normal shell pattern matching characters, `\fB&\fP'
-matches the previous history line. `\fB&\fP' may be escaped using a
-backslash; the backslash is removed before attempting a match.
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-.BR HISTIGNORE .
-.TP
-.B HISTSIZE
-The number of commands to remember in the command history (see
-.SM
-.B HISTORY
-below). The default value is 500.
-.TP
-.B HOME
-The home directory of the current user; the default argument for the
-\fBcd\fP builtin command.
-The value of this variable is also used when performing tilde expansion.
-.TP
-.B HOSTFILE
-Contains the name of a file in the same format as
-.FN /etc/hosts
-that should be read when the shell needs to complete a
-hostname.
-The list of possible hostname completions may be changed while the
-shell is running;
-the next time hostname completion is attempted after the
-value is changed,
-.B bash
-adds the contents of the new file to the existing list.
-If
-.SM
-.B HOSTFILE
-is set, but has no value, \fBbash\fP attempts to read
-.FN /etc/hosts
-to obtain the list of possible hostname completions.
-When
-.SM
-.B HOSTFILE
-is unset, the hostname list is cleared.
-.TP
-.B IFS
-The
-.I Internal Field Separator
-that is used
-for word splitting after expansion and to
-split lines into words with the
-.B read
-builtin command. The default value is
-``<space><tab><newline>''.
-.TP
-.B IGNOREEOF
-Controls the
-action of an interactive shell on receipt of an
-.SM
-.B EOF
-character as the sole input. If set, the value is the number of
-consecutive
-.SM
-.B EOF
-characters which must be
-typed as the first characters on an input line before
-.B bash
-exits. If the variable exists but does not have a numeric value, or
-has no value, the default value is 10. If it does not exist,
-.SM
-.B EOF
-signifies the end of input to the shell.
-.TP
-.B INPUTRC
-The filename for the
-.B readline
-startup file, overriding the default of
-.FN ~/.inputrc
-(see
-.SM
-.B READLINE
-below).
-.TP
-.B LANG
-Used to determine the locale category for any category not specifically
-selected with a variable starting with \fBLC_\fP.
-.TP
-.B LC_ALL
-This variable overrides the value of \fBLANG\fP and any other
-\fBLC_\fP variable specifying a locale category.
-.TP
-.B LC_COLLATE
-This variable determines the collation order used when sorting the
-results of pathname expansion, and determines the behavior of range
-expressions, equivalence classes, and collating sequences within
-pathname expansion and pattern matching.
-.TP
-.B LC_CTYPE
-This variable determines the interpretation of characters and the
-behavior of character classes within pathname expansion and pattern
-matching.
-.TP
-.B LC_MESSAGES
-This variable determines the locale used to translate double-quoted
-strings preceded by a \fB$\fP.
-.TP
-.B LC_NUMERIC
-This variable determines the locale category used for number formatting.
-.TP
-.B LINES
-Used by the \fBselect\fP builtin command to determine the column length
-for printing selection lists. Automatically set upon receipt of a SIGWINCH.
-.TP
-.B MAIL
-If this parameter is set to a file name and the
-.SM
-.B MAILPATH
-variable is not set,
-.B bash
-informs the user of the arrival of mail in the specified file.
-.TP
-.B MAILCHECK
-Specifies how
-often (in seconds)
-.B bash
-checks for mail. The default is 60 seconds. When it is time to check
-for mail, the shell does so before displaying the primary prompt.
-If this variable is unset, or set to a value that is not a number
-greater than or equal to zero, the shell disables mail checking.
-.TP
-.B MAILPATH
-A colon-separated list of file names to be checked for mail.
-The message to be printed when mail arrives in a particular file
-may be specified by separating the file name from the message with a `?'.
-When used in the text of the message, \fB$_\fP expands to the name of
-the current mailfile.
-Example:
-.RS
-.PP
-\fBMAILPATH\fP='/var/mail/bfox?"You have mail":~/shell\-mail?"$_ has mail!"'
-.PP
-.B Bash
-supplies a default value for this variable, but the location of the user
-mail files that it uses is system dependent (e.g., /var/mail/\fB$USER\fP).
-.RE
-.TP
-.B OPTERR
-If set to the value 1,
-.B bash
-displays error messages generated by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SM
-.B OPTERR
-is initialized to 1 each time the shell is invoked or a shell
-script is executed.
-.TP
-.B PATH
-The search path for commands. It
-is a colon-separated list of directories in which
-the shell looks for commands (see
-.SM
-.B COMMAND EXECUTION
-below).
-A zero-length (null) directory name in the value of \fBPATH\fP indicates the
-current directory.
-A null directory name may appear as two adjacent colons, or as an initial
-or trailing colon.
-The default path is system-dependent,
-and is set by the administrator who installs
-.BR bash .
-A common value is
-.if t \f(CW/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:.\fP.
-.if n ``/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin:.''.
-.TP
-.B POSIXLY_CORRECT
-If this variable is in the environment when \fBbash\fP starts, the shell
-enters \fIposix mode\fP before reading the startup files, as if the
-.B \-\-posix
-invocation option had been supplied. If it is set while the shell is
-running, \fBbash\fP enables \fIposix mode\fP, as if the command
-.if t \f(CWset -o posix\fP
-.if n \fIset -o posix\fP
-had been executed.
-.TP
-.B PROMPT_COMMAND
-If set, the value is executed as a command prior to issuing each primary
-prompt.
-.TP
-.B PS1
-The value of this parameter is expanded (see
-.SM
-.B PROMPTING
-below) and used as the primary prompt string. The default value is
-``\fB\es\-\ev\e$ \fP''.
-.TP
-.B PS2
-The value of this parameter is expanded as with
-.B PS1
-and used as the secondary prompt string. The default is
-``\fB> \fP''.
-.TP
-.B PS3
-The value of this parameter is used as the prompt for the
-.B select
-command (see
-.SM
-.B SHELL GRAMMAR
-above).
-.TP
-.B PS4
-The value of this parameter is expanded as with
-.B PS1
-and the value is printed before each command
-.B bash
-displays during an execution trace. The first character of
-.SM
-.B PS4
-is replicated multiple times, as necessary, to indicate multiple
-levels of indirection. The default is ``\fB+ \fP''.
-.TP
-.B TIMEFORMAT
-The value of this parameter is used as a format string specifying
-how the timing information for pipelines prefixed with the
-.B time
-reserved word should be displayed.
-The \fB%\fP character introduces an escape sequence that is
-expanded to a time value or other information.
-The escape sequences and their meanings are as follows; the
-braces denote optional portions.
-.sp .5
-.RS
-.PD 0
-.TP 10
-.B %%
-A literal \fB%\fP.
-.TP
-.B %[\fIp\fP][l]R
-The elapsed time in seconds.
-.TP
-.B %[\fIp\fP][l]U
-The number of CPU seconds spent in user mode.
-.TP
-.B %[\fIp\fP][l]S
-The number of CPU seconds spent in system mode.
-.TP
-.B %P
-The CPU percentage, computed as (%U + %S) / %R.
-.PD
-.RE
-.IP
-The optional \fIp\fP is a digit specifying the \fIprecision\fP,
-the number of fractional digits after a decimal point.
-A value of 0 causes no decimal point or fraction to be output.
-At most three places after the decimal point may be specified;
-values of \fIp\fP greater than 3 are changed to 3.
-If \fIp\fP is not specified, the value 3 is used.
-.IP
-The optional \fBl\fP specifies a longer format, including
-minutes, of the form \fIMM\fPm\fISS\fP.\fIFF\fPs.
-The value of \fIp\fP determines whether or not the fraction is
-included.
-.IP
-If this variable is not set, \fBbash\fP acts as if it had the
-value \fB$'\enreal\et%3lR\enuser\et%3lU\ensys\t%3lS'\fP.
-If the value is null, no timing information is displayed.
-A trailing newline is added when the format string is displayed.
-.TP
-.B TMOUT
-If set to a value greater than zero, \fBTMOUT\fP is treated as the
-default timeout for the \fBread\fP builtin.
-The \fBselect\fP command terminates if input does not arrive
-after \fBTMOUT\fP seconds when input is coming from a terminal.
-In an interactive shell, the value is interpreted as the
-number of seconds to wait for input after issuing the primary prompt.
-.B Bash
-terminates after waiting for that number of seconds if input does
-not arrive.
-.TP
-.B auto_resume
-This variable controls how the shell interacts with the user and
-job control. If this variable is set, single word simple
-commands without redirections are treated as candidates for resumption
-of an existing stopped job. There is no ambiguity allowed; if there is
-more than one job beginning with the string typed, the job most recently
-accessed is selected. The
-.I name
-of a stopped job, in this context, is the command line used to
-start it.
-If set to the value
-.IR exact ,
-the string supplied must match the name of a stopped job exactly;
-if set to
-.IR substring ,
-the string supplied needs to match a substring of the name of a
-stopped job. The
-.I substring
-value provides functionality analogous to the
-.B %?
-job identifier (see
-.SM
-.B JOB CONTROL
-below). If set to any other value, the supplied string must
-be a prefix of a stopped job's name; this provides functionality
-analogous to the
-.B %
-job identifier.
-.TP
-.B histchars
-The two or three characters which control history expansion
-and tokenization (see
-.SM
-.B HISTORY EXPANSION
-below). The first character is the \fIhistory expansion\fP character,
-the character which signals the start of a history
-expansion, normally `\fB!\fP'.
-The second character is the \fIquick substitution\fP
-character, which is used as shorthand for re-running the previous
-command entered, substituting one string for another in the command.
-The default is `\fB^\fP'.
-The optional third character is the character
-which indicates that the remainder of the line is a comment when found
-as the first character of a word, normally `\fB#\fP'. The history
-comment character causes history substitution to be skipped for the
-remaining words on the line. It does not necessarily cause the shell
-parser to treat the rest of the line as a comment.
-.PD
-.SS Arrays
-.B Bash
-provides one-dimensional array variables. Any variable may be used as
-an array; the
-.B declare
-builtin will explicitly declare an array. There is no maximum
-limit on the size of an array, nor any requirement that members
-be indexed or assigned contiguously. Arrays are indexed using
-integers and are zero-based.
-.PP
-An array is created automatically if any variable is assigned to using
-the syntax \fIname\fP[\fIsubscript\fP]=\fIvalue\fP. The
-.I subscript
-is treated as an arithmetic expression that must evaluate to a number
-greater than or equal to zero. To explicitly declare an array, use
-.B declare \-a \fIname\fP
-(see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.B declare \-a \fIname\fP[\fIsubscript\fP]
-is also accepted; the \fIsubscript\fP is ignored. Attributes may be
-specified for an array variable using the
-.B declare
-and
-.B readonly
-builtins. Each attribute applies to all members of an array.
-.PP
-Arrays are assigned to using compound assignments of the form
-\fIname\fP=\fB(\fPvalue\fI1\fP ... value\fIn\fP\fB)\fP, where each
-\fIvalue\fP is of the form [\fIsubscript\fP]=\fIstring\fP. Only
-\fIstring\fP is required. If
-the optional brackets and subscript are supplied, that index is assigned to;
-otherwise the index of the element assigned is the last index assigned
-to by the statement plus one. Indexing starts at zero.
-This syntax is also accepted by the
-.B declare
-builtin. Individual array elements may be assigned to using the
-\fIname\fP[\fIsubscript\fP]=\fIvalue\fP syntax introduced above.
-.PP
-Any element of an array may be referenced using
-${\fIname\fP[\fIsubscript\fP]}. The braces are required to avoid
-conflicts with pathname expansion. If
-\fIsubscript\fP is \fB@\fP or \fB*\fP, the word expands to
-all members of \fIname\fP. These subscripts differ only when the
-word appears within double quotes. If the word is double-quoted,
-${\fIname\fP[*]} expands to a single
-word with the value of each array member separated by the first
-character of the
-.SM
-.B IFS
-special variable, and ${\fIname\fP[@]} expands each element of
-\fIname\fP to a separate word. When there are no array members,
-${\fIname\fP[@]} expands to nothing. This is analogous to the expansion
-of the special parameters \fB*\fP and \fB@\fP (see
-.B Special Parameters
-above). ${#\fIname\fP[\fIsubscript\fP]} expands to the length of
-${\fIname\fP[\fIsubscript\fP]}. If \fIsubscript\fP is \fB*\fP or
-\fB@\fP, the expansion is the number of elements in the array.
-Referencing an array variable without a subscript is equivalent to
-referencing element zero.
-.PP
-The
-.B unset
-builtin is used to destroy arrays. \fBunset\fP \fIname\fP[\fIsubscript\fP]
-destroys the array element at index \fIsubscript\fP.
-\fBunset\fP \fIname\fP, where \fIname\fP is an array, or
-\fBunset\fP \fIname\fP[\fIsubscript\fP], where
-\fIsubscript\fP is \fB*\fP or \fB@\fP, removes the entire array.
-.PP
-The
-.BR declare ,
-.BR local ,
-and
-.B readonly
-builtins each accept a
-.B \-a
-option to specify an array. The
-.B read
-builtin accepts a
-.B \-a
-option to assign a list of words read from the standard input
-to an array. The
-.B set
-and
-.B declare
-builtins display array values in a way that allows them to be
-reused as assignments.
-.SH EXPANSION
-Expansion is performed on the command line after it has been split into
-words. There are seven kinds of expansion performed:
-.IR "brace expansion" ,
-.IR "tilde expansion" ,
-.IR "parameter and variable expansion" ,
-.IR "command substitution" ,
-.IR "arithmetic expansion" ,
-.IR "word splitting" ,
-and
-.IR "pathname expansion" .
-.PP
-The order of expansions is: brace expansion, tilde expansion,
-parameter, variable and arithmetic expansion and
-command substitution
-(done in a left-to-right fashion), word splitting, and pathname
-expansion.
-.PP
-On systems that can support it, there is an additional expansion
-available: \fIprocess substitution\fP.
-.PP
-Only brace expansion, word splitting, and pathname expansion
-can change the number of words of the expansion; other expansions
-expand a single word to a single word.
-The only exceptions to this are the expansions of
-"\fB$@\fP" and "\fB${\fP\fIname\fP\fB[@]}\fP"
-as explained above (see
-.SM
-.BR PARAMETERS ).
-.SS Brace Expansion
-.PP
-.I "Brace expansion"
-is a mechanism by which arbitrary strings
-may be generated. This mechanism is similar to
-\fIpathname expansion\fP, but the filenames generated
-need not exist. Patterns to be brace expanded take
-the form of an optional
-.IR preamble ,
-followed by either a series of comma-separated strings or
-a sequence expression between a pair of braces, followed by
-an optional
-.IR postscript .
-The preamble is prefixed to each string contained
-within the braces, and the postscript is then appended
-to each resulting string, expanding left to right.
-.PP
-Brace expansions may be nested. The results of each expanded
-string are not sorted; left to right order is preserved.
-For example, a\fB{\fPd,c,b\fB}\fPe expands into `ade ace abe'.
-.PP
-A sequence expression takes the form \fB{\fP\fIx\fP\fB..\fP\fIy\fP\fB}\fP,
-where \fIx\fP and \fIy\fP are either integers or single characters.
-When integers are supplied, the expression expands to each number between
-\fIx\fP and \fIy\fP, inclusive.
-When characters are supplied, the expression expands to each character
-lexicographically between \fIx\fP and \fIy\fP, inclusive. Note that
-both \fIx\fP and \fIy\fP must be of the same type.
-.PP
-Brace expansion is performed before any other expansions,
-and any characters special to other expansions are preserved
-in the result. It is strictly textual.
-.B Bash
-does not apply any syntactic interpretation to the context of the
-expansion or the text between the braces.
-.PP
-A correctly-formed brace expansion must contain unquoted opening
-and closing braces, and at least one unquoted comma or a valid
-sequence expression.
-Any incorrectly formed brace expansion is left unchanged.
-A \fB{\fP or \fB,\fP may be quoted with a backslash to prevent its
-being considered part of a brace expression.
-To avoid conflicts with parameter expansion, the string \fB${\fP
-is not considered eligible for brace expansion.
-.PP
-This construct is typically used as shorthand when the common
-prefix of the strings to be generated is longer than in the
-above example:
-.RS
-.PP
-mkdir /usr/local/src/bash/{old,new,dist,bugs}
-.RE
-or
-.RS
-chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
-.RE
-.PP
-Brace expansion introduces a slight incompatibility with
-historical versions of
-.BR sh .
-.B sh
-does not treat opening or closing braces specially when they
-appear as part of a word, and preserves them in the output.
-.B Bash
-removes braces from words as a consequence of brace
-expansion. For example, a word entered to
-.B sh
-as \fIfile{1,2}\fP
-appears identically in the output. The same word is
-output as
-.I file1 file2
-after expansion by
-.BR bash .
-If strict compatibility with
-.B sh
-is desired, start
-.B bash
-with the
-.B +B
-option or disable brace expansion with the
-.B +B
-option to the
-.B set
-command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SS Tilde Expansion
-.PP
-If a word begins with an unquoted tilde character (`\fB~\fP'), all of
-the characters preceding the first unquoted slash (or all characters,
-if there is no unquoted slash) are considered a \fItilde-prefix\fP.
-If none of the characters in the tilde-prefix are quoted, the
-characters in the tilde-prefix following the tilde are treated as a
-possible \fIlogin name\fP.
-If this login name is the null string, the tilde is replaced with the
-value of the shell parameter
-.SM
-.BR HOME .
-If
-.SM
-.B HOME
-is unset, the home directory of the user executing the shell is
-substituted instead.
-Otherwise, the tilde-prefix is replaced with the home directory
-associated with the specified login name.
-.PP
-If the tilde-prefix is a `~+', the value of the shell variable
-.SM
-.B PWD
-replaces the tilde-prefix.
-If the tilde-prefix is a `~\-', the value of the shell variable
-.SM
-.BR OLDPWD ,
-if it is set, is substituted.
-If the characters following the tilde in the tilde-prefix consist
-of a number \fIN\fP, optionally prefixed
-by a `+' or a `\-', the tilde-prefix is replaced with the corresponding
-element from the directory stack, as it would be displayed by the
-.B dirs
-builtin invoked with the tilde-prefix as an argument.
-If the characters following the tilde in the tilde-prefix consist of a
-number without a leading `+' or `\-', `+' is assumed.
-.PP
-If the login name is invalid, or the tilde expansion fails, the word
-is unchanged.
-.PP
-Each variable assignment is checked for unquoted tilde-prefixes immediately
-following a
-.B :
-or
-.BR = .
-In these cases, tilde expansion is also performed.
-Consequently, one may use file names with tildes in assignments to
-.SM
-.BR PATH ,
-.SM
-.BR MAILPATH ,
-and
-.SM
-.BR CDPATH ,
-and the shell assigns the expanded value.
-.SS Parameter Expansion
-.PP
-The `\fB$\fP' character introduces parameter expansion,
-command substitution, or arithmetic expansion. The parameter name
-or symbol to be expanded may be enclosed in braces, which
-are optional but serve to protect the variable to be expanded from
-characters immediately following it which could be
-interpreted as part of the name.
-.PP
-When braces are used, the matching ending brace is the first `\fB}\fP'
-not escaped by a backslash or within a quoted string, and not within an
-embedded arithmetic expansion, command substitution, or paramter
-expansion.
-.PP
-.PD 0
-.TP
-${\fIparameter\fP}
-The value of \fIparameter\fP is substituted. The braces are required
-when
-.I parameter
-is a positional parameter with more than one digit,
-or when
-.I parameter
-is followed by a character which is not to be
-interpreted as part of its name.
-.PD
-.PP
-If the first character of \fIparameter\fP is an exclamation point,
-a level of variable indirection is introduced.
-\fBBash\fP uses the value of the variable formed from the rest of
-\fIparameter\fP as the name of the variable; this variable is then
-expanded and that value is used in the rest of the substitution, rather
-than the value of \fIparameter\fP itself.
-This is known as \fIindirect expansion\fP.
-The exceptions to this are the expansions of ${!\fIprefix\fP*} and
-${\fB!\fP\fIname\fP[\fI@\fP]} described below.
-The exclamation point must immediately follow the left brace in order to
-introduce indirection.
-.PP
-In each of the cases below, \fIword\fP is subject to tilde expansion,
-parameter expansion, command substitution, and arithmetic expansion.
-When not performing substring expansion, \fBbash\fP tests for a parameter
-that is unset or null; omitting the colon results in a test only for a
-parameter that is unset.
-.PP
-.PD 0
-.TP
-${\fIparameter\fP\fB:\-\fP\fIword\fP}
-\fBUse Default Values\fP. If
-.I parameter
-is unset or null, the expansion of
-.I word
-is substituted. Otherwise, the value of
-.I parameter
-is substituted.
-.TP
-${\fIparameter\fP\fB:=\fP\fIword\fP}
-\fBAssign Default Values\fP.
-If
-.I parameter
-is unset or null, the expansion of
-.I word
-is assigned to
-.IR parameter .
-The value of
-.I parameter
-is then substituted. Positional parameters and special parameters may
-not be assigned to in this way.
-.TP
-${\fIparameter\fP\fB:?\fP\fIword\fP}
-\fBDisplay Error if Null or Unset\fP.
-If
-.I parameter
-is null or unset, the expansion of \fIword\fP (or a message to that effect
-if
-.I word
-is not present) is written to the standard error and the shell, if it
-is not interactive, exits. Otherwise, the value of \fIparameter\fP is
-substituted.
-.TP
-${\fIparameter\fP\fB:+\fP\fIword\fP}
-\fBUse Alternate Value\fP.
-If
-.I parameter
-is null or unset, nothing is substituted, otherwise the expansion of
-.I word
-is substituted.
-.TP
-${\fIparameter\fP\fB:\fP\fIoffset\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB:\fP\fIoffset\fP\fB:\fP\fIlength\fP}
-.PD
-\fBSubstring Expansion.\fP
-Expands to up to \fIlength\fP characters of \fIparameter\fP
-starting at the character specified by \fIoffset\fP.
-If \fIlength\fP is omitted, expands to the substring of
-\fIparameter\fP starting at the character specified by \fIoffset\fP.
-\fIlength\fP and \fIoffset\fP are arithmetic expressions (see
-.SM
-.B
-ARITHMETIC EVALUATION
-below).
-\fIlength\fP must evaluate to a number greater than or equal to zero.
-If \fIoffset\fP evaluates to a number less than zero, the value
-is used as an offset from the end of the value of \fIparameter\fP.
-If \fIparameter\fP is \fB@\fP, the result is \fIlength\fP positional
-parameters beginning at \fIoffset\fP.
-If \fIparameter\fP is an array name indexed by @ or *,
-the result is the \fIlength\fP
-members of the array beginning with ${\fIparameter\fP[\fIoffset\fP]}.
-Substring indexing is zero-based unless the positional parameters
-are used, in which case the indexing starts at 1.
-.TP
-${\fB!\fP\fIprefix\fP\fB*\fP}
-.PD 0
-.TP
-${\fB!\fP\fIprefix\fP\fB@\fP}
-.PD
-Expands to the names of variables whose names begin with \fIprefix\fP,
-separated by the first character of the
-.SM
-.B IFS
-special variable.
-.TP
-${\fB!\fP\fIname\fP[\fI@\fP]}
-.PD 0
-.TP
-${\fB!\fP\fIname\fP[\fI*\fP]}
-.PD
-If \fIname\fP is an array variable, expands to the list of array indices
-(keys) assigned in \fIname\fP.
-If \fIname\fP is not an array, expands to 0 if \fIname\fP is set and null
-otherwise.
-When \fI@\fP is used and the expansion appears within double quotes, each
-key expands to a separate word.
-.TP
-${\fB#\fP\fIparameter\fP}
-The length in characters of the value of \fIparameter\fP is substituted.
-If
-.I parameter
-is
-.B *
-or
-.BR @ ,
-the value substituted is the number of positional parameters.
-If
-.I parameter
-is an array name subscripted by
-.B *
-or
-.BR @ ,
-the value substituted is the number of elements in the array.
-.TP
-${\fIparameter\fP\fB#\fP\fIword\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB##\fP\fIword\fP}
-.PD
-The
-.I word
-is expanded to produce a pattern just as in pathname
-expansion. If the pattern matches the beginning of
-the value of
-.IR parameter ,
-then the result of the expansion is the expanded value of
-.I parameter
-with the shortest matching pattern (the ``\fB#\fP'' case) or the
-longest matching pattern (the ``\fB##\fP'' case) deleted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-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\fIword\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB%%\fP\fIword\fP}
-.PD
-The \fIword\fP is expanded to produce a pattern just as in
-pathname expansion.
-If the pattern matches a trailing portion of the expanded value of
-.IR parameter ,
-then the result of the expansion is the expanded value of
-.I parameter
-with the shortest matching pattern (the ``\fB%\fP'' case) or the
-longest matching pattern (the ``\fB%%\fP'' case) deleted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-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 \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
-of the expanded value of \fIparameter\fP.
-If \fIstring\fP is null, matches of \fIpattern\fP are deleted
-and the \fB/\fP following \fIpattern\fP may be omitted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the substitution operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-the substitution operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-.SS Command Substitution
-.PP
-\fICommand substitution\fP allows the output of a command to replace
-the command name. There are two forms:
-.PP
-.RS
-.PP
-\fB$(\fP\fIcommand\fP\|\fB)\fP
-.RE
-or
-.RS
-\fB`\fP\fIcommand\fP\fB`\fP
-.RE
-.PP
-.B Bash
-performs the expansion by executing \fIcommand\fP and
-replacing the command substitution with the standard output of the
-command, with any trailing newlines deleted.
-Embedded newlines are not deleted, but they may be removed during
-word splitting.
-The command substitution \fB$(cat \fIfile\fP)\fR can be replaced by
-the equivalent but faster \fB$(< \fIfile\fP)\fR.
-.PP
-When the old-style backquote form of substitution is used,
-backslash retains its literal meaning except when followed by
-.BR $ ,
-.BR ` ,
-or
-.BR \e .
-The first backquote not preceded by a backslash terminates the
-command substitution.
-When using the $(\^\fIcommand\fP\|) form, all characters between the
-parentheses make up the command; none are treated specially.
-.PP
-Command substitutions may be nested. To nest when using the backquoted form,
-escape the inner backquotes with backslashes.
-.PP
-If the substitution appears within double quotes, word splitting and
-pathname expansion are not performed on the results.
-.SS Arithmetic Expansion
-.PP
-Arithmetic expansion allows the evaluation of an arithmetic expression
-and the substitution of the result. The format for arithmetic expansion is:
-.RS
-.PP
-\fB$((\fP\fIexpression\fP\fB))\fP
-.RE
-.PP
-The
-.I expression
-is treated as if it were within double quotes, but a double quote
-inside the parentheses is not treated specially.
-All tokens in the expression undergo parameter expansion, string
-expansion, command substitution, and quote removal.
-Arithmetic expansions may be nested.
-.PP
-The evaluation is performed according to the rules listed below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-If
-.I expression
-is invalid,
-.B bash
-prints a message indicating failure and no substitution occurs.
-.SS Process Substitution
-.PP
-\fIProcess substitution\fP is supported on systems that support named
-pipes (\fIFIFOs\fP) or the \fB/dev/fd\fP method of naming open files.
-It takes the form of
-\fB<(\fP\fIlist\^\fP\fB)\fP
-or
-\fB>(\fP\fIlist\^\fP\fB)\fP.
-The process \fIlist\fP is run with its input or output connected to a
-\fIFIFO\fP or some file in \fB/dev/fd\fP. The name of this file is
-passed as an argument to the current command as the result of the
-expansion. If the \fB>(\fP\fIlist\^\fP\fB)\fP form is used, writing to
-the file will provide input for \fIlist\fP. If the
-\fB<(\fP\fIlist\^\fP\fB)\fP form is used, the file passed as an
-argument should be read to obtain the output of \fIlist\fP.
-.PP
-When available, process substitution is performed
-simultaneously with parameter and variable expansion,
-command substitution,
-and arithmetic expansion.
-.SS Word Splitting
-.PP
-The shell scans the results of
-parameter expansion,
-command substitution,
-and
-arithmetic expansion
-that did not occur within double quotes for
-.IR "word splitting" .
-.PP
-The shell treats each character of
-.SM
-.B IFS
-as a delimiter, and splits the results of the other
-expansions into words on these characters. If
-.SM
-.B IFS
-is unset, or its
-value is exactly
-.BR <space><tab><newline> ,
-the default, then
-any sequence of
-.SM
-.B IFS
-characters serves to delimit words. If
-.SM
-.B IFS
-has a value other than the default, then sequences of
-the whitespace characters
-.B space
-and
-.B tab
-are ignored at the beginning and end of the
-word, as long as the whitespace character is in the
-value of
-.SM
-.BR IFS
-(an
-.SM
-.B IFS
-whitespace character).
-Any character in
-.SM
-.B IFS
-that is not
-.SM
-.B IFS
-whitespace, along with any adjacent
-.SM
-.B IFS
-whitespace characters, delimits a field.
-A sequence of
-.SM
-.B IFS
-whitespace characters is also treated as a delimiter.
-If the value of
-.SM
-.B IFS
-is null, no word splitting occurs.
-.PP
-Explicit null arguments (\^\f3"\^"\fP or \^\f3'\^'\fP\^) are retained.
-Unquoted implicit null arguments, resulting from the expansion of
-parameters that have no values, are removed.
-If a parameter with no value is expanded within double quotes, a
-null argument results and is retained.
-.PP
-Note that if no expansion occurs, no splitting
-is performed.
-.SS Pathname Expansion
-.PP
-After word splitting,
-unless the
-.B \-f
-option has been set,
-.B bash
-scans each word for the characters
-.BR * ,
-.BR ? ,
-and
-.BR [ .
-If one of these characters appears, then the word is
-regarded as a
-.IR pattern ,
-and replaced with an alphabetically sorted list of
-file names matching the pattern.
-If no matching file names are found,
-and the shell option
-.B nullglob
-is disabled, the word is left unchanged.
-If the
-.B nullglob
-option is set, and no matches are found,
-the word is removed.
-If the shell option
-.B nocaseglob
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-When a pattern is used for pathname expansion,
-the character
-.B ``.''
-at the start of a name or immediately following a slash
-must be matched explicitly, unless the shell option
-.B dotglob
-is set.
-When matching a pathname, the slash character must always be
-matched explicitly.
-In other cases, the
-.B ``.''
-character is not treated specially.
-See the description of
-.B shopt
-below under
-.SM
-.B SHELL BUILTIN COMMANDS
-for a description of the
-.BR nocaseglob ,
-.BR nullglob ,
-and
-.B dotglob
-shell options.
-.PP
-The
-.SM
-.B GLOBIGNORE
-shell variable may be used to restrict the set of file names matching a
-.IR pattern .
-If
-.SM
-.B GLOBIGNORE
-is set, each matching file name that also matches one of the patterns in
-.SM
-.B GLOBIGNORE
-is removed from the list of matches.
-The file names
-.B ``.''
-and
-.B ``..''
-are always ignored when
-.SM
-.B GLOBIGNORE
-is set and not null. However, setting
-.SM
-.B GLOBIGNORE
-to a non-null value has the effect of enabling the
-.B dotglob
-shell option, so all other file names beginning with a
-.B ``.''
-will match.
-To get the old behavior of ignoring file names beginning with a
-.BR ``.'' ,
-make
-.B ``.*''
-one of the patterns in
-.SM
-.BR GLOBIGNORE .
-The
-.B dotglob
-option is disabled when
-.SM
-.B GLOBIGNORE
-is unset.
-.PP
-\fBPattern Matching\fP
-.PP
-Any character that appears in a pattern, other than the special pattern
-characters described below, matches itself. The NUL character may not
-occur in a pattern. A backslash escapes the following character; the
-escaping backslash is discarded when matching.
-The special pattern characters must be quoted if
-they are to be matched literally.
-.PP
-The special pattern characters have the following meanings:
-.PP
-.PD 0
-.TP
-.B *
-Matches any string, including the null string.
-.TP
-.B ?
-Matches any single character.
-.TP
-.B [...]
-Matches any one of the enclosed characters. A pair of characters
-separated by a hyphen denotes a
-\fIrange expression\fP;
-any character that sorts between those two characters, inclusive,
-using the current locale's collating sequence and character set,
-is matched. If the first character following the
-.B [
-is a
-.B !
-or a
-.B ^
-then any character not enclosed is matched.
-The sorting order of characters in range expressions is determined by
-the current locale and the value of the \fBLC_COLLATE\fP shell variable,
-if set.
-A
-.B \-
-may be matched by including it as the first or last character
-in the set.
-A
-.B ]
-may be matched by including it as the first character
-in the set.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and
-.BR ] ,
-\fIcharacter classes\fP can be specified using the syntax
-\fB[:\fP\fIclass\fP\fB:]\fP, where \fIclass\fP is one of the
-following classes defined in the POSIX.2 standard:
-.PP
-.RS
-.B
-.if n alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit
-.if t alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit
-.br
-A character class matches any character belonging to that class.
-The \fBword\fP character class matches letters, digits, and the character _.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and
-.BR ] ,
-an \fIequivalence class\fP can be specified using the syntax
-\fB[=\fP\fIc\fP\fB=]\fP, which matches all characters with the
-same collation weight (as defined by the current locale) as
-the character \fIc\fP.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and
-.BR ] ,
-the syntax \fB[.\fP\fIsymbol\fP\fB.]\fP matches the collating symbol
-\fIsymbol\fP.
-.RE
-.PD
-.PP
-If the \fBextglob\fP shell option is enabled using the \fBshopt\fP
-builtin, several extended pattern matching operators are recognized.
-In the following description, a \fIpattern-list\fP is a list of one
-or more patterns separated by a \fB|\fP.
-Composite patterns may be formed using one or more of the following
-sub-patterns:
-.sp 1
-.PD 0
-.RS
-.TP
-\fB?(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches zero or one occurrence of the given patterns
-.TP
-\fB*(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches zero or more occurrences of the given patterns
-.TP
-\fB+(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches one or more occurrences of the given patterns
-.TP
-\fB@(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches exactly one of the given patterns
-.TP
-\fB!(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches anything except one of the given patterns
-.RE
-.PD
-.SS Quote Removal
-.PP
-After the preceding expansions, all unquoted occurrences of the
-characters
-.BR \e ,
-.BR ' ,
-and \^\f3"\fP\^ that did not result from one of the above
-expansions are removed.
-.SH REDIRECTION
-Before a command is executed, its input and output
-may be
-.I redirected
-using a special notation interpreted by the shell.
-Redirection may also be used to open and close files for the
-current shell execution environment. The following redirection
-operators may precede or appear anywhere within a
-.I simple command
-or may follow a
-.IR command .
-Redirections are processed in the order they appear, from
-left to right.
-.PP
-In the following descriptions, if the file descriptor number is
-omitted, and the first character of the redirection operator is
-.BR < ,
-the redirection refers to the standard input (file descriptor
-0). If the first character of the redirection operator is
-.BR > ,
-the redirection refers to the standard output (file descriptor
-1).
-.PP
-The word following the redirection operator in the following
-descriptions, unless otherwise noted, is subjected to brace expansion,
-tilde expansion, parameter expansion, command substitution, arithmetic
-expansion, quote removal, pathname expansion, and word splitting.
-If it expands to more than one word,
-.B bash
-reports an error.
-.PP
-Note that the order of redirections is significant. For example,
-the command
-.RS
-.PP
-ls \fB>\fP dirlist 2\fB>&\fP1
-.RE
-.PP
-directs both standard output and standard error to the file
-.IR dirlist ,
-while the command
-.RS
-.PP
-ls 2\fB>&\fP1 \fB>\fP dirlist
-.RE
-.PP
-directs only the standard output to file
-.IR dirlist ,
-because the standard error was duplicated as standard output
-before the standard output was redirected to
-.IR dirlist .
-.PP
-\fBBash\fP handles several filenames specially when they are used in
-redirections, as described in the following table:
-.RS
-.PP
-.PD 0
-.TP
-.B /dev/fd/\fIfd\fP
-If \fIfd\fP is a valid integer, file descriptor \fIfd\fP is duplicated.
-.TP
-.B /dev/stdin
-File descriptor 0 is duplicated.
-.TP
-.B /dev/stdout
-File descriptor 1 is duplicated.
-.TP
-.B /dev/stderr
-File descriptor 2 is duplicated.
-.TP
-.B /dev/tcp/\fIhost\fP/\fIport\fP
-If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP
-is an integer port number or service name, \fBbash\fP attempts to open
-a TCP connection to the corresponding socket.
-.TP
-.B /dev/udp/\fIhost\fP/\fIport\fP
-If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP
-is an integer port number or service name, \fBbash\fP attempts to open
-a UDP connection to the corresponding socket.
-.PD
-.RE
-.PP
-A failure to open or create a file causes the redirection to fail.
-.SS Redirecting Input
-.PP
-Redirection of input causes the file whose name results from
-the expansion of
-.I word
-to be opened for reading on file descriptor
-.IR n ,
-or the standard input (file descriptor 0) if
-.I n
-is not specified.
-.PP
-The general format for redirecting input is:
-.RS
-.PP
-[\fIn\fP]\fB<\fP\fIword\fP
-.RE
-.SS Redirecting Output
-.PP
-Redirection of output causes the file whose name results from
-the expansion of
-.I word
-to be opened for writing on file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if
-.I n
-is not specified. If the file does not exist it is created;
-if it does exist it is truncated to zero size.
-.PP
-The general format for redirecting output is:
-.RS
-.PP
-[\fIn\fP]\fB>\fP\fIword\fP
-.RE
-.PP
-If the redirection operator is
-.BR > ,
-and the
-.B noclobber
-option to the
-.B set
-builtin has been enabled, the redirection will fail if the file
-whose name results from the expansion of \fIword\fP exists and is
-a regular file.
-If the redirection operator is
-.BR >| ,
-or the redirection operator is
-.B >
-and the
-.B noclobber
-option to the
-.B set
-builtin command is not enabled, the redirection is attempted even
-if the file named by \fIword\fP exists.
-.SS Appending Redirected Output
-.PP
-Redirection of output in this fashion
-causes the file whose name results from
-the expansion of
-.I word
-to be opened for appending on file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if
-.I n
-is not specified. If the file does not exist it is created.
-.PP
-The general format for appending output is:
-.RS
-.PP
-[\fIn\fP]\fB>>\fP\fIword\fP
-.RE
-.PP
-.SS Redirecting Standard Output and Standard Error
-.PP
-.B Bash
-allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be redirected to the file whose name is the
-expansion of
-.I word
-with this construct.
-.PP
-There are two formats for redirecting standard output and
-standard error:
-.RS
-.PP
-\fB&>\fP\fIword\fP
-.RE
-and
-.RS
-\fB>&\fP\fIword\fP
-.RE
-.PP
-Of the two forms, the first is preferred.
-This is semantically equivalent to
-.RS
-.PP
-\fB>\fP\fIword\fP 2\fB>&\fP1
-.RE
-.SS Here Documents
-.PP
-This type of redirection instructs the shell to read input from the
-current source until a line containing only
-.I word
-(with no trailing blanks)
-is seen. All of
-the lines read up to that point are then used as the standard
-input for a command.
-.PP
-The format of here-documents is:
-.RS
-.PP
-.nf
-\fB<<\fP[\fB\-\fP]\fIword\fP
- \fIhere-document\fP
-\fIdelimiter\fP
-.fi
-.RE
-.PP
-No parameter expansion, command substitution, arithmetic expansion,
-or pathname expansion is performed on
-.IR word .
-If any characters in
-.I word
-are quoted, the
-.I delimiter
-is the result of quote removal on
-.IR word ,
-and the lines in the here-document are not expanded.
-If \fIword\fP is unquoted,
-all lines of the here-document are subjected to parameter expansion,
-command substitution, and arithmetic expansion. In the latter
-case, the character sequence
-.B \e<newline>
-is ignored, and
-.B \e
-must be used to quote the characters
-.BR \e ,
-.BR $ ,
-and
-.BR ` .
-.PP
-If the redirection operator is
-.BR <<\- ,
-then all leading tab characters are stripped from input lines and the
-line containing
-.IR delimiter .
-This allows
-here-documents within shell scripts to be indented in a
-natural fashion.
-.SS "Here Strings"
-A variant of here documents, the format is:
-.RS
-.PP
-.nf
-\fB<<<\fP\fIword\fP
-.fi
-.RE
-.PP
-The \fIword\fP is expanded and supplied to the command on its standard
-input.
-.SS "Duplicating File Descriptors"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<&\fP\fIword\fP
-.RE
-.PP
-is used to duplicate input file descriptors.
-If
-.I word
-expands to one or more digits, the file descriptor denoted by
-.I n
-is made to be a copy of that file descriptor.
-If the digits in
-.I word
-do not specify a file descriptor open for input, a redirection error occurs.
-If
-.I word
-evaluates to
-.BR \- ,
-file descriptor
-.I n
-is closed. If
-.I n
-is not specified, the standard input (file descriptor 0) is used.
-.PP
-The operator
-.RS
-.PP
-[\fIn\fP]\fB>&\fP\fIword\fP
-.RE
-.PP
-is used similarly to duplicate output file descriptors. If
-.I n
-is not specified, the standard output (file descriptor 1) is used.
-If the digits in
-.I word
-do not specify a file descriptor open for output, a redirection error occurs.
-As a special case, if \fIn\fP is omitted, and \fIword\fP does not
-expand to one or more digits, the standard output and standard
-error are redirected as described previously.
-.SS "Moving File Descriptors"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<&\fP\fIdigit\fP\fB\-\fP
-.RE
-.PP
-moves the file descriptor \fIdigit\fP to file descriptor
-.IR n ,
-or the standard input (file descriptor 0) if \fIn\fP is not specified.
-\fIdigit\fP is closed after being duplicated to \fIn\fP.
-.PP
-Similarly, the redirection operator
-.RS
-.PP
-[\fIn\fP]\fB>&\fP\fIdigit\fP\fB\-\fP
-.RE
-.PP
-moves the file descriptor \fIdigit\fP to file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if \fIn\fP is not specified.
-.SS "Opening File Descriptors for Reading and Writing"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<>\fP\fIword\fP
-.RE
-.PP
-causes the file whose name is the expansion of
-.I word
-to be opened for both reading and writing on file descriptor
-.IR n ,
-or on file descriptor 0 if
-.I n
-is not specified. If the file does not exist, it is created.
-.SH ALIASES
-\fIAliases\fP allow a string to be substituted for a word when it is used
-as the first word of a simple command.
-The shell maintains a list of aliases that may be set and unset with the
-.B alias
-and
-.B unalias
-builtin commands (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-The first word of each command, if unquoted,
-is checked to see if it has an
-alias. If so, that word is replaced by the text of the alias.
-The alias name and the replacement text may contain any valid
-shell input, including the
-.I metacharacters
-listed above, with the exception that the alias name may not
-contain \fI=\fP. The first word of the replacement text is tested
-for aliases, but a word that is identical to an alias being expanded
-is not expanded a second time. This means that one may alias
-.B ls
-to
-.BR "ls \-F" ,
-for instance, and
-.B bash
-does not try to recursively expand the replacement text.
-If the last character of the alias value is a
-.IR blank ,
-then the next command
-word following the alias is also checked for alias expansion.
-.PP
-Aliases are created and listed with the
-.B alias
-command, and removed with the
-.B unalias
-command.
-.PP
-There is no mechanism for using arguments in the replacement text.
-If arguments are needed, a shell function should be used (see
-.SM
-.B FUNCTIONS
-below).
-.PP
-Aliases are not expanded when the shell is not interactive, unless
-the
-.B expand_aliases
-shell option is set using
-.B shopt
-(see the description of
-.B shopt
-under
-.SM
-\fBSHELL BUILTIN COMMANDS\fP
-below).
-.PP
-The rules concerning the definition and use of aliases are
-somewhat confusing.
-.B Bash
-always reads at least one complete line
-of input before executing any
-of the commands on that line. Aliases are expanded when a
-command is read, not when it is executed. Therefore, an
-alias definition appearing on the same line as another
-command does not take effect until the next line of input is read.
-The commands following the alias definition
-on that line are not affected by the new alias.
-This behavior is also an issue when functions are executed.
-Aliases are expanded when a function definition is read,
-not when the function is executed, because a function definition
-is itself a compound command. As a consequence, aliases
-defined in a function are not available until after that
-function is executed. To be safe, always put
-alias definitions on a separate line, and do not use
-.B alias
-in compound commands.
-.PP
-For almost every purpose, aliases are superseded by
-shell functions.
-.SH FUNCTIONS
-A shell function, defined as described above under
-.SM
-.BR "SHELL GRAMMAR" ,
-stores a series of commands for later execution.
-When the name of a shell function is used as a simple command name,
-the list of commands associated with that function name is executed.
-Functions are executed in the context of the
-current shell; no new process is created to interpret
-them (contrast this with the execution of a shell script).
-When a function is executed, the arguments to the
-function become the positional parameters
-during its execution.
-The special parameter
-.B #
-is updated to reflect the change. Positional parameter 0
-is unchanged.
-The first element of the
-.SM
-.B FUNCNAME
-variable is set to the name of the function while the function
-is executing.
-All other aspects of the shell execution
-environment are identical between a function and its caller
-with the exception that the
-.SM
-.B DEBUG
-trap (see the description of the
-.B trap
-builtin under
-.SM
-.B SHELL BUILTIN COMMANDS
-below) is not inherited unless the function has been given the
-\fBtrace\fP attribute (see the description of the
-.SM
-.B declare
-builtin below) or the
-\fB\-o functrace\fP shell option has been enabled with
-the \fBset\fP builtin
-(in which case all functions inherit the \fBDEBUG\fP trap).
-.PP
-Variables local to the function may be declared with the
-.B local
-builtin command. Ordinarily, variables and their values
-are shared between the function and its caller.
-.PP
-If the builtin command
-.B return
-is executed in a function, the function completes and
-execution resumes with the next command after the function
-call.
-Any command associated with the \fBRETURN\fP trap is executed
-before execution resumes.
-When a function completes, the values of the
-positional parameters and the special parameter
-.B #
-are restored to the values they had prior to the function's
-execution.
-.PP
-Function names and definitions may be listed with the
-.B \-f
-option to the
-.B declare
-or
-.B typeset
-builtin commands. The
-.B \-F
-option to
-.B declare
-or
-.B typeset
-will list the function names only
-(and optionally the source file and line number, if the \fBextdebug\fP
-shell option is enabled).
-Functions may be exported so that subshells
-automatically have them defined with the
-.B \-f
-option to the
-.B export
-builtin.
-Note that shell functions and variables with the same name may result
-in multiple identically-named entries in the environment passed to the
-shell's children.
-Care should be taken in cases where this may cause a problem.
-.PP
-Functions may be recursive. No limit is imposed on the number
-of recursive calls.
-.SH "ARITHMETIC EVALUATION"
-The shell allows arithmetic expressions to be evaluated, under
-certain circumstances (see the \fBlet\fP and \fBdeclare\fP builtin
-commands and \fBArithmetic Expansion\fP).
-Evaluation is done in fixed-width integers with no check for overflow,
-though division by 0 is trapped and flagged as an error.
-The operators and their precedence, associativity, and values
-are the same as in the C language.
-The following list of operators is grouped into levels of
-equal-precedence operators.
-The levels are listed in order of decreasing precedence.
-.PP
-.PD 0
-.TP
-.B \fIid\fP++ \fIid\fP\-\-
-variable post-increment and post-decrement
-.TP
-.B ++\fIid\fP \-\-\fIid\fP
-variable pre-increment and pre-decrement
-.TP
-.B \- +
-unary minus and plus
-.TP
-.B ! ~
-logical and bitwise negation
-.TP
-.B **
-exponentiation
-.TP
-.B * / %
-multiplication, division, remainder
-.TP
-.B + \-
-addition, subtraction
-.TP
-.B << >>
-left and right bitwise shifts
-.TP
-.B <= >= < >
-comparison
-.TP
-.B == !=
-equality and inequality
-.TP
-.B &
-bitwise AND
-.TP
-.B ^
-bitwise exclusive OR
-.TP
-.B |
-bitwise OR
-.TP
-.B &&
-logical AND
-.TP
-.B ||
-logical OR
-.TP
-.B \fIexpr\fP?\fIexpr\fP:\fIexpr\fP
-conditional operator
-.TP
-.B = *= /= %= += \-= <<= >>= &= ^= |=
-assignment
-.TP
-.B \fIexpr1\fP , \fIexpr2\fP
-comma
-.PD
-.PP
-Shell variables are allowed as operands; parameter expansion is
-performed before the expression is evaluated.
-Within an expression, shell variables may also be referenced by name
-without using the parameter expansion syntax.
-A shell variable that is null or unset evaluates to 0 when referenced
-by name without using the parameter expansion syntax.
-The value of a variable is evaluated as an arithmetic expression
-when it is referenced, or when a variable which has been given the
-\fIinteger\fP attribute using \fBdeclare -i\fP is assigned a value.
-A null value evaluates to 0.
-A shell variable need not have its integer attribute
-turned on to be used in an expression.
-.PP
-Constants with a leading 0 are interpreted as octal numbers.
-A leading 0x or 0X denotes hexadecimal.
-Otherwise, numbers take the form [\fIbase#\fP]n, where \fIbase\fP
-is a decimal number between 2 and 64 representing the arithmetic
-base, and \fIn\fP is a number in that base.
-If \fIbase#\fP is omitted, then base 10 is used.
-The digits greater than 9 are represented by the lowercase letters,
-the uppercase letters, @, and _, in that order.
-If \fIbase\fP is less than or equal to 36, lowercase and uppercase
-letters may be used interchangably to represent numbers between 10
-and 35.
-.PP
-Operators are evaluated in order of precedence. Sub-expressions in
-parentheses are evaluated first and may override the precedence
-rules above.
-.SH "CONDITIONAL EXPRESSIONS"
-Conditional expressions are used by the \fB[[\fP compound command and
-the \fBtest\fP and \fB[\fP builtin commands to test file attributes
-and perform string and arithmetic comparisons.
-Expressions are formed from the following unary or binary primaries.
-If any \fIfile\fP argument to one of the primaries is of the form
-\fI/dev/fd/n\fP, then file descriptor \fIn\fP is checked.
-If the \fIfile\fP argument to one of the primaries is one of
-\fI/dev/stdin\fP, \fI/dev/stdout\fP, or \fI/dev/stderr\fP, file
-descriptor 0, 1, or 2, respectively, is checked.
-.sp 1
-.PD 0
-.TP
-.B \-a \fIfile\fP
-True if \fIfile\fP exists.
-.TP
-.B \-b \fIfile\fP
-True if \fIfile\fP exists and is a block special file.
-.TP
-.B \-c \fIfile\fP
-True if \fIfile\fP exists and is a character special file.
-.TP
-.B \-d \fIfile\fP
-True if \fIfile\fP exists and is a directory.
-.TP
-.B \-e \fIfile\fP
-True if \fIfile\fP exists.
-.TP
-.B \-f \fIfile\fP
-True if \fIfile\fP exists and is a regular file.
-.TP
-.B \-g \fIfile\fP
-True if \fIfile\fP exists and is set-group-id.
-.TP
-.B \-h \fIfile\fP
-True if \fIfile\fP exists and is a symbolic link.
-.TP
-.B \-k \fIfile\fP
-True if \fIfile\fP exists and its ``sticky'' bit is set.
-.TP
-.B \-p \fIfile\fP
-True if \fIfile\fP exists and is a named pipe (FIFO).
-.TP
-.B \-r \fIfile\fP
-True if \fIfile\fP exists and is readable.
-.TP
-.B \-s \fIfile\fP
-True if \fIfile\fP exists and has a size greater than zero.
-.TP
-.B \-t \fIfd\fP
-True if file descriptor
-.I fd
-is open and refers to a terminal.
-.TP
-.B \-u \fIfile\fP
-True if \fIfile\fP exists and its set-user-id bit is set.
-.TP
-.B \-w \fIfile\fP
-True if \fIfile\fP exists and is writable.
-.TP
-.B \-x \fIfile\fP
-True if \fIfile\fP exists and is executable.
-.TP
-.B \-O \fIfile\fP
-True if \fIfile\fP exists and is owned by the effective user id.
-.TP
-.B \-G \fIfile\fP
-True if \fIfile\fP exists and is owned by the effective group id.
-.TP
-.B \-L \fIfile\fP
-True if \fIfile\fP exists and is a symbolic link.
-.TP
-.B \-S \fIfile\fP
-True if \fIfile\fP exists and is a socket.
-.TP
-.B \-N \fIfile\fP
-True if \fIfile\fP exists and has been modified since it was last read.
-.TP
-\fIfile1\fP \-\fBnt\fP \fIfile2\fP
-True if \fIfile1\fP is newer (according to modification date) than \fIfile2\fP,
-or if \fIfile1\fP exists and \fPfile2\fP does not.
-.TP
-\fIfile1\fP \-\fBot\fP \fIfile2\fP
-True if \fIfile1\fP is older than \fIfile2\fP, or if \fIfile2\fP exists
-and \fIfile1\fP does not.
-.TP
-\fIfile1\fP \fB\-ef\fP \fIfile2\fP
-True if \fIfile1\fP and \fIfile2\fP refer to the same device and
-inode numbers.
-.TP
-.B \-o \fIoptname\fP
-True if shell option
-.I optname
-is enabled.
-See the list of options under the description of the
-.B \-o
-option to the
-.B set
-builtin below.
-.TP
-.B \-z \fIstring\fP
-True if the length of \fIstring\fP is zero.
-.TP
-.B \-n \fIstring\fP
-.TP
-\fIstring\fP
-True if the length of
-.I string
-is non-zero.
-.TP
-\fIstring1\fP \fB==\fP \fIstring2\fP
-True if the strings are equal. \fB=\fP may be used in place of
-\fB==\fP for strict POSIX compliance.
-.TP
-\fIstring1\fP \fB!=\fP \fIstring2\fP
-True if the strings are not equal.
-.TP
-\fIstring1\fP \fB<\fP \fIstring2\fP
-True if \fIstring1\fP sorts before \fIstring2\fP lexicographically
-in the current locale.
-.TP
-\fIstring1\fP \fB>\fP \fIstring2\fP
-True if \fIstring1\fP sorts after \fIstring2\fP lexicographically
-in the current locale.
-.TP
-.I \fIarg1\fP \fBOP\fP \fIarg2\fP
-.SM
-.B OP
-is one of
-.BR \-eq ,
-.BR \-ne ,
-.BR \-lt ,
-.BR \-le ,
-.BR \-gt ,
-or
-.BR \-ge .
-These arithmetic binary operators return true if \fIarg1\fP
-is equal to, not equal to, less than, less than or equal to,
-greater than, or greater than or equal to \fIarg2\fP, respectively.
-.I Arg1
-and
-.I arg2
-may be positive or negative integers.
-.PD
-.SH "SIMPLE COMMAND EXPANSION"
-When a simple command is executed, the shell performs the following
-expansions, assignments, and redirections, from left to right.
-.IP 1.
-The words that the parser has marked as variable assignments (those
-preceding the command name) and redirections are saved for later
-processing.
-.IP 2.
-The words that are not variable assignments or redirections are
-expanded. If any words remain after expansion, the first word
-is taken to be the name of the command and the remaining words are
-the arguments.
-.IP 3.
-Redirections are performed as described above under
-.SM
-.BR REDIRECTION .
-.IP 4.
-The text after the \fB=\fP in each variable assignment undergoes tilde
-expansion, parameter expansion, command substitution, arithmetic expansion,
-and quote removal before being assigned to the variable.
-.PP
-If no command name results, the variable assignments affect the current
-shell environment. Otherwise, the variables are added to the environment
-of the executed command and do not affect the current shell environment.
-If any of the assignments attempts to assign a value to a readonly variable,
-an error occurs, and the command exits with a non-zero status.
-.PP
-If no command name results, redirections are performed, but do not
-affect the current shell environment. A redirection error causes the
-command to exit with a non-zero status.
-.PP
-If there is a command name left after expansion, execution proceeds as
-described below. Otherwise, the command exits. If one of the expansions
-contained a command substitution, the exit status of the command is
-the exit status of the last command substitution performed. If there
-were no command substitutions, the command exits with a status of zero.
-.SH "COMMAND EXECUTION"
-After a command has been split into words, if it results in a
-simple command and an optional list of arguments, the following
-actions are taken.
-.PP
-If the command name contains no slashes, the shell attempts to
-locate it. If there exists a shell function by that name, that
-function is invoked as described above in
-.SM
-.BR FUNCTIONS .
-If the name does not match a function, the shell searches for
-it in the list of shell builtins. If a match is found, that
-builtin is invoked.
-.PP
-If the name is neither a shell function nor a builtin,
-and contains no slashes,
-.B bash
-searches each element of the
-.SM
-.B PATH
-for a directory containing an executable file by that name.
-.B Bash
-uses a hash table to remember the full pathnames of executable
-files (see
-.B hash
-under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-A full search of the directories in
-.SM
-.B PATH
-is performed only if the command is not found in the hash table.
-If the search is unsuccessful, the shell prints an error
-message and returns an exit status of 127.
-.PP
-If the search is successful, or if the command name contains
-one or more slashes, the shell executes the named program in a
-separate execution environment.
-Argument 0 is set to the name given, and the remaining arguments
-to the command are set to the arguments given, if any.
-.PP
-If this execution fails because the file is not in executable
-format, and the file is not a directory, it is assumed to be
-a \fIshell script\fP, a file
-containing shell commands. A subshell is spawned to execute
-it. This subshell reinitializes itself, so
-that the effect is as if a new shell had been invoked
-to handle the script, with the exception that the locations of
-commands remembered by the parent (see
-.B hash
-below under
-.SM
-\fBSHELL BUILTIN COMMANDS\fP)
-are retained by the child.
-.PP
-If the program is a file beginning with
-.BR #! ,
-the remainder of the first line specifies an interpreter
-for the program. The shell executes the
-specified interpreter on operating systems that do not
-handle this executable format themselves. The arguments to the
-interpreter consist of a single optional argument following the
-interpreter name on the first line of the program, followed
-by the name of the program, followed by the command
-arguments, if any.
-.SH COMMAND EXECUTION ENVIRONMENT
-The shell has an \fIexecution environment\fP, which consists of the
-following:
-.sp 1
-.IP \(bu
-open files inherited by the shell at invocation, as modified by
-redirections supplied to the \fBexec\fP builtin
-.IP \(bu
-the current working directory as set by \fBcd\fP, \fBpushd\fP, or
-\fBpopd\fP, or inherited by the shell at invocation
-.IP \(bu
-the file creation mode mask as set by \fBumask\fP or inherited from
-the shell's parent
-.IP \(bu
-current traps set by \fBtrap\fP
-.IP \(bu
-shell parameters that are set by variable assignment or with \fBset\fP
-or inherited from the shell's parent in the environment
-.IP \(bu
-shell functions defined during execution or inherited from the shell's
-parent in the environment
-.IP \(bu
-options enabled at invocation (either by default or with command-line
-arguments) or by \fBset\fP
-.IP \(bu
-options enabled by \fBshopt\fP
-.IP \(bu
-shell aliases defined with \fBalias\fP
-.IP \(bu
-various process IDs, including those of background jobs, the value
-of \fB$$\fP, and the value of \fB$PPID\fP
-.PP
-When a simple command other than a builtin or shell function
-is to be executed, it
-is invoked in a separate execution environment that consists of
-the following. Unless otherwise noted, the values are inherited
-from the shell.
-.sp 1
-.IP \(bu
-the shell's open files, plus any modifications and additions specified
-by redirections to the command
-.IP \(bu
-the current working directory
-.IP \(bu
-the file creation mode mask
-.IP \(bu
-shell variables and functions marked for export, along with variables
-exported for the command, passed in the environment
-.IP \(bu
-traps caught by the shell are reset to the values the inherited
-from the shell's parent, and traps ignored by the shell are ignored
-.PP
-A command invoked in this separate environment cannot affect the
-shell's execution environment.
-.PP
-Command substitution and asynchronous commands are invoked in a
-subshell environment that is a duplicate of the shell environment,
-except that traps caught by the shell are reset to the values
-that the shell inherited from its parent at invocation. Builtin
-commands that are invoked as part of a pipeline are also executed in a
-subshell environment. Changes made to the subshell environment
-cannot affect the shell's execution environment.
-.PP
-If a command is followed by a \fB&\fP and job control is not active, the
-default standard input for the command is the empty file \fI/dev/null\fP.
-Otherwise, the invoked command inherits the file descriptors of the calling
-shell as modified by redirections.
-.SH ENVIRONMENT
-When a program is invoked it is given an array of strings
-called the
-.IR environment .
-This is a list of
-\fIname\fP\-\fIvalue\fP pairs, of the form
-.IR "name\fR=\fPvalue" .
-.PP
-The shell provides several ways to manipulate the environment.
-On invocation, the shell scans its own environment and
-creates a parameter for each name found, automatically marking
-it for
-.I export
-to child processes. Executed commands inherit the environment.
-The
-.B export
-and
-.B declare \-x
-commands allow parameters and functions to be added to and
-deleted from the environment. If the value of a parameter
-in the environment is modified, the new value becomes part
-of the environment, replacing the old. The environment
-inherited by any executed command consists of the shell's
-initial environment, whose values may be modified in the shell,
-less any pairs removed by the
-.B unset
-command, plus any additions via the
-.B export
-and
-.B declare \-x
-commands.
-.PP
-The environment for any
-.I simple command
-or function may be augmented temporarily by prefixing it with
-parameter assignments, as described above in
-.SM
-.BR PARAMETERS .
-These assignment statements affect only the environment seen
-by that command.
-.PP
-If the
-.B \-k
-option is set (see the
-.B set
-builtin command below), then
-.I all
-parameter assignments are placed in the environment for a command,
-not just those that precede the command name.
-.PP
-When
-.B bash
-invokes an external command, the variable
-.B _
-is set to the full file name of the command and passed to that
-command in its environment.
-.SH "EXIT STATUS"
-For the shell's purposes, a command which exits with a
-zero exit status has succeeded. An exit status of zero
-indicates success. A non-zero exit status indicates failure.
-When a command terminates on a fatal signal \fIN\fP, \fBbash\fP uses
-the value of 128+\fIN\fP as the exit status.
-.PP
-If a command is not found, the child process created to
-execute it returns a status of 127. If a command is found
-but is not executable, the return status is 126.
-.PP
-If a command fails because of an error during expansion or redirection,
-the exit status is greater than zero.
-.PP
-Shell builtin commands return a status of 0 (\fItrue\fP) if
-successful, and non-zero (\fIfalse\fP) if an error occurs
-while they execute.
-All builtins return an exit status of 2 to indicate incorrect usage.
-.PP
-\fBBash\fP itself returns the exit status of the last command
-executed, unless a syntax error occurs, in which case it exits
-with a non-zero value. See also the \fBexit\fP builtin
-command below.
-.SH SIGNALS
-When \fBbash\fP is interactive, in the absence of any traps, it ignores
-.SM
-.B SIGTERM
-(so that \fBkill 0\fP does not kill an interactive shell),
-and
-.SM
-.B SIGINT
-is caught and handled (so that the \fBwait\fP builtin is interruptible).
-In all cases, \fBbash\fP ignores
-.SM
-.BR SIGQUIT .
-If job control is in effect,
-.B bash
-ignores
-.SM
-.BR SIGTTIN ,
-.SM
-.BR SIGTTOU ,
-and
-.SM
-.BR SIGTSTP .
-.PP
-Synchronous jobs started by \fBbash\fP have signal handlers
-set to the values inherited by the shell from its parent.
-When job control is not in effect, asynchronous commands
-ignore
-.SM
-.B SIGINT
-and
-.SM
-.B SIGQUIT
-as well.
-Commands run as a result of command substitution ignore the
-keyboard-generated job control signals
-.SM
-.BR SIGTTIN ,
-.SM
-.BR SIGTTOU ,
-and
-.SM
-.BR SIGTSTP .
-.PP
-The shell exits by default upon receipt of a
-.SM
-.BR SIGHUP .
-Before exiting, an interactive shell resends the
-.SM
-.B SIGHUP
-to all jobs, running or stopped.
-Stopped jobs are sent
-.SM
-.B SIGCONT
-to ensure that they receive the
-.SM
-.BR SIGHUP .
-To prevent the shell from
-sending the signal to a particular job, it should be removed from the
-jobs table with the
-.B disown
-builtin (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below) or marked
-to not receive
-.SM
-.B SIGHUP
-using
-.BR "disown \-h" .
-.PP
-If the
-.B huponexit
-shell option has been set with
-.BR shopt ,
-.B bash
-sends a
-.SM
-.B SIGHUP
-to all jobs when an interactive login shell exits.
-.PP
-When \fBbash\fP receives a signal for which a trap has been set while
-waiting for a command to complete, the trap will not be executed until
-the command completes.
-When \fBbash\fP is waiting for an asynchronous command via the \fBwait\fP
-builtin, the reception of a signal for which a trap has been set will
-cause the \fBwait\fP builtin to return immediately with an exit status
-greater than 128, immediately after which the trap is executed.
-.SH "JOB CONTROL"
-.I Job control
-refers to the ability to selectively stop (\fIsuspend\fP)
-the execution of processes and continue (\fIresume\fP)
-their execution at a later point. A user typically employs
-this facility via an interactive interface supplied jointly
-by the system's terminal driver and
-.BR bash .
-.PP
-The shell associates a
-.I job
-with each pipeline. It keeps a table of currently executing
-jobs, which may be listed with the
-.B jobs
-command. When
-.B bash
-starts a job asynchronously (in the
-.IR background ),
-it prints a line that looks like:
-.RS
-.PP
-[1] 25647
-.RE
-.PP
-indicating that this job is job number 1 and that the process ID
-of the last process in the pipeline associated with this job is 25647.
-All of the processes in a single pipeline are members of the same job.
-.B Bash
-uses the
-.I job
-abstraction as the basis for job control.
-.PP
-To facilitate the implementation of the user interface to job
-control, the operating system maintains the notion of a \fIcurrent terminal
-process group ID\fP. Members of this process group (processes whose
-process group ID is equal to the current terminal process group ID)
-receive keyboard-generated signals such as
-.SM
-.BR SIGINT .
-These processes are said to be in the
-.IR foreground .
-.I Background
-processes are those whose process group ID differs from the terminal's;
-such processes are immune to keyboard-generated signals.
-Only foreground processes are allowed to read from or write to the
-terminal. Background processes which attempt to read from (write to) the
-terminal are sent a
-.SM
-.B SIGTTIN (SIGTTOU)
-signal by the terminal driver,
-which, unless caught, suspends the process.
-.PP
-If the operating system on which
-.B bash
-is running supports
-job control,
-.B bash
-contains facilities to use it.
-Typing the
-.I suspend
-character (typically
-.BR ^Z ,
-Control-Z) while a process is running
-causes that process to be stopped and returns control to
-.BR bash .
-Typing the
-.I "delayed suspend"
-character (typically
-.BR ^Y ,
-Control-Y) causes the process to be stopped when it
-attempts to read input from the terminal, and control to
-be returned to
-.BR bash .
-The user may then manipulate the state of this job, using the
-.B bg
-command to continue it in the background, the
-.B fg
-command to continue it in the foreground, or
-the
-.B kill
-command to kill it. A \fB^Z\fP takes effect immediately,
-and has the additional side effect of causing pending output
-and typeahead to be discarded.
-.PP
-There are a number of ways to refer to a job in the shell.
-The character
-.B %
-introduces a job name. Job number
-.I n
-may be referred to as
-.BR %n .
-A job may also be referred to using a prefix of the name used to
-start it, or using a substring that appears in its command line.
-For example,
-.B %ce
-refers to a stopped
-.B ce
-job. If a prefix matches more than one job,
-.B bash
-reports an error. Using
-.BR %?ce ,
-on the other hand, refers to any job containing the string
-.B ce
-in its command line. If the substring matches more than one job,
-.B bash
-reports an error. The symbols
-.B %%
-and
-.B %+
-refer to the shell's notion of the
-.IR "current job" ,
-which is the last job stopped while it was in
-the foreground or started in the background.
-The
-.I "previous job"
-may be referenced using
-.BR %\- .
-In output pertaining to jobs (e.g., the output of the
-.B jobs
-command), the current job is always flagged with a
-.BR + ,
-and the previous job with a
-.BR \- .
-.PP
-Simply naming a job can be used to bring it into the
-foreground:
-.B %1
-is a synonym for
-\fB``fg %1''\fP,
-bringing job 1 from the background into the foreground.
-Similarly,
-.B ``%1 &''
-resumes job 1 in the background, equivalent to
-\fB``bg %1''\fP.
-.PP
-The shell learns immediately whenever a job changes state.
-Normally,
-.B bash
-waits until it is about to print a prompt before reporting
-changes in a job's status so as to not interrupt
-any other output. If the
-.B \-b
-option to the
-.B set
-builtin command
-is enabled,
-.B bash
-reports such changes immediately.
-Any trap on
-.SM
-.B SIGCHLD
-is executed for each child that exits.
-.PP
-If an attempt to exit
-.B bash
-is made while jobs are stopped, the shell prints a warning message. The
-.B jobs
-command may then be used to inspect their status.
-If a second attempt to exit is made without an intervening command,
-the shell does not print another warning, and the stopped
-jobs are terminated.
-.SH PROMPTING
-When executing interactively,
-.B bash
-displays the primary prompt
-.SM
-.B PS1
-when it is ready to read a command, and the secondary prompt
-.SM
-.B PS2
-when it needs more input to complete a command.
-.B Bash
-allows these prompt strings to be customized by inserting a number of
-backslash-escaped special characters that are decoded as follows:
-.RS
-.PD 0
-.TP
-.B \ea
-an ASCII bell character (07)
-.TP
-.B \ed
-the date in "Weekday Month Date" format (e.g., "Tue May 26")
-.TP
-.B \eD{\fIformat\fP}
-the \fIformat\fP is passed to \fIstrftime\fP(3) and the result is inserted
-into the prompt string; an empty \fIformat\fP results in a locale-specific
-time representation. The braces are required
-.TP
-.B \ee
-an ASCII escape character (033)
-.TP
-.B \eh
-the hostname up to the first `.'
-.TP
-.B \eH
-the hostname
-.TP
-.B \ej
-the number of jobs currently managed by the shell
-.TP
-.B \el
-the basename of the shell's terminal device name
-.TP
-.B \en
-newline
-.TP
-.B \er
-carriage return
-.TP
-.B \es
-the name of the shell, the basename of
-.B $0
-(the portion following the final slash)
-.TP
-.B \et
-the current time in 24-hour HH:MM:SS format
-.TP
-.B \eT
-the current time in 12-hour HH:MM:SS format
-.TP
-.B \e@
-the current time in 12-hour am/pm format
-.TP
-.B \eA
-the current time in 24-hour HH:MM format
-.TP
-.B \eu
-the username of the current user
-.TP
-.B \ev
-the version of \fBbash\fP (e.g., 2.00)
-.TP
-.B \eV
-the release of \fBbash\fP, version + patchelvel (e.g., 2.00.0)
-.TP
-.B \ew
-the current working directory
-.TP
-.B \eW
-the basename of the current working directory
-.TP
-.B \e!
-the history number of this command
-.TP
-.B \e#
-the command number of this command
-.TP
-.B \e$
-if the effective UID is 0, a
-.BR # ,
-otherwise a
-.B $
-.TP
-.B \e\fInnn\fP
-the character corresponding to the octal number \fInnn\fP
-.TP
-.B \e\e
-a backslash
-.TP
-.B \e[
-begin a sequence of non-printing characters, which could be used to
-embed a terminal control sequence into the prompt
-.TP
-.B \e]
-end a sequence of non-printing characters
-.PD
-.RE
-.PP
-The command number and the history number are usually different:
-the history number of a command is its position in the history
-list, which may include commands restored from the history file
-(see
-.SM
-.B HISTORY
-below), while the command number is the position in the sequence
-of commands executed during the current shell session.
-After the string is decoded, it is expanded via
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal, subject to the value of the
-.B promptvars
-shell option (see the description of the
-.B shopt
-command under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-.SH READLINE
-This is the library that handles reading input when using an interactive
-shell, unless the
-.B \-\-noediting
-option is given at shell invocation.
-By default, the line editing commands are similar to those of emacs.
-A vi-style line editing interface is also available.
-To turn off line editing after the shell is running, use the
-.B +o emacs
-or
-.B +o vi
-options to the
-.B set
-builtin (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SS "Readline Notation"
-.PP
-In this section, the emacs-style notation is used to denote
-keystrokes. Control keys are denoted by C\-\fIkey\fR, e.g., C\-n
-means Control\-N. Similarly,
-.I meta
-keys are denoted by M\-\fIkey\fR, so M\-x means Meta\-X. (On keyboards
-without a
-.I meta
-key, M\-\fIx\fP means ESC \fIx\fP, i.e., press the Escape key
-then the
-.I x
-key. This makes ESC the \fImeta prefix\fP.
-The combination M\-C\-\fIx\fP means ESC\-Control\-\fIx\fP,
-or press the Escape key
-then hold the Control key while pressing the
-.I x
-key.)
-.PP
-Readline commands may be given numeric
-.IR arguments ,
-which normally act as a repeat count.
-Sometimes, however, it is the sign of the argument that is significant.
-Passing a negative argument to a command that acts in the forward
-direction (e.g., \fBkill\-line\fP) causes that command to act in a
-backward direction.
-Commands whose behavior with arguments deviates from this are noted
-below.
-.PP
-When a command is described as \fIkilling\fP text, the text
-deleted is saved for possible future retrieval
-(\fIyanking\fP). The killed text is saved in a
-\fIkill ring\fP. Consecutive kills cause the text to be
-accumulated into one unit, which can be yanked all at once.
-Commands which do not kill text separate the chunks of text
-on the kill ring.
-.SS "Readline Initialization"
-.PP
-Readline is customized by putting commands in an initialization
-file (the \fIinputrc\fP file).
-The name of this file is taken from the value of the
-.SM
-.B INPUTRC
-variable. If that variable is unset, the default is
-.IR ~/.inputrc .
-When a program which uses the readline library starts up, the
-initialization file is read, and the key bindings and variables
-are set.
-There are only a few basic constructs allowed in the
-readline initialization file.
-Blank lines are ignored.
-Lines beginning with a \fB#\fP are comments.
-Lines beginning with a \fB$\fP indicate conditional constructs.
-Other lines denote key bindings and variable settings.
-.PP
-The default key-bindings may be changed with an
-.I inputrc
-file.
-Other programs that use this library may add their own commands
-and bindings.
-.PP
-For example, placing
-.RS
-.PP
-M\-Control\-u: universal\-argument
-.RE
-or
-.RS
-C\-Meta\-u: universal\-argument
-.RE
-into the
-.I inputrc
-would make M\-C\-u execute the readline command
-.IR universal\-argument .
-.PP
-The following symbolic character names are recognized:
-.IR RUBOUT ,
-.IR DEL ,
-.IR ESC ,
-.IR LFD ,
-.IR NEWLINE ,
-.IR RET ,
-.IR RETURN ,
-.IR SPC ,
-.IR SPACE ,
-and
-.IR TAB .
-.PP
-In addition to command names, readline allows keys to be bound
-to a string that is inserted when the key is pressed (a \fImacro\fP).
-.SS "Readline Key Bindings"
-.PP
-The syntax for controlling key bindings in the
-.I inputrc
-file is simple. All that is required is the name of the
-command or the text of a macro and a key sequence to which
-it should be bound. The name may be specified in one of two ways:
-as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP
-prefixes, or as a key sequence.
-.PP
-When using the form \fBkeyname\fP:\^\fIfunction\-name\fP or \fImacro\fP,
-.I keyname
-is the name of a key spelled out in English. For example:
-.sp
-.RS
-Control-u: universal\-argument
-.br
-Meta-Rubout: backward-kill-word
-.br
-Control-o: "> output"
-.RE
-.LP
-In the above example,
-.I C\-u
-is bound to the function
-.BR universal\-argument ,
-.I M\-DEL
-is bound to the function
-.BR backward\-kill\-word ,
-and
-.I C\-o
-is bound to run the macro
-expressed on the right hand side (that is, to insert the text
-.if t \f(CW> output\fP
-.if n ``> output''
-into the line).
-.PP
-In the second form, \fB"keyseq"\fP:\^\fIfunction\-name\fP or \fImacro\fP,
-.B keyseq
-differs from
-.B keyname
-above in that strings denoting
-an entire key sequence may be specified by placing the sequence
-within double quotes. Some GNU Emacs style key escapes can be
-used, as in the following example, but the symbolic character names
-are not recognized.
-.sp
-.RS
-"\eC\-u": universal\-argument
-.br
-"\eC\-x\eC\-r": re\-read\-init\-file
-.br
-"\ee[11~": "Function Key 1"
-.RE
-.PP
-In this example,
-.I C\-u
-is again bound to the function
-.BR universal\-argument .
-.I "C\-x C\-r"
-is bound to the function
-.BR re\-read\-init\-file ,
-and
-.I "ESC [ 1 1 ~"
-is bound to insert the text
-.if t \f(CWFunction Key 1\fP.
-.if n ``Function Key 1''.
-.PP
-The full set of GNU Emacs style escape sequences is
-.RS
-.PD 0
-.TP
-.B \eC\-
-control prefix
-.TP
-.B \eM\-
-meta prefix
-.TP
-.B \ee
-an escape character
-.TP
-.B \e\e
-backslash
-.TP
-.B \e"
-literal "
-.TP
-.B \e'
-literal '
-.RE
-.PD
-.PP
-In addition to the GNU Emacs style escape sequences, a second
-set of backslash escapes is available:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ed
-delete
-.TP
-.B \ef
-form feed
-.TP
-.B \en
-newline
-.TP
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP
-.B \ev
-vertical tab
-.TP
-.B \e\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(one to three digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.RE
-.PD
-.PP
-When entering the text of a macro, single or double quotes must
-be used to indicate a macro definition.
-Unquoted text is assumed to be a function name.
-In the macro body, the backslash escapes described above are expanded.
-Backslash will quote any other character in the macro text,
-including " and '.
-.PP
-.B Bash
-allows the current readline key bindings to be displayed or modified
-with the
-.B bind
-builtin command. The editing mode may be switched during interactive
-use by using the
-.B \-o
-option to the
-.B set
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SS "Readline Variables"
-.PP
-Readline has variables that can be used to further customize its
-behavior. A variable may be set in the
-.I inputrc
-file with a statement of the form
-.RS
-.PP
-\fBset\fP \fIvariable\-name\fP \fIvalue\fP
-.RE
-.PP
-Except where noted, readline variables can take the values
-.B On
-or
-.BR Off .
-The variables and their default values are:
-.PP
-.PD 0
-.TP
-.B bell\-style (audible)
-Controls what happens when readline wants to ring the terminal bell.
-If set to \fBnone\fP, readline never rings the bell. If set to
-\fBvisible\fP, readline uses a visible bell if one is available.
-If set to \fBaudible\fP, readline attempts to ring the terminal's bell.
-.TP
-.B comment\-begin (``#'')
-The string that is inserted when the readline
-.B insert\-comment
-command is executed.
-This command is bound to
-.B M\-#
-in emacs mode and to
-.B #
-in vi command mode.
-.TP
-.B completion\-ignore\-case (Off)
-If set to \fBOn\fP, readline performs filename matching and completion
-in a case\-insensitive fashion.
-.TP
-.B completion\-query\-items (100)
-This determines when the user is queried about viewing
-the number of possible completions
-generated by the \fBpossible\-completions\fP command.
-It may be set to any integer value greater than or equal to
-zero. If the number of possible completions is greater than
-or equal to the value of this variable, the user is asked whether
-or not he wishes to view them; otherwise they are simply listed
-on the terminal.
-.TP
-.B convert\-meta (On)
-If set to \fBOn\fP, readline will convert characters with the
-eighth bit set to an ASCII key sequence
-by stripping the eighth bit and prefixing an
-escape character (in effect, using escape as the \fImeta prefix\fP).
-.TP
-.B disable\-completion (Off)
-If set to \fBOn\fP, readline will inhibit word completion. Completion
-characters will be inserted into the line as if they had been
-mapped to \fBself-insert\fP.
-.TP
-.B editing\-mode (emacs)
-Controls whether readline begins with a set of key bindings similar
-to \fIemacs\fP or \fIvi\fP.
-.B editing\-mode
-can be set to either
-.B emacs
-or
-.BR vi .
-.TP
-.B enable\-keypad (Off)
-When set to \fBOn\fP, readline will try to enable the application
-keypad when it is called. Some systems need this to enable the
-arrow keys.
-.TP
-.B expand\-tilde (Off)
-If set to \fBon\fP, tilde expansion is performed when readline
-attempts word completion.
-.TP
-.B history-preserve-point
-If set to \fBon\fP, the history code attempts to place point at the
-same location on each history line retrived with \fBprevious-history\fP
-or \fBnext-history\fP.
-.TP
-.B horizontal\-scroll\-mode (Off)
-When set to \fBOn\fP, makes readline use a single line for display,
-scrolling the input horizontally on a single screen line when it
-becomes longer than the screen width rather than wrapping to a new line.
-.TP
-.B input\-meta (Off)
-If set to \fBOn\fP, readline will enable eight-bit input (that is,
-it will not strip the high bit from the characters it reads),
-regardless of what the terminal claims it can support. The name
-.B meta\-flag
-is a synonym for this variable.
-.TP
-.B isearch\-terminators (``C\-[C\-J'')
-The string of characters that should terminate an incremental
-search without subsequently executing the character as a command.
-If this variable has not been given a value, the characters
-\fIESC\fP and \fIC\-J\fP will terminate an incremental search.
-.TP
-.B keymap (emacs)
-Set the current readline keymap. The set of valid keymap names is
-\fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi,
-vi\-command\fP, and
-.IR vi\-insert .
-\fIvi\fP is equivalent to \fIvi\-command\fP; \fIemacs\fP is
-equivalent to \fIemacs\-standard\fP. The default value is
-.IR emacs ;
-the value of
-.B editing\-mode
-also affects the default keymap.
-.TP
-.B mark\-directories (On)
-If set to \fBOn\fP, completed directory names have a slash
-appended.
-.TP
-.B mark\-modified\-lines (Off)
-If set to \fBOn\fP, history lines that have been modified are displayed
-with a preceding asterisk (\fB*\fP).
-.TP
-.B mark\-symlinked\-directories (Off)
-If set to \fBOn\fP, completed names which are symbolic links to directories
-have a slash appended (subject to the value of
-\fBmark\-directories\fP).
-.TP
-.B match\-hidden\-files (On)
-This variable, when set to \fBOn\fP, causes readline to match files whose
-names begin with a `.' (hidden files) when performing filename
-completion, unless the leading `.' is
-supplied by the user in the filename to be completed.
-.TP
-.B output\-meta (Off)
-If set to \fBOn\fP, readline will display characters with the
-eighth bit set directly rather than as a meta-prefixed escape
-sequence.
-.TP
-.B page\-completions (On)
-If set to \fBOn\fP, readline uses an internal \fImore\fP-like pager
-to display a screenful of possible completions at a time.
-.TP
-.B print\-completions\-horizontally (Off)
-If set to \fBOn\fP, readline will display completions with matches
-sorted horizontally in alphabetical order, rather than down the screen.
-.TP
-.B show\-all\-if\-ambiguous (Off)
-This alters the default behavior of the completion functions. If
-set to
-.BR on ,
-words which have more than one possible completion cause the
-matches to be listed immediately instead of ringing the bell.
-.TP
-.B visible\-stats (Off)
-If set to \fBOn\fP, a character denoting a file's type as reported
-by \fIstat\fP(2) is appended to the filename when listing possible
-completions.
-.PD
-.SS "Readline Conditional Constructs"
-.PP
-Readline implements a facility similar in spirit to the conditional
-compilation features of the C preprocessor which allows key
-bindings and variable settings to be performed as the result
-of tests. There are four parser directives used.
-.IP \fB$if\fP
-The
-.B $if
-construct allows bindings to be made based on the
-editing mode, the terminal being used, or the application using
-readline. The text of the test extends to the end of the line;
-no characters are required to isolate it.
-.RS
-.IP \fBmode\fP
-The \fBmode=\fP form of the \fB$if\fP directive is used to test
-whether readline is in emacs or vi mode.
-This may be used in conjunction
-with the \fBset keymap\fP command, for instance, to set bindings in
-the \fIemacs\-standard\fP and \fIemacs\-ctlx\fP keymaps only if
-readline is starting out in emacs mode.
-.IP \fBterm\fP
-The \fBterm=\fP form may be used to include terminal-specific
-key bindings, perhaps to bind the key sequences output by the
-terminal's function keys. The word on the right side of the
-.B =
-is tested against the both full name of the terminal and the portion
-of the terminal name before the first \fB\-\fP. This allows
-.I sun
-to match both
-.I sun
-and
-.IR sun\-cmd ,
-for instance.
-.IP \fBapplication\fP
-The \fBapplication\fP construct is used to include
-application-specific settings. Each program using the readline
-library sets the \fIapplication name\fP, and an initialization
-file can test for a particular value.
-This could be used to bind key sequences to functions useful for
-a specific program. For instance, the following command adds a
-key sequence that quotes the current or previous word in Bash:
-.sp 1
-.RS
-.nf
-\fB$if\fP Bash
-# Quote the current or previous word
-"\eC\-xq": "\eeb\e"\eef\e""
-\fB$endif\fP
-.fi
-.RE
-.RE
-.IP \fB$endif\fP
-This command, as seen in the previous example, terminates an
-\fB$if\fP command.
-.IP \fB$else\fP
-Commands in this branch of the \fB$if\fP directive are executed if
-the test fails.
-.IP \fB$include\fP
-This directive takes a single filename as an argument and reads commands
-and bindings from that file. For example, the following directive
-would read \fI/etc/inputrc\fP:
-.sp 1
-.RS
-.nf
-\fB$include\fP \^ \fI/etc/inputrc\fP
-.fi
-.RE
-.SS Searching
-.PP
-Readline provides commands for searching through the command history
-(see
-.SM
-.B HISTORY
-below) for lines containing a specified string.
-There are two search modes:
-.I incremental
-and
-.IR non-incremental .
-.PP
-Incremental searches begin before the user has finished typing the
-search string.
-As each character of the search string is typed, readline displays
-the next entry from the history matching the string typed so far.
-An incremental search requires only as many characters as needed to
-find the desired history entry.
-The characters present in the value of the \fBisearch-terminators\fP
-variable are used to terminate an incremental search.
-If that variable has not been assigned a value the Escape and
-Control-J characters will terminate an incremental search.
-Control-G will abort an incremental search and restore the original
-line.
-When the search is terminated, the history entry containing the
-search string becomes the current line.
-.PP
-To find other matching entries in the history list, type Control-S or
-Control-R as appropriate.
-This will search backward or forward in the history for the next
-entry matching the search string typed so far.
-Any other key sequence bound to a readline command will terminate
-the search and execute that command.
-For instance, a \fInewline\fP will terminate the search and accept
-the line, thereby executing the command from the history list.
-.PP
-Readline remembers the last incremental search string. If two
-Control-Rs are typed without any intervening characters defining a
-new search string, any remembered search string is used.
-.PP
-Non-incremental searches read the entire search string before starting
-to search for matching history lines. The search string may be
-typed by the user or be part of the contents of the current line.
-.SS "Readline Command Names"
-.PP
-The following is a list of the names of the commands and the default
-key sequences to which they are bound.
-Command names without an accompanying key sequence are unbound by default.
-In the following descriptions, \fIpoint\fP refers to the current cursor
-position, and \fImark\fP refers to a cursor position saved by the
-\fBset\-mark\fP command.
-The text between the point and mark is referred to as the \fIregion\fP.
-.SS Commands for Moving
-.PP
-.PD 0
-.TP
-.B beginning\-of\-line (C\-a)
-Move to the start of the current line.
-.TP
-.B end\-of\-line (C\-e)
-Move to the end of the line.
-.TP
-.B forward\-char (C\-f)
-Move forward a character.
-.TP
-.B backward\-char (C\-b)
-Move back a character.
-.TP
-.B forward\-word (M\-f)
-Move forward to the end of the next word. Words are composed of
-alphanumeric characters (letters and digits).
-.TP
-.B backward\-word (M\-b)
-Move back to the start of the current or previous word. Words are
-composed of alphanumeric characters (letters and digits).
-.TP
-.B clear\-screen (C\-l)
-Clear the screen leaving the current line at the top of the screen.
-With an argument, refresh the current line without clearing the
-screen.
-.TP
-.B redraw\-current\-line
-Refresh the current line.
-.PD
-.SS Commands for Manipulating the History
-.PP
-.PD 0
-.TP
-.B accept\-line (Newline, Return)
-Accept the line regardless of where the cursor is. If this line is
-non-empty, add it to the history list according to the state of the
-.SM
-.B HISTCONTROL
-variable. If the line is a modified history
-line, then restore the history line to its original state.
-.TP
-.B previous\-history (C\-p)
-Fetch the previous command from the history list, moving back in
-the list.
-.TP
-.B next\-history (C\-n)
-Fetch the next command from the history list, moving forward in the
-list.
-.TP
-.B beginning\-of\-history (M\-<)
-Move to the first line in the history.
-.TP
-.B end\-of\-history (M\->)
-Move to the end of the input history, i.e., the line currently being
-entered.
-.TP
-.B reverse\-search\-history (C\-r)
-Search backward starting at the current line and moving `up' through
-the history as necessary. This is an incremental search.
-.TP
-.B forward\-search\-history (C\-s)
-Search forward starting at the current line and moving `down' through
-the history as necessary. This is an incremental search.
-.TP
-.B non\-incremental\-reverse\-search\-history (M\-p)
-Search backward through the history starting at the current line
-using a non-incremental search for a string supplied by the user.
-.TP
-.B non\-incremental\-forward\-search\-history (M\-n)
-Search forward through the history using a non-incremental search for
-a string supplied by the user.
-.TP
-.B history\-search\-forward
-Search forward through the history for the string of characters
-between the start of the current line and the point.
-This is a non-incremental search.
-.TP
-.B history\-search\-backward
-Search backward through the history for the string of characters
-between the start of the current line and the point.
-This is a non-incremental search.
-.TP
-.B yank\-nth\-arg (M\-C\-y)
-Insert the first argument to the previous command (usually
-the second word on the previous line) at point.
-With an argument
-.IR n ,
-insert the \fIn\fPth word from the previous command (the words
-in the previous command begin with word 0). A negative argument
-inserts the \fIn\fPth word from the end of the previous command.
-.TP
-.B
-yank\-last\-arg (M\-.\^, M\-_\^)
-Insert the last argument to the previous command (the last word of
-the previous history entry). With an argument,
-behave exactly like \fByank\-nth\-arg\fP.
-Successive calls to \fByank\-last\-arg\fP move back through the history
-list, inserting the last argument of each line in turn.
-.TP
-.B shell\-expand\-line (M\-C\-e)
-Expand the line as the shell does. This
-performs alias and history expansion as well as all of the shell
-word expansions. See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B history\-expand\-line (M\-^)
-Perform history expansion on the current line.
-See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B magic\-space
-Perform history expansion on the current line and insert a space.
-See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B alias\-expand\-line
-Perform alias expansion on the current line.
-See
-.SM
-.B ALIASES
-above for a description of alias expansion.
-.TP
-.B history\-and\-alias\-expand\-line
-Perform history and alias expansion on the current line.
-.TP
-.B insert\-last\-argument (M\-.\^, M\-_\^)
-A synonym for \fByank\-last\-arg\fP.
-.TP
-.B operate\-and\-get\-next (C\-o)
-Accept the current line for execution and fetch the next line
-relative to the current line from the history for editing. Any
-argument is ignored.
-.TP
-.B edit\-and\-execute\-command (C\-xC\-e)
-Invoke an editor on the current command line, and execute the result as shell
-commands.
-\fBBash\fP attempts to invoke
-.SM
-.BR $FCEDIT ,
-.SM
-.BR $EDITOR ,
-and \fIemacs\fP as the editor, in that order.
-.PD
-.SS Commands for Changing Text
-.PP
-.PD 0
-.TP
-.B delete\-char (C\-d)
-Delete the character at point. If point is at the
-beginning of the line, there are no characters in the line, and
-the last character typed was not bound to \fBdelete\-char\fP,
-then return
-.SM
-.BR EOF .
-.TP
-.B backward\-delete\-char (Rubout)
-Delete the character behind the cursor. When given a numeric argument,
-save the deleted text on the kill ring.
-.TP
-.B forward\-backward\-delete\-char
-Delete the character under the cursor, unless the cursor is at the
-end of the line, in which case the character behind the cursor is
-deleted.
-.TP
-.B quoted\-insert (C\-q, C\-v)
-Add the next character typed to the line verbatim. This is
-how to insert characters like \fBC\-q\fP, for example.
-.TP
-.B tab\-insert (C\-v TAB)
-Insert a tab character.
-.TP
-.B self\-insert (a,\ b,\ A,\ 1,\ !,\ ...)
-Insert the character typed.
-.TP
-.B transpose\-chars (C\-t)
-Drag the character before point forward over the character at point,
-moving point forward as well.
-If point is at the end of the line, then this transposes
-the two characters before point.
-Negative arguments have no effect.
-.TP
-.B transpose\-words (M\-t)
-Drag the word before point past the word after point,
-moving point over that word as well.
-If point is at the end of the line, this transposes
-the last two words on the line.
-.TP
-.B upcase\-word (M\-u)
-Uppercase the current (or following) word. With a negative argument,
-uppercase the previous word, but do not move point.
-.TP
-.B downcase\-word (M\-l)
-Lowercase the current (or following) word. With a negative argument,
-lowercase the previous word, but do not move point.
-.TP
-.B capitalize\-word (M\-c)
-Capitalize the current (or following) word. With a negative argument,
-capitalize the previous word, but do not move point.
-.TP
-.B overwrite\-mode
-Toggle overwrite mode. With an explicit positive numeric argument,
-switches to overwrite mode. With an explicit non-positive numeric
-argument, switches to insert mode. This command affects only
-\fBemacs\fP mode; \fBvi\fP mode does overwrite differently.
-Each call to \fIreadline()\fP starts in insert mode.
-In overwrite mode, characters bound to \fBself\-insert\fP replace
-the text at point rather than pushing the text to the right.
-Characters bound to \fBbackward\-delete\-char\fP replace the character
-before point with a space. By default, this command is unbound.
-.PD
-.SS Killing and Yanking
-.PP
-.PD 0
-.TP
-.B kill\-line (C\-k)
-Kill the text from point to the end of the line.
-.TP
-.B backward\-kill\-line (C\-x Rubout)
-Kill backward to the beginning of the line.
-.TP
-.B unix\-line\-discard (C\-u)
-Kill backward from point to the beginning of the line.
-The killed text is saved on the kill-ring.
-.\" There is no real difference between this and backward-kill-line
-.TP
-.B kill\-whole\-line
-Kill all characters on the current line, no matter where point is.
-.TP
-.B kill\-word (M\-d)
-Kill from point to the end of the current word, or if between
-words, to the end of the next word.
-Word boundaries are the same as those used by \fBforward\-word\fP.
-.TP
-.B backward\-kill\-word (M\-Rubout)
-Kill the word behind point.
-Word boundaries are the same as those used by \fBbackward\-word\fP.
-.TP
-.B unix\-word\-rubout (C\-w)
-Kill the word behind point, using white space as a word boundary.
-The killed text is saved on the kill-ring.
-.TP
-.B delete\-horizontal\-space (M\-\e)
-Delete all spaces and tabs around point.
-.TP
-.B kill\-region
-Kill the text in the current region.
-.TP
-.B copy\-region\-as\-kill
-Copy the text in the region to the kill buffer.
-.TP
-.B copy\-backward\-word
-Copy the word before point to the kill buffer.
-The word boundaries are the same as \fBbackward\-word\fP.
-.TP
-.B copy\-forward\-word
-Copy the word following point to the kill buffer.
-The word boundaries are the same as \fBforward\-word\fP.
-.TP
-.B yank (C\-y)
-Yank the top of the kill ring into the buffer at point.
-.TP
-.B yank\-pop (M\-y)
-Rotate the kill ring, and yank the new top. Only works following
-.B yank
-or
-.BR yank\-pop .
-.PD
-.SS Numeric Arguments
-.PP
-.PD 0
-.TP
-.B digit\-argument (M\-0, M\-1, ..., M\-\-)
-Add this digit to the argument already accumulating, or start a new
-argument. M\-\- starts a negative argument.
-.TP
-.B universal\-argument
-This is another way to specify an argument.
-If this command is followed by one or more digits, optionally with a
-leading minus sign, those digits define the argument.
-If the command is followed by digits, executing
-.B universal\-argument
-again ends the numeric argument, but is otherwise ignored.
-As a special case, if this command is immediately followed by a
-character that is neither a digit or minus sign, the argument count
-for the next command is multiplied by four.
-The argument count is initially one, so executing this function the
-first time makes the argument count four, a second time makes the
-argument count sixteen, and so on.
-.PD
-.SS Completing
-.PP
-.PD 0
-.TP
-.B complete (TAB)
-Attempt to perform completion on the text before point.
-.B Bash
-attempts completion treating the text as a variable (if the
-text begins with \fB$\fP), username (if the text begins with
-\fB~\fP), hostname (if the text begins with \fB@\fP), or
-command (including aliases and functions) in turn. If none
-of these produces a match, filename completion is attempted.
-.TP
-.B possible\-completions (M\-?)
-List the possible completions of the text before point.
-.TP
-.B insert\-completions (M\-*)
-Insert all completions of the text before point
-that would have been generated by
-\fBpossible\-completions\fP.
-.TP
-.B menu\-complete
-Similar to \fBcomplete\fP, but replaces the word to be completed
-with a single match from the list of possible completions.
-Repeated execution of \fBmenu\-complete\fP steps through the list
-of possible completions, inserting each match in turn.
-At the end of the list of completions, the bell is rung
-(subject to the setting of \fBbell\-style\fP)
-and the original text is restored.
-An argument of \fIn\fP moves \fIn\fP positions forward in the list
-of matches; a negative argument may be used to move backward
-through the list.
-This command is intended to be bound to \fBTAB\fP, but is unbound
-by default.
-.TP
-.B delete\-char\-or\-list
-Deletes the character under the cursor if not at the beginning or
-end of the line (like \fBdelete\-char\fP).
-If at the end of the line, behaves identically to
-\fBpossible\-completions\fP.
-This command is unbound by default.
-.TP
-.B complete\-filename (M\-/)
-Attempt filename completion on the text before point.
-.TP
-.B possible\-filename\-completions (C\-x /)
-List the possible completions of the text before point,
-treating it as a filename.
-.TP
-.B complete\-username (M\-~)
-Attempt completion on the text before point, treating
-it as a username.
-.TP
-.B possible\-username\-completions (C\-x ~)
-List the possible completions of the text before point,
-treating it as a username.
-.TP
-.B complete\-variable (M\-$)
-Attempt completion on the text before point, treating
-it as a shell variable.
-.TP
-.B possible\-variable\-completions (C\-x $)
-List the possible completions of the text before point,
-treating it as a shell variable.
-.TP
-.B complete\-hostname (M\-@)
-Attempt completion on the text before point, treating
-it as a hostname.
-.TP
-.B possible\-hostname\-completions (C\-x @)
-List the possible completions of the text before point,
-treating it as a hostname.
-.TP
-.B complete\-command (M\-!)
-Attempt completion on the text before point, treating
-it as a command name. Command completion attempts to
-match the text against aliases, reserved words, shell
-functions, shell builtins, and finally executable filenames,
-in that order.
-.TP
-.B possible\-command\-completions (C\-x !)
-List the possible completions of the text before point,
-treating it as a command name.
-.TP
-.B dynamic\-complete\-history (M\-TAB)
-Attempt completion on the text before point, comparing
-the text against lines from the history list for possible
-completion matches.
-.TP
-.B complete\-into\-braces (M\-{)
-Perform filename completion and insert the list of possible completions
-enclosed within braces so the list is available to the shell (see
-.B Brace Expansion
-above).
-.PD
-.SS Keyboard Macros
-.PP
-.PD 0
-.TP
-.B start\-kbd\-macro (C\-x (\^)
-Begin saving the characters typed into the current keyboard macro.
-.TP
-.B end\-kbd\-macro (C\-x )\^)
-Stop saving the characters typed into the current keyboard macro
-and store the definition.
-.TP
-.B call\-last\-kbd\-macro (C\-x e)
-Re-execute the last keyboard macro defined, by making the characters
-in the macro appear as if typed at the keyboard.
-.PD
-.SS Miscellaneous
-.PP
-.PD 0
-.TP
-.B re\-read\-init\-file (C\-x C\-r)
-Read in the contents of the \fIinputrc\fP file, and incorporate
-any bindings or variable assignments found there.
-.TP
-.B abort (C\-g)
-Abort the current editing command and
-ring the terminal's bell (subject to the setting of
-.BR bell\-style ).
-.TP
-.B do\-uppercase\-version (M\-a, M\-b, M\-\fIx\fP, ...)
-If the metafied character \fIx\fP is lowercase, run the command
-that is bound to the corresponding uppercase character.
-.TP
-.B prefix\-meta (ESC)
-Metafy the next character typed.
-.SM
-.B ESC
-.B f
-is equivalent to
-.BR Meta\-f .
-.TP
-.B undo (C\-_, C\-x C\-u)
-Incremental undo, separately remembered for each line.
-.TP
-.B revert\-line (M\-r)
-Undo all changes made to this line. This is like executing the
-.B undo
-command enough times to return the line to its initial state.
-.TP
-.B tilde\-expand (M\-&)
-Perform tilde expansion on the current word.
-.TP
-.B set\-mark (C\-@, M\-<space>)
-Set the mark to the point. If a
-numeric argument is supplied, the mark is set to that position.
-.TP
-.B exchange\-point\-and\-mark (C\-x C\-x)
-Swap the point with the mark. The current cursor position is set to
-the saved position, and the old cursor position is saved as the mark.
-.TP
-.B character\-search (C\-])
-A character is read and point is moved to the next occurrence of that
-character. A negative count searches for previous occurrences.
-.TP
-.B character\-search\-backward (M\-C\-])
-A character is read and point is moved to the previous occurrence of that
-character. A negative count searches for subsequent occurrences.
-.TP
-.B insert\-comment (M\-#)
-Without a numeric argument, the value of the readline
-.B comment\-begin
-variable is inserted at the beginning of the current line.
-If a numeric argument is supplied, this command acts as a toggle: if
-the characters at the beginning of the line do not match the value
-of \fBcomment\-begin\fP, the value is inserted, otherwise
-the characters in \fBcomment-begin\fP are deleted from the beginning of
-the line.
-In either case, the line is accepted as if a newline had been typed.
-The default value of
-\fBcomment\-begin\fP causes this command to make the current line
-a shell comment.
-If a numeric argument causes the comment character to be removed, the line
-will be executed by the shell.
-.TP
-.B glob\-complete\-word (M\-g)
-The word before point is treated as a pattern for pathname expansion,
-with an asterisk implicitly appended. This pattern is used to
-generate a list of matching file names for possible completions.
-.TP
-.B glob\-expand\-word (C\-x *)
-The word before point is treated as a pattern for pathname expansion,
-and the list of matching file names is inserted, replacing the word.
-If a numeric argument is supplied, an asterisk is appended before
-pathname expansion.
-.TP
-.B glob\-list\-expansions (C\-x g)
-The list of expansions that would have been generated by
-.B glob\-expand\-word
-is displayed, and the line is redrawn.
-If a numeric argument is supplied, an asterisk is appended before
-pathname expansion.
-.TP
-.B dump\-functions
-Print all of the functions and their key bindings to the
-readline output stream. If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B dump\-variables
-Print all of the settable readline variables and their values to the
-readline output stream. If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B dump\-macros
-Print all of the readline key sequences bound to macros and the
-strings they ouput. If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B display\-shell\-version (C\-x C\-v)
-Display version information about the current instance of
-.BR bash .
-.PD
-.SS Programmable Completion
-.PP
-When word completion is attempted for an argument to a command for
-which a completion specification (a \fIcompspec\fP) has been defined
-using the \fBcomplete\fP builtin (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), the programmable completion facilities are invoked.
-.PP
-First, the command name is identified.
-If a compspec has been defined for that command, the
-compspec is used to generate the list of possible completions for the word.
-If the command word is a full pathname, a compspec for the full
-pathname is searched for first.
-If no compspec is found for the full pathname, an attempt is made to
-find a compspec for the portion following the final slash.
-.PP
-Once a compspec has been found, it is used to generate the list of
-matching words.
-If a compspec is not found, the default \fBbash\fP completion as
-described above under \fBCompleting\fP is performed.
-.PP
-First, the actions specified by the compspec are used.
-Only matches which are prefixed by the word being completed are
-returned.
-When the
-.B \-f
-or
-.B \-d
-option is used for filename or directory name completion, the shell
-variable
-.SM
-.B FIGNORE
-is used to filter the matches.
-.PP
-Any completions specified by a filename expansion pattern to the
-\fB\-G\fP option are generated next.
-The words generated by the pattern need not match the word
-being completed.
-The
-.SM
-.B GLOBIGNORE
-shell variable is not used to filter the matches, but the
-.SM
-.B FIGNORE
-variable is used.
-.PP
-Next, the string specified as the argument to the \fB\-W\fP option
-is considered.
-The string is first split using the characters in the
-.SM
-.B IFS
-special variable as delimiters.
-Shell quoting is honored.
-Each word is then expanded using
-brace expansion, tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and pathname expansion,
-as described above under
-.SM
-.BR EXPANSION .
-The results are split using the rules described above under
-\fBWord Splitting\fP.
-The results of the expansion are prefix-matched against the word being
-completed, and the matching words become the possible completions.
-.PP
-After these matches have been generated, any shell function or command
-specified with the \fB\-F\fP and \fB\-C\fP options is invoked.
-When the command or function is invoked, the
-.SM
-.B COMP_LINE
-and
-.SM
-.B COMP_POINT
-variables are assigned values as described above under
-\fBShell Variables\fP.
-If a shell function is being invoked, the
-.SM
-.B COMP_WORDS
-and
-.SM
-.B COMP_CWORD
-variables are also set.
-When the function or command is invoked, the first argument is the
-name of the command whose arguments are being completed, the
-second argument is the word being completed, and the third argument
-is the word preceding the word being completed on the current command line.
-No filtering of the generated completions against the word being completed
-is performed; the function or command has complete freedom in generating
-the matches.
-.PP
-Any function specified with \fB\-F\fP is invoked first.
-The function may use any of the shell facilities, including the
-\fBcompgen\fP builtin described below, to generate the matches.
-It must put the possible completions in the
-.SM
-.B COMPREPLY
-array variable.
-.PP
-Next, any command specified with the \fB\-C\fP option is invoked
-in an environment equivalent to command substitution.
-It should print a list of completions, one per line, to the
-standard output.
-Backslash may be used to escape a newline, if necessary.
-.PP
-After all of the possible completions are generated, any filter
-specified with the \fB\-X\fP option is applied to the list.
-The filter is a pattern as used for pathname expansion; a \fB&\fP
-in the pattern is replaced with the text of the word being completed.
-A literal \fB&\fP may be escaped with a backslash; the backslash
-is removed before attempting a match.
-Any completion that matches the pattern will be removed from the list.
-A leading \fB!\fP negates the pattern; in this case any completion
-not matching the pattern will be removed.
-.PP
-Finally, any prefix and suffix specified with the \fB\-P\fP and \fB\-S\fP
-options are added to each member of the completion list, and the result is
-returned to the readline completion code as the list of possible
-completions.
-.PP
-If the previously-applied actions do not generate any matches, and the
-\fB\-o dirnames\fP option was supplied to \fBcomplete\fP when the
-compspec was defined, directory name completion is attempted.
-.PP
-By default, if a compspec is found, whatever it generates is returned
-to the completion code as the full set of possible completions.
-The default \fBbash\fP completions are not attempted, and the readline
-default of filename completion is disabled.
-If the \fB-o default\fP option was supplied to \fBcomplete\fP when the
-compspec was defined, readline's default completion will be performed
-if the compspec generates no matches.
-.PP
-When a compspec indicates that directory name completion is desired,
-the programmable completion functions force readline to append a slash
-to completed names which are symbolic links to directories, subject to
-the value of the \fBmark\-directories\fP readline variable, regardless
-of the setting of the \fBmark-symlinked\-directories\fP readline variable.
-.SH HISTORY
-When the
-.B \-o history
-option to the
-.B set
-builtin is enabled, the shell provides access to the
-\fIcommand history\fP,
-the list of commands previously typed.
-The value of the \fBHISTSIZE\fP variable is used as the
-number of commands to save in a history list.
-The text of the last
-.SM
-.B HISTSIZE
-commands (default 500) is saved. The shell
-stores each command in the history list prior to parameter and
-variable expansion (see
-.SM
-.B EXPANSION
-above) but after history expansion is performed, subject to the
-values of the shell variables
-.SM
-.B HISTIGNORE
-and
-.SM
-.BR HISTCONTROL .
-.PP
-On startup, the history is initialized from the file named by
-the variable
-.SM
-.B HISTFILE
-(default \fI~/.bash_history\fP).
-The file named by the value of
-.SM
-.B HISTFILE
-is truncated, if necessary, to contain no more than
-the number of lines specified by the value of
-.SM
-.BR HISTFILESIZE .
-When an interactive shell exits, the last
-.SM
-.B $HISTSIZE
-lines are copied from the history list to
-.SM
-.BR $HISTFILE .
-If the
-.B histappend
-shell option is enabled
-(see the description of
-.B shopt
-under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), the lines are appended to the history file,
-otherwise the history file is overwritten.
-If
-.SM
-.B HISTFILE
-is unset, or if the history file is unwritable, the history is
-not saved. After saving the history, the history file is truncated
-to contain no more than
-.SM
-.B HISTFILESIZE
-lines. If
-.SM
-.B HISTFILESIZE
-is not set, no truncation is performed.
-.PP
-The builtin command
-.B fc
-(see
-.SM
-.B SHELL BUILTIN COMMANDS
-below) may be used to list or edit and re-execute a portion of
-the history list.
-The
-.B history
-builtin may be used to display or modify the history list and
-manipulate the history file.
-When using command-line editing, search commands
-are available in each editing mode that provide access to the
-history list.
-.PP
-The shell allows control over which commands are saved on the history
-list. The
-.SM
-.B HISTCONTROL
-and
-.SM
-.B HISTIGNORE
-variables may be set to cause the shell to save only a subset of the
-commands entered.
-The
-.B cmdhist
-shell option, if enabled, causes the shell to attempt to save each
-line of a multi-line command in the same history entry, adding
-semicolons where necessary to preserve syntactic correctness.
-The
-.B lithist
-shell option causes the shell to save the command with embedded newlines
-instead of semicolons. See the description of the
-.B shopt
-builtin below under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-for information on setting and unsetting shell options.
-.SH "HISTORY EXPANSION"
-.PP
-The shell supports a history expansion feature that
-is similar to the history expansion in
-.BR csh.
-This section describes what syntax features are available. This
-feature is enabled by default for interactive shells, and can be
-disabled using the
-.B \+H
-option to the
-.B set
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below). Non-interactive shells do not perform history expansion
-by default.
-.PP
-History expansions introduce words from the history list into
-the input stream, making it easy to repeat commands, insert the
-arguments to a previous command into the current input line, or
-fix errors in previous commands quickly.
-.PP
-History expansion is performed immediately after a complete line
-is read, before the shell breaks it into words.
-It takes place in two parts.
-The first is to determine which line from the history list
-to use during substitution.
-The second is to select portions of that line for inclusion into
-the current one.
-The line selected from the history is the \fIevent\fP,
-and the portions of that line that are acted upon are \fIwords\fP.
-Various \fImodifiers\fP are available to manipulate the selected words.
-The line is broken into words in the same fashion as when reading input,
-so that several \fImetacharacter\fP-separated words surrounded by
-quotes are considered one word.
-History expansions are introduced by the appearance of the
-history expansion character, which is \^\fB!\fP\^ by default.
-Only backslash (\^\fB\e\fP\^) and single quotes can quote
-the history expansion character.
-.PP
-Several shell options settable with the
-.B shopt
-builtin may be used to tailor the behavior of history expansion.
-If the
-.B histverify
-shell option is enabled (see the description of the
-.B shopt
-builtin), and
-.B readline
-is being used, history substitutions are not immediately passed to
-the shell parser.
-Instead, the expanded line is reloaded into the
-.B readline
-editing buffer for further modification.
-If
-.B readline
-is being used, and the
-.B histreedit
-shell option is enabled, a failed history substitution will be reloaded
-into the
-.B readline
-editing buffer for correction.
-The
-.B \-p
-option to the
-.B history
-builtin command may be used to see what a history expansion will
-do before using it.
-The
-.B \-s
-option to the
-.B history
-builtin may be used to add commands to the end of the history list
-without actually executing them, so that they are available for
-subsequent recall.
-.PP
-The shell allows control of the various characters used by the
-history expansion mechanism (see the description of
-.B histchars
-above under
-.BR "Shell Variables" ).
-.SS Event Designators
-.PP
-An event designator is a reference to a command line entry in the
-history list.
-.PP
-.PD 0
-.TP
-.B !
-Start a history substitution, except when followed by a
-.BR blank ,
-newline, = or ( (when the \fBextglob\fP shell option is enabled using
-the \fBshopt\fP builtin).
-.TP
-.B !\fIn\fR
-Refer to command line
-.IR n .
-.TP
-.B !\-\fIn\fR
-Refer to the current command line minus
-.IR n .
-.TP
-.B !!
-Refer to the previous command. This is a synonym for `!\-1'.
-.TP
-.B !\fIstring\fR
-Refer to the most recent command starting with
-.IR string .
-.TP
-.B !?\fIstring\fR\fB[?]\fR
-Refer to the most recent command containing
-.IR string .
-The trailing \fB?\fP may be omitted if
-.I string
-is followed immediately by a newline.
-.TP
-.B \d\s+2^\s-2\u\fIstring1\fP\d\s+2^\s-2\u\fIstring2\fP\d\s+2^\s-2\u
-Quick substitution. Repeat the last command, replacing
-.I string1
-with
-.IR string2 .
-Equivalent to
-``!!:s/\fIstring1\fP/\fIstring2\fP/''
-(see \fBModifiers\fP below).
-.TP
-.B !#
-The entire command line typed so far.
-.PD
-.SS Word Designators
-.PP
-Word designators are used to select desired words from the event.
-A
-.B :
-separates the event specification from the word designator.
-It may be omitted if the word designator begins with a
-.BR ^ ,
-.BR $ ,
-.BR * ,
-.BR \- ,
-or
-.BR % .
-Words are numbered from the beginning of the line,
-with the first word being denoted by 0 (zero).
-Words are inserted into the current line separated by single spaces.
-.PP
-.PD 0
-.TP
-.B 0 (zero)
-The zeroth word. For the shell, this is the command
-word.
-.TP
-.I n
-The \fIn\fRth word.
-.TP
-.B ^
-The first argument. That is, word 1.
-.TP
-.B $
-The last argument.
-.TP
-.B %
-The word matched by the most recent `?\fIstring\fR?' search.
-.TP
-.I x\fB\-\fPy
-A range of words; `\-\fIy\fR' abbreviates `0\-\fIy\fR'.
-.TP
-.B *
-All of the words but the zeroth. This is a synonym
-for `\fI1\-$\fP'. It is not an error to use
-.B *
-if there is just one
-word in the event; the empty string is returned in that case.
-.TP
-.B x*
-Abbreviates \fIx\-$\fP.
-.TP
-.B x\-
-Abbreviates \fIx\-$\fP like \fBx*\fP, but omits the last word.
-.PD
-.PP
-If a word designator is supplied without an event specification, the
-previous command is used as the event.
-.SS Modifiers
-.PP
-After the optional word designator, there may appear a sequence of
-one or more of the following modifiers, each preceded by a `:'.
-.PP
-.PD 0
-.PP
-.TP
-.B h
-Remove a trailing file name component, leaving only the head.
-.TP
-.B t
-Remove all leading file name components, leaving the tail.
-.TP
-.B r
-Remove a trailing suffix of the form \fI.xxx\fP, leaving the
-basename.
-.TP
-.B e
-Remove all but the trailing suffix.
-.TP
-.B p
-Print the new command but do not execute it.
-.TP
-.B q
-Quote the substituted words, escaping further substitutions.
-.TP
-.B x
-Quote the substituted words as with
-.BR q ,
-but break into words at
-.B blanks
-and newlines.
-.TP
-.B s/\fIold\fP/\fInew\fP/
-Substitute
-.I new
-for the first occurrence of
-.I old
-in the event line. Any delimiter can be used in place of /. The
-final delimiter is optional if it is the last character of the
-event line. The delimiter may be quoted in
-.I old
-and
-.I new
-with a single backslash. If & appears in
-.IR new ,
-it is replaced by
-.IR old .
-A single backslash will quote the &. If
-.I old
-is null, it is set to the last
-.I old
-substituted, or, if no previous history substitutions took place,
-the last
-.I string
-in a
-.B !?\fIstring\fR\fB[?]\fR
-search.
-.TP
-.B &
-Repeat the previous substitution.
-.TP
-.B g
-Cause changes to be applied over the entire event line. This is
-used in conjunction with `\fB:s\fP' (e.g., `\fB:gs/\fIold\fP/\fInew\fP/\fR')
-or `\fB:&\fP'. If used with
-`\fB:s\fP', any delimiter can be used
-in place of /, and the final delimiter is optional
-if it is the last character of the event line.
-An \fBa\fP may be used as a synonym for \fBg\fP.
-.TP
-.B G
-Apply the following `\fBs\fP' modifier once to each word in the event line.
-.PD
-.SH "SHELL BUILTIN COMMANDS"
-.\" start of bash_builtins
-.zZ
-.PP
-Unless otherwise noted, each builtin command documented in this
-section as accepting options preceded by
-.B \-
-accepts
-.B \-\-
-to signify the end of the options.
-.sp .5
-.PD 0
-.TP
-\fB:\fP [\fIarguments\fP]
-.PD
-No effect; the command does nothing beyond expanding
-.I arguments
-and performing any specified
-redirections. A zero exit code is returned.
-.TP
-\fB .\| \fP \fIfilename\fP [\fIarguments\fP]
-.PD 0
-.TP
-\fBsource\fP \fIfilename\fP [\fIarguments\fP]
-.PD
-Read and execute commands from
-.I filename
-in the current
-shell environment and return the exit status of the last command
-executed from
-.IR filename .
-If
-.I filename
-does not contain a slash, file names in
-.SM
-.B PATH
-are used to find the directory containing
-.IR filename .
-The file searched for in
-.SM
-.B PATH
-need not be executable.
-When \fBbash\fP is not in \fIposix mode\fP, the current directory is
-searched if no file is found in
-.SM
-.BR PATH .
-If the
-.B sourcepath
-option to the
-.B shopt
-builtin command is turned off, the
-.SM
-.B PATH
-is not searched.
-If any \fIarguments\fP are supplied, they become the positional
-parameters when \fIfilename\fP is executed. Otherwise the positional
-parameters are unchanged.
-The return status is the status of the last command exited within
-the script (0 if no commands are executed), and false if
-.I filename
-is not found or cannot be read.
-.TP
-\fBalias\fP [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-\fBAlias\fP with no arguments or with the
-.B \-p
-option prints the list of aliases in the form
-\fBalias\fP \fIname\fP=\fIvalue\fP on standard output.
-When arguments are supplied, an alias is defined for
-each \fIname\fP whose \fIvalue\fP is given.
-A trailing space in \fIvalue\fP causes the next word to be
-checked for alias substitution when the alias is expanded.
-For each \fIname\fP in the argument list for which no \fIvalue\fP
-is supplied, the name and value of the alias is printed.
-\fBAlias\fP returns true unless a \fIname\fP is given for which
-no alias has been defined.
-.TP
-\fBbg\fP [\fIjobspec\fP]
-Resume the suspended job \fIjobspec\fP in the background, as if it
-had been started with
-.BR & .
-If \fIjobspec\fP is not present, the shell's notion of the
-\fIcurrent job\fP is used.
-.B bg
-.I jobspec
-returns 0 unless run when job control is disabled or, when run with
-job control enabled, if \fIjobspec\fP was not found or started without
-job control.
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP]
-.PD 0
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-q\fP \fIfunction\fP] [\fB\-u\fP \fIfunction\fP] [\fB\-r\fP \fIkeyseq\fP]
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-f\fP \fIfilename\fP
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-x\fP \fIkeyseq\fP:\fIshell\-command\fP
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fIkeyseq\fP:\fIfunction\-name\fP
-.TP
-\fBbind\fP \fIreadline\-command\fP
-.PD
-Display current
-.B readline
-key and function bindings, bind a key sequence to a
-.B readline
-function or macro, or set a
-.B readline
-variable.
-Each non-option argument is a command as it would appear in
-.IR .inputrc ,
-but each binding or command must be passed as a separate argument;
-e.g., '"\eC\-x\eC\-r": re\-read\-init\-file'.
-Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-m \fIkeymap\fP
-Use
-.I keymap
-as the keymap to be affected by the subsequent bindings.
-Acceptable
-.I keymap
-names are
-\fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi,
-vi\-move, vi\-command\fP, and
-.IR vi\-insert .
-\fIvi\fP is equivalent to \fIvi\-command\fP; \fIemacs\fP is
-equivalent to \fIemacs\-standard\fP.
-.TP
-.B \-l
-List the names of all \fBreadline\fP functions.
-.TP
-.B \-p
-Display \fBreadline\fP function names and bindings in such a way
-that they can be re-read.
-.TP
-.B \-P
-List current \fBreadline\fP function names and bindings.
-.TP
-.B \-v
-Display \fBreadline\fP variable names and values in such a way that they
-can be re-read.
-.TP
-.B \-V
-List current \fBreadline\fP variable names and values.
-.TP
-.B \-s
-Display \fBreadline\fP key sequences bound to macros and the strings
-they output in such a way that they can be re-read.
-.TP
-.B \-S
-Display \fBreadline\fP key sequences bound to macros and the strings
-they output.
-.TP
-.B \-f \fIfilename\fP
-Read key bindings from \fIfilename\fP.
-.TP
-.B \-q \fIfunction\fP
-Query about which keys invoke the named \fIfunction\fP.
-.TP
-.B \-u \fIfunction\fP
-Unbind all keys bound to the named \fIfunction\fP.
-.TP
-.B \-r \fIkeyseq\fP
-Remove any current binding for \fIkeyseq\fP.
-.TP
-.B \-x \fIkeyseq\fP:\fIshell\-command\fP
-Cause \fIshell\-command\fP to be executed whenever \fIkeyseq\fP is
-entered.
-.PD
-.PP
-The return value is 0 unless an unrecognized option is given or an
-error occurred.
-.RE
-.TP
-\fBbreak\fP [\fIn\fP]
-Exit from within a
-.BR for ,
-.BR while ,
-.BR until ,
-or
-.B select
-loop. If \fIn\fP is specified, break \fIn\fP levels.
-.I n
-must be \(>= 1. If
-.I n
-is greater than the number of enclosing loops, all enclosing loops
-are exited. The return value is 0 unless the shell is not executing
-a loop when
-.B break
-is executed.
-.TP
-\fBbuiltin\fP \fIshell\-builtin\fP [\fIarguments\fP]
-Execute the specified shell builtin, passing it
-.IR arguments ,
-and return its exit status.
-This is useful when defining a
-function whose name is the same as a shell builtin,
-retaining the functionality of the builtin within the function.
-The \fBcd\fP builtin is commonly redefined this way.
-The return status is false if
-.I shell\-builtin
-is not a shell builtin command.
-.TP
-\fBcd\fP [\fB\-L|-P\fP] [\fIdir\fP]
-Change the current directory to \fIdir\fP. The variable
-.SM
-.B HOME
-is the
-default
-.IR dir .
-The variable
-.SM
-.B CDPATH
-defines the search path for the directory containing
-.IR dir .
-Alternative directory names in
-.SM
-.B CDPATH
-are separated by a colon (:). A null directory name in
-.SM
-.B CDPATH
-is the same as the current directory, i.e., ``\fB.\fP''. If
-.I dir
-begins with a slash (/),
-then
-.SM
-.B CDPATH
-is not used. The
-.B \-P
-option says to use the physical directory structure instead of
-following symbolic links (see also the
-.B \-P
-option to the
-.B set
-builtin command); the
-.B \-L
-option forces symbolic links to be followed. An argument of
-.B \-
-is equivalent to
-.SM
-.BR $OLDPWD .
-The return value is true if the directory was successfully changed;
-false otherwise.
-.TP
-\fBcaller\fP [\fIexpr\fP]
-Returns the context of any active subroutine call (a shell function or
-a script executed with the \fB.\fP or \fBsource\fP builtins.
-Without \fIexpr\fP, \fBcaller\fP displays the line number and source
-filename of the current subroutine call.
-If a non-negative integer is supplied as \fIexpr\fP, \fBcaller\fP
-displays the line number, subroutine name, and source file corresponding
-to that position in the current execution call stack. This extra
-information may be used, for example, to print a stack trace. The
-current frame is frame 0.
-The return value is 0 unless the shell is not executing a subroutine
-call or \fIexpr\fP does not correspond to a valid position in the
-call stack.
-.TP
-\fBcommand\fP [\fB\-pVv\fP] \fIcommand\fP [\fIarg\fP ...]
-Run
-.I command
-with
-.I args
-suppressing the normal shell function lookup. Only builtin
-commands or commands found in the
-.SM
-.B PATH
-are executed. If the
-.B \-p
-option is given, the search for
-.I command
-is performed using a default value for
-.B PATH
-that is guaranteed to find all of the standard utilities.
-If either the
-.B \-V
-or
-.B \-v
-option is supplied, a description of
-.I command
-is printed. The
-.B \-v
-option causes a single word indicating the command or file name
-used to invoke
-.I command
-to be displayed; the
-.B \-V
-option produces a more verbose description.
-If the
-.B \-V
-or
-.B \-v
-option is supplied, the exit status is 0 if
-.I command
-was found, and 1 if not. If neither option is supplied and
-an error occurred or
-.I command
-cannot be found, the exit status is 127. Otherwise, the exit status of the
-.B command
-builtin is the exit status of
-.IR command .
-.TP
-\fBcompgen\fP [\fIoption\fP] [\fIword\fP]
-Generate possible completion matches for \fIword\fP according to
-the \fIoption\fPs, which may be any option accepted by the
-.B complete
-builtin with the exception of \fB\-p\fP and \fB\-r\fP, and write
-the matches to the standard output.
-When using the \fB\-F\fP or \fB\-C\fP options, the various shell variables
-set by the programmable completion facilities, while available, will not
-have useful values.
-.sp 1
-The matches will be generated in the same way as if the programmable
-completion code had generated them directly from a completion specification
-with the same flags.
-If \fIword\fP is specified, only those completions matching \fIword\fP
-will be displayed.
-.sp 1
-The return value is true unless an invalid option is supplied, or no
-matches were generated.
-.TP
-\fBcomplete\fP [\fB\-abcdefgjksuv\fP] [\fB\-o\fP \fIcomp-option\fP] [\fB\-A\fP \fIaction\fP] [\fB\-G\fP \fIglobpat\fP] [\fB\-W\fP \fIwordlist\fP] [\fB\-P\fP \fIprefix\fP] [\fB\-S\fP \fIsuffix\fP]
-.br
-[\fB\-X\fP \fIfilterpat\fP] [\fB\-F\fP \fIfunction\fP] [\fB\-C\fP \fIcommand\fP] \fIname\fP [\fIname ...\fP]
-.PD 0
-.TP
-\fBcomplete\fP \fB\-pr\fP [\fIname\fP ...]
-.PD
-Specify how arguments to each \fIname\fP should be completed.
-If the \fB\-p\fP option is supplied, or if no options are supplied,
-existing completion specifications are printed in a way that allows
-them to be reused as input.
-The \fB\-r\fP option removes a completion specification for
-each \fIname\fP, or, if no \fIname\fPs are supplied, all
-completion specifications.
-.sp 1
-The process of applying these completion specifications when word completion
-is attempted is described above under \fBProgrammable Completion\fP.
-.sp 1
-Other options, if specified, have the following meanings.
-The arguments to the \fB\-G\fP, \fB\-W\fP, and \fB\-X\fP options
-(and, if necessary, the \fB\-P\fP and \fB\-S\fP options)
-should be quoted to protect them from expansion before the
-.B complete
-builtin is invoked.
-.RS
-.PD 0
-.TP 8
-\fB\-o\fP \fIcomp-option\fP
-The \fIcomp-option\fP controls several aspects of the compspec's behavior
-beyond the simple generation of completions.
-\fIcomp-option\fP may be one of:
-.RS
-.TP 8
-.B default
-Use readline's default filename completion if the compspec generates
-no matches.
-.TP 8
-.B dirnames
-Perform directory name completion if the compspec generates no matches.
-.TP 8
-.B filenames
-Tell readline that the compspec generates filenames, so it can perform any
-filename\-specific processing (like adding a slash to directory names or
-suppressing trailing spaces). Intended to be used with shell functions.
-.TP 8
-.B nospace
-Tell readline not to append a space (the default) to words completed at
-the end of the line.
-.RE
-.TP 8
-\fB\-A\fP \fIaction\fP
-The \fIaction\fP may be one of the following to generate a list of possible
-completions:
-.RS
-.TP 8
-.B alias
-Alias names. May also be specified as \fB\-a\fP.
-.TP 8
-.B arrayvar
-Array variable names.
-.TP 8
-.B binding
-\fBReadline\fP key binding names.
-.TP 8
-.B builtin
-Names of shell builtin commands. May also be specified as \fB\-b\fP.
-.TP 8
-.B command
-Command names. May also be specified as \fB\-c\fP.
-.TP 8
-.B directory
-Directory names. May also be specified as \fB\-d\fP.
-.TP 8
-.B disabled
-Names of disabled shell builtins.
-.TP 8
-.B enabled
-Names of enabled shell builtins.
-.TP 8
-.B export
-Names of exported shell variables. May also be specified as \fB\-e\fP.
-.TP 8
-.B file
-File names. May also be specified as \fB\-f\fP.
-.TP 8
-.B function
-Names of shell functions.
-.TP 8
-.B group
-Group names. May also be specified as \fB\-g\fP.
-.TP 8
-.B helptopic
-Help topics as accepted by the \fBhelp\fP builtin.
-.TP 8
-.B hostname
-Hostnames, as taken from the file specified by the
-.SM
-.B HOSTFILE
-shell variable.
-.TP 8
-.B job
-Job names, if job control is active. May also be specified as \fB\-j\fP.
-.TP 8
-.B keyword
-Shell reserved words. May also be specified as \fB\-k\fP.
-.TP 8
-.B running
-Names of running jobs, if job control is active.
-.TP 8
-.B service
-Service names. May also be specified as \fB\-s\fP.
-.TP 8
-.B setopt
-Valid arguments for the \fB\-o\fP option to the \fBset\fP builtin.
-.TP 8
-.B shopt
-Shell option names as accepted by the \fBshopt\fP builtin.
-.TP 8
-.B signal
-Signal names.
-.TP 8
-.B stopped
-Names of stopped jobs, if job control is active.
-.TP 8
-.B user
-User names. May also be specified as \fB\-u\fP.
-.TP 8
-.B variable
-Names of all shell variables. May also be specified as \fB\-v\fP.
-.RE
-.TP 8
-\fB\-G\fP \fIglobpat\fP
-The filename expansion pattern \fIglobpat\fP is expanded to generate
-the possible completions.
-.TP 8
-\fB\-W\fP \fIwordlist\fP
-The \fIwordlist\fP is split using the characters in the
-.SM
-.B IFS
-special variable as delimiters, and each resultant word is expanded.
-The possible completions are the members of the resultant list which
-match the word being completed.
-.TP 8
-\fB\-C\fP \fIcommand\fP
-\fIcommand\fP is executed in a subshell environment, and its output is
-used as the possible completions.
-.TP 8
-\fB\-F\fP \fIfunction\fP
-The shell function \fIfunction\fP is executed in the current shell
-environment.
-When it finishes, the possible completions are retrieved from the value
-of the
-.SM
-.B COMPREPLY
-array variable.
-.TP 8
-\fB\-X\fP \fIfilterpat\fP
-\fIfilterpat\fP is a pattern as used for filename expansion.
-It is applied to the list of possible completions generated by the
-preceding options and arguments, and each completion matching
-\fIfilterpat\fP is removed from the list.
-A leading \fB!\fP in \fIfilterpat\fP negates the pattern; in this
-case, any completion not matching \fIfilterpat\fP is removed.
-.TP 8
-\fB\-P\fP \fIprefix\fP
-\fIprefix\fP is added at the beginning of each possible completion
-after all other options have been applied.
-.TP 8
-\fB\-S\fP \fIsuffix\fP
-\fIsuffix\fP is appended to each possible completion
-after all other options have been applied.
-.PD
-.PP
-The return value is true unless an invalid option is supplied, an option
-other than \fB\-p\fP or \fB\-r\fP is supplied without a \fIname\fP
-argument, an attempt is made to remove a completion specification for
-a \fIname\fP for which no specification exists, or
-an error occurs adding a completion specification.
-.RE
-.TP
-\fBcontinue\fP [\fIn\fP]
-Resume the next iteration of the enclosing
-.BR for ,
-.BR while ,
-.BR until ,
-or
-.B select
-loop.
-If
-.I n
-is specified, resume at the \fIn\fPth enclosing loop.
-.I n
-must be \(>= 1. If
-.I n
-is greater than the number of enclosing loops, the last enclosing loop
-(the ``top-level'' loop) is resumed. The return value is 0 unless the
-shell is not executing a loop when
-.B continue
-is executed.
-.TP
-\fBdeclare\fP [\fB\-afFirtx\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-.PD 0
-.TP
-\fBtypeset\fP [\fB\-afFirtx\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-.PD
-Declare variables and/or give them attributes.
-If no \fIname\fPs are given then display the values of variables.
-The
-.B \-p
-option will display the attributes and values of each
-.IR name .
-When
-.B \-p
-is used, additional options are ignored.
-The
-.B \-F
-option inhibits the display of function definitions; only the
-function name and attributes are printed.
-If the \fBextdebug\fP shell option is enabled using \fBshopt\fP,
-the source file name and line number where the function is defined
-are displayed as well. The
-.B \-F
-option implies
-.BR \-f .
-The following options can
-be used to restrict output to variables with the specified attribute or
-to give variables attributes:
-.RS
-.PD 0
-.TP
-.B \-a
-Each \fIname\fP is an array variable (see
-.B Arrays
-above).
-.TP
-.B \-f
-Use function names only.
-.TP
-.B \-i
-The variable is treated as an integer; arithmetic evaluation (see
-.SM
-.B "ARITHMETIC EVALUATION" ") "
-is performed when the variable is assigned a value.
-.TP
-.B \-r
-Make \fIname\fPs readonly. These names cannot then be assigned values
-by subsequent assignment statements or unset.
-.TP
-.B \-t
-Give each \fIname\fP the \fItrace\fP attribute.
-Traced functions inherit the \fBDEBUG\fP trap from the calling shell.
-The trace attribute has no special meaning for variables.
-.TP
-.B \-x
-Mark \fIname\fPs for export to subsequent commands via the environment.
-.PD
-.PP
-Using `+' instead of `\-'
-turns off the attribute instead, with the exception that \fB+a\fP
-may not be used to destroy an array variable. When used in a function,
-makes each
-\fIname\fP local, as with the
-.B local
-command.
-If a variable name is followed by =\fIvalue\fP, the value of
-the variable is set to \fIvalue\fP.
-The return value is 0 unless an invalid option is encountered,
-an attempt is made to define a function using
-.if n ``\-f foo=bar'',
-.if t \f(CW\-f foo=bar\fP,
-an attempt is made to assign a value to a readonly variable,
-an attempt is made to assign a value to an array variable without
-using the compound assignment syntax (see
-.B Arrays
-above), one of the \fInames\fP is not a valid shell variable name,
-an attempt is made to turn off readonly status for a readonly variable,
-an attempt is made to turn off array status for an array variable,
-or an attempt is made to display a non-existent function with \fB\-f\fP.
-.RE
-.TP
-.B dirs [\fB\-clpv\fP] [+\fIn\fP] [\-\fIn\fP]
-Without options, displays the list of currently remembered directories.
-The default display is on a single line with directory names separated
-by spaces.
-Directories are added to the list with the
-.B pushd
-command; the
-.B popd
-command removes entries from the list.
-.RS
-.PD 0
-.TP
-\fB+\fP\fIn\fP
-Displays the \fIn\fPth entry counting from the left of the list
-shown by
-.B dirs
-when invoked without options, starting with zero.
-.TP
-\fB\-\fP\fIn\fP
-Displays the \fIn\fPth entry counting from the right of the list
-shown by
-.B dirs
-when invoked without options, starting with zero.
-.TP
-.B \-c
-Clears the directory stack by deleting all of the entries.
-.TP
-.B \-l
-Produces a longer listing; the default listing format uses a
-tilde to denote the home directory.
-.TP
-.B \-p
-Print the directory stack with one entry per line.
-.TP
-.B \-v
-Print the directory stack with one entry per line,
-prefixing each entry with its index in the stack.
-.PD
-.PP
-The return value is 0 unless an
-invalid option is supplied or \fIn\fP indexes beyond the end
-of the directory stack.
-.RE
-.TP
-\fBdisown\fP [\fB\-ar\fP] [\fB\-h\fP] [\fIjobspec\fP ...]
-Without options, each
-.I jobspec
-is removed from the table of active jobs.
-If the \fB\-h\fP option is given, each
-.I jobspec
-is not removed from the table, but is marked so that
-.SM
-.B SIGHUP
-is not sent to the job if the shell receives a
-.SM
-.BR SIGHUP .
-If no
-.I jobspec
-is present, and neither the
-.B \-a
-nor the
-.B \-r
-option is supplied, the \fIcurrent job\fP is used.
-If no
-.I jobspec
-is supplied, the
-.B \-a
-option means to remove or mark all jobs; the
-.B \-r
-option without a
-.I jobspec
-argument restricts operation to running jobs.
-The return value is 0 unless a
-.I jobspec
-does not specify a valid job.
-.TP
-\fBecho\fP [\fB\-neE\fP] [\fIarg\fP ...]
-Output the \fIarg\fPs, separated by spaces, followed by a newline.
-The return status is always 0.
-If \fB\-n\fP is specified, the trailing newline is
-suppressed. If the \fB\-e\fP option is given, interpretation of
-the following backslash-escaped characters is enabled. The
-.B \-E
-option disables the interpretation of these escape characters,
-even on systems where they are interpreted by default.
-The \fBxpg_echo\fP shell option may be used to
-dynamically determine whether or not \fBecho\fP expands these
-escape characters by default.
-.B echo
-does not interpret
-.B \-\-
-to mean the end of options.
-.B echo
-interprets the following escape sequences:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ec
-suppress trailing newline
-.TP
-.B \ee
-an escape character
-.TP
-.B \ef
-form feed
-.TP
-.B \en
-new line
-.TP
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP
-.B \ev
-vertical tab
-.TP
-.B \e\e
-backslash
-.TP
-.B \e0\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(zero to three octal digits)
-.TP
-.B \e\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(one to three octal digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.PD
-.RE
-.TP
-\fBenable\fP [\fB\-adnps\fP] [\fB\-f\fP \fIfilename\fP] [\fIname\fP ...]
-Enable and disable builtin shell commands.
-Disabling a builtin allows a disk command which has the same name
-as a shell builtin to be executed without specifying a full pathname,
-even though the shell normally searches for builtins before disk commands.
-If \fB\-n\fP is used, each \fIname\fP
-is disabled; otherwise,
-\fInames\fP are enabled. For example, to use the
-.B test
-binary found via the
-.SM
-.B PATH
-instead of the shell builtin version, run
-.if t \f(CWenable -n test\fP.
-.if n ``enable -n test''.
-The
-.B \-f
-option means to load the new builtin command
-.I name
-from shared object
-.IR filename ,
-on systems that support dynamic loading. The
-.B \-d
-option will delete a builtin previously loaded with
-.BR \-f .
-If no \fIname\fP arguments are given, or if the
-.B \-p
-option is supplied, a list of shell builtins is printed.
-With no other option arguments, the list consists of all enabled
-shell builtins.
-If \fB\-n\fP is supplied, only disabled builtins are printed.
-If \fB\-a\fP is supplied, the list printed includes all builtins, with an
-indication of whether or not each is enabled.
-If \fB\-s\fP is supplied, the output is restricted to the POSIX
-\fIspecial\fP builtins.
-The return value is 0 unless a
-.I name
-is not a shell builtin or there is an error loading a new builtin
-from a shared object.
-.TP
-\fBeval\fP [\fIarg\fP ...]
-The \fIarg\fPs are read and concatenated together into a single
-command. This command is then read and executed by the shell, and
-its exit status is returned as the value of
-.BR eval .
-If there are no
-.IR args ,
-or only null arguments,
-.B eval
-returns 0.
-.TP
-\fBexec\fP [\fB\-cl\fP] [\fB\-a\fP \fIname\fP] [\fIcommand\fP [\fIarguments\fP]]
-If
-.I command
-is specified, it replaces the shell.
-No new process is created. The
-.I arguments
-become the arguments to \fIcommand\fP.
-If the
-.B \-l
-option is supplied,
-the shell places a dash at the beginning of the zeroth arg passed to
-.IR command .
-This is what
-.IR login (1)
-does. The
-.B \-c
-option causes
-.I command
-to be executed with an empty environment. If
-.B \-a
-is supplied, the shell passes
-.I name
-as the zeroth argument to the executed command. If
-.I command
-cannot be executed for some reason, a non-interactive shell exits,
-unless the shell option
-.B execfail
-is enabled, in which case it returns failure.
-An interactive shell returns failure if the file cannot be executed.
-If
-.I command
-is not specified, any redirections take effect in the current shell,
-and the return status is 0. If there is a redirection error, the
-return status is 1.
-.TP
-\fBexit\fP [\fIn\fP]
-Cause the shell to exit
-with a status of \fIn\fP. If
-.I n
-is omitted, the exit status
-is that of the last command executed.
-A trap on
-.SM
-.B EXIT
-is executed before the shell terminates.
-.TP
-\fBexport\fP [\fB\-fn\fP\^] [\fIname\fP[=\fIword\fP]] ...
-.PD 0
-.TP
-.B export \-p
-.PD
-The supplied
-.I names
-are marked for automatic export to the environment of
-subsequently executed commands. If the
-.B \-f
-option is given,
-the
-.I names
-refer to functions.
-If no
-.I names
-are given, or if the
-.B \-p
-option is supplied, a list
-of all names that are exported in this shell is printed.
-The
-.B \-n
-option causes the export property to be removed from the
-named variables.
-If a variable name is followed by =\fIword\fP, the value of
-the variable is set to \fIword\fP.
-.B export
-returns an exit status of 0 unless an invalid option is
-encountered,
-one of the \fInames\fP is not a valid shell variable name, or
-.B \-f
-is supplied with a
-.I name
-that is not a function.
-.TP
-\fBfc\fP [\fB\-e\fP \fIename\fP] [\fB\-nlr\fP] [\fIfirst\fP] [\fIlast\fP]
-.PD 0
-.TP
-\fBfc\fP \fB\-s\fP [\fIpat\fP=\fIrep\fP] [\fIcmd\fP]
-.PD
-Fix Command. In the first form, a range of commands from
-.I first
-to
-.I last
-is selected from the history list.
-.I First
-and
-.I last
-may be specified as a string (to locate the last command beginning
-with that string) or as a number (an index into the history list,
-where a negative number is used as an offset from the current
-command number). If
-.I last
-is not specified it is set to
-the current command for listing (so that
-.if n ``fc \-l \-10''
-.if t \f(CWfc \-l \-10\fP
-prints the last 10 commands) and to
-.I first
-otherwise.
-If
-.I first
-is not specified it is set to the previous
-command for editing and \-16 for listing.
-.sp 1
-The
-.B \-n
-option suppresses
-the command numbers when listing. The
-.B \-r
-option reverses the order of
-the commands. If the
-.B \-l
-option is given,
-the commands are listed on
-standard output. Otherwise, the editor given by
-.I ename
-is invoked
-on a file containing those commands. If
-.I ename
-is not given, the
-value of the
-.SM
-.B FCEDIT
-variable is used, and
-the value of
-.SM
-.B EDITOR
-if
-.SM
-.B FCEDIT
-is not set. If neither variable is set,
-.FN vi
-is used. When editing is complete, the edited commands are
-echoed and executed.
-.sp 1
-In the second form, \fIcommand\fP is re-executed after each instance
-of \fIpat\fP is replaced by \fIrep\fP.
-A useful alias to use with this is
-.if n ``r="fc -s"'',
-.if t \f(CWr='fc \-s'\fP,
-so that typing
-.if n ``r cc''
-.if t \f(CWr cc\fP
-runs the last command beginning with
-.if n ``cc''
-.if t \f(CWcc\fP
-and typing
-.if n ``r''
-.if t \f(CWr\fP
-re-executes the last command.
-.sp 1
-If the first form is used, the return value is 0 unless an invalid
-option is encountered or
-.I first
-or
-.I last
-specify history lines out of range.
-If the
-.B \-e
-option is supplied, the return value is the value of the last
-command executed or failure if an error occurs with the temporary
-file of commands. If the second form is used, the return status
-is that of the command re-executed, unless
-.I cmd
-does not specify a valid history line, in which case
-.B fc
-returns failure.
-.TP
-\fBfg\fP [\fIjobspec\fP]
-Resume
-.I jobspec
-in the foreground, and make it the current job.
-If
-.I jobspec
-is not present, the shell's notion of the \fIcurrent job\fP is used.
-The return value is that of the command placed into the foreground,
-or failure if run when job control is disabled or, when run with
-job control enabled, if
-.I jobspec
-does not specify a valid job or
-.I jobspec
-specifies a job that was started without job control.
-.TP
-\fBgetopts\fP \fIoptstring\fP \fIname\fP [\fIargs\fP]
-.B getopts
-is used by shell procedures to parse positional parameters.
-.I optstring
-contains the option characters to be recognized; if a character
-is followed by a colon, the option is expected to have an
-argument, which should be separated from it by white space.
-The colon and question mark characters may not be used as
-option characters.
-Each time it is invoked,
-.B getopts
-places the next option in the shell variable
-.IR name ,
-initializing
-.I name
-if it does not exist,
-and the index of the next argument to be processed into the
-variable
-.SM
-.BR OPTIND .
-.SM
-.B OPTIND
-is initialized to 1 each time the shell or a shell script
-is invoked. When an option requires an argument,
-.B getopts
-places that argument into the variable
-.SM
-.BR OPTARG .
-The shell does not reset
-.SM
-.B OPTIND
-automatically; it must be manually reset between multiple
-calls to
-.B getopts
-within the same shell invocation if a new set of parameters
-is to be used.
-.sp 1
-When the end of options is encountered, \fBgetopts\fP exits with a
-return value greater than zero.
-\fBOPTIND\fP is set to the index of the first non-option argument,
-and \fBname\fP is set to ?.
-.sp 1
-.B getopts
-normally parses the positional parameters, but if more arguments are
-given in
-.IR args ,
-.B getopts
-parses those instead.
-.sp 1
-.B getopts
-can report errors in two ways. If the first character of
-.I optstring
-is a colon,
-.I silent
-error reporting is used. In normal operation diagnostic messages
-are printed when invalid options or missing option arguments are
-encountered.
-If the variable
-.SM
-.B OPTERR
-is set to 0, no error messages will be displayed, even if the first
-character of
-.I optstring
-is not a colon.
-.sp 1
-If an invalid option is seen,
-.B getopts
-places ? into
-.I name
-and, if not silent,
-prints an error message and unsets
-.SM
-.BR OPTARG .
-If
-.B getopts
-is silent,
-the option character found is placed in
-.SM
-.B OPTARG
-and no diagnostic message is printed.
-.sp 1
-If a required argument is not found, and
-.B getopts
-is not silent,
-a question mark (\^\fB?\fP\^) is placed in
-.IR name ,
-.SM
-.B OPTARG
-is unset, and a diagnostic message is printed.
-If
-.B getopts
-is silent, then a colon (\^\fB:\fP\^) is placed in
-.I name
-and
-.SM
-.B OPTARG
-is set to the option character found.
-.sp 1
-.B getopts
-returns true if an option, specified or unspecified, is found.
-It returns false if the end of options is encountered or an
-error occurs.
-.TP
-\fBhash\fP [\fB\-lr\fP] [\fB\-p\fP \fIfilename\fP] [\fB\-dt\fP] [\fIname\fP]
-For each
-.IR name ,
-the full file name of the command is determined by searching
-the directories in
-.B $PATH
-and remembered.
-If the
-.B \-p
-option is supplied, no path search is performed, and
-.I filename
-is used as the full file name of the command.
-The
-.B \-r
-option causes the shell to forget all
-remembered locations.
-The
-.B \-d
-option causes the shell to forget the remembered location of each \fIname\fP.
-If the
-.B \-t
-option is supplied, the full pathname to which each \fIname\fP corresponds
-is printed. If multiple \fIname\fP arguments are supplied with \fB\-t\fP,
-the \fIname\fP is printed before the hashed full pathname.
-The
-.B \-l
-option causes output to be displayed in a format that may be reused as input.
-If no arguments are given, or if only \fB\-l\fP is supplied,
-information about remembered commands is printed.
-The return status is true unless a
-.I name
-is not found or an invalid option is supplied.
-.TP
-\fBhelp\fP [\fB\-s\fP] [\fIpattern\fP]
-Display helpful information about builtin commands. If
-.I pattern
-is specified,
-.B help
-gives detailed help on all commands matching
-.IR pattern ;
-otherwise help for all the builtins and shell control structures
-is printed.
-The \fB\-s\fP option restricts the information displayed to a short
-usage synopsis.
-The return status is 0 unless no command matches
-.IR pattern .
-.TP
-\fBhistory [\fIn\fP]
-.PD 0
-.TP
-\fBhistory\fP \fB\-c\fP
-.TP
-\fBhistory \-d\fP \fIoffset\fP
-.TP
-\fBhistory\fP \fB\-anrw\fP [\fIfilename\fP]
-.TP
-\fBhistory\fP \fB\-p\fP \fIarg\fP [\fIarg ...\fP]
-.TP
-\fBhistory\fP \fB\-s\fP \fIarg\fP [\fIarg ...\fP]
-.PD
-With no options, display the command
-history list with line numbers. Lines listed
-with a
-.B *
-have been modified. An argument of
-.I n
-lists only the last
-.I n
-lines. If \fIfilename\fP is supplied, it is used as the
-name of the history file; if not, the value of
-.SM
-.B HISTFILE
-is used. Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-c
-Clear the history list by deleting all the entries.
-.TP
-\fB\-d\fP \fIoffset\fP
-Delete the history entry at position \fIoffset\fP.
-.TP
-.B \-a
-Append the ``new'' history lines (history lines entered since the
-beginning of the current \fBbash\fP session) to the history file.
-.TP
-.B \-n
-Read the history lines not already read from the history
-file into the current history list. These are lines
-appended to the history file since the beginning of the
-current \fBbash\fP session.
-.TP
-.B \-r
-Read the contents of the history file
-and use them as the current history.
-.TP
-.B \-w
-Write the current history to the history file, overwriting the
-history file's contents.
-.TP
-.B \-p
-Perform history substitution on the following \fIargs\fP and display
-the result on the standard output.
-Does not store the results in the history list.
-Each \fIarg\fP must be quoted to disable normal history expansion.
-.TP
-.B \-s
-Store the
-.I args
-in the history list as a single entry. The last command in the
-history list is removed before the
-.I args
-are added.
-.PD
-.PP
-The return value is 0 unless an invalid option is encountered, an
-error occurs while reading or writing the history file, an invalid
-\fIoffset\fP is supplied as an argument to \fB\-d\fP, or the
-history expansion supplied as an argument to \fB\-p\fP fails.
-.RE
-.TP
-\fBjobs\fP [\fB\-lnprs\fP] [ \fIjobspec\fP ... ]
-.PD 0
-.TP
-\fBjobs\fP \fB\-x\fP \fIcommand\fP [ \fIargs\fP ... ]
-.PD
-The first form lists the active jobs. The options have the following
-meanings:
-.RS
-.PD 0
-.TP
-.B \-l
-List process IDs
-in addition to the normal information.
-.TP
-.B \-p
-List only the process ID of the job's process group
-leader.
-.TP
-.B \-n
-Display information only about jobs that have changed status since
-the user was last notified of their status.
-.TP
-.B \-r
-Restrict output to running jobs.
-.TP
-.B \-s
-Restrict output to stopped jobs.
-.PD
-.PP
-If
-.I jobspec
-is given, output is restricted to information about that job.
-The return status is 0 unless an invalid option is encountered
-or an invalid
-.I jobspec
-is supplied.
-.PP
-If the
-.B \-x
-option is supplied,
-.B jobs
-replaces any
-.I jobspec
-found in
-.I command
-or
-.I args
-with the corresponding process group ID, and executes
-.I command
-passing it
-.IR args ,
-returning its exit status.
-.RE
-.TP
-\fBkill\fP [\fB\-s\fP \fIsigspec\fP | \fB\-n\fP \fIsignum\fP | \fB\-\fP\fIsigspec\fP] [\fIpid\fP | \fIjobspec\fP] ...
-.PD 0
-.TP
-\fBkill\fP \fB\-l\fP [\fIsigspec\fP | \fIexit_status\fP]
-.PD
-Send the signal named by
-.I sigspec
-or
-.I signum
-to the processes named by
-.I pid
-or
-.IR jobspec .
-.I sigspec
-is either a signal name such as
-.SM
-.B SIGKILL
-or a signal number;
-.I signum
-is a signal number. If
-.I sigspec
-is a signal name, the name may be
-given with or without the
-.SM
-.B SIG
-prefix.
-If
-.I sigspec
-is not present, then
-.SM
-.B SIGTERM
-is assumed.
-An argument of
-.B \-l
-lists the signal names.
-If any arguments are supplied when
-.B \-l
-is given, the names of the signals corresponding to the arguments are
-listed, and the return status is 0.
-The \fIexit_status\fP argument to
-.B \-l
-is a number specifying either a signal number or the exit status of
-a process terminated by a signal.
-.B kill
-returns true if at least one signal was successfully sent, or false
-if an error occurs or an invalid option is encountered.
-.TP
-\fBlet\fP \fIarg\fP [\fIarg\fP ...]
-Each
-.I arg
-is an arithmetic expression to be evaluated (see
-.SM
-.BR "ARITHMETIC EVALUATION" ).
-If the last
-.I arg
-evaluates to 0,
-.B let
-returns 1; 0 is returned otherwise.
-.TP
-\fBlocal\fP [\fIoption\fP] [\fIname\fP[=\fIvalue\fP] ...]
-For each argument, a local variable named
-.I name
-is created, and assigned
-.IR value .
-The \fIoption\fP can be any of the options accepted by \fBdeclare\fP.
-When
-.B local
-is used within a function, it causes the variable
-.I name
-to have a visible scope restricted to that function and its children.
-With no operands,
-.B local
-writes a list of local variables to the standard output. It is
-an error to use
-.B local
-when not within a function. The return status is 0 unless
-.B local
-is used outside a function, an invalid
-.I name
-is supplied, or
-\fIname\fP is a readonly variable.
-.TP
-.B logout
-Exit a login shell.
-.TP
-\fBpopd\fP [\-\fBn\fP] [+\fIn\fP] [\-\fIn\fP]
-Removes entries from the directory stack. With no arguments,
-removes the top directory from the stack, and performs a
-.B cd
-to the new top directory.
-Arguments, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-\fB+\fP\fIn\fP
-Removes the \fIn\fPth entry counting from the left of the list
-shown by
-.BR dirs ,
-starting with zero. For example:
-.if n ``popd +0''
-.if t \f(CWpopd +0\fP
-removes the first directory,
-.if n ``popd +1''
-.if t \f(CWpopd +1\fP
-the second.
-.TP
-\fB\-\fP\fIn\fP
-Removes the \fIn\fPth entry counting from the right of the list
-shown by
-.BR dirs ,
-starting with zero. For example:
-.if n ``popd -0''
-.if t \f(CWpopd -0\fP
-removes the last directory,
-.if n ``popd -1''
-.if t \f(CWpopd -1\fP
-the next to last.
-.TP
-.B \-n
-Suppresses the normal change of directory when removing directories
-from the stack, so that only the stack is manipulated.
-.PD
-.PP
-If the
-.B popd
-command is successful, a
-.B dirs
-is performed as well, and the return status is 0.
-.B popd
-returns false if an invalid option is encountered, the directory stack
-is empty, a non-existent directory stack entry is specified, or the
-directory change fails.
-.RE
-.TP
-\fBprintf\fP \fIformat\fP [\fIarguments\fP]
-Write the formatted \fIarguments\fP to the standard output under the
-control of the \fIformat\fP.
-The \fIformat\fP is a character string which contains three types of objects:
-plain characters, which are simply copied to standard output, character
-escape sequences, which are converted and copied to the standard output, and
-format specifications, each of which causes printing of the next successive
-\fIargument\fP.
-In addition to the standard \fIprintf\fP(1) formats, \fB%b\fP causes
-\fBprintf\fP to expand backslash escape sequences in the corresponding
-\fIargument\fP, and \fB%q\fP causes \fBprintf\fP to output the corresponding
-\fIargument\fP in a format that can be reused as shell input.
-.sp 1
-The \fIformat\fP is reused as necessary to consume all of the \fIarguments\fP.
-If the \fIformat\fP requires more \fIarguments\fP than are supplied, the
-extra format specifications behave as if a zero value or null string, as
-appropriate, had been supplied. The return value is zero on success,
-non-zero on failure.
-.TP
-\fBpushd\fP [\fB\-n\fP] [\fIdir\fP]
-.PD 0
-.TP
-\fBpushd\fP [\fB\-n\fP] [+\fIn\fP] [\-\fIn\fP]
-.PD
-Adds a directory to the top of the directory stack, or rotates
-the stack, making the new top of the stack the current working
-directory. With no arguments, exchanges the top two directories
-and returns 0, unless the directory stack is empty.
-Arguments, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-\fB+\fP\fIn\fP
-Rotates the stack so that the \fIn\fPth directory
-(counting from the left of the list shown by
-.BR dirs ,
-starting with zero)
-is at the top.
-.TP
-\fB\-\fP\fIn\fP
-Rotates the stack so that the \fIn\fPth directory
-(counting from the right of the list shown by
-.BR dirs ,
-starting with zero) is at the top.
-.TP
-.B \-n
-Suppresses the normal change of directory when adding directories
-to the stack, so that only the stack is manipulated.
-.TP
-.I dir
-Adds
-.I dir
-to the directory stack at the top, making it the
-new current working directory.
-.PD
-.PP
-If the
-.B pushd
-command is successful, a
-.B dirs
-is performed as well.
-If the first form is used,
-.B pushd
-returns 0 unless the cd to
-.I dir
-fails. With the second form,
-.B pushd
-returns 0 unless the directory stack is empty,
-a non-existent directory stack element is specified,
-or the directory change to the specified new current directory
-fails.
-.RE
-.TP
-\fBpwd\fP [\fB\-LP\fP]
-Print the absolute pathname of the current working directory.
-The pathname printed contains no symbolic links if the
-.B \-P
-option is supplied or the
-.B \-o physical
-option to the
-.B set
-builtin command is enabled.
-If the
-.B \-L
-option is used, the pathname printed may contain symbolic links.
-The return status is 0 unless an error occurs while
-reading the name of the current directory or an
-invalid option is supplied.
-.TP
-\fBread\fP [\fB\-ers\fP] [\fB\-u\fP \fIfd\fP] [\fB\-t\fP \fItimeout\fP] [\fB\-a\fP \fIaname\fP] [\fB\-p\fP \fIprompt\fP] [\fB\-n\fP \fInchars\fP] [\fB\-d\fP \fIdelim\fP] [\fIname\fP ...]
-One line is read from the standard input, or from the file descriptor
-\fIfd\fP supplied as an argument to the \fB\-u\fP option, and the first word
-is assigned to the first
-.IR name ,
-the second word to the second
-.IR name ,
-and so on, with leftover words and their intervening separators assigned
-to the last
-.IR name .
-If there are fewer words read from the input stream than names,
-the remaining names are assigned empty values.
-The characters in
-.SM
-.B IFS
-are used to split the line into words.
-The backslash character (\fB\e\fP) may be used to remove any special
-meaning for the next character read and for line continuation.
-Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-a \fIaname\fP
-The words are assigned to sequential indices
-of the array variable
-.IR aname ,
-starting at 0.
-.I aname
-is unset before any new values are assigned.
-Other \fIname\fP arguments are ignored.
-.TP
-.B \-d \fIdelim\fP
-The first character of \fIdelim\fP is used to terminate the input line,
-rather than newline.
-.TP
-.B \-e
-If the standard input
-is coming from a terminal,
-.B readline
-(see
-.SM
-.B READLINE
-above) is used to obtain the line.
-.TP
-.B \-n \fInchars\fP
-\fBread\fP returns after reading \fInchars\fP characters rather than
-waiting for a complete line of input.
-.TP
-.B \-p \fIprompt\fP
-Display \fIprompt\fP on standard error, without a
-trailing newline, before attempting to read any input. The prompt
-is displayed only if input is coming from a terminal.
-.TP
-.B \-r
-Backslash does not act as an escape character.
-The backslash is considered to be part of the line.
-In particular, a backslash-newline pair may not be used as a line
-continuation.
-.TP
-.B \-s
-Silent mode. If input is coming from a terminal, characters are
-not echoed.
-.TP
-.B \-t \fItimeout\fP
-Cause \fBread\fP to time out and return failure if a complete line of
-input is not read within \fItimeout\fP seconds.
-This option has no effect if \fBread\fP is not reading input from the
-terminal or a pipe.
-.TP
-.B \-u \fIfd\FP
-Read input from file descriptor \fIfd\fP.
-.PD
-.PP
-If no
-.I names
-are supplied, the line read is assigned to the variable
-.SM
-.BR REPLY .
-The return code is zero, unless end-of-file is encountered, \fBread\fP
-times out, or an invalid file descriptor is supplied as the argument to
-\fB\-u\fP.
-.RE
-.TP
-\fBreadonly\fP [\fB\-apf\fP] [\fIname\fP[=\fIword\fP] ...]
-.PD
-The given
-\fInames\fP are marked readonly; the values of these
-.I names
-may not be changed by subsequent assignment.
-If the
-.B \-f
-option is supplied, the functions corresponding to the
-\fInames\fP are so
-marked.
-The
-.B \-a
-option restricts the variables to arrays.
-If no
-.I name
-arguments are given, or if the
-.B \-p
-option is supplied, a list of all readonly names is printed.
-The
-.B \-p
-option causes output to be displayed in a format that
-may be reused as input.
-If a variable name is followed by =\fIword\fP, the value of
-the variable is set to \fIword\fP.
-The return status is 0 unless an invalid option is encountered,
-one of the
-.I names
-is not a valid shell variable name, or
-.B \-f
-is supplied with a
-.I name
-that is not a function.
-.TP
-\fBreturn\fP [\fIn\fP]
-Causes a function to exit with the return value specified by
-.IR n .
-If
-.I n
-is omitted, the return status is that of the last command
-executed in the function body. If used outside a function,
-but during execution of a script by the
-.B .
-(\fBsource\fP) command, it causes the shell to stop executing
-that script and return either
-.I n
-or the exit status of the last command executed within the
-script as the exit status of the script. If used outside a
-function and not during execution of a script by \fB.\fP\^,
-the return status is false.
-Any command associated with the \fBRETURN\fP trap is executed
-before execution resumes after the function or script.
-.TP
-\fBset\fP [\fB\-\-abefhkmnptuvxBCHP\fP] [\fB\-o\fP \fIoption\fP] [\fIarg\fP ...]
-Without options, the name and value of each shell variable are displayed
-in a format that can be reused as input.
-The output is sorted according to the current locale.
-When options are specified, they set or unset shell attributes.
-Any arguments remaining after the options are processed are treated
-as values for the positional parameters and are assigned, in order, to
-.BR $1 ,
-.BR $2 ,
-.B ...
-.BR $\fIn\fP .
-Options, if specified, have the following meanings:
-.RS
-.PD 0
-.TP 8
-.B \-a
-Automatically mark variables and functions which are modified or created
-for export to the environment of subsequent commands.
-.TP 8
-.B \-b
-Report the status of terminated background jobs
-immediately, rather than before the next primary prompt. This is
-effective only when job control is enabled.
-.TP 8
-.B \-e
-Exit immediately if a \fIsimple command\fP (see
-.SM
-.B SHELL GRAMMAR
-above) exits with a non-zero status.
-The shell does not exit if the
-command that fails is part of the command list immediately following a
-.B while
-or
-.B until
-keyword,
-part of the test in an
-.I if
-statement, part of a
-.B &&
-or
-.B \(bv\(bv
-list, or if the command's return value is
-being inverted via
-.BR ! .
-A trap on \fBERR\fP, if set, is executed before the shell exits.
-.TP 8
-.B \-f
-Disable pathname expansion.
-.TP 8
-.B \-h
-Remember the location of commands as they are looked up for execution.
-This is enabled by default.
-.TP 8
-.B \-k
-All arguments in the form of assignment statements
-are placed in the environment for a command, not just
-those that precede the command name.
-.TP 8
-.B \-m
-Monitor mode. Job control is enabled. This option is on
-by default for interactive shells on systems that support
-it (see
-.SM
-.B JOB CONTROL
-above). Background processes run in a separate process
-group and a line containing their exit status is printed
-upon their completion.
-.TP 8
-.B \-n
-Read commands but do not execute them. This may be used to
-check a shell script for syntax errors. This is ignored by
-interactive shells.
-.TP 8
-.B \-o \fIoption\-name\fP
-The \fIoption\-name\fP can be one of the following:
-.RS
-.TP 8
-.B allexport
-Same as
-.BR \-a .
-.TP 8
-.B braceexpand
-Same as
-.BR \-B .
-.TP 8
-.B emacs
-Use an emacs-style command line editing interface. This is enabled
-by default when the shell is interactive, unless the shell is started
-with the
-.B \-\-noediting
-option.
-.TP 8
-.B errtrace
-Same as
-.BR \-E .
-.TP 8
-.B functrace
-Same as
-.BR \-T .
-.TP 8
-.B errexit
-Same as
-.BR \-e .
-.TP 8
-.B hashall
-Same as
-.BR \-h .
-.TP 8
-.B histexpand
-Same as
-.BR \-H .
-.TP 8
-.B history
-Enable command history, as described above under
-.SM
-.BR HISTORY .
-This option is on by default in interactive shells.
-.TP 8
-.B ignoreeof
-The effect is as if the shell command
-.if t \f(CWIGNOREEOF=10\fP
-.if n ``IGNOREEOF=10''
-had been executed
-(see
-.B Shell Variables
-above).
-.TP 8
-.B keyword
-Same as
-.BR \-k .
-.TP 8
-.B monitor
-Same as
-.BR \-m .
-.TP 8
-.B noclobber
-Same as
-.BR \-C .
-.TP 8
-.B noexec
-Same as
-.BR \-n .
-.TP 8
-.B noglob
-Same as
-.BR \-f .
-.B nolog
-Currently ignored.
-.TP 8
-.B notify
-Same as
-.BR \-b .
-.TP 8
-.B nounset
-Same as
-.BR \-u .
-.TP 8
-.B onecmd
-Same as
-.BR \-t .
-.TP 8
-.B physical
-Same as
-.BR \-P .
-.TP 8
-.B posix
-Change the behavior of
-.B bash
-where the default operation differs
-from the POSIX 1003.2 standard to match the standard (\fIposix mode\fP).
-.TP 8
-.B privileged
-Same as
-.BR \-p .
-.TP 8
-.B verbose
-Same as
-.BR \-v .
-.TP 8
-.B vi
-Use a vi-style command line editing interface.
-.TP 8
-.B xtrace
-Same as
-.BR \-x .
-.sp .5
-.PP
-If
-.B \-o
-is supplied with no \fIoption\-name\fP, the values of the current options are
-printed.
-If
-.B +o
-is supplied with no \fIoption\-name\fP, a series of
-.B set
-commands to recreate the current option settings is displayed on
-the standard output.
-.RE
-.TP 8
-.B \-p
-Turn on
-.I privileged
-mode. In this mode, the
-.SM
-.B $ENV
-and
-.SM
-.B $BASH_ENV
-files are not processed, shell functions are not inherited from the
-environment, and the
-.SM
-.B SHELLOPTS
-variable, if it appears in the environment, is ignored.
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the \fB\-p\fP option is not supplied, these actions
-are taken and the effective user id is set to the real user id.
-If the \fB\-p\fP option is supplied at startup, the effective user id is
-not reset.
-Turning this option off causes the effective user
-and group ids to be set to the real user and group ids.
-.TP 8
-.B \-t
-Exit after reading and executing one command.
-.TP 8
-.B \-u
-Treat unset variables as an error when performing
-parameter expansion. If expansion is attempted on an
-unset variable, the shell prints an error message, and,
-if not interactive, exits with a non-zero status.
-.TP 8
-.B \-v
-Print shell input lines as they are read.
-.TP 8
-.B \-x
-After expanding each \fIsimple command\fP,
-\fBfor\fP command, \fBcase\fP command, \fBselect\fP command, or
-arithmetic \fBfor\fP command, display the expanded value of
-.SM
-.BR PS4 ,
-followed by the command and its expanded arguments
-or associated word list.
-.TP 8
-.B \-B
-The shell performs brace expansion (see
-.B Brace Expansion
-above). This is on by default.
-.TP 8
-.B \-C
-If set,
-.B bash
-does not overwrite an existing file with the
-.BR > ,
-.BR >& ,
-and
-.B <>
-redirection operators. This may be overridden when
-creating output files by using the redirection operator
-.B >|
-instead of
-.BR > .
-.TP 8
-.B \-E
-If set, any trap on \fBERR\fP is inherited by shell functions, command
-substitutions, and commands executed in a subshell environment.
-The \fBERR\fP trap is normally not inherited in such cases.
-.TP 8
-.B \-H
-Enable
-.B !
-style history substitution. This option is on by
-default when the shell is interactive.
-.TP 8
-.B \-P
-If set, the shell does not follow symbolic links when executing
-commands such as
-.B cd
-that change the current working directory. It uses the
-physical directory structure instead. By default,
-.B bash
-follows the logical chain of directories when performing commands
-which change the current directory.
-.TP 8
-.B \-T
-If set, any trap on \fBDEBUG\fP is inherited by shell functions, command
-substitutions, and commands executed in a subshell environment.
-The \fBDEBUG\fP trap is normally not inherited in such cases.
-.TP 8
-.B \-\-
-If no arguments follow this option, then the positional parameters are
-unset. Otherwise, the positional parameters are set to the
-\fIarg\fPs, even if some of them begin with a
-.BR \- .
-.TP 8
-.B \-
-Signal the end of options, cause all remaining \fIarg\fPs to be
-assigned to the positional parameters. The
-.B \-x
-and
-.B \-v
-options are turned off.
-If there are no \fIarg\fPs,
-the positional parameters remain unchanged.
-.PD
-.PP
-The options are off by default unless otherwise noted.
-Using + rather than \- causes these options to be turned off.
-The options can also be specified as arguments to an invocation of
-the shell.
-The current set of options may be found in
-.BR $\- .
-The return status is always true unless an invalid option is encountered.
-.RE
-.TP
-\fBshift\fP [\fIn\fP]
-The positional parameters from \fIn\fP+1 ... are renamed to
-.B $1
-.B ....
-Parameters represented by the numbers \fB$#\fP
-down to \fB$#\fP\-\fIn\fP+1 are unset.
-.I n
-must be a non-negative number less than or equal to \fB$#\fP.
-If
-.I n
-is 0, no parameters are changed.
-If
-.I n
-is not given, it is assumed to be 1.
-If
-.I n
-is greater than \fB$#\fP, the positional parameters are not changed.
-The return status is greater than zero if
-.I n
-is greater than
-.B $#
-or less than zero; otherwise 0.
-.TP
-\fBshopt\fP [\fB\-pqsu\fP] [\fB\-o\fP] [\fIoptname\fP ...]
-Toggle the values of variables controlling optional shell behavior.
-With no options, or with the
-.B \-p
-option, a list of all settable options is displayed, with
-an indication of whether or not each is set.
-The \fB\-p\fP option causes output to be displayed in a form that
-may be reused as input.
-Other options have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-s
-Enable (set) each \fIoptname\fP.
-.TP
-.B \-u
-Disable (unset) each \fIoptname\fP.
-.TP
-.B \-q
-Suppresses normal output (quiet mode); the return status indicates
-whether the \fIoptname\fP is set or unset.
-If multiple \fIoptname\fP arguments are given with
-.BR \-q ,
-the return status is zero if all \fIoptnames\fP are enabled; non-zero
-otherwise.
-.TP
-.B \-o
-Restricts the values of \fIoptname\fP to be those defined for the
-.B \-o
-option to the
-.B set
-builtin.
-.PD
-.PP
-If either
-.B \-s
-or
-.B \-u
-is used with no \fIoptname\fP arguments, the display is limited to
-those options which are set or unset, respectively.
-Unless otherwise noted, the \fBshopt\fP options are disabled (unset)
-by default.
-.PP
-The return status when listing options is zero if all \fIoptnames\fP
-are enabled, non-zero otherwise. When setting or unsetting options,
-the return status is zero unless an \fIoptname\fP is not a valid shell
-option.
-.PP
-The list of \fBshopt\fP options is:
-.if t .sp .5v
-.if n .sp 1v
-.PD 0
-.TP 8
-.B cdable_vars
-If set, an argument to the
-.B cd
-builtin command that
-is not a directory is assumed to be the name of a variable whose
-value is the directory to change to.
-.TP 8
-.B cdspell
-If set, minor errors in the spelling of a directory component in a
-.B cd
-command will be corrected.
-The errors checked for are transposed characters,
-a missing character, and one character too many.
-If a correction is found, the corrected file name is printed,
-and the command proceeds.
-This option is only used by interactive shells.
-.TP 8
-.B checkhash
-If set, \fBbash\fP checks that a command found in the hash
-table exists before trying to execute it. If a hashed command no
-longer exists, a normal path search is performed.
-.TP 8
-.B checkwinsize
-If set, \fBbash\fP checks the window size after each command
-and, if necessary, updates the values of
-.SM
-.B LINES
-and
-.SM
-.BR COLUMNS .
-.TP 8
-.B cmdhist
-If set,
-.B bash
-attempts to save all lines of a multiple-line
-command in the same history entry. This allows
-easy re-editing of multi-line commands.
-.TP 8
-.B dotglob
-If set,
-.B bash
-includes filenames beginning with a `.' in the results of pathname
-expansion.
-.TP 8
-.B execfail
-If set, a non-interactive shell will not exit if
-it cannot execute the file specified as an argument to the
-.B exec
-builtin command. An interactive shell does not exit if
-.B exec
-fails.
-.TP 8
-.B expand_aliases
-If set, aliases are expanded as described above under
-.SM
-.BR ALIASES .
-This option is enabled by default for interactive shells.
-.TP 8
-.B extdebug
-If set, behavior intended for use by debuggers is enabled:
-.RS
-.TP
-.B 1.
-The \fB\-F\fP option to the \fBdeclare\fP builtin displays the source
-file name and line number corresponding to each function name supplied
-as an argument.
-.TP
-.B 2.
-If the command run by the \fBDEBUG\fP trap returns a non-zero value, the
-next command is skipped and not executed.
-.TP
-.B 3.
-If the command run by the \fBDEBUG\fP trap returns a value of 2, and the
-shell is executing in a subroutine (a shell function or a shell script
-executed by the \fB.\fP or \fBsource\fP builtins), a call to
-\fBreturn\fP is simulated.
-.RE
-.TP 8
-.B extglob
-If set, the extended pattern matching features described above under
-\fBPathname Expansion\fP are enabled.
-.TP 8
-.B extquote
-If set, \fB$\fP'\fIstring\fP' and \fB$\fP"\fIstring\fP" quoting is
-performed within \fB${\fP\fIparameter\fP\fB}\fP expansions
-enclosed in double quotes. This option is enabled by default.
-.TP 8
-.B histappend
-If set, the history list is appended to the file named by the value
-of the
-.B HISTFILE
-variable when the shell exits, rather than overwriting the file.
-.TP 8
-.B histreedit
-If set, and
-.B readline
-is being used, a user is given the opportunity to re-edit a
-failed history substitution.
-.TP 8
-.B histverify
-If set, and
-.B readline
-is being used, the results of history substitution are not immediately
-passed to the shell parser. Instead, the resulting line is loaded into
-the \fBreadline\fP editing buffer, allowing further modification.
-.TP 8
-.B hostcomplete
-If set, and
-.B readline
-is being used, \fBbash\fP will attempt to perform hostname completion when a
-word containing a \fB@\fP is being completed (see
-.B Completing
-under
-.SM
-.B READLINE
-above).
-This is enabled by default.
-.TP 8
-.B huponexit
-If set, \fBbash\fP will send
-.SM
-.B SIGHUP
-to all jobs when an interactive login shell exits.
-.TP 8
-.B interactive_comments
-If set, allow a word beginning with
-.B #
-to cause that word and all remaining characters on that
-line to be ignored in an interactive shell (see
-.SM
-.B COMMENTS
-above). This option is enabled by default.
-.TP 8
-.B lithist
-If set, and the
-.B cmdhist
-option is enabled, multi-line commands are saved to the history with
-embedded newlines rather than using semicolon separators where possible.
-.TP 8
-.B login_shell
-The shell sets this option if it is started as a login shell (see
-.SM
-.B "INVOCATION"
-above).
-The value may not be changed.
-.TP 8
-.B mailwarn
-If set, and a file that \fBbash\fP is checking for mail has been
-accessed since the last time it was checked, the message ``The mail in
-\fImailfile\fP has been read'' is displayed.
-.TP 8
-.B no_empty_cmd_completion
-If set, and
-.B readline
-is being used,
-.B bash
-will not attempt to search the \fBPATH\fP for possible completions when
-completion is attempted on an empty line.
-.TP 8
-.B nocaseglob
-If set,
-.B bash
-matches filenames in a case\-insensitive fashion when performing pathname
-expansion (see
-.B Pathname Expansion
-above).
-.TP 8
-.B nullglob
-If set,
-.B bash
-allows patterns which match no
-files (see
-.B Pathname Expansion
-above)
-to expand to a null string, rather than themselves.
-.TP 8
-.B progcomp
-If set, the programmable completion facilities (see
-\fBProgrammable Completion\fP above) are enabled.
-This option is enabled by default.
-.TP 8
-.B promptvars
-If set, prompt strings undergo variable and parameter expansion after
-being expanded as described in
-.SM
-.B PROMPTING
-above. This option is enabled by default.
-.TP 8
-.B restricted_shell
-The shell sets this option if it is started in restricted mode (see
-.SM
-.B "RESTRICTED SHELL"
-below).
-The value may not be changed.
-This is not reset when the startup files are executed, allowing
-the startup files to discover whether or not a shell is restricted.
-.TP 8
-.B shift_verbose
-If set, the
-.B shift
-builtin prints an error message when the shift count exceeds the
-number of positional parameters.
-.TP 8
-.B sourcepath
-If set, the
-\fBsource\fP (\fB.\fP) builtin uses the value of
-.SM
-.B PATH
-to find the directory containing the file supplied as an argument.
-This option is enabled by default.
-.TP 8
-.B xpg_echo
-If set, the \fBecho\fP builtin expands backslash-escape sequences
-by default.
-.RE
-.TP
-\fBsuspend\fP [\fB\-f\fP]
-Suspend the execution of this shell until it receives a
-.SM
-.B SIGCONT
-signal. The
-.B \-f
-option says not to complain if this is
-a login shell; just suspend anyway. The return status is 0 unless
-the shell is a login shell and
-.B \-f
-is not supplied, or if job control is not enabled.
-.TP
-\fBtest\fP \fIexpr\fP
-.PD 0
-.TP
-\fB[\fP \fIexpr\fP \fB]\fP
-Return a status of 0 or 1 depending on
-the evaluation of the conditional expression
-.IR expr .
-Each operator and operand must be a separate argument.
-Expressions are composed of the primaries described above under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" .
-.if t .sp 0.5
-.if n .sp 1
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence.
-.RS
-.PD 0
-.TP
-.B ! \fIexpr\fP
-True if
-.I expr
-is false.
-.TP
-.B ( \fIexpr\fP )
-Returns the value of \fIexpr\fP.
-This may be used to override the normal precedence of operators.
-.TP
-\fIexpr1\fP \-\fBa\fP \fIexpr2\fP
-True if both
-.I expr1
-and
-.I expr2
-are true.
-.TP
-\fIexpr1\fP \-\fBo\fP \fIexpr2\fP
-True if either
-.I expr1
-or
-.I expr2
-is true.
-.PD
-.PP
-\fBtest\fP and \fB[\fP evaluate conditional
-expressions using a set of rules based on the number of arguments.
-.if t .sp 0.5
-.if n .sp 1
-.PD 0
-.TP
-0 arguments
-The expression is false.
-.TP
-1 argument
-The expression is true if and only if the argument is not null.
-.TP
-2 arguments
-If the first argument is \fB!\fP, the expression is true if and
-only if the second argument is null.
-If the first argument is one of the unary conditional operators listed above
-under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" ,
-the expression is true if the unary test is true.
-If the first argument is not a valid unary conditional operator, the expression
-is false.
-.TP
-3 arguments
-If the second argument is one of the binary conditional operators listed above
-under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" ,
-the result of the expression is the result of the binary test using
-the first and third arguments as operands.
-If the first argument is \fB!\fP, the value is the negation of
-the two-argument test using the second and third arguments.
-If the first argument is exactly \fB(\fP and the third argument is
-exactly \fB)\fP, the result is the one-argument test of the second
-argument.
-Otherwise, the expression is false.
-The \fB\-a\fP and \fB\-o\fP operators are considered binary operators
-in this case.
-.TP
-4 arguments
-If the first argument is \fB!\fP, the result is the negation of
-the three-argument expression composed of the remaining arguments.
-Otherwise, the expression is parsed and evaluated according to
-precedence using the rules listed above.
-.TP
-5 or more arguments
-The expression is parsed and evaluated according to precedence
-using the rules listed above.
-.RE
-.PD
-.TP
-.B times
-Print the accumulated user and system times for the shell and
-for processes run from the shell. The return status is 0.
-.TP
-\fBtrap\fP [\fB\-lp\fP] [\fIarg\fP] [\fIsigspec\fP ...]
-The command
-.I arg
-is to be read and executed when the shell receives
-signal(s)
-.IR sigspec .
-If
-.I arg
-is absent or
-.BR \- ,
-all specified signals are
-reset to their original values (the values they had
-upon entrance to the shell).
-If
-.I arg
-is the null string the signal specified by each
-.I sigspec
-is ignored by the shell and by the commands it invokes.
-If
-.I arg
-is not present and
-.B \-p
-has been supplied, then the trap commands associated with each
-.I sigspec
-are displayed.
-If no arguments are supplied or if only
-.B \-p
-is given,
-.B trap
-prints the list of commands associated with each signal number.
-The
-.B \-l
-option causes the shell to print a list of signal names and
-their corresponding numbers.
-Each
-.I sigspec
-is either
-a signal name defined in <\fIsignal.h\fP>, or a signal number.
-If a
-.I sigspec
-is
-.SM
-.B EXIT
-(0) the command
-.I arg
-is executed on exit from the shell.
-If a
-.I sigspec
-is
-.SM
-.BR DEBUG ,
-the command
-.I arg
-is executed before every \fIsimple command\fP, \fIfor\fP command,
-\fIcase\fP command, \fIselect\fP command, every arithmetic \fIfor\fP
-command, and before the first command executes in a shell function (see
-.SM
-.B SHELL GRAMMAR
-above).
-Refer to the description of the \fBextglob\fP option to the
-\fBshopt\fP builtin for details of its effect on the \fBDEBUG\fP trap.
-If a
-.I sigspec
-is
-.SM
-.BR ERR ,
-the command
-.I arg
-is executed whenever a simple command has a non\-zero exit status.
-The
-.SM
-.B ERR
-trap is not executed if the failed
-command is part of the command list immediately following a
-.B while
-or
-.B until
-keyword,
-part of the test in an
-.I if
-statement, part of a
-.B &&
-or
-.B \(bv\(bv
-list, or if the command's return value is
-being inverted via
-.BR ! .
-If a
-.I sigspec
-is
-.SM
-.BR RETURN ,
-the command
-.I arg
-is executed each time a shell function or a script executed with the
-\fB.\fP or \fBsource\fP builtins finishes executing.
-Signals ignored upon entry to the shell cannot be trapped or reset.
-Trapped signals are reset to their original values in a child
-process when it is created.
-The return status is false if any
-.I sigspec
-is invalid; otherwise
-.B trap
-returns true.
-.TP
-\fBtype\fP [\fB\-aftpP\fP] \fIname\fP [\fIname\fP ...]
-With no options,
-indicate how each
-.I name
-would be interpreted if used as a command name.
-If the
-.B \-t
-option is used,
-.B type
-prints a string which is one of
-.IR alias ,
-.IR keyword ,
-.IR function ,
-.IR builtin ,
-or
-.I file
-if
-.I name
-is an alias, shell reserved word, function, builtin, or disk file,
-respectively.
-If the
-.I name
-is not found, then nothing is printed, and an exit status of false
-is returned.
-If the
-.B \-p
-option is used,
-.B type
-either returns the name of the disk file
-that would be executed if
-.I name
-were specified as a command name,
-or nothing if
-.if t \f(CWtype -t name\fP
-.if n ``type -t name''
-would not return
-.IR file .
-The
-.B \-P
-option forces a
-.SM
-.B PATH
-search for each \fIname\fP, even if
-.if t \f(CWtype -t name\fP
-.if n ``type -t name''
-would not return
-.IR file .
-If a command is hashed,
-.B \-p
-and
-.B \-P
-print the hashed value, not necessarily the file that appears
-first in
-.SM
-.BR PATH .
-If the
-.B \-a
-option is used,
-.B type
-prints all of the places that contain
-an executable named
-.IR name .
-This includes aliases and functions,
-if and only if the
-.B \-p
-option is not also used.
-The table of hashed commands is not consulted
-when using
-.BR \-a .
-The
-.B \-f
-option suppresses shell function lookup, as with the \fBcommand\fP builtin.
-.B type
-returns true if any of the arguments are found, false if
-none are found.
-.TP
-\fBulimit\fP [\fB\-SHacdflmnpstuv\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
-set for the given resource. A hard limit cannot be increased once it
-is set; a soft limit may be increased up to the value of the hard limit.
-If neither \fB\-H\fP nor \fB\-S\fP is specified, both the soft and hard
-limits are set.
-The value of
-.I limit
-can be a number in the unit specified for the resource
-or one of the special values
-.BR hard ,
-.BR soft ,
-or
-.BR unlimited ,
-which stand for the current hard limit, the current soft limit, and
-no limit, respectively.
-If
-.I limit
-is omitted, the current value of the soft limit of the resource is
-printed, unless the \fB\-H\fP option is given. When more than one
-resource is specified, the limit name and unit are printed before the value.
-Other options are interpreted as follows:
-.RS
-.PD 0
-.TP
-.B \-a
-All current limits are reported
-.TP
-.B \-c
-The maximum size of core files created
-.TP
-.B \-d
-The maximum size of a process's data segment
-.TP
-.B \-f
-The maximum size of files created by the shell
-.TP
-.B \-l
-The maximum size that may be locked into memory
-.TP
-.B \-m
-The maximum resident set size
-.TP
-.B \-n
-The maximum number of open file descriptors (most systems do not
-allow this value to be set)
-.TP
-.B \-p
-The pipe size in 512-byte blocks (this may not be set)
-.TP
-.B \-s
-The maximum stack size
-.TP
-.B \-t
-The maximum amount of cpu time in seconds
-.TP
-.B \-u
-The maximum number of processes available to a single user
-.TP
-.B \-v
-The maximum amount of virtual memory available to the shell
-.PD
-.PP
-If
-.I limit
-is given, it is the new value of the specified resource (the
-.B \-a
-option is display only).
-If no option is given, then
-.B \-f
-is assumed. Values are in 1024-byte increments, except for
-.BR \-t ,
-which is in seconds,
-.BR \-p ,
-which is in units of 512-byte blocks,
-and
-.B \-n
-and
-.BR \-u ,
-which are unscaled values.
-The return status is 0 unless an invalid option or argument is supplied,
-or an error occurs while setting a new limit.
-.RE
-.TP
-\fBumask\fP [\fB\-p\fP] [\fB\-S\fP] [\fImode\fP]
-The user file-creation mask is set to
-.IR mode .
-If
-.I mode
-begins with a digit, it
-is interpreted as an octal number; otherwise
-it is interpreted as a symbolic mode mask similar
-to that accepted by
-.IR chmod (1).
-If
-.I mode
-is omitted, the current value of the mask is printed.
-The
-.B \-S
-option causes the mask to be printed in symbolic form; the
-default output is an octal number.
-If the
-.B \-p
-option is supplied, and
-.I mode
-is omitted, the output is in a form that may be reused as input.
-The return status is 0 if the mode was successfully changed or if
-no \fImode\fP argument was supplied, and false otherwise.
-.TP
-\fBunalias\fP [\-\fBa\fP] [\fIname\fP ...]
-Remove each \fIname\fP from the list of defined aliases. If
-.B \-a
-is supplied, all alias definitions are removed. The return
-value is true unless a supplied
-.I name
-is not a defined alias.
-.TP
-\fBunset\fP [\-\fBfv\fP] [\fIname\fP ...]
-For each
-.IR name ,
-remove the corresponding variable or function.
-If no options are supplied, or the
-.B \-v
-option is given, each
-.I name
-refers to a shell variable.
-Read-only variables may not be unset.
-If
-.B \-f
-is specifed,
-each
-.I name
-refers to a shell function, and the function definition
-is removed.
-Each unset variable or function is removed from the environment
-passed to subsequent commands.
-If any of
-.SM
-.BR RANDOM ,
-.SM
-.BR SECONDS ,
-.SM
-.BR LINENO ,
-.SM
-.BR HISTCMD ,
-.SM
-.BR FUNCNAME ,
-.SM
-.BR GROUPS ,
-or
-.SM
-.B DIRSTACK
-are unset, they lose their special properties, even if they are
-subsequently reset. The exit status is true unless a
-.I name
-is readonly.
-.TP
-\fBwait\fP [\fIn\fP]
-Wait for the specified process and return its termination
-status.
-.I n
-may be a process
-ID or a job specification; if a job spec is given, all processes
-in that job's pipeline are waited for. If
-.I n
-is not given, all currently active child processes
-are waited for, and the return status is zero. If
-.I n
-specifies a non-existent process or job, the return status is
-127. Otherwise, the return status is the exit status of the last
-process or job waited for.
-.\" bash_builtins
-.if \n(zZ=1 .ig zZ
-.SH "RESTRICTED SHELL"
-.\" rbash.1
-.zY
-.PP
-If
-.B bash
-is started with the name
-.BR rbash ,
-or the
-.B \-r
-option is supplied at invocation,
-the shell becomes restricted.
-A restricted shell is used to
-set up an environment more controlled than the standard shell.
-It behaves identically to
-.B bash
-with the exception that the following are disallowed or not performed:
-.IP \(bu
-changing directories with \fBcd\fP
-.IP \(bu
-setting or unsetting the values of
-.BR SHELL ,
-.BR PATH ,
-.BR ENV ,
-or
-.B BASH_ENV
-.IP \(bu
-specifying command names containing
-.B /
-.IP \(bu
-specifying a file name containing a
-.B /
-as an argument to the
-.B .
-builtin command
-.IP \(bu
-Specifying a filename containing a slash as an argument to the
-.B \-p
-option to the
-.B hash
-builtin command
-.IP \(bu
-importing function definitions from the shell environment at startup
-.IP \(bu
-parsing the value of \fBSHELLOPTS\fP from the shell environment at startup
-.IP \(bu
-redirecting output using the >, >|, <>, >&, &>, and >> redirection operators
-.IP \(bu
-using the
-.B exec
-builtin command to replace the shell with another command
-.IP \(bu
-adding or deleting builtin commands with the
-.B \-f
-and
-.B \-d
-options to the
-.B enable
-builtin command
-.IP \(bu
-Using the \fBenable\fP builtin command to enable disabled shell builtins
-.IP \(bu
-specifying the
-.B \-p
-option to the
-.B command
-builtin command
-.IP \(bu
-turning off restricted mode with
-\fBset +r\fP or \fBset +o restricted\fP.
-.PP
-These restrictions are enforced after any startup files are read.
-.PP
-When a command that is found to be a shell script is executed (see
-.SM
-.B "COMMAND EXECUTION"
-above),
-.B rbash
-turns off any restrictions in the shell spawned to execute the
-script.
-.\" end of rbash.1
-.if \n(zY=1 .ig zY
-.SH "SEE ALSO"
-.PD 0
-.TP
-\fIBash Reference Manual\fP, Brian Fox and Chet Ramey
-.TP
-\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey
-.TP
-\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey
-.TP
-\fIPortable Operating System Interface (POSIX) Part 2: Shell and Utilities\fP, IEEE
-.TP
-\fIsh\fP(1), \fIksh\fP(1), \fIcsh\fP(1)
-.TP
-\fIemacs\fP(1), \fIvi\fP(1)
-.TP
-\fIreadline\fP(3)
-.PD
-.SH FILES
-.PD 0
-.TP
-.FN /bin/bash
-The \fBbash\fP executable
-.TP
-.FN /etc/profile
-The systemwide initialization file, executed for login shells
-.TP
-.FN ~/.bash_profile
-The personal initialization file, executed for login shells
-.TP
-.FN ~/.bashrc
-The individual per-interactive-shell startup file
-.TP
-.FN ~/.bash_logout
-The individual login shell cleanup file, executed when a login shell exits
-.TP
-.FN ~/.inputrc
-Individual \fIreadline\fP initialization file
-.PD
-.SH AUTHORS
-Brian Fox, Free Software Foundation
-.br
-bfox@gnu.org
-.PP
-Chet Ramey, Case Western Reserve University
-.br
-chet@po.CWRU.Edu
-.SH BUG REPORTS
-If you find a bug in
-.B bash,
-you should report it. But first, you should
-make sure that it really is a bug, and that it appears in the latest
-version of
-.BR bash .
-The latest version is always available from
-\fIftp://ftp.gnu.org/pub/bash/\fP.
-.PP
-Once you have determined that a bug actually exists, use the
-.I bashbug
-command to submit a bug report.
-If you have a fix, you are encouraged to mail that as well!
-Suggestions and `philosophical' bug reports may be mailed
-to \fIbug-bash@gnu.org\fP or posted to the Usenet
-newsgroup
-.BR gnu.bash.bug .
-.PP
-ALL bug reports should include:
-.PP
-.PD 0
-.TP 20
-The version number of \fBbash\fR
-.TP
-The hardware and operating system
-.TP
-The compiler used to compile
-.TP
-A description of the bug behaviour
-.TP
-A short script or `recipe' which exercises the bug
-.PD
-.PP
-.I bashbug
-inserts the first three items automatically into the template
-it provides for filing a bug report.
-.PP
-Comments and bug reports concerning
-this manual page should be directed to
-.IR chet@po.CWRU.Edu .
-.SH BUGS
-.PP
-It's too big and too slow.
-.PP
-There are some subtle differences between
-.B bash
-and traditional versions of
-.BR sh ,
-mostly because of the
-.SM
-.B POSIX
-specification.
-.PP
-Aliases are confusing in some uses.
-.PP
-Shell builtin commands and functions are not stoppable/restartable.
-.PP
-Compound commands and command sequences of the form `a ; b ; c'
-are not handled gracefully when process suspension is attempted.
-When a process is stopped, the shell immediately executes the next
-command in the sequence.
-It suffices to place the sequence of commands between
-parentheses to force it into a subshell, which may be stopped as
-a unit.
-.PP
-Commands inside of \fB$(\fP...\fB)\fP command substitution are not
-parsed until substitution is attempted. This will delay error
-reporting until some time after the command is entered.
-.PP
-Array variables may not (yet) be exported.
-.zZ
-.zY
diff --git a/doc/bash.1~ b/doc/bash.1~
deleted file mode 100644
index 1dcf497e..00000000
--- a/doc/bash.1~
+++ /dev/null
@@ -1,8888 +0,0 @@
-\"
-.\" MAN PAGE COMMENTS to
-.\"
-.\" Chet Ramey
-.\" Information Network Services
-.\" Case Western Reserve University
-.\" chet@po.cwru.edu
-.\"
-.\" Last Change: Thu May 11 14:25:48 EDT 2006
-.\"
-.\" bash_builtins, strip all but Built-Ins section
-.if \n(zZ=1 .ig zZ
-.if \n(zY=1 .ig zY
-.TH BASH 1 "2006 May 11" "GNU Bash-3.2"
-.\"
-.\" There's some problem with having a `@'
-.\" in a tagged paragraph with the BSD man macros.
-.\" It has to do with `@' appearing in the }1 macro.
-.\" This is a problem on 4.3 BSD and Ultrix, but Sun
-.\" appears to have fixed it.
-.\" If you're seeing the characters
-.\" `@u-3p' appearing before the lines reading
-.\" `possible-hostname-completions
-.\" and `complete-hostname' down in READLINE,
-.\" then uncomment this redefinition.
-.\"
-.de }1
-.ds ]X \&\\*(]B\\
-.nr )E 0
-.if !"\\$1"" .nr )I \\$1n
-.}f
-.ll \\n(LLu
-.in \\n()Ru+\\n(INu+\\n()Iu
-.ti \\n(INu
-.ie !\\n()Iu+\\n()Ru-\w\\*(]Xu-3p \{\\*(]X
-.br\}
-.el \\*(]X\h|\\n()Iu+\\n()Ru\c
-.}f
-..
-.\"
-.\" File Name macro. This used to be `.PN', for Path Name,
-.\" but Sun doesn't seem to like that very much.
-.\"
-.de FN
-\fI\|\\$1\|\fP
-..
-.SH NAME
-bash \- GNU Bourne-Again SHell
-.SH SYNOPSIS
-.B bash
-[options]
-[file]
-.SH COPYRIGHT
-.if n Bash is Copyright (C) 1989-2005 by the Free Software Foundation, Inc.
-.if t Bash is Copyright \(co 1989-2005 by the Free Software Foundation, Inc.
-.SH DESCRIPTION
-.B Bash
-is an \fBsh\fR-compatible command language interpreter that
-executes commands read from the standard input or from a file.
-.B Bash
-also incorporates useful features from the \fIKorn\fP and \fIC\fP
-shells (\fBksh\fP and \fBcsh\fP).
-.PP
-.B Bash
-is intended to be a conformant implementation of the
-Shell and Utilities portion of the IEEE POSIX specification
-(IEEE Standard 1003.1).
-.B Bash
-can be configured to be POSIX-conformant by default.
-.SH OPTIONS
-In addition to the single-character shell options documented in the
-description of the \fBset\fR builtin command, \fBbash\fR
-interprets the following options when it is invoked:
-.PP
-.PD 0
-.TP 10
-.BI \-c "\| string\^"
-If the
-.B \-c
-option is present, then commands are read from
-.IR string .
-If there are arguments after the
-.IR string ,
-they are assigned to the positional parameters, starting with
-.BR $0 .
-.TP
-.B \-i
-If the
-.B \-i
-option is present, the shell is
-.IR interactive .
-.TP
-.B \-l
-Make
-.B bash
-act as if it had been invoked as a login shell (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-r
-If the
-.B \-r
-option is present, the shell becomes
-.I restricted
-(see
-.SM
-.B "RESTRICTED SHELL"
-below).
-.TP
-.B \-s
-If the
-.B \-s
-option is present, or if no arguments remain after option
-processing, then commands are read from the standard input.
-This option allows the positional parameters to be set
-when invoking an interactive shell.
-.TP
-.B \-D
-A list of all double-quoted strings preceded by \fB$\fP
-is printed on the standard output.
-These are the strings that
-are subject to language translation when the current locale
-is not \fBC\fP or \fBPOSIX\fP.
-This implies the \fB\-n\fP option; no commands will be executed.
-.TP
-.B [\-+]O [\fIshopt_option\fP]
-\fIshopt_option\fP is one of the shell options accepted by the
-\fBshopt\fP builtin (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-If \fIshopt_option\fP is present, \fB\-O\fP sets the value of that option;
-\fB+O\fP unsets it.
-If \fIshopt_option\fP is not supplied, the names and values of the shell
-options accepted by \fBshopt\fP are printed on the standard output.
-If the invocation option is \fB+O\fP, the output is displayed in a format
-that may be reused as input.
-.TP
-.B \-\-
-A
-.B \-\-
-signals the end of options and disables further option processing.
-Any arguments after the
-.B \-\-
-are treated as filenames and arguments. An argument of
-.B \-
-is equivalent to \fB\-\-\fP.
-.PD
-.PP
-.B Bash
-also interprets a number of multi-character options.
-These options must appear on the command line before the
-single-character options to be recognized.
-.PP
-.PD 0
-.TP
-.B \-\-debugger
-Arrange for the debugger profile to be executed before the shell
-starts.
-Turns on extended debugging mode (see the description of the
-.B extdebug
-option to the
-.B shopt
-builtin below)
-and shell function tracing (see the description of the
-\fB\-o functrace\fP option to the
-.B set
-builtin below).
-.TP
-.B \-\-dump\-po\-strings
-Equivalent to \fB\-D\fP, but the output is in the GNU \fIgettext\fP
-\fBpo\fP (portable object) file format.
-.TP
-.B \-\-dump\-strings
-Equivalent to \fB\-D\fP.
-.TP
-.B \-\-help
-Display a usage message on standard output and exit successfully.
-.TP
-\fB\-\-init\-file\fP \fIfile\fP
-.PD 0
-.TP
-\fB\-\-rcfile\fP \fIfile\fP
-.PD
-Execute commands from
-.I file
-instead of the standard personal initialization file
-.I ~/.bashrc
-if the shell is interactive (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-\-login
-Equivalent to \fB\-l\fP.
-.TP
-.B \-\-noediting
-Do not use the GNU
-.B readline
-library to read command lines when the shell is interactive.
-.TP
-.B \-\-noprofile
-Do not read either the system-wide startup file
-.FN /etc/profile
-or any of the personal initialization files
-.IR ~/.bash_profile ,
-.IR ~/.bash_login ,
-or
-.IR ~/.profile .
-By default,
-.B bash
-reads these files when it is invoked as a login shell (see
-.SM
-.B INVOCATION
-below).
-.TP
-.B \-\-norc
-Do not read and execute the personal initialization file
-.I ~/.bashrc
-if the shell is interactive.
-This option is on by default if the shell is invoked as
-.BR sh .
-.TP
-.B \-\-posix
-Change the behavior of \fBbash\fP where the default operation differs
-from the POSIX standard to match the standard (\fIposix mode\fP).
-.TP
-.B \-\-restricted
-The shell becomes restricted (see
-.SM
-.B "RESTRICTED SHELL"
-below).
-.TP
-.B \-\-verbose
-Equivalent to \fB\-v\fP.
-.TP
-.B \-\-version
-Show version information for this instance of
-.B bash
-on the standard output and exit successfully.
-.PD
-.SH ARGUMENTS
-If arguments remain after option processing, and neither the
-.B \-c
-nor the
-.B \-s
-option has been supplied, the first argument is assumed to
-be the name of a file containing shell commands.
-If
-.B bash
-is invoked in this fashion,
-.B $0
-is set to the name of the file, and the positional parameters
-are set to the remaining arguments.
-.B Bash
-reads and executes commands from this file, then exits.
-\fBBash\fP's exit status is the exit status of the last command
-executed in the script.
-If no commands are executed, the exit status is 0.
-An attempt is first made to open the file in the current directory, and,
-if no file is found, then the shell searches the directories in
-.SM
-.B PATH
-for the script.
-.SH INVOCATION
-A \fIlogin shell\fP is one whose first character of argument zero is a
-.BR \- ,
-or one started with the
-.B \-\-login
-option.
-.PP
-An \fIinteractive\fP shell is one started without non-option arguments
-and without the
-.B \-c
-option
-whose standard input and error are
-both connected to terminals (as determined by
-.IR isatty (3)),
-or one started with the
-.B \-i
-option.
-.SM
-.B PS1
-is set and
-.B $\-
-includes
-.B i
-if
-.B bash
-is interactive,
-allowing a shell script or a startup file to test this state.
-.PP
-The following paragraphs describe how
-.B bash
-executes its startup files.
-If any of the files exist but cannot be read,
-.B bash
-reports an error.
-Tildes are expanded in file names as described below under
-.B "Tilde Expansion"
-in the
-.SM
-.B EXPANSION
-section.
-.PP
-When
-.B bash
-is invoked as an interactive login shell, or as a non-interactive shell
-with the \fB\-\-login\fP option, it first reads and
-executes commands from the file \fI/etc/profile\fP, if that
-file exists.
-After reading that file, it looks for \fI~/.bash_profile\fP,
-\fI~/.bash_login\fP, and \fI~/.profile\fP, in that order, and reads
-and executes commands from the first one that exists and is readable.
-The
-.B \-\-noprofile
-option may be used when the shell is started to inhibit this behavior.
-.PP
-When a login shell exits,
-.B bash
-reads and executes commands from the file \fI~/.bash_logout\fP, if it
-exists.
-.PP
-When an interactive shell that is not a login shell is started,
-.B bash
-reads and executes commands from \fI~/.bashrc\fP, if that file exists.
-This may be inhibited by using the
-.B \-\-norc
-option.
-The \fB\-\-rcfile\fP \fIfile\fP option will force
-.B bash
-to read and execute commands from \fIfile\fP instead of \fI~/.bashrc\fP.
-.PP
-When
-.B bash
-is started non-interactively, to run a shell script, for example, it
-looks for the variable
-.SM
-.B BASH_ENV
-in the environment, expands its value if it appears there, and uses the
-expanded value as the name of a file to read and execute.
-.B Bash
-behaves as if the following command were executed:
-.sp .5
-.RS
-.if t \f(CWif [ \-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi\fP
-.if n if [ \-n "$BASH_ENV" ]; then . "$BASH_ENV"; fi
-.RE
-.sp .5
-but the value of the
-.SM
-.B PATH
-variable is not used to search for the file name.
-.PP
-If
-.B bash
-is invoked with the name
-.BR sh ,
-it tries to mimic the startup behavior of historical versions of
-.B sh
-as closely as possible,
-while conforming to the POSIX standard as well.
-When invoked as an interactive login shell, or a non-interactive
-shell with the \fB\-\-login\fP option, it first attempts to
-read and execute commands from
-.I /etc/profile
-and
-.IR ~/.profile ,
-in that order.
-The
-.B \-\-noprofile
-option may be used to inhibit this behavior.
-When invoked as an interactive shell with the name
-.BR sh ,
-.B bash
-looks for the variable
-.SM
-.BR ENV ,
-expands its value if it is defined, and uses the
-expanded value as the name of a file to read and execute.
-Since a shell invoked as
-.B sh
-does not attempt to read and execute commands from any other startup
-files, the
-.B \-\-rcfile
-option has no effect.
-A non-interactive shell invoked with the name
-.B sh
-does not attempt to read any other startup files.
-When invoked as
-.BR sh ,
-.B bash
-enters
-.I posix
-mode after the startup files are read.
-.PP
-When
-.B bash
-is started in
-.I posix
-mode, as with the
-.B \-\-posix
-command line option, it follows the POSIX standard for startup files.
-In this mode, interactive shells expand the
-.SM
-.B ENV
-variable and commands are read and executed from the file
-whose name is the expanded value.
-No other startup files are read.
-.PP
-.B Bash
-attempts to determine when it is being run by the remote shell
-daemon, usually \fIrshd\fP.
-If
-.B bash
-determines it is being run by \fIrshd\fP, it reads and executes
-commands from \fI~/.bashrc\fP, if that file exists and is readable.
-It will not do this if invoked as \fBsh\fP.
-The
-.B \-\-norc
-option may be used to inhibit this behavior, and the
-.B \-\-rcfile
-option may be used to force another file to be read, but
-\fIrshd\fP does not generally invoke the shell with those options
-or allow them to be specified.
-.PP
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the \fB\-p\fP option is not supplied, no startup
-files are read, shell functions are not inherited from the environment, the
-.SM
-.B SHELLOPTS
-variable, if it appears in the environment, is ignored,
-and the effective user id is set to the real user id.
-If the \fB\-p\fP option is supplied at invocation, the startup behavior is
-the same, but the effective user id is not reset.
-.SH DEFINITIONS
-.PP
-The following definitions are used throughout the rest of this
-document.
-.PD 0
-.TP
-.B blank
-A space or tab.
-.TP
-.B word
-A sequence of characters considered as a single unit by the shell.
-Also known as a
-.BR token .
-.TP
-.B name
-A
-.I word
-consisting only of alphanumeric characters and underscores, and
-beginning with an alphabetic character or an underscore. Also
-referred to as an
-.BR identifier .
-.TP
-.B metacharacter
-A character that, when unquoted, separates words. One of the following:
-.br
-.RS
-.PP
-.if t \fB| & ; ( ) < > space tab\fP
-.if n \fB| & ; ( ) < > space tab\fP
-.RE
-.PP
-.TP
-.B control operator
-A \fItoken\fP that performs a control function. It is one of the following
-symbols:
-.RS
-.PP
-.if t \fB\(bv\(bv & && ; ;; ( ) | <newline>\fP
-.if n \fB|| & && ; ;; ( ) | <newline>\fP
-.RE
-.PD
-.SH "RESERVED WORDS"
-\fIReserved words\fP are words that have a special meaning to the shell.
-The following words are recognized as reserved when unquoted and either
-the first word of a simple command (see
-.SM
-.B SHELL GRAMMAR
-below) or the third word of a
-.B case
-or
-.B for
-command:
-.if t .RS
-.PP
-.B
-.if n ! case do done elif else esac fi for function if in select then until while { } time [[ ]]
-.if t ! case do done elif else esac fi for function if in select then until while { } time [[ ]]
-.if t .RE
-.SH "SHELL GRAMMAR"
-.SS Simple Commands
-.PP
-A \fIsimple command\fP is a sequence of optional variable assignments
-followed by \fBblank\fP-separated words and redirections, and
-terminated by a \fIcontrol operator\fP. The first word
-specifies the command to be executed, and is passed as argument zero.
-The remaining words are passed as arguments to the invoked command.
-.PP
-The return value of a \fIsimple command\fP is its exit status, or
-128+\fIn\^\fP if the command is terminated by signal
-.IR n .
-.SS Pipelines
-.PP
-A \fIpipeline\fP is a sequence of one or more commands separated by
-the character
-.BR | .
-The format for a pipeline is:
-.RS
-.PP
-[\fBtime\fP [\fB\-p\fP]] [ ! ] \fIcommand\fP [ \fB|\fP \fIcommand2\fP ... ]
-.RE
-.PP
-The standard output of
-.I command
-is connected via a pipe to the standard input of
-.IR command2 .
-This connection is performed before any redirections specified by the
-command (see
-.SM
-.B REDIRECTION
-below).
-.PP
-The return status of a pipeline is the exit status of the last
-command, unless the \fBpipefail\fP option is enabled.
-If \fBpipefail\fP is enabled, the pipeline's return status is the
-value of the last (rightmost) command to exit with a non-zero status,
-or zero if all commands exit successfully.
-If the reserved word
-.B !
-precedes a pipeline, the exit status of that pipeline is the logical
-negation of the exit status as described above.
-The shell waits for all commands in the pipeline to
-terminate before returning a value.
-.PP
-If the
-.B time
-reserved word precedes a pipeline, the elapsed as well as user and
-system time consumed by its execution are reported when the pipeline
-terminates.
-The \fB\-p\fP option changes the output format to that specified by POSIX.
-The
-.SM
-.B TIMEFORMAT
-variable may be set to a format string that specifies how the timing
-information should be displayed; see the description of
-.SM
-.B TIMEFORMAT
-under
-.B "Shell Variables"
-below.
-.PP
-Each command in a pipeline is executed as a separate process (i.e., in a
-subshell).
-.SS Lists
-.PP
-A \fIlist\fP is a sequence of one or more pipelines separated by one
-of the operators
-.BR ; ,
-.BR & ,
-.BR && ,
-or
-.BR \(bv\(bv ,
-and optionally terminated by one of
-.BR ; ,
-.BR & ,
-or
-.BR <newline> .
-.PP
-Of these list operators,
-.B &&
-and
-.B \(bv\(bv
-have equal precedence, followed by
-.B ;
-and
-.BR &,
-which have equal precedence.
-.PP
-A sequence of one or more newlines may appear in a \fIlist\fP instead
-of a semicolon to delimit commands.
-.PP
-If a command is terminated by the control operator
-.BR & ,
-the shell executes the command in the \fIbackground\fP
-in a subshell. The shell does not wait for the command to
-finish, and the return status is 0. Commands separated by a
-.B ;
-are executed sequentially; the shell waits for each
-command to terminate in turn. The return status is the
-exit status of the last command executed.
-.PP
-The control operators
-.B &&
-and
-.B \(bv\(bv
-denote AND lists and OR lists, respectively.
-An AND list has the form
-.RS
-.PP
-\fIcommand1\fP \fB&&\fP \fIcommand2\fP
-.RE
-.PP
-.I command2
-is executed if, and only if,
-.I command1
-returns an exit status of zero.
-.PP
-An OR list has the form
-.RS
-.PP
-\fIcommand1\fP \fB\(bv\(bv\fP \fIcommand2\fP
-.PP
-.RE
-.PP
-.I command2
-is executed if and only if
-.I command1
-returns a non-zero exit status. The return status of
-AND and OR lists is the exit status of the last command
-executed in the list.
-.SS Compound Commands
-.PP
-A \fIcompound command\fP is one of the following:
-.TP
-(\fIlist\fP)
-\fIlist\fP is executed in a subshell environment (see
-.SM
-\fBCOMMAND EXECUTION ENVIRONMENT\fP
-below).
-Variable assignments and builtin
-commands that affect the shell's environment do not remain in effect
-after the command completes. The return status is the exit status of
-\fIlist\fP.
-.TP
-{ \fIlist\fP; }
-\fIlist\fP is simply executed in the current shell environment.
-\fIlist\fP must be terminated with a newline or semicolon.
-This is known as a \fIgroup command\fP.
-The return status is the exit status of
-\fIlist\fP.
-Note that unlike the metacharacters \fB(\fP and \fB)\fP, \fB{\fP and
-\fB}\fP are \fIreserved words\fP and must occur where a reserved
-word is permitted to be recognized. Since they do not cause a word
-break, they must be separated from \fIlist\fP by whitespace.
-.TP
-((\fIexpression\fP))
-The \fIexpression\fP is evaluated according to the rules described
-below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-If the value of the expression is non-zero, the return status is 0;
-otherwise the return status is 1. This is exactly equivalent to
-\fBlet "\fIexpression\fP"\fR.
-.TP
-\fB[[\fP \fIexpression\fP \fB]]\fP
-Return a status of 0 or 1 depending on the evaluation of
-the conditional expression \fIexpression\fP.
-Expressions are composed of the primaries described below under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" .
-Word splitting and pathname expansion are not performed on the words
-between the \fB[[\fP and \fB]]\fP; tilde expansion, parameter and
-variable expansion, arithmetic expansion, command substitution, process
-substitution, and quote removal are performed.
-Conditional operators such as \fB\-f\fP must be unquoted to be recognized
-as primaries.
-.if t .sp 0.5
-.if n .sp 1
-When the \fB==\fP and \fB!=\fP operators are used, the string to the
-right of the operator is considered a pattern and matched according
-to the rules described below under \fBPattern Matching\fP.
-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 (\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
-.if n .sp 1
-An additional binary operator, \fB=~\fP, is available, with the same
-precedence as \fB==\fP and \fB!=\fP.
-When it is used, the string to the right of the operator is considered
-an extended regular expression and matched accordingly (as in \fIregex\fP(3)).
-The return value is 0 if the string matches
-the pattern, and 1 otherwise.
-If the regular expression is syntactically incorrect, the conditional
-expression's return value is 2.
-If the shell option
-.B nocasematch
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-Substrings matched by parenthesized subexpressions within the regular
-expression are saved in the array variable \fBBASH_REMATCH\fP.
-The element of \fBBASH_REMATCH\fP with index 0 is the portion of the string
-matching the entire regular expression.
-The element of \fBBASH_REMATCH\fP with index \fIn\fP is the portion of the
-string matching the \fIn\fPth parenthesized subexpression.
-.if t .sp 0.5
-.if n .sp 1
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence:
-.if t .sp 0.5
-.if n .sp 1
-.RS
-.PD 0
-.TP
-.B ( \fIexpression\fP )
-Returns the value of \fIexpression\fP.
-This may be used to override the normal precedence of operators.
-.TP
-.B ! \fIexpression\fP
-True if
-.I expression
-is false.
-.TP
-\fIexpression1\fP \fB&&\fP \fIexpression2\fP
-True if both
-.I expression1
-and
-.I expression2
-are true.
-.TP
-.if t \fIexpression1\fP \fB\(bv\(bv\fP \fIexpression2\fP
-.if n \fIexpression1\fP \fB||\fP \fIexpression2\fP
-True if either
-.I expression1
-or
-.I expression2
-is true.
-.PD
-.LP
-The \fB&&\fP and
-.if t \fB\(bv\(bv\fP
-.if n \fB||\fP
-operators do not evaluate \fIexpression2\fP if the value of
-\fIexpression1\fP is sufficient to determine the return value of
-the entire conditional expression.
-.RE
-.TP
-\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ] ; \fBdo\fP \fIlist\fP ; \fBdone\fP
-The list of words following \fBin\fP is expanded, generating a list
-of items.
-The variable \fIname\fP is set to each element of this list
-in turn, and \fIlist\fP is executed each time.
-If the \fBin\fP \fIword\fP is omitted, the \fBfor\fP command executes
-\fIlist\fP once for each positional parameter that is set (see
-.SM
-.B PARAMETERS
-below).
-The return status is the exit status of the last command that executes.
-If the expansion of the items following \fBin\fP results in an empty
-list, no commands are executed, and the return status is 0.
-.TP
-\fBfor\fP (( \fIexpr1\fP ; \fIexpr2\fP ; \fIexpr3\fP )) ; \fBdo\fP \fIlist\fP ; \fBdone\fP
-First, the arithmetic expression \fIexpr1\fP is evaluated according
-to the rules described below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-The arithmetic expression \fIexpr2\fP is then evaluated repeatedly
-until it evaluates to zero.
-Each time \fIexpr2\fP evaluates to a non-zero value, \fIlist\fP is
-executed and the arithmetic expression \fIexpr3\fP is evaluated.
-If any expression is omitted, it behaves as if it evaluates to 1.
-The return value is the exit status of the last command in \fIlist\fP
-that is executed, or false if any of the expressions is invalid.
-.TP
-\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ] ; \fBdo\fP \fIlist\fP ; \fBdone\fP
-The list of words following \fBin\fP is expanded, generating a list
-of items. The set of expanded words is printed on the standard
-error, each preceded by a number. If the \fBin\fP
-\fIword\fP is omitted, the positional parameters are printed (see
-.SM
-.B PARAMETERS
-below). The
-.B PS3
-prompt is then displayed and a line read from the standard input.
-If the line consists of a number corresponding to one of
-the displayed words, then the value of
-.I name
-is set to that word. If the line is empty, the words and prompt
-are displayed again. If EOF is read, the command completes. Any
-other value read causes
-.I name
-to be set to null. The line read is saved in the variable
-.BR REPLY .
-The
-.I list
-is executed after each selection until a
-.B break
-command is executed.
-The exit status of
-.B select
-is the exit status of the last command executed in
-.IR list ,
-or zero if no commands were executed.
-.TP
-\fBcase\fP \fIword\fP \fBin\fP [ [(] \fIpattern\fP [ \fB|\fP \fIpattern\fP ] \
-... ) \fIlist\fP ;; ] ... \fBesac\fP
-A \fBcase\fP command first expands \fIword\fP, and tries to match
-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 substitution,
-command substitution, process substitution and quote removal.
-Each \fIpattern\fP examined is expanded using tilde
-expansion, parameter and variable expansion, arithmetic substitution,
-command substitution, and process substitution.
-If the shell option
-.B nocasematch
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-When a match is found, the
-corresponding \fIlist\fP is executed. After the first match, no
-subsequent matches are attempted. The exit status is zero if no
-pattern matches. Otherwise, it is the exit status of the
-last command executed in \fIlist\fP.
-.TP
-\fBif\fP \fIlist\fP; \fBthen\fP \fIlist;\fP \
-[ \fBelif\fP \fIlist\fP; \fBthen\fP \fIlist\fP; ] ... \
-[ \fBelse\fP \fIlist\fP; ] \fBfi\fP
-The
-.B if
-.I list
-is executed. If its exit status is zero, the
-\fBthen\fP \fIlist\fP is executed. Otherwise, each \fBelif\fP
-\fIlist\fP is executed in turn, and if its exit status is zero,
-the corresponding \fBthen\fP \fIlist\fP is executed and the
-command completes. Otherwise, the \fBelse\fP \fIlist\fP is
-executed, if present. The exit status is the exit status of the
-last command executed, or zero if no condition tested true.
-.TP
-\fBwhile\fP \fIlist\fP; \fBdo\fP \fIlist\fP; \fBdone\fP
-.PD 0
-.TP
-\fBuntil\fP \fIlist\fP; \fBdo\fP \fIlist\fP; \fBdone\fP
-.PD
-The \fBwhile\fP command continuously executes the \fBdo\fP
-\fIlist\fP as long as the last command in \fIlist\fP returns
-an exit status of zero. The \fBuntil\fP command is identical
-to the \fBwhile\fP command, except that the test is negated;
-the
-.B do
-.I list
-is executed as long as the last command in
-.I list
-returns a non-zero exit status.
-The exit status of the \fBwhile\fP and \fBuntil\fP commands
-is the exit status
-of the last \fBdo\fP \fIlist\fP command executed, or zero if
-none was executed.
-.SS Shell Function Definitions
-.PP
-A shell function is an object that is called like a simple command and
-executes a compound command with a new set of positional parameters.
-Shell functions are declared as follows:
-.TP
-[ \fBfunction\fP ] \fIname\fP () \fIcompound\-command\fP [\fIredirection\fP]
-This defines a function named \fIname\fP.
-The reserved word \fBfunction\fP is optional.
-If the \fBfunction\fP reserved word is supplied, the parentheses are optional.
-The \fIbody\fP of the function is the compound command
-.I compound\-command
-(see \fBCompound Commands\fP above).
-That command is usually a \fIlist\fP of commands between { and }, but
-may be any command listed under \fBCompound Commands\fP above.
-\fIcompound\-command\fP is executed whenever \fIname\fP is specified as the
-name of a simple command.
-Any redirections (see
-.SM
-.B REDIRECTION
-below) specified when a function is defined are performed
-when the function is executed.
-The exit status of a function definition is zero unless a syntax error
-occurs or a readonly function with the same name already exists.
-When executed, the exit status of a function is the exit status of the
-last command executed in the body. (See
-.SM
-.B FUNCTIONS
-below.)
-.SH COMMENTS
-In a non-interactive shell, or an interactive shell in which the
-.B interactive_comments
-option to the
-.B shopt
-builtin is enabled (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), a word beginning with
-.B #
-causes that word and all remaining characters on that line to
-be ignored. An interactive shell without the
-.B interactive_comments
-option enabled does not allow comments. The
-.B interactive_comments
-option is on by default in interactive shells.
-.SH QUOTING
-\fIQuoting\fP is used to remove the special meaning of certain
-characters or words to the shell. Quoting can be used to
-disable special treatment for special characters, to prevent
-reserved words from being recognized as such, and to prevent
-parameter expansion.
-.PP
-Each of the \fImetacharacters\fP listed above under
-.SM
-.B DEFINITIONS
-has special meaning to the shell and must be quoted if it is to
-represent itself.
-.PP
-When the command history expansion facilities are being used
-(see
-.SM
-.B HISTORY EXPANSION
-below), the
-\fIhistory expansion\fP character, usually \fB!\fP, must be quoted
-to prevent history expansion.
-.PP
-There are three quoting mechanisms: the
-.IR "escape character" ,
-single quotes, and double quotes.
-.PP
-A non-quoted backslash (\fB\e\fP) is the
-.IR "escape character" .
-It preserves the literal value of the next character that follows,
-with the exception of <newline>. If a \fB\e\fP<newline> pair
-appears, and the backslash is not itself quoted, the \fB\e\fP<newline>
-is treated as a line continuation (that is, it is removed from the
-input stream and effectively ignored).
-.PP
-Enclosing characters in single quotes preserves the literal value
-of each character within the quotes. A single quote may not occur
-between single quotes, even when preceded by a backslash.
-.PP
-Enclosing characters in double quotes preserves the literal value
-of all characters within the quotes, with the exception of
-.BR $ ,
-.BR ` ,
-.BR \e ,
-and, when history expansion is enabled,
-.BR ! .
-The characters
-.B $
-and
-.B `
-retain their special meaning within double quotes. The backslash
-retains its special meaning only when followed by one of the following
-characters:
-.BR $ ,
-.BR ` ,
-\^\fB"\fP\^,
-.BR \e ,
-or
-.BR <newline> .
-A double quote may be quoted within double quotes by preceding it with
-a backslash.
-If enabled, history expansion will be performed unless an
-.B !
-appearing in double quotes is escaped using a backslash.
-The backslash preceding the
-.B !
-is not removed.
-.PP
-The special parameters
-.B *
-and
-.B @
-have special meaning when in double
-quotes (see
-.SM
-.B PARAMETERS
-below).
-.PP
-Words of the form \fB$\fP\(aq\fIstring\fP\(aq are treated specially. The
-word expands to \fIstring\fP, with backslash-escaped characters replaced
-as specified by the ANSI C standard. Backslash escape sequences, if
-present, are decoded as follows:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ee
-an escape character
-.TP
-.B \ef
-form feed
-.TP
-.B \en
-new line
-.TP
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP
-.B \ev
-vertical tab
-.TP
-.B \e\e
-backslash
-.TP
-.B \e\(aq
-single quote
-.TP
-.B \e\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(one to three digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.TP
-.B \ec\fIx\fP
-a control-\fIx\fP character
-.PD
-.RE
-.LP
-The expanded result is single-quoted, as if the dollar sign had
-not been present.
-.PP
-A double-quoted string preceded by a dollar sign (\fB$\fP) will cause
-the string to be translated according to the current locale.
-If the current locale is \fBC\fP or \fBPOSIX\fP, the dollar sign
-is ignored.
-If the string is translated and replaced, the replacement is
-double-quoted.
-.SH PARAMETERS
-A
-.I parameter
-is an entity that stores values.
-It can be a
-.IR name ,
-a number, or one of the special characters listed below under
-.BR "Special Parameters" .
-A
-.I variable
-is a parameter denoted by a
-.IR name .
-A variable has a \fIvalue\fP and zero or more \fIattributes\fP.
-Attributes are assigned using the
-.B declare
-builtin command (see
-.B declare
-below in
-.SM
-.BR "SHELL BUILTIN COMMANDS" ).
-.PP
-A parameter is set if it has been assigned a value. The null string is
-a valid value. Once a variable is set, it may be unset only by using
-the
-.B unset
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.PP
-A
-.I variable
-may be assigned to by a statement of the form
-.RS
-.PP
-\fIname\fP=[\fIvalue\fP]
-.RE
-.PP
-If
-.I value
-is not given, the variable is assigned the null string. All
-.I values
-undergo tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote
-removal (see
-.SM
-.B EXPANSION
-below). If the variable has its
-.B integer
-attribute set, then
-.I value
-is evaluated as an arithmetic expression even if the $((...)) expansion is
-not used (see
-.B "Arithmetic Expansion"
-below).
-Word splitting is not performed, with the exception
-of \fB"$@"\fP as explained below under
-.BR "Special Parameters" .
-Pathname expansion is not performed.
-Assignment statements may also appear as arguments to the
-.BR alias ,
-.BR declare ,
-.BR typeset ,
-.BR export ,
-.BR readonly ,
-and
-.B local
-builtin commands.
-.PP
-In the context where an assignment statement is assigning a value
-to a shell variable or array index, the += operator can be used to
-append to or add to the variable's previous value.
-When += is applied to a variable for which the integer attribute has been
-set, \fIvalue\fP is evaluated as an arithmetic expression and added to the
-variable's current value, which is also evaluated.
-When += is applied to an array variable using compound assignment (see
-.B Arrays
-below), the
-variable's value is not unset (as it is when using =), and new values are
-appended to the array beginning at one greater than the array's maximum index.
-When applied to a string-valued variable, \fIvalue\fP is expanded and
-appended to the variable's value.
-.SS Positional Parameters
-.PP
-A
-.I positional parameter
-is a parameter denoted by one or more
-digits, other than the single digit 0. Positional parameters are
-assigned from the shell's arguments when it is invoked,
-and may be reassigned using the
-.B set
-builtin command. Positional parameters may not be assigned to
-with assignment statements. The positional parameters are
-temporarily replaced when a shell function is executed (see
-.SM
-.B FUNCTIONS
-below).
-.PP
-When a positional parameter consisting of more than a single
-digit is expanded, it must be enclosed in braces (see
-.SM
-.B EXPANSION
-below).
-.SS Special Parameters
-.PP
-The shell treats several parameters specially. These parameters may
-only be referenced; assignment to them is not allowed.
-.PD 0
-.TP
-.B *
-Expands to the positional parameters, starting from one. When the
-expansion occurs within double quotes, it expands to a single word
-with the value of each parameter separated by the first character
-of the
-.SM
-.B IFS
-special variable. That is, "\fB$*\fP" is equivalent
-to "\fB$1\fP\fIc\fP\fB$2\fP\fIc\fP\fB...\fP", where
-.I c
-is the first character of the value of the
-.SM
-.B IFS
-variable. If
-.SM
-.B IFS
-is unset, the parameters are separated by spaces.
-If
-.SM
-.B IFS
-is null, the parameters are joined without intervening separators.
-.TP
-.B @
-Expands to the positional parameters, starting from one. When the
-expansion occurs within double quotes, each parameter expands to a
-separate word. That is, "\fB$@\fP" is equivalent to
-"\fB$1\fP" "\fB$2\fP" ...
-If the double-quoted expansion occurs within a word, the expansion of
-the first parameter is joined with the beginning part of the original
-word, and the expansion of the last parameter is joined with the last
-part of the original word.
-When there are no positional parameters, "\fB$@\fP" and
-.B $@
-expand to nothing (i.e., they are removed).
-.TP
-.B #
-Expands to the number of positional parameters in decimal.
-.TP
-.B ?
-Expands to the status of the most recently executed foreground
-pipeline.
-.TP
-.B \-
-Expands to the current option flags as specified upon invocation,
-by the
-.B set
-builtin command, or those set by the shell itself
-(such as the
-.B \-i
-option).
-.TP
-.B $
-Expands to the process ID of the shell. In a () subshell, it
-expands to the process ID of the current shell, not the
-subshell.
-.TP
-.B !
-Expands to the process ID of the most recently executed background
-(asynchronous) command.
-.TP
-.B 0
-Expands to the name of the shell or shell script. This is set at
-shell initialization. If
-.B bash
-is invoked with a file of commands,
-.B $0
-is set to the name of that file. If
-.B bash
-is started with the
-.B \-c
-option, then
-.B $0
-is set to the first argument after the string to be
-executed, if one is present. Otherwise, it is set
-to the file name used to invoke
-.BR bash ,
-as given by argument zero.
-.TP
-.B _
-At shell startup, set to the absolute pathname used to invoke the
-shell or shell script being executed as passed in the environment
-or argument list.
-Subsequently, expands to the last argument to the previous command,
-after expansion.
-Also set to the full pathname used to invoke each command executed
-and placed in the environment exported to that command.
-When checking mail, this parameter holds the name of the mail file
-currently being checked.
-.PD
-.SS Shell Variables
-.PP
-The following variables are set by the shell:
-.PP
-.PD 0
-.TP
-.B BASH
-Expands to the full file name used to invoke this instance of
-.BR bash .
-.TP
-.B BASH_ARGC
-An array variable whose values are the number of parameters in each
-frame of the current bash execution call stack.
-The number of
-parameters to the current subroutine (shell function or script executed
-with \fB.\fP or \fBsource\fP) is at the top of the stack.
-When a subroutine is executed, the number of parameters passed is pushed onto
-\fBBASH_ARGC\fP.
-The shell sets \fBBASH_ARGC\fP only when in extended debugging mode
-(see the description of the
-.B extdebug
-option to the
-.B shopt
-builtin below)
-.TP
-.B BASH_ARGV
-An array variable containing all of the parameters in the current bash
-execution call stack. The final parameter of the last subroutine call
-is at the top of the stack; the first parameter of the initial call is
-at the bottom. When a subroutine is executed, the parameters supplied
-are pushed onto \fBBASH_ARGV\fP.
-The shell sets \fBBASH_ARGV\fP only when in extended debugging mode
-(see the description of the
-.B extdebug
-option to the
-.B shopt
-builtin below)
-.TP
-.B BASH_COMMAND
-The command currently being executed or about to be executed, unless the
-shell is executing a command as the result of a trap,
-in which case it is the command executing at the time of the trap.
-.TP
-.B BASH_EXECUTION_STRING
-The command argument to the \fB\-c\fP invocation option.
-.TP
-.B BASH_LINENO
-An array variable whose members are the line numbers in source files
-corresponding to each member of \fBFUNCNAME\fP.
-\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP is the line number in the source
-file where \fB${FUNCNAME[\fP\fI$ifP\fB]}\fP was called.
-The corresponding source file name is \fB${BASH_SOURCE[\fP\fI$i\fP\fB]}\fB.
-Use \fBLINENO\fP to obtain the current line number.
-.TP
-.B BASH_REMATCH
-An array variable whose members are assigned by the \fB=~\fP binary
-operator to the \fB[[\fP conditional command.
-The element with index 0 is the portion of the string
-matching the entire regular expression.
-The element with index \fIn\fP is the portion of the
-string matching the \fIn\fPth parenthesized subexpression.
-This variable is read-only.
-.TP
-.B BASH_SOURCE
-An array variable whose members are the source filenames corresponding
-to the elements in the \fBFUNCNAME\fP array variable.
-.TP
-.B BASH_SUBSHELL
-Incremented by one each time a subshell or subshell environment is spawned.
-The initial value is 0.
-.TP
-.B BASH_VERSINFO
-A readonly array variable whose members hold version information for
-this instance of
-.BR bash .
-The values assigned to the array members are as follows:
-.sp .5
-.RS
-.PD 0
-.TP 24
-.B BASH_VERSINFO[\fR0\fP]
-The major version number (the \fIrelease\fP).
-.TP
-.B BASH_VERSINFO[\fR1\fP]
-The minor version number (the \fIversion\fP).
-.TP
-.B BASH_VERSINFO[\fR2\fP]
-The patch level.
-.TP
-.B BASH_VERSINFO[\fR3\fP]
-The build version.
-.TP
-.B BASH_VERSINFO[\fR4\fP]
-The release status (e.g., \fIbeta1\fP).
-.TP
-.B BASH_VERSINFO[\fR5\fP]
-The value of \fBMACHTYPE\fP.
-.PD
-.RE
-.TP
-.B BASH_VERSION
-Expands to a string describing the version of this instance of
-.BR bash .
-.TP
-.B COMP_CWORD
-An index into \fB${COMP_WORDS}\fP of the word containing the current
-cursor position.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_LINE
-The current command line.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_POINT
-The index of the current cursor position relative to the beginning of
-the current command.
-If the current cursor position is at the end of the current command,
-the value of this variable is equal to \fB${#COMP_LINE}\fP.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COMP_WORDBREAKS
-The set of characters that the Readline library treats as word
-separators when performing word completion.
-If
-.SM
-.B COMP_WORDBREAKS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B COMP_WORDS
-An array variable (see \fBArrays\fP below) consisting of the individual
-words in the current command line.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B DIRSTACK
-An array variable (see
-.B Arrays
-below) containing the current contents of the directory stack.
-Directories appear in the stack in the order they are displayed by the
-.B dirs
-builtin.
-Assigning to members of this array variable may be used to modify
-directories already in the stack, but the
-.B pushd
-and
-.B popd
-builtins must be used to add and remove directories.
-Assignment to this variable will not change the current directory.
-If
-.SM
-.B DIRSTACK
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B EUID
-Expands to the effective user ID of the current user, initialized at
-shell startup. This variable is readonly.
-.TP
-.B FUNCNAME
-An array variable containing the names of all shell functions
-currently in the execution call stack.
-The element with index 0 is the name of any currently-executing
-shell function.
-The bottom-most element is "main".
-This variable exists only when a shell function is executing.
-Assignments to
-.SM
-.B FUNCNAME
-have no effect and return an error status.
-If
-.SM
-.B FUNCNAME
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B GROUPS
-An array variable containing the list of groups of which the current
-user is a member.
-Assignments to
-.SM
-.B GROUPS
-have no effect and return an error status.
-If
-.SM
-.B GROUPS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B HISTCMD
-The history number, or index in the history list, of the current
-command.
-If
-.SM
-.B HISTCMD
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B HOSTNAME
-Automatically set to the name of the current host.
-.TP
-.B HOSTTYPE
-Automatically set to a string that uniquely
-describes the type of machine on which
-.B bash
-is executing.
-The default is system-dependent.
-.TP
-.B LINENO
-Each time this parameter is referenced, the shell substitutes
-a decimal number representing the current sequential line number
-(starting with 1) within a script or function. When not in a
-script or function, the value substituted is not guaranteed to
-be meaningful.
-If
-.SM
-.B LINENO
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B MACHTYPE
-Automatically set to a string that fully describes the system
-type on which
-.B bash
-is executing, in the standard GNU \fIcpu-company-system\fP format.
-The default is system-dependent.
-.TP
-.B OLDPWD
-The previous working directory as set by the
-.B cd
-command.
-.TP
-.B OPTARG
-The value of the last option argument processed by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.TP
-.B OPTIND
-The index of the next argument to be processed by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.TP
-.B OSTYPE
-Automatically set to a string that
-describes the operating system on which
-.B bash
-is executing.
-The default is system-dependent.
-.TP
-.B PIPESTATUS
-An array variable (see
-.B Arrays
-below) containing a list of exit status values from the processes
-in the most-recently-executed foreground pipeline (which may
-contain only a single command).
-.TP
-.B PPID
-The process ID of the shell's parent. This variable is readonly.
-.TP
-.B PWD
-The current working directory as set by the
-.B cd
-command.
-.TP
-.B RANDOM
-Each time this parameter is referenced, a random integer between
-0 and 32767 is
-generated. The sequence of random numbers may be initialized by assigning
-a value to
-.SM
-.BR RANDOM .
-If
-.SM
-.B RANDOM
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B REPLY
-Set to the line of input read by the
-.B read
-builtin command when no arguments are supplied.
-.TP
-.B SECONDS
-Each time this parameter is
-referenced, the number of seconds since shell invocation is returned. If a
-value is assigned to
-.SM
-.BR SECONDS ,
-the value returned upon subsequent
-references is
-the number of seconds since the assignment plus the value assigned.
-If
-.SM
-.B SECONDS
-is unset, it loses its special properties, even if it is
-subsequently reset.
-.TP
-.B SHELLOPTS
-A colon-separated list of enabled shell options. Each word in
-the list is a valid argument for the
-.B \-o
-option to the
-.B set
-builtin command (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below). The options appearing in
-.SM
-.B SHELLOPTS
-are those reported as
-.I on
-by \fBset \-o\fP.
-If this variable is in the environment when
-.B bash
-starts up, each shell option in the list will be enabled before
-reading any startup files.
-This variable is read-only.
-.TP
-.B SHLVL
-Incremented by one each time an instance of
-.B bash
-is started.
-.TP
-.B UID
-Expands to the user ID of the current user, initialized at shell startup.
-This variable is readonly.
-.PD
-.PP
-The following variables are used by the shell. In some cases,
-.B bash
-assigns a default value to a variable; these cases are noted
-below.
-.PP
-.PD 0
-.TP
-.B BASH_ENV
-If this parameter is set when \fBbash\fP is executing a shell script,
-its value is interpreted as a filename containing commands to
-initialize the shell, as in
-.IR ~/.bashrc .
-The value of
-.SM
-.B BASH_ENV
-is subjected to parameter expansion, command substitution, and arithmetic
-expansion before being interpreted as a file name.
-.SM
-.B PATH
-is not used to search for the resultant file name.
-.TP
-.B CDPATH
-The search path for the
-.B cd
-command.
-This is a colon-separated list of directories in which the shell looks
-for destination directories specified by the
-.B cd
-command.
-A sample value is
-.if t \f(CW".:~:/usr"\fP.
-.if n ".:~:/usr".
-.TP
-.B COLUMNS
-Used by the \fBselect\fP builtin command to determine the terminal width
-when printing selection lists. Automatically set upon receipt of a SIGWINCH.
-.TP
-.B COMPREPLY
-An array variable from which \fBbash\fP reads the possible completions
-generated by a shell function invoked by the programmable completion
-facility (see \fBProgrammable Completion\fP below).
-.TP
-.B EMACS
-If \fBbash\fP finds this variable in the environment when the shell starts
-with value
-.if t \f(CWt\fP,
-.if n "t",
-it assumes that the shell is running in an emacs shell buffer and disables
-line editing.
-.TP
-.B FCEDIT
-The default editor for the
-.B fc
-builtin command.
-.TP
-.B FIGNORE
-A colon-separated list of suffixes to ignore when performing
-filename completion (see
-.SM
-.B READLINE
-below).
-A filename whose suffix matches one of the entries in
-.SM
-.B FIGNORE
-is excluded from the list of matched filenames.
-A sample value is
-.if t \f(CW".o:~"\fP.
-.if n ".o:~".
-.TP
-.B GLOBIGNORE
-A colon-separated list of patterns defining the set of filenames to
-be ignored by pathname expansion.
-If a filename matched by a pathname expansion pattern also matches one
-of the patterns in
-.SM
-.BR GLOBIGNORE ,
-it is removed from the list of matches.
-.TP
-.B HISTCONTROL
-A colon-separated list of values controlling how commands are saved on
-the history list.
-If the list of values includes
-.IR ignorespace ,
-lines which begin with a
-.B space
-character are not saved in the history list.
-A value of
-.I ignoredups
-causes lines matching the previous history entry to not be saved.
-A value of
-.I ignoreboth
-is shorthand for \fIignorespace\fP and \fIignoredups\fP.
-A value of
-.IR erasedups
-causes all previous lines matching the current line to be removed from
-the history list before that line is saved.
-Any value not in the above list is ignored.
-If \fBHISTCONTROL\fP is unset, or does not include a valid value,
-all lines read by the shell parser are saved on the history list,
-subject to the value of
-.BR HISTIGNORE .
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-.BR HISTCONTROL .
-.TP
-.B HISTFILE
-The name of the file in which command history is saved (see
-.SM
-.B HISTORY
-below). The default value is \fI~/.bash_history\fP. If unset, the
-command history is not saved when an interactive shell exits.
-.TP
-.B HISTFILESIZE
-The maximum number of lines contained in the history file. When this
-variable is assigned a value, the history file is truncated, if
-necessary, by removing the oldest entries,
-to contain no more than that number of lines. The default
-value is 500. The history file is also truncated to this size after
-writing it when an interactive shell exits.
-.TP
-.B HISTIGNORE
-A colon-separated list of patterns used to decide which command lines
-should be saved on the history list. Each pattern is anchored at the
-beginning of the line and must match the complete line (no implicit
-`\fB*\fP' is appended). Each pattern is tested against the line
-after the checks specified by
-.B HISTCONTROL
-are applied.
-In addition to the normal shell pattern matching characters, `\fB&\fP'
-matches the previous history line. `\fB&\fP' may be escaped using a
-backslash; the backslash is removed before attempting a match.
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-.BR HISTIGNORE .
-.TP
-.B HISTSIZE
-The number of commands to remember in the command history (see
-.SM
-.B HISTORY
-below). The default value is 500.
-.TP
-.B HISTTIMEFORMAT
-If this variable is set and not null, its value is used as a format string
-for \fIstrftime\fP(3) to print the time stamp associated with each history
-entry displayed by the \fBhistory\fP builtin.
-If this variable is set, time stamps are written to the history file so
-they may be preserved across shell sessions.
-.TP
-.B HOME
-The home directory of the current user; the default argument for the
-\fBcd\fP builtin command.
-The value of this variable is also used when performing tilde expansion.
-.TP
-.B HOSTFILE
-Contains the name of a file in the same format as
-.FN /etc/hosts
-that should be read when the shell needs to complete a
-hostname.
-The list of possible hostname completions may be changed while the
-shell is running;
-the next time hostname completion is attempted after the
-value is changed,
-.B bash
-adds the contents of the new file to the existing list.
-If
-.SM
-.B HOSTFILE
-is set, but has no value, \fBbash\fP attempts to read
-.FN /etc/hosts
-to obtain the list of possible hostname completions.
-When
-.SM
-.B HOSTFILE
-is unset, the hostname list is cleared.
-.TP
-.B IFS
-The
-.I Internal Field Separator
-that is used
-for word splitting after expansion and to
-split lines into words with the
-.B read
-builtin command. The default value is
-``<space><tab><newline>''.
-.TP
-.B IGNOREEOF
-Controls the
-action of an interactive shell on receipt of an
-.SM
-.B EOF
-character as the sole input. If set, the value is the number of
-consecutive
-.SM
-.B EOF
-characters which must be
-typed as the first characters on an input line before
-.B bash
-exits. If the variable exists but does not have a numeric value, or
-has no value, the default value is 10. If it does not exist,
-.SM
-.B EOF
-signifies the end of input to the shell.
-.TP
-.B INPUTRC
-The filename for the
-.B readline
-startup file, overriding the default of
-.FN ~/.inputrc
-(see
-.SM
-.B READLINE
-below).
-.TP
-.B LANG
-Used to determine the locale category for any category not specifically
-selected with a variable starting with \fBLC_\fP.
-.TP
-.B LC_ALL
-This variable overrides the value of \fBLANG\fP and any other
-\fBLC_\fP variable specifying a locale category.
-.TP
-.B LC_COLLATE
-This variable determines the collation order used when sorting the
-results of pathname expansion, and determines the behavior of range
-expressions, equivalence classes, and collating sequences within
-pathname expansion and pattern matching.
-.TP
-.B LC_CTYPE
-This variable determines the interpretation of characters and the
-behavior of character classes within pathname expansion and pattern
-matching.
-.TP
-.B LC_MESSAGES
-This variable determines the locale used to translate double-quoted
-strings preceded by a \fB$\fP.
-.TP
-.B LC_NUMERIC
-This variable determines the locale category used for number formatting.
-.TP
-.B LINES
-Used by the \fBselect\fP builtin command to determine the column length
-for printing selection lists. Automatically set upon receipt of a SIGWINCH.
-.TP
-.B MAIL
-If this parameter is set to a file name and the
-.SM
-.B MAILPATH
-variable is not set,
-.B bash
-informs the user of the arrival of mail in the specified file.
-.TP
-.B MAILCHECK
-Specifies how
-often (in seconds)
-.B bash
-checks for mail. The default is 60 seconds. When it is time to check
-for mail, the shell does so before displaying the primary prompt.
-If this variable is unset, or set to a value that is not a number
-greater than or equal to zero, the shell disables mail checking.
-.TP
-.B MAILPATH
-A colon-separated list of file names to be checked for mail.
-The message to be printed when mail arrives in a particular file
-may be specified by separating the file name from the message with a `?'.
-When used in the text of the message, \fB$_\fP expands to the name of
-the current mailfile.
-Example:
-.RS
-.PP
-\fBMAILPATH\fP=\(aq/var/mail/bfox?"You have mail":~/shell\-mail?"$_ has mail!"\(aq
-.PP
-.B Bash
-supplies a default value for this variable, but the location of the user
-mail files that it uses is system dependent (e.g., /var/mail/\fB$USER\fP).
-.RE
-.TP
-.B OPTERR
-If set to the value 1,
-.B bash
-displays error messages generated by the
-.B getopts
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SM
-.B OPTERR
-is initialized to 1 each time the shell is invoked or a shell
-script is executed.
-.TP
-.B PATH
-The search path for commands. It
-is a colon-separated list of directories in which
-the shell looks for commands (see
-.SM
-.B COMMAND EXECUTION
-below).
-A zero-length (null) directory name in the value of \fBPATH\fP indicates the
-current directory.
-A null directory name may appear as two adjacent colons, or as an initial
-or trailing colon.
-The default path is system-dependent,
-and is set by the administrator who installs
-.BR bash .
-A common value is
-.if t \f(CW/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin\fP.
-.if n ``/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin''.
-.TP
-.B POSIXLY_CORRECT
-If this variable is in the environment when \fBbash\fP starts, the shell
-enters \fIposix mode\fP before reading the startup files, as if the
-.B \-\-posix
-invocation option had been supplied. If it is set while the shell is
-running, \fBbash\fP enables \fIposix mode\fP, as if the command
-.if t \f(CWset -o posix\fP
-.if n \fIset -o posix\fP
-had been executed.
-.TP
-.B PROMPT_COMMAND
-If set, the value is executed as a command prior to issuing each primary
-prompt.
-.TP
-.B PS1
-The value of this parameter is expanded (see
-.SM
-.B PROMPTING
-below) and used as the primary prompt string. The default value is
-``\fB\es\-\ev\e$ \fP''.
-.TP
-.B PS2
-The value of this parameter is expanded as with
-.B PS1
-and used as the secondary prompt string. The default is
-``\fB> \fP''.
-.TP
-.B PS3
-The value of this parameter is used as the prompt for the
-.B select
-command (see
-.SM
-.B SHELL GRAMMAR
-above).
-.TP
-.B PS4
-The value of this parameter is expanded as with
-.B PS1
-and the value is printed before each command
-.B bash
-displays during an execution trace. The first character of
-.SM
-.B PS4
-is replicated multiple times, as necessary, to indicate multiple
-levels of indirection. The default is ``\fB+ \fP''.
-.TP
-.B SHELL
-The full pathname to the shell is kept in this environment variable.
-If it is not set when the shell starts,
-.B bash
-assigns to it the full pathname of the current user's login shell.
-.TP
-.B TIMEFORMAT
-The value of this parameter is used as a format string specifying
-how the timing information for pipelines prefixed with the
-.B time
-reserved word should be displayed.
-The \fB%\fP character introduces an escape sequence that is
-expanded to a time value or other information.
-The escape sequences and their meanings are as follows; the
-braces denote optional portions.
-.sp .5
-.RS
-.PD 0
-.TP 10
-.B %%
-A literal \fB%\fP.
-.TP
-.B %[\fIp\fP][l]R
-The elapsed time in seconds.
-.TP
-.B %[\fIp\fP][l]U
-The number of CPU seconds spent in user mode.
-.TP
-.B %[\fIp\fP][l]S
-The number of CPU seconds spent in system mode.
-.TP
-.B %P
-The CPU percentage, computed as (%U + %S) / %R.
-.PD
-.RE
-.IP
-The optional \fIp\fP is a digit specifying the \fIprecision\fP,
-the number of fractional digits after a decimal point.
-A value of 0 causes no decimal point or fraction to be output.
-At most three places after the decimal point may be specified;
-values of \fIp\fP greater than 3 are changed to 3.
-If \fIp\fP is not specified, the value 3 is used.
-.IP
-The optional \fBl\fP specifies a longer format, including
-minutes, of the form \fIMM\fPm\fISS\fP.\fIFF\fPs.
-The value of \fIp\fP determines whether or not the fraction is
-included.
-.IP
-If this variable is not set, \fBbash\fP acts as if it had the
-value \fB$\(aq\enreal\et%3lR\enuser\et%3lU\ensys\t%3lS\(aq\fP.
-If the value is null, no timing information is displayed.
-A trailing newline is added when the format string is displayed.
-.TP
-.B TMOUT
-If set to a value greater than zero, \fBTMOUT\fP is treated as the
-default timeout for the \fBread\fP builtin.
-The \fBselect\fP command terminates if input does not arrive
-after \fBTMOUT\fP seconds when input is coming from a terminal.
-In an interactive shell, the value is interpreted as the
-number of seconds to wait for input after issuing the primary prompt.
-.B Bash
-terminates after waiting for that number of seconds if input does
-not arrive.
-.TP
-.B TMPDIR
-If set, \fBBash\fP uses its value as the name of a directory in which
-\fBBash\fP creates temporary files for the shell's use.
-.TP
-.B auto_resume
-This variable controls how the shell interacts with the user and
-job control. If this variable is set, single word simple
-commands without redirections are treated as candidates for resumption
-of an existing stopped job. There is no ambiguity allowed; if there is
-more than one job beginning with the string typed, the job most recently
-accessed is selected. The
-.I name
-of a stopped job, in this context, is the command line used to
-start it.
-If set to the value
-.IR exact ,
-the string supplied must match the name of a stopped job exactly;
-if set to
-.IR substring ,
-the string supplied needs to match a substring of the name of a
-stopped job. The
-.I substring
-value provides functionality analogous to the
-.B %?
-job identifier (see
-.SM
-.B JOB CONTROL
-below). If set to any other value, the supplied string must
-be a prefix of a stopped job's name; this provides functionality
-analogous to the \fB%\fP\fIstring\fP job identifier.
-.TP
-.B histchars
-The two or three characters which control history expansion
-and tokenization (see
-.SM
-.B HISTORY EXPANSION
-below). The first character is the \fIhistory expansion\fP character,
-the character which signals the start of a history
-expansion, normally `\fB!\fP'.
-The second character is the \fIquick substitution\fP
-character, which is used as shorthand for re-running the previous
-command entered, substituting one string for another in the command.
-The default is `\fB^\fP'.
-The optional third character is the character
-which indicates that the remainder of the line is a comment when found
-as the first character of a word, normally `\fB#\fP'. The history
-comment character causes history substitution to be skipped for the
-remaining words on the line. It does not necessarily cause the shell
-parser to treat the rest of the line as a comment.
-.PD
-.SS Arrays
-.B Bash
-provides one-dimensional array variables. Any variable may be used as
-an array; the
-.B declare
-builtin will explicitly declare an array. There is no maximum
-limit on the size of an array, nor any requirement that members
-be indexed or assigned contiguously. Arrays are indexed using
-integers and are zero-based.
-.PP
-An array is created automatically if any variable is assigned to using
-the syntax \fIname\fP[\fIsubscript\fP]=\fIvalue\fP. The
-.I subscript
-is treated as an arithmetic expression that must evaluate to a number
-greater than or equal to zero. To explicitly declare an array, use
-.B declare \-a \fIname\fP
-(see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.B declare \-a \fIname\fP[\fIsubscript\fP]
-is also accepted; the \fIsubscript\fP is ignored. Attributes may be
-specified for an array variable using the
-.B declare
-and
-.B readonly
-builtins. Each attribute applies to all members of an array.
-.PP
-Arrays are assigned to using compound assignments of the form
-\fIname\fP=\fB(\fPvalue\fI1\fP ... value\fIn\fP\fB)\fP, where each
-\fIvalue\fP is of the form [\fIsubscript\fP]=\fIstring\fP. Only
-\fIstring\fP is required. If
-the optional brackets and subscript are supplied, that index is assigned to;
-otherwise the index of the element assigned is the last index assigned
-to by the statement plus one. Indexing starts at zero.
-This syntax is also accepted by the
-.B declare
-builtin. Individual array elements may be assigned to using the
-\fIname\fP[\fIsubscript\fP]=\fIvalue\fP syntax introduced above.
-.PP
-Any element of an array may be referenced using
-${\fIname\fP[\fIsubscript\fP]}. The braces are required to avoid
-conflicts with pathname expansion. If
-\fIsubscript\fP is \fB@\fP or \fB*\fP, the word expands to
-all members of \fIname\fP. These subscripts differ only when the
-word appears within double quotes. If the word is double-quoted,
-${\fIname\fP[*]} expands to a single
-word with the value of each array member separated by the first
-character of the
-.SM
-.B IFS
-special variable, and ${\fIname\fP[@]} expands each element of
-\fIname\fP to a separate word. When there are no array members,
-${\fIname\fP[@]} expands to nothing.
-If the double-quoted expansion occurs within a word, the expansion of
-the first parameter is joined with the beginning part of the original
-word, and the expansion of the last parameter is joined with the last
-part of the original word.
-This is analogous to the expansion
-of the special parameters \fB*\fP and \fB@\fP (see
-.B Special Parameters
-above). ${#\fIname\fP[\fIsubscript\fP]} expands to the length of
-${\fIname\fP[\fIsubscript\fP]}. If \fIsubscript\fP is \fB*\fP or
-\fB@\fP, the expansion is the number of elements in the array.
-Referencing an array variable without a subscript is equivalent to
-referencing element zero.
-.PP
-The
-.B unset
-builtin is used to destroy arrays. \fBunset\fP \fIname\fP[\fIsubscript\fP]
-destroys the array element at index \fIsubscript\fP.
-Care must be taken to avoid unwanted side effects caused by filename
-generation.
-\fBunset\fP \fIname\fP, where \fIname\fP is an array, or
-\fBunset\fP \fIname\fP[\fIsubscript\fP], where
-\fIsubscript\fP is \fB*\fP or \fB@\fP, removes the entire array.
-.PP
-The
-.BR declare ,
-.BR local ,
-and
-.B readonly
-builtins each accept a
-.B \-a
-option to specify an array. The
-.B read
-builtin accepts a
-.B \-a
-option to assign a list of words read from the standard input
-to an array. The
-.B set
-and
-.B declare
-builtins display array values in a way that allows them to be
-reused as assignments.
-.SH EXPANSION
-Expansion is performed on the command line after it has been split into
-words. There are seven kinds of expansion performed:
-.IR "brace expansion" ,
-.IR "tilde expansion" ,
-.IR "parameter and variable expansion" ,
-.IR "command substitution" ,
-.IR "arithmetic expansion" ,
-.IR "word splitting" ,
-and
-.IR "pathname expansion" .
-.PP
-The order of expansions is: brace expansion, tilde expansion,
-parameter, variable and arithmetic expansion and
-command substitution
-(done in a left-to-right fashion), word splitting, and pathname
-expansion.
-.PP
-On systems that can support it, there is an additional expansion
-available: \fIprocess substitution\fP.
-.PP
-Only brace expansion, word splitting, and pathname expansion
-can change the number of words of the expansion; other expansions
-expand a single word to a single word.
-The only exceptions to this are the expansions of
-"\fB$@\fP" and "\fB${\fP\fIname\fP\fB[@]}\fP"
-as explained above (see
-.SM
-.BR PARAMETERS ).
-.SS Brace Expansion
-.PP
-.I "Brace expansion"
-is a mechanism by which arbitrary strings
-may be generated. This mechanism is similar to
-\fIpathname expansion\fP, but the filenames generated
-need not exist. Patterns to be brace expanded take
-the form of an optional
-.IR preamble ,
-followed by either a series of comma-separated strings or
-a sequence expression between a pair of braces, followed by
-an optional
-.IR postscript .
-The preamble is prefixed to each string contained
-within the braces, and the postscript is then appended
-to each resulting string, expanding left to right.
-.PP
-Brace expansions may be nested. The results of each expanded
-string are not sorted; left to right order is preserved.
-For example, a\fB{\fPd,c,b\fB}\fPe expands into `ade ace abe'.
-.PP
-A sequence expression takes the form \fB{\fP\fIx\fP\fB..\fP\fIy\fP\fB}\fP,
-where \fIx\fP and \fIy\fP are either integers or single characters.
-When integers are supplied, the expression expands to each number between
-\fIx\fP and \fIy\fP, inclusive.
-When characters are supplied, the expression expands to each character
-lexicographically between \fIx\fP and \fIy\fP, inclusive. Note that
-both \fIx\fP and \fIy\fP must be of the same type.
-.PP
-Brace expansion is performed before any other expansions,
-and any characters special to other expansions are preserved
-in the result. It is strictly textual.
-.B Bash
-does not apply any syntactic interpretation to the context of the
-expansion or the text between the braces.
-.PP
-A correctly-formed brace expansion must contain unquoted opening
-and closing braces, and at least one unquoted comma or a valid
-sequence expression.
-Any incorrectly formed brace expansion is left unchanged.
-A \fB{\fP or \fB,\fP may be quoted with a backslash to prevent its
-being considered part of a brace expression.
-To avoid conflicts with parameter expansion, the string \fB${\fP
-is not considered eligible for brace expansion.
-.PP
-This construct is typically used as shorthand when the common
-prefix of the strings to be generated is longer than in the
-above example:
-.RS
-.PP
-mkdir /usr/local/src/bash/{old,new,dist,bugs}
-.RE
-or
-.RS
-chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
-.RE
-.PP
-Brace expansion introduces a slight incompatibility with
-historical versions of
-.BR sh .
-.B sh
-does not treat opening or closing braces specially when they
-appear as part of a word, and preserves them in the output.
-.B Bash
-removes braces from words as a consequence of brace
-expansion. For example, a word entered to
-.B sh
-as \fIfile{1,2}\fP
-appears identically in the output. The same word is
-output as
-.I file1 file2
-after expansion by
-.BR bash .
-If strict compatibility with
-.B sh
-is desired, start
-.B bash
-with the
-.B +B
-option or disable brace expansion with the
-.B +B
-option to the
-.B set
-command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SS Tilde Expansion
-.PP
-If a word begins with an unquoted tilde character (`\fB~\fP'), all of
-the characters preceding the first unquoted slash (or all characters,
-if there is no unquoted slash) are considered a \fItilde-prefix\fP.
-If none of the characters in the tilde-prefix are quoted, the
-characters in the tilde-prefix following the tilde are treated as a
-possible \fIlogin name\fP.
-If this login name is the null string, the tilde is replaced with the
-value of the shell parameter
-.SM
-.BR HOME .
-If
-.SM
-.B HOME
-is unset, the home directory of the user executing the shell is
-substituted instead.
-Otherwise, the tilde-prefix is replaced with the home directory
-associated with the specified login name.
-.PP
-If the tilde-prefix is a `~+', the value of the shell variable
-.SM
-.B PWD
-replaces the tilde-prefix.
-If the tilde-prefix is a `~\-', the value of the shell variable
-.SM
-.BR OLDPWD ,
-if it is set, is substituted.
-If the characters following the tilde in the tilde-prefix consist
-of a number \fIN\fP, optionally prefixed
-by a `+' or a `\-', the tilde-prefix is replaced with the corresponding
-element from the directory stack, as it would be displayed by the
-.B dirs
-builtin invoked with the tilde-prefix as an argument.
-If the characters following the tilde in the tilde-prefix consist of a
-number without a leading `+' or `\-', `+' is assumed.
-.PP
-If the login name is invalid, or the tilde expansion fails, the word
-is unchanged.
-.PP
-Each variable assignment is checked for unquoted tilde-prefixes immediately
-following a
-.B :
-or the first
-.BR = .
-In these cases, tilde expansion is also performed.
-Consequently, one may use file names with tildes in assignments to
-.SM
-.BR PATH ,
-.SM
-.BR MAILPATH ,
-and
-.SM
-.BR CDPATH ,
-and the shell assigns the expanded value.
-.SS Parameter Expansion
-.PP
-The `\fB$\fP' character introduces parameter expansion,
-command substitution, or arithmetic expansion. The parameter name
-or symbol to be expanded may be enclosed in braces, which
-are optional but serve to protect the variable to be expanded from
-characters immediately following it which could be
-interpreted as part of the name.
-.PP
-When braces are used, the matching ending brace is the first `\fB}\fP'
-not escaped by a backslash or within a quoted string, and not within an
-embedded arithmetic expansion, command substitution, or parameter
-expansion.
-.PP
-.PD 0
-.TP
-${\fIparameter\fP}
-The value of \fIparameter\fP is substituted. The braces are required
-when
-.I parameter
-is a positional parameter with more than one digit,
-or when
-.I parameter
-is followed by a character which is not to be
-interpreted as part of its name.
-.PD
-.PP
-If the first character of \fIparameter\fP is an exclamation point,
-a level of variable indirection is introduced.
-\fBBash\fP uses the value of the variable formed from the rest of
-\fIparameter\fP as the name of the variable; this variable is then
-expanded and that value is used in the rest of the substitution, rather
-than the value of \fIparameter\fP itself.
-This is known as \fIindirect expansion\fP.
-The exceptions to this are the expansions of ${!\fIprefix\fP*} and
-${\fB!\fP\fIname\fP[\fI@\fP]} described below.
-The exclamation point must immediately follow the left brace in order to
-introduce indirection.
-.PP
-In each of the cases below, \fIword\fP is subject to tilde expansion,
-parameter expansion, command substitution, and arithmetic expansion.
-When not performing substring expansion, \fBbash\fP tests for a parameter
-that is unset or null; omitting the colon results in a test only for a
-parameter that is unset.
-.PP
-.PD 0
-.TP
-${\fIparameter\fP\fB:\-\fP\fIword\fP}
-\fBUse Default Values\fP. If
-.I parameter
-is unset or null, the expansion of
-.I word
-is substituted. Otherwise, the value of
-.I parameter
-is substituted.
-.TP
-${\fIparameter\fP\fB:=\fP\fIword\fP}
-\fBAssign Default Values\fP.
-If
-.I parameter
-is unset or null, the expansion of
-.I word
-is assigned to
-.IR parameter .
-The value of
-.I parameter
-is then substituted. Positional parameters and special parameters may
-not be assigned to in this way.
-.TP
-${\fIparameter\fP\fB:?\fP\fIword\fP}
-\fBDisplay Error if Null or Unset\fP.
-If
-.I parameter
-is null or unset, the expansion of \fIword\fP (or a message to that effect
-if
-.I word
-is not present) is written to the standard error and the shell, if it
-is not interactive, exits. Otherwise, the value of \fIparameter\fP is
-substituted.
-.TP
-${\fIparameter\fP\fB:+\fP\fIword\fP}
-\fBUse Alternate Value\fP.
-If
-.I parameter
-is null or unset, nothing is substituted, otherwise the expansion of
-.I word
-is substituted.
-.TP
-${\fIparameter\fP\fB:\fP\fIoffset\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB:\fP\fIoffset\fP\fB:\fP\fIlength\fP}
-.PD
-\fBSubstring Expansion.\fP
-Expands to up to \fIlength\fP characters of \fIparameter\fP
-starting at the character specified by \fIoffset\fP.
-If \fIlength\fP is omitted, expands to the substring of
-\fIparameter\fP starting at the character specified by \fIoffset\fP.
-\fIlength\fP and \fIoffset\fP are arithmetic expressions (see
-.SM
-.B
-ARITHMETIC EVALUATION
-below).
-\fIlength\fP must evaluate to a number greater than or equal to zero.
-If \fIoffset\fP evaluates to a number less than zero, the value
-is used as an offset from the end of the value of \fIparameter\fP.
-If \fIparameter\fP is \fB@\fP, the result is \fIlength\fP positional
-parameters beginning at \fIoffset\fP.
-If \fIparameter\fP is an array name indexed by @ or *,
-the result is the \fIlength\fP
-members of the array beginning with ${\fIparameter\fP[\fIoffset\fP]}.
-A negative \fIoffset\fP is taken relative to one greater than the maximum
-index of the specified array.
-Note that a negative offset must be separated from the colon by at least
-one space to avoid being confused with the :- expansion.
-Substring indexing is zero-based unless the positional parameters
-are used, in which case the indexing starts at 1.
-.TP
-${\fB!\fP\fIprefix\fP\fB*\fP}
-.PD 0
-.TP
-${\fB!\fP\fIprefix\fP\fB@\fP}
-.PD
-Expands to the names of variables whose names begin with \fIprefix\fP,
-separated by the first character of the
-.SM
-.B IFS
-special variable.
-.TP
-${\fB!\fP\fIname\fP[\fI@\fP]}
-.PD 0
-.TP
-${\fB!\fP\fIname\fP[\fI*\fP]}
-.PD
-If \fIname\fP is an array variable, expands to the list of array indices
-(keys) assigned in \fIname\fP.
-If \fIname\fP is not an array, expands to 0 if \fIname\fP is set and null
-otherwise.
-When \fI@\fP is used and the expansion appears within double quotes, each
-key expands to a separate word.
-.TP
-${\fB#\fP\fIparameter\fP}
-The length in characters of the value of \fIparameter\fP is substituted.
-If
-.I parameter
-is
-.B *
-or
-.BR @ ,
-the value substituted is the number of positional parameters.
-If
-.I parameter
-is an array name subscripted by
-.B *
-or
-.BR @ ,
-the value substituted is the number of elements in the array.
-.TP
-${\fIparameter\fP\fB#\fP\fIword\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB##\fP\fIword\fP}
-.PD
-The
-.I word
-is expanded to produce a pattern just as in pathname
-expansion. If the pattern matches the beginning of
-the value of
-.IR parameter ,
-then the result of the expansion is the expanded value of
-.I parameter
-with the shortest matching pattern (the ``\fB#\fP'' case) or the
-longest matching pattern (the ``\fB##\fP'' case) deleted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-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\fIword\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB%%\fP\fIword\fP}
-.PD
-The \fIword\fP is expanded to produce a pattern just as in
-pathname expansion.
-If the pattern matches a trailing portion of the expanded value of
-.IR parameter ,
-then the result of the expansion is the expanded value of
-.I parameter
-with the shortest matching pattern (the ``\fB%\fP'' case) or the
-longest matching pattern (the ``\fB%%\fP'' case) deleted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-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}
-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.
-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
-of the expanded value of \fIparameter\fP.
-If \fIstring\fP is null, matches of \fIpattern\fP are deleted
-and the \fB/\fP following \fIpattern\fP may be omitted.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the substitution operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If
-.I parameter
-is an array variable subscripted with
-.B @
-or
-.BR * ,
-the substitution operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-.SS Command Substitution
-.PP
-\fICommand substitution\fP allows the output of a command to replace
-the command name. There are two forms:
-.PP
-.RS
-.PP
-\fB$(\fP\fIcommand\fP\|\fB)\fP
-.RE
-or
-.RS
-\fB`\fP\fIcommand\fP\fB`\fP
-.RE
-.PP
-.B Bash
-performs the expansion by executing \fIcommand\fP and
-replacing the command substitution with the standard output of the
-command, with any trailing newlines deleted.
-Embedded newlines are not deleted, but they may be removed during
-word splitting.
-The command substitution \fB$(cat \fIfile\fP)\fR can be replaced by
-the equivalent but faster \fB$(< \fIfile\fP)\fR.
-.PP
-When the old-style backquote form of substitution is used,
-backslash retains its literal meaning except when followed by
-.BR $ ,
-.BR ` ,
-or
-.BR \e .
-The first backquote not preceded by a backslash terminates the
-command substitution.
-When using the $(\^\fIcommand\fP\|) form, all characters between the
-parentheses make up the command; none are treated specially.
-.PP
-Command substitutions may be nested. To nest when using the backquoted form,
-escape the inner backquotes with backslashes.
-.PP
-If the substitution appears within double quotes, word splitting and
-pathname expansion are not performed on the results.
-.SS Arithmetic Expansion
-.PP
-Arithmetic expansion allows the evaluation of an arithmetic expression
-and the substitution of the result. The format for arithmetic expansion is:
-.RS
-.PP
-\fB$((\fP\fIexpression\fP\fB))\fP
-.RE
-.PP
-The
-.I expression
-is treated as if it were within double quotes, but a double quote
-inside the parentheses is not treated specially.
-All tokens in the expression undergo parameter expansion, string
-expansion, command substitution, and quote removal.
-Arithmetic expansions may be nested.
-.PP
-The evaluation is performed according to the rules listed below under
-.SM
-.BR "ARITHMETIC EVALUATION" .
-If
-.I expression
-is invalid,
-.B bash
-prints a message indicating failure and no substitution occurs.
-.SS Process Substitution
-.PP
-\fIProcess substitution\fP is supported on systems that support named
-pipes (\fIFIFOs\fP) or the \fB/dev/fd\fP method of naming open files.
-It takes the form of
-\fB<(\fP\fIlist\^\fP\fB)\fP
-or
-\fB>(\fP\fIlist\^\fP\fB)\fP.
-The process \fIlist\fP is run with its input or output connected to a
-\fIFIFO\fP or some file in \fB/dev/fd\fP. The name of this file is
-passed as an argument to the current command as the result of the
-expansion. If the \fB>(\fP\fIlist\^\fP\fB)\fP form is used, writing to
-the file will provide input for \fIlist\fP. If the
-\fB<(\fP\fIlist\^\fP\fB)\fP form is used, the file passed as an
-argument should be read to obtain the output of \fIlist\fP.
-.PP
-When available, process substitution is performed
-simultaneously with parameter and variable expansion,
-command substitution,
-and arithmetic expansion.
-.SS Word Splitting
-.PP
-The shell scans the results of
-parameter expansion,
-command substitution,
-and
-arithmetic expansion
-that did not occur within double quotes for
-.IR "word splitting" .
-.PP
-The shell treats each character of
-.SM
-.B IFS
-as a delimiter, and splits the results of the other
-expansions into words on these characters. If
-.SM
-.B IFS
-is unset, or its
-value is exactly
-.BR <space><tab><newline> ,
-the default, then
-any sequence of
-.SM
-.B IFS
-characters serves to delimit words. If
-.SM
-.B IFS
-has a value other than the default, then sequences of
-the whitespace characters
-.B space
-and
-.B tab
-are ignored at the beginning and end of the
-word, as long as the whitespace character is in the
-value of
-.SM
-.BR IFS
-(an
-.SM
-.B IFS
-whitespace character).
-Any character in
-.SM
-.B IFS
-that is not
-.SM
-.B IFS
-whitespace, along with any adjacent
-.SM
-.B IFS
-whitespace characters, delimits a field.
-A sequence of
-.SM
-.B IFS
-whitespace characters is also treated as a delimiter.
-If the value of
-.SM
-.B IFS
-is null, no word splitting occurs.
-.PP
-Explicit null arguments (\^\f3"\^"\fP or \^\f3\(aq\^\(aq\fP\^) are retained.
-Unquoted implicit null arguments, resulting from the expansion of
-parameters that have no values, are removed.
-If a parameter with no value is expanded within double quotes, a
-null argument results and is retained.
-.PP
-Note that if no expansion occurs, no splitting
-is performed.
-.SS Pathname Expansion
-.PP
-After word splitting,
-unless the
-.B \-f
-option has been set,
-.B bash
-scans each word for the characters
-.BR * ,
-.BR ? ,
-and
-.BR [ .
-If one of these characters appears, then the word is
-regarded as a
-.IR pattern ,
-and replaced with an alphabetically sorted list of
-file names matching the pattern.
-If no matching file names are found,
-and the shell option
-.B nullglob
-is disabled, the word is left unchanged.
-If the
-.B nullglob
-option is set, and no matches are found,
-the word is removed.
-If the
-.B failglob
-shell option is set, and no matches are found, an error message
-is printed and the command is not executed.
-If the shell option
-.B nocaseglob
-is enabled, the match is performed without regard to the case
-of alphabetic characters.
-When a pattern is used for pathname expansion,
-the character
-.B ``.''
-at the start of a name or immediately following a slash
-must be matched explicitly, unless the shell option
-.B dotglob
-is set.
-When matching a pathname, the slash character must always be
-matched explicitly.
-In other cases, the
-.B ``.''
-character is not treated specially.
-See the description of
-.B shopt
-below under
-.SM
-.B SHELL BUILTIN COMMANDS
-for a description of the
-.BR nocaseglob ,
-.BR nullglob ,
-.BR failglob ,
-and
-.B dotglob
-shell options.
-.PP
-The
-.SM
-.B GLOBIGNORE
-shell variable may be used to restrict the set of file names matching a
-.IR pattern .
-If
-.SM
-.B GLOBIGNORE
-is set, each matching file name that also matches one of the patterns in
-.SM
-.B GLOBIGNORE
-is removed from the list of matches.
-The file names
-.B ``.''
-and
-.B ``..''
-are always ignored when
-.SM
-.B GLOBIGNORE
-is set and not null. However, setting
-.SM
-.B GLOBIGNORE
-to a non-null value has the effect of enabling the
-.B dotglob
-shell option, so all other file names beginning with a
-.B ``.''
-will match.
-To get the old behavior of ignoring file names beginning with a
-.BR ``.'' ,
-make
-.B ``.*''
-one of the patterns in
-.SM
-.BR GLOBIGNORE .
-The
-.B dotglob
-option is disabled when
-.SM
-.B GLOBIGNORE
-is unset.
-.PP
-\fBPattern Matching\fP
-.PP
-Any character that appears in a pattern, other than the special pattern
-characters described below, matches itself. The NUL character may not
-occur in a pattern. A backslash escapes the following character; the
-escaping backslash is discarded when matching.
-The special pattern characters must be quoted if
-they are to be matched literally.
-.PP
-The special pattern characters have the following meanings:
-.PP
-.PD 0
-.TP
-.B *
-Matches any string, including the null string.
-.TP
-.B ?
-Matches any single character.
-.TP
-.B [...]
-Matches any one of the enclosed characters. A pair of characters
-separated by a hyphen denotes a
-\fIrange expression\fP;
-any character that sorts between those two characters, inclusive,
-using the current locale's collating sequence and character set,
-is matched. If the first character following the
-.B [
-is a
-.B !
-or a
-.B ^
-then any character not enclosed is matched.
-The sorting order of characters in range expressions is determined by
-the current locale and the value of the \fBLC_COLLATE\fP shell variable,
-if set.
-A
-.B \-
-may be matched by including it as the first or last character
-in the set.
-A
-.B ]
-may be matched by including it as the first character
-in the set.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and
-.BR ] ,
-\fIcharacter classes\fP can be specified using the syntax
-\fB[:\fP\fIclass\fP\fB:]\fP, where \fIclass\fP is one of the
-following classes defined in the POSIX standard:
-.PP
-.RS
-.B
-.if n alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit
-.if t alnum alpha ascii blank cntrl digit graph lower print punct space upper word xdigit
-.br
-A character class matches any character belonging to that class.
-The \fBword\fP character class matches letters, digits, and the character _.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and
-.BR ] ,
-an \fIequivalence class\fP can be specified using the syntax
-\fB[=\fP\fIc\fP\fB=]\fP, which matches all characters with the
-same collation weight (as defined by the current locale) as
-the character \fIc\fP.
-.br
-.if t .sp 0.5
-.if n .sp 1
-Within
-.B [
-and
-.BR ] ,
-the syntax \fB[.\fP\fIsymbol\fP\fB.]\fP matches the collating symbol
-\fIsymbol\fP.
-.RE
-.PD
-.PP
-If the \fBextglob\fP shell option is enabled using the \fBshopt\fP
-builtin, several extended pattern matching operators are recognized.
-In the following description, a \fIpattern-list\fP is a list of one
-or more patterns separated by a \fB|\fP.
-Composite patterns may be formed using one or more of the following
-sub-patterns:
-.sp 1
-.PD 0
-.RS
-.TP
-\fB?(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches zero or one occurrence of the given patterns
-.TP
-\fB*(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches zero or more occurrences of the given patterns
-.TP
-\fB+(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches one or more occurrences of the given patterns
-.TP
-\fB@(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches one of the given patterns
-.TP
-\fB!(\fP\^\fIpattern-list\^\fP\fB)\fP
-Matches anything except one of the given patterns
-.RE
-.PD
-.SS Quote Removal
-.PP
-After the preceding expansions, all unquoted occurrences of the
-characters
-.BR \e ,
-.BR \(aq ,
-and \^\f3"\fP\^ that did not result from one of the above
-expansions are removed.
-.SH REDIRECTION
-Before a command is executed, its input and output
-may be
-.I redirected
-using a special notation interpreted by the shell.
-Redirection may also be used to open and close files for the
-current shell execution environment. The following redirection
-operators may precede or appear anywhere within a
-.I simple command
-or may follow a
-.IR command .
-Redirections are processed in the order they appear, from
-left to right.
-.PP
-In the following descriptions, if the file descriptor number is
-omitted, and the first character of the redirection operator is
-.BR < ,
-the redirection refers to the standard input (file descriptor
-0). If the first character of the redirection operator is
-.BR > ,
-the redirection refers to the standard output (file descriptor
-1).
-.PP
-The word following the redirection operator in the following
-descriptions, unless otherwise noted, is subjected to brace expansion,
-tilde expansion, parameter expansion, command substitution, arithmetic
-expansion, quote removal, pathname expansion, and word splitting.
-If it expands to more than one word,
-.B bash
-reports an error.
-.PP
-Note that the order of redirections is significant. For example,
-the command
-.RS
-.PP
-ls \fB>\fP dirlist 2\fB>&\fP1
-.RE
-.PP
-directs both standard output and standard error to the file
-.IR dirlist ,
-while the command
-.RS
-.PP
-ls 2\fB>&\fP1 \fB>\fP dirlist
-.RE
-.PP
-directs only the standard output to file
-.IR dirlist ,
-because the standard error was duplicated as standard output
-before the standard output was redirected to
-.IR dirlist .
-.PP
-\fBBash\fP handles several filenames specially when they are used in
-redirections, as described in the following table:
-.RS
-.PP
-.PD 0
-.TP
-.B /dev/fd/\fIfd\fP
-If \fIfd\fP is a valid integer, file descriptor \fIfd\fP is duplicated.
-.TP
-.B /dev/stdin
-File descriptor 0 is duplicated.
-.TP
-.B /dev/stdout
-File descriptor 1 is duplicated.
-.TP
-.B /dev/stderr
-File descriptor 2 is duplicated.
-.TP
-.B /dev/tcp/\fIhost\fP/\fIport\fP
-If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP
-is an integer port number or service name, \fBbash\fP attempts to open
-a TCP connection to the corresponding socket.
-.TP
-.B /dev/udp/\fIhost\fP/\fIport\fP
-If \fIhost\fP is a valid hostname or Internet address, and \fIport\fP
-is an integer port number or service name, \fBbash\fP attempts to open
-a UDP connection to the corresponding socket.
-.PD
-.RE
-.PP
-A failure to open or create a file causes the redirection to fail.
-.PP
-Redirections using file descriptors greater than 9 should be used with
-care, as they may conflict with file descriptors the shell uses
-internally.
-.SS Redirecting Input
-.PP
-Redirection of input causes the file whose name results from
-the expansion of
-.I word
-to be opened for reading on file descriptor
-.IR n ,
-or the standard input (file descriptor 0) if
-.I n
-is not specified.
-.PP
-The general format for redirecting input is:
-.RS
-.PP
-[\fIn\fP]\fB<\fP\fIword\fP
-.RE
-.SS Redirecting Output
-.PP
-Redirection of output causes the file whose name results from
-the expansion of
-.I word
-to be opened for writing on file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if
-.I n
-is not specified. If the file does not exist it is created;
-if it does exist it is truncated to zero size.
-.PP
-The general format for redirecting output is:
-.RS
-.PP
-[\fIn\fP]\fB>\fP\fIword\fP
-.RE
-.PP
-If the redirection operator is
-.BR > ,
-and the
-.B noclobber
-option to the
-.B set
-builtin has been enabled, the redirection will fail if the file
-whose name results from the expansion of \fIword\fP exists and is
-a regular file.
-If the redirection operator is
-.BR >| ,
-or the redirection operator is
-.B >
-and the
-.B noclobber
-option to the
-.B set
-builtin command is not enabled, the redirection is attempted even
-if the file named by \fIword\fP exists.
-.SS Appending Redirected Output
-.PP
-Redirection of output in this fashion
-causes the file whose name results from
-the expansion of
-.I word
-to be opened for appending on file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if
-.I n
-is not specified. If the file does not exist it is created.
-.PP
-The general format for appending output is:
-.RS
-.PP
-[\fIn\fP]\fB>>\fP\fIword\fP
-.RE
-.PP
-.SS Redirecting Standard Output and Standard Error
-.PP
-.B Bash
-allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be redirected to the file whose name is the
-expansion of
-.I word
-with this construct.
-.PP
-There are two formats for redirecting standard output and
-standard error:
-.RS
-.PP
-\fB&>\fP\fIword\fP
-.RE
-and
-.RS
-\fB>&\fP\fIword\fP
-.RE
-.PP
-Of the two forms, the first is preferred.
-This is semantically equivalent to
-.RS
-.PP
-\fB>\fP\fIword\fP 2\fB>&\fP1
-.RE
-.SS Here Documents
-.PP
-This type of redirection instructs the shell to read input from the
-current source until a line containing only
-.I word
-(with no trailing blanks)
-is seen. All of
-the lines read up to that point are then used as the standard
-input for a command.
-.PP
-The format of here-documents is:
-.RS
-.PP
-.nf
-\fB<<\fP[\fB\-\fP]\fIword\fP
- \fIhere-document\fP
-\fIdelimiter\fP
-.fi
-.RE
-.PP
-No parameter expansion, command substitution, arithmetic expansion,
-or pathname expansion is performed on
-.IR word .
-If any characters in
-.I word
-are quoted, the
-.I delimiter
-is the result of quote removal on
-.IR word ,
-and the lines in the here-document are not expanded.
-If \fIword\fP is unquoted,
-all lines of the here-document are subjected to parameter expansion,
-command substitution, and arithmetic expansion. In the latter
-case, the character sequence
-.B \e<newline>
-is ignored, and
-.B \e
-must be used to quote the characters
-.BR \e ,
-.BR $ ,
-and
-.BR ` .
-.PP
-If the redirection operator is
-.BR <<\- ,
-then all leading tab characters are stripped from input lines and the
-line containing
-.IR delimiter .
-This allows
-here-documents within shell scripts to be indented in a
-natural fashion.
-.SS "Here Strings"
-A variant of here documents, the format is:
-.RS
-.PP
-.nf
-\fB<<<\fP\fIword\fP
-.fi
-.RE
-.PP
-The \fIword\fP is expanded and supplied to the command on its standard
-input.
-.SS "Duplicating File Descriptors"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<&\fP\fIword\fP
-.RE
-.PP
-is used to duplicate input file descriptors.
-If
-.I word
-expands to one or more digits, the file descriptor denoted by
-.I n
-is made to be a copy of that file descriptor.
-If the digits in
-.I word
-do not specify a file descriptor open for input, a redirection error occurs.
-If
-.I word
-evaluates to
-.BR \- ,
-file descriptor
-.I n
-is closed. If
-.I n
-is not specified, the standard input (file descriptor 0) is used.
-.PP
-The operator
-.RS
-.PP
-[\fIn\fP]\fB>&\fP\fIword\fP
-.RE
-.PP
-is used similarly to duplicate output file descriptors. If
-.I n
-is not specified, the standard output (file descriptor 1) is used.
-If the digits in
-.I word
-do not specify a file descriptor open for output, a redirection error occurs.
-As a special case, if \fIn\fP is omitted, and \fIword\fP does not
-expand to one or more digits, the standard output and standard
-error are redirected as described previously.
-.SS "Moving File Descriptors"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<&\fP\fIdigit\fP\fB\-\fP
-.RE
-.PP
-moves the file descriptor \fIdigit\fP to file descriptor
-.IR n ,
-or the standard input (file descriptor 0) if \fIn\fP is not specified.
-\fIdigit\fP is closed after being duplicated to \fIn\fP.
-.PP
-Similarly, the redirection operator
-.RS
-.PP
-[\fIn\fP]\fB>&\fP\fIdigit\fP\fB\-\fP
-.RE
-.PP
-moves the file descriptor \fIdigit\fP to file descriptor
-.IR n ,
-or the standard output (file descriptor 1) if \fIn\fP is not specified.
-.SS "Opening File Descriptors for Reading and Writing"
-.PP
-The redirection operator
-.RS
-.PP
-[\fIn\fP]\fB<>\fP\fIword\fP
-.RE
-.PP
-causes the file whose name is the expansion of
-.I word
-to be opened for both reading and writing on file descriptor
-.IR n ,
-or on file descriptor 0 if
-.I n
-is not specified. If the file does not exist, it is created.
-.SH ALIASES
-\fIAliases\fP allow a string to be substituted for a word when it is used
-as the first word of a simple command.
-The shell maintains a list of aliases that may be set and unset with the
-.B alias
-and
-.B unalias
-builtin commands (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-The first word of each simple command, if unquoted,
-is checked to see if it has an
-alias. If so, that word is replaced by the text of the alias.
-The characters \fB/\fP, \fB$\fP, \fB`\fP, and \fB=\fP and
-any of the shell \fImetacharacters\fP or quoting characters
-listed above may not appear in an alias name.
-The replacement text may contain any valid shell input,
-including shell metacharacters.
-The first word of the replacement text is tested
-for aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.
-This means that one may alias
-.B ls
-to
-.BR "ls \-F" ,
-for instance, and
-.B bash
-does not try to recursively expand the replacement text.
-If the last character of the alias value is a
-.IR blank ,
-then the next command
-word following the alias is also checked for alias expansion.
-.PP
-Aliases are created and listed with the
-.B alias
-command, and removed with the
-.B unalias
-command.
-.PP
-There is no mechanism for using arguments in the replacement text.
-If arguments are needed, a shell function should be used (see
-.SM
-.B FUNCTIONS
-below).
-.PP
-Aliases are not expanded when the shell is not interactive, unless
-the
-.B expand_aliases
-shell option is set using
-.B shopt
-(see the description of
-.B shopt
-under
-.SM
-\fBSHELL BUILTIN COMMANDS\fP
-below).
-.PP
-The rules concerning the definition and use of aliases are
-somewhat confusing.
-.B Bash
-always reads at least one complete line
-of input before executing any
-of the commands on that line. Aliases are expanded when a
-command is read, not when it is executed. Therefore, an
-alias definition appearing on the same line as another
-command does not take effect until the next line of input is read.
-The commands following the alias definition
-on that line are not affected by the new alias.
-This behavior is also an issue when functions are executed.
-Aliases are expanded when a function definition is read,
-not when the function is executed, because a function definition
-is itself a compound command. As a consequence, aliases
-defined in a function are not available until after that
-function is executed. To be safe, always put
-alias definitions on a separate line, and do not use
-.B alias
-in compound commands.
-.PP
-For almost every purpose, aliases are superseded by
-shell functions.
-.SH FUNCTIONS
-A shell function, defined as described above under
-.SM
-.BR "SHELL GRAMMAR" ,
-stores a series of commands for later execution.
-When the name of a shell function is used as a simple command name,
-the list of commands associated with that function name is executed.
-Functions are executed in the context of the
-current shell; no new process is created to interpret
-them (contrast this with the execution of a shell script).
-When a function is executed, the arguments to the
-function become the positional parameters
-during its execution.
-The special parameter
-.B #
-is updated to reflect the change. Special parameter 0
-is unchanged.
-The first element of the
-.SM
-.B FUNCNAME
-variable is set to the name of the function while the function
-is executing.
-All other aspects of the shell execution
-environment are identical between a function and its caller
-with the exception that the
-.SM
-.B DEBUG
-and
-.B RETURN
-traps (see the description of the
-.B trap
-builtin under
-.SM
-.B SHELL BUILTIN COMMANDS
-below) are not inherited unless the function has been given the
-\fBtrace\fP attribute (see the description of the
-.SM
-.B declare
-builtin below) or the
-\fB\-o functrace\fP shell option has been enabled with
-the \fBset\fP builtin
-(in which case all functions inherit the \fBDEBUG\fP and \fBRETURN\fP traps).
-.PP
-Variables local to the function may be declared with the
-.B local
-builtin command. Ordinarily, variables and their values
-are shared between the function and its caller.
-.PP
-If the builtin command
-.B return
-is executed in a function, the function completes and
-execution resumes with the next command after the function
-call.
-Any command associated with the \fBRETURN\fP trap is executed
-before execution resumes.
-When a function completes, the values of the
-positional parameters and the special parameter
-.B #
-are restored to the values they had prior to the function's
-execution.
-.PP
-Function names and definitions may be listed with the
-.B \-f
-option to the
-.B declare
-or
-.B typeset
-builtin commands. The
-.B \-F
-option to
-.B declare
-or
-.B typeset
-will list the function names only
-(and optionally the source file and line number, if the \fBextdebug\fP
-shell option is enabled).
-Functions may be exported so that subshells
-automatically have them defined with the
-.B \-f
-option to the
-.B export
-builtin.
-A function definition may be deleted using the \fB\-f\fP option to
-the
-.B unset
-builtin.
-Note that shell functions and variables with the same name may result
-in multiple identically-named entries in the environment passed to the
-shell's children.
-Care should be taken in cases where this may cause a problem.
-.PP
-Functions may be recursive. No limit is imposed on the number
-of recursive calls.
-.SH "ARITHMETIC EVALUATION"
-The shell allows arithmetic expressions to be evaluated, under
-certain circumstances (see the \fBlet\fP and \fBdeclare\fP builtin
-commands and \fBArithmetic Expansion\fP).
-Evaluation is done in fixed-width integers with no check for overflow,
-though division by 0 is trapped and flagged as an error.
-The operators and their precedence, associativity, and values
-are the same as in the C language.
-The following list of operators is grouped into levels of
-equal-precedence operators.
-The levels are listed in order of decreasing precedence.
-.PP
-.PD 0
-.TP
-.B \fIid\fP++ \fIid\fP\-\-
-variable post-increment and post-decrement
-.TP
-.B ++\fIid\fP \-\-\fIid\fP
-variable pre-increment and pre-decrement
-.TP
-.B \- +
-unary minus and plus
-.TP
-.B ! ~
-logical and bitwise negation
-.TP
-.B **
-exponentiation
-.TP
-.B * / %
-multiplication, division, remainder
-.TP
-.B + \-
-addition, subtraction
-.TP
-.B << >>
-left and right bitwise shifts
-.TP
-.B <= >= < >
-comparison
-.TP
-.B == !=
-equality and inequality
-.TP
-.B &
-bitwise AND
-.TP
-.B ^
-bitwise exclusive OR
-.TP
-.B |
-bitwise OR
-.TP
-.B &&
-logical AND
-.TP
-.B ||
-logical OR
-.TP
-.B \fIexpr\fP?\fIexpr\fP:\fIexpr\fP
-conditional operator
-.TP
-.B = *= /= %= += \-= <<= >>= &= ^= |=
-assignment
-.TP
-.B \fIexpr1\fP , \fIexpr2\fP
-comma
-.PD
-.PP
-Shell variables are allowed as operands; parameter expansion is
-performed before the expression is evaluated.
-Within an expression, shell variables may also be referenced by name
-without using the parameter expansion syntax.
-A shell variable that is null or unset evaluates to 0 when referenced
-by name without using the parameter expansion syntax.
-The value of a variable is evaluated as an arithmetic expression
-when it is referenced, or when a variable which has been given the
-\fIinteger\fP attribute using \fBdeclare -i\fP is assigned a value.
-A null value evaluates to 0.
-A shell variable need not have its integer attribute
-turned on to be used in an expression.
-.PP
-Constants with a leading 0 are interpreted as octal numbers.
-A leading 0x or 0X denotes hexadecimal.
-Otherwise, numbers take the form [\fIbase#\fP]n, where \fIbase\fP
-is a decimal number between 2 and 64 representing the arithmetic
-base, and \fIn\fP is a number in that base.
-If \fIbase#\fP is omitted, then base 10 is used.
-The digits greater than 9 are represented by the lowercase letters,
-the uppercase letters, @, and _, in that order.
-If \fIbase\fP is less than or equal to 36, lowercase and uppercase
-letters may be used interchangeably to represent numbers between 10
-and 35.
-.PP
-Operators are evaluated in order of precedence. Sub-expressions in
-parentheses are evaluated first and may override the precedence
-rules above.
-.SH "CONDITIONAL EXPRESSIONS"
-Conditional expressions are used by the \fB[[\fP compound command and
-the \fBtest\fP and \fB[\fP builtin commands to test file attributes
-and perform string and arithmetic comparisons.
-Expressions are formed from the following unary or binary primaries.
-If any \fIfile\fP argument to one of the primaries is of the form
-\fI/dev/fd/n\fP, then file descriptor \fIn\fP is checked.
-If the \fIfile\fP argument to one of the primaries is one of
-\fI/dev/stdin\fP, \fI/dev/stdout\fP, or \fI/dev/stderr\fP, file
-descriptor 0, 1, or 2, respectively, is checked.
-.PP
-Unless otherwise specified, primaries that operate on files follow symbolic
-links and operate on the target of the link, rather than the link itself.
-.sp 1
-.PD 0
-.TP
-.B \-a \fIfile\fP
-True if \fIfile\fP exists.
-.TP
-.B \-b \fIfile\fP
-True if \fIfile\fP exists and is a block special file.
-.TP
-.B \-c \fIfile\fP
-True if \fIfile\fP exists and is a character special file.
-.TP
-.B \-d \fIfile\fP
-True if \fIfile\fP exists and is a directory.
-.TP
-.B \-e \fIfile\fP
-True if \fIfile\fP exists.
-.TP
-.B \-f \fIfile\fP
-True if \fIfile\fP exists and is a regular file.
-.TP
-.B \-g \fIfile\fP
-True if \fIfile\fP exists and is set-group-id.
-.TP
-.B \-h \fIfile\fP
-True if \fIfile\fP exists and is a symbolic link.
-.TP
-.B \-k \fIfile\fP
-True if \fIfile\fP exists and its ``sticky'' bit is set.
-.TP
-.B \-p \fIfile\fP
-True if \fIfile\fP exists and is a named pipe (FIFO).
-.TP
-.B \-r \fIfile\fP
-True if \fIfile\fP exists and is readable.
-.TP
-.B \-s \fIfile\fP
-True if \fIfile\fP exists and has a size greater than zero.
-.TP
-.B \-t \fIfd\fP
-True if file descriptor
-.I fd
-is open and refers to a terminal.
-.TP
-.B \-u \fIfile\fP
-True if \fIfile\fP exists and its set-user-id bit is set.
-.TP
-.B \-w \fIfile\fP
-True if \fIfile\fP exists and is writable.
-.TP
-.B \-x \fIfile\fP
-True if \fIfile\fP exists and is executable.
-.TP
-.B \-O \fIfile\fP
-True if \fIfile\fP exists and is owned by the effective user id.
-.TP
-.B \-G \fIfile\fP
-True if \fIfile\fP exists and is owned by the effective group id.
-.TP
-.B \-L \fIfile\fP
-True if \fIfile\fP exists and is a symbolic link.
-.TP
-.B \-S \fIfile\fP
-True if \fIfile\fP exists and is a socket.
-.TP
-.B \-N \fIfile\fP
-True if \fIfile\fP exists and has been modified since it was last read.
-.TP
-\fIfile1\fP \-\fBnt\fP \fIfile2\fP
-True if \fIfile1\fP is newer (according to modification date) than \fIfile2\fP,
-or if \fIfile1\fP exists and \fPfile2\fP does not.
-.TP
-\fIfile1\fP \-\fBot\fP \fIfile2\fP
-True if \fIfile1\fP is older than \fIfile2\fP, or if \fIfile2\fP exists
-and \fIfile1\fP does not.
-.TP
-\fIfile1\fP \fB\-ef\fP \fIfile2\fP
-True if \fIfile1\fP and \fIfile2\fP refer to the same device and
-inode numbers.
-.TP
-.B \-o \fIoptname\fP
-True if shell option
-.I optname
-is enabled.
-See the list of options under the description of the
-.B \-o
-option to the
-.B set
-builtin below.
-.TP
-.B \-z \fIstring\fP
-True if the length of \fIstring\fP is zero.
-.TP
-\fIstring\fP
-.PD 0
-.TP
-.B \-n \fIstring\fP
-.PD
-True if the length of
-.I string
-is non-zero.
-.TP
-\fIstring1\fP \fB==\fP \fIstring2\fP
-True if the strings are equal. \fB=\fP may be used in place of
-\fB==\fP for strict POSIX compliance.
-.TP
-\fIstring1\fP \fB!=\fP \fIstring2\fP
-True if the strings are not equal.
-.TP
-\fIstring1\fP \fB<\fP \fIstring2\fP
-True if \fIstring1\fP sorts before \fIstring2\fP lexicographically
-in the current locale.
-.TP
-\fIstring1\fP \fB>\fP \fIstring2\fP
-True if \fIstring1\fP sorts after \fIstring2\fP lexicographically
-in the current locale.
-.TP
-.I \fIarg1\fP \fBOP\fP \fIarg2\fP
-.SM
-.B OP
-is one of
-.BR \-eq ,
-.BR \-ne ,
-.BR \-lt ,
-.BR \-le ,
-.BR \-gt ,
-or
-.BR \-ge .
-These arithmetic binary operators return true if \fIarg1\fP
-is equal to, not equal to, less than, less than or equal to,
-greater than, or greater than or equal to \fIarg2\fP, respectively.
-.I Arg1
-and
-.I arg2
-may be positive or negative integers.
-.PD
-.SH "SIMPLE COMMAND EXPANSION"
-When a simple command is executed, the shell performs the following
-expansions, assignments, and redirections, from left to right.
-.IP 1.
-The words that the parser has marked as variable assignments (those
-preceding the command name) and redirections are saved for later
-processing.
-.IP 2.
-The words that are not variable assignments or redirections are
-expanded. If any words remain after expansion, the first word
-is taken to be the name of the command and the remaining words are
-the arguments.
-.IP 3.
-Redirections are performed as described above under
-.SM
-.BR REDIRECTION .
-.IP 4.
-The text after the \fB=\fP in each variable assignment undergoes tilde
-expansion, parameter expansion, command substitution, arithmetic expansion,
-and quote removal before being assigned to the variable.
-.PP
-If no command name results, the variable assignments affect the current
-shell environment. Otherwise, the variables are added to the environment
-of the executed command and do not affect the current shell environment.
-If any of the assignments attempts to assign a value to a readonly variable,
-an error occurs, and the command exits with a non-zero status.
-.PP
-If no command name results, redirections are performed, but do not
-affect the current shell environment. A redirection error causes the
-command to exit with a non-zero status.
-.PP
-If there is a command name left after expansion, execution proceeds as
-described below. Otherwise, the command exits. If one of the expansions
-contained a command substitution, the exit status of the command is
-the exit status of the last command substitution performed. If there
-were no command substitutions, the command exits with a status of zero.
-.SH "COMMAND EXECUTION"
-After a command has been split into words, if it results in a
-simple command and an optional list of arguments, the following
-actions are taken.
-.PP
-If the command name contains no slashes, the shell attempts to
-locate it. If there exists a shell function by that name, that
-function is invoked as described above in
-.SM
-.BR FUNCTIONS .
-If the name does not match a function, the shell searches for
-it in the list of shell builtins. If a match is found, that
-builtin is invoked.
-.PP
-If the name is neither a shell function nor a builtin,
-and contains no slashes,
-.B bash
-searches each element of the
-.SM
-.B PATH
-for a directory containing an executable file by that name.
-.B Bash
-uses a hash table to remember the full pathnames of executable
-files (see
-.B hash
-under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-A full search of the directories in
-.SM
-.B PATH
-is performed only if the command is not found in the hash table.
-If the search is unsuccessful, the shell prints an error
-message and returns an exit status of 127.
-.PP
-If the search is successful, or if the command name contains
-one or more slashes, the shell executes the named program in a
-separate execution environment.
-Argument 0 is set to the name given, and the remaining arguments
-to the command are set to the arguments given, if any.
-.PP
-If this execution fails because the file is not in executable
-format, and the file is not a directory, it is assumed to be
-a \fIshell script\fP, a file
-containing shell commands. A subshell is spawned to execute
-it. This subshell reinitializes itself, so
-that the effect is as if a new shell had been invoked
-to handle the script, with the exception that the locations of
-commands remembered by the parent (see
-.B hash
-below under
-.SM
-\fBSHELL BUILTIN COMMANDS\fP)
-are retained by the child.
-.PP
-If the program is a file beginning with
-.BR #! ,
-the remainder of the first line specifies an interpreter
-for the program. The shell executes the
-specified interpreter on operating systems that do not
-handle this executable format themselves. The arguments to the
-interpreter consist of a single optional argument following the
-interpreter name on the first line of the program, followed
-by the name of the program, followed by the command
-arguments, if any.
-.SH COMMAND EXECUTION ENVIRONMENT
-The shell has an \fIexecution environment\fP, which consists of the
-following:
-.sp 1
-.IP \(bu
-open files inherited by the shell at invocation, as modified by
-redirections supplied to the \fBexec\fP builtin
-.IP \(bu
-the current working directory as set by \fBcd\fP, \fBpushd\fP, or
-\fBpopd\fP, or inherited by the shell at invocation
-.IP \(bu
-the file creation mode mask as set by \fBumask\fP or inherited from
-the shell's parent
-.IP \(bu
-current traps set by \fBtrap\fP
-.IP \(bu
-shell parameters that are set by variable assignment or with \fBset\fP
-or inherited from the shell's parent in the environment
-.IP \(bu
-shell functions defined during execution or inherited from the shell's
-parent in the environment
-.IP \(bu
-options enabled at invocation (either by default or with command-line
-arguments) or by \fBset\fP
-.IP \(bu
-options enabled by \fBshopt\fP
-.IP \(bu
-shell aliases defined with \fBalias\fP
-.IP \(bu
-various process IDs, including those of background jobs, the value
-of \fB$$\fP, and the value of \fB$PPID\fP
-.PP
-When a simple command other than a builtin or shell function
-is to be executed, it
-is invoked in a separate execution environment that consists of
-the following. Unless otherwise noted, the values are inherited
-from the shell.
-.sp 1
-.IP \(bu
-the shell's open files, plus any modifications and additions specified
-by redirections to the command
-.IP \(bu
-the current working directory
-.IP \(bu
-the file creation mode mask
-.IP \(bu
-shell variables and functions marked for export, along with variables
-exported for the command, passed in the environment
-.IP \(bu
-traps caught by the shell are reset to the values inherited from the
-shell's parent, and traps ignored by the shell are ignored
-.PP
-A command invoked in this separate environment cannot affect the
-shell's execution environment.
-.PP
-Command substitution, commands grouped with parentheses,
-and asynchronous commands are invoked in a
-subshell environment that is a duplicate of the shell environment,
-except that traps caught by the shell are reset to the values
-that the shell inherited from its parent at invocation. Builtin
-commands that are invoked as part of a pipeline are also executed in a
-subshell environment. Changes made to the subshell environment
-cannot affect the shell's execution environment.
-.PP
-If a command is followed by a \fB&\fP and job control is not active, the
-default standard input for the command is the empty file \fI/dev/null\fP.
-Otherwise, the invoked command inherits the file descriptors of the calling
-shell as modified by redirections.
-.SH ENVIRONMENT
-When a program is invoked it is given an array of strings
-called the
-.IR environment .
-This is a list of
-\fIname\fP\-\fIvalue\fP pairs, of the form
-.IR "name\fR=\fPvalue" .
-.PP
-The shell provides several ways to manipulate the environment.
-On invocation, the shell scans its own environment and
-creates a parameter for each name found, automatically marking
-it for
-.I export
-to child processes. Executed commands inherit the environment.
-The
-.B export
-and
-.B declare \-x
-commands allow parameters and functions to be added to and
-deleted from the environment. If the value of a parameter
-in the environment is modified, the new value becomes part
-of the environment, replacing the old. The environment
-inherited by any executed command consists of the shell's
-initial environment, whose values may be modified in the shell,
-less any pairs removed by the
-.B unset
-command, plus any additions via the
-.B export
-and
-.B declare \-x
-commands.
-.PP
-The environment for any
-.I simple command
-or function may be augmented temporarily by prefixing it with
-parameter assignments, as described above in
-.SM
-.BR PARAMETERS .
-These assignment statements affect only the environment seen
-by that command.
-.PP
-If the
-.B \-k
-option is set (see the
-.B set
-builtin command below), then
-.I all
-parameter assignments are placed in the environment for a command,
-not just those that precede the command name.
-.PP
-When
-.B bash
-invokes an external command, the variable
-.B _
-is set to the full file name of the command and passed to that
-command in its environment.
-.SH "EXIT STATUS"
-For the shell's purposes, a command which exits with a
-zero exit status has succeeded. An exit status of zero
-indicates success. A non-zero exit status indicates failure.
-When a command terminates on a fatal signal \fIN\fP, \fBbash\fP uses
-the value of 128+\fIN\fP as the exit status.
-.PP
-If a command is not found, the child process created to
-execute it returns a status of 127. If a command is found
-but is not executable, the return status is 126.
-.PP
-If a command fails because of an error during expansion or redirection,
-the exit status is greater than zero.
-.PP
-Shell builtin commands return a status of 0 (\fItrue\fP) if
-successful, and non-zero (\fIfalse\fP) if an error occurs
-while they execute.
-All builtins return an exit status of 2 to indicate incorrect usage.
-.PP
-\fBBash\fP itself returns the exit status of the last command
-executed, unless a syntax error occurs, in which case it exits
-with a non-zero value. See also the \fBexit\fP builtin
-command below.
-.SH SIGNALS
-When \fBbash\fP is interactive, in the absence of any traps, it ignores
-.SM
-.B SIGTERM
-(so that \fBkill 0\fP does not kill an interactive shell),
-and
-.SM
-.B SIGINT
-is caught and handled (so that the \fBwait\fP builtin is interruptible).
-In all cases, \fBbash\fP ignores
-.SM
-.BR SIGQUIT .
-If job control is in effect,
-.B bash
-ignores
-.SM
-.BR SIGTTIN ,
-.SM
-.BR SIGTTOU ,
-and
-.SM
-.BR SIGTSTP .
-.PP
-Non-builtin commands run by \fBbash\fP have signal handlers
-set to the values inherited by the shell from its parent.
-When job control is not in effect, asynchronous commands
-ignore
-.SM
-.B SIGINT
-and
-.SM
-.B SIGQUIT
-in addition to these inherited handlers.
-Commands run as a result of command substitution ignore the
-keyboard-generated job control signals
-.SM
-.BR SIGTTIN ,
-.SM
-.BR SIGTTOU ,
-and
-.SM
-.BR SIGTSTP .
-.PP
-The shell exits by default upon receipt of a
-.SM
-.BR SIGHUP .
-Before exiting, an interactive shell resends the
-.SM
-.B SIGHUP
-to all jobs, running or stopped.
-Stopped jobs are sent
-.SM
-.B SIGCONT
-to ensure that they receive the
-.SM
-.BR SIGHUP .
-To prevent the shell from
-sending the signal to a particular job, it should be removed from the
-jobs table with the
-.B disown
-builtin (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below) or marked
-to not receive
-.SM
-.B SIGHUP
-using
-.BR "disown \-h" .
-.PP
-If the
-.B huponexit
-shell option has been set with
-.BR shopt ,
-.B bash
-sends a
-.SM
-.B SIGHUP
-to all jobs when an interactive login shell exits.
-.PP
-If \fBbash\fP is waiting for a command to complete and receives a signal
-for which a trap has been set, the trap will not be executed until
-the command completes.
-When \fBbash\fP is waiting for an asynchronous command via the \fBwait\fP
-builtin, the reception of a signal for which a trap has been set will
-cause the \fBwait\fP builtin to return immediately with an exit status
-greater than 128, immediately after which the trap is executed.
-.SH "JOB CONTROL"
-.I Job control
-refers to the ability to selectively stop (\fIsuspend\fP)
-the execution of processes and continue (\fIresume\fP)
-their execution at a later point. A user typically employs
-this facility via an interactive interface supplied jointly
-by the system's terminal driver and
-.BR bash .
-.PP
-The shell associates a
-.I job
-with each pipeline. It keeps a table of currently executing
-jobs, which may be listed with the
-.B jobs
-command. When
-.B bash
-starts a job asynchronously (in the
-.IR background ),
-it prints a line that looks like:
-.RS
-.PP
-[1] 25647
-.RE
-.PP
-indicating that this job is job number 1 and that the process ID
-of the last process in the pipeline associated with this job is 25647.
-All of the processes in a single pipeline are members of the same job.
-.B Bash
-uses the
-.I job
-abstraction as the basis for job control.
-.PP
-To facilitate the implementation of the user interface to job
-control, the operating system maintains the notion of a \fIcurrent terminal
-process group ID\fP. Members of this process group (processes whose
-process group ID is equal to the current terminal process group ID)
-receive keyboard-generated signals such as
-.SM
-.BR SIGINT .
-These processes are said to be in the
-.IR foreground .
-.I Background
-processes are those whose process group ID differs from the terminal's;
-such processes are immune to keyboard-generated signals.
-Only foreground processes are allowed to read from or write to the
-terminal. Background processes which attempt to read from (write to) the
-terminal are sent a
-.SM
-.B SIGTTIN (SIGTTOU)
-signal by the terminal driver,
-which, unless caught, suspends the process.
-.PP
-If the operating system on which
-.B bash
-is running supports
-job control,
-.B bash
-contains facilities to use it.
-Typing the
-.I suspend
-character (typically
-.BR ^Z ,
-Control-Z) while a process is running
-causes that process to be stopped and returns control to
-.BR bash .
-Typing the
-.I "delayed suspend"
-character (typically
-.BR ^Y ,
-Control-Y) causes the process to be stopped when it
-attempts to read input from the terminal, and control to
-be returned to
-.BR bash .
-The user may then manipulate the state of this job, using the
-.B bg
-command to continue it in the background, the
-.B fg
-command to continue it in the foreground, or
-the
-.B kill
-command to kill it. A \fB^Z\fP takes effect immediately,
-and has the additional side effect of causing pending output
-and typeahead to be discarded.
-.PP
-There are a number of ways to refer to a job in the shell.
-The character
-.B %
-introduces a job name. Job number
-.I n
-may be referred to as
-.BR %n .
-A job may also be referred to using a prefix of the name used to
-start it, or using a substring that appears in its command line.
-For example,
-.B %ce
-refers to a stopped
-.B ce
-job. If a prefix matches more than one job,
-.B bash
-reports an error. Using
-.BR %?ce ,
-on the other hand, refers to any job containing the string
-.B ce
-in its command line. If the substring matches more than one job,
-.B bash
-reports an error. The symbols
-.B %%
-and
-.B %+
-refer to the shell's notion of the
-.IR "current job" ,
-which is the last job stopped while it was in
-the foreground or started in the background.
-The
-.I "previous job"
-may be referenced using
-.BR %\- .
-In output pertaining to jobs (e.g., the output of the
-.B jobs
-command), the current job is always flagged with a
-.BR + ,
-and the previous job with a
-.BR \- .
-A single % (with no accompanying job specification) also refers to the
-current job.
-.PP
-Simply naming a job can be used to bring it into the
-foreground:
-.B %1
-is a synonym for
-\fB``fg %1''\fP,
-bringing job 1 from the background into the foreground.
-Similarly,
-.B ``%1 &''
-resumes job 1 in the background, equivalent to
-\fB``bg %1''\fP.
-.PP
-The shell learns immediately whenever a job changes state.
-Normally,
-.B bash
-waits until it is about to print a prompt before reporting
-changes in a job's status so as to not interrupt
-any other output. If the
-.B \-b
-option to the
-.B set
-builtin command
-is enabled,
-.B bash
-reports such changes immediately.
-Any trap on
-.SM
-.B SIGCHLD
-is executed for each child that exits.
-.PP
-If an attempt to exit
-.B bash
-is made while jobs are stopped, the shell prints a warning message. The
-.B jobs
-command may then be used to inspect their status.
-If a second attempt to exit is made without an intervening command,
-the shell does not print another warning, and the stopped
-jobs are terminated.
-.SH PROMPTING
-When executing interactively,
-.B bash
-displays the primary prompt
-.SM
-.B PS1
-when it is ready to read a command, and the secondary prompt
-.SM
-.B PS2
-when it needs more input to complete a command.
-.B Bash
-allows these prompt strings to be customized by inserting a number of
-backslash-escaped special characters that are decoded as follows:
-.RS
-.PD 0
-.TP
-.B \ea
-an ASCII bell character (07)
-.TP
-.B \ed
-the date in "Weekday Month Date" format (e.g., "Tue May 26")
-.TP
-.B \eD{\fIformat\fP}
-the \fIformat\fP is passed to \fIstrftime\fP(3) and the result is inserted
-into the prompt string; an empty \fIformat\fP results in a locale-specific
-time representation. The braces are required
-.TP
-.B \ee
-an ASCII escape character (033)
-.TP
-.B \eh
-the hostname up to the first `.'
-.TP
-.B \eH
-the hostname
-.TP
-.B \ej
-the number of jobs currently managed by the shell
-.TP
-.B \el
-the basename of the shell's terminal device name
-.TP
-.B \en
-newline
-.TP
-.B \er
-carriage return
-.TP
-.B \es
-the name of the shell, the basename of
-.B $0
-(the portion following the final slash)
-.TP
-.B \et
-the current time in 24-hour HH:MM:SS format
-.TP
-.B \eT
-the current time in 12-hour HH:MM:SS format
-.TP
-.B \e@
-the current time in 12-hour am/pm format
-.TP
-.B \eA
-the current time in 24-hour HH:MM format
-.TP
-.B \eu
-the username of the current user
-.TP
-.B \ev
-the version of \fBbash\fP (e.g., 2.00)
-.TP
-.B \eV
-the release of \fBbash\fP, version + patch level (e.g., 2.00.0)
-.TP
-.B \ew
-the current working directory, with \fB$HOME\fP abbreviated with a tilde
-.TP
-.B \eW
-the basename of the current working directory, with \fB$HOME\fP
-abbreviated with a tilde
-.TP
-.B \e!
-the history number of this command
-.TP
-.B \e#
-the command number of this command
-.TP
-.B \e$
-if the effective UID is 0, a
-.BR # ,
-otherwise a
-.B $
-.TP
-.B \e\fInnn\fP
-the character corresponding to the octal number \fInnn\fP
-.TP
-.B \e\e
-a backslash
-.TP
-.B \e[
-begin a sequence of non-printing characters, which could be used to
-embed a terminal control sequence into the prompt
-.TP
-.B \e]
-end a sequence of non-printing characters
-.PD
-.RE
-.PP
-The command number and the history number are usually different:
-the history number of a command is its position in the history
-list, which may include commands restored from the history file
-(see
-.SM
-.B HISTORY
-below), while the command number is the position in the sequence
-of commands executed during the current shell session.
-After the string is decoded, it is expanded via
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal, subject to the value of the
-.B promptvars
-shell option (see the description of the
-.B shopt
-command under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-.SH READLINE
-This is the library that handles reading input when using an interactive
-shell, unless the
-.B \-\-noediting
-option is given at shell invocation.
-By default, the line editing commands are similar to those of emacs.
-A vi-style line editing interface is also available.
-To turn off line editing after the shell is running, use the
-.B +o emacs
-or
-.B +o vi
-options to the
-.B set
-builtin (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SS "Readline Notation"
-.PP
-In this section, the emacs-style notation is used to denote
-keystrokes. Control keys are denoted by C\-\fIkey\fR, e.g., C\-n
-means Control\-N. Similarly,
-.I meta
-keys are denoted by M\-\fIkey\fR, so M\-x means Meta\-X. (On keyboards
-without a
-.I meta
-key, M\-\fIx\fP means ESC \fIx\fP, i.e., press the Escape key
-then the
-.I x
-key. This makes ESC the \fImeta prefix\fP.
-The combination M\-C\-\fIx\fP means ESC\-Control\-\fIx\fP,
-or press the Escape key
-then hold the Control key while pressing the
-.I x
-key.)
-.PP
-Readline commands may be given numeric
-.IR arguments ,
-which normally act as a repeat count.
-Sometimes, however, it is the sign of the argument that is significant.
-Passing a negative argument to a command that acts in the forward
-direction (e.g., \fBkill\-line\fP) causes that command to act in a
-backward direction.
-Commands whose behavior with arguments deviates from this are noted
-below.
-.PP
-When a command is described as \fIkilling\fP text, the text
-deleted is saved for possible future retrieval
-(\fIyanking\fP). The killed text is saved in a
-\fIkill ring\fP. Consecutive kills cause the text to be
-accumulated into one unit, which can be yanked all at once.
-Commands which do not kill text separate the chunks of text
-on the kill ring.
-.SS "Readline Initialization"
-.PP
-Readline is customized by putting commands in an initialization
-file (the \fIinputrc\fP file).
-The name of this file is taken from the value of the
-.SM
-.B INPUTRC
-variable. If that variable is unset, the default is
-.IR ~/.inputrc .
-When a program which uses the readline library starts up, the
-initialization file is read, and the key bindings and variables
-are set.
-There are only a few basic constructs allowed in the
-readline initialization file.
-Blank lines are ignored.
-Lines beginning with a \fB#\fP are comments.
-Lines beginning with a \fB$\fP indicate conditional constructs.
-Other lines denote key bindings and variable settings.
-.PP
-The default key-bindings may be changed with an
-.I inputrc
-file.
-Other programs that use this library may add their own commands
-and bindings.
-.PP
-For example, placing
-.RS
-.PP
-M\-Control\-u: universal\-argument
-.RE
-or
-.RS
-C\-Meta\-u: universal\-argument
-.RE
-into the
-.I inputrc
-would make M\-C\-u execute the readline command
-.IR universal\-argument .
-.PP
-The following symbolic character names are recognized:
-.IR RUBOUT ,
-.IR DEL ,
-.IR ESC ,
-.IR LFD ,
-.IR NEWLINE ,
-.IR RET ,
-.IR RETURN ,
-.IR SPC ,
-.IR SPACE ,
-and
-.IR TAB .
-.PP
-In addition to command names, readline allows keys to be bound
-to a string that is inserted when the key is pressed (a \fImacro\fP).
-.SS "Readline Key Bindings"
-.PP
-The syntax for controlling key bindings in the
-.I inputrc
-file is simple. All that is required is the name of the
-command or the text of a macro and a key sequence to which
-it should be bound. The name may be specified in one of two ways:
-as a symbolic key name, possibly with \fIMeta\-\fP or \fIControl\-\fP
-prefixes, or as a key sequence.
-.PP
-When using the form \fBkeyname\fP:\^\fIfunction\-name\fP or \fImacro\fP,
-.I keyname
-is the name of a key spelled out in English. For example:
-.sp
-.RS
-Control-u: universal\-argument
-.br
-Meta-Rubout: backward-kill-word
-.br
-Control-o: "> output"
-.RE
-.LP
-In the above example,
-.I C\-u
-is bound to the function
-.BR universal\-argument ,
-.I M\-DEL
-is bound to the function
-.BR backward\-kill\-word ,
-and
-.I C\-o
-is bound to run the macro
-expressed on the right hand side (that is, to insert the text
-.if t \f(CW> output\fP
-.if n ``> output''
-into the line).
-.PP
-In the second form, \fB"keyseq"\fP:\^\fIfunction\-name\fP or \fImacro\fP,
-.B keyseq
-differs from
-.B keyname
-above in that strings denoting
-an entire key sequence may be specified by placing the sequence
-within double quotes. Some GNU Emacs style key escapes can be
-used, as in the following example, but the symbolic character names
-are not recognized.
-.sp
-.RS
-"\eC\-u": universal\-argument
-.br
-"\eC\-x\eC\-r": re\-read\-init\-file
-.br
-"\ee[11~": "Function Key 1"
-.RE
-.PP
-In this example,
-.I C\-u
-is again bound to the function
-.BR universal\-argument .
-.I "C\-x C\-r"
-is bound to the function
-.BR re\-read\-init\-file ,
-and
-.I "ESC [ 1 1 ~"
-is bound to insert the text
-.if t \f(CWFunction Key 1\fP.
-.if n ``Function Key 1''.
-.PP
-The full set of GNU Emacs style escape sequences is
-.RS
-.PD 0
-.TP
-.B \eC\-
-control prefix
-.TP
-.B \eM\-
-meta prefix
-.TP
-.B \ee
-an escape character
-.TP
-.B \e\e
-backslash
-.TP
-.B \e"
-literal "
-.TP
-.B \e\(aq
-literal \(aq
-.RE
-.PD
-.PP
-In addition to the GNU Emacs style escape sequences, a second
-set of backslash escapes is available:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ed
-delete
-.TP
-.B \ef
-form feed
-.TP
-.B \en
-newline
-.TP
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP
-.B \ev
-vertical tab
-.TP
-.B \e\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(one to three digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.RE
-.PD
-.PP
-When entering the text of a macro, single or double quotes must
-be used to indicate a macro definition.
-Unquoted text is assumed to be a function name.
-In the macro body, the backslash escapes described above are expanded.
-Backslash will quote any other character in the macro text,
-including " and \(aq.
-.PP
-.B Bash
-allows the current readline key bindings to be displayed or modified
-with the
-.B bind
-builtin command. The editing mode may be switched during interactive
-use by using the
-.B \-o
-option to the
-.B set
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-.SS "Readline Variables"
-.PP
-Readline has variables that can be used to further customize its
-behavior. A variable may be set in the
-.I inputrc
-file with a statement of the form
-.RS
-.PP
-\fBset\fP \fIvariable\-name\fP \fIvalue\fP
-.RE
-.PP
-Except where noted, readline variables can take the values
-.B On
-or
-.B Off
-(without regard to case).
-Unrecognized variable names are ignored.
-When a variable value is read, empty or null values, "on" (case-insensitive),
-and "1" are equivalent to \fBOn\fP. All other values are equivalent to
-\fBOff\fP.
-The variables and their default values are:
-.PP
-.PD 0
-.TP
-.B bell\-style (audible)
-Controls what happens when readline wants to ring the terminal bell.
-If set to \fBnone\fP, readline never rings the bell. If set to
-\fBvisible\fP, readline uses a visible bell if one is available.
-If set to \fBaudible\fP, readline attempts to ring the terminal's bell.
-.TP
-.B bind\-tty\-special\-chars (On)
-If set to \fBOn\fP, readline attempts to bind the control characters
-treated specially by the kernel's terminal driver to their readline
-equivalents.
-.TP
-.B comment\-begin (``#'')
-The string that is inserted when the readline
-.B insert\-comment
-command is executed.
-This command is bound to
-.B M\-#
-in emacs mode and to
-.B #
-in vi command mode.
-.TP
-.B completion\-ignore\-case (Off)
-If set to \fBOn\fP, readline performs filename matching and completion
-in a case\-insensitive fashion.
-.TP
-.B completion\-query\-items (100)
-This determines when the user is queried about viewing
-the number of possible completions
-generated by the \fBpossible\-completions\fP command.
-It may be set to any integer value greater than or equal to
-zero. If the number of possible completions is greater than
-or equal to the value of this variable, the user is asked whether
-or not he wishes to view them; otherwise they are simply listed
-on the terminal.
-.TP
-.B convert\-meta (On)
-If set to \fBOn\fP, readline will convert characters with the
-eighth bit set to an ASCII key sequence
-by stripping the eighth bit and prefixing an
-escape character (in effect, using escape as the \fImeta prefix\fP).
-.TP
-.B disable\-completion (Off)
-If set to \fBOn\fP, readline will inhibit word completion. Completion
-characters will be inserted into the line as if they had been
-mapped to \fBself-insert\fP.
-.TP
-.B editing\-mode (emacs)
-Controls whether readline begins with a set of key bindings similar
-to \fIemacs\fP or \fIvi\fP.
-.B editing\-mode
-can be set to either
-.B emacs
-or
-.BR vi .
-.TP
-.B enable\-keypad (Off)
-When set to \fBOn\fP, readline will try to enable the application
-keypad when it is called. Some systems need this to enable the
-arrow keys.
-.TP
-.B expand\-tilde (Off)
-If set to \fBon\fP, tilde expansion is performed when readline
-attempts word completion.
-.TP
-.B history\-preserve\-point (Off)
-If set to \fBon\fP, the history code attempts to place point at the
-same location on each history line retrieved with \fBprevious-history\fP
-or \fBnext-history\fP.
-.TP
-.B horizontal\-scroll\-mode (Off)
-When set to \fBOn\fP, makes readline use a single line for display,
-scrolling the input horizontally on a single screen line when it
-becomes longer than the screen width rather than wrapping to a new line.
-.TP
-.B input\-meta (Off)
-If set to \fBOn\fP, readline will enable eight-bit input (that is,
-it will not strip the high bit from the characters it reads),
-regardless of what the terminal claims it can support. The name
-.B meta\-flag
-is a synonym for this variable.
-.TP
-.B isearch\-terminators (``C\-[C\-J'')
-The string of characters that should terminate an incremental
-search without subsequently executing the character as a command.
-If this variable has not been given a value, the characters
-\fIESC\fP and \fIC\-J\fP will terminate an incremental search.
-.TP
-.B keymap (emacs)
-Set the current readline keymap. The set of valid keymap names is
-\fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi,
-vi\-command\fP, and
-.IR vi\-insert .
-\fIvi\fP is equivalent to \fIvi\-command\fP; \fIemacs\fP is
-equivalent to \fIemacs\-standard\fP. The default value is
-.IR emacs ;
-the value of
-.B editing\-mode
-also affects the default keymap.
-.TP
-.B mark\-directories (On)
-If set to \fBOn\fP, completed directory names have a slash
-appended.
-.TP
-.B mark\-modified\-lines (Off)
-If set to \fBOn\fP, history lines that have been modified are displayed
-with a preceding asterisk (\fB*\fP).
-.TP
-.B mark\-symlinked\-directories (Off)
-If set to \fBOn\fP, completed names which are symbolic links to directories
-have a slash appended (subject to the value of
-\fBmark\-directories\fP).
-.TP
-.B match\-hidden\-files (On)
-This variable, when set to \fBOn\fP, causes readline to match files whose
-names begin with a `.' (hidden files) when performing filename
-completion, unless the leading `.' is
-supplied by the user in the filename to be completed.
-.TP
-.B output\-meta (Off)
-If set to \fBOn\fP, readline will display characters with the
-eighth bit set directly rather than as a meta-prefixed escape
-sequence.
-.TP
-.B page\-completions (On)
-If set to \fBOn\fP, readline uses an internal \fImore\fP-like pager
-to display a screenful of possible completions at a time.
-.TP
-.B print\-completions\-horizontally (Off)
-If set to \fBOn\fP, readline will display completions with matches
-sorted horizontally in alphabetical order, rather than down the screen.
-.TP
-.B show\-all\-if\-ambiguous (Off)
-This alters the default behavior of the completion functions. If
-set to
-.BR on ,
-words which have more than one possible completion cause the
-matches to be listed immediately instead of ringing the bell.
-.TP
-.B show\-all\-if\-unmodified (Off)
-This alters the default behavior of the completion functions in
-a fashion similar to \fBshow\-all\-if\-ambiguous\fP.
-If set to
-.BR on ,
-words which have more than one possible completion without any
-possible partial completion (the possible completions don't share
-a common prefix) cause the matches to be listed immediately instead
-of ringing the bell.
-.TP
-.B visible\-stats (Off)
-If set to \fBOn\fP, a character denoting a file's type as reported
-by \fIstat\fP(2) is appended to the filename when listing possible
-completions.
-.PD
-.SS "Readline Conditional Constructs"
-.PP
-Readline implements a facility similar in spirit to the conditional
-compilation features of the C preprocessor which allows key
-bindings and variable settings to be performed as the result
-of tests. There are four parser directives used.
-.IP \fB$if\fP
-The
-.B $if
-construct allows bindings to be made based on the
-editing mode, the terminal being used, or the application using
-readline. The text of the test extends to the end of the line;
-no characters are required to isolate it.
-.RS
-.IP \fBmode\fP
-The \fBmode=\fP form of the \fB$if\fP directive is used to test
-whether readline is in emacs or vi mode.
-This may be used in conjunction
-with the \fBset keymap\fP command, for instance, to set bindings in
-the \fIemacs\-standard\fP and \fIemacs\-ctlx\fP keymaps only if
-readline is starting out in emacs mode.
-.IP \fBterm\fP
-The \fBterm=\fP form may be used to include terminal-specific
-key bindings, perhaps to bind the key sequences output by the
-terminal's function keys. The word on the right side of the
-.B =
-is tested against the both full name of the terminal and the portion
-of the terminal name before the first \fB\-\fP. This allows
-.I sun
-to match both
-.I sun
-and
-.IR sun\-cmd ,
-for instance.
-.IP \fBapplication\fP
-The \fBapplication\fP construct is used to include
-application-specific settings. Each program using the readline
-library sets the \fIapplication name\fP, and an initialization
-file can test for a particular value.
-This could be used to bind key sequences to functions useful for
-a specific program. For instance, the following command adds a
-key sequence that quotes the current or previous word in Bash:
-.sp 1
-.RS
-.nf
-\fB$if\fP Bash
-# Quote the current or previous word
-"\eC\-xq": "\eeb\e"\eef\e""
-\fB$endif\fP
-.fi
-.RE
-.RE
-.IP \fB$endif\fP
-This command, as seen in the previous example, terminates an
-\fB$if\fP command.
-.IP \fB$else\fP
-Commands in this branch of the \fB$if\fP directive are executed if
-the test fails.
-.IP \fB$include\fP
-This directive takes a single filename as an argument and reads commands
-and bindings from that file. For example, the following directive
-would read \fI/etc/inputrc\fP:
-.sp 1
-.RS
-.nf
-\fB$include\fP \^ \fI/etc/inputrc\fP
-.fi
-.RE
-.SS Searching
-.PP
-Readline provides commands for searching through the command history
-(see
-.SM
-.B HISTORY
-below) for lines containing a specified string.
-There are two search modes:
-.I incremental
-and
-.IR non-incremental .
-.PP
-Incremental searches begin before the user has finished typing the
-search string.
-As each character of the search string is typed, readline displays
-the next entry from the history matching the string typed so far.
-An incremental search requires only as many characters as needed to
-find the desired history entry.
-The characters present in the value of the \fBisearch-terminators\fP
-variable are used to terminate an incremental search.
-If that variable has not been assigned a value the Escape and
-Control-J characters will terminate an incremental search.
-Control-G will abort an incremental search and restore the original
-line.
-When the search is terminated, the history entry containing the
-search string becomes the current line.
-.PP
-To find other matching entries in the history list, type Control-S or
-Control-R as appropriate.
-This will search backward or forward in the history for the next
-entry matching the search string typed so far.
-Any other key sequence bound to a readline command will terminate
-the search and execute that command.
-For instance, a \fInewline\fP will terminate the search and accept
-the line, thereby executing the command from the history list.
-.PP
-Readline remembers the last incremental search string. If two
-Control-Rs are typed without any intervening characters defining a
-new search string, any remembered search string is used.
-.PP
-Non-incremental searches read the entire search string before starting
-to search for matching history lines. The search string may be
-typed by the user or be part of the contents of the current line.
-.SS "Readline Command Names"
-.PP
-The following is a list of the names of the commands and the default
-key sequences to which they are bound.
-Command names without an accompanying key sequence are unbound by default.
-In the following descriptions, \fIpoint\fP refers to the current cursor
-position, and \fImark\fP refers to a cursor position saved by the
-\fBset\-mark\fP command.
-The text between the point and mark is referred to as the \fIregion\fP.
-.SS Commands for Moving
-.PP
-.PD 0
-.TP
-.B beginning\-of\-line (C\-a)
-Move to the start of the current line.
-.TP
-.B end\-of\-line (C\-e)
-Move to the end of the line.
-.TP
-.B forward\-char (C\-f)
-Move forward a character.
-.TP
-.B backward\-char (C\-b)
-Move back a character.
-.TP
-.B forward\-word (M\-f)
-Move forward to the end of the next word. Words are composed of
-alphanumeric characters (letters and digits).
-.TP
-.B backward\-word (M\-b)
-Move back to the start of the current or previous word. Words are
-composed of alphanumeric characters (letters and digits).
-.TP
-.B clear\-screen (C\-l)
-Clear the screen leaving the current line at the top of the screen.
-With an argument, refresh the current line without clearing the
-screen.
-.TP
-.B redraw\-current\-line
-Refresh the current line.
-.PD
-.SS Commands for Manipulating the History
-.PP
-.PD 0
-.TP
-.B accept\-line (Newline, Return)
-Accept the line regardless of where the cursor is. If this line is
-non-empty, add it to the history list according to the state of the
-.SM
-.B HISTCONTROL
-variable. If the line is a modified history
-line, then restore the history line to its original state.
-.TP
-.B previous\-history (C\-p)
-Fetch the previous command from the history list, moving back in
-the list.
-.TP
-.B next\-history (C\-n)
-Fetch the next command from the history list, moving forward in the
-list.
-.TP
-.B beginning\-of\-history (M\-<)
-Move to the first line in the history.
-.TP
-.B end\-of\-history (M\->)
-Move to the end of the input history, i.e., the line currently being
-entered.
-.TP
-.B reverse\-search\-history (C\-r)
-Search backward starting at the current line and moving `up' through
-the history as necessary. This is an incremental search.
-.TP
-.B forward\-search\-history (C\-s)
-Search forward starting at the current line and moving `down' through
-the history as necessary. This is an incremental search.
-.TP
-.B non\-incremental\-reverse\-search\-history (M\-p)
-Search backward through the history starting at the current line
-using a non-incremental search for a string supplied by the user.
-.TP
-.B non\-incremental\-forward\-search\-history (M\-n)
-Search forward through the history using a non-incremental search for
-a string supplied by the user.
-.TP
-.B history\-search\-forward
-Search forward through the history for the string of characters
-between the start of the current line and the point.
-This is a non-incremental search.
-.TP
-.B history\-search\-backward
-Search backward through the history for the string of characters
-between the start of the current line and the point.
-This is a non-incremental search.
-.TP
-.B yank\-nth\-arg (M\-C\-y)
-Insert the first argument to the previous command (usually
-the second word on the previous line) at point.
-With an argument
-.IR n ,
-insert the \fIn\fPth word from the previous command (the words
-in the previous command begin with word 0). A negative argument
-inserts the \fIn\fPth word from the end of the previous command.
-Once the argument \fIn\fP is computed, the argument is extracted
-as if the "!\fIn\fP" history expansion had been specified.
-.TP
-.B
-yank\-last\-arg (M\-.\^, M\-_\^)
-Insert the last argument to the previous command (the last word of
-the previous history entry). With an argument,
-behave exactly like \fByank\-nth\-arg\fP.
-Successive calls to \fByank\-last\-arg\fP move back through the history
-list, inserting the last argument of each line in turn.
-The history expansion facilities are used to extract the last argument,
-as if the "!$" history expansion had been specified.
-.TP
-.B shell\-expand\-line (M\-C\-e)
-Expand the line as the shell does. This
-performs alias and history expansion as well as all of the shell
-word expansions. See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B history\-expand\-line (M\-^)
-Perform history expansion on the current line.
-See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B magic\-space
-Perform history expansion on the current line and insert a space.
-See
-.SM
-.B HISTORY EXPANSION
-below for a description of history expansion.
-.TP
-.B alias\-expand\-line
-Perform alias expansion on the current line.
-See
-.SM
-.B ALIASES
-above for a description of alias expansion.
-.TP
-.B history\-and\-alias\-expand\-line
-Perform history and alias expansion on the current line.
-.TP
-.B insert\-last\-argument (M\-.\^, M\-_\^)
-A synonym for \fByank\-last\-arg\fP.
-.TP
-.B operate\-and\-get\-next (C\-o)
-Accept the current line for execution and fetch the next line
-relative to the current line from the history for editing. Any
-argument is ignored.
-.TP
-.B edit\-and\-execute\-command (C\-xC\-e)
-Invoke an editor on the current command line, and execute the result as shell
-commands.
-\fBBash\fP attempts to invoke
-.SM
-.BR $FCEDIT ,
-.SM
-.BR $EDITOR ,
-and \fIemacs\fP as the editor, in that order.
-.PD
-.SS Commands for Changing Text
-.PP
-.PD 0
-.TP
-.B delete\-char (C\-d)
-Delete the character at point. If point is at the
-beginning of the line, there are no characters in the line, and
-the last character typed was not bound to \fBdelete\-char\fP,
-then return
-.SM
-.BR EOF .
-.TP
-.B backward\-delete\-char (Rubout)
-Delete the character behind the cursor. When given a numeric argument,
-save the deleted text on the kill ring.
-.TP
-.B forward\-backward\-delete\-char
-Delete the character under the cursor, unless the cursor is at the
-end of the line, in which case the character behind the cursor is
-deleted.
-.TP
-.B quoted\-insert (C\-q, C\-v)
-Add the next character typed to the line verbatim. This is
-how to insert characters like \fBC\-q\fP, for example.
-.TP
-.B tab\-insert (C\-v TAB)
-Insert a tab character.
-.TP
-.B self\-insert (a,\ b,\ A,\ 1,\ !,\ ...)
-Insert the character typed.
-.TP
-.B transpose\-chars (C\-t)
-Drag the character before point forward over the character at point,
-moving point forward as well.
-If point is at the end of the line, then this transposes
-the two characters before point.
-Negative arguments have no effect.
-.TP
-.B transpose\-words (M\-t)
-Drag the word before point past the word after point,
-moving point over that word as well.
-If point is at the end of the line, this transposes
-the last two words on the line.
-.TP
-.B upcase\-word (M\-u)
-Uppercase the current (or following) word. With a negative argument,
-uppercase the previous word, but do not move point.
-.TP
-.B downcase\-word (M\-l)
-Lowercase the current (or following) word. With a negative argument,
-lowercase the previous word, but do not move point.
-.TP
-.B capitalize\-word (M\-c)
-Capitalize the current (or following) word. With a negative argument,
-capitalize the previous word, but do not move point.
-.TP
-.B overwrite\-mode
-Toggle overwrite mode. With an explicit positive numeric argument,
-switches to overwrite mode. With an explicit non-positive numeric
-argument, switches to insert mode. This command affects only
-\fBemacs\fP mode; \fBvi\fP mode does overwrite differently.
-Each call to \fIreadline()\fP starts in insert mode.
-In overwrite mode, characters bound to \fBself\-insert\fP replace
-the text at point rather than pushing the text to the right.
-Characters bound to \fBbackward\-delete\-char\fP replace the character
-before point with a space. By default, this command is unbound.
-.PD
-.SS Killing and Yanking
-.PP
-.PD 0
-.TP
-.B kill\-line (C\-k)
-Kill the text from point to the end of the line.
-.TP
-.B backward\-kill\-line (C\-x Rubout)
-Kill backward to the beginning of the line.
-.TP
-.B unix\-line\-discard (C\-u)
-Kill backward from point to the beginning of the line.
-The killed text is saved on the kill-ring.
-.\" There is no real difference between this and backward-kill-line
-.TP
-.B kill\-whole\-line
-Kill all characters on the current line, no matter where point is.
-.TP
-.B kill\-word (M\-d)
-Kill from point to the end of the current word, or if between
-words, to the end of the next word.
-Word boundaries are the same as those used by \fBforward\-word\fP.
-.TP
-.B backward\-kill\-word (M\-Rubout)
-Kill the word behind point.
-Word boundaries are the same as those used by \fBbackward\-word\fP.
-.TP
-.B unix\-word\-rubout (C\-w)
-Kill the word behind point, using white space as a word boundary.
-The killed text is saved on the kill-ring.
-.TP
-.B unix\-filename\-rubout
-Kill the word behind point, using white space and the slash character
-as the word boundaries.
-The killed text is saved on the kill-ring.
-.TP
-.B delete\-horizontal\-space (M\-\e)
-Delete all spaces and tabs around point.
-.TP
-.B kill\-region
-Kill the text in the current region.
-.TP
-.B copy\-region\-as\-kill
-Copy the text in the region to the kill buffer.
-.TP
-.B copy\-backward\-word
-Copy the word before point to the kill buffer.
-The word boundaries are the same as \fBbackward\-word\fP.
-.TP
-.B copy\-forward\-word
-Copy the word following point to the kill buffer.
-The word boundaries are the same as \fBforward\-word\fP.
-.TP
-.B yank (C\-y)
-Yank the top of the kill ring into the buffer at point.
-.TP
-.B yank\-pop (M\-y)
-Rotate the kill ring, and yank the new top. Only works following
-.B yank
-or
-.BR yank\-pop .
-.PD
-.SS Numeric Arguments
-.PP
-.PD 0
-.TP
-.B digit\-argument (M\-0, M\-1, ..., M\-\-)
-Add this digit to the argument already accumulating, or start a new
-argument. M\-\- starts a negative argument.
-.TP
-.B universal\-argument
-This is another way to specify an argument.
-If this command is followed by one or more digits, optionally with a
-leading minus sign, those digits define the argument.
-If the command is followed by digits, executing
-.B universal\-argument
-again ends the numeric argument, but is otherwise ignored.
-As a special case, if this command is immediately followed by a
-character that is neither a digit or minus sign, the argument count
-for the next command is multiplied by four.
-The argument count is initially one, so executing this function the
-first time makes the argument count four, a second time makes the
-argument count sixteen, and so on.
-.PD
-.SS Completing
-.PP
-.PD 0
-.TP
-.B complete (TAB)
-Attempt to perform completion on the text before point.
-.B Bash
-attempts completion treating the text as a variable (if the
-text begins with \fB$\fP), username (if the text begins with
-\fB~\fP), hostname (if the text begins with \fB@\fP), or
-command (including aliases and functions) in turn. If none
-of these produces a match, filename completion is attempted.
-.TP
-.B possible\-completions (M\-?)
-List the possible completions of the text before point.
-.TP
-.B insert\-completions (M\-*)
-Insert all completions of the text before point
-that would have been generated by
-\fBpossible\-completions\fP.
-.TP
-.B menu\-complete
-Similar to \fBcomplete\fP, but replaces the word to be completed
-with a single match from the list of possible completions.
-Repeated execution of \fBmenu\-complete\fP steps through the list
-of possible completions, inserting each match in turn.
-At the end of the list of completions, the bell is rung
-(subject to the setting of \fBbell\-style\fP)
-and the original text is restored.
-An argument of \fIn\fP moves \fIn\fP positions forward in the list
-of matches; a negative argument may be used to move backward
-through the list.
-This command is intended to be bound to \fBTAB\fP, but is unbound
-by default.
-.TP
-.B delete\-char\-or\-list
-Deletes the character under the cursor if not at the beginning or
-end of the line (like \fBdelete\-char\fP).
-If at the end of the line, behaves identically to
-\fBpossible\-completions\fP.
-This command is unbound by default.
-.TP
-.B complete\-filename (M\-/)
-Attempt filename completion on the text before point.
-.TP
-.B possible\-filename\-completions (C\-x /)
-List the possible completions of the text before point,
-treating it as a filename.
-.TP
-.B complete\-username (M\-~)
-Attempt completion on the text before point, treating
-it as a username.
-.TP
-.B possible\-username\-completions (C\-x ~)
-List the possible completions of the text before point,
-treating it as a username.
-.TP
-.B complete\-variable (M\-$)
-Attempt completion on the text before point, treating
-it as a shell variable.
-.TP
-.B possible\-variable\-completions (C\-x $)
-List the possible completions of the text before point,
-treating it as a shell variable.
-.TP
-.B complete\-hostname (M\-@)
-Attempt completion on the text before point, treating
-it as a hostname.
-.TP
-.B possible\-hostname\-completions (C\-x @)
-List the possible completions of the text before point,
-treating it as a hostname.
-.TP
-.B complete\-command (M\-!)
-Attempt completion on the text before point, treating
-it as a command name. Command completion attempts to
-match the text against aliases, reserved words, shell
-functions, shell builtins, and finally executable filenames,
-in that order.
-.TP
-.B possible\-command\-completions (C\-x !)
-List the possible completions of the text before point,
-treating it as a command name.
-.TP
-.B dynamic\-complete\-history (M\-TAB)
-Attempt completion on the text before point, comparing
-the text against lines from the history list for possible
-completion matches.
-.TP
-.B complete\-into\-braces (M\-{)
-Perform filename completion and insert the list of possible completions
-enclosed within braces so the list is available to the shell (see
-.B Brace Expansion
-above).
-.PD
-.SS Keyboard Macros
-.PP
-.PD 0
-.TP
-.B start\-kbd\-macro (C\-x (\^)
-Begin saving the characters typed into the current keyboard macro.
-.TP
-.B end\-kbd\-macro (C\-x )\^)
-Stop saving the characters typed into the current keyboard macro
-and store the definition.
-.TP
-.B call\-last\-kbd\-macro (C\-x e)
-Re-execute the last keyboard macro defined, by making the characters
-in the macro appear as if typed at the keyboard.
-.PD
-.SS Miscellaneous
-.PP
-.PD 0
-.TP
-.B re\-read\-init\-file (C\-x C\-r)
-Read in the contents of the \fIinputrc\fP file, and incorporate
-any bindings or variable assignments found there.
-.TP
-.B abort (C\-g)
-Abort the current editing command and
-ring the terminal's bell (subject to the setting of
-.BR bell\-style ).
-.TP
-.B do\-uppercase\-version (M\-a, M\-b, M\-\fIx\fP, ...)
-If the metafied character \fIx\fP is lowercase, run the command
-that is bound to the corresponding uppercase character.
-.TP
-.B prefix\-meta (ESC)
-Metafy the next character typed.
-.SM
-.B ESC
-.B f
-is equivalent to
-.BR Meta\-f .
-.TP
-.B undo (C\-_, C\-x C\-u)
-Incremental undo, separately remembered for each line.
-.TP
-.B revert\-line (M\-r)
-Undo all changes made to this line. This is like executing the
-.B undo
-command enough times to return the line to its initial state.
-.TP
-.B tilde\-expand (M\-&)
-Perform tilde expansion on the current word.
-.TP
-.B set\-mark (C\-@, M\-<space>)
-Set the mark to the point. If a
-numeric argument is supplied, the mark is set to that position.
-.TP
-.B exchange\-point\-and\-mark (C\-x C\-x)
-Swap the point with the mark. The current cursor position is set to
-the saved position, and the old cursor position is saved as the mark.
-.TP
-.B character\-search (C\-])
-A character is read and point is moved to the next occurrence of that
-character. A negative count searches for previous occurrences.
-.TP
-.B character\-search\-backward (M\-C\-])
-A character is read and point is moved to the previous occurrence of that
-character. A negative count searches for subsequent occurrences.
-.TP
-.B insert\-comment (M\-#)
-Without a numeric argument, the value of the readline
-.B comment\-begin
-variable is inserted at the beginning of the current line.
-If a numeric argument is supplied, this command acts as a toggle: if
-the characters at the beginning of the line do not match the value
-of \fBcomment\-begin\fP, the value is inserted, otherwise
-the characters in \fBcomment-begin\fP are deleted from the beginning of
-the line.
-In either case, the line is accepted as if a newline had been typed.
-The default value of
-\fBcomment\-begin\fP causes this command to make the current line
-a shell comment.
-If a numeric argument causes the comment character to be removed, the line
-will be executed by the shell.
-.TP
-.B glob\-complete\-word (M\-g)
-The word before point is treated as a pattern for pathname expansion,
-with an asterisk implicitly appended. This pattern is used to
-generate a list of matching file names for possible completions.
-.TP
-.B glob\-expand\-word (C\-x *)
-The word before point is treated as a pattern for pathname expansion,
-and the list of matching file names is inserted, replacing the word.
-If a numeric argument is supplied, an asterisk is appended before
-pathname expansion.
-.TP
-.B glob\-list\-expansions (C\-x g)
-The list of expansions that would have been generated by
-.B glob\-expand\-word
-is displayed, and the line is redrawn.
-If a numeric argument is supplied, an asterisk is appended before
-pathname expansion.
-.TP
-.B dump\-functions
-Print all of the functions and their key bindings to the
-readline output stream. If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B dump\-variables
-Print all of the settable readline variables and their values to the
-readline output stream. If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B dump\-macros
-Print all of the readline key sequences bound to macros and the
-strings they output. If a numeric argument is supplied,
-the output is formatted in such a way that it can be made part
-of an \fIinputrc\fP file.
-.TP
-.B display\-shell\-version (C\-x C\-v)
-Display version information about the current instance of
-.BR bash .
-.PD
-.SS Programmable Completion
-.PP
-When word completion is attempted for an argument to a command for
-which a completion specification (a \fIcompspec\fP) has been defined
-using the \fBcomplete\fP builtin (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), the programmable completion facilities are invoked.
-.PP
-First, the command name is identified.
-If a compspec has been defined for that command, the
-compspec is used to generate the list of possible completions for the word.
-If the command word is a full pathname, a compspec for the full
-pathname is searched for first.
-If no compspec is found for the full pathname, an attempt is made to
-find a compspec for the portion following the final slash.
-.PP
-Once a compspec has been found, it is used to generate the list of
-matching words.
-If a compspec is not found, the default \fBbash\fP completion as
-described above under \fBCompleting\fP is performed.
-.PP
-First, the actions specified by the compspec are used.
-Only matches which are prefixed by the word being completed are
-returned.
-When the
-.B \-f
-or
-.B \-d
-option is used for filename or directory name completion, the shell
-variable
-.SM
-.B FIGNORE
-is used to filter the matches.
-.PP
-Any completions specified by a filename expansion pattern to the
-\fB\-G\fP option are generated next.
-The words generated by the pattern need not match the word
-being completed.
-The
-.SM
-.B GLOBIGNORE
-shell variable is not used to filter the matches, but the
-.SM
-.B FIGNORE
-variable is used.
-.PP
-Next, the string specified as the argument to the \fB\-W\fP option
-is considered.
-The string is first split using the characters in the
-.SM
-.B IFS
-special variable as delimiters.
-Shell quoting is honored.
-Each word is then expanded using
-brace expansion, tilde expansion, parameter and variable expansion,
-command substitution, and arithmetic expansion,
-as described above under
-.SM
-.BR EXPANSION .
-The results are split using the rules described above under
-\fBWord Splitting\fP.
-The results of the expansion are prefix-matched against the word being
-completed, and the matching words become the possible completions.
-.PP
-After these matches have been generated, any shell function or command
-specified with the \fB\-F\fP and \fB\-C\fP options is invoked.
-When the command or function is invoked, the
-.SM
-.B COMP_LINE
-and
-.SM
-.B COMP_POINT
-variables are assigned values as described above under
-\fBShell Variables\fP.
-If a shell function is being invoked, the
-.SM
-.B COMP_WORDS
-and
-.SM
-.B COMP_CWORD
-variables are also set.
-When the function or command is invoked, the first argument is the
-name of the command whose arguments are being completed, the
-second argument is the word being completed, and the third argument
-is the word preceding the word being completed on the current command line.
-No filtering of the generated completions against the word being completed
-is performed; the function or command has complete freedom in generating
-the matches.
-.PP
-Any function specified with \fB\-F\fP is invoked first.
-The function may use any of the shell facilities, including the
-\fBcompgen\fP builtin described below, to generate the matches.
-It must put the possible completions in the
-.SM
-.B COMPREPLY
-array variable.
-.PP
-Next, any command specified with the \fB\-C\fP option is invoked
-in an environment equivalent to command substitution.
-It should print a list of completions, one per line, to the
-standard output.
-Backslash may be used to escape a newline, if necessary.
-.PP
-After all of the possible completions are generated, any filter
-specified with the \fB\-X\fP option is applied to the list.
-The filter is a pattern as used for pathname expansion; a \fB&\fP
-in the pattern is replaced with the text of the word being completed.
-A literal \fB&\fP may be escaped with a backslash; the backslash
-is removed before attempting a match.
-Any completion that matches the pattern will be removed from the list.
-A leading \fB!\fP negates the pattern; in this case any completion
-not matching the pattern will be removed.
-.PP
-Finally, any prefix and suffix specified with the \fB\-P\fP and \fB\-S\fP
-options are added to each member of the completion list, and the result is
-returned to the readline completion code as the list of possible
-completions.
-.PP
-If the previously-applied actions do not generate any matches, and the
-\fB\-o dirnames\fP option was supplied to \fBcomplete\fP when the
-compspec was defined, directory name completion is attempted.
-.PP
-If the \fB\-o plusdirs\fP option was supplied to \fBcomplete\fP when the
-compspec was defined, directory name completion is attempted and any
-matches are added to the results of the other actions.
-.PP
-By default, if a compspec is found, whatever it generates is returned
-to the completion code as the full set of possible completions.
-The default \fBbash\fP completions are not attempted, and the readline
-default of filename completion is disabled.
-If the \fB\-o bashdefault\fP option was supplied to \fBcomplete\fP when
-the compspec was defined, the \fBbash\fP default completions are attempted
-if the compspec generates no matches.
-If the \fB\-o default\fP option was supplied to \fBcomplete\fP when the
-compspec was defined, readline's default completion will be performed
-if the compspec (and, if attempted, the default \fBbash\fP completions)
-generate no matches.
-.PP
-When a compspec indicates that directory name completion is desired,
-the programmable completion functions force readline to append a slash
-to completed names which are symbolic links to directories, subject to
-the value of the \fBmark\-directories\fP readline variable, regardless
-of the setting of the \fBmark-symlinked\-directories\fP readline variable.
-.SH HISTORY
-When the
-.B \-o history
-option to the
-.B set
-builtin is enabled, the shell provides access to the
-\fIcommand history\fP,
-the list of commands previously typed.
-The value of the \fBHISTSIZE\fP variable is used as the
-number of commands to save in a history list.
-The text of the last
-.SM
-.B HISTSIZE
-commands (default 500) is saved. The shell
-stores each command in the history list prior to parameter and
-variable expansion (see
-.SM
-.B EXPANSION
-above) but after history expansion is performed, subject to the
-values of the shell variables
-.SM
-.B HISTIGNORE
-and
-.SM
-.BR HISTCONTROL .
-.PP
-On startup, the history is initialized from the file named by
-the variable
-.SM
-.B HISTFILE
-(default \fI~/.bash_history\fP).
-The file named by the value of
-.SM
-.B HISTFILE
-is truncated, if necessary, to contain no more than
-the number of lines specified by the value of
-.SM
-.BR HISTFILESIZE .
-When an interactive shell exits, the last
-.SM
-.B $HISTSIZE
-lines are copied from the history list to
-.SM
-.BR $HISTFILE .
-If the
-.B histappend
-shell option is enabled
-(see the description of
-.B shopt
-under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below), the lines are appended to the history file,
-otherwise the history file is overwritten.
-If
-.SM
-.B HISTFILE
-is unset, or if the history file is unwritable, the history is
-not saved. After saving the history, the history file is truncated
-to contain no more than
-.SM
-.B HISTFILESIZE
-lines. If
-.SM
-.B HISTFILESIZE
-is not set, no truncation is performed.
-.PP
-The builtin command
-.B fc
-(see
-.SM
-.B SHELL BUILTIN COMMANDS
-below) may be used to list or edit and re-execute a portion of
-the history list.
-The
-.B history
-builtin may be used to display or modify the history list and
-manipulate the history file.
-When using command-line editing, search commands
-are available in each editing mode that provide access to the
-history list.
-.PP
-The shell allows control over which commands are saved on the history
-list. The
-.SM
-.B HISTCONTROL
-and
-.SM
-.B HISTIGNORE
-variables may be set to cause the shell to save only a subset of the
-commands entered.
-The
-.B cmdhist
-shell option, if enabled, causes the shell to attempt to save each
-line of a multi-line command in the same history entry, adding
-semicolons where necessary to preserve syntactic correctness.
-The
-.B lithist
-shell option causes the shell to save the command with embedded newlines
-instead of semicolons. See the description of the
-.B shopt
-builtin below under
-.SM
-.B "SHELL BUILTIN COMMANDS"
-for information on setting and unsetting shell options.
-.SH "HISTORY EXPANSION"
-.PP
-The shell supports a history expansion feature that
-is similar to the history expansion in
-.BR csh.
-This section describes what syntax features are available. This
-feature is enabled by default for interactive shells, and can be
-disabled using the
-.B \+H
-option to the
-.B set
-builtin command (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below). Non-interactive shells do not perform history expansion
-by default.
-.PP
-History expansions introduce words from the history list into
-the input stream, making it easy to repeat commands, insert the
-arguments to a previous command into the current input line, or
-fix errors in previous commands quickly.
-.PP
-History expansion is performed immediately after a complete line
-is read, before the shell breaks it into words.
-It takes place in two parts.
-The first is to determine which line from the history list
-to use during substitution.
-The second is to select portions of that line for inclusion into
-the current one.
-The line selected from the history is the \fIevent\fP,
-and the portions of that line that are acted upon are \fIwords\fP.
-Various \fImodifiers\fP are available to manipulate the selected words.
-The line is broken into words in the same fashion as when reading input,
-so that several \fImetacharacter\fP-separated words surrounded by
-quotes are considered one word.
-History expansions are introduced by the appearance of the
-history expansion character, which is \^\fB!\fP\^ by default.
-Only backslash (\^\fB\e\fP\^) and single quotes can quote
-the history expansion character.
-.PP
-Several characters inhibit history expansion if found immediately
-following the history expansion character, even if it is unquoted:
-space, tab, newline, carriage return, and \fB=\fP.
-If the \fBextglob\fP shell option is enabled, \fB(\fP will also
-inhibit expansion.
-.PP
-Several shell options settable with the
-.B shopt
-builtin may be used to tailor the behavior of history expansion.
-If the
-.B histverify
-shell option is enabled (see the description of the
-.B shopt
-builtin), and
-.B readline
-is being used, history substitutions are not immediately passed to
-the shell parser.
-Instead, the expanded line is reloaded into the
-.B readline
-editing buffer for further modification.
-If
-.B readline
-is being used, and the
-.B histreedit
-shell option is enabled, a failed history substitution will be reloaded
-into the
-.B readline
-editing buffer for correction.
-The
-.B \-p
-option to the
-.B history
-builtin command may be used to see what a history expansion will
-do before using it.
-The
-.B \-s
-option to the
-.B history
-builtin may be used to add commands to the end of the history list
-without actually executing them, so that they are available for
-subsequent recall.
-.PP
-The shell allows control of the various characters used by the
-history expansion mechanism (see the description of
-.B histchars
-above under
-.BR "Shell Variables" ).
-.SS Event Designators
-.PP
-An event designator is a reference to a command line entry in the
-history list.
-.PP
-.PD 0
-.TP
-.B !
-Start a history substitution, except when followed by a
-.BR blank ,
-newline, carriage return, =
-or ( (when the \fBextglob\fP shell option is enabled using
-the \fBshopt\fP builtin).
-.TP
-.B !\fIn\fR
-Refer to command line
-.IR n .
-.TP
-.B !\-\fIn\fR
-Refer to the current command line minus
-.IR n .
-.TP
-.B !!
-Refer to the previous command. This is a synonym for `!\-1'.
-.TP
-.B !\fIstring\fR
-Refer to the most recent command starting with
-.IR string .
-.TP
-.B !?\fIstring\fR\fB[?]\fR
-Refer to the most recent command containing
-.IR string .
-The trailing \fB?\fP may be omitted if
-.I string
-is followed immediately by a newline.
-.TP
-.B \d\s+2^\s-2\u\fIstring1\fP\d\s+2^\s-2\u\fIstring2\fP\d\s+2^\s-2\u
-Quick substitution. Repeat the last command, replacing
-.I string1
-with
-.IR string2 .
-Equivalent to
-``!!:s/\fIstring1\fP/\fIstring2\fP/''
-(see \fBModifiers\fP below).
-.TP
-.B !#
-The entire command line typed so far.
-.PD
-.SS Word Designators
-.PP
-Word designators are used to select desired words from the event.
-A
-.B :
-separates the event specification from the word designator.
-It may be omitted if the word designator begins with a
-.BR ^ ,
-.BR $ ,
-.BR * ,
-.BR \- ,
-or
-.BR % .
-Words are numbered from the beginning of the line,
-with the first word being denoted by 0 (zero).
-Words are inserted into the current line separated by single spaces.
-.PP
-.PD 0
-.TP
-.B 0 (zero)
-The zeroth word. For the shell, this is the command
-word.
-.TP
-.I n
-The \fIn\fRth word.
-.TP
-.B ^
-The first argument. That is, word 1.
-.TP
-.B $
-The last argument.
-.TP
-.B %
-The word matched by the most recent `?\fIstring\fR?' search.
-.TP
-.I x\fB\-\fPy
-A range of words; `\-\fIy\fR' abbreviates `0\-\fIy\fR'.
-.TP
-.B *
-All of the words but the zeroth. This is a synonym
-for `\fI1\-$\fP'. It is not an error to use
-.B *
-if there is just one
-word in the event; the empty string is returned in that case.
-.TP
-.B x*
-Abbreviates \fIx\-$\fP.
-.TP
-.B x\-
-Abbreviates \fIx\-$\fP like \fBx*\fP, but omits the last word.
-.PD
-.PP
-If a word designator is supplied without an event specification, the
-previous command is used as the event.
-.SS Modifiers
-.PP
-After the optional word designator, there may appear a sequence of
-one or more of the following modifiers, each preceded by a `:'.
-.PP
-.PD 0
-.PP
-.TP
-.B h
-Remove a trailing file name component, leaving only the head.
-.TP
-.B t
-Remove all leading file name components, leaving the tail.
-.TP
-.B r
-Remove a trailing suffix of the form \fI.xxx\fP, leaving the
-basename.
-.TP
-.B e
-Remove all but the trailing suffix.
-.TP
-.B p
-Print the new command but do not execute it.
-.TP
-.B q
-Quote the substituted words, escaping further substitutions.
-.TP
-.B x
-Quote the substituted words as with
-.BR q ,
-but break into words at
-.B blanks
-and newlines.
-.TP
-.B s/\fIold\fP/\fInew\fP/
-Substitute
-.I new
-for the first occurrence of
-.I old
-in the event line. Any delimiter can be used in place of /. The
-final delimiter is optional if it is the last character of the
-event line. The delimiter may be quoted in
-.I old
-and
-.I new
-with a single backslash. If & appears in
-.IR new ,
-it is replaced by
-.IR old .
-A single backslash will quote the &. If
-.I old
-is null, it is set to the last
-.I old
-substituted, or, if no previous history substitutions took place,
-the last
-.I string
-in a
-.B !?\fIstring\fR\fB[?]\fR
-search.
-.TP
-.B &
-Repeat the previous substitution.
-.TP
-.B g
-Cause changes to be applied over the entire event line. This is
-used in conjunction with `\fB:s\fP' (e.g., `\fB:gs/\fIold\fP/\fInew\fP/\fR')
-or `\fB:&\fP'. If used with
-`\fB:s\fP', any delimiter can be used
-in place of /, and the final delimiter is optional
-if it is the last character of the event line.
-An \fBa\fP may be used as a synonym for \fBg\fP.
-.TP
-.B G
-Apply the following `\fBs\fP' modifier once to each word in the event line.
-.PD
-.SH "SHELL BUILTIN COMMANDS"
-.\" start of bash_builtins
-.zZ
-.PP
-Unless otherwise noted, each builtin command documented in this
-section as accepting options preceded by
-.B \-
-accepts
-.B \-\-
-to signify the end of the options.
-For example, the \fB:\fP, \fBtrue\fP, \fBfalse\fP, and \fBtest\fP builtins
-do not accept options.
-.sp .5
-.PD 0
-.TP
-\fB:\fP [\fIarguments\fP]
-.PD
-No effect; the command does nothing beyond expanding
-.I arguments
-and performing any specified
-redirections. A zero exit code is returned.
-.TP
-\fB .\| \fP \fIfilename\fP [\fIarguments\fP]
-.PD 0
-.TP
-\fBsource\fP \fIfilename\fP [\fIarguments\fP]
-.PD
-Read and execute commands from
-.I filename
-in the current
-shell environment and return the exit status of the last command
-executed from
-.IR filename .
-If
-.I filename
-does not contain a slash, file names in
-.SM
-.B PATH
-are used to find the directory containing
-.IR filename .
-The file searched for in
-.SM
-.B PATH
-need not be executable.
-When \fBbash\fP is not in \fIposix mode\fP, the current directory is
-searched if no file is found in
-.SM
-.BR PATH .
-If the
-.B sourcepath
-option to the
-.B shopt
-builtin command is turned off, the
-.SM
-.B PATH
-is not searched.
-If any \fIarguments\fP are supplied, they become the positional
-parameters when \fIfilename\fP is executed. Otherwise the positional
-parameters are unchanged.
-The return status is the status of the last command exited within
-the script (0 if no commands are executed), and false if
-.I filename
-is not found or cannot be read.
-.TP
-\fBalias\fP [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-\fBAlias\fP with no arguments or with the
-.B \-p
-option prints the list of aliases in the form
-\fBalias\fP \fIname\fP=\fIvalue\fP on standard output.
-When arguments are supplied, an alias is defined for
-each \fIname\fP whose \fIvalue\fP is given.
-A trailing space in \fIvalue\fP causes the next word to be
-checked for alias substitution when the alias is expanded.
-For each \fIname\fP in the argument list for which no \fIvalue\fP
-is supplied, the name and value of the alias is printed.
-\fBAlias\fP returns true unless a \fIname\fP is given for which
-no alias has been defined.
-.TP
-\fBbg\fP [\fIjobspec\fP ...]
-Resume each suspended job \fIjobspec\fP in the background, as if it
-had been started with
-.BR & .
-If \fIjobspec\fP is not present, the shell's notion of the
-\fIcurrent job\fP is used.
-.B bg
-.I jobspec
-returns 0 unless run when job control is disabled or, when run with
-job control enabled, any specified \fIjobspec\fP was not found
-or was started without job control.
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-lpsvPSV\fP]
-.PD 0
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] [\fB\-q\fP \fIfunction\fP] [\fB\-u\fP \fIfunction\fP] [\fB\-r\fP \fIkeyseq\fP]
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-f\fP \fIfilename\fP
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fB\-x\fP \fIkeyseq\fP:\fIshell\-command\fP
-.TP
-\fBbind\fP [\fB\-m\fP \fIkeymap\fP] \fIkeyseq\fP:\fIfunction\-name\fP
-.TP
-\fBbind\fP \fIreadline\-command\fP
-.PD
-Display current
-.B readline
-key and function bindings, bind a key sequence to a
-.B readline
-function or macro, or set a
-.B readline
-variable.
-Each non-option argument is a command as it would appear in
-.IR .inputrc ,
-but each binding or command must be passed as a separate argument;
-e.g., '"\eC\-x\eC\-r": re\-read\-init\-file'.
-Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-m \fIkeymap\fP
-Use
-.I keymap
-as the keymap to be affected by the subsequent bindings.
-Acceptable
-.I keymap
-names are
-\fIemacs, emacs\-standard, emacs\-meta, emacs\-ctlx, vi,
-vi\-move, vi\-command\fP, and
-.IR vi\-insert .
-\fIvi\fP is equivalent to \fIvi\-command\fP; \fIemacs\fP is
-equivalent to \fIemacs\-standard\fP.
-.TP
-.B \-l
-List the names of all \fBreadline\fP functions.
-.TP
-.B \-p
-Display \fBreadline\fP function names and bindings in such a way
-that they can be re-read.
-.TP
-.B \-P
-List current \fBreadline\fP function names and bindings.
-.TP
-.B \-v
-Display \fBreadline\fP variable names and values in such a way that they
-can be re-read.
-.TP
-.B \-V
-List current \fBreadline\fP variable names and values.
-.TP
-.B \-s
-Display \fBreadline\fP key sequences bound to macros and the strings
-they output in such a way that they can be re-read.
-.TP
-.B \-S
-Display \fBreadline\fP key sequences bound to macros and the strings
-they output.
-.TP
-.B \-f \fIfilename\fP
-Read key bindings from \fIfilename\fP.
-.TP
-.B \-q \fIfunction\fP
-Query about which keys invoke the named \fIfunction\fP.
-.TP
-.B \-u \fIfunction\fP
-Unbind all keys bound to the named \fIfunction\fP.
-.TP
-.B \-r \fIkeyseq\fP
-Remove any current binding for \fIkeyseq\fP.
-.TP
-.B \-x \fIkeyseq\fP:\fIshell\-command\fP
-Cause \fIshell\-command\fP to be executed whenever \fIkeyseq\fP is
-entered.
-.PD
-.PP
-The return value is 0 unless an unrecognized option is given or an
-error occurred.
-.RE
-.TP
-\fBbreak\fP [\fIn\fP]
-Exit from within a
-.BR for ,
-.BR while ,
-.BR until ,
-or
-.B select
-loop. If \fIn\fP is specified, break \fIn\fP levels.
-.I n
-must be \(>= 1. If
-.I n
-is greater than the number of enclosing loops, all enclosing loops
-are exited. The return value is 0 unless the shell is not executing
-a loop when
-.B break
-is executed.
-.TP
-\fBbuiltin\fP \fIshell\-builtin\fP [\fIarguments\fP]
-Execute the specified shell builtin, passing it
-.IR arguments ,
-and return its exit status.
-This is useful when defining a
-function whose name is the same as a shell builtin,
-retaining the functionality of the builtin within the function.
-The \fBcd\fP builtin is commonly redefined this way.
-The return status is false if
-.I shell\-builtin
-is not a shell builtin command.
-.TP
-\fBcd\fP [\fB\-L|-P\fP] [\fIdir\fP]
-Change the current directory to \fIdir\fP. The variable
-.SM
-.B HOME
-is the
-default
-.IR dir .
-The variable
-.SM
-.B CDPATH
-defines the search path for the directory containing
-.IR dir .
-Alternative directory names in
-.SM
-.B CDPATH
-are separated by a colon (:). A null directory name in
-.SM
-.B CDPATH
-is the same as the current directory, i.e., ``\fB.\fP''. If
-.I dir
-begins with a slash (/),
-then
-.SM
-.B CDPATH
-is not used. The
-.B \-P
-option says to use the physical directory structure instead of
-following symbolic links (see also the
-.B \-P
-option to the
-.B set
-builtin command); the
-.B \-L
-option forces symbolic links to be followed. An argument of
-.B \-
-is equivalent to
-.SM
-.BR $OLDPWD .
-If a non-empty directory name from \fBCDPATH\fP is used, or if
-\fB\-\fP is the first argument, and the directory change is
-successful, the absolute pathname of the new working directory is
-written to the standard output.
-The return value is true if the directory was successfully changed;
-false otherwise.
-.TP
-\fBcaller\fP [\fIexpr\fP]
-Returns the context of any active subroutine call (a shell function or
-a script executed with the \fB.\fP or \fBsource\fP builtins.
-Without \fIexpr\fP, \fBcaller\fP displays the line number and source
-filename of the current subroutine call.
-If a non-negative integer is supplied as \fIexpr\fP, \fBcaller\fP
-displays the line number, subroutine name, and source file corresponding
-to that position in the current execution call stack. This extra
-information may be used, for example, to print a stack trace. The
-current frame is frame 0.
-The return value is 0 unless the shell is not executing a subroutine
-call or \fIexpr\fP does not correspond to a valid position in the
-call stack.
-.TP
-\fBcommand\fP [\fB\-pVv\fP] \fIcommand\fP [\fIarg\fP ...]
-Run
-.I command
-with
-.I args
-suppressing the normal shell function lookup. Only builtin
-commands or commands found in the
-.SM
-.B PATH
-are executed. If the
-.B \-p
-option is given, the search for
-.I command
-is performed using a default value for
-.B PATH
-that is guaranteed to find all of the standard utilities.
-If either the
-.B \-V
-or
-.B \-v
-option is supplied, a description of
-.I command
-is printed. The
-.B \-v
-option causes a single word indicating the command or file name
-used to invoke
-.I command
-to be displayed; the
-.B \-V
-option produces a more verbose description.
-If the
-.B \-V
-or
-.B \-v
-option is supplied, the exit status is 0 if
-.I command
-was found, and 1 if not. If neither option is supplied and
-an error occurred or
-.I command
-cannot be found, the exit status is 127. Otherwise, the exit status of the
-.B command
-builtin is the exit status of
-.IR command .
-.TP
-\fBcompgen\fP [\fIoption\fP] [\fIword\fP]
-Generate possible completion matches for \fIword\fP according to
-the \fIoption\fPs, which may be any option accepted by the
-.B complete
-builtin with the exception of \fB\-p\fP and \fB\-r\fP, and write
-the matches to the standard output.
-When using the \fB\-F\fP or \fB\-C\fP options, the various shell variables
-set by the programmable completion facilities, while available, will not
-have useful values.
-.sp 1
-The matches will be generated in the same way as if the programmable
-completion code had generated them directly from a completion specification
-with the same flags.
-If \fIword\fP is specified, only those completions matching \fIword\fP
-will be displayed.
-.sp 1
-The return value is true unless an invalid option is supplied, or no
-matches were generated.
-.TP
-\fBcomplete\fP [\fB\-abcdefgjksuv\fP] [\fB\-o\fP \fIcomp-option\fP] [\fB\-A\fP \fIaction\fP] [\fB\-G\fP \fIglobpat\fP] [\fB\-W\fP \fIwordlist\fP] [\fB\-P\fP \fIprefix\fP] [\fB\-S\fP \fIsuffix\fP]
-.br
-[\fB\-X\fP \fIfilterpat\fP] [\fB\-F\fP \fIfunction\fP] [\fB\-C\fP \fIcommand\fP] \fIname\fP [\fIname ...\fP]
-.PD 0
-.TP
-\fBcomplete\fP \fB\-pr\fP [\fIname\fP ...]
-.PD
-Specify how arguments to each \fIname\fP should be completed.
-If the \fB\-p\fP option is supplied, or if no options are supplied,
-existing completion specifications are printed in a way that allows
-them to be reused as input.
-The \fB\-r\fP option removes a completion specification for
-each \fIname\fP, or, if no \fIname\fPs are supplied, all
-completion specifications.
-.sp 1
-The process of applying these completion specifications when word completion
-is attempted is described above under \fBProgrammable Completion\fP.
-.sp 1
-Other options, if specified, have the following meanings.
-The arguments to the \fB\-G\fP, \fB\-W\fP, and \fB\-X\fP options
-(and, if necessary, the \fB\-P\fP and \fB\-S\fP options)
-should be quoted to protect them from expansion before the
-.B complete
-builtin is invoked.
-.RS
-.PD 0
-.TP 8
-\fB\-o\fP \fIcomp-option\fP
-The \fIcomp-option\fP controls several aspects of the compspec's behavior
-beyond the simple generation of completions.
-\fIcomp-option\fP may be one of:
-.RS
-.TP 8
-.B bashdefault
-Perform the rest of the default \fBbash\fP completions if the compspec
-generates no matches.
-.TP 8
-.B default
-Use readline's default filename completion if the compspec generates
-no matches.
-.TP 8
-.B dirnames
-Perform directory name completion if the compspec generates no matches.
-.TP 8
-.B filenames
-Tell readline that the compspec generates filenames, so it can perform any
-filename\-specific processing (like adding a slash to directory names or
-suppressing trailing spaces). Intended to be used with shell functions.
-.TP 8
-.B nospace
-Tell readline not to append a space (the default) to words completed at
-the end of the line.
-.TP 8
-.B plusdirs
-After any matches defined by the compspec are generated,
-directory name completion is attempted and any
-matches are added to the results of the other actions.
-.RE
-.TP 8
-\fB\-A\fP \fIaction\fP
-The \fIaction\fP may be one of the following to generate a list of possible
-completions:
-.RS
-.TP 8
-.B alias
-Alias names. May also be specified as \fB\-a\fP.
-.TP 8
-.B arrayvar
-Array variable names.
-.TP 8
-.B binding
-\fBReadline\fP key binding names.
-.TP 8
-.B builtin
-Names of shell builtin commands. May also be specified as \fB\-b\fP.
-.TP 8
-.B command
-Command names. May also be specified as \fB\-c\fP.
-.TP 8
-.B directory
-Directory names. May also be specified as \fB\-d\fP.
-.TP 8
-.B disabled
-Names of disabled shell builtins.
-.TP 8
-.B enabled
-Names of enabled shell builtins.
-.TP 8
-.B export
-Names of exported shell variables. May also be specified as \fB\-e\fP.
-.TP 8
-.B file
-File names. May also be specified as \fB\-f\fP.
-.TP 8
-.B function
-Names of shell functions.
-.TP 8
-.B group
-Group names. May also be specified as \fB\-g\fP.
-.TP 8
-.B helptopic
-Help topics as accepted by the \fBhelp\fP builtin.
-.TP 8
-.B hostname
-Hostnames, as taken from the file specified by the
-.SM
-.B HOSTFILE
-shell variable.
-.TP 8
-.B job
-Job names, if job control is active. May also be specified as \fB\-j\fP.
-.TP 8
-.B keyword
-Shell reserved words. May also be specified as \fB\-k\fP.
-.TP 8
-.B running
-Names of running jobs, if job control is active.
-.TP 8
-.B service
-Service names. May also be specified as \fB\-s\fP.
-.TP 8
-.B setopt
-Valid arguments for the \fB\-o\fP option to the \fBset\fP builtin.
-.TP 8
-.B shopt
-Shell option names as accepted by the \fBshopt\fP builtin.
-.TP 8
-.B signal
-Signal names.
-.TP 8
-.B stopped
-Names of stopped jobs, if job control is active.
-.TP 8
-.B user
-User names. May also be specified as \fB\-u\fP.
-.TP 8
-.B variable
-Names of all shell variables. May also be specified as \fB\-v\fP.
-.RE
-.TP 8
-\fB\-G\fP \fIglobpat\fP
-The filename expansion pattern \fIglobpat\fP is expanded to generate
-the possible completions.
-.TP 8
-\fB\-W\fP \fIwordlist\fP
-The \fIwordlist\fP is split using the characters in the
-.SM
-.B IFS
-special variable as delimiters, and each resultant word is expanded.
-The possible completions are the members of the resultant list which
-match the word being completed.
-.TP 8
-\fB\-C\fP \fIcommand\fP
-\fIcommand\fP is executed in a subshell environment, and its output is
-used as the possible completions.
-.TP 8
-\fB\-F\fP \fIfunction\fP
-The shell function \fIfunction\fP is executed in the current shell
-environment.
-When it finishes, the possible completions are retrieved from the value
-of the
-.SM
-.B COMPREPLY
-array variable.
-.TP 8
-\fB\-X\fP \fIfilterpat\fP
-\fIfilterpat\fP is a pattern as used for filename expansion.
-It is applied to the list of possible completions generated by the
-preceding options and arguments, and each completion matching
-\fIfilterpat\fP is removed from the list.
-A leading \fB!\fP in \fIfilterpat\fP negates the pattern; in this
-case, any completion not matching \fIfilterpat\fP is removed.
-.TP 8
-\fB\-P\fP \fIprefix\fP
-\fIprefix\fP is added at the beginning of each possible completion
-after all other options have been applied.
-.TP 8
-\fB\-S\fP \fIsuffix\fP
-\fIsuffix\fP is appended to each possible completion
-after all other options have been applied.
-.PD
-.PP
-The return value is true unless an invalid option is supplied, an option
-other than \fB\-p\fP or \fB\-r\fP is supplied without a \fIname\fP
-argument, an attempt is made to remove a completion specification for
-a \fIname\fP for which no specification exists, or
-an error occurs adding a completion specification.
-.RE
-.TP
-\fBcontinue\fP [\fIn\fP]
-Resume the next iteration of the enclosing
-.BR for ,
-.BR while ,
-.BR until ,
-or
-.B select
-loop.
-If
-.I n
-is specified, resume at the \fIn\fPth enclosing loop.
-.I n
-must be \(>= 1. If
-.I n
-is greater than the number of enclosing loops, the last enclosing loop
-(the ``top-level'' loop) is resumed. The return value is 0 unless the
-shell is not executing a loop when
-.B continue
-is executed.
-.TP
-\fBdeclare\fP [\fB\-afFirtx\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-.PD 0
-.TP
-\fBtypeset\fP [\fB\-afFirtx\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-.PD
-Declare variables and/or give them attributes.
-If no \fIname\fPs are given then display the values of variables.
-The
-.B \-p
-option will display the attributes and values of each
-.IR name .
-When
-.B \-p
-is used, additional options are ignored.
-The
-.B \-F
-option inhibits the display of function definitions; only the
-function name and attributes are printed.
-If the \fBextdebug\fP shell option is enabled using \fBshopt\fP,
-the source file name and line number where the function is defined
-are displayed as well. The
-.B \-F
-option implies
-.BR \-f .
-The following options can
-be used to restrict output to variables with the specified attribute or
-to give variables attributes:
-.RS
-.PD 0
-.TP
-.B \-a
-Each \fIname\fP is an array variable (see
-.B Arrays
-above).
-.TP
-.B \-f
-Use function names only.
-.TP
-.B \-i
-The variable is treated as an integer; arithmetic evaluation (see
-.SM
-.B "ARITHMETIC EVALUATION" ") "
-is performed when the variable is assigned a value.
-.TP
-.B \-r
-Make \fIname\fPs readonly. These names cannot then be assigned values
-by subsequent assignment statements or unset.
-.TP
-.B \-t
-Give each \fIname\fP the \fItrace\fP attribute.
-Traced functions inherit the \fBDEBUG\fP and \fBRETURN\fP traps from
-the calling shell.
-The trace attribute has no special meaning for variables.
-.TP
-.B \-x
-Mark \fIname\fPs for export to subsequent commands via the environment.
-.PD
-.PP
-Using `+' instead of `\-'
-turns off the attribute instead, with the exception that \fB+a\fP
-may not be used to destroy an array variable. When used in a function,
-makes each
-\fIname\fP local, as with the
-.B local
-command.
-If a variable name is followed by =\fIvalue\fP, the value of
-the variable is set to \fIvalue\fP.
-The return value is 0 unless an invalid option is encountered,
-an attempt is made to define a function using
-.if n ``\-f foo=bar'',
-.if t \f(CW\-f foo=bar\fP,
-an attempt is made to assign a value to a readonly variable,
-an attempt is made to assign a value to an array variable without
-using the compound assignment syntax (see
-.B Arrays
-above), one of the \fInames\fP is not a valid shell variable name,
-an attempt is made to turn off readonly status for a readonly variable,
-an attempt is made to turn off array status for an array variable,
-or an attempt is made to display a non-existent function with \fB\-f\fP.
-.RE
-.TP
-.B dirs [\fB\-clpv\fP] [+\fIn\fP] [\-\fIn\fP]
-Without options, displays the list of currently remembered directories.
-The default display is on a single line with directory names separated
-by spaces.
-Directories are added to the list with the
-.B pushd
-command; the
-.B popd
-command removes entries from the list.
-.RS
-.PD 0
-.TP
-\fB+\fP\fIn\fP
-Displays the \fIn\fPth entry counting from the left of the list
-shown by
-.B dirs
-when invoked without options, starting with zero.
-.TP
-\fB\-\fP\fIn\fP
-Displays the \fIn\fPth entry counting from the right of the list
-shown by
-.B dirs
-when invoked without options, starting with zero.
-.TP
-.B \-c
-Clears the directory stack by deleting all of the entries.
-.TP
-.B \-l
-Produces a longer listing; the default listing format uses a
-tilde to denote the home directory.
-.TP
-.B \-p
-Print the directory stack with one entry per line.
-.TP
-.B \-v
-Print the directory stack with one entry per line,
-prefixing each entry with its index in the stack.
-.PD
-.PP
-The return value is 0 unless an
-invalid option is supplied or \fIn\fP indexes beyond the end
-of the directory stack.
-.RE
-.TP
-\fBdisown\fP [\fB\-ar\fP] [\fB\-h\fP] [\fIjobspec\fP ...]
-Without options, each
-.I jobspec
-is removed from the table of active jobs.
-If the \fB\-h\fP option is given, each
-.I jobspec
-is not removed from the table, but is marked so that
-.SM
-.B SIGHUP
-is not sent to the job if the shell receives a
-.SM
-.BR SIGHUP .
-If no
-.I jobspec
-is present, and neither the
-.B \-a
-nor the
-.B \-r
-option is supplied, the \fIcurrent job\fP is used.
-If no
-.I jobspec
-is supplied, the
-.B \-a
-option means to remove or mark all jobs; the
-.B \-r
-option without a
-.I jobspec
-argument restricts operation to running jobs.
-The return value is 0 unless a
-.I jobspec
-does not specify a valid job.
-.TP
-\fBecho\fP [\fB\-neE\fP] [\fIarg\fP ...]
-Output the \fIarg\fPs, separated by spaces, followed by a newline.
-The return status is always 0.
-If \fB\-n\fP is specified, the trailing newline is
-suppressed. If the \fB\-e\fP option is given, interpretation of
-the following backslash-escaped characters is enabled. The
-.B \-E
-option disables the interpretation of these escape characters,
-even on systems where they are interpreted by default.
-The \fBxpg_echo\fP shell option may be used to
-dynamically determine whether or not \fBecho\fP expands these
-escape characters by default.
-.B echo
-does not interpret \fB\-\-\fP to mean the end of options.
-.B echo
-interprets the following escape sequences:
-.RS
-.PD 0
-.TP
-.B \ea
-alert (bell)
-.TP
-.B \eb
-backspace
-.TP
-.B \ec
-suppress trailing newline
-.TP
-.B \ee
-an escape character
-.TP
-.B \ef
-form feed
-.TP
-.B \en
-new line
-.TP
-.B \er
-carriage return
-.TP
-.B \et
-horizontal tab
-.TP
-.B \ev
-vertical tab
-.TP
-.B \e\e
-backslash
-.TP
-.B \e0\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(zero to three octal digits)
-.TP
-.B \e\fInnn\fP
-the eight-bit character whose value is the octal value \fInnn\fP
-(one to three octal digits)
-.TP
-.B \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.PD
-.RE
-.TP
-\fBenable\fP [\fB\-adnps\fP] [\fB\-f\fP \fIfilename\fP] [\fIname\fP ...]
-Enable and disable builtin shell commands.
-Disabling a builtin allows a disk command which has the same name
-as a shell builtin to be executed without specifying a full pathname,
-even though the shell normally searches for builtins before disk commands.
-If \fB\-n\fP is used, each \fIname\fP
-is disabled; otherwise,
-\fInames\fP are enabled. For example, to use the
-.B test
-binary found via the
-.SM
-.B PATH
-instead of the shell builtin version, run
-.if t \f(CWenable -n test\fP.
-.if n ``enable -n test''.
-The
-.B \-f
-option means to load the new builtin command
-.I name
-from shared object
-.IR filename ,
-on systems that support dynamic loading. The
-.B \-d
-option will delete a builtin previously loaded with
-.BR \-f .
-If no \fIname\fP arguments are given, or if the
-.B \-p
-option is supplied, a list of shell builtins is printed.
-With no other option arguments, the list consists of all enabled
-shell builtins.
-If \fB\-n\fP is supplied, only disabled builtins are printed.
-If \fB\-a\fP is supplied, the list printed includes all builtins, with an
-indication of whether or not each is enabled.
-If \fB\-s\fP is supplied, the output is restricted to the POSIX
-\fIspecial\fP builtins.
-The return value is 0 unless a
-.I name
-is not a shell builtin or there is an error loading a new builtin
-from a shared object.
-.TP
-\fBeval\fP [\fIarg\fP ...]
-The \fIarg\fPs are read and concatenated together into a single
-command. This command is then read and executed by the shell, and
-its exit status is returned as the value of
-.BR eval .
-If there are no
-.IR args ,
-or only null arguments,
-.B eval
-returns 0.
-.TP
-\fBexec\fP [\fB\-cl\fP] [\fB\-a\fP \fIname\fP] [\fIcommand\fP [\fIarguments\fP]]
-If
-.I command
-is specified, it replaces the shell.
-No new process is created. The
-.I arguments
-become the arguments to \fIcommand\fP.
-If the
-.B \-l
-option is supplied,
-the shell places a dash at the beginning of the zeroth arg passed to
-.IR command .
-This is what
-.IR login (1)
-does. The
-.B \-c
-option causes
-.I command
-to be executed with an empty environment. If
-.B \-a
-is supplied, the shell passes
-.I name
-as the zeroth argument to the executed command. If
-.I command
-cannot be executed for some reason, a non-interactive shell exits,
-unless the shell option
-.B execfail
-is enabled, in which case it returns failure.
-An interactive shell returns failure if the file cannot be executed.
-If
-.I command
-is not specified, any redirections take effect in the current shell,
-and the return status is 0. If there is a redirection error, the
-return status is 1.
-.TP
-\fBexit\fP [\fIn\fP]
-Cause the shell to exit
-with a status of \fIn\fP. If
-.I n
-is omitted, the exit status
-is that of the last command executed.
-A trap on
-.SM
-.B EXIT
-is executed before the shell terminates.
-.TP
-\fBexport\fP [\fB\-fn\fP\^] [\fIname\fP[=\fIword\fP]] ...
-.PD 0
-.TP
-.B export \-p
-.PD
-The supplied
-.I names
-are marked for automatic export to the environment of
-subsequently executed commands. If the
-.B \-f
-option is given,
-the
-.I names
-refer to functions.
-If no
-.I names
-are given, or if the
-.B \-p
-option is supplied, a list
-of all names that are exported in this shell is printed.
-The
-.B \-n
-option causes the export property to be removed from each
-\fIname\fP.
-If a variable name is followed by =\fIword\fP, the value of
-the variable is set to \fIword\fP.
-.B export
-returns an exit status of 0 unless an invalid option is
-encountered,
-one of the \fInames\fP is not a valid shell variable name, or
-.B \-f
-is supplied with a
-.I name
-that is not a function.
-.TP
-\fBfc\fP [\fB\-e\fP \fIename\fP] [\fB\-nlr\fP] [\fIfirst\fP] [\fIlast\fP]
-.PD 0
-.TP
-\fBfc\fP \fB\-s\fP [\fIpat\fP=\fIrep\fP] [\fIcmd\fP]
-.PD
-Fix Command. In the first form, a range of commands from
-.I first
-to
-.I last
-is selected from the history list.
-.I First
-and
-.I last
-may be specified as a string (to locate the last command beginning
-with that string) or as a number (an index into the history list,
-where a negative number is used as an offset from the current
-command number). If
-.I last
-is not specified it is set to
-the current command for listing (so that
-.if n ``fc \-l \-10''
-.if t \f(CWfc \-l \-10\fP
-prints the last 10 commands) and to
-.I first
-otherwise.
-If
-.I first
-is not specified it is set to the previous
-command for editing and \-16 for listing.
-.sp 1
-The
-.B \-n
-option suppresses
-the command numbers when listing. The
-.B \-r
-option reverses the order of
-the commands. If the
-.B \-l
-option is given,
-the commands are listed on
-standard output. Otherwise, the editor given by
-.I ename
-is invoked
-on a file containing those commands. If
-.I ename
-is not given, the
-value of the
-.SM
-.B FCEDIT
-variable is used, and
-the value of
-.SM
-.B EDITOR
-if
-.SM
-.B FCEDIT
-is not set. If neither variable is set,
-.FN vi
-is used. When editing is complete, the edited commands are
-echoed and executed.
-.sp 1
-In the second form, \fIcommand\fP is re-executed after each instance
-of \fIpat\fP is replaced by \fIrep\fP.
-A useful alias to use with this is
-.if n ``r="fc -s"'',
-.if t \f(CWr='fc \-s'\fP,
-so that typing
-.if n ``r cc''
-.if t \f(CWr cc\fP
-runs the last command beginning with
-.if n ``cc''
-.if t \f(CWcc\fP
-and typing
-.if n ``r''
-.if t \f(CWr\fP
-re-executes the last command.
-.sp 1
-If the first form is used, the return value is 0 unless an invalid
-option is encountered or
-.I first
-or
-.I last
-specify history lines out of range.
-If the
-.B \-e
-option is supplied, the return value is the value of the last
-command executed or failure if an error occurs with the temporary
-file of commands. If the second form is used, the return status
-is that of the command re-executed, unless
-.I cmd
-does not specify a valid history line, in which case
-.B fc
-returns failure.
-.TP
-\fBfg\fP [\fIjobspec\fP]
-Resume
-.I jobspec
-in the foreground, and make it the current job.
-If
-.I jobspec
-is not present, the shell's notion of the \fIcurrent job\fP is used.
-The return value is that of the command placed into the foreground,
-or failure if run when job control is disabled or, when run with
-job control enabled, if
-.I jobspec
-does not specify a valid job or
-.I jobspec
-specifies a job that was started without job control.
-.TP
-\fBgetopts\fP \fIoptstring\fP \fIname\fP [\fIargs\fP]
-.B getopts
-is used by shell procedures to parse positional parameters.
-.I optstring
-contains the option characters to be recognized; if a character
-is followed by a colon, the option is expected to have an
-argument, which should be separated from it by white space.
-The colon and question mark characters may not be used as
-option characters.
-Each time it is invoked,
-.B getopts
-places the next option in the shell variable
-.IR name ,
-initializing
-.I name
-if it does not exist,
-and the index of the next argument to be processed into the
-variable
-.SM
-.BR OPTIND .
-.SM
-.B OPTIND
-is initialized to 1 each time the shell or a shell script
-is invoked. When an option requires an argument,
-.B getopts
-places that argument into the variable
-.SM
-.BR OPTARG .
-The shell does not reset
-.SM
-.B OPTIND
-automatically; it must be manually reset between multiple
-calls to
-.B getopts
-within the same shell invocation if a new set of parameters
-is to be used.
-.sp 1
-When the end of options is encountered, \fBgetopts\fP exits with a
-return value greater than zero.
-\fBOPTIND\fP is set to the index of the first non-option argument,
-and \fBname\fP is set to ?.
-.sp 1
-.B getopts
-normally parses the positional parameters, but if more arguments are
-given in
-.IR args ,
-.B getopts
-parses those instead.
-.sp 1
-.B getopts
-can report errors in two ways. If the first character of
-.I optstring
-is a colon,
-.I silent
-error reporting is used. In normal operation diagnostic messages
-are printed when invalid options or missing option arguments are
-encountered.
-If the variable
-.SM
-.B OPTERR
-is set to 0, no error messages will be displayed, even if the first
-character of
-.I optstring
-is not a colon.
-.sp 1
-If an invalid option is seen,
-.B getopts
-places ? into
-.I name
-and, if not silent,
-prints an error message and unsets
-.SM
-.BR OPTARG .
-If
-.B getopts
-is silent,
-the option character found is placed in
-.SM
-.B OPTARG
-and no diagnostic message is printed.
-.sp 1
-If a required argument is not found, and
-.B getopts
-is not silent,
-a question mark (\^\fB?\fP\^) is placed in
-.IR name ,
-.SM
-.B OPTARG
-is unset, and a diagnostic message is printed.
-If
-.B getopts
-is silent, then a colon (\^\fB:\fP\^) is placed in
-.I name
-and
-.SM
-.B OPTARG
-is set to the option character found.
-.sp 1
-.B getopts
-returns true if an option, specified or unspecified, is found.
-It returns false if the end of options is encountered or an
-error occurs.
-.TP
-\fBhash\fP [\fB\-lr\fP] [\fB\-p\fP \fIfilename\fP] [\fB\-dt\fP] [\fIname\fP]
-For each
-.IR name ,
-the full file name of the command is determined by searching
-the directories in
-.B $PATH
-and remembered.
-If the
-.B \-p
-option is supplied, no path search is performed, and
-.I filename
-is used as the full file name of the command.
-The
-.B \-r
-option causes the shell to forget all
-remembered locations.
-The
-.B \-d
-option causes the shell to forget the remembered location of each \fIname\fP.
-If the
-.B \-t
-option is supplied, the full pathname to which each \fIname\fP corresponds
-is printed. If multiple \fIname\fP arguments are supplied with \fB\-t\fP,
-the \fIname\fP is printed before the hashed full pathname.
-The
-.B \-l
-option causes output to be displayed in a format that may be reused as input.
-If no arguments are given, or if only \fB\-l\fP is supplied,
-information about remembered commands is printed.
-The return status is true unless a
-.I name
-is not found or an invalid option is supplied.
-.TP
-\fBhelp\fP [\fB\-s\fP] [\fIpattern\fP]
-Display helpful information about builtin commands. If
-.I pattern
-is specified,
-.B help
-gives detailed help on all commands matching
-.IR pattern ;
-otherwise help for all the builtins and shell control structures
-is printed.
-The \fB\-s\fP option restricts the information displayed to a short
-usage synopsis.
-The return status is 0 unless no command matches
-.IR pattern .
-.TP
-\fBhistory [\fIn\fP]
-.PD 0
-.TP
-\fBhistory\fP \fB\-c\fP
-.TP
-\fBhistory \-d\fP \fIoffset\fP
-.TP
-\fBhistory\fP \fB\-anrw\fP [\fIfilename\fP]
-.TP
-\fBhistory\fP \fB\-p\fP \fIarg\fP [\fIarg ...\fP]
-.TP
-\fBhistory\fP \fB\-s\fP \fIarg\fP [\fIarg ...\fP]
-.PD
-With no options, display the command
-history list with line numbers. Lines listed
-with a
-.B *
-have been modified. An argument of
-.I n
-lists only the last
-.I n
-lines.
-If the shell variable \fBHISTTIMEFORMAT\fP is set and not null,
-it is used as a format string for \fIstrftime\fP(3) to display
-the time stamp associated with each displayed history entry.
-No intervening blank is printed between the formatted time stamp
-and the history line.
-If \fIfilename\fP is supplied, it is used as the
-name of the history file; if not, the value of
-.SM
-.B HISTFILE
-is used. Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-c
-Clear the history list by deleting all the entries.
-.TP
-\fB\-d\fP \fIoffset\fP
-Delete the history entry at position \fIoffset\fP.
-.TP
-.B \-a
-Append the ``new'' history lines (history lines entered since the
-beginning of the current \fBbash\fP session) to the history file.
-.TP
-.B \-n
-Read the history lines not already read from the history
-file into the current history list. These are lines
-appended to the history file since the beginning of the
-current \fBbash\fP session.
-.TP
-.B \-r
-Read the contents of the history file
-and use them as the current history.
-.TP
-.B \-w
-Write the current history to the history file, overwriting the
-history file's contents.
-.TP
-.B \-p
-Perform history substitution on the following \fIargs\fP and display
-the result on the standard output.
-Does not store the results in the history list.
-Each \fIarg\fP must be quoted to disable normal history expansion.
-.TP
-.B \-s
-Store the
-.I args
-in the history list as a single entry. The last command in the
-history list is removed before the
-.I args
-are added.
-.PD
-.PP
-If the \fBHISTTIMEFORMAT\fP is set, the time stamp information
-associated with each history entry is written to the history file.
-The return value is 0 unless an invalid option is encountered, an
-error occurs while reading or writing the history file, an invalid
-\fIoffset\fP is supplied as an argument to \fB\-d\fP, or the
-history expansion supplied as an argument to \fB\-p\fP fails.
-.RE
-.TP
-\fBjobs\fP [\fB\-lnprs\fP] [ \fIjobspec\fP ... ]
-.PD 0
-.TP
-\fBjobs\fP \fB\-x\fP \fIcommand\fP [ \fIargs\fP ... ]
-.PD
-The first form lists the active jobs. The options have the following
-meanings:
-.RS
-.PD 0
-.TP
-.B \-l
-List process IDs
-in addition to the normal information.
-.TP
-.B \-p
-List only the process ID of the job's process group
-leader.
-.TP
-.B \-n
-Display information only about jobs that have changed status since
-the user was last notified of their status.
-.TP
-.B \-r
-Restrict output to running jobs.
-.TP
-.B \-s
-Restrict output to stopped jobs.
-.PD
-.PP
-If
-.I jobspec
-is given, output is restricted to information about that job.
-The return status is 0 unless an invalid option is encountered
-or an invalid
-.I jobspec
-is supplied.
-.PP
-If the
-.B \-x
-option is supplied,
-.B jobs
-replaces any
-.I jobspec
-found in
-.I command
-or
-.I args
-with the corresponding process group ID, and executes
-.I command
-passing it
-.IR args ,
-returning its exit status.
-.RE
-.TP
-\fBkill\fP [\fB\-s\fP \fIsigspec\fP | \fB\-n\fP \fIsignum\fP | \fB\-\fP\fIsigspec\fP] [\fIpid\fP | \fIjobspec\fP] ...
-.PD 0
-.TP
-\fBkill\fP \fB\-l\fP [\fIsigspec\fP | \fIexit_status\fP]
-.PD
-Send the signal named by
-.I sigspec
-or
-.I signum
-to the processes named by
-.I pid
-or
-.IR jobspec .
-.I sigspec
-is either a case-insensitive signal name such as
-.SM
-.B SIGKILL
-(with or without the
-.SM
-.B SIG
-prefix) or a signal number;
-.I signum
-is a signal number.
-If
-.I sigspec
-is not present, then
-.SM
-.B SIGTERM
-is assumed.
-An argument of
-.B \-l
-lists the signal names.
-If any arguments are supplied when
-.B \-l
-is given, the names of the signals corresponding to the arguments are
-listed, and the return status is 0.
-The \fIexit_status\fP argument to
-.B \-l
-is a number specifying either a signal number or the exit status of
-a process terminated by a signal.
-.B kill
-returns true if at least one signal was successfully sent, or false
-if an error occurs or an invalid option is encountered.
-.TP
-\fBlet\fP \fIarg\fP [\fIarg\fP ...]
-Each
-.I arg
-is an arithmetic expression to be evaluated (see
-.SM
-.BR "ARITHMETIC EVALUATION" ).
-If the last
-.I arg
-evaluates to 0,
-.B let
-returns 1; 0 is returned otherwise.
-.TP
-\fBlocal\fP [\fIoption\fP] [\fIname\fP[=\fIvalue\fP] ...]
-For each argument, a local variable named
-.I name
-is created, and assigned
-.IR value .
-The \fIoption\fP can be any of the options accepted by \fBdeclare\fP.
-When
-.B local
-is used within a function, it causes the variable
-.I name
-to have a visible scope restricted to that function and its children.
-With no operands,
-.B local
-writes a list of local variables to the standard output. It is
-an error to use
-.B local
-when not within a function. The return status is 0 unless
-.B local
-is used outside a function, an invalid
-.I name
-is supplied, or
-\fIname\fP is a readonly variable.
-.TP
-.B logout
-Exit a login shell.
-.TP
-\fBpopd\fP [\-\fBn\fP] [+\fIn\fP] [\-\fIn\fP]
-Removes entries from the directory stack. With no arguments,
-removes the top directory from the stack, and performs a
-.B cd
-to the new top directory.
-Arguments, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-\fB+\fP\fIn\fP
-Removes the \fIn\fPth entry counting from the left of the list
-shown by
-.BR dirs ,
-starting with zero. For example:
-.if n ``popd +0''
-.if t \f(CWpopd +0\fP
-removes the first directory,
-.if n ``popd +1''
-.if t \f(CWpopd +1\fP
-the second.
-.TP
-\fB\-\fP\fIn\fP
-Removes the \fIn\fPth entry counting from the right of the list
-shown by
-.BR dirs ,
-starting with zero. For example:
-.if n ``popd -0''
-.if t \f(CWpopd -0\fP
-removes the last directory,
-.if n ``popd -1''
-.if t \f(CWpopd -1\fP
-the next to last.
-.TP
-.B \-n
-Suppresses the normal change of directory when removing directories
-from the stack, so that only the stack is manipulated.
-.PD
-.PP
-If the
-.B popd
-command is successful, a
-.B dirs
-is performed as well, and the return status is 0.
-.B popd
-returns false if an invalid option is encountered, the directory stack
-is empty, a non-existent directory stack entry is specified, or the
-directory change fails.
-.RE
-.TP
-\fBprintf\fP [\fB\-v\fP \fIvar\fP] \fIformat\fP [\fIarguments\fP]
-Write the formatted \fIarguments\fP to the standard output under the
-control of the \fIformat\fP.
-The \fIformat\fP is a character string which contains three types of objects:
-plain characters, which are simply copied to standard output, character
-escape sequences, which are converted and copied to the standard output, and
-format specifications, each of which causes printing of the next successive
-\fIargument\fP.
-In addition to the standard \fIprintf\fP(1) formats, \fB%b\fP causes
-\fBprintf\fP to expand backslash escape sequences in the corresponding
-\fIargument\fP (except that \fB\ec\fP terminates output, backslashes in
-\fB\e\(aq\fP, \fB\e"\fP, and \fB\e?\fP are not removed, and octal escapes
-beginning with \fB\e0\fP may contain up to four digits),
-and \fB%q\fP causes \fBprintf\fP to output the corresponding
-\fIargument\fP in a format that can be reused as shell input.
-.sp 1
-The \fB\-v\fP option causes the output to be assigned to the variable
-\fIvar\fP rather than being printed to the standard output.
-.sp 1
-The \fIformat\fP is reused as necessary to consume all of the \fIarguments\fP.
-If the \fIformat\fP requires more \fIarguments\fP than are supplied, the
-extra format specifications behave as if a zero value or null string, as
-appropriate, had been supplied. The return value is zero on success,
-non-zero on failure.
-.TP
-\fBpushd\fP [\fB\-n\fP] [\fIdir\fP]
-.PD 0
-.TP
-\fBpushd\fP [\fB\-n\fP] [+\fIn\fP] [\-\fIn\fP]
-.PD
-Adds a directory to the top of the directory stack, or rotates
-the stack, making the new top of the stack the current working
-directory. With no arguments, exchanges the top two directories
-and returns 0, unless the directory stack is empty.
-Arguments, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-\fB+\fP\fIn\fP
-Rotates the stack so that the \fIn\fPth directory
-(counting from the left of the list shown by
-.BR dirs ,
-starting with zero)
-is at the top.
-.TP
-\fB\-\fP\fIn\fP
-Rotates the stack so that the \fIn\fPth directory
-(counting from the right of the list shown by
-.BR dirs ,
-starting with zero) is at the top.
-.TP
-.B \-n
-Suppresses the normal change of directory when adding directories
-to the stack, so that only the stack is manipulated.
-.TP
-.I dir
-Adds
-.I dir
-to the directory stack at the top, making it the
-new current working directory.
-.PD
-.PP
-If the
-.B pushd
-command is successful, a
-.B dirs
-is performed as well.
-If the first form is used,
-.B pushd
-returns 0 unless the cd to
-.I dir
-fails. With the second form,
-.B pushd
-returns 0 unless the directory stack is empty,
-a non-existent directory stack element is specified,
-or the directory change to the specified new current directory
-fails.
-.RE
-.TP
-\fBpwd\fP [\fB\-LP\fP]
-Print the absolute pathname of the current working directory.
-The pathname printed contains no symbolic links if the
-.B \-P
-option is supplied or the
-.B \-o physical
-option to the
-.B set
-builtin command is enabled.
-If the
-.B \-L
-option is used, the pathname printed may contain symbolic links.
-The return status is 0 unless an error occurs while
-reading the name of the current directory or an
-invalid option is supplied.
-.TP
-\fBread\fP [\fB\-ers\fP] [\fB\-u\fP \fIfd\fP] [\fB\-t\fP \fItimeout\fP] [\fB\-a\fP \fIaname\fP] [\fB\-p\fP \fIprompt\fP] [\fB\-n\fP \fInchars\fP] [\fB\-d\fP \fIdelim\fP] [\fIname\fP ...]
-One line is read from the standard input, or from the file descriptor
-\fIfd\fP supplied as an argument to the \fB\-u\fP option, and the first word
-is assigned to the first
-.IR name ,
-the second word to the second
-.IR name ,
-and so on, with leftover words and their intervening separators assigned
-to the last
-.IR name .
-If there are fewer words read from the input stream than names,
-the remaining names are assigned empty values.
-The characters in
-.SM
-.B IFS
-are used to split the line into words.
-The backslash character (\fB\e\fP) may be used to remove any special
-meaning for the next character read and for line continuation.
-Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-a \fIaname\fP
-The words are assigned to sequential indices
-of the array variable
-.IR aname ,
-starting at 0.
-.I aname
-is unset before any new values are assigned.
-Other \fIname\fP arguments are ignored.
-.TP
-.B \-d \fIdelim\fP
-The first character of \fIdelim\fP is used to terminate the input line,
-rather than newline.
-.TP
-.B \-e
-If the standard input
-is coming from a terminal,
-.B readline
-(see
-.SM
-.B READLINE
-above) is used to obtain the line.
-.TP
-.B \-n \fInchars\fP
-\fBread\fP returns after reading \fInchars\fP characters rather than
-waiting for a complete line of input.
-.TP
-.B \-p \fIprompt\fP
-Display \fIprompt\fP on standard error, without a
-trailing newline, before attempting to read any input. The prompt
-is displayed only if input is coming from a terminal.
-.TP
-.B \-r
-Backslash does not act as an escape character.
-The backslash is considered to be part of the line.
-In particular, a backslash-newline pair may not be used as a line
-continuation.
-.TP
-.B \-s
-Silent mode. If input is coming from a terminal, characters are
-not echoed.
-.TP
-.B \-t \fItimeout\fP
-Cause \fBread\fP to time out and return failure if a complete line of
-input is not read within \fItimeout\fP seconds.
-This option has no effect if \fBread\fP is not reading input from the
-terminal or a pipe.
-.TP
-.B \-u \fIfd\fP
-Read input from file descriptor \fIfd\fP.
-.PD
-.PP
-If no
-.I names
-are supplied, the line read is assigned to the variable
-.SM
-.BR REPLY .
-The return code is zero, unless end-of-file is encountered, \fBread\fP
-times out, or an invalid file descriptor is supplied as the argument to
-\fB\-u\fP.
-.RE
-.TP
-\fBreadonly\fP [\fB\-apf\fP] [\fIname\fP[=\fIword\fP] ...]
-.PD
-The given
-\fInames\fP are marked readonly; the values of these
-.I names
-may not be changed by subsequent assignment.
-If the
-.B \-f
-option is supplied, the functions corresponding to the
-\fInames\fP are so
-marked.
-The
-.B \-a
-option restricts the variables to arrays.
-If no
-.I name
-arguments are given, or if the
-.B \-p
-option is supplied, a list of all readonly names is printed.
-The
-.B \-p
-option causes output to be displayed in a format that
-may be reused as input.
-If a variable name is followed by =\fIword\fP, the value of
-the variable is set to \fIword\fP.
-The return status is 0 unless an invalid option is encountered,
-one of the
-.I names
-is not a valid shell variable name, or
-.B \-f
-is supplied with a
-.I name
-that is not a function.
-.TP
-\fBreturn\fP [\fIn\fP]
-Causes a function to exit with the return value specified by
-.IR n .
-If
-.I n
-is omitted, the return status is that of the last command
-executed in the function body. If used outside a function,
-but during execution of a script by the
-.B .
-(\fBsource\fP) command, it causes the shell to stop executing
-that script and return either
-.I n
-or the exit status of the last command executed within the
-script as the exit status of the script. If used outside a
-function and not during execution of a script by \fB.\fP\^,
-the return status is false.
-Any command associated with the \fBRETURN\fP trap is executed
-before execution resumes after the function or script.
-.TP
-\fBset\fP [\fB\-\-abefhkmnptuvxBCHP\fP] [\fB\-o\fP \fIoption\fP] [\fIarg\fP ...]
-Without options, the name and value of each shell variable are displayed
-in a format that can be reused as input
-for setting or resetting the currently-set variables.
-Read-only variables cannot be reset.
-In \fIposix mode\fP, only shell variables are listed.
-The output is sorted according to the current locale.
-When options are specified, they set or unset shell attributes.
-Any arguments remaining after the options are processed are treated
-as values for the positional parameters and are assigned, in order, to
-.BR $1 ,
-.BR $2 ,
-.B ...
-.BR $\fIn\fP .
-Options, if specified, have the following meanings:
-.RS
-.PD 0
-.TP 8
-.B \-a
-Automatically mark variables and functions which are modified or
-created for export to the environment of subsequent commands.
-.TP 8
-.B \-b
-Report the status of terminated background jobs
-immediately, rather than before the next primary prompt. This is
-effective only when job control is enabled.
-.TP 8
-.B \-e
-Exit immediately if a \fIsimple command\fP (see
-.SM
-.B SHELL GRAMMAR
-above) exits with a non-zero status.
-The shell does not exit if the
-command that fails is part of the command list immediately following a
-.B while
-or
-.B until
-keyword,
-part of the test in an
-.I if
-statement, part of a
-.B &&
-or
-.B \(bv\(bv
-list, or if the command's return value is
-being inverted via
-.BR ! .
-A trap on \fBERR\fP, if set, is executed before the shell exits.
-.TP 8
-.B \-f
-Disable pathname expansion.
-.TP 8
-.B \-h
-Remember the location of commands as they are looked up for execution.
-This is enabled by default.
-.TP 8
-.B \-k
-All arguments in the form of assignment statements
-are placed in the environment for a command, not just
-those that precede the command name.
-.TP 8
-.B \-m
-Monitor mode. Job control is enabled. This option is on
-by default for interactive shells on systems that support
-it (see
-.SM
-.B JOB CONTROL
-above). Background processes run in a separate process
-group and a line containing their exit status is printed
-upon their completion.
-.TP 8
-.B \-n
-Read commands but do not execute them. This may be used to
-check a shell script for syntax errors. This is ignored by
-interactive shells.
-.TP 8
-.B \-o \fIoption\-name\fP
-The \fIoption\-name\fP can be one of the following:
-.RS
-.TP 8
-.B allexport
-Same as
-.BR \-a .
-.TP 8
-.B braceexpand
-Same as
-.BR \-B .
-.TP 8
-.B emacs
-Use an emacs-style command line editing interface. This is enabled
-by default when the shell is interactive, unless the shell is started
-with the
-.B \-\-noediting
-option.
-.TP 8
-.B errtrace
-Same as
-.BR \-E .
-.TP 8
-.B functrace
-Same as
-.BR \-T .
-.TP 8
-.B errexit
-Same as
-.BR \-e .
-.TP 8
-.B hashall
-Same as
-.BR \-h .
-.TP 8
-.B histexpand
-Same as
-.BR \-H .
-.TP 8
-.B history
-Enable command history, as described above under
-.SM
-.BR HISTORY .
-This option is on by default in interactive shells.
-.TP 8
-.B ignoreeof
-The effect is as if the shell command
-.if t \f(CWIGNOREEOF=10\fP
-.if n ``IGNOREEOF=10''
-had been executed
-(see
-.B Shell Variables
-above).
-.TP 8
-.B keyword
-Same as
-.BR \-k .
-.TP 8
-.B monitor
-Same as
-.BR \-m .
-.TP 8
-.B noclobber
-Same as
-.BR \-C .
-.TP 8
-.B noexec
-Same as
-.BR \-n .
-.TP 8
-.B noglob
-Same as
-.BR \-f .
-.B nolog
-Currently ignored.
-.TP 8
-.B notify
-Same as
-.BR \-b .
-.TP 8
-.B nounset
-Same as
-.BR \-u .
-.TP 8
-.B onecmd
-Same as
-.BR \-t .
-.TP 8
-.B physical
-Same as
-.BR \-P .
-.TP 8
-.B pipefail
-If set, the return value of a pipeline is the value of the last
-(rightmost) command to exit with a non-zero status, or zero if all
-commands in the pipeline exit successfully.
-This option is disabled by default.
-.TP 8
-.B posix
-Change the behavior of
-.B bash
-where the default operation differs
-from the POSIX standard to match the standard (\fIposix mode\fP).
-.TP 8
-.B privileged
-Same as
-.BR \-p .
-.TP 8
-.B verbose
-Same as
-.BR \-v .
-.TP 8
-.B vi
-Use a vi-style command line editing interface.
-.TP 8
-.B xtrace
-Same as
-.BR \-x .
-.sp .5
-.PP
-If
-.B \-o
-is supplied with no \fIoption\-name\fP, the values of the current options are
-printed.
-If
-.B +o
-is supplied with no \fIoption\-name\fP, a series of
-.B set
-commands to recreate the current option settings is displayed on
-the standard output.
-.RE
-.TP 8
-.B \-p
-Turn on
-.I privileged
-mode. In this mode, the
-.SM
-.B $ENV
-and
-.SM
-.B $BASH_ENV
-files are not processed, shell functions are not inherited from the
-environment, and the
-.SM
-.B SHELLOPTS
-variable, if it appears in the environment, is ignored.
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the \fB\-p\fP option is not supplied, these actions
-are taken and the effective user id is set to the real user id.
-If the \fB\-p\fP option is supplied at startup, the effective user id is
-not reset.
-Turning this option off causes the effective user
-and group ids to be set to the real user and group ids.
-.TP 8
-.B \-t
-Exit after reading and executing one command.
-.TP 8
-.B \-u
-Treat unset variables as an error when performing
-parameter expansion. If expansion is attempted on an
-unset variable, the shell prints an error message, and,
-if not interactive, exits with a non-zero status.
-.TP 8
-.B \-v
-Print shell input lines as they are read.
-.TP 8
-.B \-x
-After expanding each \fIsimple command\fP,
-\fBfor\fP command, \fBcase\fP command, \fBselect\fP command, or
-arithmetic \fBfor\fP command, display the expanded value of
-.SM
-.BR PS4 ,
-followed by the command and its expanded arguments
-or associated word list.
-.TP 8
-.B \-B
-The shell performs brace expansion (see
-.B Brace Expansion
-above). This is on by default.
-.TP 8
-.B \-C
-If set,
-.B bash
-does not overwrite an existing file with the
-.BR > ,
-.BR >& ,
-and
-.B <>
-redirection operators. This may be overridden when
-creating output files by using the redirection operator
-.B >|
-instead of
-.BR > .
-.TP 8
-.B \-E
-If set, any trap on \fBERR\fP is inherited by shell functions, command
-substitutions, and commands executed in a subshell environment.
-The \fBERR\fP trap is normally not inherited in such cases.
-.TP 8
-.B \-H
-Enable
-.B !
-style history substitution. This option is on by
-default when the shell is interactive.
-.TP 8
-.B \-P
-If set, the shell does not follow symbolic links when executing
-commands such as
-.B cd
-that change the current working directory. It uses the
-physical directory structure instead. By default,
-.B bash
-follows the logical chain of directories when performing commands
-which change the current directory.
-.TP 8
-.B \-T
-If set, any traps on \fBDEBUG\fP and \fBRETURN\fP are inherited by shell
-functions, command substitutions, and commands executed in a
-subshell environment.
-The \fBDEBUG\fP and \fBRETURN\fP traps are normally not inherited
-in such cases.
-.TP 8
-.B \-\-
-If no arguments follow this option, then the positional parameters are
-unset. Otherwise, the positional parameters are set to the
-\fIarg\fPs, even if some of them begin with a
-.BR \- .
-.TP 8
-.B \-
-Signal the end of options, cause all remaining \fIarg\fPs to be
-assigned to the positional parameters. The
-.B \-x
-and
-.B \-v
-options are turned off.
-If there are no \fIarg\fPs,
-the positional parameters remain unchanged.
-.PD
-.PP
-The options are off by default unless otherwise noted.
-Using + rather than \- causes these options to be turned off.
-The options can also be specified as arguments to an invocation of
-the shell.
-The current set of options may be found in
-.BR $\- .
-The return status is always true unless an invalid option is encountered.
-.RE
-.TP
-\fBshift\fP [\fIn\fP]
-The positional parameters from \fIn\fP+1 ... are renamed to
-.B $1
-.B ....
-Parameters represented by the numbers \fB$#\fP
-down to \fB$#\fP\-\fIn\fP+1 are unset.
-.I n
-must be a non-negative number less than or equal to \fB$#\fP.
-If
-.I n
-is 0, no parameters are changed.
-If
-.I n
-is not given, it is assumed to be 1.
-If
-.I n
-is greater than \fB$#\fP, the positional parameters are not changed.
-The return status is greater than zero if
-.I n
-is greater than
-.B $#
-or less than zero; otherwise 0.
-.TP
-\fBshopt\fP [\fB\-pqsu\fP] [\fB\-o\fP] [\fIoptname\fP ...]
-Toggle the values of variables controlling optional shell behavior.
-With no options, or with the
-.B \-p
-option, a list of all settable options is displayed, with
-an indication of whether or not each is set.
-The \fB\-p\fP option causes output to be displayed in a form that
-may be reused as input.
-Other options have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-s
-Enable (set) each \fIoptname\fP.
-.TP
-.B \-u
-Disable (unset) each \fIoptname\fP.
-.TP
-.B \-q
-Suppresses normal output (quiet mode); the return status indicates
-whether the \fIoptname\fP is set or unset.
-If multiple \fIoptname\fP arguments are given with
-.BR \-q ,
-the return status is zero if all \fIoptnames\fP are enabled; non-zero
-otherwise.
-.TP
-.B \-o
-Restricts the values of \fIoptname\fP to be those defined for the
-.B \-o
-option to the
-.B set
-builtin.
-.PD
-.PP
-If either
-.B \-s
-or
-.B \-u
-is used with no \fIoptname\fP arguments, the display is limited to
-those options which are set or unset, respectively.
-Unless otherwise noted, the \fBshopt\fP options are disabled (unset)
-by default.
-.PP
-The return status when listing options is zero if all \fIoptnames\fP
-are enabled, non-zero otherwise. When setting or unsetting options,
-the return status is zero unless an \fIoptname\fP is not a valid shell
-option.
-.PP
-The list of \fBshopt\fP options is:
-.if t .sp .5v
-.if n .sp 1v
-.PD 0
-.TP 8
-.B cdable_vars
-If set, an argument to the
-.B cd
-builtin command that
-is not a directory is assumed to be the name of a variable whose
-value is the directory to change to.
-.TP 8
-.B cdspell
-If set, minor errors in the spelling of a directory component in a
-.B cd
-command will be corrected.
-The errors checked for are transposed characters,
-a missing character, and one character too many.
-If a correction is found, the corrected file name is printed,
-and the command proceeds.
-This option is only used by interactive shells.
-.TP 8
-.B checkhash
-If set, \fBbash\fP checks that a command found in the hash
-table exists before trying to execute it. If a hashed command no
-longer exists, a normal path search is performed.
-.TP 8
-.B checkwinsize
-If set, \fBbash\fP checks the window size after each command
-and, if necessary, updates the values of
-.SM
-.B LINES
-and
-.SM
-.BR COLUMNS .
-.TP 8
-.B cmdhist
-If set,
-.B bash
-attempts to save all lines of a multiple-line
-command in the same history entry. This allows
-easy re-editing of multi-line commands.
-.TP 8
-.B dotglob
-If set,
-.B bash
-includes filenames beginning with a `.' in the results of pathname
-expansion.
-.TP 8
-.B execfail
-If set, a non-interactive shell will not exit if
-it cannot execute the file specified as an argument to the
-.B exec
-builtin command. An interactive shell does not exit if
-.B exec
-fails.
-.TP 8
-.B expand_aliases
-If set, aliases are expanded as described above under
-.SM
-.BR ALIASES .
-This option is enabled by default for interactive shells.
-.TP 8
-.B extdebug
-If set, behavior intended for use by debuggers is enabled:
-.RS
-.TP
-.B 1.
-The \fB\-F\fP option to the \fBdeclare\fP builtin displays the source
-file name and line number corresponding to each function name supplied
-as an argument.
-.TP
-.B 2.
-If the command run by the \fBDEBUG\fP trap returns a non-zero value, the
-next command is skipped and not executed.
-.TP
-.B 3.
-If the command run by the \fBDEBUG\fP trap returns a value of 2, and the
-shell is executing in a subroutine (a shell function or a shell script
-executed by the \fB.\fP or \fBsource\fP builtins), a call to
-\fBreturn\fP is simulated.
-.TP
-.B 4.
-\fBBASH_ARGC\fP and \fBBASH_ARGV\fP are updated as described in their
-descriptions above.
-.TP
-.B 5.
-Function tracing is enabled: command substitution, shell functions, and
-subshells invoked with \fB(\fP \fIcommand\fP \fB)\fP inherit the
-\fBDEBUG\fP and \fBRETURN\fP traps.
-.TP
-.B 6.
-Error tracing is enabled: command substitution, shell functions, and
-subshells invoked with \fB(\fP \fIcommand\fP \fB)\fP inherit the
-\fBERROR\fP trap.
-.RE
-.TP 8
-.B extglob
-If set, the extended pattern matching features described above under
-\fBPathname Expansion\fP are enabled.
-.TP 8
-.B extquote
-If set, \fB$\fP\(aq\fIstring\fP\(aq and \fB$\fP"\fIstring\fP" quoting is
-performed within \fB${\fP\fIparameter\fP\fB}\fP expansions
-enclosed in double quotes. This option is enabled by default.
-.TP 8
-.B failglob
-If set, patterns which fail to match filenames during pathname expansion
-result in an expansion error.
-.TP 8
-.B force_fignore
-If set, the suffixes specified by the \fBFIGNORE\fP shell variable
-cause words to be ignored when performing word completion even if
-the ignored words are the only possible completions.
-See
-.SM
-\fBSHELL VARIABLES\fP
-above for a description of \fBFIGNORE\fP.
-This option is enabled by default.
-.TP 8
-.B gnu_errfmt
-If set, shell error messages are written in the standard GNU error
-message format.
-.TP 8
-.B histappend
-If set, the history list is appended to the file named by the value
-of the
-.B HISTFILE
-variable when the shell exits, rather than overwriting the file.
-.TP 8
-.B histreedit
-If set, and
-.B readline
-is being used, a user is given the opportunity to re-edit a
-failed history substitution.
-.TP 8
-.B histverify
-If set, and
-.B readline
-is being used, the results of history substitution are not immediately
-passed to the shell parser. Instead, the resulting line is loaded into
-the \fBreadline\fP editing buffer, allowing further modification.
-.TP 8
-.B hostcomplete
-If set, and
-.B readline
-is being used, \fBbash\fP will attempt to perform hostname completion when a
-word containing a \fB@\fP is being completed (see
-.B Completing
-under
-.SM
-.B READLINE
-above).
-This is enabled by default.
-.TP 8
-.B huponexit
-If set, \fBbash\fP will send
-.SM
-.B SIGHUP
-to all jobs when an interactive login shell exits.
-.TP 8
-.B interactive_comments
-If set, allow a word beginning with
-.B #
-to cause that word and all remaining characters on that
-line to be ignored in an interactive shell (see
-.SM
-.B COMMENTS
-above). This option is enabled by default.
-.TP 8
-.B lithist
-If set, and the
-.B cmdhist
-option is enabled, multi-line commands are saved to the history with
-embedded newlines rather than using semicolon separators where possible.
-.TP 8
-.B login_shell
-The shell sets this option if it is started as a login shell (see
-.SM
-.B "INVOCATION"
-above).
-The value may not be changed.
-.TP 8
-.B mailwarn
-If set, and a file that \fBbash\fP is checking for mail has been
-accessed since the last time it was checked, the message ``The mail in
-\fImailfile\fP has been read'' is displayed.
-.TP 8
-.B no_empty_cmd_completion
-If set, and
-.B readline
-is being used,
-.B bash
-will not attempt to search the \fBPATH\fP for possible completions when
-completion is attempted on an empty line.
-.TP 8
-.B nocaseglob
-If set,
-.B bash
-matches filenames in a case\-insensitive fashion when performing pathname
-expansion (see
-.B Pathname Expansion
-above).
-.TP 8
-.B nocasematch
-If set,
-.B bash
-matches patterns in a case\-insensitive fashion when performing matching
-while executing \fBcase\fP or \fB[[\fP conditional commands.
-.TP 8
-.B nullglob
-If set,
-.B bash
-allows patterns which match no
-files (see
-.B Pathname Expansion
-above)
-to expand to a null string, rather than themselves.
-.TP 8
-.B progcomp
-If set, the programmable completion facilities (see
-\fBProgrammable Completion\fP above) are enabled.
-This option is enabled by default.
-.TP 8
-.B promptvars
-If set, prompt strings undergo
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal after being expanded as described in
-.SM
-.B PROMPTING
-above. This option is enabled by default.
-.TP 8
-.B restricted_shell
-The shell sets this option if it is started in restricted mode (see
-.SM
-.B "RESTRICTED SHELL"
-below).
-The value may not be changed.
-This is not reset when the startup files are executed, allowing
-the startup files to discover whether or not a shell is restricted.
-.TP 8
-.B shift_verbose
-If set, the
-.B shift
-builtin prints an error message when the shift count exceeds the
-number of positional parameters.
-.TP 8
-.B sourcepath
-If set, the
-\fBsource\fP (\fB.\fP) builtin uses the value of
-.SM
-.B PATH
-to find the directory containing the file supplied as an argument.
-This option is enabled by default.
-.TP 8
-.B xpg_echo
-If set, the \fBecho\fP builtin expands backslash-escape sequences
-by default.
-.RE
-.TP
-\fBsuspend\fP [\fB\-f\fP]
-Suspend the execution of this shell until it receives a
-.SM
-.B SIGCONT
-signal. The
-.B \-f
-option says not to complain if this is
-a login shell; just suspend anyway. The return status is 0 unless
-the shell is a login shell and
-.B \-f
-is not supplied, or if job control is not enabled.
-.TP
-\fBtest\fP \fIexpr\fP
-.PD 0
-.TP
-\fB[\fP \fIexpr\fP \fB]\fP
-Return a status of 0 or 1 depending on
-the evaluation of the conditional expression
-.IR expr .
-Each operator and operand must be a separate argument.
-Expressions are composed of the primaries described above under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" .
-\fBtest\fP does not accept any options, nor does it accept and ignore
-an argument of \fB\-\-\fP as signifying the end of options.
-.if t .sp 0.5
-.if n .sp 1
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence.
-.RS
-.PD 0
-.TP
-.B ! \fIexpr\fP
-True if
-.I expr
-is false.
-.TP
-.B ( \fIexpr\fP )
-Returns the value of \fIexpr\fP.
-This may be used to override the normal precedence of operators.
-.TP
-\fIexpr1\fP \-\fBa\fP \fIexpr2\fP
-True if both
-.I expr1
-and
-.I expr2
-are true.
-.TP
-\fIexpr1\fP \-\fBo\fP \fIexpr2\fP
-True if either
-.I expr1
-or
-.I expr2
-is true.
-.PD
-.PP
-\fBtest\fP and \fB[\fP evaluate conditional
-expressions using a set of rules based on the number of arguments.
-.if t .sp 0.5
-.if n .sp 1
-.PD 0
-.TP
-0 arguments
-The expression is false.
-.TP
-1 argument
-The expression is true if and only if the argument is not null.
-.TP
-2 arguments
-If the first argument is \fB!\fP, the expression is true if and
-only if the second argument is null.
-If the first argument is one of the unary conditional operators listed above
-under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" ,
-the expression is true if the unary test is true.
-If the first argument is not a valid unary conditional operator, the expression
-is false.
-.TP
-3 arguments
-If the second argument is one of the binary conditional operators listed above
-under
-.SM
-.BR "CONDITIONAL EXPRESSIONS" ,
-the result of the expression is the result of the binary test using
-the first and third arguments as operands.
-If the first argument is \fB!\fP, the value is the negation of
-the two-argument test using the second and third arguments.
-If the first argument is exactly \fB(\fP and the third argument is
-exactly \fB)\fP, the result is the one-argument test of the second
-argument.
-Otherwise, the expression is false.
-The \fB\-a\fP and \fB\-o\fP operators are considered binary operators
-in this case.
-.TP
-4 arguments
-If the first argument is \fB!\fP, the result is the negation of
-the three-argument expression composed of the remaining arguments.
-Otherwise, the expression is parsed and evaluated according to
-precedence using the rules listed above.
-.TP
-5 or more arguments
-The expression is parsed and evaluated according to precedence
-using the rules listed above.
-.RE
-.PD
-.TP
-.B times
-Print the accumulated user and system times for the shell and
-for processes run from the shell. The return status is 0.
-.TP
-\fBtrap\fP [\fB\-lp\fP] [[\fIarg\fP] \fIsigspec\fP ...]
-The command
-.I arg
-is to be read and executed when the shell receives
-signal(s)
-.IR sigspec .
-If
-.I arg
-is absent (and there is a single \fIsigspec\fP) or
-.BR \- ,
-each specified signal is
-reset to its original disposition (the value it had
-upon entrance to the shell).
-If
-.I arg
-is the null string the signal specified by each
-.I sigspec
-is ignored by the shell and by the commands it invokes.
-If
-.I arg
-is not present and
-.B \-p
-has been supplied, then the trap commands associated with each
-.I sigspec
-are displayed.
-If no arguments are supplied or if only
-.B \-p
-is given,
-.B trap
-prints the list of commands associated with each signal.
-The
-.B \-l
-option causes the shell to print a list of signal names and
-their corresponding numbers.
-Each
-.I sigspec
-is either
-a signal name defined in <\fIsignal.h\fP>, or a signal number.
-Signal names are case insensitive and the SIG prefix is optional.
-If a
-.I sigspec
-is
-.SM
-.B EXIT
-(0) the command
-.I arg
-is executed on exit from the shell.
-If a
-.I sigspec
-is
-.SM
-.BR DEBUG ,
-the command
-.I arg
-is executed before every \fIsimple command\fP, \fIfor\fP command,
-\fIcase\fP command, \fIselect\fP command, every arithmetic \fIfor\fP
-command, and before the first command executes in a shell function (see
-.SM
-.B SHELL GRAMMAR
-above).
-Refer to the description of the \fBextdebug\fP option to the
-\fBshopt\fP builtin for details of its effect on the \fBDEBUG\fP trap.
-If a
-.I sigspec
-is
-.SM
-.BR ERR ,
-the command
-.I arg
-is executed whenever a simple command has a non\-zero exit status,
-subject to the following conditions.
-The
-.SM
-.B ERR
-trap is not executed if the failed
-command is part of the command list immediately following a
-.B while
-or
-.B until
-keyword,
-part of the test in an
-.I if
-statement, part of a
-.B &&
-or
-.B \(bv\(bv
-list, or if the command's return value is
-being inverted via
-.BR ! .
-These are the same conditions obeyed by the \fBerrexit\fP option.
-If a
-.I sigspec
-is
-.SM
-.BR RETURN ,
-the command
-.I arg
-is executed each time a shell function or a script executed with the
-\fB.\fP or \fBsource\fP builtins finishes executing.
-Signals ignored upon entry to the shell cannot be trapped or reset.
-Trapped signals that are not being ignored are reset to their original
-values in a child process when it is created.
-The return status is false if any
-.I sigspec
-is invalid; otherwise
-.B trap
-returns true.
-.TP
-\fBtype\fP [\fB\-aftpP\fP] \fIname\fP [\fIname\fP ...]
-With no options,
-indicate how each
-.I name
-would be interpreted if used as a command name.
-If the
-.B \-t
-option is used,
-.B type
-prints a string which is one of
-.IR alias ,
-.IR keyword ,
-.IR function ,
-.IR builtin ,
-or
-.I file
-if
-.I name
-is an alias, shell reserved word, function, builtin, or disk file,
-respectively.
-If the
-.I name
-is not found, then nothing is printed, and an exit status of false
-is returned.
-If the
-.B \-p
-option is used,
-.B type
-either returns the name of the disk file
-that would be executed if
-.I name
-were specified as a command name,
-or nothing if
-.if t \f(CWtype -t name\fP
-.if n ``type -t name''
-would not return
-.IR file .
-The
-.B \-P
-option forces a
-.SM
-.B PATH
-search for each \fIname\fP, even if
-.if t \f(CWtype -t name\fP
-.if n ``type -t name''
-would not return
-.IR file .
-If a command is hashed,
-.B \-p
-and
-.B \-P
-print the hashed value, not necessarily the file that appears
-first in
-.SM
-.BR PATH .
-If the
-.B \-a
-option is used,
-.B type
-prints all of the places that contain
-an executable named
-.IR name .
-This includes aliases and functions,
-if and only if the
-.B \-p
-option is not also used.
-The table of hashed commands is not consulted
-when using
-.BR \-a .
-The
-.B \-f
-option suppresses shell function lookup, as with the \fBcommand\fP builtin.
-.B type
-returns true if any of the arguments are found, false if
-none are found.
-.TP
-\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
-set for the given resource. A hard limit cannot be increased once it
-is set; a soft limit may be increased up to the value of the hard limit.
-If neither \fB\-H\fP nor \fB\-S\fP is specified, both the soft and hard
-limits are set.
-The value of
-.I limit
-can be a number in the unit specified for the resource
-or one of the special values
-.BR hard ,
-.BR soft ,
-or
-.BR unlimited ,
-which stand for the current hard limit, the current soft limit, and
-no limit, respectively.
-If
-.I limit
-is omitted, the current value of the soft limit of the resource is
-printed, unless the \fB\-H\fP option is given. When more than one
-resource is specified, the limit name and unit are printed before the value.
-Other options are interpreted as follows:
-.RS
-.PD 0
-.TP
-.B \-a
-All current limits are reported
-.TP
-.B \-c
-The maximum size of core files created
-.TP
-.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 written by the shell and its children
-.TP
-.B \-i
-The maximum number of pending signals
-.TP
-.B \-l
-The maximum size that may be locked into memory
-.TP
-.B \-m
-The maximum resident set size
-.TP
-.B \-n
-The maximum number of open file descriptors (most systems do not
-allow this value to be set)
-.TP
-.B \-p
-The pipe size in 512-byte blocks (this may not be set)
-.TP
-.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
-.B \-t
-The maximum amount of cpu time in seconds
-.TP
-.B \-u
-The maximum number of processes available to a single user
-.TP
-.B \-v
-The maximum amount of virtual memory available to the shell
-.TP
-.B \-x
-The maximum number of file locks
-.PD
-.PP
-If
-.I limit
-is given, it is the new value of the specified resource (the
-.B \-a
-option is display only).
-If no option is given, then
-.B \-f
-is assumed. Values are in 1024-byte increments, except for
-.BR \-t ,
-which is in seconds,
-.BR \-p ,
-which is in units of 512-byte blocks,
-and
-.B \-n
-and
-.BR \-u ,
-which are unscaled values.
-The return status is 0 unless an invalid option or argument is supplied,
-or an error occurs while setting a new limit.
-.RE
-.TP
-\fBumask\fP [\fB\-p\fP] [\fB\-S\fP] [\fImode\fP]
-The user file-creation mask is set to
-.IR mode .
-If
-.I mode
-begins with a digit, it
-is interpreted as an octal number; otherwise
-it is interpreted as a symbolic mode mask similar
-to that accepted by
-.IR chmod (1).
-If
-.I mode
-is omitted, the current value of the mask is printed.
-The
-.B \-S
-option causes the mask to be printed in symbolic form; the
-default output is an octal number.
-If the
-.B \-p
-option is supplied, and
-.I mode
-is omitted, the output is in a form that may be reused as input.
-The return status is 0 if the mode was successfully changed or if
-no \fImode\fP argument was supplied, and false otherwise.
-.TP
-\fBunalias\fP [\-\fBa\fP] [\fIname\fP ...]
-Remove each \fIname\fP from the list of defined aliases. If
-.B \-a
-is supplied, all alias definitions are removed. The return
-value is true unless a supplied
-.I name
-is not a defined alias.
-.TP
-\fBunset\fP [\-\fBfv\fP] [\fIname\fP ...]
-For each
-.IR name ,
-remove the corresponding variable or function.
-If no options are supplied, or the
-.B \-v
-option is given, each
-.I name
-refers to a shell variable.
-Read-only variables may not be unset.
-If
-.B \-f
-is specified, each
-.I name
-refers to a shell function, and the function definition
-is removed.
-Each unset variable or function is removed from the environment
-passed to subsequent commands.
-If any of
-.SM
-.BR RANDOM ,
-.SM
-.BR SECONDS ,
-.SM
-.BR LINENO ,
-.SM
-.BR HISTCMD ,
-.SM
-.BR FUNCNAME ,
-.SM
-.BR GROUPS ,
-or
-.SM
-.B DIRSTACK
-are unset, they lose their special properties, even if they are
-subsequently reset. The exit status is true unless a
-.I name
-is readonly.
-.TP
-\fBwait\fP [\fIn ...\fP]
-Wait for each specified process and return its termination status.
-Each
-.I n
-may be a process
-ID or a job specification; if a job spec is given, all processes
-in that job's pipeline are waited for. If
-.I n
-is not given, all currently active child processes
-are waited for, and the return status is zero. If
-.I n
-specifies a non-existent process or job, the return status is
-127. Otherwise, the return status is the exit status of the last
-process or job waited for.
-.\" bash_builtins
-.if \n(zZ=1 .ig zZ
-.SH "RESTRICTED SHELL"
-.\" rbash.1
-.zY
-.PP
-If
-.B bash
-is started with the name
-.BR rbash ,
-or the
-.B \-r
-option is supplied at invocation,
-the shell becomes restricted.
-A restricted shell is used to
-set up an environment more controlled than the standard shell.
-It behaves identically to
-.B bash
-with the exception that the following are disallowed or not performed:
-.IP \(bu
-changing directories with \fBcd\fP
-.IP \(bu
-setting or unsetting the values of
-.BR SHELL ,
-.BR PATH ,
-.BR ENV ,
-or
-.B BASH_ENV
-.IP \(bu
-specifying command names containing
-.B /
-.IP \(bu
-specifying a file name containing a
-.B /
-as an argument to the
-.B .
-builtin command
-.IP \(bu
-Specifying a filename containing a slash as an argument to the
-.B \-p
-option to the
-.B hash
-builtin command
-.IP \(bu
-importing function definitions from the shell environment at startup
-.IP \(bu
-parsing the value of \fBSHELLOPTS\fP from the shell environment at startup
-.IP \(bu
-redirecting output using the >, >|, <>, >&, &>, and >> redirection operators
-.IP \(bu
-using the
-.B exec
-builtin command to replace the shell with another command
-.IP \(bu
-adding or deleting builtin commands with the
-.B \-f
-and
-.B \-d
-options to the
-.B enable
-builtin command
-.IP \(bu
-Using the \fBenable\fP builtin command to enable disabled shell builtins
-.IP \(bu
-specifying the
-.B \-p
-option to the
-.B command
-builtin command
-.IP \(bu
-turning off restricted mode with
-\fBset +r\fP or \fBset +o restricted\fP.
-.PP
-These restrictions are enforced after any startup files are read.
-.PP
-.ie \n(zY=1 When a command that is found to be a shell script is executed,
-.el \{ When a command that is found to be a shell script is executed
-(see
-.SM
-.B "COMMAND EXECUTION"
-above),
-\}
-.B rbash
-turns off any restrictions in the shell spawned to execute the
-script.
-.\" end of rbash.1
-.if \n(zY=1 .ig zY
-.SH "SEE ALSO"
-.PD 0
-.TP
-\fIBash Reference Manual\fP, Brian Fox and Chet Ramey
-.TP
-\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey
-.TP
-\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey
-.TP
-\fIPortable Operating System Interface (POSIX) Part 2: Shell and Utilities\fP, IEEE
-.TP
-\fIsh\fP(1), \fIksh\fP(1), \fIcsh\fP(1)
-.TP
-\fIemacs\fP(1), \fIvi\fP(1)
-.TP
-\fIreadline\fP(3)
-.PD
-.SH FILES
-.PD 0
-.TP
-.FN /bin/bash
-The \fBbash\fP executable
-.TP
-.FN /etc/profile
-The systemwide initialization file, executed for login shells
-.TP
-.FN ~/.bash_profile
-The personal initialization file, executed for login shells
-.TP
-.FN ~/.bashrc
-The individual per-interactive-shell startup file
-.TP
-.FN ~/.bash_logout
-The individual login shell cleanup file, executed when a login shell exits
-.TP
-.FN ~/.inputrc
-Individual \fIreadline\fP initialization file
-.PD
-.SH AUTHORS
-Brian Fox, Free Software Foundation
-.br
-bfox@gnu.org
-.PP
-Chet Ramey, Case Western Reserve University
-.br
-chet@po.cwru.edu
-.SH BUG REPORTS
-If you find a bug in
-.B bash,
-you should report it. But first, you should
-make sure that it really is a bug, and that it appears in the latest
-version of
-.BR bash .
-The latest version is always available from
-\fIftp://ftp.gnu.org/pub/bash/\fP.
-.PP
-Once you have determined that a bug actually exists, use the
-.I bashbug
-command to submit a bug report.
-If you have a fix, you are encouraged to mail that as well!
-Suggestions and `philosophical' bug reports may be mailed
-to \fIbug-bash@gnu.org\fP or posted to the Usenet
-newsgroup
-.BR gnu.bash.bug .
-.PP
-ALL bug reports should include:
-.PP
-.PD 0
-.TP 20
-The version number of \fBbash\fR
-.TP
-The hardware and operating system
-.TP
-The compiler used to compile
-.TP
-A description of the bug behaviour
-.TP
-A short script or `recipe' which exercises the bug
-.PD
-.PP
-.I bashbug
-inserts the first three items automatically into the template
-it provides for filing a bug report.
-.PP
-Comments and bug reports concerning
-this manual page should be directed to
-.IR chet@po.cwru.edu .
-.SH BUGS
-.PP
-It's too big and too slow.
-.PP
-There are some subtle differences between
-.B bash
-and traditional versions of
-.BR sh ,
-mostly because of the
-.SM
-.B POSIX
-specification.
-.PP
-Aliases are confusing in some uses.
-.PP
-Shell builtin commands and functions are not stoppable/restartable.
-.PP
-Compound commands and command sequences of the form `a ; b ; c'
-are not handled gracefully when process suspension is attempted.
-When a process is stopped, the shell immediately executes the next
-command in the sequence.
-It suffices to place the sequence of commands between
-parentheses to force it into a subshell, which may be stopped as
-a unit.
-.PP
-Commands inside of \fB$(\fP...\fB)\fP command substitution are not
-parsed until substitution is attempted. This will delay error
-reporting until some time after the command is entered. For example,
-unmatched parentheses, even inside shell comments, will result in
-error messages while the construct is being read.
-.PP
-Array variables may not (yet) be exported.
-.zZ
-.zY
diff --git a/doc/bashref.texi.orig b/doc/bashref.texi.orig
deleted file mode 100644
index fdce9e3c..00000000
--- a/doc/bashref.texi.orig
+++ /dev/null
@@ -1,7105 +0,0 @@
-\input texinfo.tex @c -*- texinfo -*-
-@c %**start of header
-@setfilename bashref.info
-@settitle Bash Reference Manual
-@c %**end of header
-
-@setchapternewpage odd
-
-@include version.texi
-
-@copying
-This text is a brief description of the features that are present in
-the Bash shell (version @value{VERSION}, @value{UPDATED}).
-
-This is Edition @value{EDITION}, last updated @value{UPDATED},
-of @cite{The GNU Bash Reference Manual},
-for @code{Bash}, Version @value{VERSION}.
-
-Copyright @copyright{} 1988-2003 Free Software Foundation, Inc.
-
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.1 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with the Front-Cover texts being ``A GNU Manual,''
-and with the Back-Cover Texts as in (a) below. A copy of the license is
-included in the section entitled ``GNU Free Documentation License.''
-
-(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
-this GNU Manual, like GNU software. Copies published by the Free
-Software Foundation raise funds for GNU development.''
-@end quotation
-@end copying
-
-@defcodeindex bt
-@defcodeindex rw
-@set BashFeatures
-
-@dircategory Basics
-@direntry
-* Bash: (bash). The GNU Bourne-Again SHell.
-@end direntry
-
-@finalout
-
-@titlepage
-@title Bash Reference Manual
-@subtitle Reference Documentation for Bash
-@subtitle Edition @value{EDITION}, for @code{Bash} Version @value{VERSION}.
-@subtitle @value{UPDATED-MONTH}
-@author Chet Ramey, Case Western Reserve University
-@author Brian Fox, Free Software Foundation
-
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-
-@sp 1
-Published by the Free Software Foundation @*
-59 Temple Place, Suite 330, @*
-Boston, MA 02111-1307 @*
-USA @*
-
-@end titlepage
-
-@contents
-
-@ifnottex
-@node Top, Introduction, (dir), (dir)
-@top Bash Features
-
-This text is a brief description of the features that are present in
-the Bash shell (version @value{VERSION}, @value{UPDATED})..
-
-This is Edition @value{EDITION}, last updated @value{UPDATED},
-of @cite{The GNU Bash Reference Manual},
-for @code{Bash}, Version @value{VERSION}.
-
-Bash contains features that appear in other popular shells, and some
-features that only appear in Bash. Some of the shells that Bash has
-borrowed concepts from are the Bourne Shell (@file{sh}), the Korn Shell
-(@file{ksh}), and the C-shell (@file{csh} and its successor,
-@file{tcsh}). The following menu breaks the features up into
-categories based upon which one of these other shells inspired the
-feature.
-
-This manual is meant as a brief introduction to features found in
-Bash. The Bash manual page should be used as the definitive
-reference on shell behavior.
-
-@menu
-* Introduction:: An introduction to the shell.
-
-* Definitions:: Some definitions used in the rest of this
- manual.
-
-* Basic Shell Features:: The shell "building blocks".
-
-* Shell Builtin Commands:: Commands that are a part of the shell.
-
-* Shell Variables:: Variables used or set by Bash.
-
-* Bash Features:: Features found only in Bash.
-
-* Job Control:: A chapter describing what job control is
- and how Bash allows you to use it.
-
-* Using History Interactively:: Chapter dealing with history expansion
- rules.
-
-* Command Line Editing:: Chapter describing the command line
- editing features.
-
-* Installing Bash:: How to build and install Bash on your system.
-
-* Reporting Bugs:: How to report bugs in Bash.
-
-* Major Differences From The Bourne Shell:: A terse list of the differences
- between Bash and historical
- versions of /bin/sh.
-
-* Copying This Manual:: Copying this manual.
-
-* Builtin Index:: Index of Bash builtin commands.
-
-* Reserved Word Index:: Index of Bash reserved words.
-
-* Variable Index:: Quick reference helps you find the
- variable you want.
-
-* Function Index:: Index of bindable Readline functions.
-
-* Concept Index:: General index for concepts described in
- this manual.
-@end menu
-@end ifnottex
-
-@node Introduction
-@chapter Introduction
-@menu
-* What is Bash?:: A short description of Bash.
-
-* What is a shell?:: A brief introduction to shells.
-@end menu
-
-@node What is Bash?
-@section What is Bash?
-
-Bash is the shell, or command language interpreter,
-for the @sc{gnu} operating system.
-The name is an acronym for the @samp{Bourne-Again SHell},
-a pun on Stephen Bourne, the author of the direct ancestor of
-the current Unix shell @code{/bin/sh},
-which appeared in the Seventh Edition Bell Labs Research version
-of Unix.
-
-Bash is largely compatible with @code{sh} and incorporates useful
-features from the Korn shell @code{ksh} and the C shell @code{csh}.
-It is intended to be a conformant implementation of the @sc{ieee}
-@sc{posix} Shell and Tools specification (@sc{ieee} Working Group 1003.2).
-It offers functional improvements over @code{sh} for both interactive and
-programming use.
-
-While the @sc{gnu} operating system provides other shells, including
-a version of @code{csh}, Bash is the default shell.
-Like other @sc{gnu} software, Bash is quite portable. It currently runs
-on nearly every version of Unix and a few other operating systems @minus{}
-independently-supported ports exist for @sc{ms-dos}, @sc{os/2},
-Windows @sc{95/98}, and Windows @sc{nt}.
-
-@node What is a shell?
-@section What is a shell?
-
-At its base, a shell is simply a macro processor that executes
-commands. A Unix shell is both a command interpreter, which
-provides the user interface to the rich set of @sc{gnu} utilities,
-and a programming language, allowing these utilitites to be
-combined. Files containing commands can be created, and become
-commands themselves. These new commands have the same status as
-system commands in directories such as @file{/bin}, allowing users
-or groups to establish custom environments.
-
-A shell allows execution of @sc{gnu} commands, both synchronously and
-asynchronously.
-The shell waits for synchronous commands to complete before accepting
-more input; asynchronous commands continue to execute in parallel
-with the shell while it reads and executes additional commands.
-The @dfn{redirection} constructs permit
-fine-grained control of the input and output of those commands.
-Moreover, the shell allows control over the contents of commands'
-environments.
-Shells may be used interactively or non-interactively: they accept
-input typed from the keyboard or from a file.
-
-Shells also provide a small set of built-in
-commands (@dfn{builtins}) implementing functionality impossible
-or inconvenient to obtain via separate utilities.
-For example, @code{cd}, @code{break}, @code{continue}, and
-@code{exec}) cannot be implemented outside of the shell because
-they directly manipulate the shell itself.
-The @code{history}, @code{getopts}, @code{kill}, or @code{pwd}
-builtins, among others, could be implemented in separate utilities,
-but they are more convenient to use as builtin commands.
-All of the shell builtins are described in
-subsequent sections.
-
-While executing commands is essential, most of the power (and
-complexity) of shells is due to their embedded programming
-languages. Like any high-level language, the shell provides
-variables, flow control constructs, quoting, and functions.
-
-Shells offer features geared specifically for
-interactive use rather than to augment the programming language.
-These interactive features include job control, command line
-editing, history and aliases. Each of these features is
-described in this manual.
-
-@node Definitions
-@chapter Definitions
-These definitions are used throughout the remainder of this manual.
-
-@table @code
-
-@item POSIX
-@cindex POSIX
-A family of open system standards based on Unix. Bash
-is concerned with @sc{posix} 1003.2, the Shell and Tools Standard.
-
-@item blank
-A space or tab character.
-
-@item builtin
-@cindex builtin
-A command that is implemented internally by the shell itself, rather
-than by an executable program somewhere in the file system.
-
-@item control operator
-@cindex control operator
-A @code{word} that performs a control function. It is a @code{newline}
-or one of the following:
-@samp{||}, @samp{&&}, @samp{&}, @samp{;}, @samp{;;},
-@samp{|}, @samp{(}, or @samp{)}.
-
-@item exit status
-@cindex exit status
-The value returned by a command to its caller. The value is restricted
-to eight bits, so the maximum value is 255.
-
-@item field
-@cindex field
-A unit of text that is the result of one of the shell expansions. After
-expansion, when executing a command, the resulting fields are used as
-the command name and arguments.
-
-@item filename
-@cindex filename
-A string of characters used to identify a file.
-
-@item job
-@cindex job
-A set of processes comprising a pipeline, and any processes descended
-from it, that are all in the same process group.
-
-@item job control
-@cindex job control
-A mechanism by which users can selectively stop (suspend) and restart
-(resume) execution of processes.
-
-@item metacharacter
-@cindex metacharacter
-A character that, when unquoted, separates words. A metacharacter is
-a @code{blank} or one of the following characters:
-@samp{|}, @samp{&}, @samp{;}, @samp{(}, @samp{)}, @samp{<}, or
-@samp{>}.
-
-@item name
-@cindex name
-@cindex identifier
-A @code{word} consisting solely of letters, numbers, and underscores,
-and beginning with a letter or underscore. @code{Name}s are used as
-shell variable and function names.
-Also referred to as an @code{identifier}.
-
-@item operator
-@cindex operator, shell
-A @code{control operator} or a @code{redirection operator}.
-@xref{Redirections}, for a list of redirection operators.
-
-@item process group
-@cindex process group
-A collection of related processes each having the same process
-group @sc{id}.
-
-@item process group ID
-@cindex process group ID
-A unique identifer that represents a @code{process group}
-during its lifetime.
-
-@item reserved word
-@cindex reserved word
-A @code{word} that has a special meaning to the shell. Most reserved
-words introduce shell flow control constructs, such as @code{for} and
-@code{while}.
-
-@item return status
-@cindex return status
-A synonym for @code{exit status}.
-
-@item signal
-@cindex signal
-A mechanism by which a process may be notified by the kernel
-of an event occurring in the system.
-
-@item special builtin
-@cindex special builtin
-A shell builtin command that has been classified as special by the
-@sc{posix} 1003.2 standard.
-
-@item token
-@cindex token
-A sequence of characters considered a single unit by the shell. It is
-either a @code{word} or an @code{operator}.
-
-@item word
-@cindex word
-A @code{token} that is not an @code{operator}.
-@end table
-
-@node Basic Shell Features
-@chapter Basic Shell Features
-@cindex Bourne shell
-
-Bash is an acronym for @samp{Bourne-Again SHell}.
-The Bourne shell is
-the traditional Unix shell originally written by Stephen Bourne.
-All of the Bourne shell builtin commands are available in Bash,
-and the rules for evaluation and quoting are taken from the @sc{posix}
-1003.2 specification for the `standard' Unix shell.
-
-This chapter briefly summarizes the shell's `building blocks':
-commands, control structures, shell functions, shell @i{parameters},
-shell expansions,
-@i{redirections}, which are a way to direct input and output from
-and to named files, and how the shell executes commands.
-
-@menu
-* Shell Syntax:: What your input means to the shell.
-* Shell Commands:: The types of commands you can use.
-* Shell Functions:: Grouping commands by name.
-* Shell Parameters:: How the shell stores values.
-* Shell Expansions:: How Bash expands parameters and the various
- expansions available.
-* Redirections:: A way to control where input and output go.
-* Executing Commands:: What happens when you run a command.
-* Shell Scripts:: Executing files of shell commands.
-@end menu
-
-@node Shell Syntax
-@section Shell Syntax
-@menu
-* Shell Operation:: The basic operation of the shell.
-
-* Quoting:: How to remove the special meaning from characters.
-
-* Comments:: How to specify comments.
-@end menu
-
-When the shell reads input, it proceeds through a
-sequence of operations. If the input indicates the beginning of a
-comment, the shell ignores the comment symbol (@samp{#}), and the rest
-of that line.
-
-Otherwise, roughly speaking, the shell reads its input and
-divides the input into words and operators, employing the quoting rules
-to select which meanings to assign various words and characters.
-
-The shell then parses these tokens into commands and other constructs,
-removes the special meaning of certain words or characters, expands
-others, redirects input and output as needed, executes the specified
-command, waits for the command's exit status, and makes that exit status
-available for further inspection or processing.
-
-@node Shell Operation
-@subsection Shell Operation
-
-The following is a brief description of the shell's operation when it
-reads and executes a command. Basically, the shell does the
-following:
-
-@enumerate
-@item
-Reads its input from a file (@pxref{Shell Scripts}), from a string
-supplied as an argument to the @option{-c} invocation option
-(@pxref{Invoking Bash}), or from the user's terminal.
-
-@item
-Breaks the input into words and operators, obeying the quoting rules
-described in @ref{Quoting}. These tokens are separated by
-@code{metacharacters}. Alias expansion is performed by this step
-(@pxref{Aliases}).
-
-@item
-Parses the tokens into simple and compound commands
-(@pxref{Shell Commands}).
-
-@item
-Performs the various shell expansions (@pxref{Shell Expansions}), breaking
-the expanded tokens into lists of filenames (@pxref{Filename Expansion})
-and commands and arguments.
-
-@item
-Performs any necessary redirections (@pxref{Redirections}) and removes
-the redirection operators and their operands from the argument list.
-
-@item
-Executes the command (@pxref{Executing Commands}).
-
-@item
-Optionally waits for the command to complete and collects its exit
-status (@pxref{Exit Status}).
-
-@end enumerate
-
-@node Quoting
-@subsection Quoting
-@cindex quoting
-@menu
-* Escape Character:: How to remove the special meaning from a single
- character.
-* Single Quotes:: How to inhibit all interpretation of a sequence
- of characters.
-* Double Quotes:: How to suppress most of the interpretation of a
- sequence of characters.
-* ANSI-C Quoting:: How to expand ANSI-C sequences in quoted strings.
-
-* Locale Translation:: How to translate strings into different languages.
-@end menu
-
-Quoting is used to remove the special meaning of certain
-characters or words to the shell. Quoting can be used to
-disable special treatment for special characters, to prevent
-reserved words from being recognized as such, and to prevent
-parameter expansion.
-
-Each of the shell metacharacters (@pxref{Definitions})
-has special meaning to the shell and must be quoted if it is to
-represent itself.
-When the command history expansion facilities are being used, the
-@var{history expansion} character, usually @samp{!}, must be quoted
-to prevent history expansion. @xref{Bash History Facilities}, for
-more details concerning history expansion.
-
-There are three quoting mechanisms: the
-@var{escape character}, single quotes, and double quotes.
-
-@node Escape Character
-@subsubsection Escape Character
-A non-quoted backslash @samp{\} is the Bash escape character.
-It preserves the literal value of the next character that follows,
-with the exception of @code{newline}. If a @code{\newline} pair
-appears, and the backslash itself is not quoted, the @code{\newline}
-is treated as a line continuation (that is, it is removed from
-the input stream and effectively ignored).
-
-@node Single Quotes
-@subsubsection Single Quotes
-
-Enclosing characters in single quotes (@samp{'}) preserves the literal value
-of each character within the quotes. A single quote may not occur
-between single quotes, even when preceded by a backslash.
-
-@node Double Quotes
-@subsubsection Double Quotes
-
-Enclosing characters in double quotes (@samp{"}) preserves the literal value
-of all characters within the quotes, with the exception of
-@samp{$}, @samp{`}, and @samp{\}.
-The characters @samp{$} and @samp{`}
-retain their special meaning within double quotes (@pxref{Shell Expansions}).
-The backslash retains its special meaning only when followed by one of
-the following characters:
-@samp{$}, @samp{`}, @samp{"}, @samp{\}, or @code{newline}.
-Within double quotes, backslashes that are followed by one of these
-characters are removed. Backslashes preceding characters without a
-special meaning are left unmodified.
-A double quote may be quoted within double quotes by preceding it with
-a backslash.
-When command history is being used, the double quote may not be used to
-quote the history expansion character.
-
-The special parameters @samp{*} and @samp{@@} have special meaning
-when in double quotes (@pxref{Shell Parameter Expansion}).
-
-@node ANSI-C Quoting
-@subsubsection ANSI-C Quoting
-@cindex quoting, ANSI
-
-Words of the form @code{$'@var{string}'} are treated specially. The
-word expands to @var{string}, with backslash-escaped characters replaced
-as specified by the ANSI C standard. Backslash escape sequences, if
-present, are decoded as follows:
-
-@table @code
-@item \a
-alert (bell)
-@item \b
-backspace
-@item \e
-an escape character (not ANSI C)
-@item \f
-form feed
-@item \n
-newline
-@item \r
-carriage return
-@item \t
-horizontal tab
-@item \v
-vertical tab
-@item \\
-backslash
-@item \'
-single quote
-@item \@var{nnn}
-the eight-bit character whose value is the octal value @var{nnn}
-(one to three digits)
-@item \x@var{HH}
-the eight-bit character whose value is the hexadecimal value @var{HH}
-(one or two hex digits)
-@item \c@var{x}
-a control-@var{x} character
-@end table
-
-@noindent
-The expanded result is single-quoted, as if the dollar sign had not
-been present.
-
-@node Locale Translation
-@subsubsection Locale-Specific Translation
-@cindex localization
-@cindex internationalization
-@cindex native languages
-@cindex translation, native languages
-
-A double-quoted string preceded by a dollar sign (@samp{$}) will cause
-the string to be translated according to the current locale.
-If the current locale is @code{C} or @code{POSIX}, the dollar sign
-is ignored.
-If the string is translated and replaced, the replacement is
-double-quoted.
-
-@vindex LC_MESSAGES
-@vindex TEXTDOMAIN
-@vindex TEXTDOMAINDIR
-Some systems use the message catalog selected by the @env{LC_MESSAGES}
-shell variable. Others create the name of the message catalog from the
-value of the @env{TEXTDOMAIN} shell variable, possibly adding a
-suffix of @samp{.mo}. If you use the @env{TEXTDOMAIN} variable, you
-may need to set the @env{TEXTDOMAINDIR} variable to the location of
-the message catalog files. Still others use both variables in this
-fashion:
-@env{TEXTDOMAINDIR}/@env{LC_MESSAGES}/LC_MESSAGES/@env{TEXTDOMAIN}.mo.
-
-@node Comments
-@subsection Comments
-@cindex comments, shell
-
-In a non-interactive shell, or an interactive shell in which the
-@code{interactive_comments} option to the @code{shopt}
-builtin is enabled (@pxref{Bash Builtins}),
-a word beginning with @samp{#}
-causes that word and all remaining characters on that line to
-be ignored. An interactive shell without the @code{interactive_comments}
-option enabled does not allow comments. The @code{interactive_comments}
-option is on by default in interactive shells.
-@xref{Interactive Shells}, for a description of what makes
-a shell interactive.
-
-@node Shell Commands
-@section Shell Commands
-@cindex commands, shell
-
-A simple shell command such as @code{echo a b c} consists of the command
-itself followed by arguments, separated by spaces.
-
-More complex shell commands are composed of simple commands arranged together
-in a variety of ways: in a pipeline in which the output of one command
-becomes the input of a second, in a loop or conditional construct, or in
-some other grouping.
-
-@menu
-* Simple Commands:: The most common type of command.
-* Pipelines:: Connecting the input and output of several
- commands.
-* Lists:: How to execute commands sequentially.
-* Looping Constructs:: Shell commands for iterative action.
-* Conditional Constructs:: Shell commands for conditional execution.
-* Command Grouping:: Ways to group commands.
-@end menu
-
-@node Simple Commands
-@subsection Simple Commands
-@cindex commands, simple
-
-A simple command is the kind of command encountered most often.
-It's just a sequence of words separated by @code{blank}s, terminated
-by one of the shell's control operators (@pxref{Definitions}). The
-first word generally specifies a command to be executed, with the
-rest of the words being that command's arguments.
-
-The return status (@pxref{Exit Status}) of a simple command is
-its exit status as provided
-by the @sc{posix} 1003.1 @code{waitpid} function, or 128+@var{n} if
-the command was terminated by signal @var{n}.
-
-@node Pipelines
-@subsection Pipelines
-@cindex pipeline
-@cindex commands, pipelines
-
-A @code{pipeline} is a sequence of simple commands separated by
-@samp{|}.
-
-@rwindex time
-@rwindex !
-@cindex command timing
-The format for a pipeline is
-@example
-[@code{time} [@code{-p}]] [@code{!}] @var{command1} [@code{|} @var{command2} @dots{}]
-@end example
-
-@noindent
-The output of each command in the pipeline is connected via a pipe
-to the input of the next command.
-That is, each command reads the previous command's output.
-
-The reserved word @code{time} causes timing statistics
-to be printed for the pipeline once it finishes.
-The statistics currently consist of elapsed (wall-clock) time and
-user and system time consumed by the command's execution.
-The @option{-p} option changes the output format to that specified
-by @sc{posix}.
-The @env{TIMEFORMAT} variable may be set to a format string that
-specifies how the timing information should be displayed.
-@xref{Bash Variables}, for a description of the available formats.
-The use of @code{time} as a reserved word permits the timing of
-shell builtins, shell functions, and pipelines. An external
-@code{time} command cannot time these easily.
-
-If the pipeline is not executed asynchronously (@pxref{Lists}), the
-shell waits for all commands in the pipeline to complete.
-
-Each command in a pipeline is executed in its own subshell
-(@pxref{Command Execution Environment}). The exit
-status of a pipeline is the exit status of the last command in the
-pipeline. If the reserved word @samp{!} precedes the pipeline, the
-exit status is the logical negation of the exit status of the last command.
-
-@node Lists
-@subsection Lists of Commands
-@cindex commands, lists
-
-A @code{list} is a sequence of one or more pipelines separated by one
-of the operators @samp{;}, @samp{&}, @samp{&&}, or @samp{||},
-and optionally terminated by one of @samp{;}, @samp{&}, or a
-@code{newline}.
-
-Of these list operators, @samp{&&} and @samp{||}
-have equal precedence, followed by @samp{;} and @samp{&},
-which have equal precedence.
-
-A sequence of one or more newlines may appear in a @code{list}
-to delimit commands, equivalent to a semicolon.
-
-If a command is terminated by the control operator @samp{&},
-the shell executes the command asynchronously in a subshell.
-This is known as executing the command in the @var{background}.
-The shell does not wait for the command to finish, and the return
-status is 0 (true).
-When job control is not active (@pxref{Job Control}),
-the standard input for asynchronous commands, in the absence of any
-explicit redirections, is redirected from @code{/dev/null}.
-
-Commands separated by a @samp{;} are executed sequentially; the shell
-waits for each command to terminate in turn. The return status is the
-exit status of the last command executed.
-
-The control operators @samp{&&} and @samp{||}
-denote @sc{and} lists and @sc{or} lists, respectively.
-An @sc{and} list has the form
-@example
-@var{command1} && @var{command2}
-@end example
-
-@noindent
-@var{command2} is executed if, and only if, @var{command1}
-returns an exit status of zero.
-
-An @sc{or} list has the form
-@example
-@var{command1} || @var{command2}
-@end example
-
-@noindent
-@var{command2} is executed if, and only if, @var{command1}
-returns a non-zero exit status.
-
-The return status of
-@sc{and} and @sc{or} lists is the exit status of the last command
-executed in the list.
-
-@node Looping Constructs
-@subsection Looping Constructs
-@cindex commands, looping
-
-Bash supports the following looping constructs.
-
-Note that wherever a @samp{;} appears in the description of a
-command's syntax, it may be replaced with one or more newlines.
-
-@table @code
-@item until
-@rwindex until
-@rwindex do
-@rwindex done
-The syntax of the @code{until} command is:
-@example
-until @var{test-commands}; do @var{consequent-commands}; done
-@end example
-Execute @var{consequent-commands} as long as
-@var{test-commands} has an exit status which is not zero.
-The return status is the exit status of the last command executed
-in @var{consequent-commands}, or zero if none was executed.
-
-@item while
-@rwindex while
-The syntax of the @code{while} command is:
-@example
-while @var{test-commands}; do @var{consequent-commands}; done
-@end example
-
-Execute @var{consequent-commands} as long as
-@var{test-commands} has an exit status of zero.
-The return status is the exit status of the last command executed
-in @var{consequent-commands}, or zero if none was executed.
-
-@item for
-@rwindex for
-The syntax of the @code{for} command is:
-
-@example
-for @var{name} [in @var{words} @dots{}]; do @var{commands}; done
-@end example
-Expand @var{words}, and execute @var{commands} once for each member
-in the resultant list, with @var{name} bound to the current member.
-If @samp{in @var{words}} is not present, the @code{for} command
-executes the @var{commands} once for each positional parameter that is
-set, as if @samp{in "$@@"} had been specified
-(@pxref{Special Parameters}).
-The return status is the exit status of the last command that executes.
-If there are no items in the expansion of @var{words}, no commands are
-executed, and the return status is zero.
-
-An alternate form of the @code{for} command is also supported:
-
-@example
-for (( @var{expr1} ; @var{expr2} ; @var{expr3} )) ; do @var{commands} ; done
-@end example
-First, the arithmetic expression @var{expr1} is evaluated according
-to the rules described below (@pxref{Shell Arithmetic}).
-The arithmetic expression @var{expr2} is then evaluated repeatedly
-until it evaluates to zero.
-Each time @var{expr2} evaluates to a non-zero value, @var{commands} are
-executed and the arithmetic expression @var{expr3} is evaluated.
-If any expression is omitted, it behaves as if it evaluates to 1.
-The return value is the exit status of the last command in @var{list}
-that is executed, or false if any of the expressions is invalid.
-
-@end table
-
-The @code{break} and @code{continue} builtins (@pxref{Bourne Shell Builtins})
-may be used to control loop execution.
-
-@node Conditional Constructs
-@subsection Conditional Constructs
-@cindex commands, conditional
-
-@table @code
-@item if
-@rwindex if
-@rwindex then
-@rwindex else
-@rwindex elif
-@rwindex fi
-The syntax of the @code{if} command is:
-
-@example
-if @var{test-commands}; then
- @var{consequent-commands};
-[elif @var{more-test-commands}; then
- @var{more-consequents};]
-[else @var{alternate-consequents};]
-fi
-@end example
-
-The @var{test-commands} list is executed, and if its return status is zero,
-the @var{consequent-commands} list is executed.
-If @var{test-commands} returns a non-zero status, each @code{elif} list
-is executed in turn, and if its exit status is zero,
-the corresponding @var{more-consequents} is executed and the
-command completes.
-If @samp{else @var{alternate-consequents}} is present, and
-the final command in the final @code{if} or @code{elif} clause
-has a non-zero exit status, then @var{alternate-consequents} is executed.
-The return status is the exit status of the last command executed, or
-zero if no condition tested true.
-
-@item case
-@rwindex case
-@rwindex in
-@rwindex esac
-The syntax of the @code{case} command is:
-
-@example
-@code{case @var{word} in [ [(] @var{pattern} [| @var{pattern}]@dots{}) @var{command-list} ;;]@dots{} esac}
-@end example
-
-@code{case} will selectively execute the @var{command-list} corresponding to
-the first @var{pattern} that matches @var{word}.
-The @samp{|} is used to separate multiple patterns, and the @samp{)}
-operator terminates a pattern list.
-A list of patterns and an associated command-list is known
-as a @var{clause}. Each clause must be terminated with @samp{;;}.
-The @var{word} undergoes tilde expansion, parameter expansion, command
-substitution, arithmetic expansion, and quote removal before matching is
-attempted. Each @var{pattern} undergoes tilde expansion, parameter
-expansion, command substitution, and arithmetic expansion.
-
-There may be an arbitrary number of @code{case} clauses, each terminated
-by a @samp{;;}. The first pattern that matches determines the
-command-list that is executed.
-
-Here is an example using @code{case} in a script that could be used to
-describe one interesting feature of an animal:
-
-@example
-echo -n "Enter the name of an animal: "
-read ANIMAL
-echo -n "The $ANIMAL has "
-case $ANIMAL in
- horse | dog | cat) echo -n "four";;
- man | kangaroo ) echo -n "two";;
- *) echo -n "an unknown number of";;
-esac
-echo " legs."
-@end example
-
-@noindent
-The return status is zero if no @var{pattern} is matched. Otherwise, the
-return status is the exit status of the @var{command-list} executed.
-
-@item select
-@rwindex select
-
-The @code{select} construct allows the easy generation of menus.
-It has almost the same syntax as the @code{for} command:
-
-@example
-select @var{name} [in @var{words} @dots{}]; do @var{commands}; done
-@end example
-
-The list of words following @code{in} is expanded, generating a list
-of items. The set of expanded words is printed on the standard
-error output stream, each preceded by a number. If the
-@samp{in @var{words}} is omitted, the positional parameters are printed,
-as if @samp{in "$@@"} had been specifed.
-The @env{PS3} prompt is then displayed and a line is read from the
-standard input.
-If the line consists of a number corresponding to one of the displayed
-words, then the value of @var{name} is set to that word.
-If the line is empty, the words and prompt are displayed again.
-If @code{EOF} is read, the @code{select} command completes.
-Any other value read causes @var{name} to be set to null.
-The line read is saved in the variable @env{REPLY}.
-
-The @var{commands} are executed after each selection until a
-@code{break} command is executed, at which
-point the @code{select} command completes.
-
-Here is an example that allows the user to pick a filename from the
-current directory, and displays the name and index of the file
-selected.
-
-@example
-select fname in *;
-do
- echo you picked $fname \($REPLY\)
- break;
-done
-@end example
-
-@item ((@dots{}))
-@example
-(( @var{expression} ))
-@end example
-
-The arithmetic @var{expression} is evaluated according to the rules
-described below (@pxref{Shell Arithmetic}).
-If the value of the expression is non-zero, the return status is 0;
-otherwise the return status is 1. This is exactly equivalent to
-@example
-let "@var{expression}"
-@end example
-@noindent
-@xref{Bash Builtins}, for a full description of the @code{let} builtin.
-
-@item [[@dots{}]]
-@rwindex [[
-@rwindex ]]
-@example
-[[ @var{expression} ]]
-@end example
-
-Return a status of 0 or 1 depending on the evaluation of
-the conditional expression @var{expression}.
-Expressions are composed of the primaries described below in
-@ref{Bash Conditional Expressions}.
-Word splitting and filename expansion are not performed on the words
-between the @samp{[[} and @samp{]]}; tilde expansion, parameter and
-variable expansion, arithmetic expansion, command substitution, process
-substitution, and quote removal are performed.
-Conditional operators such as @samp{-f} must be unquoted to be recognized
-as primaries.
-
-When the @samp{==} and @samp{!=} operators are used, the string to the
-right of the operator is considered a pattern and matched according
-to the rules described below in @ref{Pattern Matching}.
-The return value is 0 if the string matches or does not match
-the pattern, respectively, and 1 otherwise.
-Any part of the pattern may be quoted to force it to be matched as a
-string.
-
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence:
-
-@table @code
-@item ( @var{expression} )
-Returns the value of @var{expression}.
-This may be used to override the normal precedence of operators.
-
-@item ! @var{expression}
-True if @var{expression} is false.
-
-@item @var{expression1} && @var{expression2}
-True if both @var{expression1} and @var{expression2} are true.
-
-@item @var{expression1} || @var{expression2}
-True if either @var{expression1} or @var{expression2} is true.
-@end table
-@noindent
-The @code{&&} and @code{||} operators do not evaluate @var{expression2} if the
-value of @var{expression1} is sufficient to determine the return
-value of the entire conditional expression.
-
-@end table
-
-@node Command Grouping
-@subsection Grouping Commands
-@cindex commands, grouping
-
-Bash provides two ways to group a list of commands to be executed
-as a unit. When commands are grouped, redirections may be applied
-to the entire command list. For example, the output of all the
-commands in the list may be redirected to a single stream.
-
-@table @code
-@item ()
-@example
-( @var{list} )
-@end example
-
-Placing a list of commands between parentheses causes a subshell
-to be created, and each of the commands in @var{list} to be executed
-in that subshell. Since the @var{list} is executed in a subshell,
-variable assignments do not remain in effect after the subshell completes.
-
-@item @{@}
-@rwindex @{
-@rwindex @}
-@example
-@{ @var{list}; @}
-@end example
-
-Placing a list of commands between curly braces causes the list to
-be executed in the current shell context. No subshell is created.
-The semicolon (or newline) following @var{list} is required.
-@end table
-
-In addition to the creation of a subshell, there is a subtle difference
-between these two constructs due to historical reasons. The braces
-are @code{reserved words}, so they must be separated from the @var{list}
-by @code{blank}s. The parentheses are @code{operators}, and are
-recognized as separate tokens by the shell even if they are not separated
-from the @var{list} by whitespace.
-
-The exit status of both of these constructs is the exit status of
-@var{list}.
-
-@node Shell Functions
-@section Shell Functions
-@cindex shell function
-@cindex functions, shell
-
-Shell functions are a way to group commands for later execution
-using a single name for the group. They are executed just like
-a "regular" command.
-When the name of a shell function is used as a simple command name,
-the list of commands associated with that function name is executed.
-Shell functions are executed in the current
-shell context; no new process is created to interpret them.
-
-Functions are declared using this syntax:
-@rwindex function
-@example
-[ @code{function} ] @var{name} () @{ @var{command-list}; @}
-@end example
-
-This defines a shell function named @var{name}. The reserved
-word @code{function} is optional.
-If the @code{function} reserved
-word is supplied, the parentheses are optional.
-The @var{body} of the function is the @var{command-list} between @{ and @}.
-This list is executed whenever @var{name} is specified as the
-name of a command. The exit status of a function is
-the exit status of the last command executed in the body.
-
-Note that for historical reasons, the curly braces that surround
-the body of the function must be separated from the body by
-@code{blank}s or newlines.
-This is because the braces are reserved words and are only recognized
-as such when they are separated by whitespace.
-Also, the @var{command-list} must be terminated by a semicolon,
-a @samp{&}, or a newline.
-
-When a function is executed, the arguments to the
-function become the positional parameters
-during its execution (@pxref{Positional Parameters}).
-The special parameter @samp{#} that expands to the number of
-positional parameters is updated to reflect the change.
-Positional parameter @code{0} is unchanged.
-The first element of the @env{FUNCNAME} variable is set to the
-name of the function while the function is executing.
-All other aspects of the shell execution
-environment are identical between a function and its caller
-with the exception that the @env{DEBUG} trap
-below) is not inherited unless the function has been given the
-@code{trace} attribute using the @code{declare} builtin or
-the @code{-o functrace} option has been enabled with
-the @code{set} builtin,
-(in which case all functions inherit the @code{DEBUG} trap).
-@xref{Bourne Shell Builtins}, for the description of the
-@code{trap} builtin.
-
-If the builtin command @code{return}
-is executed in a function, the function completes and
-execution resumes with the next command after the function
-call.
-Any command associated with the @code{RETURN} trap is executed
-before execution resumes.
-When a function completes, the values of the
-positional parameters and the special parameter @samp{#}
-are restored to the values they had prior to the function's
-execution. If a numeric argument is given to @code{return},
-that is the function's return status; otherwise the function's
-return status is the exit status of the last command executed
-before the @code{return}.
-
-Variables local to the function may be declared with the
-@code{local} builtin. These variables are visible only to
-the function and the commands it invokes.
-
-Function names and definitions may be listed with the
-@option{-f} option to the @code{declare} or @code{typeset}
-builtin commands (@pxref{Bash Builtins}).
-The @option{-F} option to @code{declare} or @code{typeset}
-will list the function names only
-(and optionally the source file and line number, if the @code{extdebug}
-shell option is enabled).
-Functions may be exported so that subshells
-automatically have them defined with the
-@option{-f} option to the @code{export} builtin
-(@pxref{Bourne Shell Builtins}).
-Note that shell functions and variables with the same name may result
-in multiple identically-named entries in the environment passed to the
-shell's children.
-Care should be taken in cases where this may cause a problem.
-
-Functions may be recursive. No limit is placed on the number of
-recursive calls.
-
-@node Shell Parameters
-@section Shell Parameters
-@cindex parameters
-@cindex variable, shell
-@cindex shell variable
-
-@menu
-* Positional Parameters:: The shell's command-line arguments.
-* Special Parameters:: Parameters denoted by special characters.
-@end menu
-
-A @var{parameter} is an entity that stores values.
-It can be a @code{name}, a number, or one of the special characters
-listed below.
-A @var{variable} is a parameter denoted by a @code{name}.
-A variable has a @var{value} and zero or more @var{attributes}.
-Attributes are assigned using the @code{declare} builtin command
-(see the description of the @code{declare} builtin in @ref{Bash Builtins}).
-
-A parameter is set if it has been assigned a value. The null string is
-a valid value. Once a variable is set, it may be unset only by using
-the @code{unset} builtin command.
-
-A variable may be assigned to by a statement of the form
-@example
-@var{name}=[@var{value}]
-@end example
-@noindent
-If @var{value}
-is not given, the variable is assigned the null string. All
-@var{value}s undergo tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote
-removal (detailed below). If the variable has its @code{integer}
-attribute set, then @var{value}
-is evaluated as an arithmetic expression even if the @code{$((@dots{}))}
-expansion is not used (@pxref{Arithmetic Expansion}).
-Word splitting is not performed, with the exception
-of @code{"$@@"} as explained below.
-Filename expansion is not performed.
-Assignment statements may also appear as arguments to the
-@code{declare}, @code{typeset}, @code{export}, @code{readonly},
-and @code{local} builtin commands.
-
-@node Positional Parameters
-@subsection Positional Parameters
-@cindex parameters, positional
-
-A @var{positional parameter} is a parameter denoted by one or more
-digits, other than the single digit @code{0}. Positional parameters are
-assigned from the shell's arguments when it is invoked,
-and may be reassigned using the @code{set} builtin command.
-Positional parameter @code{N} may be referenced as @code{$@{N@}}, or
-as @code{$N} when @code{N} consists of a single digit.
-Positional parameters may not be assigned to with assignment statements.
-The @code{set} and @code{shift} builtins are used to set and
-unset them (@pxref{Shell Builtin Commands}).
-The positional parameters are
-temporarily replaced when a shell function is executed
-(@pxref{Shell Functions}).
-
-When a positional parameter consisting of more than a single
-digit is expanded, it must be enclosed in braces.
-
-@node Special Parameters
-@subsection Special Parameters
-@cindex parameters, special
-
-The shell treats several parameters specially. These parameters may
-only be referenced; assignment to them is not allowed.
-
-@vtable @code
-
-@item *
-Expands to the positional parameters, starting from one. When the
-expansion occurs within double quotes, it expands to a single word
-with the value of each parameter separated by the first character
-of the @env{IFS}
-special variable. That is, @code{"$*"} is equivalent
-to @code{"$1@var{c}$2@var{c}@dots{}"}, where @var{c}
-is the first character of the value of the @code{IFS}
-variable.
-If @env{IFS} is unset, the parameters are separated by spaces.
-If @env{IFS} is null, the parameters are joined without intervening
-separators.
-
-
-@item @@
-Expands to the positional parameters, starting from one. When the
-expansion occurs within double quotes, each parameter expands to a
-separate word. That is, @code{"$@@"} is equivalent to
-@code{"$1" "$2" @dots{}}.
-When there are no positional parameters, @code{"$@@"} and
-@code{$@@}
-expand to nothing (i.e., they are removed).
-
-@item #
-Expands to the number of positional parameters in decimal.
-
-@item ?
-Expands to the exit status of the most recently executed foreground
-pipeline.
-
-@item -
-(A hyphen.) Expands to the current option flags as specified upon
-invocation, by the @code{set}
-builtin command, or those set by the shell itself
-(such as the @option{-i} option).
-
-@item $
-Expands to the process @sc{id} of the shell. In a @code{()} subshell, it
-expands to the process @sc{id} of the invoking shell, not the subshell.
-
-@item !
-Expands to the process @sc{id} of the most recently executed background
-(asynchronous) command.
-
-@item 0
-Expands to the name of the shell or shell script. This is set at
-shell initialization. If Bash is invoked with a file of commands
-(@pxref{Shell Scripts}), @code{$0} is set to the name of that file.
-If Bash is started with the @option{-c} option (@pxref{Invoking Bash}),
-then @code{$0} is set to the first argument after the string to be
-executed, if one is present. Otherwise, it is set
-to the filename used to invoke Bash, as given by argument zero.
-
-@item _
-(An underscore.)
-At shell startup, set to the absolute filename of the shell or shell
-script being executed as passed in the argument list.
-Subsequently, expands to the last argument to the previous command,
-after expansion.
-Also set to the full pathname of each command executed and placed in
-the environment exported to that command.
-When checking mail, this parameter holds the name of the mail file.
-@end vtable
-
-@node Shell Expansions
-@section Shell Expansions
-@cindex expansion
-
-Expansion is performed on the command line after it has been split into
-@code{token}s. There are seven kinds of expansion performed:
-@itemize @bullet
-@item brace expansion
-@item tilde expansion
-@item parameter and variable expansion
-@item command substitution
-@item arithmetic expansion
-@item word splitting
-@item filename expansion
-@end itemize
-
-@menu
-* Brace Expansion:: Expansion of expressions within braces.
-* Tilde Expansion:: Expansion of the ~ character.
-* Shell Parameter Expansion:: How Bash expands variables to their values.
-* Command Substitution:: Using the output of a command as an argument.
-* Arithmetic Expansion:: How to use arithmetic in shell expansions.
-* Process Substitution:: A way to write and read to and from a
- command.
-* Word Splitting:: How the results of expansion are split into separate
- arguments.
-* Filename Expansion:: A shorthand for specifying filenames matching patterns.
-* Quote Removal:: How and when quote characters are removed from
- words.
-@end menu
-
-The order of expansions is: brace expansion, tilde expansion,
-parameter, variable, and arithmetic expansion and
-command substitution
-(done in a left-to-right fashion), word splitting, and filename
-expansion.
-
-On systems that can support it, there is an additional expansion
-available: @var{process substitution}. This is performed at the
-same time as parameter, variable, and arithmetic expansion and
-command substitution.
-
-Only brace expansion, word splitting, and filename expansion
-can change the number of words of the expansion; other expansions
-expand a single word to a single word.
-The only exceptions to this are the expansions of
-@code{"$@@"} (@pxref{Special Parameters}) and @code{"$@{@var{name}[@@]@}"}
-(@pxref{Arrays}).
-
-After all expansions, @code{quote removal} (@pxref{Quote Removal})
-is performed.
-
-@node Brace Expansion
-@subsection Brace Expansion
-@cindex brace expansion
-@cindex expansion, brace
-
-Brace expansion is a mechanism by which arbitrary strings may be generated.
-This mechanism is similar to
-@var{filename expansion} (@pxref{Filename Expansion}),
-but the file names generated need not exist.
-Patterns to be brace expanded take the form of an optional @var{preamble},
-followed by either a series of comma-separated strings or a sequnce expression
-between a pair of braces,
-followed by an optional @var{postscript}.
-The preamble is prefixed to each string contained within the braces, and
-the postscript is then appended to each resulting string, expanding left
-to right.
-
-Brace expansions may be nested.
-The results of each expanded string are not sorted; left to right order
-is preserved.
-For example,
-@example
-bash$ echo a@{d,c,b@}e
-ade ace abe
-@end example
-
-A sequence expression takes the form @code{@{@var{x}..@var{y}@}},
-where @var{x} and @var{y} are either integers or single characters.
-When integers are supplied, the expression expands to each number between
-@var{x} and @var{y}, inclusive.
-When characters are supplied, the expression expands to each character
-lexicographically between @var{x} and @var{y}, inclusive. Note that
-both @var{x} and @var{y} must be of the same type.
-
-Brace expansion is performed before any other expansions,
-and any characters special to other expansions are preserved
-in the result. It is strictly textual. Bash
-does not apply any syntactic interpretation to the context of the
-expansion or the text between the braces.
-To avoid conflicts with parameter expansion, the string @samp{$@{}
-is not considered eligible for brace expansion.
-
-A correctly-formed brace expansion must contain unquoted opening
-and closing braces, and at least one unquoted comma or a valid
-sequence expression.
-Any incorrectly formed brace expansion is left unchanged.
-
-A @{ or @samp{,} may be quoted with a backslash to prevent its
-being considered part of a brace expression.
-To avoid conflicts with parameter expansion, the string @samp{$@{}
-is not considered eligible for brace expansion.
-
-This construct is typically used as shorthand when the common
-prefix of the strings to be generated is longer than in the
-above example:
-@example
-mkdir /usr/local/src/bash/@{old,new,dist,bugs@}
-@end example
-or
-@example
-chown root /usr/@{ucb/@{ex,edit@},lib/@{ex?.?*,how_ex@}@}
-@end example
-
-@node Tilde Expansion
-@subsection Tilde Expansion
-@cindex tilde expansion
-@cindex expansion, tilde
-
-If a word begins with an unquoted tilde character (@samp{~}), all of the
-characters up to the first unquoted slash (or all characters,
-if there is no unquoted slash) are considered a @var{tilde-prefix}.
-If none of the characters in the tilde-prefix are quoted, the
-characters in the tilde-prefix following the tilde are treated as a
-possible @var{login name}.
-If this login name is the null string, the tilde is replaced with the
-value of the @env{HOME} shell variable.
-If @env{HOME} is unset, the home directory of the user executing the
-shell is substituted instead.
-Otherwise, the tilde-prefix is replaced with the home directory
-associated with the specified login name.
-
-If the tilde-prefix is @samp{~+}, the value of
-the shell variable @env{PWD} replaces the tilde-prefix.
-If the tilde-prefix is @samp{~-}, the value of the shell variable
-@env{OLDPWD}, if it is set, is substituted.
-
-If the characters following the tilde in the tilde-prefix consist of a
-number @var{N}, optionally prefixed by a @samp{+} or a @samp{-},
-the tilde-prefix is replaced with the
-corresponding element from the directory stack, as it would be displayed
-by the @code{dirs} builtin invoked with the characters following tilde
-in the tilde-prefix as an argument (@pxref{The Directory Stack}).
-If the tilde-prefix, sans the tilde, consists of a number without a
-leading @samp{+} or @samp{-}, @samp{+} is assumed.
-
-If the login name is invalid, or the tilde expansion fails, the word is
-left unchanged.
-
-Each variable assignment is checked for unquoted tilde-prefixes immediately
-following a @samp{:} or @samp{=}.
-In these cases, tilde expansion is also performed.
-Consequently, one may use file names with tildes in assignments to
-@env{PATH}, @env{MAILPATH}, and @env{CDPATH},
-and the shell assigns the expanded value.
-
-The following table shows how Bash treats unquoted tilde-prefixes:
-
-@table @code
-@item ~
-The value of @code{$HOME}
-@item ~/foo
-@file{$HOME/foo}
-
-@item ~fred/foo
-The subdirectory @code{foo} of the home directory of the user
-@code{fred}
-
-@item ~+/foo
-@file{$PWD/foo}
-
-@item ~-/foo
-@file{$@{OLDPWD-'~-'@}/foo}
-
-@item ~@var{N}
-The string that would be displayed by @samp{dirs +@var{N}}
-
-@item ~+@var{N}
-The string that would be displayed by @samp{dirs +@var{N}}
-
-@item ~-@var{N}
-The string that would be displayed by @samp{dirs -@var{N}}
-
-@end table
-
-@node Shell Parameter Expansion
-@subsection Shell Parameter Expansion
-@cindex parameter expansion
-@cindex expansion, parameter
-
-The @samp{$} character introduces parameter expansion,
-command substitution, or arithmetic expansion. The parameter name
-or symbol to be expanded may be enclosed in braces, which
-are optional but serve to protect the variable to be expanded from
-characters immediately following it which could be
-interpreted as part of the name.
-
-When braces are used, the matching ending brace is the first @samp{@}}
-not escaped by a backslash or within a quoted string, and not within an
-embedded arithmetic expansion, command substitution, or parameter
-expansion.
-
-The basic form of parameter expansion is $@{@var{parameter}@}.
-The value of @var{parameter} is substituted. The braces are required
-when @var{parameter}
-is a positional parameter with more than one digit,
-or when @var{parameter}
-is followed by a character that is not to be
-interpreted as part of its name.
-
-If the first character of @var{parameter} is an exclamation point,
-a level of variable indirection is introduced.
-Bash uses the value of the variable formed from the rest of
-@var{parameter} as the name of the variable; this variable is then
-expanded and that value is used in the rest of the substitution, rather
-than the value of @var{parameter} itself.
-This is known as @code{indirect expansion}.
-The exceptions to this are the expansions of $@{!@var{prefix*}@}
-and $@{!@var{name}[@@]@}
-described below.
-The exclamation point must immediately follow the left brace in order to
-introduce indirection.
-
-In each of the cases below, @var{word} is subject to tilde expansion,
-parameter expansion, command substitution, and arithmetic expansion.
-
-When not performing substring expansion, Bash tests for a parameter
-that is unset or null; omitting the colon results in a test only for a
-parameter that is unset. Put another way, if the colon is included,
-the operator tests for both existence and that the value is not null;
-if the colon is omitted, the operator tests only for existence.
-
-@table @code
-
-@item $@{@var{parameter}:@minus{}@var{word}@}
-If @var{parameter} is unset or null, the expansion of
-@var{word} is substituted. Otherwise, the value of
-@var{parameter} is substituted.
-
-@item $@{@var{parameter}:=@var{word}@}
-If @var{parameter}
-is unset or null, the expansion of @var{word}
-is assigned to @var{parameter}.
-The value of @var{parameter}
-is then substituted. Positional parameters and special parameters may
-not be assigned to in this way.
-
-@item $@{@var{parameter}:?@var{word}@}
-If @var{parameter}
-is null or unset, the expansion of @var{word} (or a message
-to that effect if @var{word}
-is not present) is written to the standard error and the shell, if it
-is not interactive, exits. Otherwise, the value of @var{parameter} is
-substituted.
-
-@item $@{@var{parameter}:+@var{word}@}
-If @var{parameter}
-is null or unset, nothing is substituted, otherwise the expansion of
-@var{word} is substituted.
-
-@item $@{@var{parameter}:@var{offset}@}
-@itemx $@{@var{parameter}:@var{offset}:@var{length}@}
-Expands to up to @var{length} characters of @var{parameter}
-starting at the character specified by @var{offset}.
-If @var{length} is omitted, expands to the substring of
-@var{parameter} starting at the character specified by @var{offset}.
-@var{length} and @var{offset} are arithmetic expressions
-(@pxref{Shell Arithmetic}).
-This is referred to as Substring Expansion.
-
-@var{length} must evaluate to a number greater than or equal to zero.
-If @var{offset} evaluates to a number less than zero, the value
-is used as an offset from the end of the value of @var{parameter}.
-If @var{parameter} is @samp{@@}, the result is @var{length} positional
-parameters beginning at @var{offset}.
-If @var{parameter} is an array name indexed by @samp{@@} or @samp{*},
-the result is the @var{length}
-members of the array beginning with @code{$@{@var{parameter}[@var{offset}]@}}.
-Substring indexing is zero-based unless the positional parameters
-are used, in which case the indexing starts at 1.
-
-@item $@{!@var{prefix}*@}
-@itemx $@{!@var{prefix}@@@}
-Expands to the names of variables whose names begin with @var{prefix},
-separated by the first character of the @env{IFS} special variable.
-
-@item $@{!@var{name}[@@]@}
-@itemx $@{!@var{name}[*]@}
-If @var{name} is an array variable, expands to the list of array indices
-(keys) assigned in @var{name}.
-If @var{name} is not an array, expands to 0 if @var{name} is set and null
-otherwise.
-When @samp{@@} is used and the expansion appears within double quotes, each
-key expands to a separate word.
-
-@item $@{#@var{parameter}@}
-The length in characters of the expanded value of @var{parameter} is
-substituted.
-If @var{parameter} is @samp{*} or @samp{@@}, the value substituted
-is the number of positional parameters.
-If @var{parameter} is an array name subscripted by @samp{*} or @samp{@@},
-the value substituted is the number of elements in the array.
-
-@item $@{@var{parameter}#@var{word}@}
-@itemx $@{@var{parameter}##@var{word}@}
-The @var{word}
-is expanded to produce a pattern just as in filename
-expansion (@pxref{Filename Expansion}). If the pattern matches
-the beginning of the expanded value of @var{parameter},
-then the result of the expansion is the expanded value of @var{parameter}
-with the shortest matching pattern (the @samp{#} case) or the
-longest matching pattern (the @samp{##} case) deleted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter} is an array variable subscripted with
-@samp{@@} or @samp{*},
-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{word}@}
-@itemx $@{@var{parameter}%%@var{word}@}
-The @var{word} is expanded to produce a pattern just as in
-filename expansion.
-If the pattern matches a trailing portion of the expanded value of
-@var{parameter}, then the result of the expansion is the value of
-@var{parameter} with the shortest matching pattern (the @samp{%} case)
-or the longest matching pattern (the @samp{%%} case) deleted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter}
-is an array variable subscripted with @samp{@@} or @samp{*},
-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{#}, 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
-of the expanded value of @var{parameter}.
-If @var{string} is null, matches of @var{pattern} are deleted
-and the @code{/} following @var{pattern} may be omitted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the substitution operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter}
-is an array variable subscripted with @samp{@@} or @samp{*},
-the substitution operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-
-@end table
-
-@node Command Substitution
-@subsection Command Substitution
-@cindex command substitution
-
-Command substitution allows the output of a command to replace
-the command itself.
-Command substitution occurs when a command is enclosed as follows:
-@example
-$(@var{command})
-@end example
-@noindent
-or
-@example
-`@var{command}`
-@end example
-
-@noindent
-Bash performs the expansion by executing @var{command} and
-replacing the command substitution with the standard output of the
-command, with any trailing newlines deleted.
-Embedded newlines are not deleted, but they may be removed during
-word splitting.
-The command substitution @code{$(cat @var{file})} can be
-replaced by the equivalent but faster @code{$(< @var{file})}.
-
-When the old-style backquote form of substitution is used,
-backslash retains its literal meaning except when followed by
-@samp{$}, @samp{`}, or @samp{\}.
-The first backquote not preceded by a backslash terminates the
-command substitution.
-When using the @code{$(@var{command})} form, all characters between
-the parentheses make up the command; none are treated specially.
-
-Command substitutions may be nested. To nest when using the backquoted
-form, escape the inner backquotes with backslashes.
-
-If the substitution appears within double quotes, word splitting and
-filename expansion are not performed on the results.
-
-@node Arithmetic Expansion
-@subsection Arithmetic Expansion
-@cindex expansion, arithmetic
-@cindex arithmetic expansion
-
-Arithmetic expansion allows the evaluation of an arithmetic expression
-and the substitution of the result. The format for arithmetic expansion is:
-
-@example
-$(( @var{expression} ))
-@end example
-
-The expression is treated as if it were within double quotes, but
-a double quote inside the parentheses is not treated specially.
-All tokens in the expression undergo parameter expansion, command
-substitution, and quote removal.
-Arithmetic expansions may be nested.
-
-The evaluation is performed according to the rules listed below
-(@pxref{Shell Arithmetic}).
-If the expression is invalid, Bash prints a message indicating
-failure to the standard error and no substitution occurs.
-
-@node Process Substitution
-@subsection Process Substitution
-@cindex process substitution
-
-Process substitution is supported on systems that support named
-pipes (@sc{fifo}s) or the @file{/dev/fd} method of naming open files.
-It takes the form of
-@example
-<(@var{list})
-@end example
-@noindent
-or
-@example
->(@var{list})
-@end example
-@noindent
-The process @var{list} is run with its input or output connected to a
-@sc{fifo} or some file in @file{/dev/fd}. The name of this file is
-passed as an argument to the current command as the result of the
-expansion. If the @code{>(@var{list})} form is used, writing to
-the file will provide input for @var{list}. If the
-@code{<(@var{list})} form is used, the file passed as an
-argument should be read to obtain the output of @var{list}.
-Note that no space may appear between the @code{<} or @code{>}
-and the left parenthesis, otherwise the construct would be interpreted
-as a redirection.
-
-When available, process substitution is performed simultaneously with
-parameter and variable expansion, command substitution, and arithmetic
-expansion.
-
-@node Word Splitting
-@subsection Word Splitting
-@cindex word splitting
-
-The shell scans the results of parameter expansion, command substitution,
-and arithmetic expansion that did not occur within double quotes for
-word splitting.
-
-The shell treats each character of @env{$IFS}
-as a delimiter, and splits the results of the other
-expansions into words on these characters. If
-@env{IFS} is unset, or its value is exactly @code{<space><tab><newline>},
-the default, then any sequence of @env{IFS}
-characters serves to delimit words. If @env{IFS}
-has a value other than the default, then sequences of
-the whitespace characters @code{space} and @code{tab}
-are ignored at the beginning and end of the
-word, as long as the whitespace character is in the
-value of @env{IFS} (an @env{IFS} whitespace character).
-Any character in @env{IFS} that is not @env{IFS}
-whitespace, along with any adjacent @env{IFS}
-whitespace characters, delimits a field. A sequence of @env{IFS}
-whitespace characters is also treated as a delimiter.
-If the value of @env{IFS} is null, no word splitting occurs.
-
-Explicit null arguments (@code{""} or @code{''}) are retained.
-Unquoted implicit null arguments, resulting from the expansion of
-parameters that have no values, are removed.
-If a parameter with no value is expanded within double quotes, a
-null argument results and is retained.
-
-Note that if no expansion occurs, no splitting
-is performed.
-
-@node Filename Expansion
-@subsection Filename Expansion
-@menu
-* Pattern Matching:: How the shell matches patterns.
-@end menu
-@cindex expansion, filename
-@cindex expansion, pathname
-@cindex filename expansion
-@cindex pathname expansion
-
-After word splitting, unless the @option{-f} option has been set
-(@pxref{The Set Builtin}), Bash scans each word for the characters
-@samp{*}, @samp{?}, and @samp{[}.
-If one of these characters appears, then the word is
-regarded as a @var{pattern},
-and replaced with an alphabetically sorted list of
-file names matching the pattern. If no matching file names are found,
-and the shell option @code{nullglob} is disabled, the word is left
-unchanged.
-If the @code{nullglob} option is set, and no matches are found, the word
-is removed.
-If the shell option @code{nocaseglob} is enabled, the match is performed
-without regard to the case of alphabetic characters.
-
-When a pattern is used for filename generation, the character @samp{.}
-at the start of a filename or immediately following a slash
-must be matched explicitly, unless the shell option @code{dotglob} is set.
-When matching a file name, the slash character must always be
-matched explicitly.
-In other cases, the @samp{.} character is not treated specially.
-
-See the description of @code{shopt} in @ref{Bash Builtins},
-for a description of the @code{nocaseglob}, @code{nullglob},
-and @code{dotglob} options.
-
-The @env{GLOBIGNORE}
-shell variable may be used to restrict the set of filenames matching a
-pattern. If @env{GLOBIGNORE}
-is set, each matching filename that also matches one of the patterns in
-@env{GLOBIGNORE} is removed from the list of matches. The filenames
-@file{.} and @file{..}
-are always ignored when @env{GLOBIGNORE}
-is set and not null.
-However, setting @env{GLOBIGNORE} to a non-null value has the effect of
-enabling the @code{dotglob}
-shell option, so all other filenames beginning with a
-@samp{.} will match.
-To get the old behavior of ignoring filenames beginning with a
-@samp{.}, make @samp{.*} one of the patterns in @env{GLOBIGNORE}.
-The @code{dotglob} option is disabled when @env{GLOBIGNORE}
-is unset.
-
-@node Pattern Matching
-@subsubsection Pattern Matching
-@cindex pattern matching
-@cindex matching, pattern
-
-Any character that appears in a pattern, other than the special pattern
-characters described below, matches itself.
-The @sc{nul} character may not occur in a pattern.
-A backslash escapes the following character; the
-escaping backslash is discarded when matching.
-The special pattern characters must be quoted if they are to be matched
-literally.
-
-The special pattern characters have the following meanings:
-@table @code
-@item *
-Matches any string, including the null string.
-@item ?
-Matches any single character.
-@item [@dots{}]
-Matches any one of the enclosed characters. A pair of characters
-separated by a hyphen denotes a @var{range expression};
-any character that sorts between those two characters, inclusive,
-using the current locale's collating sequence and character set,
-is matched. If the first character following the
-@samp{[} is a @samp{!} or a @samp{^}
-then any character not enclosed is matched. A @samp{@minus{}}
-may be matched by including it as the first or last character
-in the set. A @samp{]} may be matched by including it as the first
-character in the set.
-The sorting order of characters in range expressions is determined by
-the current locale and the value of the @env{LC_COLLATE} shell variable,
-if set.
-
-For example, in the default C locale, @samp{[a-dx-z]} is equivalent to
-@samp{[abcdxyz]}. Many locales sort characters in dictionary order, and in
-these locales @samp{[a-dx-z]} is typically not equivalent to @samp{[abcdxyz]};
-it might be equivalent to @samp{[aBbCcDdxXyYz]}, for example. To obtain
-the traditional interpretation of ranges in bracket expressions, you can
-force the use of the C locale by setting the @env{LC_COLLATE} or
-@env{LC_ALL} environment variable to the value @samp{C}.
-
-Within @samp{[} and @samp{]}, @var{character classes} can be specified
-using the syntax
-@code{[:}@var{class}@code{:]}, where @var{class} is one of the
-following classes defined in the @sc{posix} 1003.2 standard:
-@example
-alnum alpha ascii blank cntrl digit graph lower
-print punct space upper word xdigit
-@end example
-@noindent
-A character class matches any character belonging to that class.
-The @code{word} character class matches letters, digits, and the character
-@samp{_}.
-
-Within @samp{[} and @samp{]}, an @var{equivalence class} can be
-specified using the syntax @code{[=}@var{c}@code{=]}, which
-matches all characters with the same collation weight (as defined
-by the current locale) as the character @var{c}.
-
-Within @samp{[} and @samp{]}, the syntax @code{[.}@var{symbol}@code{.]}
-matches the collating symbol @var{symbol}.
-@end table
-
-If the @code{extglob} shell option is enabled using the @code{shopt}
-builtin, several extended pattern matching operators are recognized.
-In the following description, a @var{pattern-list} is a list of one
-or more patterns separated by a @samp{|}.
-Composite patterns may be formed using one or more of the following
-sub-patterns:
-
-@table @code
-@item ?(@var{pattern-list})
-Matches zero or one occurrence of the given patterns.
-
-@item *(@var{pattern-list})
-Matches zero or more occurrences of the given patterns.
-
-@item +(@var{pattern-list})
-Matches one or more occurrences of the given patterns.
-
-@item @@(@var{pattern-list})
-Matches exactly one of the given patterns.
-
-@item !(@var{pattern-list})
-Matches anything except one of the given patterns.
-@end table
-
-@node Quote Removal
-@subsection Quote Removal
-
-After the preceding expansions, all unquoted occurrences of the
-characters @samp{\}, @samp{'}, and @samp{"} that did not
-result from one of the above expansions are removed.
-
-@node Redirections
-@section Redirections
-@cindex redirection
-
-Before a command is executed, its input and output
-may be @var{redirected}
-using a special notation interpreted by the shell.
-Redirection may also be used to open and close files for the
-current shell execution environment. The following redirection
-operators may precede or appear anywhere within a
-simple command or may follow a command.
-Redirections are processed in the order they appear, from
-left to right.
-
-In the following descriptions, if the file descriptor number is
-omitted, and the first character of the redirection operator is
-@samp{<}, the redirection refers to the standard input (file
-descriptor 0). If the first character of the redirection operator
-is @samp{>}, the redirection refers to the standard output (file
-descriptor 1).
-
-The word following the redirection operator in the following
-descriptions, unless otherwise noted, is subjected to brace expansion,
-tilde expansion, parameter expansion, command substitution, arithmetic
-expansion, quote removal, filename expansion, and word splitting.
-If it expands to more than one word, Bash reports an error.
-
-Note that the order of redirections is significant. For example,
-the command
-@example
-ls > @var{dirlist} 2>&1
-@end example
-@noindent
-directs both standard output (file descriptor 1) and standard error
-(file descriptor 2) to the file @var{dirlist}, while the command
-@example
-ls 2>&1 > @var{dirlist}
-@end example
-@noindent
-directs only the standard output to file @var{dirlist},
-because the standard error was duplicated as standard output
-before the standard output was redirected to @var{dirlist}.
-
-Bash handles several filenames specially when they are used in
-redirections, as described in the following table:
-
-@table @code
-@item /dev/fd/@var{fd}
-If @var{fd} is a valid integer, file descriptor @var{fd} is duplicated.
-
-@item /dev/stdin
-File descriptor 0 is duplicated.
-
-@item /dev/stdout
-File descriptor 1 is duplicated.
-
-@item /dev/stderr
-File descriptor 2 is duplicated.
-
-@item /dev/tcp/@var{host}/@var{port}
-If @var{host} is a valid hostname or Internet address, and @var{port}
-is an integer port number or service name, Bash attempts to open a TCP
-connection to the corresponding socket.
-
-@item /dev/udp/@var{host}/@var{port}
-If @var{host} is a valid hostname or Internet address, and @var{port}
-is an integer port number or service name, Bash attempts to open a UDP
-connection to the corresponding socket.
-
-@end table
-
-A failure to open or create a file causes the redirection to fail.
-
-@subsection Redirecting Input
-Redirection of input causes the file whose name results from
-the expansion of @var{word}
-to be opened for reading on file descriptor @code{n},
-or the standard input (file descriptor 0) if @code{n}
-is not specified.
-
-The general format for redirecting input is:
-@example
-[@var{n}]<@var{word}
-@end example
-
-@subsection Redirecting Output
-Redirection of output causes the file whose name results from
-the expansion of @var{word}
-to be opened for writing on file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n}
-is not specified. If the file does not exist it is created;
-if it does exist it is truncated to zero size.
-
-The general format for redirecting output is:
-@example
-[@var{n}]>[|]@var{word}
-@end example
-
-If the redirection operator is @samp{>}, and the @code{noclobber}
-option to the @code{set} builtin has been enabled, the redirection
-will fail if the file whose name results from the expansion of
-@var{word} exists and is a regular file.
-If the redirection operator is @samp{>|}, or the redirection operator is
-@samp{>} and the @code{noclobber} option is not enabled, the redirection
-is attempted even if the file named by @var{word} exists.
-
-@subsection Appending Redirected Output
-Redirection of output in this fashion
-causes the file whose name results from
-the expansion of @var{word}
-to be opened for appending on file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n}
-is not specified. If the file does not exist it is created.
-
-The general format for appending output is:
-@example
-[@var{n}]>>@var{word}
-@end example
-
-@subsection Redirecting Standard Output and Standard Error
-Bash allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be redirected to the file whose name is the
-expansion of @var{word} with this construct.
-
-There are two formats for redirecting standard output and
-standard error:
-@example
-&>@var{word}
-@end example
-@noindent
-and
-@example
->&@var{word}
-@end example
-@noindent
-Of the two forms, the first is preferred.
-This is semantically equivalent to
-@example
->@var{word} 2>&1
-@end example
-
-@subsection Here Documents
-This type of redirection instructs the shell to read input from the
-current source until a line containing only @var{word}
-(with no trailing blanks) is seen. All of
-the lines read up to that point are then used as the standard
-input for a command.
-
-The format of here-documents is:
-@example
-<<[@minus{}]@var{word}
- @var{here-document}
-@var{delimiter}
-@end example
-
-No parameter expansion, command substitution, arithmetic expansion,
-or filename expansion is performed on
-@var{word}. If any characters in @var{word} are quoted, the
-@var{delimiter} is the result of quote removal on @var{word},
-and the lines in the here-document are not expanded.
-If @var{word} is unquoted,
-all lines of the here-document are subjected to parameter expansion,
-command substitution, and arithmetic expansion. In the latter
-case, the character sequence @code{\newline} is ignored, and @samp{\}
-must be used to quote the characters
-@samp{\}, @samp{$}, and @samp{`}.
-
-If the redirection operator is @samp{<<-},
-then all leading tab characters are stripped from input lines and the
-line containing @var{delimiter}.
-This allows here-documents within shell scripts to be indented in a
-natural fashion.
-
-@subsection Here Strings
-A variant of here documents, the format is:
-@example
-<<< @var{word}
-@end example
-
-The @var{word} is expanded and supplied to the command on its standard
-input.
-
-@subsection Duplicating File Descriptors
-The redirection operator
-@example
-[@var{n}]<&@var{word}
-@end example
-@noindent
-is used to duplicate input file descriptors.
-If @var{word}
-expands to one or more digits, the file descriptor denoted by @var{n}
-is made to be a copy of that file descriptor.
-If the digits in @var{word} do not specify a file descriptor open for
-input, a redirection error occurs.
-If @var{word}
-evaluates to @samp{-}, file descriptor @var{n} is closed. If
-@var{n} is not specified, the standard input (file descriptor 0) is used.
-
-The operator
-@example
-[@var{n}]>&@var{word}
-@end example
-@noindent
-is used similarly to duplicate output file descriptors. If
-@var{n} is not specified, the standard output (file descriptor 1) is used.
-If the digits in @var{word} do not specify a file descriptor open for
-output, a redirection error occurs.
-As a special case, if @var{n} is omitted, and @var{word} does not
-expand to one or more digits, the standard output and standard
-error are redirected as described previously.
-
-@subsection Moving File Descriptors
-The redirection operator
-@example
-[@var{n}]<&@var{digit}-
-@end example
-@noindent
-moves the file descriptor @var{digit} to file descriptor @var{n},
-or the standard input (file descriptor 0) if @var{n} is not specified.
-@var{digit} is closed after being duplicated to @var{n}.
-
-Similarly, the redirection operator
-@example
-[@var{n}]>&@var{digit}-
-@end example
-@noindent
-moves the file descriptor @var{digit} to file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n} is not specified.
-
-@subsection Opening File Descriptors for Reading and Writing
-The redirection operator
-@example
-[@var{n}]<>@var{word}
-@end example
-@noindent
-causes the file whose name is the expansion of @var{word}
-to be opened for both reading and writing on file descriptor
-@var{n}, or on file descriptor 0 if @var{n}
-is not specified. If the file does not exist, it is created.
-
-@node Executing Commands
-@section Executing Commands
-
-@menu
-* Simple Command Expansion:: How Bash expands simple commands before
- executing them.
-
-* Command Search and Execution:: How Bash finds commands and runs them.
-
-* Command Execution Environment:: The environment in which Bash
- executes commands that are not
- shell builtins.
-
-* Environment:: The environment given to a command.
-
-* Exit Status:: The status returned by commands and how Bash
- interprets it.
-
-* Signals:: What happens when Bash or a command it runs
- receives a signal.
-
-@end menu
-
-@node Simple Command Expansion
-@subsection Simple Command Expansion
-@cindex command expansion
-
-When a simple command is executed, the shell performs the following
-expansions, assignments, and redirections, from left to right.
-
-@enumerate
-@item
-The words that the parser has marked as variable assignments (those
-preceding the command name) and redirections are saved for later
-processing.
-
-@item
-The words that are not variable assignments or redirections are
-expanded (@pxref{Shell Expansions}).
-If any words remain after expansion, the first word
-is taken to be the name of the command and the remaining words are
-the arguments.
-
-@item
-Redirections are performed as described above (@pxref{Redirections}).
-
-@item
-The text after the @samp{=} in each variable assignment undergoes tilde
-expansion, parameter expansion, command substitution, arithmetic expansion,
-and quote removal before being assigned to the variable.
-@end enumerate
-
-If no command name results, the variable assignments affect the current
-shell environment. Otherwise, the variables are added to the environment
-of the executed command and do not affect the current shell environment.
-If any of the assignments attempts to assign a value to a readonly variable,
-an error occurs, and the command exits with a non-zero status.
-
-If no command name results, redirections are performed, but do not
-affect the current shell environment. A redirection error causes the
-command to exit with a non-zero status.
-
-If there is a command name left after expansion, execution proceeds as
-described below. Otherwise, the command exits. If one of the expansions
-contained a command substitution, the exit status of the command is
-the exit status of the last command substitution performed. If there
-were no command substitutions, the command exits with a status of zero.
-
-@node Command Search and Execution
-@subsection Command Search and Execution
-@cindex command execution
-@cindex command search
-
-After a command has been split into words, if it results in a
-simple command and an optional list of arguments, the following
-actions are taken.
-
-@enumerate
-@item
-If the command name contains no slashes, the shell attempts to
-locate it. If there exists a shell function by that name, that
-function is invoked as described in @ref{Shell Functions}.
-
-@item
-If the name does not match a function, the shell searches for
-it in the list of shell builtins. If a match is found, that
-builtin is invoked.
-
-@item
-If the name is neither a shell function nor a builtin,
-and contains no slashes, Bash searches each element of
-@env{$PATH} for a directory containing an executable file
-by that name. Bash uses a hash table to remember the full
-pathnames of executable files to avoid multiple @env{PATH} searches
-(see the description of @code{hash} in @ref{Bourne Shell Builtins}).
-A full search of the directories in @env{$PATH}
-is performed only if the command is not found in the hash table.
-If the search is unsuccessful, the shell prints an error
-message and returns an exit status of 127.
-
-@item
-If the search is successful, or if the command name contains
-one or more slashes, the shell executes the named program in
-a separate execution environment.
-Argument 0 is set to the name given, and the remaining arguments
-to the command are set to the arguments supplied, if any.
-
-@item
-If this execution fails because the file is not in executable
-format, and the file is not a directory, it is assumed to be a
-@var{shell script} and the shell executes it as described in
-@ref{Shell Scripts}.
-
-@item
-If the command was not begun asynchronously, the shell waits for
-the command to complete and collects its exit status.
-
-@end enumerate
-
-@node Command Execution Environment
-@subsection Command Execution Environment
-@cindex execution environment
-
-The shell has an @var{execution environment}, which consists of the
-following:
-
-@itemize @bullet
-@item
-open files inherited by the shell at invocation, as modified by
-redirections supplied to the @code{exec} builtin
-
-@item
-the current working directory as set by @code{cd}, @code{pushd}, or
-@code{popd}, or inherited by the shell at invocation
-
-@item
-the file creation mode mask as set by @code{umask} or inherited from
-the shell's parent
-
-@item
-current traps set by @code{trap}
-
-@item
-shell parameters that are set by variable assignment or with @code{set}
-or inherited from the shell's parent in the environment
-
-@item
-shell functions defined during execution or inherited from the shell's
-parent in the environment
-
-@item
-options enabled at invocation (either by default or with command-line
-arguments) or by @code{set}
-
-@item
-options enabled by @code{shopt}
-
-@item
-shell aliases defined with @code{alias} (@pxref{Aliases})
-
-@item
-various process @sc{id}s, including those of background jobs
-(@pxref{Lists}), the value of @code{$$}, and the value of
-@env{$PPID}
-
-@end itemize
-
-When a simple command other than a builtin or shell function
-is to be executed, it
-is invoked in a separate execution environment that consists of
-the following. Unless otherwise noted, the values are inherited
-from the shell.
-
-@itemize @bullet
-@item
-the shell's open files, plus any modifications and additions specified
-by redirections to the command
-
-@item
-the current working directory
-
-@item
-the file creation mode mask
-
-@item
-shell variables and functions marked for export, along with variables
-exported for the command, passed in the environment (@pxref{Environment})
-
-@item
-traps caught by the shell are reset to the values inherited from the
-shell's parent, and traps ignored by the shell are ignored
-
-@end itemize
-
-A command invoked in this separate environment cannot affect the
-shell's execution environment.
-
-Command substitution and asynchronous commands are invoked in a
-subshell environment that is a duplicate of the shell environment,
-except that traps caught by the shell are reset to the values
-that the shell inherited from its parent at invocation. Builtin
-commands that are invoked as part of a pipeline are also executed
-in a subshell environment. Changes made to the subshell environment
-cannot affect the shell's execution environment.
-
-If a command is followed by a @samp{&} and job control is not active, the
-default standard input for the command is the empty file @file{/dev/null}.
-Otherwise, the invoked command inherits the file descriptors of the calling
-shell as modified by redirections.
-
-@node Environment
-@subsection Environment
-@cindex environment
-
-When a program is invoked it is given an array of strings
-called the @var{environment}.
-This is a list of name-value pairs, of the form @code{name=value}.
-
-Bash provides several ways to manipulate the environment.
-On invocation, the shell scans its own environment and
-creates a parameter for each name found, automatically marking
-it for @var{export}
-to child processes. Executed commands inherit the environment.
-The @code{export} and @samp{declare -x}
-commands allow parameters and functions to be added to and
-deleted from the environment. If the value of a parameter
-in the environment is modified, the new value becomes part
-of the environment, replacing the old. The environment
-inherited by any executed command consists of the shell's
-initial environment, whose values may be modified in the shell,
-less any pairs removed by the @code{unset} and @samp{export -n}
-commands, plus any additions via the @code{export} and
-@samp{declare -x} commands.
-
-The environment for any simple command
-or function may be augmented temporarily by prefixing it with
-parameter assignments, as described in @ref{Shell Parameters}.
-These assignment statements affect only the environment seen
-by that command.
-
-If the @option{-k} option is set (@pxref{The Set Builtin}), then all
-parameter assignments are placed in the environment for a command,
-not just those that precede the command name.
-
-When Bash invokes an external command, the variable @samp{$_}
-is set to the full path name of the command and passed to that
-command in its environment.
-
-@node Exit Status
-@subsection Exit Status
-@cindex exit status
-
-For the shell's purposes, a command which exits with a
-zero exit status has succeeded.
-A non-zero exit status indicates failure.
-This seemingly counter-intuitive scheme is used so there
-is one well-defined way to indicate success and a variety of
-ways to indicate various failure modes.
-When a command terminates on a fatal signal whose number is @var{N},
-Bash uses the value 128+@var{N} as the exit status.
-
-If a command is not found, the child process created to
-execute it returns a status of 127. If a command is found
-but is not executable, the return status is 126.
-
-If a command fails because of an error during expansion or redirection,
-the exit status is greater than zero.
-
-The exit status is used by the Bash conditional commands
-(@pxref{Conditional Constructs}) and some of the list
-constructs (@pxref{Lists}).
-
-All of the Bash builtins return an exit status of zero if they succeed
-and a non-zero status on failure, so they may be used by the
-conditional and list constructs.
-All builtins return an exit status of 2 to indicate incorrect usage.
-
-@node Signals
-@subsection Signals
-@cindex signal handling
-
-When Bash is interactive, in the absence of any traps, it ignores
-@code{SIGTERM} (so that @samp{kill 0} does not kill an interactive shell),
-and @code{SIGINT}
-is caught and handled (so that the @code{wait} builtin is interruptible).
-When Bash receives a @code{SIGINT}, it breaks out of any executing loops.
-In all cases, Bash ignores @code{SIGQUIT}.
-If job control is in effect (@pxref{Job Control}), Bash
-ignores @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-Commands started by Bash have signal handlers set to the
-values inherited by the shell from its parent.
-When job control is not in effect, asynchronous commands
-ignore @code{SIGINT} and @code{SIGQUIT} as well.
-Commands run as a result of
-command substitution ignore the keyboard-generated job control signals
-@code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-The shell exits by default upon receipt of a @code{SIGHUP}.
-Before exiting, an interactive shell resends the @code{SIGHUP} to
-all jobs, running or stopped.
-Stopped jobs are sent @code{SIGCONT} to ensure that they receive
-the @code{SIGHUP}.
-To prevent the shell from sending the @code{SIGHUP} signal to a
-particular job, it should be removed
-from the jobs table with the @code{disown}
-builtin (@pxref{Job Control Builtins}) or marked
-to not receive @code{SIGHUP} using @code{disown -h}.
-
-If the @code{huponexit} shell option has been set with @code{shopt}
-(@pxref{Bash Builtins}), Bash sends a @code{SIGHUP} to all jobs when
-an interactive login shell exits.
-
-When Bash receives a signal for which a trap has been set while waiting
-for a command to complete, the trap will not be executed until the
-command completes.
-When Bash is waiting for an asynchronous
-command via the @code{wait} builtin, the reception of a signal for
-which a trap has been set will cause the @code{wait} builtin to return
-immediately with an exit status greater than 128, immediately after
-which the trap is executed.
-
-@node Shell Scripts
-@section Shell Scripts
-@cindex shell script
-
-A shell script is a text file containing shell commands. When such
-a file is used as the first non-option argument when invoking Bash,
-and neither the @option{-c} nor @option{-s} option is supplied
-(@pxref{Invoking Bash}),
-Bash reads and executes commands from the file, then exits. This
-mode of operation creates a non-interactive shell. The shell first
-searches for the file in the current directory, and looks in the
-directories in @env{$PATH} if not found there.
-
-When Bash runs
-a shell script, it sets the special parameter @code{0} to the name
-of the file, rather than the name of the shell, and the positional
-parameters are set to the remaining arguments, if any are given.
-If no additional arguments are supplied, the positional parameters
-are unset.
-
-A shell script may be made executable by using the @code{chmod} command
-to turn on the execute bit. When Bash finds such a file while
-searching the @env{$PATH} for a command, it spawns a subshell to
-execute it. In other words, executing
-@example
-filename @var{arguments}
-@end example
-@noindent
-is equivalent to executing
-@example
-bash filename @var{arguments}
-@end example
-
-@noindent
-if @code{filename} is an executable shell script.
-This subshell reinitializes itself, so that the effect is as if a
-new shell had been invoked to interpret the script, with the
-exception that the locations of commands remembered by the parent
-(see the description of @code{hash} in @ref{Bourne Shell Builtins})
-are retained by the child.
-
-Most versions of Unix make this a part of the operating system's command
-execution mechanism. If the first line of a script begins with
-the two characters @samp{#!}, the remainder of the line specifies
-an interpreter for the program.
-Thus, you can specify Bash, @code{awk}, Perl, or some other
-interpreter and write the rest of the script file in that language.
-
-The arguments to the interpreter
-consist of a single optional argument following the interpreter
-name on the first line of the script file, followed by the name of
-the script file, followed by the rest of the arguments. Bash
-will perform this action on operating systems that do not handle it
-themselves. Note that some older versions of Unix limit the interpreter
-name and argument to a maximum of 32 characters.
-
-Bash scripts often begin with @code{#! /bin/bash} (assuming that
-Bash has been installed in @file{/bin}), since this ensures that
-Bash will be used to interpret the script, even if it is executed
-under another shell.
-
-@node Shell Builtin Commands
-@chapter Shell Builtin Commands
-
-@menu
-* Bourne Shell Builtins:: Builtin commands inherited from the Bourne
- Shell.
-* Bash Builtins:: Table of builtins specific to Bash.
-* The Set Builtin:: This builtin is so overloaded it
- deserves its own section.
-* Special Builtins:: Builtin commands classified specially by
- POSIX.2.
-@end menu
-
-Builtin commands are contained within the shell itself.
-When the name of a builtin command is used as the first word of
-a simple command (@pxref{Simple Commands}), the shell executes
-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
-the Bourne Shell, as well as the builtin commands which are unique
-to or have been extended in Bash.
-
-Several builtin commands are described in other chapters: builtin
-commands which provide the Bash interface to the job control
-facilities (@pxref{Job Control Builtins}), the directory stack
-(@pxref{Directory Stack Builtins}), the command history
-(@pxref{Bash History Builtins}), and the programmable completion
-facilities (@pxref{Programmable Completion Builtins}).
-
-Many of the builtins have been extended by @sc{posix} or Bash.
-
-@node Bourne Shell Builtins
-@section Bourne Shell Builtins
-
-The following shell builtin commands are inherited from the Bourne Shell.
-These commands are implemented as specified by the @sc{posix} 1003.2 standard.
-
-@table @code
-@item : @r{(a colon)}
-@btindex :
-@example
-: [@var{arguments}]
-@end example
-Do nothing beyond expanding @var{arguments} and performing redirections.
-The return status is zero.
-
-@item . @r{(a period)}
-@btindex .
-@example
-. @var{filename} [@var{arguments}]
-@end example
-Read and execute commands from the @var{filename} argument in the
-current shell context. If @var{filename} does not contain a slash,
-the @env{PATH} variable is used to find @var{filename}.
-When Bash is not in @sc{posix} mode, the current directory is searched
-if @var{filename} is not found in @env{$PATH}.
-If any @var{arguments} are supplied, they become the positional
-parameters when @var{filename} is executed. Otherwise the positional
-parameters are unchanged.
-The return status is the exit status of the last command executed, or
-zero if no commands are executed. If @var{filename} is not found, or
-cannot be read, the return status is non-zero.
-This builtin is equivalent to @code{source}.
-
-@item break
-@btindex break
-@example
-break [@var{n}]
-@end example
-Exit from a @code{for}, @code{while}, @code{until}, or @code{select} loop.
-If @var{n} is supplied, the @var{n}th enclosing loop is exited.
-@var{n} must be greater than or equal to 1.
-The return status is zero unless @var{n} is not greater than or equal to 1.
-
-@item cd
-@btindex cd
-@example
-cd [-L|-P] [@var{directory}]
-@end example
-Change the current working directory to @var{directory}. If @var{directory}
-is not given, the value of the @env{HOME} shell variable is used. If the
-shell variable @env{CDPATH} exists, it is used as a search path. If
-@var{directory} begins with a slash, @env{CDPATH} is not used.
-The @option{-P} option means
-to not follow symbolic links; symbolic links are followed by default
-or with the @option{-L} option.
-If @var{directory} is @samp{-}, it is equivalent to @env{$OLDPWD}.
-The return status is zero if the directory is successfully changed,
-non-zero otherwise.
-
-@item continue
-@btindex continue
-@example
-continue [@var{n}]
-@end example
-Resume the next iteration of an enclosing @code{for}, @code{while},
-@code{until}, or @code{select} loop.
-If @var{n} is supplied, the execution of the @var{n}th enclosing loop
-is resumed.
-@var{n} must be greater than or equal to 1.
-The return status is zero unless @var{n} is not greater than or equal to 1.
-
-@item eval
-@btindex eval
-@example
-eval [@var{arguments}]
-@end example
-The arguments are concatenated together into a single command, which is
-then read and executed, and its exit status returned as the exit status
-of @code{eval}.
-If there are no arguments or only empty arguments, the return status is
-zero.
-
-@item exec
-@btindex exec
-@example
-exec [-cl] [-a @var{name}] [@var{command} [@var{arguments}]]
-@end example
-If @var{command}
-is supplied, it replaces the shell without creating a new process.
-If the @option{-l} option is supplied, the shell places a dash at the
-beginning of the zeroth arg passed to @var{command}.
-This is what the @code{login} program does.
-The @option{-c} option causes @var{command} to be executed with an empty
-environment.
-If @option{-a} is supplied, the shell passes @var{name} as the zeroth
-argument to @var{command}.
-If no @var{command} is specified, redirections may be used to affect
-the current shell environment. If there are no redirection errors, the
-return status is zero; otherwise the return status is non-zero.
-
-@item exit
-@btindex exit
-@example
-exit [@var{n}]
-@end example
-Exit the shell, returning a status of @var{n} to the shell's parent.
-If @var{n} is omitted, the exit status is that of the last command executed.
-Any trap on @code{EXIT} is executed before the shell terminates.
-
-@item export
-@btindex export
-@example
-export [-fn] [-p] [@var{name}[=@var{value}]]
-@end example
-Mark each @var{name} to be passed to child processes
-in the environment. If the @option{-f} option is supplied, the @var{name}s
-refer to shell functions; otherwise the names refer to shell variables.
-The @option{-n} option means to no longer mark each @var{name} for export.
-If no @var{names} are supplied, or if the @option{-p} option is given, a
-list of exported names is displayed.
-The @option{-p} option displays output in a form that may be reused as input.
-If a variable name is followed by =@var{value}, the value of
-the variable is set to @var{value}.
-
-The return status is zero unless an invalid option is supplied, one of
-the names is not a valid shell variable name, or @option{-f} is supplied
-with a name that is not a shell function.
-
-@item getopts
-@btindex getopts
-@example
-getopts @var{optstring} @var{name} [@var{args}]
-@end example
-@code{getopts} is used by shell scripts to parse positional parameters.
-@var{optstring} contains the option characters to be recognized; if a
-character is followed by a colon, the option is expected to have an
-argument, which should be separated from it by white space.
-The colon (@samp{:}) and question mark (@samp{?}) may not be
-used as option characters.
-Each time it is invoked, @code{getopts}
-places the next option in the shell variable @var{name}, initializing
-@var{name} if it does not exist,
-and the index of the next argument to be processed into the
-variable @env{OPTIND}.
-@env{OPTIND} is initialized to 1 each time the shell or a shell script
-is invoked.
-When an option requires an argument,
-@code{getopts} places that argument into the variable @env{OPTARG}.
-The shell does not reset @env{OPTIND} automatically; it must be manually
-reset between multiple calls to @code{getopts} within the same shell
-invocation if a new set of parameters is to be used.
-
-When the end of options is encountered, @code{getopts} exits with a
-return value greater than zero.
-@env{OPTIND} is set to the index of the first non-option argument,
-and @code{name} is set to @samp{?}.
-
-@code{getopts}
-normally parses the positional parameters, but if more arguments are
-given in @var{args}, @code{getopts} parses those instead.
-
-@code{getopts} can report errors in two ways. If the first character of
-@var{optstring} is a colon, @var{silent}
-error reporting is used. In normal operation diagnostic messages
-are printed when invalid options or missing option arguments are
-encountered.
-If the variable @env{OPTERR}
-is set to 0, no error messages will be displayed, even if the first
-character of @code{optstring} is not a colon.
-
-If an invalid option is seen,
-@code{getopts} places @samp{?} into @var{name} and, if not silent,
-prints an error message and unsets @env{OPTARG}.
-If @code{getopts} is silent, the option character found is placed in
-@env{OPTARG} and no diagnostic message is printed.
-
-If a required argument is not found, and @code{getopts}
-is not silent, a question mark (@samp{?}) is placed in @var{name},
-@code{OPTARG} is unset, and a diagnostic message is printed.
-If @code{getopts} is silent, then a colon (@samp{:}) is placed in
-@var{name} and @env{OPTARG} is set to the option character found.
-
-@item hash
-@btindex hash
-@example
-hash [-'r] [-p @var{filename}] [-dt] [@var{name}]
-@end example
-Remember the full pathnames of commands specified as @var{name} arguments,
-so they need not be searched for on subsequent invocations.
-The commands are found by searching through the directories listed in
-@env{$PATH}.
-The @option{-p} option inhibits the path search, and @var{filename} is
-used as the location of @var{name}.
-The @option{-r} option causes the shell to forget all remembered locations.
-The @option{-d} option causes the shell to forget the remembered location
-of each @var{name}.
-If the @option{-t} option is supplied, the full pathname to which each
-@var{name} corresponds is printed. If multiple @var{name} arguments are
-supplied with @option{-t} the @var{name} is printed before the hashed
-full pathname.
-The @option{-l} option causes output to be displayed in a format
-that may be reused as input.
-If no arguments are given, or if only @option{-l} is supplied,
-information about remembered commands is printed.
-The return status is zero unless a @var{name} is not found or an invalid
-option is supplied.
-
-@item pwd
-@btindex pwd
-@example
-pwd [-LP]
-@end example
-Print the absolute pathname of the current working directory.
-If the @option{-P} option is supplied, the pathname printed will not
-contain symbolic links.
-If the @option{-L} option is supplied, the pathname printed may contain
-symbolic links.
-The return status is zero unless an error is encountered while
-determining the name of the current directory or an invalid option
-is supplied.
-
-@item readonly
-@btindex readonly
-@example
-readonly [-apf] [@var{name}[=@var{value}]] @dots{}
-@end example
-Mark each @var{name} as readonly.
-The values of these names may not be changed by subsequent assignment.
-If the @option{-f} option is supplied, each @var{name} refers to a shell
-function.
-The @option{-a} option means each @var{name} refers to an array variable.
-If no @var{name} arguments are given, or if the @option{-p}
-option is supplied, a list of all readonly names is printed.
-The @option{-p} option causes output to be displayed in a format that
-may be reused as input.
-If a variable name is followed by =@var{value}, the value of
-the variable is set to @var{value}.
-The return status is zero unless an invalid option is supplied, one of
-the @var{name} arguments is not a valid shell variable or function name,
-or the @option{-f} option is supplied with a name that is not a shell function.
-
-@item return
-@btindex return
-@example
-return [@var{n}]
-@end example
-Cause a shell function to exit with the return value @var{n}.
-If @var{n} is not supplied, the return value is the exit status of the
-last command executed in the function.
-This may also be used to terminate execution of a script being executed
-with the @code{.} (or @code{source}) builtin, returning either @var{n} or
-the exit status of the last command executed within the script as the exit
-status of the script.
-Any command associated with the @code{RETURN} trap is executed
-before execution resumes after the function or script.
-The return status is non-zero if @code{return} is used outside a function
-and not during the execution of a script by @code{.} or @code{source}.
-
-@item shift
-@btindex shift
-@example
-shift [@var{n}]
-@end example
-Shift the positional parameters to the left by @var{n}.
-The positional parameters from @var{n}+1 @dots{} @code{$#} are
-renamed to @code{$1} @dots{} @code{$#}-@var{n}+1.
-Parameters represented by the numbers @code{$#} to @var{n}+1 are unset.
-@var{n} must be a non-negative number less than or equal to @code{$#}.
-If @var{n} is zero or greater than @code{$#}, the positional parameters
-are not changed.
-If @var{n} is not supplied, it is assumed to be 1.
-The return status is zero unless @var{n} is greater than @code{$#} or
-less than zero, non-zero otherwise.
-
-@item test
-@itemx [
-@btindex test
-@btindex [
-Evaluate a conditional expression @var{expr}.
-Each operator and operand must be a separate argument.
-Expressions are composed of the primaries described below in
-@ref{Bash Conditional Expressions}.
-
-When the @code{[} form is used, the last argument to the command must
-be a @code{]}.
-
-Expressions may be combined using the following operators, listed in
-decreasing order of precedence.
-
-@table @code
-@item ! @var{expr}
-True if @var{expr} is false.
-
-@item ( @var{expr} )
-Returns the value of @var{expr}.
-This may be used to override the normal precedence of operators.
-
-@item @var{expr1} -a @var{expr2}
-True if both @var{expr1} and @var{expr2} are true.
-
-@item @var{expr1} -o @var{expr2}
-True if either @var{expr1} or @var{expr2} is true.
-@end table
-
-The @code{test} and @code{[} builtins evaluate conditional
-expressions using a set of rules based on the number of arguments.
-
-@table @asis
-@item 0 arguments
-The expression is false.
-
-@item 1 argument
-The expression is true if and only if the argument is not null.
-
-@item 2 arguments
-If the first argument is @samp{!}, the expression is true if and
-only if the second argument is null.
-If the first argument is one of the unary conditional operators
-(@pxref{Bash Conditional Expressions}), the expression
-is true if the unary test is true.
-If the first argument is not a valid unary operator, the expression is
-false.
-
-@item 3 arguments
-If the second argument is one of the binary conditional
-operators (@pxref{Bash Conditional Expressions}), the
-result of the expression is the result of the binary test using the
-first and third arguments as operands.
-If the first argument is @samp{!}, the value is the negation of
-the two-argument test using the second and third arguments.
-If the first argument is exactly @samp{(} and the third argument is
-exactly @samp{)}, the result is the one-argument test of the second
-argument.
-Otherwise, the expression is false.
-The @samp{-a} and @samp{-o} operators are considered binary operators
-in this case.
-
-@item 4 arguments
-If the first argument is @samp{!}, the result is the negation of
-the three-argument expression composed of the remaining arguments.
-Otherwise, the expression is parsed and evaluated according to
-precedence using the rules listed above.
-
-@item 5 or more arguments
-The expression is parsed and evaluated according to precedence
-using the rules listed above.
-@end table
-
-@item times
-@btindex times
-@example
-times
-@end example
-Print out the user and system times used by the shell and its children.
-The return status is zero.
-
-@item trap
-@btindex trap
-@example
-trap [-lp] [@var{arg}] [@var{sigspec} @dots{}]
-@end example
-The commands in @var{arg} are to be read and executed when the
-shell receives signal @var{sigspec}. If @var{arg} is absent or
-equal to @samp{-}, all specified signals are reset to the values
-they had when the shell was started.
-If @var{arg} is the null string, then the signal specified by
-each @var{sigspec} is ignored by the shell and commands it invokes.
-If @var{arg} is not present and @option{-p} has been supplied,
-the shell displays the trap commands associated with each @var{sigspec}.
-If no arguments are supplied, or
-only @option{-p} is given, @code{trap} prints the list of commands
-associated with each signal number in a form that may be reused as
-shell input.
-The @option{-l} option causes the shell to print a list of signal names
-and their corresponding numbers.
-
-Each @var{sigspec} is either a signal name such as @code{SIGINT} (with
-or without the @code{SIG} prefix) or a signal number.
-If a @var{sigspec}
-is @code{0} or @code{EXIT}, @var{arg} is executed when the shell exits.
-If a @var{sigspec} is @code{DEBUG}, the command @var{arg} is executed
-before every simple command, @code{for} command, @code{case} command,
-@code{select} command, every arithmetic @code{for} command, and before
-the first command executes in a shell function.
-Refer to the description of the @code{extglob} option to the
-@code{shopt} builtin (@pxref{Bash Builtins}) for details of its
-effect on the @code{DEBUG} trap.
-If a @var{sigspec} is @code{ERR}, the command @var{arg}
-is executed whenever a simple command has a non-zero exit status.
-The @code{ERR} trap is not executed if the failed command is part of the
-command list immediately following an @code{until} or @code{while} keyword,
-part of the test in an @code{if} statement,
-part of a @code{&&} or @code{||} list, or if the command's return
-status is being inverted using @code{!}.
-If a @var{sigspec} is @code{RETURN}, the command @var{arg} is executed
-each time a shell function or a script executed with the @code{.} or
-@code{source} builtins finishes executing.
-
-Signals ignored upon entry to the shell cannot be trapped or reset.
-Trapped signals are reset to their original values in a child
-process when it is created.
-
-The return status is zero unless a @var{sigspec} does not specify a
-valid signal.
-
-@item umask
-@btindex umask
-@example
-umask [-p] [-S] [@var{mode}]
-@end example
-Set the shell process's file creation mask to @var{mode}. If
-@var{mode} begins with a digit, it is interpreted as an octal number;
-if not, it is interpreted as a symbolic mode mask similar
-to that accepted by the @code{chmod} command. If @var{mode} is
-omitted, the current value of the mask is printed. If the @option{-S}
-option is supplied without a @var{mode} argument, the mask is printed
-in a symbolic format.
-If the @option{-p} option is supplied, and @var{mode}
-is omitted, the output is in a form that may be reused as input.
-The return status is zero if the mode is successfully changed or if
-no @var{mode} argument is supplied, and non-zero otherwise.
-
-Note that when the mode is interpreted as an octal number, each number
-of the umask is subtracted from @code{7}. Thus, a umask of @code{022}
-results in permissions of @code{755}.
-
-@item unset
-@btindex unset
-@example
-unset [-fv] [@var{name}]
-@end example
-Each variable or function @var{name} is removed.
-If no options are supplied, or the @option{-v} option is given, each
-@var{name} refers to a shell variable.
-If the @option{-f} option is given, the @var{name}s refer to shell
-functions, and the function definition is removed.
-Readonly variables and functions may not be unset.
-The return status is zero unless a @var{name} is readonly.
-@end table
-
-@node Bash Builtins
-@section Bash Builtin Commands
-
-This section describes builtin commands which are unique to
-or have been extended in Bash.
-Some of these commands are specified in the @sc{posix} 1003.2 standard.
-
-@table @code
-
-@item alias
-@btindex alias
-@example
-alias [@code{-p}] [@var{name}[=@var{value}] @dots{}]
-@end example
-
-Without arguments or with the @option{-p} option, @code{alias} prints
-the list of aliases on the standard output in a form that allows
-them to be reused as input.
-If arguments are supplied, an alias is defined for each @var{name}
-whose @var{value} is given. If no @var{value} is given, the name
-and value of the alias is printed.
-Aliases are described in @ref{Aliases}.
-
-@item bind
-@btindex bind
-@example
-bind [-m @var{keymap}] [-lpsvPSV]
-bind [-m @var{keymap}] [-q @var{function}] [-u @var{function}] [-r @var{keyseq}]
-bind [-m @var{keymap}] -f @var{filename}
-bind [-m @var{keymap}] -x @var{keyseq:shell-command}
-bind [-m @var{keymap}] @var{keyseq:function-name}
-bind @var{readline-command}
-@end example
-
-Display current Readline (@pxref{Command Line Editing})
-key and function bindings,
-bind a key sequence to a Readline function or macro,
-or set a Readline variable.
-Each non-option argument is a command as it would appear in a
-a Readline initialization file (@pxref{Readline Init File}),
-but each binding or command must be passed as a separate argument; e.g.,
-@samp{"\C-x\C-r":re-read-init-file}.
-Options, if supplied, have the following meanings:
-
-@table @code
-@item -m @var{keymap}
-Use @var{keymap} as the keymap to be affected by
-the subsequent bindings. Acceptable @var{keymap}
-names are
-@code{emacs},
-@code{emacs-standard},
-@code{emacs-meta},
-@code{emacs-ctlx},
-@code{vi},
-@code{vi-move},
-@code{vi-command}, and
-@code{vi-insert}.
-@code{vi} is equivalent to @code{vi-command};
-@code{emacs} is equivalent to @code{emacs-standard}.
-
-@item -l
-List the names of all Readline functions.
-
-@item -p
-Display Readline function names and bindings in such a way that they
-can be used as input or in a Readline initialization file.
-
-@item -P
-List current Readline function names and bindings.
-
-@item -v
-Display Readline variable names and values in such a way that they
-can be used as input or in a Readline initialization file.
-
-@item -V
-List current Readline variable names and values.
-
-@item -s
-Display Readline key sequences bound to macros and the strings they output
-in such a way that they can be used as input or in a Readline
-initialization file.
-
-@item -S
-Display Readline key sequences bound to macros and the strings they output.
-
-@item -f @var{filename}
-Read key bindings from @var{filename}.
-
-@item -q @var{function}
-Query about which keys invoke the named @var{function}.
-
-@item -u @var{function}
-Unbind all keys bound to the named @var{function}.
-
-@item -r @var{keyseq}
-Remove any current binding for @var{keyseq}.
-
-@item -x @var{keyseq:shell-command}
-Cause @var{shell-command} to be executed whenever @var{keyseq} is
-entered.
-
-@end table
-
-@noindent
-The return status is zero unless an invalid option is supplied or an
-error occurs.
-
-@item builtin
-@btindex builtin
-@example
-builtin [@var{shell-builtin} [@var{args}]]
-@end example
-Run a shell builtin, passing it @var{args}, and return its exit status.
-This is useful when defining a shell function with the same
-name as a shell builtin, retaining the functionality of the builtin within
-the function.
-The return status is non-zero if @var{shell-builtin} is not a shell
-builtin command.
-
-@item caller
-@btindex caller
-@example
-caller [@var{expr}]
-@end example
-Returns the context of any active subroutine call (a shell function or
-a script executed with the @code{.} or @code{source} builtins.
-
-Without @var{expr}, @code{caller} displays the line number and source
-filename of the current subroutine call.
-If a non-negative integer is supplied as @var{expr}, @code{caller}
-displays the line number, subroutine name, and source file corresponding
-to that position in the current execution call stack. This extra
-information may be used, for example, to print a stack trace. The
-current frame is frame 0.
-
-The return value is 0 unless the shell is not executing a subroutine
-call or @var{expr} does not correspond to a valid position in the
-call stack.
-
-@item command
-@btindex command
-@example
-command [-pVv] @var{command} [@var{arguments} @dots{}]
-@end example
-Runs @var{command} with @var{arguments} ignoring any shell function
-named @var{command}.
-Only shell builtin commands or commands found by searching the
-@env{PATH} are executed.
-If there is a shell function named @code{ls}, running @samp{command ls}
-within the function will execute the external command @code{ls}
-instead of calling the function recursively.
-The @option{-p} option means to use a default value for @env{PATH}
-that is guaranteed to find all of the standard utilities.
-The return status in this case is 127 if @var{command} cannot be
-found or an error occurred, and the exit status of @var{command}
-otherwise.
-
-If either the @option{-V} or @option{-v} option is supplied, a
-description of @var{command} is printed. The @option{-v} option
-causes a single word indicating the command or file name used to
-invoke @var{command} to be displayed; the @option{-V} option produces
-a more verbose description. In this case, the return status is
-zero if @var{command} is found, and non-zero if not.
-
-@item declare
-@btindex declare
-@example
-declare [-afFirtx] [-p] [@var{name}[=@var{value}] @dots{}]
-@end example
-
-Declare variables and give them attributes. If no @var{name}s
-are given, then display the values of variables instead.
-
-The @option{-p} option will display the attributes and values of each
-@var{name}.
-When @option{-p} is used, additional options are ignored.
-The @option{-F} option inhibits the display of function definitions;
-only the function name and attributes are printed.
-If the @code{extdebug} shell option is enabled using @code{shopt}
-(@pxref{Bash Builtins}), the source file name and line number where
-the function is defined are displayed as well.
-@option{-F} implies @option{-f}.
-The following options can be used to restrict output to variables with
-the specified attributes or to give variables attributes:
-
-@table @code
-@item -a
-Each @var{name} is an array variable (@pxref{Arrays}).
-
-@item -f
-Use function names only.
-
-@item -i
-The variable is to be treated as
-an integer; arithmetic evaluation (@pxref{Shell Arithmetic}) is
-performed when the variable is assigned a value.
-
-@item -r
-Make @var{name}s readonly. These names cannot then be assigned values
-by subsequent assignment statements or unset.
-
-@item -t
-Give each @var{name} the @code{trace} attribute.
-Traced functions inherit the @code{DEBUG} trap from the calling shell.
-The trace attribute has no special meaning for variables.
-
-@item -x
-Mark each @var{name} for export to subsequent commands via
-the environment.
-@end table
-
-Using @samp{+} instead of @samp{-} turns off the attribute instead.
-When used in a function, @code{declare} makes each @var{name} local,
-as with the @code{local} command. If a variable name is followed by
-=@var{value}, the value of the variable is set to @var{value}.
-
-The return status is zero unless an invalid option is encountered,
-an attempt is made to define a function using @samp{-f foo=bar},
-an attempt is made to assign a value to a readonly variable,
-an attempt is made to assign a value to an array variable without
-using the compound assignment syntax (@pxref{Arrays}),
-one of the @var{names} is not a valid shell variable name,
-an attempt is made to turn off readonly status for a readonly variable,
-an attempt is made to turn off array status for an array variable,
-or an attempt is made to display a non-existent function with @option{-f}.
-
-@item echo
-@btindex echo
-@example
-echo [-neE] [@var{arg} @dots{}]
-@end example
-Output the @var{arg}s, separated by spaces, terminated with a
-newline.
-The return status is always 0.
-If @option{-n} is specified, the trailing newline is suppressed.
-If the @option{-e} option is given, interpretation of the following
-backslash-escaped characters is enabled.
-The @option{-E} option disables the interpretation of these escape characters,
-even on systems where they are interpreted by default.
-The @code{xpg_echo} shell option may be used to
-dynamically determine whether or not @code{echo} expands these
-escape characters by default.
-@code{echo} interprets the following escape sequences:
-@table @code
-@item \a
-alert (bell)
-@item \b
-backspace
-@item \c
-suppress trailing newline
-@item \e
-escape
-@item \f
-form feed
-@item \n
-new line
-@item \r
-carriage return
-@item \t
-horizontal tab
-@item \v
-vertical tab
-@item \\
-backslash
-@item \0@var{nnn}
-the eight-bit character whose value is the octal value @var{nnn}
-(zero to three octal digits)
-@item \@var{nnn}
-the eight-bit character whose value is the octal value @var{nnn}
-(one to three octal digits)
-@item \x@var{HH}
-the eight-bit character whose value is the hexadecimal value @var{HH}
-(one or two hex digits)
-@end table
-
-@item enable
-@btindex enable
-@example
-enable [-n] [-p] [-f @var{filename}] [-ads] [@var{name} @dots{}]
-@end example
-Enable and disable builtin shell commands.
-Disabling a builtin allows a disk command which has the same name
-as a shell builtin to be executed without specifying a full pathname,
-even though the shell normally searches for builtins before disk commands.
-If @option{-n} is used, the @var{name}s become disabled. Otherwise
-@var{name}s are enabled. For example, to use the @code{test} binary
-found via @env{$PATH} instead of the shell builtin version, type
-@samp{enable -n test}.
-
-If the @option{-p} option is supplied, or no @var{name} arguments appear,
-a list of shell builtins is printed. With no other arguments, the list
-consists of all enabled shell builtins.
-The @option{-a} option means to list
-each builtin with an indication of whether or not it is enabled.
-
-The @option{-f} option means to load the new builtin command @var{name}
-from shared object @var{filename}, on systems that support dynamic loading.
-The @option{-d} option will delete a builtin loaded with @option{-f}.
-
-If there are no options, a list of the shell builtins is displayed.
-The @option{-s} option restricts @code{enable} to the @sc{posix} special
-builtins. If @option{-s} is used with @option{-f}, the new builtin becomes
-a special builtin (@pxref{Special Builtins}).
-
-The return status is zero unless a @var{name} is not a shell builtin
-or there is an error loading a new builtin from a shared object.
-
-@item help
-@btindex help
-@example
-help [-s] [@var{pattern}]
-@end example
-Display helpful information about builtin commands.
-If @var{pattern} is specified, @code{help} gives detailed help
-on all commands matching @var{pattern}, otherwise a list of
-the builtins is printed.
-The @option{-s} option restricts the information displayed to a short
-usage synopsis.
-The return status is zero unless no command matches @var{pattern}.
-
-@item let
-@btindex let
-@example
-let @var{expression} [@var{expression}]
-@end example
-The @code{let} builtin allows arithmetic to be performed on shell
-variables. Each @var{expression} is evaluated according to the
-rules given below in @ref{Shell Arithmetic}. If the
-last @var{expression} evaluates to 0, @code{let} returns 1;
-otherwise 0 is returned.
-
-@item local
-@btindex local
-@example
-local [@var{option}] @var{name}[=@var{value}] @dots{}
-@end example
-For each argument, a local variable named @var{name} is created,
-and assigned @var{value}.
-The @var{option} can be any of the options accepted by @code{declare}.
-@code{local} can only be used within a function; it makes the variable
-@var{name} have a visible scope restricted to that function and its
-children. The return status is zero unless @code{local} is used outside
-a function, an invalid @var{name} is supplied, or @var{name} is a
-readonly variable.
-
-@item logout
-@btindex logout
-@example
-logout [@var{n}]
-@end example
-Exit a login shell, returning a status of @var{n} to the shell's
-parent.
-
-@item printf
-@btindex printf
-@example
-@code{printf} @var{format} [@var{arguments}]
-@end example
-Write the formatted @var{arguments} to the standard output under the
-control of the @var{format}.
-The @var{format} is a character string which contains three types of objects:
-plain characters, which are simply copied to standard output, character
-escape sequences, which are converted and copied to the standard output, and
-format specifications, each of which causes printing of the next successive
-@var{argument}.
-In addition to the standard @code{printf(1)} formats, @samp{%b} causes
-@code{printf} to expand backslash escape sequences in the corresponding
-@var{argument}, and @samp{%q} causes @code{printf} to output the
-corresponding @var{argument} in a format that can be reused as shell input.
-
-The @var{format} is reused as necessary to consume all of the @var{arguments}.
-If the @var{format} requires more @var{arguments} than are supplied, the
-extra format specifications behave as if a zero value or null string, as
-appropriate, had been supplied. The return value is zero on success,
-non-zero on failure.
-
-@item read
-@btindex read
-@example
-read [-ers] [-a @var{aname}] [-d @var{delim}] [-n @var{nchars}] [-p @var{prompt}] [-t @var{timeout}] [-u @var{fd}] [@var{name} @dots{}]
-@end example
-One line is read from the standard input, or from the file descriptor
-@var{fd} supplied as an argument to the @option{-u} option, and the first word
-is assigned to the first @var{name}, the second word to the second @var{name},
-and so on, with leftover words and their intervening separators assigned
-to the last @var{name}.
-If there are fewer words read from the input stream than names,
-the remaining names are assigned empty values.
-The characters in the value of the @env{IFS} variable
-are used to split the line into words.
-The backslash character @samp{\} may be used to remove any special
-meaning for the next character read and for line continuation.
-If no names are supplied, the line read is assigned to the
-variable @env{REPLY}.
-The return code is zero, unless end-of-file is encountered, @code{read}
-times out, or an invalid file descriptor is supplied as the argument to
-@option{-u}.
-Options, if supplied, have the following meanings:
-
-@table @code
-@item -a @var{aname}
-The words are assigned to sequential indices of the array variable
-@var{aname}, starting at 0.
-All elements are removed from @var{aname} before the assignment.
-Other @var{name} arguments are ignored.
-
-@item -d @var{delim}
-The first character of @var{delim} is used to terminate the input line,
-rather than newline.
-
-@item -e
-Readline (@pxref{Command Line Editing}) is used to obtain the line.
-
-@item -n @var{nchars}
-@code{read} returns after reading @var{nchars} characters rather than
-waiting for a complete line of input.
-
-@item -p @var{prompt}
-Display @var{prompt}, without a trailing newline, before attempting
-to read any input.
-The prompt is displayed only if input is coming from a terminal.
-
-@item -r
-If this option is given, backslash does not act as an escape character.
-The backslash is considered to be part of the line.
-In particular, a backslash-newline pair may not be used as a line
-continuation.
-
-@item -s
-Silent mode. If input is coming from a terminal, characters are
-not echoed.
-
-@item -t @var{timeout}
-Cause @code{read} to time out and return failure if a complete line of
-input is not read within @var{timeout} seconds.
-This option has no effect if @code{read} is not reading input from the
-terminal or a pipe.
-
-@item -u @var{fd}
-Read input from file descriptor @var{fd}.
-
-@end table
-
-@item shopt
-@btindex shopt
-@example
-shopt [-pqsu] [-o] [@var{optname} @dots{}]
-@end example
-Toggle the values of variables controlling optional shell behavior.
-With no options, or with the @option{-p} option, a list of all settable
-options is displayed, with an indication of whether or not each is set.
-The @option{-p} option causes output to be displayed in a form that
-may be reused as input.
-Other options have the following meanings:
-
-@table @code
-@item -s
-Enable (set) each @var{optname}.
-
-@item -u
-Disable (unset) each @var{optname}.
-
-@item -q
-Suppresses normal output; the return status
-indicates whether the @var{optname} is set or unset.
-If multiple @var{optname} arguments are given with @option{-q},
-the return status is zero if all @var{optnames} are enabled;
-non-zero otherwise.
-
-@item -o
-Restricts the values of
-@var{optname} to be those defined for the @option{-o} option to the
-@code{set} builtin (@pxref{The Set Builtin}).
-@end table
-
-If either @option{-s} or @option{-u}
-is used with no @var{optname} arguments, the display is limited to
-those options which are set or unset, respectively.
-
-Unless otherwise noted, the @code{shopt} options are disabled (off)
-by default.
-
-The return status when listing options is zero if all @var{optnames}
-are enabled, non-zero otherwise. When setting or unsetting options,
-the return status is zero unless an @var{optname} is not a valid shell
-option.
-
-The list of @code{shopt} options is:
-@table @code
-@item cdable_vars
-If this is set, an argument to the @code{cd}
-builtin command that
-is not a directory is assumed to be the name of a variable whose
-value is the directory to change to.
-
-@item cdspell
-If set, minor errors in the spelling of a directory component in a
-@code{cd} command will be corrected.
-The errors checked for are transposed characters,
-a missing character, and a character too many.
-If a correction is found, the corrected path is printed,
-and the command proceeds.
-This option is only used by interactive shells.
-
-@item checkhash
-If this is set, Bash checks that a command found in the hash
-table exists before trying to execute it. If a hashed command no
-longer exists, a normal path search is performed.
-
-@item checkwinsize
-If set, Bash checks the window size after each command
-and, if necessary, updates the values of
-@env{LINES} and @env{COLUMNS}.
-
-@item cmdhist
-If set, Bash
-attempts to save all lines of a multiple-line
-command in the same history entry. This allows
-easy re-editing of multi-line commands.
-
-@item dotglob
-If set, Bash includes filenames beginning with a `.' in
-the results of filename expansion.
-
-@item execfail
-If this is set, a non-interactive shell will not exit if
-it cannot execute the file specified as an argument to the @code{exec}
-builtin command. An interactive shell does not exit if @code{exec}
-fails.
-
-@item expand_aliases
-If set, aliases are expanded as described below under Aliases,
-@ref{Aliases}.
-This option is enabled by default for interactive shells.
-
-@item extdebug
-If set, behavior intended for use by debuggers is enabled:
-
-@enumerate
-@item
-The @option{-F} option to the @code{declare} builtin (@pxref{Bash Builtins})
-displays the source file name and line number corresponding to each function
-name supplied as an argument.
-
-@item
-If the command run by the @code{DEBUG} trap returns a non-zero value, the
-next command is skipped and not executed.
-
-@item
-If the command run by the @code{DEBUG} trap returns a value of 2, and the
-shell is executing in a subroutine (a shell function or a shell script
-executed by the @code{.} or @code{source} builtins), a call to
-@code{return} is simulated.
-@end enumerate
-
-@item extglob
-If set, the extended pattern matching features described above
-(@pxref{Pattern Matching}) are enabled.
-
-@item extquote
-If set, @code{$'@var{string}'} and @code{$"@var{string}"} quoting is
-performed within @code{$@{@var{parameter}@}} expansions
-enclosed in double quotes. This option is enabled by default.
-
-@item histappend
-If set, the history list is appended to the file named by the value
-of the @env{HISTFILE}
-variable when the shell exits, rather than overwriting the file.
-
-@item histreedit
-If set, and Readline
-is being used, a user is given the opportunity to re-edit a
-failed history substitution.
-
-@item histverify
-If set, and Readline
-is being used, the results of history substitution are not immediately
-passed to the shell parser. Instead, the resulting line is loaded into
-the Readline editing buffer, allowing further modification.
-
-@item hostcomplete
-If set, and Readline is being used, Bash will attempt to perform
-hostname completion when a word containing a @samp{@@} is being
-completed (@pxref{Commands For Completion}). This option is enabled
-by default.
-
-@item huponexit
-If set, Bash will send @code{SIGHUP} to all jobs when an interactive
-login shell exits (@pxref{Signals}).
-
-@item interactive_comments
-Allow a word beginning with @samp{#}
-to cause that word and all remaining characters on that
-line to be ignored in an interactive shell.
-This option is enabled by default.
-
-@item lithist
-If enabled, and the @code{cmdhist}
-option is enabled, multi-line commands are saved to the history with
-embedded newlines rather than using semicolon separators where possible.
-
-@item login_shell
-The shell sets this option if it is started as a login shell
-(@pxref{Invoking Bash}).
-The value may not be changed.
-
-@item mailwarn
-If set, and a file that Bash is checking for mail has been
-accessed since the last time it was checked, the message
-@code{"The mail in @var{mailfile} has been read"} is displayed.
-
-@item no_empty_cmd_completion
-If set, and Readline is being used, Bash will not attempt to search
-the @env{PATH} for possible completions when completion is attempted
-on an empty line.
-
-@item nocaseglob
-If set, Bash matches filenames in a case-insensitive fashion when
-performing filename expansion.
-
-@item nullglob
-If set, Bash allows filename patterns which match no
-files to expand to a null string, rather than themselves.
-
-@item progcomp
-If set, the programmable completion facilities
-(@pxref{Programmable Completion}) are enabled.
-This option is enabled by default.
-
-@item promptvars
-If set, prompt strings undergo variable and parameter expansion after
-being expanded (@pxref{Printing a Prompt}).
-This option is enabled by default.
-
-@item restricted_shell
-The shell sets this option if it is started in restricted mode
-(@pxref{The Restricted Shell}).
-The value may not be changed.
-This is not reset when the startup files are executed, allowing
-the startup files to discover whether or not a shell is restricted.
-
-@item shift_verbose
-If this is set, the @code{shift}
-builtin prints an error message when the shift count exceeds the
-number of positional parameters.
-
-@item sourcepath
-If set, the @code{source} builtin uses the value of @env{PATH}
-to find the directory containing the file supplied as an argument.
-This option is enabled by default.
-
-@item xpg_echo
-If set, the @code{echo} builtin expands backslash-escape sequences
-by default.
-
-@end table
-
-@noindent
-The return status when listing options is zero if all @var{optnames}
-are enabled, non-zero otherwise.
-When setting or unsetting options, the return status is zero unless an
-@var{optname} is not a valid shell option.
-
-@item source
-@btindex source
-@example
-source @var{filename}
-@end example
-A synonym for @code{.} (@pxref{Bourne Shell Builtins}).
-
-@item type
-@btindex type
-@example
-type [-afptP] [@var{name} @dots{}]
-@end example
-For each @var{name}, indicate how it would be interpreted if used as a
-command name.
-
-If the @option{-t} option is used, @code{type} prints a single word
-which is one of @samp{alias}, @samp{function}, @samp{builtin},
-@samp{file} or @samp{keyword},
-if @var{name} is an alias, shell function, shell builtin,
-disk file, or shell reserved word, respectively.
-If the @var{name} is not found, then nothing is printed, and
-@code{type} returns a failure status.
-
-If the @option{-p} option is used, @code{type} either returns the name
-of the disk file that would be executed, or nothing if @option{-t}
-would not return @samp{file}.
-
-The @option{-P} option forces a path search for each @var{name}, even if
-@option{-t} would not return @samp{file}.
-
-If a command is hashed, @option{-p} and @option{-P} print the hashed value,
-not necessarily the file that appears first in @code{$PATH}.
-
-If the @option{-a} option is used, @code{type} returns all of the places
-that contain an executable named @var{file}.
-This includes aliases and functions, if and only if the @option{-p} option
-is not also used.
-
-If the @option{-f} option is used, @code{type} does not attempt to find
-shell functions, as with the @code{command} builtin.
-
-The return status is zero if any of the @var{names} are found, non-zero
-if none are found.
-
-@item typeset
-@btindex typeset
-@example
-typeset [-afFrxi] [-p] [@var{name}[=@var{value}] @dots{}]
-@end example
-The @code{typeset} command is supplied for compatibility with the Korn
-shell; however, it has been deprecated in favor of the @code{declare}
-builtin command.
-
-@item ulimit
-@btindex ulimit
-@example
-ulimit [-acdflmnpstuvSH] [@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
-option is given, it is interpreted as follows:
-@table @code
-@item -S
-Change and report the soft limit associated with a resource.
-
-@item -H
-Change and report the hard limit associated with a resource.
-
-@item -a
-All current limits are reported.
-
-@item -c
-The maximum size of core files created.
-
-@item -d
-The maximum size of a process's data segment.
-
-@item -f
-The maximum size of files created by the shell.
-
-@item -l
-The maximum size that may be locked into memory.
-
-@item -m
-The maximum resident set size.
-
-@item -n
-The maximum number of open file descriptors.
-
-@item -p
-The pipe buffer size.
-
-@item -s
-The maximum stack size.
-
-@item -t
-The maximum amount of cpu time in seconds.
-
-@item -u
-The maximum number of processes available to a single user.
-
-@item -v
-The maximum amount of virtual memory available to the process.
-
-@end table
-
-If @var{limit} is given, it is the new value of the specified resource;
-the special @var{limit} values @code{hard}, @code{soft}, and
-@code{unlimited} stand for the current hard limit, the current soft limit,
-and no limit, respectively.
-Otherwise, the current value of the soft limit for the specified resource
-is printed, unless the @option{-H} option is supplied.
-When setting new limits, if neither @option{-H} nor @option{-S} is supplied,
-both the hard and soft limits are set.
-If no option is given, then @option{-f} is assumed. Values are in 1024-byte
-increments, except for @option{-t}, which is in seconds, @option{-p},
-which is in units of 512-byte blocks, and @option{-n} and @option{-u}, which
-are unscaled values.
-
-The return status is zero unless an invalid option or argument is supplied,
-or an error occurs while setting a new limit.
-
-@item unalias
-@btindex unalias
-@example
-unalias [-a] [@var{name} @dots{} ]
-@end example
-
-Remove each @var{name} from the list of aliases. If @option{-a} is
-supplied, all aliases are removed.
-Aliases are described in @ref{Aliases}.
-
-@end table
-
-@node The Set Builtin
-@section The Set Builtin
-
-This builtin is so complicated that it deserves its own section.
-
-@table @code
-@item set
-@btindex set
-@example
-set [--abefhkmnptuvxBCHP] [-o @var{option}] [@var{argument} @dots{}]
-@end example
-
-If no options or arguments are supplied, @code{set} displays the names
-and values of all shell variables and functions, sorted according to the
-current locale, in a format that may be reused as input.
-
-When options are supplied, they set or unset shell attributes.
-Options, if specified, have the following meanings:
-
-@table @code
-@item -a
-Mark variables and function which are modified or created for export
-to the environment of subsequent commands.
-
-@item -b
-Cause the status of terminated background jobs to be reported
-immediately, rather than before printing the next primary prompt.
-
-@item -e
-Exit immediately if a simple command (@pxref{Simple Commands}) exits
-with a non-zero status, unless the command that fails is part of the
-command list immediately following a @code{while} or @code{until}
-keyword, part of the test in an @code{if} statement,
-part of a @code{&&} or @code{||} list, or if the command's return
-status is being inverted using @code{!}.
-A trap on @code{ERR}, if set, is executed before the shell exits.
-
-@item -f
-Disable file name generation (globbing).
-
-@item -h
-Locate and remember (hash) commands as they are looked up for execution.
-This option is enabled by default.
-
-@item -k
-All arguments in the form of assignment statements are placed
-in the environment for a command, not just those that precede
-the command name.
-
-@item -m
-Job control is enabled (@pxref{Job Control}).
-
-@item -n
-Read commands but do not execute them; this may be used to check a
-script for syntax errors.
-This option is ignored by interactive shells.
-
-@item -o @var{option-name}
-
-Set the option corresponding to @var{option-name}:
-
-@table @code
-@item allexport
-Same as @code{-a}.
-
-@item braceexpand
-Same as @code{-B}.
-
-@item emacs
-Use an @code{emacs}-style line editing interface (@pxref{Command Line Editing}).
-
-@item errexit
-Same as @code{-e}.
-
-@item errtrace
-Same as @code{-E}.
-
-@item functrace
-Same as @code{-T}.
-
-@item hashall
-Same as @code{-h}.
-
-@item histexpand
-Same as @code{-H}.
-
-@item history
-Enable command history, as described in @ref{Bash History Facilities}.
-This option is on by default in interactive shells.
-
-@item ignoreeof
-An interactive shell will not exit upon reading EOF.
-
-@item keyword
-Same as @code{-k}.
-
-@item monitor
-Same as @code{-m}.
-
-@item noclobber
-Same as @code{-C}.
-
-@item noexec
-Same as @code{-n}.
-
-@item noglob
-Same as @code{-f}.
-
-@item nolog
-Currently ignored.
-
-@item notify
-Same as @code{-b}.
-
-@item nounset
-Same as @code{-u}.
-
-@item onecmd
-Same as @code{-t}.
-
-@item physical
-Same as @code{-P}.
-
-@item posix
-Change the behavior of Bash where the default operation differs
-from the @sc{posix} 1003.2 standard to match the standard
-(@pxref{Bash POSIX Mode}).
-This is intended to make Bash behave as a strict superset of that
-standard.
-
-@item privileged
-Same as @code{-p}.
-
-@item verbose
-Same as @code{-v}.
-
-@item vi
-Use a @code{vi}-style line editing interface.
-
-@item xtrace
-Same as @code{-x}.
-@end table
-
-@item -p
-Turn on privileged mode.
-In this mode, the @env{$BASH_ENV} and @env{$ENV} files are not
-processed, shell functions are not inherited from the environment,
-and the @env{SHELLOPTS} variable, if it appears in the environment,
-is ignored.
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the @code{-p} option is not supplied, these actions
-are taken and the effective user id is set to the real user id.
-If the @code{-p} option is supplied at startup, the effective user id is
-not reset.
-Turning this option off causes the effective user
-and group ids to be set to the real user and group ids.
-
-@item -t
-Exit after reading and executing one command.
-
-@item -u
-Treat unset variables as an error when performing parameter expansion.
-An error message will be written to the standard error, and a non-interactive
-shell will exit.
-
-@item -v
-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
-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
-the command and its expanded arguments.
-
-@item -B
-The shell will perform brace expansion (@pxref{Brace Expansion}).
-This option is on by default.
-
-@item -C
-Prevent output redirection using @samp{>}, @samp{>&}, and @samp{<>}
-from overwriting existing files.
-
-@item -E
-If set, any trap on @code{ERR} is inherited by shell functions, command
-substitutions, and commands executed in a subshell environment.
-The @code{ERR} trap is normally not inherited in such cases.
-
-@item -H
-Enable @samp{!} style history substitution (@pxref{History Interaction}).
-This option is on by default for interactive shells.
-
-@item -P
-If set, do not follow symbolic links when performing commands such as
-@code{cd} which change the current directory. The physical directory
-is used instead. By default, Bash follows
-the logical chain of directories when performing commands
-which change the current directory.
-
-For example, if @file{/usr/sys} is a symbolic link to @file{/usr/local/sys}
-then:
-@example
-$ cd /usr/sys; echo $PWD
-/usr/sys
-$ cd ..; pwd
-/usr
-@end example
-
-@noindent
-If @code{set -P} is on, then:
-@example
-$ cd /usr/sys; echo $PWD
-/usr/local/sys
-$ cd ..; pwd
-/usr/local
-@end example
-
-@item -T
-If set, any trap on @code{DEBUG} is inherited by shell functions, command
-substitutions, and commands executed in a subshell environment.
-The @code{DEBUG} trap is normally not inherited in such cases.
-
-@item --
-If no arguments follow this option, then the positional parameters are
-unset. Otherwise, the positional parameters are set to the
-@var{arguments}, even if some of them begin with a @samp{-}.
-
-@item -
-Signal the end of options, cause all remaining @var{arguments}
-to be assigned to the positional parameters. The @option{-x}
-and @option{-v} options are turned off.
-If there are no arguments, the positional parameters remain unchanged.
-@end table
-
-Using @samp{+} rather than @samp{-} causes these options to be
-turned off. The options can also be used upon invocation of the
-shell. The current set of options may be found in @code{$-}.
-
-The remaining N @var{arguments} are positional parameters and are
-assigned, in order, to @code{$1}, @code{$2}, @dots{} @code{$N}.
-The special parameter @code{#} is set to N.
-
-The return status is always zero unless an invalid option is supplied.
-@end table
-
-@node Special Builtins
-@section Special Builtins
-@cindex special builtin
-
-For historical reasons, the @sc{posix} 1003.2 standard has classified
-several builtin commands as @emph{special}.
-When Bash is executing in @sc{posix} mode, the special builtins
-differ from other builtin commands in three respects:
-
-@enumerate
-@item
-Special builtins are found before shell functions during command lookup.
-
-@item
-If a special builtin returns an error status, a non-interactive shell exits.
-
-@item
-Assignment statements preceding the command stay in effect in the shell
-environment after the command completes.
-@end enumerate
-
-When Bash is not executing in @sc{posix} mode, these builtins behave no
-differently than the rest of the Bash builtin commands.
-The Bash @sc{posix} mode is described in @ref{Bash POSIX Mode}.
-
-These are the @sc{posix} special builtins:
-@example
-@w{break : . continue eval exec exit export readonly return set}
-@w{shift trap unset}
-@end example
-
-@node Shell Variables
-@chapter Shell Variables
-
-@menu
-* Bourne Shell Variables:: Variables which Bash uses in the same way
- as the Bourne Shell.
-* Bash Variables:: List of variables that exist in Bash.
-@end menu
-
-This chapter describes the shell variables that Bash uses.
-Bash automatically assigns default values to a number of variables.
-
-@node Bourne Shell Variables
-@section Bourne Shell Variables
-
-Bash uses certain shell variables in the same way as the Bourne shell.
-In some cases, Bash assigns a default value to the variable.
-
-@vtable @code
-
-@item CDPATH
-A colon-separated list of directories used as a search path for
-the @code{cd} builtin command.
-
-@item HOME
-The current user's home directory; the default for the @code{cd} builtin
-command.
-The value of this variable is also used by tilde expansion
-(@pxref{Tilde Expansion}).
-
-@item IFS
-A list of characters that separate fields; used when the shell splits
-words as part of expansion.
-
-@item MAIL
-If this parameter is set to a filename and the @env{MAILPATH} variable
-is not set, Bash informs the user of the arrival of mail in
-the specified file.
-
-@item MAILPATH
-A colon-separated list of filenames which the shell periodically checks
-for new mail.
-Each list entry can specify the message that is printed when new mail
-arrives in the mail file by separating the file name from the message with
-a @samp{?}.
-When used in the text of the message, @code{$_} expands to the name of
-the current mail file.
-
-@item OPTARG
-The value of the last option argument processed by the @code{getopts} builtin.
-
-@item OPTIND
-The index of the last option argument processed by the @code{getopts} builtin.
-
-@item PATH
-A colon-separated list of directories in which the shell looks for
-commands.
-A zero-length (null) directory name in the value of @code{PATH} indicates the
-current directory.
-A null directory name may appear as two adjacent colons, or as an initial
-or trailing colon.
-
-
-@item PS1
-The primary prompt string. The default value is @samp{\s-\v\$ }.
-@xref{Printing a Prompt}, for the complete list of escape
-sequences that are expanded before @env{PS1} is displayed.
-
-@item PS2
-The secondary prompt string. The default value is @samp{> }.
-
-@end vtable
-
-@node Bash Variables
-@section Bash Variables
-
-These variables are set or used by Bash, but other shells
-do not normally treat them specially.
-
-A few variables used by Bash are described in different chapters:
-variables for controlling the job control facilities
-(@pxref{Job Control Variables}).
-
-@vtable @code
-
-@item BASH
-The full pathname used to execute the current instance of Bash.
-
-@item BASH_ARGC
-An array variable whose values are the number of parameters in each
-frame of the current bash execution call stack. The number of
-parameters to the current subroutine (shell function or script executed
-with @code{.} or @code{source}) is at the top of the stack. When a
-subroutine is executed, the number of parameters passed is pushed onto
-@code{BASH_ARGC}.
-
-@item BASH_ARGV
-An array variable containing all of the parameters in the current bash
-execution call stack. The final parameter of the last subroutine call
-is at the top of the stack; the first parameter of the initial call is
-at the bottom. When a subroutine is executed, the parameters supplied
-are pushed onto @code{BASH_ARGV}.
-
-@item BASH_COMMAND
-The command currently being executed or about to be executed, unless the
-shell is executing a command as the result of a trap,
-in which case it is the command executing at the time of the trap.
-
-@item BASH_ENV
-If this variable is set when Bash is invoked to execute a shell
-script, its value is expanded and used as the name of a startup file
-to read before executing the script. @xref{Bash Startup Files}.
-
-@item BASH_EXECUTION_STRING
-The command argument to the @option{-c} invocation option.
-
-@item BASH_LINENO
-An array variable whose members are the line numbers in source files
-corresponding to each member of @var{FUNCNAME}.
-@code{$@{BASH_LINENO[$i]@}} is the line number in the source file where
-@code{$@{FUNCNAME[$i + 1]@}} was called.
-The corresponding source file name is @code{$@{BASH_SOURCE[$i + 1]@}}.
-Use @code{LINENO} to obtain the current line number.
-
-@item BASH_SOURCE
-An array variable whose members are the source filenames corresponding
-to the elements in the @code{FUNCNAME} array variable.
-
-@item BASH_SUBSHELL
-Incremented by one each time a subshell or subshell environment is spawned.
-The initial value is 0.
-
-@item BASH_VERSINFO
-A readonly array variable (@pxref{Arrays})
-whose members hold version information for this instance of Bash.
-The values assigned to the array members are as follows:
-
-@table @code
-
-@item BASH_VERSINFO[0]
-The major version number (the @var{release}).
-
-@item BASH_VERSINFO[1]
-The minor version number (the @var{version}).
-
-@item BASH_VERSINFO[2]
-The patch level.
-
-@item BASH_VERSINFO[3]
-The build version.
-
-@item BASH_VERSINFO[4]
-The release status (e.g., @var{beta1}).
-
-@item BASH_VERSINFO[5]
-The value of @env{MACHTYPE}.
-
-@end table
-
-@item BASH_VERSION
-The version number of the current instance of Bash.
-
-@item COLUMNS
-Used by the @code{select} builtin command to determine the terminal width
-when printing selection lists. Automatically set upon receipt of a
-@code{SIGWINCH}.
-
-@item COMP_CWORD
-An index into @env{$@{COMP_WORDS@}} of the word containing the current
-cursor position.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_LINE
-The current command line.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_POINT
-The index of the current cursor position relative to the beginning of
-the current command.
-If the current cursor position is at the end of the current command,
-the value of this variable is equal to @code{$@{#COMP_LINE@}}.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_WORDBREAKS
-The set of characters that the Readline library treats as word
-separators when performing word completion.
-If @code{COMP_WORDBREAKS} is unset, it loses its special properties,
-even if it is subsequently reset.
-
-@item COMP_WORDS
-An array variable consisting of the individual
-words in the current command line.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMPREPLY
-An array variable from which Bash reads the possible completions
-generated by a shell function invoked by the programmable completion
-facility (@pxref{Programmable Completion}).
-
-@item DIRSTACK
-An array variable containing the current contents of the directory stack.
-Directories appear in the stack in the order they are displayed by the
-@code{dirs} builtin.
-Assigning to members of this array variable may be used to modify
-directories already in the stack, but the @code{pushd} and @code{popd}
-builtins must be used to add and remove directories.
-Assignment to this variable will not change the current directory.
-If @env{DIRSTACK} is unset, it loses its special properties, even if
-it is subsequently reset.
-
-@item EMACS
-If Bash finds this variable in the environment when the shell
-starts with value @samp{t}, it assumes that the shell is running in an
-emacs shell buffer and disables line editing.
-
-@item EUID
-The numeric effective user id of the current user. This variable
-is readonly.
-
-@item FCEDIT
-The editor used as a default by the @option{-e} option to the @code{fc}
-builtin command.
-
-@item FIGNORE
-A colon-separated list of suffixes to ignore when performing
-filename completion.
-A file name whose suffix matches one of the entries in
-@env{FIGNORE}
-is excluded from the list of matched file names. A sample
-value is @samp{.o:~}
-
-@item FUNCNAME
-An array variable containing the names of all shell functions
-currently in the execution call stack.
-The element with index 0 is the name of any currently-executing
-shell function.
-The bottom-most element is "main".
-This variable exists only when a shell function is executing.
-Assignments to @env{FUNCNAME} have no effect and return an error status.
-If @env{FUNCNAME} is unset, it loses its special properties, even if
-it is subsequently reset.
-
-@item GLOBIGNORE
-A colon-separated list of patterns defining the set of filenames to
-be ignored by filename expansion.
-If a filename matched by a filename expansion pattern also matches one
-of the patterns in @env{GLOBIGNORE}, it is removed from the list
-of matches.
-
-@item GROUPS
-An array variable containing the list of groups of which the current
-user is a member.
-Assignments to @env{GROUPS} have no effect and return an error status.
-If @env{GROUPS} is unset, it loses its special properties, even if it is
-subsequently reset.
-
-@item histchars
-Up to three characters which control history expansion, quick
-substitution, and tokenization (@pxref{History Interaction}).
-The first character is the
-@var{history expansion} character, that is, the character which signifies the
-start of a history expansion, normally @samp{!}. The second character is the
-character which signifies `quick substitution' when seen as the first
-character on a line, normally @samp{^}. The optional third character is the
-character which indicates that the remainder of the line is a comment when
-found as the first character of a word, usually @samp{#}. The history
-comment character causes history substitution to be skipped for the
-remaining words on the line. It does not necessarily cause the shell
-parser to treat the rest of the line as a comment.
-
-@item HISTCMD
-The history number, or index in the history list, of the current
-command. If @env{HISTCMD} is unset, it loses its special properties,
-even if it is subsequently reset.
-
-@item HISTCONTROL
-A colon-separated list of values controlling how commands are saved on
-the history list.
-If the list of values includes @samp{ignorespace}, lines which begin
-with a space character are not saved in the history list.
-A value of @samp{ignoredups} causes lines which match the previous
-history entry to not be saved.
-A value of @samp{ignoreboth} is shorthand for
-@samp{ignorespace} and @samp{ignoredups}.
-A value of @samp{erasedups} causes all previous lines matching the
-current line to be removed from the history list before that line
-is saved.
-Any value not in the above list is ignored.
-If @env{HISTCONTROL} is unset, or does not include a valid value,
-all lines read by the shell parser are saved on the history list,
-subject to the value of @env{HISTIGNORE}.
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-@env{HISTCONTROL}.
-
-@item HISTFILE
-The name of the file to which the command history is saved. The
-default value is @file{~/.bash_history}.
-
-@item HISTFILESIZE
-The maximum number of lines contained in the history file. When this
-variable is assigned a value, the history file is truncated, if
-necessary, to contain no more than that number of lines.
-The history file is also truncated to this size after
-writing it when an interactive shell exits.
-The default value is 500.
-
-@item HISTIGNORE
-A colon-separated list of patterns used to decide which command
-lines should be saved on the history list. Each pattern is
-anchored at the beginning of the line and must match the complete
-line (no implicit @samp{*} is appended). Each pattern is tested
-against the line after the checks specified by @env{HISTCONTROL}
-are applied. In addition to the normal shell pattern matching
-characters, @samp{&} matches the previous history line. @samp{&}
-may be escaped using a backslash; the backslash is removed
-before attempting a match.
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-@env{HISTIGNORE}.
-
-@env{HISTIGNORE} subsumes the function of @env{HISTCONTROL}. A
-pattern of @samp{&} is identical to @code{ignoredups}, and a
-pattern of @samp{[ ]*} is identical to @code{ignorespace}.
-Combining these two patterns, separating them with a colon,
-provides the functionality of @code{ignoreboth}.
-
-@item HISTSIZE
-The maximum number of commands to remember on the history list.
-The default value is 500.
-
-@item HOSTFILE
-Contains the name of a file in the same format as @file{/etc/hosts} that
-should be read when the shell needs to complete a hostname.
-The list of possible hostname completions may be changed while the shell
-is running;
-the next time hostname completion is attempted after the
-value is changed, Bash adds the contents of the new file to the
-existing list.
-If @env{HOSTFILE} is set, but has no value, Bash attempts to read
-@file{/etc/hosts} to obtain the list of possible hostname completions.
-When @env{HOSTFILE} is unset, the hostname list is cleared.
-
-@item HOSTNAME
-The name of the current host.
-
-@item HOSTTYPE
-A string describing the machine Bash is running on.
-
-@item IGNOREEOF
-Controls the action of the shell on receipt of an @code{EOF} character
-as the sole input. If set, the value denotes the number
-of consecutive @code{EOF} characters that can be read as the
-first character on an input line
-before the shell will exit. If the variable exists but does not
-have a numeric value (or has no value) then the default is 10.
-If the variable does not exist, then @code{EOF} signifies the end of
-input to the shell. This is only in effect for interactive shells.
-
-@item INPUTRC
-The name of the Readline initialization file, overriding the default
-of @file{~/.inputrc}.
-
-@item LANG
-Used to determine the locale category for any category not specifically
-selected with a variable starting with @code{LC_}.
-
-@item LC_ALL
-This variable overrides the value of @env{LANG} and any other
-@code{LC_} variable specifying a locale category.
-
-@item LC_COLLATE
-This variable determines the collation order used when sorting the
-results of filename expansion, and
-determines the behavior of range expressions, equivalence classes,
-and collating sequences within filename expansion and pattern matching
-(@pxref{Filename Expansion}).
-
-@item LC_CTYPE
-This variable determines the interpretation of characters and the
-behavior of character classes within filename expansion and pattern
-matching (@pxref{Filename Expansion}).
-
-@item LC_MESSAGES
-This variable determines the locale used to translate double-quoted
-strings preceded by a @samp{$} (@pxref{Locale Translation}).
-
-@item LC_NUMERIC
-This variable determines the locale category used for number formatting.
-
-@item LINENO
-The line number in the script or shell function currently executing.
-
-@item LINES
-Used by the @code{select} builtin command to determine the column length
-for printing selection lists. Automatically set upon receipt of a
-@code{SIGWINCH}.
-
-@item MACHTYPE
-A string that fully describes the system type on which Bash
-is executing, in the standard @sc{gnu} @var{cpu-company-system} format.
-
-@item MAILCHECK
-How often (in seconds) that the shell should check for mail in the
-files specified in the @env{MAILPATH} or @env{MAIL} variables.
-The default is 60 seconds. When it is time to check
-for mail, the shell does so before displaying the primary prompt.
-If this variable is unset, or set to a value that is not a number
-greater than or equal to zero, the shell disables mail checking.
-
-@item OLDPWD
-The previous working directory as set by the @code{cd} builtin.
-
-@item OPTERR
-If set to the value 1, Bash displays error messages
-generated by the @code{getopts} builtin command.
-
-@item OSTYPE
-A string describing the operating system Bash is running on.
-
-@item PIPESTATUS
-An array variable (@pxref{Arrays})
-containing a list of exit status values from the processes
-in the most-recently-executed foreground pipeline (which may
-contain only a single command).
-
-@item POSIXLY_CORRECT
-If this variable is in the environment when @code{bash} starts, the shell
-enters @sc{posix} mode (@pxref{Bash POSIX Mode}) before reading the
-startup files, as if the @option{--posix} invocation option had been supplied.
-If it is set while the shell is running, @code{bash} enables @sc{posix} mode,
-as if the command
-@example
-@code{set -o posix}
-@end example
-@noindent
-had been executed.
-
-@item PPID
-The process @sc{id} of the shell's parent process. This variable
-is readonly.
-
-@item PROMPT_COMMAND
-If set, the value is interpreted as a command to execute
-before the printing of each primary prompt (@env{$PS1}).
-
-@item PS3
-The value of this variable is used as the prompt for the
-@code{select} command. If this variable is not set, the
-@code{select} command prompts with @samp{#? }
-
-@item PS4
-The value is the prompt printed before the command line is echoed
-when the @option{-x} option is set (@pxref{The Set Builtin}).
-The first character of @env{PS4} is replicated multiple times, as
-necessary, to indicate multiple levels of indirection.
-The default is @samp{+ }.
-
-@item PWD
-The current working directory as set by the @code{cd} builtin.
-
-@item RANDOM
-Each time this parameter is referenced, a random integer
-between 0 and 32767 is generated. Assigning a value to this
-variable seeds the random number generator.
-
-@item REPLY
-The default variable for the @code{read} builtin.
-
-@item SECONDS
-This variable expands to the number of seconds since the
-shell was started. Assignment to this variable resets
-the count to the value assigned, and the expanded value
-becomes the value assigned plus the number of seconds
-since the assignment.
-
-@item SHELLOPTS
-A colon-separated list of enabled shell options. Each word in
-the list is a valid argument for the @option{-o} option to the
-@code{set} builtin command (@pxref{The Set Builtin}).
-The options appearing in @env{SHELLOPTS} are those reported
-as @samp{on} by @samp{set -o}.
-If this variable is in the environment when Bash
-starts up, each shell option in the list will be enabled before
-reading any startup files. This variable is readonly.
-
-@item SHLVL
-Incremented by one each time a new instance of Bash is started. This is
-intended to be a count of how deeply your Bash shells are nested.
-
-@item TIMEFORMAT
-The value of this parameter is used as a format string specifying
-how the timing information for pipelines prefixed with the @code{time}
-reserved word should be displayed.
-The @samp{%} character introduces an
-escape sequence that is expanded to a time value or other
-information.
-The escape sequences and their meanings are as
-follows; the braces denote optional portions.
-
-@table @code
-
-@item %%
-A literal @samp{%}.
-
-@item %[@var{p}][l]R
-The elapsed time in seconds.
-
-@item %[@var{p}][l]U
-The number of CPU seconds spent in user mode.
-
-@item %[@var{p}][l]S
-The number of CPU seconds spent in system mode.
-
-@item %P
-The CPU percentage, computed as (%U + %S) / %R.
-@end table
-
-The optional @var{p} is a digit specifying the precision, the number of
-fractional digits after a decimal point.
-A value of 0 causes no decimal point or fraction to be output.
-At most three places after the decimal point may be specified; values
-of @var{p} greater than 3 are changed to 3.
-If @var{p} is not specified, the value 3 is used.
-
-The optional @code{l} specifies a longer format, including minutes, of
-the form @var{MM}m@var{SS}.@var{FF}s.
-The value of @var{p} determines whether or not the fraction is included.
-
-If this variable is not set, Bash acts as if it had the value
-@example
-@code{$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'}
-@end example
-If the value is null, no timing information is displayed.
-A trailing newline is added when the format string is displayed.
-
-@item TMOUT
-If set to a value greater than zero, @code{TMOUT} is treated as the
-default timeout for the @code{read} builtin (@pxref{Bash Builtins}).
-The @code{select} command (@pxref{Conditional Constructs}) terminates
-if input does not arrive after @code{TMOUT} seconds when input is coming
-from a terminal.
-
-In an interative shell, the value is interpreted as
-the number of seconds to wait for input after issuing the primary
-prompt when the shell is interactive.
-Bash terminates after that number of seconds if input does
-not arrive.
-
-@item UID
-The numeric real user id of the current user. This variable is readonly.
-
-@end vtable
-
-@node Bash Features
-@chapter Bash Features
-
-This section describes features unique to Bash.
-
-@menu
-* Invoking Bash:: Command line options that you can give
- to Bash.
-* Bash Startup Files:: When and how Bash executes scripts.
-* Interactive Shells:: What an interactive shell is.
-* Bash Conditional Expressions:: Primitives used in composing expressions for
- the @code{test} builtin.
-* Shell Arithmetic:: Arithmetic on shell variables.
-* Aliases:: Substituting one command for another.
-* Arrays:: Array Variables.
-* The Directory Stack:: History of visited directories.
-* Printing a Prompt:: Controlling the PS1 string.
-* The Restricted Shell:: A more controlled mode of shell execution.
-* Bash POSIX Mode:: Making Bash behave more closely to what
- the POSIX standard specifies.
-@end menu
-
-@node Invoking Bash
-@section Invoking Bash
-
-@example
-bash [long-opt] [-ir] [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] [@var{argument} @dots{}]
-bash [long-opt] [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] -c @var{string} [@var{argument} @dots{}]
-bash [long-opt] -s [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] [@var{argument} @dots{}]
-@end example
-
-In addition to the single-character shell command-line options
-(@pxref{The Set Builtin}), there are several multi-character
-options that you can use. These options must appear on the command
-line before the single-character options to be recognized.
-
-@table @code
-@item --debugger
-Arrange for the debugger profile to be executed before the shell
-starts. Turns on extended debugging mode (see @ref{Bash Builtins}
-for a description of the @code{extdebug} option to the @code{shopt}
-builtin) and shell function tracing
-(see @ref{The Set Builtin} for a description of the @code{-o functrace}
-option).
-
-@item --dump-po-strings
-A list of all double-quoted strings preceded by @samp{$}
-is printed on the standard ouput
-in the @sc{gnu} @code{gettext} PO (portable object) file format.
-Equivalent to @option{-D} except for the output format.
-
-@item --dump-strings
-Equivalent to @option{-D}.
-
-@item --help
-Display a usage message on standard output and exit sucessfully.
-
-@item --init-file @var{filename}
-@itemx --rcfile @var{filename}
-Execute commands from @var{filename} (instead of @file{~/.bashrc})
-in an interactive shell.
-
-@item --login
-Equivalent to @option{-l}.
-
-@item --noediting
-Do not use the @sc{gnu} Readline library (@pxref{Command Line Editing})
-to read command lines when the shell is interactive.
-
-@item --noprofile
-Don't load the system-wide startup file @file{/etc/profile}
-or any of the personal initialization files
-@file{~/.bash_profile}, @file{~/.bash_login}, or @file{~/.profile}
-when Bash is invoked as a login shell.
-
-@item --norc
-Don't read the @file{~/.bashrc} initialization file in an
-interactive shell. This is on by default if the shell is
-invoked as @code{sh}.
-
-@item --posix
-Change the behavior of Bash where the default operation differs
-from the @sc{posix} 1003.2 standard to match the standard. This
-is intended to make Bash behave as a strict superset of that
-standard. @xref{Bash POSIX Mode}, for a description of the Bash
-@sc{posix} mode.
-
-@item --restricted
-Make the shell a restricted shell (@pxref{The Restricted Shell}).
-
-@item --verbose
-Equivalent to @option{-v}. Print shell input lines as they're read.
-
-@item --version
-Show version information for this instance of
-Bash on the standard output and exit successfully.
-
-@end table
-
-There are several single-character options that may be supplied at
-invocation which are not available with the @code{set} builtin.
-
-@table @code
-@item -c @var{string}
-Read and execute commands from @var{string} after processing the
-options, then exit. Any remaining arguments are assigned to the
-positional parameters, starting with @code{$0}.
-
-@item -i
-Force the shell to run interactively. Interactive shells are
-described in @ref{Interactive Shells}.
-
-@item -l
-Make this shell act as if it had been directly invoked by login.
-When the shell is interactive, this is equivalent to starting a
-login shell with @samp{exec -l bash}.
-When the shell is not interactive, the login shell startup files will
-be executed.
-@samp{exec bash -l} or @samp{exec bash --login}
-will replace the current shell with a Bash login shell.
-@xref{Bash Startup Files}, for a description of the special behavior
-of a login shell.
-
-@item -r
-Make the shell a restricted shell (@pxref{The Restricted Shell}).
-
-@item -s
-If this option is present, or if no arguments remain after option
-processing, then commands are read from the standard input.
-This option allows the positional parameters to be set
-when invoking an interactive shell.
-
-@item -D
-A list of all double-quoted strings preceded by @samp{$}
-is printed on the standard ouput.
-These are the strings that
-are subject to language translation when the current locale
-is not @code{C} or @code{POSIX} (@pxref{Locale Translation}).
-This implies the @option{-n} option; no commands will be executed.
-
-@item [-+]O [@var{shopt_option}]
-@var{shopt_option} is one of the shell options accepted by the
-@code{shopt} builtin (@pxref{Shell Builtin Commands}).
-If @var{shopt_option} is present, @option{-O} sets the value of that option;
-@option{+O} unsets it.
-If @var{shopt_option} is not supplied, the names and values of the shell
-options accepted by @code{shopt} are printed on the standard output.
-If the invocation option is @option{+O}, the output is displayed in a format
-that may be reused as input.
-
-@item --
-A @code{--} signals the end of options and disables further option
-processing.
-Any arguments after the @code{--} are treated as filenames and arguments.
-
-@end table
-
-@cindex login shell
-A @emph{login} shell is one whose first character of argument zero is
-@samp{-}, or one invoked with the @option{--login} option.
-
-@cindex interactive shell
-An @emph{interactive} shell is one started without non-option arguments,
-unless @option{-s} is specified,
-without specifying the @option{-c} option, and whose input and output are both
-connected to terminals (as determined by @code{isatty(3)}), or one
-started with the @option{-i} option. @xref{Interactive Shells}, for more
-information.
-
-If arguments remain after option processing, and neither the
-@option{-c} nor the @option{-s}
-option has been supplied, the first argument is assumed to
-be the name of a file containing shell commands (@pxref{Shell Scripts}).
-When Bash is invoked in this fashion, @code{$0}
-is set to the name of the file, and the positional parameters
-are set to the remaining arguments.
-Bash reads and executes commands from this file, then exits.
-Bash's exit status is the exit status of the last command executed
-in the script. If no commands are executed, the exit status is 0.
-
-@node Bash Startup Files
-@section Bash Startup Files
-@cindex startup files
-
-This section describs how Bash executes its startup files.
-If any of the files exist but cannot be read, Bash reports an error.
-Tildes are expanded in file names as described above under
-Tilde Expansion (@pxref{Tilde Expansion}).
-
-Interactive shells are described in @ref{Interactive Shells}.
-
-@subsubheading Invoked as an interactive login shell, or with @option{--login}
-
-When Bash is invoked as an interactive login shell, or as a
-non-interactive shell with the @option{--login} option, it first reads and
-executes commands from the file @file{/etc/profile}, if that file exists.
-After reading that file, it looks for @file{~/.bash_profile},
-@file{~/.bash_login}, and @file{~/.profile}, in that order, and reads
-and executes commands from the first one that exists and is readable.
-The @option{--noprofile} option may be used when the shell is started to
-inhibit this behavior.
-
-When a login shell exits, Bash reads and executes commands from
-the file @file{~/.bash_logout}, if it exists.
-
-@subsubheading Invoked as an interactive non-login shell
-
-When an interactive shell that is not a login shell is started, Bash
-reads and executes commands from @file{~/.bashrc}, if that file exists.
-This may be inhibited by using the @option{--norc} option.
-The @option{--rcfile @var{file}} option will force Bash to read and
-execute commands from @var{file} instead of @file{~/.bashrc}.
-
-So, typically, your @file{~/.bash_profile} contains the line
-@example
-@code{if [ -f ~/.bashrc ]; then . ~/.bashrc; fi}
-@end example
-@noindent
-after (or before) any login-specific initializations.
-
-@subsubheading Invoked non-interactively
-
-When Bash is started non-interactively, to run a shell script,
-for example, it looks for the variable @env{BASH_ENV} in the environment,
-expands its value if it appears there, and uses the expanded value as
-the name of a file to read and execute. Bash behaves as if the
-following command were executed:
-@example
-@code{if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi}
-@end example
-@noindent
-but the value of the @env{PATH} variable is not used to search for the
-file name.
-
-As noted above, if a non-interactive shell is invoked with the
-@option{--login} option, Bash attempts to read and execute commands from the
-login shell startup files.
-
-@subsubheading Invoked with name @code{sh}
-
-If Bash is invoked with the name @code{sh}, it tries to mimic the
-startup behavior of historical versions of @code{sh} as closely as
-possible, while conforming to the @sc{posix} standard as well.
-
-When invoked as an interactive login shell, or as a non-interactive
-shell with the @option{--login} option, it first attempts to read
-and execute commands from @file{/etc/profile} and @file{~/.profile}, in
-that order.
-The @option{--noprofile} option may be used to inhibit this behavior.
-When invoked as an interactive shell with the name @code{sh}, Bash
-looks for the variable @env{ENV}, expands its value if it is defined,
-and uses the expanded value as the name of a file to read and execute.
-Since a shell invoked as @code{sh} does not attempt to read and execute
-commands from any other startup files, the @option{--rcfile} option has
-no effect.
-A non-interactive shell invoked with the name @code{sh} does not attempt
-to read any other startup files.
-
-When invoked as @code{sh}, Bash enters @sc{posix} mode after
-the startup files are read.
-
-@subsubheading Invoked in @sc{posix} mode
-
-When Bash is started in @sc{posix} mode, as with the
-@option{--posix} command line option, it follows the @sc{posix} standard
-for startup files.
-In this mode, interactive shells expand the @env{ENV} variable
-and commands are read and executed from the file whose name is the
-expanded value.
-No other startup files are read.
-
-@subsubheading Invoked by remote shell daemon
-
-Bash attempts to determine when it is being run by the remote shell
-daemon, usually @code{rshd}. If Bash determines it is being run by
-rshd, it reads and executes commands from @file{~/.bashrc}, if that
-file exists and is readable.
-It will not do this if invoked as @code{sh}.
-The @option{--norc} option may be used to inhibit this behavior, and the
-@option{--rcfile} option may be used to force another file to be read, but
-@code{rshd} does not generally invoke the shell with those options or
-allow them to be specified.
-
-@subsubheading Invoked with unequal effective and real @sc{uid/gid}s
-
-If Bash is started with the effective user (group) id not equal to the
-real user (group) id, and the @code{-p} option is not supplied, no startup
-files are read, shell functions are not inherited from the environment,
-the @env{SHELLOPTS} variable, if it appears in the environment, is ignored,
-and the effective user id is set to the real user id.
-If the @code{-p} option is supplied at invocation, the startup behavior is
-the same, but the effective user id is not reset.
-
-@node Interactive Shells
-@section Interactive Shells
-@cindex interactive shell
-@cindex shell, interactive
-
-@menu
-* What is an Interactive Shell?:: What determines whether a shell is Interactive.
-* Is this Shell Interactive?:: How to tell if a shell is interactive.
-* Interactive Shell Behavior:: What changes in a interactive shell?
-@end menu
-
-@node What is an Interactive Shell?
-@subsection What is an Interactive Shell?
-
-An interactive shell
-is one started without non-option arguments, unless @option{-s} is
-specified, without specifiying the @option{-c} option, and
-whose input and output are both
-connected to terminals (as determined by @code{isatty(3)}),
-or one started with the @option{-i} option.
-
-An interactive shell generally reads from and writes to a user's
-terminal.
-
-The @option{-s} invocation option may be used to set the positional parameters
-when an interactive shell is started.
-
-@node Is this Shell Interactive?
-@subsection Is this Shell Interactive?
-
-To determine within a startup script whether or not Bash is
-running interactively,
-test the value of the @samp{-} special parameter.
-It contains @code{i} when the shell is interactive. For example:
-
-@example
-case "$-" in
-*i*) echo This shell is interactive ;;
-*) echo This shell is not interactive ;;
-esac
-@end example
-
-Alternatively, startup scripts may examine the variable
-@env{PS1}; it is unset in non-interactive shells, and set in
-interactive shells. Thus:
-
-@example
-if [ -z "$PS1" ]; then
- echo This shell is not interactive
-else
- echo This shell is interactive
-fi
-@end example
-
-@node Interactive Shell Behavior
-@subsection Interactive Shell Behavior
-
-When the shell is running interactively, it changes its behavior in
-several ways.
-
-@enumerate
-@item
-Startup files are read and executed as described in @ref{Bash Startup Files}.
-
-@item
-Job Control (@pxref{Job Control}) is enabled by default. When job
-control is in effect, Bash ignores the keyboard-generated job control
-signals @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-@item
-Bash expands and displays @env{PS1} before reading the first line
-of a command, and expands and displays @env{PS2} before reading the
-second and subsequent lines of a multi-line command.
-
-@item
-Bash executes the value of the @env{PROMPT_COMMAND} variable as a command
-before printing the primary prompt, @env{$PS1}
-(@pxref{Bash Variables}).
-
-@item
-Readline (@pxref{Command Line Editing}) is used to read commands from
-the user's terminal.
-
-@item
-Bash inspects the value of the @code{ignoreeof} option to @code{set -o}
-instead of exiting immediately when it receives an @code{EOF} on its
-standard input when reading a command (@pxref{The Set Builtin}).
-
-@item
-Command history (@pxref{Bash History Facilities})
-and history expansion (@pxref{History Interaction})
-are enabled by default.
-Bash will save the command history to the file named by @env{$HISTFILE}
-when an interactive shell exits.
-
-@item
-Alias expansion (@pxref{Aliases}) is performed by default.
-
-@item
-In the absence of any traps, Bash ignores @code{SIGTERM}
-(@pxref{Signals}).
-
-@item
-In the absence of any traps, @code{SIGINT} is caught and handled
-((@pxref{Signals}).
-@code{SIGINT} will interrupt some shell builtins.
-
-@item
-An interactive login shell sends a @code{SIGHUP} to all jobs on exit
-if the @code{hupoxexit} shell option has been enabled (@pxref{Signals}).
-
-@item
-The @option{-n} invocation option is ignored, and @samp{set -n} has
-no effect (@pxref{The Set Builtin}).
-
-@item
-Bash will check for mail periodically, depending on the values of the
-@env{MAIL}, @env{MAILPATH}, and @env{MAILCHECK} shell variables
-(@pxref{Bash Variables}).
-
-@item
-Expansion errors due to references to unbound shell variables after
-@samp{set -u} has been enabled will not cause the shell to exit
-(@pxref{The Set Builtin}).
-
-@item
-The shell will not exit on expansion errors caused by @var{var} being unset
-or null in @code{$@{@var{var}:?@var{word}@}} expansions
-(@pxref{Shell Parameter Expansion}).
-
-@item
-Redirection errors encountered by shell builtins will not cause the
-shell to exit.
-
-@item
-When running in @sc{posix} mode, a special builtin returning an error
-status will not cause the shell to exit (@pxref{Bash POSIX Mode}).
-@item
-A failed @code{exec} will not cause the shell to exit
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Parser syntax errors will not cause the shell to exit.
-
-@item
-Simple spelling correction for directory arguments to the @code{cd}
-builtin is enabled by default (see the description of the @code{cdspell}
-option to the @code{shopt} builtin in @ref{Bash Builtins}).
-
-@item
-The shell will check the value of the @env{TMOUT} variable and exit
-if a command is not read within the specified number of seconds after
-printing @env{$PS1} (@pxref{Bash Variables}).
-
-@end enumerate
-
-@node Bash Conditional Expressions
-@section Bash Conditional Expressions
-@cindex expressions, conditional
-
-Conditional expressions are used by the @code{[[} compound command
-and the @code{test} and @code{[} builtin commands.
-
-Expressions may be unary or binary.
-Unary expressions are often used to examine the status of a file.
-There are string operators and numeric comparison operators as well.
-If the @var{file} argument to one of the primaries is of the form
-@file{/dev/fd/@var{N}}, then file descriptor @var{N} is checked.
-If the @var{file} argument to one of the primaries is one of
-@file{/dev/stdin}, @file{/dev/stdout}, or @file{/dev/stderr}, file
-descriptor 0, 1, or 2, respectively, is checked.
-
-@table @code
-@item -a @var{file}
-True if @var{file} exists.
-
-@item -b @var{file}
-True if @var{file} exists and is a block special file.
-
-@item -c @var{file}
-True if @var{file} exists and is a character special file.
-
-@item -d @var{file}
-True if @var{file} exists and is a directory.
-
-@item -e @var{file}
-True if @var{file} exists.
-
-@item -f @var{file}
-True if @var{file} exists and is a regular file.
-
-@item -g @var{file}
-True if @var{file} exists and its set-group-id bit is set.
-
-@item -h @var{file}
-True if @var{file} exists and is a symbolic link.
-
-@item -k @var{file}
-True if @var{file} exists and its "sticky" bit is set.
-
-@item -p @var{file}
-True if @var{file} exists and is a named pipe (FIFO).
-
-@item -r @var{file}
-True if @var{file} exists and is readable.
-
-@item -s @var{file}
-True if @var{file} exists and has a size greater than zero.
-
-@item -t @var{fd}
-True if file descriptor @var{fd} is open and refers to a terminal.
-
-@item -u @var{file}
-True if @var{file} exists and its set-user-id bit is set.
-
-@item -w @var{file}
-True if @var{file} exists and is writable.
-
-@item -x @var{file}
-True if @var{file} exists and is executable.
-
-@item -O @var{file}
-True if @var{file} exists and is owned by the effective user id.
-
-@item -G @var{file}
-True if @var{file} exists and is owned by the effective group id.
-
-@item -L @var{file}
-True if @var{file} exists and is a symbolic link.
-
-@item -S @var{file}
-True if @var{file} exists and is a socket.
-
-@item -N @var{file}
-True if @var{file} exists and has been modified since it was last read.
-
-@item @var{file1} -nt @var{file2}
-True if @var{file1} is newer (according to modification date)
-than @var{file2}, or if @var{file1} exists and @var{file2} does not.
-
-@item @var{file1} -ot @var{file2}
-True if @var{file1} is older than @var{file2},
-or if @var{file2} exists and @var{file1} does not.
-
-@item @var{file1} -ef @var{file2}
-True if @var{file1} and @var{file2} refer to the same device and
-inode numbers.
-
-@item -o @var{optname}
-True if shell option @var{optname} is enabled.
-The list of options appears in the description of the @option{-o}
-option to the @code{set} builtin (@pxref{The Set Builtin}).
-
-@item -z @var{string}
-True if the length of @var{string} is zero.
-
-@item -n @var{string}
-@itemx @var{string}
-True if the length of @var{string} is non-zero.
-
-@item @var{string1} == @var{string2}
-True if the strings are equal.
-@samp{=} may be used in place of @samp{==} for strict @sc{posix} compliance.
-
-@item @var{string1} != @var{string2}
-True if the strings are not equal.
-
-@item @var{string1} < @var{string2}
-True if @var{string1} sorts before @var{string2} lexicographically
-in the current locale.
-
-@item @var{string1} > @var{string2}
-True if @var{string1} sorts after @var{string2} lexicographically
-in the current locale.
-
-@item @var{arg1} OP @var{arg2}
-@code{OP} is one of
-@samp{-eq}, @samp{-ne}, @samp{-lt}, @samp{-le}, @samp{-gt}, or @samp{-ge}.
-These arithmetic binary operators return true if @var{arg1}
-is equal to, not equal to, less than, less than or equal to,
-greater than, or greater than or equal to @var{arg2},
-respectively. @var{Arg1} and @var{arg2}
-may be positive or negative integers.
-
-@end table
-
-@node Shell Arithmetic
-@section Shell Arithmetic
-@cindex arithmetic, shell
-@cindex shell arithmetic
-@cindex expressions, arithmetic
-@cindex evaluation, arithmetic
-@cindex arithmetic evaluation
-
-The shell allows arithmetic expressions to be evaluated, as one of
-the shell expansions or by the @code{let} and the @option{-i} option
-to the @code{declare} builtins.
-
-Evaluation is done in fixed-width integers with no check for overflow,
-though division by 0 is trapped and flagged as an error.
-The operators and their precedence, associativity, and values
-are the same as in the C language.
-The following list of operators is grouped into levels of
-equal-precedence operators.
-The levels are listed in order of decreasing precedence.
-
-@table @code
-
-@item @var{id}++ @var{id}--
-variable post-increment and post-decrement
-
-@item ++@var{id} --@var{id}
-variable pre-increment and pre-decrement
-
-@item - +
-unary minus and plus
-
-@item ! ~
-logical and bitwise negation
-
-@item **
-exponentiation
-
-@item * / %
-multiplication, division, remainder
-
-@item + -
-addition, subtraction
-
-@item << >>
-left and right bitwise shifts
-
-@item <= >= < >
-comparison
-
-@item == !=
-equality and inequality
-
-@item &
-bitwise AND
-
-@item ^
-bitwise exclusive OR
-
-@item |
-bitwise OR
-
-@item &&
-logical AND
-
-@item ||
-logical OR
-
-@item expr ? expr : expr
-conditional operator
-
-@item = *= /= %= += -= <<= >>= &= ^= |=
-assignment
-
-@item expr1 , expr2
-comma
-@end table
-
-Shell variables are allowed as operands; parameter expansion is
-performed before the expression is evaluated.
-Within an expression, shell variables may also be referenced by name
-without using the parameter expansion syntax.
-A shell variable that is null or unset evaluates to 0 when referenced
-by name without using the parameter expansion syntax.
-The value of a variable is evaluated as an arithmetic expression
-when it is referenced, or when a variable which has been given the
-@var{integer} attribute using @samp{declare -i} is assigned a value.
-A null value evaluates to 0.
-A shell variable need not have its integer attribute turned on
-to be used in an expression.
-
-Constants with a leading 0 are interpreted as octal numbers.
-A leading @samp{0x} or @samp{0X} denotes hexadecimal. Otherwise,
-numbers take the form [@var{base}@code{#}]@var{n}, where @var{base}
-is a decimal number between 2 and 64 representing the arithmetic
-base, and @var{n} is a number in that base. If @var{base}@code{#} is
-omitted, then base 10 is used.
-The digits greater than 9 are represented by the lowercase letters,
-the uppercase letters, @samp{@@}, and @samp{_}, in that order.
-If @var{base} is less than or equal to 36, lowercase and uppercase
-letters may be used interchangably to represent numbers between 10
-and 35.
-
-Operators are evaluated in order of precedence. Sub-expressions in
-parentheses are evaluated first and may override the precedence
-rules above.
-
-@node Aliases
-@section Aliases
-@cindex alias expansion
-
-@var{Aliases} allow a string to be substituted for a word when it is used
-as the first word of a simple command.
-The shell maintains a list of aliases that may be set and unset with
-the @code{alias} and @code{unalias} builtin commands.
-
-The first word of each simple command, if unquoted, is checked to see
-if it has an alias.
-If so, that word is replaced by the text of the alias.
-The alias name and the replacement text may contain any valid
-shell input, including shell metacharacters, with the exception
-that the alias name may not contain @samp{=}.
-The first word of the replacement text is tested for
-aliases, but a word that is identical to an alias being expanded
-is not expanded a second time. This means that one may alias
-@code{ls} to @code{"ls -F"},
-for instance, and Bash does not try to recursively expand the
-replacement text. If the last character of the alias value is a
-space or tab character, then the next command word following the
-alias is also checked for alias expansion.
-
-Aliases are created and listed with the @code{alias}
-command, and removed with the @code{unalias} command.
-
-There is no mechanism for using arguments in the replacement text,
-as in @code{csh}.
-If arguments are needed, a shell function should be used
-(@pxref{Shell Functions}).
-
-Aliases are not expanded when the shell is not interactive,
-unless the @code{expand_aliases} shell option is set using
-@code{shopt} (@pxref{Bash Builtins}).
-
-The rules concerning the definition and use of aliases are
-somewhat confusing. Bash
-always reads at least one complete line
-of input before executing any
-of the commands on that line. Aliases are expanded when a
-command is read, not when it is executed. Therefore, an
-alias definition appearing on the same line as another
-command does not take effect until the next line of input is read.
-The commands following the alias definition
-on that line are not affected by the new alias.
-This behavior is also an issue when functions are executed.
-Aliases are expanded when a function definition is read,
-not when the function is executed, because a function definition
-is itself a compound command. As a consequence, aliases
-defined in a function are not available until after that
-function is executed. To be safe, always put
-alias definitions on a separate line, and do not use @code{alias}
-in compound commands.
-
-For almost every purpose, shell functions are preferred over aliases.
-
-@node Arrays
-@section Arrays
-@cindex arrays
-
-Bash provides one-dimensional array variables. Any variable may be used as
-an array; the @code{declare} builtin will explicitly declare an array.
-There is no maximum
-limit on the size of an array, nor any requirement that members
-be indexed or assigned contiguously. Arrays are zero-based.
-
-An array is created automatically if any variable is assigned to using
-the syntax
-@example
-name[@var{subscript}]=@var{value}
-@end example
-
-@noindent
-The @var{subscript}
-is treated as an arithmetic expression that must evaluate to a number
-greater than or equal to zero. To explicitly declare an array, use
-@example
-declare -a @var{name}
-@end example
-@noindent
-The syntax
-@example
-declare -a @var{name}[@var{subscript}]
-@end example
-@noindent
-is also accepted; the @var{subscript} is ignored. Attributes may be
-specified for an array variable using the @code{declare} and
-@code{readonly} builtins. Each attribute applies to all members of
-an array.
-
-Arrays are assigned to using compound assignments of the form
-@example
-name=(value@var{1} @dots{} value@var{n})
-@end example
-@noindent
-where each
-@var{value} is of the form @code{[[@var{subscript}]=]}@var{string}. If
-the optional subscript is supplied, that index is assigned to;
-otherwise the index of the element assigned is the last index assigned
-to by the statement plus one. Indexing starts at zero.
-This syntax is also accepted by the @code{declare}
-builtin. Individual array elements may be assigned to using the
-@code{name[}@var{subscript}@code{]=}@var{value} syntax introduced above.
-
-Any element of an array may be referenced using
-@code{$@{name[}@var{subscript}@code{]@}}.
-The braces are required to avoid
-conflicts with the shell's filename expansion operators. If the
-@var{subscript} is @samp{@@} or @samp{*}, the word expands to all members
-of the array @var{name}. These subscripts differ only when the word
-appears within double quotes. If the word is double-quoted,
-@code{$@{name[*]@}} expands to a single word with
-the value of each array member separated by the first character of the
-@env{IFS} variable, and @code{$@{name[@@]@}} expands each element of
-@var{name} to a separate word. When there are no array members,
-@code{$@{name[@@]@}} expands to nothing. This is analogous to the
-expansion of the special parameters @samp{@@} and @samp{*}.
-@code{$@{#name[}@var{subscript}@code{]@}} expands to the length of
-@code{$@{name[}@var{subscript}@code{]@}}.
-If @var{subscript} is @samp{@@} or
-@samp{*}, the expansion is the number of elements in the array.
-Referencing an array variable without a subscript is equivalent to
-referencing element zero.
-
-The @code{unset} builtin is used to destroy arrays.
-@code{unset} @var{name}[@var{subscript}]
-destroys the array element at index @var{subscript}.
-@code{unset} @var{name}, where @var{name} is an array, removes the
-entire array. A subscript of @samp{*} or @samp{@@} also removes the
-entire array.
-
-The @code{declare}, @code{local}, and @code{readonly}
-builtins each accept a @option{-a}
-option to specify an array. The @code{read}
-builtin accepts a @option{-a}
-option to assign a list of words read from the standard input
-to an array, and can read values from the standard input into
-individual array elements. The @code{set} and @code{declare}
-builtins display array values in a way that allows them to be
-reused as input.
-
-@node The Directory Stack
-@section The Directory Stack
-@cindex directory stack
-
-@menu
-* Directory Stack Builtins:: Bash builtin commands to manipulate
- the directory stack.
-@end menu
-
-The directory stack is a list of recently-visited directories. The
-@code{pushd} builtin adds directories to the stack as it changes
-the current directory, and the @code{popd} builtin removes specified
-directories from the stack and changes the current directory to
-the directory removed. The @code{dirs} builtin displays the contents
-of the directory stack.
-
-The contents of the directory stack are also visible
-as the value of the @env{DIRSTACK} shell variable.
-
-@node Directory Stack Builtins
-@subsection Directory Stack Builtins
-
-@table @code
-
-@item dirs
-@btindex dirs
-@example
-dirs [+@var{N} | -@var{N}] [-clpv]
-@end example
-Display the list of currently remembered directories. Directories
-are added to the list with the @code{pushd} command; the
-@code{popd} command removes directories from the list.
-@table @code
-@item +@var{N}
-Displays the @var{N}th directory (counting from the left of the
-list printed by @code{dirs} when invoked without options), starting
-with zero.
-@item -@var{N}
-Displays the @var{N}th directory (counting from the right of the
-list printed by @code{dirs} when invoked without options), starting
-with zero.
-@item -c
-Clears the directory stack by deleting all of the elements.
-@item -l
-Produces a longer listing; the default listing format uses a
-tilde to denote the home directory.
-@item -p
-Causes @code{dirs} to print the directory stack with one entry per
-line.
-@item -v
-Causes @code{dirs} to print the directory stack with one entry per
-line, prefixing each entry with its index in the stack.
-@end table
-
-@item popd
-@btindex popd
-@example
-popd [+@var{N} | -@var{N}] [-n]
-@end example
-
-Remove the top entry from the directory stack, and @code{cd}
-to the new top directory.
-When no arguments are given, @code{popd}
-removes the top directory from the stack and
-performs a @code{cd} to the new top directory. The
-elements are numbered from 0 starting at the first directory listed with
-@code{dirs}; i.e., @code{popd} is equivalent to @code{popd +0}.
-@table @code
-@item +@var{N}
-Removes the @var{N}th directory (counting from the left of the
-list printed by @code{dirs}), starting with zero.
-@item -@var{N}
-Removes the @var{N}th directory (counting from the right of the
-list printed by @code{dirs}), starting with zero.
-@item -n
-Suppresses the normal change of directory when removing directories
-from the stack, so that only the stack is manipulated.
-@end table
-
-@btindex pushd
-@item pushd
-@example
-pushd [@var{dir} | @var{+N} | @var{-N}] [-n]
-@end example
-
-Save the current directory on the top of the directory stack
-and then @code{cd} to @var{dir}.
-With no arguments, @code{pushd} exchanges the top two directories.
-
-@table @code
-@item +@var{N}
-Brings the @var{N}th directory (counting from the left of the
-list printed by @code{dirs}, starting with zero) to the top of
-the list by rotating the stack.
-@item -@var{N}
-Brings the @var{N}th directory (counting from the right of the
-list printed by @code{dirs}, starting with zero) to the top of
-the list by rotating the stack.
-@item -n
-Suppresses the normal change of directory when adding directories
-to the stack, so that only the stack is manipulated.
-@item @var{dir}
-Makes the current working directory be the top of the stack, and then
-executes the equivalent of `@code{cd} @var{dir}'.
-@code{cd}s to @var{dir}.
-@end table
-
-@end table
-
-@node Printing a Prompt
-@section Controlling the Prompt
-@cindex prompting
-
-The value of the variable @env{PROMPT_COMMAND} is examined just before
-Bash prints each primary prompt. If @env{PROMPT_COMMAND} is set and
-has a non-null value, then the
-value is executed just as if it had been typed on the command line.
-
-In addition, the following table describes the special characters which
-can appear in the prompt variables:
-
-@table @code
-@item \a
-A bell character.
-@item \d
-The date, in "Weekday Month Date" format (e.g., "Tue May 26").
-@item \D@{@var{format}@}
-The @var{format} is passed to @code{strftime}(3) and the result is inserted
-into the prompt string; an empty @var{format} results in a locale-specific
-time representation. The braces are required.
-@item \e
-An escape character.
-@item \h
-The hostname, up to the first `.'.
-@item \H
-The hostname.
-@item \j
-The number of jobs currently managed by the shell.
-@item \l
-The basename of the shell's terminal device name.
-@item \n
-A newline.
-@item \r
-A carriage return.
-@item \s
-The name of the shell, the basename of @code{$0} (the portion
-following the final slash).
-@item \t
-The time, in 24-hour HH:MM:SS format.
-@item \T
-The time, in 12-hour HH:MM:SS format.
-@item \@@
-The time, in 12-hour am/pm format.
-@item \A
-The time, in 24-hour HH:MM format.
-@item \u
-The username of the current user.
-@item \v
-The version of Bash (e.g., 2.00)
-@item \V
-The release of Bash, version + patchlevel (e.g., 2.00.0)
-@item \w
-The current working directory.
-@item \W
-The basename of @env{$PWD}.
-@item \!
-The history number of this command.
-@item \#
-The command number of this command.
-@item \$
-If the effective uid is 0, @code{#}, otherwise @code{$}.
-@item \@var{nnn}
-The character whose ASCII code is the octal value @var{nnn}.
-@item \\
-A backslash.
-@item \[
-Begin a sequence of non-printing characters. This could be used to
-embed a terminal control sequence into the prompt.
-@item \]
-End a sequence of non-printing characters.
-@end table
-
-The command number and the history number are usually different:
-the history number of a command is its position in the history
-list, which may include commands restored from the history file
-(@pxref{Bash History Facilities}), while the command number is
-the position in the sequence of commands executed during the current
-shell session.
-
-After the string is decoded, it is expanded via
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal, subject to the value of the
-@code{promptvars} shell option (@pxref{Bash Builtins}).
-
-@node The Restricted Shell
-@section The Restricted Shell
-@cindex restricted shell
-
-If Bash is started with the name @code{rbash}, or the
-@option{--restricted}
-or
-@option{-r}
-option is supplied at invocation, the shell becomes restricted.
-A restricted shell is used to
-set up an environment more controlled than the standard shell.
-A restricted shell behaves identically to @code{bash}
-with the exception that the following are disallowed or not performed:
-
-@itemize @bullet
-@item
-Changing directories with the @code{cd} builtin.
-@item
-Setting or unsetting the values of the @env{SHELL}, @env{PATH},
-@env{ENV}, or @env{BASH_ENV} variables.
-@item
-Specifying command names containing slashes.
-@item
-Specifying a filename containing a slash as an argument to the @code{.}
-builtin command.
-@item
-Specifying a filename containing a slash as an argument to the @option{-p}
-option to the @code{hash} builtin command.
-@item
-Importing function definitions from the shell environment at startup.
-@item
-Parsing the value of @env{SHELLOPTS} from the shell environment at startup.
-@item
-Redirecting output using the @samp{>}, @samp{>|}, @samp{<>}, @samp{>&},
-@samp{&>}, and @samp{>>} redirection operators.
-@item
-Using the @code{exec} builtin to replace the shell with another command.
-@item
-Adding or deleting builtin commands with the
-@option{-f} and @option{-d} options to the @code{enable} builtin.
-@item
-Using the @code{enable} builtin command to enable disabled shell builtins.
-@item
-Specifying the @option{-p} option to the @code{command} builtin.
-@item
-Turning off restricted mode with @samp{set +r} or @samp{set +o restricted}.
-@end itemize
-
-These restrictions are enforced after any startup files are read.
-
-When a command that is found to be a shell script is executed
-(@pxref{Shell Scripts}), @code{rbash} turns off any restrictions in
-the shell spawned to execute the script.
-
-@node Bash POSIX Mode
-@section Bash POSIX Mode
-@cindex POSIX Mode
-
-Starting Bash with the @option{--posix} command-line option or executing
-@samp{set -o posix} while Bash is running will cause Bash to conform more
-closely to the @sc{posix} 1003.2 standard by changing the behavior to
-match that specified by @sc{posix} in areas where the Bash default differs.
-
-When invoked as @code{sh}, Bash enters @sc{posix} mode after reading the
-startup files.
-
-The following list is what's changed when `@sc{posix} mode' is in effect:
-
-@enumerate
-@item
-When a command in the hash table no longer exists, Bash will re-search
-@env{$PATH} to find the new location. This is also available with
-@samp{shopt -s checkhash}.
-
-@item
-The message printed by the job control code and builtins when a job
-exits with a non-zero status is `Done(status)'.
-
-@item
-The message printed by the job control code and builtins when a job
-is stopped is `Stopped(@var{signame})', where @var{signame} is, for
-example, @code{SIGTSTP}.
-
-@item
-Reserved words may not be aliased.
-
-@item
-The @sc{posix} 1003.2 @env{PS1} and @env{PS2} expansions of @samp{!} to
-the history number and @samp{!!} to @samp{!} are enabled,
-and parameter expansion is performed on the values of @env{PS1} and
-@env{PS2} regardless of the setting of the @code{promptvars} option.
-
-@item
-Interactive comments are enabled by default. (Bash has them on by
-default anyway.)
-
-@item
-The @sc{posix} 1003.2 startup files are executed (@env{$ENV}) rather than
-the normal Bash files.
-
-@item
-Tilde expansion is only performed on assignments preceding a command
-name, rather than on all assignment statements on the line.
-
-@item
-The default history file is @file{~/.sh_history} (this is the
-default value of @env{$HISTFILE}).
-
-@item
-The output of @samp{kill -l} prints all the signal names on a single line,
-separated by spaces.
-
-@item
-Non-interactive shells exit if @var{filename} in @code{.} @var{filename}
-is not found.
-
-@item
-Non-interactive shells exit if a syntax error in an arithmetic expansion
-results in an invalid expression.
-
-@item
-Redirection operators do not perform filename expansion on the word
-in the redirection unless the shell is interactive.
-
-@item
-Redirection operators do not perform word splitting on the word in the
-redirection.
-
-@item
-Function names must be valid shell @code{name}s. That is, they may not
-contain characters other than letters, digits, and underscores, and
-may not start with a digit. Declaring a function with an invalid name
-causes a fatal syntax error in non-interactive shells.
-
-@item
-@sc{posix} 1003.2 `special' builtins are found before shell functions
-during command lookup.
-
-@item
-If a @sc{posix} 1003.2 special builtin returns an error status, a
-non-interactive shell exits. The fatal errors are those listed in
-the POSIX.2 standard, and include things like passing incorrect options,
-redirection errors, variable assignment errors for assignments preceding
-the command name, and so on.
-
-@item
-If the @code{cd} builtin finds a directory to change to
-using @env{$CDPATH}, the
-value it assigns to the @env{PWD} variable does not contain any
-symbolic links, as if @samp{cd -P} had been executed.
-
-@item
-If @env{CDPATH} is set, the @code{cd} builtin will not implicitly
-append the current directory to it. This means that @code{cd} will
-fail if no valid directory name can be constructed from
-any of the entries in @env{$CDPATH}, even if the a directory with
-the same name as the name given as an argument to @code{cd} exists
-in the current directory.
-
-@item
-A non-interactive shell exits with an error status if a variable
-assignment error occurs when no command name follows the assignment
-statements.
-A variable assignment error occurs, for example, when trying to assign
-a value to a readonly variable.
-
-@item
-A non-interactive shell exits with an error status if the iteration
-variable in a @code{for} statement or the selection variable in a
-@code{select} statement is a readonly variable.
-
-@item
-Process substitution is not available.
-
-@item
-Assignment statements preceding @sc{posix} 1003.2 special builtins
-persist in the shell environment after the builtin completes.
-
-@item
-Assignment statements preceding shell function calls persist in the
-shell environment after the function returns, as if a @sc{posix}
-special builtin command had been executed.
-
-@item
-The @code{export} and @code{readonly} builtin commands display their
-output in the format required by @sc{posix} 1003.2.
-
-@item
-The @code{trap} builtin displays signal names without the leading
-@code{SIG}.
-
-@item
-The @code{.} and @code{source} builtins do not search the current directory
-for the filename argument if it is not found by searching @env{PATH}.
-
-@item
-Subshells spawned to execute command substitutions inherit the value of
-the @option{-e} option from the parent shell. When not in @sc{posix} mode,
-Bash clears the @option{-e} option in such subshells.
-
-@item
-Alias expansion is always enabled, even in non-interactive shells.
-
-@item
-When the @code{set} builtin is invoked without options, it does not display
-shell function names and definitions.
-
-@item
-When the @code{set} builtin is invoked without options, it displays
-variable values without quotes, unless they contain shell metacharacters,
-even if the result contains nonprinting characters.
-
-@item
-When the @code{cd} builtin is invoked in @var{logical} mode, and the pathname
-constructed from @code{$PWD} and the directory name supplied as an argument
-does not refer to an existing directory, @code{cd} will fail instead of
-falling back to @var{physical} mode.
-@end enumerate
-
-There is other @sc{posix} 1003.2 behavior that Bash does not implement.
-Specifically:
-
-@enumerate
-@item
-Assignment statements affect the execution environment of all
-builtins, not just special ones.
-
-@item
-When a subshell is created to execute a shell script with execute permission,
-but without a leading @samp{#!}, Bash sets @code{$0} to the full pathname of
-the script as found by searching @code{$PATH}, rather than the command as
-typed by the user.
-
-@item
-When using @samp{.} to source a shell script found in @code{$PATH}, bash
-checks execute permission bits rather than read permission bits, just as
-if it were searching for a command.
-
-@end enumerate
-
-@node Job Control
-@chapter Job Control
-
-This chapter discusses what job control is, how it works, and how
-Bash allows you to access its facilities.
-
-@menu
-* Job Control Basics:: How job control works.
-* Job Control Builtins:: Bash builtin commands used to interact
- with job control.
-* Job Control Variables:: Variables Bash uses to customize job
- control.
-@end menu
-
-@node Job Control Basics
-@section Job Control Basics
-@cindex job control
-@cindex foreground
-@cindex background
-@cindex suspending jobs
-
-Job control
-refers to the ability to selectively stop (suspend)
-the execution of processes and continue (resume)
-their execution at a later point. A user typically employs
-this facility via an interactive interface supplied jointly
-by the system's terminal driver and Bash.
-
-The shell associates a @var{job} with each pipeline. It keeps a
-table of currently executing jobs, which may be listed with the
-@code{jobs} command. When Bash starts a job
-asynchronously, it prints a line that looks
-like:
-@example
-[1] 25647
-@end example
-@noindent
-indicating that this job is job number 1 and that the process @sc{id}
-of the last process in the pipeline associated with this job is
-25647. All of the processes in a single pipeline are members of
-the same job. Bash uses the @var{job} abstraction as the
-basis for job control.
-
-To facilitate the implementation of the user interface to job
-control, the operating system maintains the notion of a current terminal
-process group @sc{id}. Members of this process group (processes whose
-process group @sc{id} is equal to the current terminal process group
-@sc{id}) receive keyboard-generated signals such as @code{SIGINT}.
-These processes are said to be in the foreground. Background
-processes are those whose process group @sc{id} differs from the
-terminal's; such processes are immune to keyboard-generated
-signals. Only foreground processes are allowed to read from or
-write to the terminal. Background processes which attempt to
-read from (write to) the terminal are sent a @code{SIGTTIN}
-(@code{SIGTTOU}) signal by the terminal driver, which, unless
-caught, suspends the process.
-
-If the operating system on which Bash is running supports
-job control, Bash contains facilities to use it. Typing the
-@var{suspend} character (typically @samp{^Z}, Control-Z) while a
-process is running causes that process to be stopped and returns
-control to Bash. Typing the @var{delayed suspend} character
-(typically @samp{^Y}, Control-Y) causes the process to be stopped
-when it attempts to read input from the terminal, and control to
-be returned to Bash. The user then manipulates the state of
-this job, using the @code{bg} command to continue it in the
-background, the @code{fg} command to continue it in the
-foreground, or the @code{kill} command to kill it. A @samp{^Z}
-takes effect immediately, and has the additional side effect of
-causing pending output and typeahead to be discarded.
-
-There are a number of ways to refer to a job in the shell. The
-character @samp{%} introduces a job name.
-
-Job number @code{n} may be referred to as @samp{%n}.
-The symbols @samp{%%} and
-@samp{%+} refer to the shell's notion of the current job, which
-is the last job stopped while it was in the foreground or started
-in the background. The
-previous job may be referenced using @samp{%-}. In output
-pertaining to jobs (e.g., the output of the @code{jobs} command),
-the current job is always flagged with a @samp{+}, and the
-previous job with a @samp{-}.
-
-A job may also be referred to
-using a prefix of the name used to start it, or using a substring
-that appears in its command line. For example, @samp{%ce} refers
-to a stopped @code{ce} job. Using @samp{%?ce}, on the
-other hand, refers to any job containing the string @samp{ce} in
-its command line. If the prefix or substring matches more than one job,
-Bash reports an error.
-
-Simply naming a job can be used to bring it into the foreground:
-@samp{%1} is a synonym for @samp{fg %1}, bringing job 1 from the
-background into the foreground. Similarly, @samp{%1 &} resumes
-job 1 in the background, equivalent to @samp{bg %1}
-
-The shell learns immediately whenever a job changes state.
-Normally, Bash waits until it is about to print a prompt
-before reporting changes in a job's status so as to not interrupt
-any other output.
-If the @option{-b} option to the @code{set} builtin is enabled,
-Bash reports such changes immediately (@pxref{The Set Builtin}).
-Any trap on @code{SIGCHLD} is executed for each child process
-that exits.
-
-If an attempt to exit Bash is while jobs are stopped, the
-shell prints a message warning that there are stopped jobs.
-The @code{jobs} command may then be used to inspect their status.
-If a second attempt to exit is made without an intervening command,
-Bash does not print another warning, and the stopped jobs are terminated.
-
-@node Job Control Builtins
-@section Job Control Builtins
-
-@table @code
-
-@item bg
-@btindex bg
-@example
-bg [@var{jobspec}]
-@end example
-Resume the suspended job @var{jobspec} in the background, as if it
-had been started with @samp{&}.
-If @var{jobspec} is not supplied, the current job is used.
-The return status is zero unless it is run when job control is not
-enabled, or, when run with job control enabled, if @var{jobspec} was
-not found or @var{jobspec} specifies a job that was started without
-job control.
-
-@item fg
-@btindex fg
-@example
-fg [@var{jobspec}]
-@end example
-Resume the job @var{jobspec} in the foreground and make it the current job.
-If @var{jobspec} is not supplied, the current job is used.
-The return status is that of the command placed into the foreground,
-or non-zero if run when job control is disabled or, when run with
-job control enabled, @var{jobspec} does not specify a valid job or
-@var{jobspec} specifies a job that was started without job control.
-
-@item jobs
-@btindex jobs
-@example
-jobs [-lnprs] [@var{jobspec}]
-jobs -x @var{command} [@var{arguments}]
-@end example
-
-The first form lists the active jobs. The options have the
-following meanings:
-
-@table @code
-@item -l
-List process @sc{id}s in addition to the normal information.
-
-@item -n
-Display information only about jobs that have changed status since
-the user was last notified of their status.
-
-@item -p
-List only the process @sc{id} of the job's process group leader.
-
-@item -r
-Restrict output to running jobs.
-
-@item -s
-Restrict output to stopped jobs.
-@end table
-
-If @var{jobspec} is given,
-output is restricted to information about that job.
-If @var{jobspec} is not supplied, the status of all jobs is
-listed.
-
-If the @option{-x} option is supplied, @code{jobs} replaces any
-@var{jobspec} found in @var{command} or @var{arguments} with the
-corresponding process group @sc{id}, and executes @var{command},
-passing it @var{argument}s, returning its exit status.
-
-@item kill
-@btindex kill
-@example
-kill [-s @var{sigspec}] [-n @var{signum}] [-@var{sigspec}] @var{jobspec} or @var{pid}
-kill -l [@var{exit_status}]
-@end example
-Send a signal specified by @var{sigspec} or @var{signum} to the process
-named by job specification @var{jobspec} or process @sc{id} @var{pid}.
-@var{sigspec} is either a signal name such as @code{SIGINT} (with or without
-the @code{SIG} prefix) or a signal number; @var{signum} is a signal number.
-If @var{sigspec} and @var{signum} are not present, @code{SIGTERM} is used.
-The @option{-l} option lists the signal names.
-If any arguments are supplied when @option{-l} is given, the names of the
-signals corresponding to the arguments are listed, and the return status
-is zero.
-@var{exit_status} is a number specifying a signal number or the exit
-status of a process terminated by a signal.
-The return status is zero if at least one signal was successfully sent,
-or non-zero if an error occurs or an invalid option is encountered.
-
-@item wait
-@btindex wait
-@example
-wait [@var{jobspec} or @var{pid}]
-@end example
-Wait until the child process specified by process @sc{id} @var{pid} or job
-specification @var{jobspec} exits and return the exit status of the last
-command waited for.
-If a job spec is given, all processes in the job are waited for.
-If no arguments are given, all currently active child processes are
-waited for, and the return status is zero.
-If neither @var{jobspec} nor @var{pid} specifies an active child process
-of the shell, the return status is 127.
-
-@item disown
-@btindex disown
-@example
-disown [-ar] [-h] [@var{jobspec} @dots{}]
-@end example
-Without options, each @var{jobspec} is removed from the table of
-active jobs.
-If the @option{-h} option is given, the job is not removed from the table,
-but is marked so that @code{SIGHUP} is not sent to the job if the shell
-receives a @code{SIGHUP}.
-If @var{jobspec} is not present, and neither the @option{-a} nor @option{-r}
-option is supplied, the current job is used.
-If no @var{jobspec} is supplied, the @option{-a} option means to remove or
-mark all jobs; the @option{-r} option without a @var{jobspec}
-argument restricts operation to running jobs.
-
-@item suspend
-@btindex suspend
-@example
-suspend [-f]
-@end example
-Suspend the execution of this shell until it receives a
-@code{SIGCONT} signal. The @option{-f} option means to suspend
-even if the shell is a login shell.
-
-@end table
-
-When job control is not active, the @code{kill} and @code{wait}
-builtins do not accept @var{jobspec} arguments. They must be
-supplied process @sc{id}s.
-
-@node Job Control Variables
-@section Job Control Variables
-
-@vtable @code
-
-@item auto_resume
-This variable controls how the shell interacts with the user and
-job control. If this variable exists then single word simple
-commands without redirections are treated as candidates for resumption
-of an existing job. There is no ambiguity allowed; if there is
-more than one job beginning with the string typed, then
-the most recently accessed job will be selected.
-The name of a stopped job, in this context, is the command line
-used to start it. If this variable is set to the value @samp{exact},
-the string supplied must match the name of a stopped job exactly;
-if set to @samp{substring},
-the string supplied needs to match a substring of the name of a
-stopped job. The @samp{substring} value provides functionality
-analogous to the @samp{%?} job @sc{id} (@pxref{Job Control Basics}).
-If set to any other value, the supplied string must
-be a prefix of a stopped job's name; this provides functionality
-analogous to the @samp{%} job @sc{id}.
-
-@end vtable
-
-@set readline-appendix
-@set history-appendix
-@cindex Readline, how to use
-@include rluser.texi
-@cindex History, how to use
-@include hsuser.texi
-@clear readline-appendix
-@clear history-appendix
-
-@node Installing Bash
-@chapter Installing Bash
-
-This chapter provides basic instructions for installing Bash on
-the various supported platforms. The distribution supports the
-@sc{gnu} operating systems, nearly every version of Unix, and several
-non-Unix systems such as BeOS and Interix.
-Other independent ports exist for
-@sc{ms-dos}, @sc{os/2}, Windows @sc{95/98}, and Windows @sc{nt}.
-
-@menu
-* Basic Installation:: Installation instructions.
-
-* Compilers and Options:: How to set special options for various
- systems.
-
-* Compiling For Multiple Architectures:: How to compile Bash for more
- than one kind of system from
- the same source tree.
-
-* Installation Names:: How to set the various paths used by the installation.
-
-* Specifying the System Type:: How to configure Bash for a particular system.
-
-* Sharing Defaults:: How to share default configuration values among GNU
- programs.
-
-* Operation Controls:: Options recognized by the configuration program.
-
-* Optional Features:: How to enable and disable optional features when
- building Bash.
-@end menu
-
-@node Basic Installation
-@section Basic Installation
-@cindex installation
-@cindex configuration
-@cindex Bash installation
-@cindex Bash configuration
-
-These are installation instructions for Bash.
-
-The simplest way to compile Bash is:
-
-@enumerate
-@item
-@code{cd} to the directory containing the source code and type
-@samp{./configure} to configure Bash for your system. If you're
-using @code{csh} on an old version of System V, you might need to
-type @samp{sh ./configure} instead to prevent @code{csh} from trying
-to execute @code{configure} itself.
-
-Running @code{configure} takes some time.
-While running, it prints messages telling which features it is
-checking for.
-
-@item
-Type @samp{make} to compile Bash and build the @code{bashbug} bug
-reporting script.
-
-@item
-Optionally, type @samp{make tests} to run the Bash test suite.
-
-@item
-Type @samp{make install} to install @code{bash} and @code{bashbug}.
-This will also install the manual pages and Info file.
-
-@end enumerate
-
-The @code{configure} shell script attempts to guess correct
-values for various system-dependent variables used during
-compilation. It uses those values to create a @file{Makefile} in
-each directory of the package (the top directory, the
-@file{builtins}, @file{doc}, and @file{support} directories,
-each directory under @file{lib}, and several others). It also creates a
-@file{config.h} file containing system-dependent definitions.
-Finally, it creates a shell script named @code{config.status} that you
-can run in the future to recreate the current configuration, a
-file @file{config.cache} that saves the results of its tests to
-speed up reconfiguring, and a file @file{config.log} containing
-compiler output (useful mainly for debugging @code{configure}).
-If at some point
-@file{config.cache} contains results you don't want to keep, you
-may remove or edit it.
-
-To find out more about the options and arguments that the
-@code{configure} script understands, type
-
-@example
-bash-2.04$ ./configure --help
-@end example
-
-@noindent
-at the Bash prompt in your Bash source directory.
-
-If you need to do unusual things to compile Bash, please
-try to figure out how @code{configure} could check whether or not
-to do them, and mail diffs or instructions to
-@email{bash-maintainers@@gnu.org} so they can be
-considered for the next release.
-
-The file @file{configure.in} is used to create @code{configure}
-by a program called Autoconf. You only need
-@file{configure.in} if you want to change it or regenerate
-@code{configure} using a newer version of Autoconf. If
-you do this, make sure you are using Autoconf version 2.50 or
-newer.
-
-You can remove the program binaries and object files from the
-source code directory by typing @samp{make clean}. To also remove the
-files that @code{configure} created (so you can compile Bash for
-a different kind of computer), type @samp{make distclean}.
-
-@node Compilers and Options
-@section Compilers and Options
-
-Some systems require unusual options for compilation or linking
-that the @code{configure} script does not know about. You can
-give @code{configure} initial values for variables by setting
-them in the environment. Using a Bourne-compatible shell, you
-can do that on the command line like this:
-
-@example
-CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
-@end example
-
-On systems that have the @code{env} program, you can do it like this:
-
-@example
-env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
-@end example
-
-The configuration process uses GCC to build Bash if it
-is available.
-
-@node Compiling For Multiple Architectures
-@section Compiling For Multiple Architectures
-
-You can compile Bash for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you must use a version of @code{make} that
-supports the @code{VPATH} variable, such as GNU @code{make}.
-@code{cd} to the
-directory where you want the object files and executables to go and run
-the @code{configure} script from the source directory. You may need to
-supply the @option{--srcdir=PATH} argument to tell @code{configure} where the
-source files are. @code{configure} automatically checks for the
-source code in the directory that @code{configure} is in and in `..'.
-
-If you have to use a @code{make} that does not supports the @code{VPATH}
-variable, you can compile Bash for one architecture at a
-time in the source code directory. After you have installed
-Bash for one architecture, use @samp{make distclean} before
-reconfiguring for another architecture.
-
-Alternatively, if your system supports symbolic links, you can use the
-@file{support/mkclone} script to create a build tree which has
-symbolic links back to each file in the source directory. Here's an
-example that creates a build directory in the current directory from a
-source directory @file{/usr/gnu/src/bash-2.0}:
-
-@example
-bash /usr/gnu/src/bash-2.0/support/mkclone -s /usr/gnu/src/bash-2.0 .
-@end example
-
-@noindent
-The @code{mkclone} script requires Bash, so you must have already built
-Bash for at least one architecture before you can create build
-directories for other architectures.
-
-@node Installation Names
-@section Installation Names
-
-By default, @samp{make install} will install into
-@file{/usr/local/bin}, @file{/usr/local/man}, etc. You can
-specify an installation prefix other than @file{/usr/local} by
-giving @code{configure} the option @option{--prefix=@var{PATH}},
-or by specifying a value for the @code{DESTDIR} @samp{make}
-variable when running @samp{make install}.
-
-You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.
-If you give @code{configure} the option
-@option{--exec-prefix=@var{PATH}}, @samp{make install} will use
-@var{PATH} as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
-@node Specifying the System Type
-@section Specifying the System Type
-
-There may be some features @code{configure} can not figure out
-automatically, but need to determine by the type of host Bash
-will run on. Usually @code{configure} can figure that
-out, but if it prints a message saying it can not guess the host
-type, give it the @option{--host=TYPE} option. @samp{TYPE} can
-either be a short name for the system type, such as @samp{sun4},
-or a canonical name with three fields: @samp{CPU-COMPANY-SYSTEM}
-(e.g., @samp{i386-unknown-freebsd4.2}).
-
-See the file @file{support/config.sub} for the possible
-values of each field.
-
-@node Sharing Defaults
-@section Sharing Defaults
-
-If you want to set default values for @code{configure} scripts to
-share, you can create a site shell script called
-@code{config.site} that gives default values for variables like
-@code{CC}, @code{cache_file}, and @code{prefix}. @code{configure}
-looks for @file{PREFIX/share/config.site} if it exists, then
-@file{PREFIX/etc/config.site} if it exists. Or, you can set the
-@code{CONFIG_SITE} environment variable to the location of the site
-script. A warning: the Bash @code{configure} looks for a site script,
-but not all @code{configure} scripts do.
-
-@node Operation Controls
-@section Operation Controls
-
-@code{configure} recognizes the following options to control how it
-operates.
-
-@table @code
-
-@item --cache-file=@var{file}
-Use and save the results of the tests in
-@var{file} instead of @file{./config.cache}. Set @var{file} to
-@file{/dev/null} to disable caching, for debugging
-@code{configure}.
-
-@item --help
-Print a summary of the options to @code{configure}, and exit.
-
-@item --quiet
-@itemx --silent
-@itemx -q
-Do not print messages saying which checks are being made.
-
-@item --srcdir=@var{dir}
-Look for the Bash source code in directory @var{dir}. Usually
-@code{configure} can determine that directory automatically.
-
-@item --version
-Print the version of Autoconf used to generate the @code{configure}
-script, and exit.
-@end table
-
-@code{configure} also accepts some other, not widely used, boilerplate
-options. @samp{configure --help} prints the complete list.
-
-@node Optional Features
-@section Optional Features
-
-The Bash @code{configure} has a number of @option{--enable-@var{feature}}
-options, where @var{feature} indicates an optional part of Bash.
-There are also several @option{--with-@var{package}} options,
-where @var{package} is something like @samp{bash-malloc} or @samp{purify}.
-To turn off the default use of a package, use
-@option{--without-@var{package}}. To configure Bash without a feature
-that is enabled by default, use @option{--disable-@var{feature}}.
-
-Here is a complete list of the @option{--enable-} and
-@option{--with-} options that the Bash @code{configure} recognizes.
-
-@table @code
-@item --with-afs
-Define if you are using the Andrew File System from Transarc.
-
-@item --with-bash-malloc
-Use the Bash version of
-@code{malloc} in @file{lib/malloc/malloc.c}. This is not the same
-@code{malloc} that appears in @sc{gnu} libc, but an older version
-derived from the 4.2 @sc{bsd} @code{malloc}. This @code{malloc} is
-very fast, but wastes some space on each allocation.
-This option is enabled by default.
-The @file{NOTES} file contains a list of systems for
-which this should be turned off, and @code{configure} disables this
-option automatically for a number of systems.
-
-@item --with-curses
-Use the curses library instead of the termcap library. This should
-be supplied if your system has an inadequate or incomplete termcap
-database.
-
-@item --with-gnu-malloc
-A synonym for @code{--with-bash-malloc}.
-
-@item --with-installed-readline[=@var{PREFIX}]
-Define this to make Bash link with a locally-installed version of Readline
-rather than the version in @file{lib/readline}. This works only with
-Readline 4.3 and later versions. If @var{PREFIX} is @code{yes} or not
-supplied, @code{configure} uses the values of the make variables
-@code{includedir} and @code{libdir}, which are subdirectories of @code{prefix}
-by default, to find the installed version of Readline if it is not in
-the standard system include and library directories.
-If @var{PREFIX} is @code{no}, Bash links with the version in
-@file{lib/readline}.
-If @var{PREFIX} is set to any other value, @code{configure} treats it as
-a directory pathname and looks for
-the installed version of Readline in subdirectories of that directory
-(include files in @var{PREFIX}/@code{include} and the library in
-@var{PREFIX}/@code{lib}).
-
-@item --with-purify
-Define this to use the Purify memory allocation checker from Rational
-Software.
-
-@item --enable-minimal-config
-This produces a shell with minimal features, close to the historical
-Bourne shell.
-@end table
-
-There are several @option{--enable-} options that alter how Bash is
-compiled and linked, rather than changing run-time features.
-
-@table @code
-@item --enable-largefile
-Enable support for @uref{http://www.sas.com/standards/large_file/x_open.20Mar96.html,
-large files} if the operating system requires special compiler options
-to build programs which can access large files. This is enabled by
-default, if the operating system provides large file support.
-
-@item --enable-profiling
-This builds a Bash binary that produces profiling information to be
-processed by @code{gprof} each time it is executed.
-
-@item --enable-static-link
-This causes Bash to be linked statically, if @code{gcc} is being used.
-This could be used to build a version to use as root's shell.
-@end table
-
-The @samp{minimal-config} option can be used to disable all of
-the following options, but it is processed first, so individual
-options may be enabled using @samp{enable-@var{feature}}.
-
-All of the following options except for @samp{disabled-builtins} and
-@samp{xpg-echo-default} are
-enabled by default, unless the operating system does not provide the
-necessary support.
-
-@table @code
-@item --enable-alias
-Allow alias expansion and include the @code{alias} and @code{unalias}
-builtins (@pxref{Aliases}).
-
-@item --enable-arith-for-command
-Include support for the alternate form of the @code{for} command
-that behaves like the C language @code{for} statement
-(@pxref{Looping Constructs}).
-
-@item --enable-array-variables
-Include support for one-dimensional array shell variables
-(@pxref{Arrays}).
-
-@item --enable-bang-history
-Include support for @code{csh}-like history substitution
-(@pxref{History Interaction}).
-
-@item --enable-brace-expansion
-Include @code{csh}-like brace expansion
-( @code{b@{a,b@}c} @expansion{} @code{bac bbc} ).
-See @ref{Brace Expansion}, for a complete description.
-
-@item --enable-command-timing
-Include support for recognizing @code{time} as a reserved word and for
-displaying timing statistics for the pipeline following @code{time}
-(@pxref{Pipelines}).
-This allows pipelines as well as shell builtins and functions to be timed.
-
-@item --enable-cond-command
-Include support for the @code{[[} conditional command
-(@pxref{Conditional Constructs}).
-
-@item --enable-directory-stack
-Include support for a @code{csh}-like directory stack and the
-@code{pushd}, @code{popd}, and @code{dirs} builtins
-(@pxref{The Directory Stack}).
-
-@item --enable-disabled-builtins
-Allow builtin commands to be invoked via @samp{builtin xxx}
-even after @code{xxx} has been disabled using @samp{enable -n xxx}.
-See @ref{Bash Builtins}, for details of the @code{builtin} and
-@code{enable} builtin commands.
-
-@item --enable-dparen-arithmetic
-Include support for the @code{((@dots{}))} command
-(@pxref{Conditional Constructs}).
-
-@item --enable-extended-glob
-Include support for the extended pattern matching features described
-above under @ref{Pattern Matching}.
-
-@item --enable-help-builtin
-Include the @code{help} builtin, which displays help on shell builtins and
-variables (@pxref{Bash Builtins}).
-
-@item --enable-history
-Include command history and the @code{fc} and @code{history}
-builtin commands (@pxref{Bash History Facilities}).
-
-@item --enable-job-control
-This enables the job control features (@pxref{Job Control}),
-if the operating system supports them.
-
-@item --enable-multibyte
-This enables support for multibyte characters if the operating
-system provides the necessary support.
-
-@item --enable-net-redirections
-This enables the special handling of filenames of the form
-@code{/dev/tcp/@var{host}/@var{port}} and
-@code{/dev/udp/@var{host}/@var{port}}
-when used in redirections (@pxref{Redirections}).
-
-@item --enable-process-substitution
-This enables process substitution (@pxref{Process Substitution}) if
-the operating system provides the necessary support.
-
-@item --enable-prompt-string-decoding
-Turn on the interpretation of a number of backslash-escaped characters
-in the @env{$PS1}, @env{$PS2}, @env{$PS3}, and @env{$PS4} prompt
-strings. See @ref{Printing a Prompt}, for a complete list of prompt
-string escape sequences.
-
-@item --enable-progcomp
-Enable the programmable completion facilities
-(@pxref{Programmable Completion}).
-If Readline is not enabled, this option has no effect.
-
-@item --enable-readline
-Include support for command-line editing and history with the Bash
-version of the Readline library (@pxref{Command Line Editing}).
-
-@item --enable-restricted
-Include support for a @dfn{restricted shell}. If this is enabled, Bash,
-when called as @code{rbash}, enters a restricted mode. See
-@ref{The Restricted Shell}, for a description of restricted mode.
-
-@item --enable-select
-Include the @code{select} builtin, which allows the generation of simple
-menus (@pxref{Conditional Constructs}).
-
-@item --enable-usg-echo-default
-A synonym for @code{--enable-xpg-echo-default}.
-
-@item --enable-xpg-echo-default
-Make the @code{echo} builtin expand backslash-escaped characters by default,
-without requiring the @option{-e} option.
-This sets the default value of the @code{xpg_echo} shell option to @code{on},
-which makes the Bash @code{echo} behave more like the version specified in
-the Single Unix Specification, version 2.
-@xref{Bash Builtins}, for a description of the escape sequences that
-@code{echo} recognizes.
-
-@end table
-
-The file @file{config-top.h} contains C Preprocessor
-@samp{#define} statements for options which are not settable from
-@code{configure}.
-Some of these are not meant to be changed; beware of the consequences if
-you do.
-Read the comments associated with each definition for more
-information about its effect.
-
-@node Reporting Bugs
-@appendix Reporting Bugs
-
-Please report all bugs you find in Bash.
-But first, you should
-make sure that it really is a bug, and that it appears in the latest
-version of Bash.
-The latest version of Bash is always available for FTP from
-@uref{ftp://ftp.gnu.org/pub/bash/}.
-
-Once you have determined that a bug actually exists, use the
-@code{bashbug} command to submit a bug report.
-If you have a fix, you are encouraged to mail that as well!
-Suggestions and `philosophical' bug reports may be mailed
-to @email{bug-bash@@gnu.org} or posted to the Usenet
-newsgroup @code{gnu.bash.bug}.
-
-All bug reports should include:
-@itemize @bullet
-@item
-The version number of Bash.
-@item
-The hardware and operating system.
-@item
-The compiler used to compile Bash.
-@item
-A description of the bug behaviour.
-@item
-A short script or `recipe' which exercises the bug and may be used
-to reproduce it.
-@end itemize
-
-@noindent
-@code{bashbug} inserts the first three items automatically into
-the template it provides for filing a bug report.
-
-Please send all reports concerning this manual to
-@email{chet@@po.CWRU.Edu}.
-
-@node Major Differences From The Bourne Shell
-@appendix Major Differences From The Bourne Shell
-
-Bash implements essentially the same grammar, parameter and
-variable expansion, redirection, and quoting as the Bourne Shell.
-Bash uses the @sc{posix} 1003.2 standard as the specification of
-how these features are to be implemented. There are some
-differences between the traditional Bourne shell and Bash; this
-section quickly details the differences of significance. A
-number of these differences are explained in greater depth in
-previous sections.
-This section uses the version of @code{sh} included in SVR4.2 as
-the baseline reference.
-
-@itemize @bullet
-
-@item
-Bash is @sc{posix}-conformant, even where the @sc{posix} specification
-differs from traditional @code{sh} behavior (@pxref{Bash POSIX Mode}).
-
-@item
-Bash has multi-character invocation options (@pxref{Invoking Bash}).
-
-@item
-Bash has command-line editing (@pxref{Command Line Editing}) and
-the @code{bind} builtin.
-
-@item
-Bash provides a programmable word completion mechanism
-(@pxref{Programmable Completion}), and two builtin commands,
-@code{complete} and @code{compgen}, to manipulate it.
-
-@item
-Bash has command history (@pxref{Bash History Facilities}) and the
-@code{history} and @code{fc} builtins to manipulate it.
-
-@item
-Bash implements @code{csh}-like history expansion
-(@pxref{History Interaction}).
-
-@item
-Bash has one-dimensional array variables (@pxref{Arrays}), and the
-appropriate variable expansions and assignment syntax to use them.
-Several of the Bash builtins take options to act on arrays.
-Bash provides a number of built-in array variables.
-
-@item
-The @code{$'@dots{}'} quoting syntax, which expands ANSI-C
-backslash-escaped characters in the text between the single quotes,
-is supported (@pxref{ANSI-C Quoting}).
-
-@item
-Bash supports the @code{$"@dots{}"} quoting syntax to do
-locale-specific translation of the characters between the double
-quotes. The @option{-D}, @option{--dump-strings}, and @option{--dump-po-strings}
-invocation options list the translatable strings found in a script
-(@pxref{Locale Translation}).
-
-@item
-Bash implements the @code{!} keyword to negate the return value of
-a pipeline (@pxref{Pipelines}).
-Very useful when an @code{if} statement needs to act only if a test fails.
-
-@item
-Bash has the @code{time} reserved word and command timing (@pxref{Pipelines}).
-The display of the timing statistics may be controlled with the
-@env{TIMEFORMAT} variable.
-
-@item
-Bash implements the @code{for (( @var{expr1} ; @var{expr2} ; @var{expr3} ))}
-arithmetic for command, similar to the C language (@pxref{Looping Constructs}).
-
-@item
-Bash includes the @code{select} compound command, which allows the
-generation of simple menus (@pxref{Conditional Constructs}).
-
-@item
-Bash includes the @code{[[} compound command, which makes conditional
-testing part of the shell grammar (@pxref{Conditional Constructs}).
-
-@item
-Bash includes brace expansion (@pxref{Brace Expansion}) and tilde
-expansion (@pxref{Tilde Expansion}).
-
-@item
-Bash implements command aliases and the @code{alias} and @code{unalias}
-builtins (@pxref{Aliases}).
-
-@item
-Bash provides shell arithmetic, the @code{((} compound command
-(@pxref{Conditional Constructs}),
-and arithmetic expansion (@pxref{Shell Arithmetic}).
-
-@item
-Variables present in the shell's initial environment are automatically
-exported to child processes. The Bourne shell does not normally do
-this unless the variables are explicitly marked using the @code{export}
-command.
-
-@item
-Bash includes the @sc{posix} pattern removal @samp{%}, @samp{#}, @samp{%%}
-and @samp{##} expansions to remove leading or trailing substrings from
-variable values (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{#xx@}}, which returns the length of @code{$@{xx@}},
-is supported (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{var:}@var{offset}@code{[:}@var{length}@code{]@}},
-which expands to the substring of @code{var}'s value of length
-@var{length}, beginning at @var{offset}, is present
-(@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion
-@code{$@{var/[/]}@var{pattern}@code{[/}@var{replacement}@code{]@}},
-which matches @var{pattern} and replaces it with @var{replacement} in
-the value of @code{var}, is available (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{!@var{prefix@}*}} expansion, which expands to
-the names of all shell variables whose names begin with @var{prefix},
-is available (@pxref{Shell Parameter Expansion}).
-
-@item
-Bash has @var{indirect} variable expansion using @code{$@{!word@}}
-(@pxref{Shell Parameter Expansion}).
-
-@item
-Bash can expand positional parameters beyond @code{$9} using
-@code{$@{@var{num}@}}.
-
-@item
-The @sc{posix} @code{$()} form of command substitution
-is implemented (@pxref{Command Substitution}),
-and preferred to the Bourne shell's @code{``} (which
-is also implemented for backwards compatibility).
-
-@item
-Bash has process substitution (@pxref{Process Substitution}).
-
-@item
-Bash automatically assigns variables that provide information about the
-current user (@env{UID}, @env{EUID}, and @env{GROUPS}), the current host
-(@env{HOSTTYPE}, @env{OSTYPE}, @env{MACHTYPE}, and @env{HOSTNAME}),
-and the instance of Bash that is running (@env{BASH},
-@env{BASH_VERSION}, and @env{BASH_VERSINFO}). @xref{Bash Variables},
-for details.
-
-@item
-The @env{IFS} variable is used to split only the results of expansion,
-not all words (@pxref{Word Splitting}).
-This closes a longstanding shell security hole.
-
-@item
-Bash implements the full set of @sc{posix} 1003.2 filename expansion operators,
-including @var{character classes}, @var{equivalence classes}, and
-@var{collating symbols} (@pxref{Filename Expansion}).
-
-@item
-Bash implements extended pattern matching features when the @code{extglob}
-shell option is enabled (@pxref{Pattern Matching}).
-
-@item
-It is possible to have a variable and a function with the same name;
-@code{sh} does not separate the two name spaces.
-
-@item
-Bash functions are permitted to have local variables using the
-@code{local} builtin, and thus useful recursive functions may be written
-(@pxref{Bash Builtins}).
-
-@item
-Variable assignments preceding commands affect only that command, even
-builtins and functions (@pxref{Environment}).
-In @code{sh}, all variable assignments
-preceding commands are global unless the command is executed from the
-file system.
-
-@item
-Bash performs filename expansion on filenames specified as operands
-to input and output redirection operators (@pxref{Redirections}).
-
-@item
-Bash contains the @samp{<>} redirection operator, allowing a file to be
-opened for both reading and writing, and the @samp{&>} redirection
-operator, for directing standard output and standard error to the same
-file (@pxref{Redirections}).
-
-@item
-Bash treats a number of filenames specially when they are
-used in redirection operators (@pxref{Redirections}).
-
-@item
-Bash can open network connections to arbitrary machines and services
-with the redirection operators (@pxref{Redirections}).
-
-@item
-The @code{noclobber} option is available to avoid overwriting existing
-files with output redirection (@pxref{The Set Builtin}).
-The @samp{>|} redirection operator may be used to override @code{noclobber}.
-
-@item
-The Bash @code{cd} and @code{pwd} builtins (@pxref{Bourne Shell Builtins})
-each take @option{-L} and @option{-P} options to switch between logical and
-physical modes.
-
-@item
-Bash allows a function to override a builtin with the same name, and provides
-access to that builtin's functionality within the function via the
-@code{builtin} and @code{command} builtins (@pxref{Bash Builtins}).
-
-@item
-The @code{command} builtin allows selective disabling of functions
-when command lookup is performed (@pxref{Bash Builtins}).
-
-@item
-Individual builtins may be enabled or disabled using the @code{enable}
-builtin (@pxref{Bash Builtins}).
-
-@item
-The Bash @code{exec} builtin takes additional options that allow users
-to control the contents of the environment passed to the executed
-command, and what the zeroth argument to the command is to be
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Shell functions may be exported to children via the environment
-using @code{export -f} (@pxref{Shell Functions}).
-
-@item
-The Bash @code{export}, @code{readonly}, and @code{declare} builtins can
-take a @option{-f} option to act on shell functions, a @option{-p} option to
-display variables with various attributes set in a format that can be
-used as shell input, a @option{-n} option to remove various variable
-attributes, and @samp{name=value} arguments to set variable attributes
-and values simultaneously.
-
-@item
-The Bash @code{hash} builtin allows a name to be associated with
-an arbitrary filename, even when that filename cannot be found by
-searching the @env{$PATH}, using @samp{hash -p}
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Bash includes a @code{help} builtin for quick reference to shell
-facilities (@pxref{Bash Builtins}).
-
-@item
-The @code{printf} builtin is available to display formatted output
-(@pxref{Bash Builtins}).
-
-@item
-The Bash @code{read} builtin (@pxref{Bash Builtins})
-will read a line ending in @samp{\} with
-the @option{-r} option, and will use the @env{REPLY} variable as a
-default if no non-option arguments are supplied.
-The Bash @code{read} builtin
-also accepts a prompt string with the @option{-p} option and will use
-Readline to obtain the line when given the @option{-e} option.
-The @code{read} builtin also has additional options to control input:
-the @option{-s} option will turn off echoing of input characters as
-they are read, the @option{-t} option will allow @code{read} to time out
-if input does not arrive within a specified number of seconds, the
-@option{-n} option will allow reading only a specified number of
-characters rather than a full line, and the @option{-d} option will read
-until a particular character rather than newline.
-
-@item
-The @code{return} builtin may be used to abort execution of scripts
-executed with the @code{.} or @code{source} builtins
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Bash includes the @code{shopt} builtin, for finer control of shell
-optional capabilities (@pxref{Bash Builtins}), and allows these options
-to be set and unset at shell invocation (@pxref{Invoking Bash}).
-
-@item
-Bash has much more optional behavior controllable with the @code{set}
-builtin (@pxref{The Set Builtin}).
-
-@item
-The @code{test} builtin (@pxref{Bourne Shell Builtins})
-is slightly different, as it implements the @sc{posix} algorithm,
-which specifies the behavior based on the number of arguments.
-
-@item
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a
-@code{DEBUG} pseudo-signal specification, similar to @code{EXIT}.
-Commands specified with a @code{DEBUG} trap are executed before every
-simple command, @code{for} command, @code{case} command,
-@code{select} command, every arithmetic @code{for} command, and before
-the first command executes in a shell function.
-The @code{DEBUG} trap is not inherited by shell functions unless the
-function has been given the @code{trace} attribute or the
-@code{functrace} option has been enabled using the @code{shopt} builtin.
-The @code{extdebug} shell option has additional effects on the
-@code{DEBUG} trap.
-
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows an
-@code{ERR} pseudo-signal specification, similar to @code{EXIT} and @code{DEBUG}.
-Commands specified with an @code{ERR} trap are executed after a simple
-command fails, with a few exceptions.
-The @code{ERR} trap is not inherited by shell functions unless the
-@code{-o errtrace} option to the @code{set} builtin is enabled.
-
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a
-@code{RETURN} pseudo-signal specification, similar to
-@code{EXIT} and @code{DEBUG}.
-Commands specified with an @code{RETURN} trap are executed before
-execution resumes after a shell function or a shell script executed with
-@code{.} or @code{source} returns.
-The @code{RETURN} trap is not inherited by shell functions.
-
-@item
-The Bash @code{type} builtin is more extensive and gives more information
-about the names it finds (@pxref{Bash Builtins}).
-
-@item
-The Bash @code{umask} builtin permits a @option{-p} option to cause
-the output to be displayed in the form of a @code{umask} command
-that may be reused as input (@pxref{Bourne Shell Builtins}).
-
-@item
-Bash implements a @code{csh}-like directory stack, and provides the
-@code{pushd}, @code{popd}, and @code{dirs} builtins to manipulate it
-(@pxref{The Directory Stack}).
-Bash also makes the directory stack visible as the value of the
-@env{DIRSTACK} shell variable.
-
-@item
-Bash interprets special backslash-escaped characters in the prompt
-strings when interactive (@pxref{Printing a Prompt}).
-
-@item
-The Bash restricted mode is more useful (@pxref{The Restricted Shell});
-the SVR4.2 shell restricted mode is too limited.
-
-@item
-The @code{disown} builtin can remove a job from the internal shell
-job table (@pxref{Job Control Builtins}) or suppress the sending
-of @code{SIGHUP} to a job when the shell exits as the result of a
-@code{SIGHUP}.
-
-@item
-The SVR4.2 shell has two privilege-related builtins
-(@code{mldmode} and @code{priv}) not present in Bash.
-
-@item
-Bash does not have the @code{stop} or @code{newgrp} builtins.
-
-@item
-Bash does not use the @env{SHACCT} variable or perform shell accounting.
-
-@item
-The SVR4.2 @code{sh} uses a @env{TIMEOUT} variable like Bash uses
-@env{TMOUT}.
-
-@end itemize
-
-@noindent
-More features unique to Bash may be found in @ref{Bash Features}.
-
-
-@appendixsec Implementation Differences From The SVR4.2 Shell
-
-Since Bash is a completely new implementation, it does not suffer from
-many of the limitations of the SVR4.2 shell. For instance:
-
-@itemize @bullet
-
-@item
-Bash does not fork a subshell when redirecting into or out of
-a shell control structure such as an @code{if} or @code{while}
-statement.
-
-@item
-Bash does not allow unbalanced quotes. The SVR4.2 shell will silently
-insert a needed closing quote at @code{EOF} under certain circumstances.
-This can be the cause of some hard-to-find errors.
-
-@item
-The SVR4.2 shell uses a baroque memory management scheme based on
-trapping @code{SIGSEGV}. If the shell is started from a process with
-@code{SIGSEGV} blocked (e.g., by using the @code{system()} C library
-function call), it misbehaves badly.
-
-@item
-In a questionable attempt at security, the SVR4.2 shell,
-when invoked without the @option{-p} option, will alter its real
-and effective @sc{uid} and @sc{gid} if they are less than some
-magic threshold value, commonly 100.
-This can lead to unexpected results.
-
-@item
-The SVR4.2 shell does not allow users to trap @code{SIGSEGV},
-@code{SIGALRM}, or @code{SIGCHLD}.
-
-@item
-The SVR4.2 shell does not allow the @env{IFS}, @env{MAILCHECK},
-@env{PATH}, @env{PS1}, or @env{PS2} variables to be unset.
-
-@item
-The SVR4.2 shell treats @samp{^} as the undocumented equivalent of
-@samp{|}.
-
-@item
-Bash allows multiple option arguments when it is invoked (@code{-x -v});
-the SVR4.2 shell allows only one option argument (@code{-xv}). In
-fact, some versions of the shell dump core if the second argument begins
-with a @samp{-}.
-
-@item
-The SVR4.2 shell exits a script if any builtin fails; Bash exits
-a script only if one of the @sc{posix} 1003.2 special builtins fails, and
-only for certain failures, as enumerated in the @sc{posix} 1003.2 standard.
-
-@item
-The SVR4.2 shell behaves differently when invoked as @code{jsh}
-(it turns on job control).
-@end itemize
-
-@node Copying This Manual
-@appendix Copying This Manual
-
-@menu
-* GNU Free Documentation License:: License for copying this manual.
-@end menu
-
-@include fdl.texi
-
-@node Builtin Index
-@unnumbered Index of Shell Builtin Commands
-@printindex bt
-
-@node Reserved Word Index
-@unnumbered Index of Shell Reserved Words
-@printindex rw
-
-@node Variable Index
-@unnumbered Parameter and Variable Index
-@printindex vr
-
-@node Function Index
-@unnumbered Function Index
-@printindex fn
-
-@node Concept Index
-@unnumbered Concept Index
-@printindex cp
-
-@bye
diff --git a/doc/bashref.texi~ b/doc/bashref.texi~
deleted file mode 100644
index b9a0b664..00000000
--- a/doc/bashref.texi~
+++ /dev/null
@@ -1,7423 +0,0 @@
-\input texinfo.tex @c -*- texinfo -*-
-@c %**start of header
-@setfilename bashref.info
-@settitle Bash Reference Manual
-@c %**end of header
-
-@setchapternewpage odd
-
-@include version.texi
-
-@copying
-This text is a brief description of the features that are present in
-the Bash shell (version @value{VERSION}, @value{UPDATED}).
-
-This is Edition @value{EDITION}, last updated @value{UPDATED},
-of @cite{The GNU Bash Reference Manual},
-for @code{Bash}, Version @value{VERSION}.
-
-Copyright @copyright{} 1988-2005 Free Software Foundation, Inc.
-
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
-
-@quotation
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU Free Documentation License, Version 1.2 or
-any later version published by the Free Software Foundation; with no
-Invariant Sections, with the Front-Cover texts being ``A GNU Manual,''
-and with the Back-Cover Texts as in (a) below. A copy of the license is
-included in the section entitled ``GNU Free Documentation License.''
-
-(a) The FSF's Back-Cover Text is: ``You have freedom to copy and modify
-this GNU Manual, like GNU software. Copies published by the Free
-Software Foundation raise funds for GNU development.''
-@end quotation
-@end copying
-
-@defcodeindex bt
-@defcodeindex rw
-@set BashFeatures
-
-@dircategory Basics
-@direntry
-* Bash: (bash). The GNU Bourne-Again SHell.
-@end direntry
-
-@finalout
-
-@titlepage
-@title Bash Reference Manual
-@subtitle Reference Documentation for Bash
-@subtitle Edition @value{EDITION}, for @code{Bash} Version @value{VERSION}.
-@subtitle @value{UPDATED-MONTH}
-@author Chet Ramey, Case Western Reserve University
-@author Brian Fox, Free Software Foundation
-
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-
-@sp 1
-Published by the Free Software Foundation @*
-59 Temple Place, Suite 330, @*
-Boston, MA 02111-1307 @*
-USA @*
-
-@end titlepage
-
-@contents
-
-@ifnottex
-@node Top, Introduction, (dir), (dir)
-@top Bash Features
-
-This text is a brief description of the features that are present in
-the Bash shell (version @value{VERSION}, @value{UPDATED}).
-
-This is Edition @value{EDITION}, last updated @value{UPDATED},
-of @cite{The GNU Bash Reference Manual},
-for @code{Bash}, Version @value{VERSION}.
-
-Bash contains features that appear in other popular shells, and some
-features that only appear in Bash. Some of the shells that Bash has
-borrowed concepts from are the Bourne Shell (@file{sh}), the Korn Shell
-(@file{ksh}), and the C-shell (@file{csh} and its successor,
-@file{tcsh}). The following menu breaks the features up into
-categories based upon which one of these other shells inspired the
-feature.
-
-This manual is meant as a brief introduction to features found in
-Bash. The Bash manual page should be used as the definitive
-reference on shell behavior.
-
-@menu
-* Introduction:: An introduction to the shell.
-* Definitions:: Some definitions used in the rest of this
- manual.
-* Basic Shell Features:: The shell "building blocks".
-* Shell Builtin Commands:: Commands that are a part of the shell.
-* Shell Variables:: Variables used or set by Bash.
-* Bash Features:: Features found only in Bash.
-* Job Control:: What job control is and how Bash allows you
- to use it.
-* Using History Interactively:: Command History Expansion
-* Command Line Editing:: Chapter describing the command line
- editing features.
-* Installing Bash:: How to build and install Bash on your system.
-* Reporting Bugs:: How to report bugs in Bash.
-* Major Differences From The Bourne Shell:: A terse list of the differences
- between Bash and historical
- versions of /bin/sh.
-* Copying This Manual:: Copying this manual.
-* Builtin Index:: Index of Bash builtin commands.
-* Reserved Word Index:: Index of Bash reserved words.
-* Variable Index:: Quick reference helps you find the
- variable you want.
-* Function Index:: Index of bindable Readline functions.
-* Concept Index:: General index for concepts described in
- this manual.
-@end menu
-@end ifnottex
-
-@node Introduction
-@chapter Introduction
-@menu
-* What is Bash?:: A short description of Bash.
-* What is a shell?:: A brief introduction to shells.
-@end menu
-
-@node What is Bash?
-@section What is Bash?
-
-Bash is the shell, or command language interpreter,
-for the @sc{gnu} operating system.
-The name is an acronym for the @samp{Bourne-Again SHell},
-a pun on Stephen Bourne, the author of the direct ancestor of
-the current Unix shell @code{sh},
-which appeared in the Seventh Edition Bell Labs Research version
-of Unix.
-
-Bash is largely compatible with @code{sh} and incorporates useful
-features from the Korn shell @code{ksh} and the C shell @code{csh}.
-It is intended to be a conformant implementation of the @sc{ieee}
-@sc{posix} Shell and Tools portion of the @sc{ieee} @sc{posix}
-specification (@sc{ieee} Standard 1003.1).
-It offers functional improvements over @code{sh} for both interactive and
-programming use.
-
-While the @sc{gnu} operating system provides other shells, including
-a version of @code{csh}, Bash is the default shell.
-Like other @sc{gnu} software, Bash is quite portable. It currently runs
-on nearly every version of Unix and a few other operating systems @minus{}
-independently-supported ports exist for @sc{ms-dos}, @sc{os/2},
-and Windows platforms.
-
-@node What is a shell?
-@section What is a shell?
-
-At its base, a shell is simply a macro processor that executes
-commands. The term macro processor means functionality where text
-and symbols are expanded to create larger expressions.
-
-A Unix shell is both a command interpreter and a programming
-language. As a command interpreter, the shell provides the user
-interface to the rich set of @sc{gnu} utilities. The programming
-language features allow these utilitites to be combined.
-Files containing commands can be created, and become
-commands themselves. These new commands have the same status as
-system commands in directories such as @file{/bin}, allowing users
-or groups to establish custom environments to automate their common
-tasks.
-
-Shells may be used interactively or non-interactively. In
-interactive mode, they accept input typed from the keyboard.
-When executing non-interactively, shells execute commands read
-from a file.
-
-A shell allows execution of @sc{gnu} commands, both synchronously and
-asynchronously.
-The shell waits for synchronous commands to complete before accepting
-more input; asynchronous commands continue to execute in parallel
-with the shell while it reads and executes additional commands.
-The @dfn{redirection} constructs permit
-fine-grained control of the input and output of those commands.
-Moreover, the shell allows control over the contents of commands'
-environments.
-
-Shells also provide a small set of built-in
-commands (@dfn{builtins}) implementing functionality impossible
-or inconvenient to obtain via separate utilities.
-For example, @code{cd}, @code{break}, @code{continue}, and
-@code{exec}) cannot be implemented outside of the shell because
-they directly manipulate the shell itself.
-The @code{history}, @code{getopts}, @code{kill}, or @code{pwd}
-builtins, among others, could be implemented in separate utilities,
-but they are more convenient to use as builtin commands.
-All of the shell builtins are described in
-subsequent sections.
-
-While executing commands is essential, most of the power (and
-complexity) of shells is due to their embedded programming
-languages. Like any high-level language, the shell provides
-variables, flow control constructs, quoting, and functions.
-
-Shells offer features geared specifically for
-interactive use rather than to augment the programming language.
-These interactive features include job control, command line
-editing, command history and aliases. Each of these features is
-described in this manual.
-
-@node Definitions
-@chapter Definitions
-These definitions are used throughout the remainder of this manual.
-
-@table @code
-
-@item POSIX
-@cindex POSIX
-A family of open system standards based on Unix. Bash
-is primarily concerned with the Shell and Utilities portion of the
-@sc{posix} 1003.1 standard.
-
-@item blank
-A space or tab character.
-
-@item builtin
-@cindex builtin
-A command that is implemented internally by the shell itself, rather
-than by an executable program somewhere in the file system.
-
-@item control operator
-@cindex control operator
-A @code{word} that performs a control function. It is a @code{newline}
-or one of the following:
-@samp{||}, @samp{&&}, @samp{&}, @samp{;}, @samp{;;},
-@samp{|}, @samp{(}, or @samp{)}.
-
-@item exit status
-@cindex exit status
-The value returned by a command to its caller. The value is restricted
-to eight bits, so the maximum value is 255.
-
-@item field
-@cindex field
-A unit of text that is the result of one of the shell expansions. After
-expansion, when executing a command, the resulting fields are used as
-the command name and arguments.
-
-@item filename
-@cindex filename
-A string of characters used to identify a file.
-
-@item job
-@cindex job
-A set of processes comprising a pipeline, and any processes descended
-from it, that are all in the same process group.
-
-@item job control
-@cindex job control
-A mechanism by which users can selectively stop (suspend) and restart
-(resume) execution of processes.
-
-@item metacharacter
-@cindex metacharacter
-A character that, when unquoted, separates words. A metacharacter is
-a @code{blank} or one of the following characters:
-@samp{|}, @samp{&}, @samp{;}, @samp{(}, @samp{)}, @samp{<}, or
-@samp{>}.
-
-@item name
-@cindex name
-@cindex identifier
-A @code{word} consisting solely of letters, numbers, and underscores,
-and beginning with a letter or underscore. @code{Name}s are used as
-shell variable and function names.
-Also referred to as an @code{identifier}.
-
-@item operator
-@cindex operator, shell
-A @code{control operator} or a @code{redirection operator}.
-@xref{Redirections}, for a list of redirection operators.
-
-@item process group
-@cindex process group
-A collection of related processes each having the same process
-group @sc{id}.
-
-@item process group ID
-@cindex process group ID
-A unique identifer that represents a @code{process group}
-during its lifetime.
-
-@item reserved word
-@cindex reserved word
-A @code{word} that has a special meaning to the shell. Most reserved
-words introduce shell flow control constructs, such as @code{for} and
-@code{while}.
-
-@item return status
-@cindex return status
-A synonym for @code{exit status}.
-
-@item signal
-@cindex signal
-A mechanism by which a process may be notified by the kernel
-of an event occurring in the system.
-
-@item special builtin
-@cindex special builtin
-A shell builtin command that has been classified as special by the
-@sc{posix} standard.
-
-@item token
-@cindex token
-A sequence of characters considered a single unit by the shell. It is
-either a @code{word} or an @code{operator}.
-
-@item word
-@cindex word
-A @code{token} that is not an @code{operator}.
-@end table
-
-@node Basic Shell Features
-@chapter Basic Shell Features
-@cindex Bourne shell
-
-Bash is an acronym for @samp{Bourne-Again SHell}.
-The Bourne shell is
-the traditional Unix shell originally written by Stephen Bourne.
-All of the Bourne shell builtin commands are available in Bash,
-The rules for evaluation and quoting are taken from the @sc{posix}
-specification for the `standard' Unix shell.
-
-This chapter briefly summarizes the shell's `building blocks':
-commands, control structures, shell functions, shell @i{parameters},
-shell expansions,
-@i{redirections}, which are a way to direct input and output from
-and to named files, and how the shell executes commands.
-
-@menu
-* Shell Syntax:: What your input means to the shell.
-* Shell Commands:: The types of commands you can use.
-* Shell Functions:: Grouping commands by name.
-* Shell Parameters:: How the shell stores values.
-* Shell Expansions:: How Bash expands parameters and the various
- expansions available.
-* Redirections:: A way to control where input and output go.
-* Executing Commands:: What happens when you run a command.
-* Shell Scripts:: Executing files of shell commands.
-@end menu
-
-@node Shell Syntax
-@section Shell Syntax
-@menu
-* Shell Operation:: The basic operation of the shell.
-* Quoting:: How to remove the special meaning from characters.
-* Comments:: How to specify comments.
-@end menu
-
-When the shell reads input, it proceeds through a
-sequence of operations. If the input indicates the beginning of a
-comment, the shell ignores the comment symbol (@samp{#}), and the rest
-of that line.
-
-Otherwise, roughly speaking, the shell reads its input and
-divides the input into words and operators, employing the quoting rules
-to select which meanings to assign various words and characters.
-
-The shell then parses these tokens into commands and other constructs,
-removes the special meaning of certain words or characters, expands
-others, redirects input and output as needed, executes the specified
-command, waits for the command's exit status, and makes that exit status
-available for further inspection or processing.
-
-@node Shell Operation
-@subsection Shell Operation
-
-The following is a brief description of the shell's operation when it
-reads and executes a command. Basically, the shell does the
-following:
-
-@enumerate
-@item
-Reads its input from a file (@pxref{Shell Scripts}), from a string
-supplied as an argument to the @option{-c} invocation option
-(@pxref{Invoking Bash}), or from the user's terminal.
-
-@item
-Breaks the input into words and operators, obeying the quoting rules
-described in @ref{Quoting}. These tokens are separated by
-@code{metacharacters}. Alias expansion is performed by this step
-(@pxref{Aliases}).
-
-@item
-Parses the tokens into simple and compound commands
-(@pxref{Shell Commands}).
-
-@item
-Performs the various shell expansions (@pxref{Shell Expansions}), breaking
-the expanded tokens into lists of filenames (@pxref{Filename Expansion})
-and commands and arguments.
-
-@item
-Performs any necessary redirections (@pxref{Redirections}) and removes
-the redirection operators and their operands from the argument list.
-
-@item
-Executes the command (@pxref{Executing Commands}).
-
-@item
-Optionally waits for the command to complete and collects its exit
-status (@pxref{Exit Status}).
-
-@end enumerate
-
-@node Quoting
-@subsection Quoting
-@cindex quoting
-@menu
-* Escape Character:: How to remove the special meaning from a single
- character.
-* Single Quotes:: How to inhibit all interpretation of a sequence
- of characters.
-* Double Quotes:: How to suppress most of the interpretation of a
- sequence of characters.
-* ANSI-C Quoting:: How to expand ANSI-C sequences in quoted strings.
-* Locale Translation:: How to translate strings into different languages.
-@end menu
-
-Quoting is used to remove the special meaning of certain
-characters or words to the shell. Quoting can be used to
-disable special treatment for special characters, to prevent
-reserved words from being recognized as such, and to prevent
-parameter expansion.
-
-Each of the shell metacharacters (@pxref{Definitions})
-has special meaning to the shell and must be quoted if it is to
-represent itself.
-When the command history expansion facilities are being used
-(@pxref{History Interaction}), the
-@var{history expansion} character, usually @samp{!}, must be quoted
-to prevent history expansion. @xref{Bash History Facilities}, for
-more details concerning history expansion.
-
-There are three quoting mechanisms: the
-@var{escape character}, single quotes, and double quotes.
-
-@node Escape Character
-@subsubsection Escape Character
-A non-quoted backslash @samp{\} is the Bash escape character.
-It preserves the literal value of the next character that follows,
-with the exception of @code{newline}. If a @code{\newline} pair
-appears, and the backslash itself is not quoted, the @code{\newline}
-is treated as a line continuation (that is, it is removed from
-the input stream and effectively ignored).
-
-@node Single Quotes
-@subsubsection Single Quotes
-
-Enclosing characters in single quotes (@samp{'}) preserves the literal value
-of each character within the quotes. A single quote may not occur
-between single quotes, even when preceded by a backslash.
-
-@node Double Quotes
-@subsubsection Double Quotes
-
-Enclosing characters in double quotes (@samp{"}) preserves the literal value
-of all characters within the quotes, with the exception of
-@samp{$}, @samp{`}, @samp{\},
-and, when history expansion is enabled, @samp{!}.
-The characters @samp{$} and @samp{`}
-retain their special meaning within double quotes (@pxref{Shell Expansions}).
-The backslash retains its special meaning only when followed by one of
-the following characters:
-@samp{$}, @samp{`}, @samp{"}, @samp{\}, or @code{newline}.
-Within double quotes, backslashes that are followed by one of these
-characters are removed. Backslashes preceding characters without a
-special meaning are left unmodified.
-A double quote may be quoted within double quotes by preceding it with
-a backslash.
-If enabled, history expansion will be performed unless an @samp{!}
-appearing in double quotes is escaped using a backslash.
-The backslash preceding the @samp{!} is not removed.
-
-The special parameters @samp{*} and @samp{@@} have special meaning
-when in double quotes (@pxref{Shell Parameter Expansion}).
-
-@node ANSI-C Quoting
-@subsubsection ANSI-C Quoting
-@cindex quoting, ANSI
-
-Words of the form @code{$'@var{string}'} are treated specially. The
-word expands to @var{string}, with backslash-escaped characters replaced
-as specified by the ANSI C standard. Backslash escape sequences, if
-present, are decoded as follows:
-
-@table @code
-@item \a
-alert (bell)
-@item \b
-backspace
-@item \e
-an escape character (not ANSI C)
-@item \f
-form feed
-@item \n
-newline
-@item \r
-carriage return
-@item \t
-horizontal tab
-@item \v
-vertical tab
-@item \\
-backslash
-@item \'
-single quote
-@item \@var{nnn}
-the eight-bit character whose value is the octal value @var{nnn}
-(one to three digits)
-@item \x@var{HH}
-the eight-bit character whose value is the hexadecimal value @var{HH}
-(one or two hex digits)
-@item \c@var{x}
-a control-@var{x} character
-@end table
-
-@noindent
-The expanded result is single-quoted, as if the dollar sign had not
-been present.
-
-@node Locale Translation
-@subsubsection Locale-Specific Translation
-@cindex localization
-@cindex internationalization
-@cindex native languages
-@cindex translation, native languages
-
-A double-quoted string preceded by a dollar sign (@samp{$}) will cause
-the string to be translated according to the current locale.
-If the current locale is @code{C} or @code{POSIX}, the dollar sign
-is ignored.
-If the string is translated and replaced, the replacement is
-double-quoted.
-
-@vindex LC_MESSAGES
-@vindex TEXTDOMAIN
-@vindex TEXTDOMAINDIR
-Some systems use the message catalog selected by the @env{LC_MESSAGES}
-shell variable. Others create the name of the message catalog from the
-value of the @env{TEXTDOMAIN} shell variable, possibly adding a
-suffix of @samp{.mo}. If you use the @env{TEXTDOMAIN} variable, you
-may need to set the @env{TEXTDOMAINDIR} variable to the location of
-the message catalog files. Still others use both variables in this
-fashion:
-@env{TEXTDOMAINDIR}/@env{LC_MESSAGES}/LC_MESSAGES/@env{TEXTDOMAIN}.mo.
-
-@node Comments
-@subsection Comments
-@cindex comments, shell
-
-In a non-interactive shell, or an interactive shell in which the
-@code{interactive_comments} option to the @code{shopt}
-builtin is enabled (@pxref{Bash Builtins}),
-a word beginning with @samp{#}
-causes that word and all remaining characters on that line to
-be ignored. An interactive shell without the @code{interactive_comments}
-option enabled does not allow comments. The @code{interactive_comments}
-option is on by default in interactive shells.
-@xref{Interactive Shells}, for a description of what makes
-a shell interactive.
-
-@node Shell Commands
-@section Shell Commands
-@cindex commands, shell
-
-A simple shell command such as @code{echo a b c} consists of the command
-itself followed by arguments, separated by spaces.
-
-More complex shell commands are composed of simple commands arranged together
-in a variety of ways: in a pipeline in which the output of one command
-becomes the input of a second, in a loop or conditional construct, or in
-some other grouping.
-
-@menu
-* Simple Commands:: The most common type of command.
-* Pipelines:: Connecting the input and output of several
- commands.
-* Lists:: How to execute commands sequentially.
-* Compound Commands:: Shell commands for control flow.
-@end menu
-
-@node Simple Commands
-@subsection Simple Commands
-@cindex commands, simple
-
-A simple command is the kind of command encountered most often.
-It's just a sequence of words separated by @code{blank}s, terminated
-by one of the shell's control operators (@pxref{Definitions}). The
-first word generally specifies a command to be executed, with the
-rest of the words being that command's arguments.
-
-The return status (@pxref{Exit Status}) of a simple command is
-its exit status as provided
-by the @sc{posix} 1003.1 @code{waitpid} function, or 128+@var{n} if
-the command was terminated by signal @var{n}.
-
-@node Pipelines
-@subsection Pipelines
-@cindex pipeline
-@cindex commands, pipelines
-
-A @code{pipeline} is a sequence of simple commands separated by
-@samp{|}.
-
-@rwindex time
-@rwindex !
-@cindex command timing
-The format for a pipeline is
-@example
-[@code{time} [@code{-p}]] [@code{!}] @var{command1} [@code{|} @var{command2} @dots{}]
-@end example
-
-@noindent
-The output of each command in the pipeline is connected via a pipe
-to the input of the next command.
-That is, each command reads the previous command's output.
-
-The reserved word @code{time} causes timing statistics
-to be printed for the pipeline once it finishes.
-The statistics currently consist of elapsed (wall-clock) time and
-user and system time consumed by the command's execution.
-The @option{-p} option changes the output format to that specified
-by @sc{posix}.
-The @env{TIMEFORMAT} variable may be set to a format string that
-specifies how the timing information should be displayed.
-@xref{Bash Variables}, for a description of the available formats.
-The use of @code{time} as a reserved word permits the timing of
-shell builtins, shell functions, and pipelines. An external
-@code{time} command cannot time these easily.
-
-If the pipeline is not executed asynchronously (@pxref{Lists}), the
-shell waits for all commands in the pipeline to complete.
-
-Each command in a pipeline is executed in its own subshell
-(@pxref{Command Execution Environment}). The exit
-status of a pipeline is the exit status of the last command in the
-pipeline, unless the @code{pipefail} option is enabled
-(@pxref{The Set Builtin}).
-If @code{pipefail} is enabled, the pipeline's return status is the
-value of the last (rightmost) command to exit with a non-zero status,
-or zero if all commands exit successfully.
-If the reserved word @samp{!} precedes the pipeline, the
-exit status is the logical negation of the exit status as described
-above.
-The shell waits for all commands in the pipeline to terminate before
-returning a value.
-
-@node Lists
-@subsection Lists of Commands
-@cindex commands, lists
-
-A @code{list} is a sequence of one or more pipelines separated by one
-of the operators @samp{;}, @samp{&}, @samp{&&}, or @samp{||},
-and optionally terminated by one of @samp{;}, @samp{&}, or a
-@code{newline}.
-
-Of these list operators, @samp{&&} and @samp{||}
-have equal precedence, followed by @samp{;} and @samp{&},
-which have equal precedence.
-
-A sequence of one or more newlines may appear in a @code{list}
-to delimit commands, equivalent to a semicolon.
-
-If a command is terminated by the control operator @samp{&},
-the shell executes the command asynchronously in a subshell.
-This is known as executing the command in the @var{background}.
-The shell does not wait for the command to finish, and the return
-status is 0 (true).
-When job control is not active (@pxref{Job Control}),
-the standard input for asynchronous commands, in the absence of any
-explicit redirections, is redirected from @code{/dev/null}.
-
-Commands separated by a @samp{;} are executed sequentially; the shell
-waits for each command to terminate in turn. The return status is the
-exit status of the last command executed.
-
-The control operators @samp{&&} and @samp{||}
-denote @sc{and} lists and @sc{or} lists, respectively.
-An @sc{and} list has the form
-@example
-@var{command1} && @var{command2}
-@end example
-
-@noindent
-@var{command2} is executed if, and only if, @var{command1}
-returns an exit status of zero.
-
-An @sc{or} list has the form
-@example
-@var{command1} || @var{command2}
-@end example
-
-@noindent
-@var{command2} is executed if, and only if, @var{command1}
-returns a non-zero exit status.
-
-The return status of
-@sc{and} and @sc{or} lists is the exit status of the last command
-executed in the list.
-
-@node Compound Commands
-@subsection Compound Commands
-@cindex commands, compound
-
-@menu
-* Looping Constructs:: Shell commands for iterative action.
-* Conditional Constructs:: Shell commands for conditional execution.
-* Command Grouping:: Ways to group commands.
-@end menu
-
-Compound commands are the shell programming constructs.
-Each construct begins with a reserved word or control operator and is
-terminated by a corresponding reserved word or operator.
-Any redirections (@pxref{Redirections}) associated with a compound command
-apply to all commands within that compound command unless explicitly overridden.
-
-Bash provides looping constructs, conditional commands, and mechanisms
-to group commands and execute them as a unit.
-
-@node Looping Constructs
-@subsubsection Looping Constructs
-@cindex commands, looping
-
-Bash supports the following looping constructs.
-
-Note that wherever a @samp{;} appears in the description of a
-command's syntax, it may be replaced with one or more newlines.
-
-@table @code
-@item until
-@rwindex until
-@rwindex do
-@rwindex done
-The syntax of the @code{until} command is:
-@example
-until @var{test-commands}; do @var{consequent-commands}; done
-@end example
-Execute @var{consequent-commands} as long as
-@var{test-commands} has an exit status which is not zero.
-The return status is the exit status of the last command executed
-in @var{consequent-commands}, or zero if none was executed.
-
-@item while
-@rwindex while
-The syntax of the @code{while} command is:
-@example
-while @var{test-commands}; do @var{consequent-commands}; done
-@end example
-
-Execute @var{consequent-commands} as long as
-@var{test-commands} has an exit status of zero.
-The return status is the exit status of the last command executed
-in @var{consequent-commands}, or zero if none was executed.
-
-@item for
-@rwindex for
-The syntax of the @code{for} command is:
-
-@example
-for @var{name} [in @var{words} @dots{}]; do @var{commands}; done
-@end example
-Expand @var{words}, and execute @var{commands} once for each member
-in the resultant list, with @var{name} bound to the current member.
-If @samp{in @var{words}} is not present, the @code{for} command
-executes the @var{commands} once for each positional parameter that is
-set, as if @samp{in "$@@"} had been specified
-(@pxref{Special Parameters}).
-The return status is the exit status of the last command that executes.
-If there are no items in the expansion of @var{words}, no commands are
-executed, and the return status is zero.
-
-An alternate form of the @code{for} command is also supported:
-
-@example
-for (( @var{expr1} ; @var{expr2} ; @var{expr3} )) ; do @var{commands} ; done
-@end example
-First, the arithmetic expression @var{expr1} is evaluated according
-to the rules described below (@pxref{Shell Arithmetic}).
-The arithmetic expression @var{expr2} is then evaluated repeatedly
-until it evaluates to zero.
-Each time @var{expr2} evaluates to a non-zero value, @var{commands} are
-executed and the arithmetic expression @var{expr3} is evaluated.
-If any expression is omitted, it behaves as if it evaluates to 1.
-The return value is the exit status of the last command in @var{list}
-that is executed, or false if any of the expressions is invalid.
-
-@end table
-
-The @code{break} and @code{continue} builtins (@pxref{Bourne Shell Builtins})
-may be used to control loop execution.
-
-@node Conditional Constructs
-@subsubsection Conditional Constructs
-@cindex commands, conditional
-
-@table @code
-@item if
-@rwindex if
-@rwindex then
-@rwindex else
-@rwindex elif
-@rwindex fi
-The syntax of the @code{if} command is:
-
-@example
-if @var{test-commands}; then
- @var{consequent-commands};
-[elif @var{more-test-commands}; then
- @var{more-consequents};]
-[else @var{alternate-consequents};]
-fi
-@end example
-
-The @var{test-commands} list is executed, and if its return status is zero,
-the @var{consequent-commands} list is executed.
-If @var{test-commands} returns a non-zero status, each @code{elif} list
-is executed in turn, and if its exit status is zero,
-the corresponding @var{more-consequents} is executed and the
-command completes.
-If @samp{else @var{alternate-consequents}} is present, and
-the final command in the final @code{if} or @code{elif} clause
-has a non-zero exit status, then @var{alternate-consequents} is executed.
-The return status is the exit status of the last command executed, or
-zero if no condition tested true.
-
-@item case
-@rwindex case
-@rwindex in
-@rwindex esac
-The syntax of the @code{case} command is:
-
-@example
-@code{case @var{word} in [ [(] @var{pattern} [| @var{pattern}]@dots{}) @var{command-list} ;;]@dots{} esac}
-@end example
-
-@code{case} will selectively execute the @var{command-list} corresponding to
-the first @var{pattern} that matches @var{word}.
-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 @samp{|} is used to separate multiple patterns, and the @samp{)}
-operator terminates a pattern list.
-A list of patterns and an associated command-list is known
-as a @var{clause}. Each clause must be terminated with @samp{;;}.
-The @var{word} undergoes tilde expansion, parameter expansion, command
-substitution, arithmetic expansion, and quote removal before matching is
-attempted. Each @var{pattern} undergoes tilde expansion, parameter
-expansion, command substitution, and arithmetic expansion.
-
-There may be an arbitrary number of @code{case} clauses, each terminated
-by a @samp{;;}. The first pattern that matches determines the
-command-list that is executed.
-
-Here is an example using @code{case} in a script that could be used to
-describe one interesting feature of an animal:
-
-@example
-echo -n "Enter the name of an animal: "
-read ANIMAL
-echo -n "The $ANIMAL has "
-case $ANIMAL in
- horse | dog | cat) echo -n "four";;
- man | kangaroo ) echo -n "two";;
- *) echo -n "an unknown number of";;
-esac
-echo " legs."
-@end example
-
-@noindent
-The return status is zero if no @var{pattern} is matched. Otherwise, the
-return status is the exit status of the @var{command-list} executed.
-
-@item select
-@rwindex select
-
-The @code{select} construct allows the easy generation of menus.
-It has almost the same syntax as the @code{for} command:
-
-@example
-select @var{name} [in @var{words} @dots{}]; do @var{commands}; done
-@end example
-
-The list of words following @code{in} is expanded, generating a list
-of items. The set of expanded words is printed on the standard
-error output stream, each preceded by a number. If the
-@samp{in @var{words}} is omitted, the positional parameters are printed,
-as if @samp{in "$@@"} had been specifed.
-The @env{PS3} prompt is then displayed and a line is read from the
-standard input.
-If the line consists of a number corresponding to one of the displayed
-words, then the value of @var{name} is set to that word.
-If the line is empty, the words and prompt are displayed again.
-If @code{EOF} is read, the @code{select} command completes.
-Any other value read causes @var{name} to be set to null.
-The line read is saved in the variable @env{REPLY}.
-
-The @var{commands} are executed after each selection until a
-@code{break} command is executed, at which
-point the @code{select} command completes.
-
-Here is an example that allows the user to pick a filename from the
-current directory, and displays the name and index of the file
-selected.
-
-@example
-select fname in *;
-do
- echo you picked $fname \($REPLY\)
- break;
-done
-@end example
-
-@item ((@dots{}))
-@example
-(( @var{expression} ))
-@end example
-
-The arithmetic @var{expression} is evaluated according to the rules
-described below (@pxref{Shell Arithmetic}).
-If the value of the expression is non-zero, the return status is 0;
-otherwise the return status is 1. This is exactly equivalent to
-@example
-let "@var{expression}"
-@end example
-@noindent
-@xref{Bash Builtins}, for a full description of the @code{let} builtin.
-
-@item [[@dots{}]]
-@rwindex [[
-@rwindex ]]
-@example
-[[ @var{expression} ]]
-@end example
-
-Return a status of 0 or 1 depending on the evaluation of
-the conditional expression @var{expression}.
-Expressions are composed of the primaries described below in
-@ref{Bash Conditional Expressions}.
-Word splitting and filename expansion are not performed on the words
-between the @samp{[[} and @samp{]]}; tilde expansion, parameter and
-variable expansion, arithmetic expansion, command substitution, process
-substitution, and quote removal are performed.
-Conditional operators such as @samp{-f} must be unquoted to be recognized
-as primaries.
-
-When the @samp{==} and @samp{!=} operators are used, the string to the
-right of the operator is considered a pattern and matched according
-to the rules described below in @ref{Pattern Matching}.
-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 (@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.
-
-An additional binary operator, @samp{=~}, is available, with the same
-precedence as @samp{==} and @samp{!=}.
-When it is used, the string to the right of the operator is considered
-an extended regular expression and matched accordingly (as in @i{regex}3)).
-The return value is 0 if the string matches
-the pattern, and 1 otherwise.
-If the regular expression is syntactically incorrect, the conditional
-expression's return value is 2.
-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.
-Substrings matched by parenthesized subexpressions within the regular
-expression are saved in the array variable @code{BASH_REMATCH}.
-The element of @code{BASH_REMATCH} with index 0 is the portion of the string
-matching the entire regular expression.
-The element of @code{BASH_REMATCH} with index @var{n} is the portion of the
-string matching the @var{n}th parenthesized subexpression.
-
-Expressions may be combined using the following operators, listed
-in decreasing order of precedence:
-
-@table @code
-@item ( @var{expression} )
-Returns the value of @var{expression}.
-This may be used to override the normal precedence of operators.
-
-@item ! @var{expression}
-True if @var{expression} is false.
-
-@item @var{expression1} && @var{expression2}
-True if both @var{expression1} and @var{expression2} are true.
-
-@item @var{expression1} || @var{expression2}
-True if either @var{expression1} or @var{expression2} is true.
-@end table
-@noindent
-The @code{&&} and @code{||} operators do not evaluate @var{expression2} if the
-value of @var{expression1} is sufficient to determine the return
-value of the entire conditional expression.
-
-@end table
-
-@node Command Grouping
-@subsubsection Grouping Commands
-@cindex commands, grouping
-
-Bash provides two ways to group a list of commands to be executed
-as a unit. When commands are grouped, redirections may be applied
-to the entire command list. For example, the output of all the
-commands in the list may be redirected to a single stream.
-
-@table @code
-@item ()
-@example
-( @var{list} )
-@end example
-
-Placing a list of commands between parentheses causes a subshell
-environment to be created (@pxref{Command Execution Environment}), and each
-of the commands in @var{list} to be executed in that subshell. Since the
-@var{list} is executed in a subshell, variable assignments do not remain in
-effect after the subshell completes.
-
-@item @{@}
-@rwindex @{
-@rwindex @}
-@example
-@{ @var{list}; @}
-@end example
-
-Placing a list of commands between curly braces causes the list to
-be executed in the current shell context. No subshell is created.
-The semicolon (or newline) following @var{list} is required.
-@end table
-
-In addition to the creation of a subshell, there is a subtle difference
-between these two constructs due to historical reasons. The braces
-are @code{reserved words}, so they must be separated from the @var{list}
-by @code{blank}s. The parentheses are @code{operators}, and are
-recognized as separate tokens by the shell even if they are not separated
-from the @var{list} by whitespace.
-
-The exit status of both of these constructs is the exit status of
-@var{list}.
-
-@node Shell Functions
-@section Shell Functions
-@cindex shell function
-@cindex functions, shell
-
-Shell functions are a way to group commands for later execution
-using a single name for the group. They are executed just like
-a "regular" command.
-When the name of a shell function is used as a simple command name,
-the list of commands associated with that function name is executed.
-Shell functions are executed in the current
-shell context; no new process is created to interpret them.
-
-Functions are declared using this syntax:
-@rwindex function
-@example
-[ @code{function} ] @var{name} () @var{compound-command} [ @var{redirections} ]
-@end example
-
-This defines a shell function named @var{name}. The reserved
-word @code{function} is optional.
-If the @code{function} reserved
-word is supplied, the parentheses are optional.
-The @var{body} of the function is the compound command
-@var{compound-command} (@pxref{Compound Commands}).
-That command is usually a @var{list} enclosed between @{ and @}, but
-may be any compound command listed above.
-@var{compound-command} is executed whenever @var{name} is specified as the
-name of a command.
-Any redirections (@pxref{Redirections}) associated with the shell function
-are performed when the function is executed.
-
-A function definition may be deleted using the @option{-f} option to the
-@code{unset} builtin (@pxref{Bourne Shell Builtins}).
-
-The exit status of a function definition is zero unless a syntax error
-occurs or a readonly function with the same name already exists.
-When executed, the exit status of a function is the exit status of the
-last command executed in the body.
-
-Note that for historical reasons, in the most common usage the curly braces
-that surround the body of the function must be separated from the body by
-@code{blank}s or newlines.
-This is because the braces are reserved words and are only recognized
-as such when they are separated by whitespace.
-Also, when using the braces, the @var{list} must be terminated by a semicolon,
-a @samp{&}, or a newline.
-
-When a function is executed, the arguments to the
-function become the positional parameters
-during its execution (@pxref{Positional Parameters}).
-The special parameter @samp{#} that expands to the number of
-positional parameters is updated to reflect the change.
-Special parameter @code{0} is unchanged.
-The first element of the @env{FUNCNAME} variable is set to the
-name of the function while the function is executing.
-All other aspects of the shell execution
-environment are identical between a function and its caller
-with the exception that the @env{DEBUG} and @env{RETURN} traps
-are not inherited unless the function has been given the
-@code{trace} attribute using the @code{declare} builtin or
-the @code{-o functrace} option has been enabled with
-the @code{set} builtin,
-(in which case all functions inherit the @env{DEBUG} and @env{RETURN} traps).
-@xref{Bourne Shell Builtins}, for the description of the
-@code{trap} builtin.
-
-If the builtin command @code{return}
-is executed in a function, the function completes and
-execution resumes with the next command after the function
-call.
-Any command associated with the @code{RETURN} trap is executed
-before execution resumes.
-When a function completes, the values of the
-positional parameters and the special parameter @samp{#}
-are restored to the values they had prior to the function's
-execution. If a numeric argument is given to @code{return},
-that is the function's return status; otherwise the function's
-return status is the exit status of the last command executed
-before the @code{return}.
-
-Variables local to the function may be declared with the
-@code{local} builtin. These variables are visible only to
-the function and the commands it invokes.
-
-Function names and definitions may be listed with the
-@option{-f} option to the @code{declare} or @code{typeset}
-builtin commands (@pxref{Bash Builtins}).
-The @option{-F} option to @code{declare} or @code{typeset}
-will list the function names only
-(and optionally the source file and line number, if the @code{extdebug}
-shell option is enabled).
-Functions may be exported so that subshells
-automatically have them defined with the
-@option{-f} option to the @code{export} builtin
-(@pxref{Bourne Shell Builtins}).
-Note that shell functions and variables with the same name may result
-in multiple identically-named entries in the environment passed to the
-shell's children.
-Care should be taken in cases where this may cause a problem.
-
-Functions may be recursive. No limit is placed on the number of
-recursive calls.
-
-@node Shell Parameters
-@section Shell Parameters
-@cindex parameters
-@cindex variable, shell
-@cindex shell variable
-
-@menu
-* Positional Parameters:: The shell's command-line arguments.
-* Special Parameters:: Parameters denoted by special characters.
-@end menu
-
-A @var{parameter} is an entity that stores values.
-It can be a @code{name}, a number, or one of the special characters
-listed below.
-A @var{variable} is a parameter denoted by a @code{name}.
-A variable has a @var{value} and zero or more @var{attributes}.
-Attributes are assigned using the @code{declare} builtin command
-(see the description of the @code{declare} builtin in @ref{Bash Builtins}).
-
-A parameter is set if it has been assigned a value. The null string is
-a valid value. Once a variable is set, it may be unset only by using
-the @code{unset} builtin command.
-
-A variable may be assigned to by a statement of the form
-@example
-@var{name}=[@var{value}]
-@end example
-@noindent
-If @var{value}
-is not given, the variable is assigned the null string. All
-@var{value}s undergo tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote
-removal (detailed below). If the variable has its @code{integer}
-attribute set, then @var{value}
-is evaluated as an arithmetic expression even if the @code{$((@dots{}))}
-expansion is not used (@pxref{Arithmetic Expansion}).
-Word splitting is not performed, with the exception
-of @code{"$@@"} as explained below.
-Filename expansion is not performed.
-Assignment statements may also appear as arguments to the
-@code{alias},
-@code{declare}, @code{typeset}, @code{export}, @code{readonly},
-and @code{local} builtin commands.
-
-In the context where an assignment statement is assigning a value
-to a shell variable or array index (@pxref{Arrays}), the @samp{+=}
-operator can be used to
-append to or add to the variable's previous value.
-When @samp{+=} is applied to a variable for which the integer attribute
-has been set, @var{value} is evaluated as an arithmetic expression and
-added to the variable's current value, which is also evaluated.
-When @samp{+=} is applied to an array variable using compound assignment
-(@pxref{Arrays}), the
-variable's value is not unset (as it is when using @samp{=}), and new
-values are appended to the array beginning at one greater than the array's
-maximum index.
-When applied to a string-valued variable, @var{value} is expanded and
-appended to the variable's value.
-
-@node Positional Parameters
-@subsection Positional Parameters
-@cindex parameters, positional
-
-A @var{positional parameter} is a parameter denoted by one or more
-digits, other than the single digit @code{0}. Positional parameters are
-assigned from the shell's arguments when it is invoked,
-and may be reassigned using the @code{set} builtin command.
-Positional parameter @code{N} may be referenced as @code{$@{N@}}, or
-as @code{$N} when @code{N} consists of a single digit.
-Positional parameters may not be assigned to with assignment statements.
-The @code{set} and @code{shift} builtins are used to set and
-unset them (@pxref{Shell Builtin Commands}).
-The positional parameters are
-temporarily replaced when a shell function is executed
-(@pxref{Shell Functions}).
-
-When a positional parameter consisting of more than a single
-digit is expanded, it must be enclosed in braces.
-
-@node Special Parameters
-@subsection Special Parameters
-@cindex parameters, special
-
-The shell treats several parameters specially. These parameters may
-only be referenced; assignment to them is not allowed.
-
-@vtable @code
-
-@item *
-Expands to the positional parameters, starting from one. When the
-expansion occurs within double quotes, it expands to a single word
-with the value of each parameter separated by the first character
-of the @env{IFS}
-special variable. That is, @code{"$*"} is equivalent
-to @code{"$1@var{c}$2@var{c}@dots{}"}, where @var{c}
-is the first character of the value of the @code{IFS}
-variable.
-If @env{IFS} is unset, the parameters are separated by spaces.
-If @env{IFS} is null, the parameters are joined without intervening
-separators.
-
-
-@item @@
-Expands to the positional parameters, starting from one. When the
-expansion occurs within double quotes, each parameter expands to a
-separate word. That is, @code{"$@@"} is equivalent to
-@code{"$1" "$2" @dots{}}.
-If the double-quoted expansion occurs within a word, the expansion of
-the first parameter is joined with the beginning part of the original
-word, and the expansion of the last parameter is joined with the last
-part of the original word.
-When there are no positional parameters, @code{"$@@"} and
-@code{$@@}
-expand to nothing (i.e., they are removed).
-
-@item #
-Expands to the number of positional parameters in decimal.
-
-@item ?
-Expands to the exit status of the most recently executed foreground
-pipeline.
-
-@item -
-(A hyphen.) Expands to the current option flags as specified upon
-invocation, by the @code{set}
-builtin command, or those set by the shell itself
-(such as the @option{-i} option).
-
-@item $
-Expands to the process @sc{id} of the shell. In a @code{()} subshell, it
-expands to the process @sc{id} of the invoking shell, not the subshell.
-
-@item !
-Expands to the process @sc{id} of the most recently executed background
-(asynchronous) command.
-
-@item 0
-Expands to the name of the shell or shell script. This is set at
-shell initialization. If Bash is invoked with a file of commands
-(@pxref{Shell Scripts}), @code{$0} is set to the name of that file.
-If Bash is started with the @option{-c} option (@pxref{Invoking Bash}),
-then @code{$0} is set to the first argument after the string to be
-executed, if one is present. Otherwise, it is set
-to the filename used to invoke Bash, as given by argument zero.
-
-@item _
-(An underscore.)
-At shell startup, set to the absolute pathname used to invoke the
-shell or shell script being executed as passed in the environment
-or argument list.
-Subsequently, expands to the last argument to the previous command,
-after expansion.
-Also set to the full pathname used to invoke each command executed
-and placed in the environment exported to that command.
-When checking mail, this parameter holds the name of the mail file.
-@end vtable
-
-@node Shell Expansions
-@section Shell Expansions
-@cindex expansion
-
-Expansion is performed on the command line after it has been split into
-@code{token}s. There are seven kinds of expansion performed:
-@itemize @bullet
-@item brace expansion
-@item tilde expansion
-@item parameter and variable expansion
-@item command substitution
-@item arithmetic expansion
-@item word splitting
-@item filename expansion
-@end itemize
-
-@menu
-* Brace Expansion:: Expansion of expressions within braces.
-* Tilde Expansion:: Expansion of the ~ character.
-* Shell Parameter Expansion:: How Bash expands variables to their values.
-* Command Substitution:: Using the output of a command as an argument.
-* Arithmetic Expansion:: How to use arithmetic in shell expansions.
-* Process Substitution:: A way to write and read to and from a
- command.
-* Word Splitting:: How the results of expansion are split into separate
- arguments.
-* Filename Expansion:: A shorthand for specifying filenames matching patterns.
-* Quote Removal:: How and when quote characters are removed from
- words.
-@end menu
-
-The order of expansions is: brace expansion, tilde expansion,
-parameter, variable, and arithmetic expansion and
-command substitution
-(done in a left-to-right fashion), word splitting, and filename
-expansion.
-
-On systems that can support it, there is an additional expansion
-available: @var{process substitution}. This is performed at the
-same time as parameter, variable, and arithmetic expansion and
-command substitution.
-
-Only brace expansion, word splitting, and filename expansion
-can change the number of words of the expansion; other expansions
-expand a single word to a single word.
-The only exceptions to this are the expansions of
-@code{"$@@"} (@pxref{Special Parameters}) and @code{"$@{@var{name}[@@]@}"}
-(@pxref{Arrays}).
-
-After all expansions, @code{quote removal} (@pxref{Quote Removal})
-is performed.
-
-@node Brace Expansion
-@subsection Brace Expansion
-@cindex brace expansion
-@cindex expansion, brace
-
-Brace expansion is a mechanism by which arbitrary strings may be generated.
-This mechanism is similar to
-@var{filename expansion} (@pxref{Filename Expansion}),
-but the file names generated need not exist.
-Patterns to be brace expanded take the form of an optional @var{preamble},
-followed by either a series of comma-separated strings or a sequnce expression
-between a pair of braces,
-followed by an optional @var{postscript}.
-The preamble is prefixed to each string contained within the braces, and
-the postscript is then appended to each resulting string, expanding left
-to right.
-
-Brace expansions may be nested.
-The results of each expanded string are not sorted; left to right order
-is preserved.
-For example,
-@example
-bash$ echo a@{d,c,b@}e
-ade ace abe
-@end example
-
-A sequence expression takes the form @code{@{@var{x}..@var{y}@}},
-where @var{x} and @var{y} are either integers or single characters.
-When integers are supplied, the expression expands to each number between
-@var{x} and @var{y}, inclusive.
-When characters are supplied, the expression expands to each character
-lexicographically between @var{x} and @var{y}, inclusive. Note that
-both @var{x} and @var{y} must be of the same type.
-
-Brace expansion is performed before any other expansions,
-and any characters special to other expansions are preserved
-in the result. It is strictly textual. Bash
-does not apply any syntactic interpretation to the context of the
-expansion or the text between the braces.
-To avoid conflicts with parameter expansion, the string @samp{$@{}
-is not considered eligible for brace expansion.
-
-A correctly-formed brace expansion must contain unquoted opening
-and closing braces, and at least one unquoted comma or a valid
-sequence expression.
-Any incorrectly formed brace expansion is left unchanged.
-
-A @{ or @samp{,} may be quoted with a backslash to prevent its
-being considered part of a brace expression.
-To avoid conflicts with parameter expansion, the string @samp{$@{}
-is not considered eligible for brace expansion.
-
-This construct is typically used as shorthand when the common
-prefix of the strings to be generated is longer than in the
-above example:
-@example
-mkdir /usr/local/src/bash/@{old,new,dist,bugs@}
-@end example
-or
-@example
-chown root /usr/@{ucb/@{ex,edit@},lib/@{ex?.?*,how_ex@}@}
-@end example
-
-@node Tilde Expansion
-@subsection Tilde Expansion
-@cindex tilde expansion
-@cindex expansion, tilde
-
-If a word begins with an unquoted tilde character (@samp{~}), all of the
-characters up to the first unquoted slash (or all characters,
-if there is no unquoted slash) are considered a @var{tilde-prefix}.
-If none of the characters in the tilde-prefix are quoted, the
-characters in the tilde-prefix following the tilde are treated as a
-possible @var{login name}.
-If this login name is the null string, the tilde is replaced with the
-value of the @env{HOME} shell variable.
-If @env{HOME} is unset, the home directory of the user executing the
-shell is substituted instead.
-Otherwise, the tilde-prefix is replaced with the home directory
-associated with the specified login name.
-
-If the tilde-prefix is @samp{~+}, the value of
-the shell variable @env{PWD} replaces the tilde-prefix.
-If the tilde-prefix is @samp{~-}, the value of the shell variable
-@env{OLDPWD}, if it is set, is substituted.
-
-If the characters following the tilde in the tilde-prefix consist of a
-number @var{N}, optionally prefixed by a @samp{+} or a @samp{-},
-the tilde-prefix is replaced with the
-corresponding element from the directory stack, as it would be displayed
-by the @code{dirs} builtin invoked with the characters following tilde
-in the tilde-prefix as an argument (@pxref{The Directory Stack}).
-If the tilde-prefix, sans the tilde, consists of a number without a
-leading @samp{+} or @samp{-}, @samp{+} is assumed.
-
-If the login name is invalid, or the tilde expansion fails, the word is
-left unchanged.
-
-Each variable assignment is checked for unquoted tilde-prefixes immediately
-following a @samp{:} or the first @samp{=}.
-In these cases, tilde expansion is also performed.
-Consequently, one may use file names with tildes in assignments to
-@env{PATH}, @env{MAILPATH}, and @env{CDPATH},
-and the shell assigns the expanded value.
-
-The following table shows how Bash treats unquoted tilde-prefixes:
-
-@table @code
-@item ~
-The value of @code{$HOME}
-@item ~/foo
-@file{$HOME/foo}
-
-@item ~fred/foo
-The subdirectory @code{foo} of the home directory of the user
-@code{fred}
-
-@item ~+/foo
-@file{$PWD/foo}
-
-@item ~-/foo
-@file{$@{OLDPWD-'~-'@}/foo}
-
-@item ~@var{N}
-The string that would be displayed by @samp{dirs +@var{N}}
-
-@item ~+@var{N}
-The string that would be displayed by @samp{dirs +@var{N}}
-
-@item ~-@var{N}
-The string that would be displayed by @samp{dirs -@var{N}}
-
-@end table
-
-@node Shell Parameter Expansion
-@subsection Shell Parameter Expansion
-@cindex parameter expansion
-@cindex expansion, parameter
-
-The @samp{$} character introduces parameter expansion,
-command substitution, or arithmetic expansion. The parameter name
-or symbol to be expanded may be enclosed in braces, which
-are optional but serve to protect the variable to be expanded from
-characters immediately following it which could be
-interpreted as part of the name.
-
-When braces are used, the matching ending brace is the first @samp{@}}
-not escaped by a backslash or within a quoted string, and not within an
-embedded arithmetic expansion, command substitution, or parameter
-expansion.
-
-The basic form of parameter expansion is $@{@var{parameter}@}.
-The value of @var{parameter} is substituted. The braces are required
-when @var{parameter}
-is a positional parameter with more than one digit,
-or when @var{parameter}
-is followed by a character that is not to be
-interpreted as part of its name.
-
-If the first character of @var{parameter} is an exclamation point,
-a level of variable indirection is introduced.
-Bash uses the value of the variable formed from the rest of
-@var{parameter} as the name of the variable; this variable is then
-expanded and that value is used in the rest of the substitution, rather
-than the value of @var{parameter} itself.
-This is known as @code{indirect expansion}.
-The exceptions to this are the expansions of $@{!@var{prefix*}@}
-and $@{!@var{name}[@@]@}
-described below.
-The exclamation point must immediately follow the left brace in order to
-introduce indirection.
-
-In each of the cases below, @var{word} is subject to tilde expansion,
-parameter expansion, command substitution, and arithmetic expansion.
-
-When not performing substring expansion, Bash tests for a parameter
-that is unset or null; omitting the colon results in a test only for a
-parameter that is unset. Put another way, if the colon is included,
-the operator tests for both existence and that the value is not null;
-if the colon is omitted, the operator tests only for existence.
-
-@table @code
-
-@item $@{@var{parameter}:@minus{}@var{word}@}
-If @var{parameter} is unset or null, the expansion of
-@var{word} is substituted. Otherwise, the value of
-@var{parameter} is substituted.
-
-@item $@{@var{parameter}:=@var{word}@}
-If @var{parameter}
-is unset or null, the expansion of @var{word}
-is assigned to @var{parameter}.
-The value of @var{parameter} is then substituted.
-Positional parameters and special parameters may not be assigned to
-in this way.
-
-@item $@{@var{parameter}:?@var{word}@}
-If @var{parameter}
-is null or unset, the expansion of @var{word} (or a message
-to that effect if @var{word}
-is not present) is written to the standard error and the shell, if it
-is not interactive, exits. Otherwise, the value of @var{parameter} is
-substituted.
-
-@item $@{@var{parameter}:+@var{word}@}
-If @var{parameter}
-is null or unset, nothing is substituted, otherwise the expansion of
-@var{word} is substituted.
-
-@item $@{@var{parameter}:@var{offset}@}
-@itemx $@{@var{parameter}:@var{offset}:@var{length}@}
-Expands to up to @var{length} characters of @var{parameter}
-starting at the character specified by @var{offset}.
-If @var{length} is omitted, expands to the substring of
-@var{parameter} starting at the character specified by @var{offset}.
-@var{length} and @var{offset} are arithmetic expressions
-(@pxref{Shell Arithmetic}).
-This is referred to as Substring Expansion.
-
-@var{length} must evaluate to a number greater than or equal to zero.
-If @var{offset} evaluates to a number less than zero, the value
-is used as an offset from the end of the value of @var{parameter}.
-If @var{parameter} is @samp{@@}, the result is @var{length} positional
-parameters beginning at @var{offset}.
-If @var{parameter} is an array name indexed by @samp{@@} or @samp{*},
-the result is the @var{length}
-members of the array beginning with @code{$@{@var{parameter}[@var{offset}]@}}.
-A negative @var{offset} is taken relative to one greater than the maximum
-index of the specified array.
-Note that a negative offset must be separated from the colon by at least
-one space to avoid being confused with the @samp{:-} expansion.
-Substring indexing is zero-based unless the positional parameters
-are used, in which case the indexing starts at 1.
-
-@item $@{!@var{prefix}*@}
-@itemx $@{!@var{prefix}@@@}
-Expands to the names of variables whose names begin with @var{prefix},
-separated by the first character of the @env{IFS} special variable.
-
-@item $@{!@var{name}[@@]@}
-@itemx $@{!@var{name}[*]@}
-If @var{name} is an array variable, expands to the list of array indices
-(keys) assigned in @var{name}.
-If @var{name} is not an array, expands to 0 if @var{name} is set and null
-otherwise.
-When @samp{@@} is used and the expansion appears within double quotes, each
-key expands to a separate word.
-
-@item $@{#@var{parameter}@}
-The length in characters of the expanded value of @var{parameter} is
-substituted.
-If @var{parameter} is @samp{*} or @samp{@@}, the value substituted
-is the number of positional parameters.
-If @var{parameter} is an array name subscripted by @samp{*} or @samp{@@},
-the value substituted is the number of elements in the array.
-
-@item $@{@var{parameter}#@var{word}@}
-@itemx $@{@var{parameter}##@var{word}@}
-The @var{word}
-is expanded to produce a pattern just as in filename
-expansion (@pxref{Filename Expansion}). If the pattern matches
-the beginning of the expanded value of @var{parameter},
-then the result of the expansion is the expanded value of @var{parameter}
-with the shortest matching pattern (the @samp{#} case) or the
-longest matching pattern (the @samp{##} case) deleted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter} is an array variable subscripted with
-@samp{@@} or @samp{*},
-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{word}@}
-@itemx $@{@var{parameter}%%@var{word}@}
-The @var{word} is expanded to produce a pattern just as in
-filename expansion.
-If the pattern matches a trailing portion of the expanded value of
-@var{parameter}, then the result of the expansion is the value of
-@var{parameter} with the shortest matching pattern (the @samp{%} case)
-or the longest matching pattern (the @samp{%%} case) deleted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the pattern removal operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter}
-is an array variable subscripted with @samp{@@} or @samp{*},
-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}@}
-
-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}.
-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
-of the expanded value of @var{parameter}.
-If @var{string} is null, matches of @var{pattern} are deleted
-and the @code{/} following @var{pattern} may be omitted.
-If @var{parameter} is @samp{@@} or @samp{*},
-the substitution operation is applied to each positional
-parameter in turn, and the expansion is the resultant list.
-If @var{parameter}
-is an array variable subscripted with @samp{@@} or @samp{*},
-the substitution operation is applied to each member of the
-array in turn, and the expansion is the resultant list.
-
-@end table
-
-@node Command Substitution
-@subsection Command Substitution
-@cindex command substitution
-
-Command substitution allows the output of a command to replace
-the command itself.
-Command substitution occurs when a command is enclosed as follows:
-@example
-$(@var{command})
-@end example
-@noindent
-or
-@example
-`@var{command}`
-@end example
-
-@noindent
-Bash performs the expansion by executing @var{command} and
-replacing the command substitution with the standard output of the
-command, with any trailing newlines deleted.
-Embedded newlines are not deleted, but they may be removed during
-word splitting.
-The command substitution @code{$(cat @var{file})} can be
-replaced by the equivalent but faster @code{$(< @var{file})}.
-
-When the old-style backquote form of substitution is used,
-backslash retains its literal meaning except when followed by
-@samp{$}, @samp{`}, or @samp{\}.
-The first backquote not preceded by a backslash terminates the
-command substitution.
-When using the @code{$(@var{command})} form, all characters between
-the parentheses make up the command; none are treated specially.
-
-Command substitutions may be nested. To nest when using the backquoted
-form, escape the inner backquotes with backslashes.
-
-If the substitution appears within double quotes, word splitting and
-filename expansion are not performed on the results.
-
-@node Arithmetic Expansion
-@subsection Arithmetic Expansion
-@cindex expansion, arithmetic
-@cindex arithmetic expansion
-
-Arithmetic expansion allows the evaluation of an arithmetic expression
-and the substitution of the result. The format for arithmetic expansion is:
-
-@example
-$(( @var{expression} ))
-@end example
-
-The expression is treated as if it were within double quotes, but
-a double quote inside the parentheses is not treated specially.
-All tokens in the expression undergo parameter expansion, command
-substitution, and quote removal.
-Arithmetic expansions may be nested.
-
-The evaluation is performed according to the rules listed below
-(@pxref{Shell Arithmetic}).
-If the expression is invalid, Bash prints a message indicating
-failure to the standard error and no substitution occurs.
-
-@node Process Substitution
-@subsection Process Substitution
-@cindex process substitution
-
-Process substitution is supported on systems that support named
-pipes (@sc{fifo}s) or the @file{/dev/fd} method of naming open files.
-It takes the form of
-@example
-<(@var{list})
-@end example
-@noindent
-or
-@example
->(@var{list})
-@end example
-@noindent
-The process @var{list} is run with its input or output connected to a
-@sc{fifo} or some file in @file{/dev/fd}. The name of this file is
-passed as an argument to the current command as the result of the
-expansion. If the @code{>(@var{list})} form is used, writing to
-the file will provide input for @var{list}. If the
-@code{<(@var{list})} form is used, the file passed as an
-argument should be read to obtain the output of @var{list}.
-Note that no space may appear between the @code{<} or @code{>}
-and the left parenthesis, otherwise the construct would be interpreted
-as a redirection.
-
-When available, process substitution is performed simultaneously with
-parameter and variable expansion, command substitution, and arithmetic
-expansion.
-
-@node Word Splitting
-@subsection Word Splitting
-@cindex word splitting
-
-The shell scans the results of parameter expansion, command substitution,
-and arithmetic expansion that did not occur within double quotes for
-word splitting.
-
-The shell treats each character of @env{$IFS}
-as a delimiter, and splits the results of the other
-expansions into words on these characters. If
-@env{IFS} is unset, or its value is exactly @code{<space><tab><newline>},
-the default, then any sequence of @env{IFS}
-characters serves to delimit words. If @env{IFS}
-has a value other than the default, then sequences of
-the whitespace characters @code{space} and @code{tab}
-are ignored at the beginning and end of the
-word, as long as the whitespace character is in the
-value of @env{IFS} (an @env{IFS} whitespace character).
-Any character in @env{IFS} that is not @env{IFS}
-whitespace, along with any adjacent @env{IFS}
-whitespace characters, delimits a field. A sequence of @env{IFS}
-whitespace characters is also treated as a delimiter.
-If the value of @env{IFS} is null, no word splitting occurs.
-
-Explicit null arguments (@code{""} or @code{''}) are retained.
-Unquoted implicit null arguments, resulting from the expansion of
-parameters that have no values, are removed.
-If a parameter with no value is expanded within double quotes, a
-null argument results and is retained.
-
-Note that if no expansion occurs, no splitting
-is performed.
-
-@node Filename Expansion
-@subsection Filename Expansion
-@menu
-* Pattern Matching:: How the shell matches patterns.
-@end menu
-@cindex expansion, filename
-@cindex expansion, pathname
-@cindex filename expansion
-@cindex pathname expansion
-
-After word splitting, unless the @option{-f} option has been set
-(@pxref{The Set Builtin}), Bash scans each word for the characters
-@samp{*}, @samp{?}, and @samp{[}.
-If one of these characters appears, then the word is
-regarded as a @var{pattern},
-and replaced with an alphabetically sorted list of
-file names matching the pattern. If no matching file names are found,
-and the shell option @code{nullglob} is disabled, the word is left
-unchanged.
-If the @code{nullglob} option is set, and no matches are found, the word
-is removed.
-If the @code{failglob} shell option is set, and no matches are found,
-an error message is printed and the command is not executed.
-If the shell option @code{nocaseglob} is enabled, the match is performed
-without regard to the case of alphabetic characters.
-
-When a pattern is used for filename generation, the character @samp{.}
-at the start of a filename or immediately following a slash
-must be matched explicitly, unless the shell option @code{dotglob} is set.
-When matching a file name, the slash character must always be
-matched explicitly.
-In other cases, the @samp{.} character is not treated specially.
-
-See the description of @code{shopt} in @ref{Bash Builtins},
-for a description of the @code{nocaseglob}, @code{nullglob},
-@code{failglob}, and @code{dotglob} options.
-
-The @env{GLOBIGNORE}
-shell variable may be used to restrict the set of filenames matching a
-pattern. If @env{GLOBIGNORE}
-is set, each matching filename that also matches one of the patterns in
-@env{GLOBIGNORE} is removed from the list of matches. The filenames
-@file{.} and @file{..}
-are always ignored when @env{GLOBIGNORE}
-is set and not null.
-However, setting @env{GLOBIGNORE} to a non-null value has the effect of
-enabling the @code{dotglob}
-shell option, so all other filenames beginning with a
-@samp{.} will match.
-To get the old behavior of ignoring filenames beginning with a
-@samp{.}, make @samp{.*} one of the patterns in @env{GLOBIGNORE}.
-The @code{dotglob} option is disabled when @env{GLOBIGNORE}
-is unset.
-
-@node Pattern Matching
-@subsubsection Pattern Matching
-@cindex pattern matching
-@cindex matching, pattern
-
-Any character that appears in a pattern, other than the special pattern
-characters described below, matches itself.
-The @sc{nul} character may not occur in a pattern.
-A backslash escapes the following character; the
-escaping backslash is discarded when matching.
-The special pattern characters must be quoted if they are to be matched
-literally.
-
-The special pattern characters have the following meanings:
-@table @code
-@item *
-Matches any string, including the null string.
-@item ?
-Matches any single character.
-@item [@dots{}]
-Matches any one of the enclosed characters. A pair of characters
-separated by a hyphen denotes a @var{range expression};
-any character that sorts between those two characters, inclusive,
-using the current locale's collating sequence and character set,
-is matched. If the first character following the
-@samp{[} is a @samp{!} or a @samp{^}
-then any character not enclosed is matched. A @samp{@minus{}}
-may be matched by including it as the first or last character
-in the set. A @samp{]} may be matched by including it as the first
-character in the set.
-The sorting order of characters in range expressions is determined by
-the current locale and the value of the @env{LC_COLLATE} shell variable,
-if set.
-
-For example, in the default C locale, @samp{[a-dx-z]} is equivalent to
-@samp{[abcdxyz]}. Many locales sort characters in dictionary order, and in
-these locales @samp{[a-dx-z]} is typically not equivalent to @samp{[abcdxyz]};
-it might be equivalent to @samp{[aBbCcDdxXyYz]}, for example. To obtain
-the traditional interpretation of ranges in bracket expressions, you can
-force the use of the C locale by setting the @env{LC_COLLATE} or
-@env{LC_ALL} environment variable to the value @samp{C}.
-
-Within @samp{[} and @samp{]}, @var{character classes} can be specified
-using the syntax
-@code{[:}@var{class}@code{:]}, where @var{class} is one of the
-following classes defined in the @sc{posix} standard:
-@example
-alnum alpha ascii blank cntrl digit graph lower
-print punct space upper word xdigit
-@end example
-@noindent
-A character class matches any character belonging to that class.
-The @code{word} character class matches letters, digits, and the character
-@samp{_}.
-
-Within @samp{[} and @samp{]}, an @var{equivalence class} can be
-specified using the syntax @code{[=}@var{c}@code{=]}, which
-matches all characters with the same collation weight (as defined
-by the current locale) as the character @var{c}.
-
-Within @samp{[} and @samp{]}, the syntax @code{[.}@var{symbol}@code{.]}
-matches the collating symbol @var{symbol}.
-@end table
-
-If the @code{extglob} shell option is enabled using the @code{shopt}
-builtin, several extended pattern matching operators are recognized.
-In the following description, a @var{pattern-list} is a list of one
-or more patterns separated by a @samp{|}.
-Composite patterns may be formed using one or more of the following
-sub-patterns:
-
-@table @code
-@item ?(@var{pattern-list})
-Matches zero or one occurrence of the given patterns.
-
-@item *(@var{pattern-list})
-Matches zero or more occurrences of the given patterns.
-
-@item +(@var{pattern-list})
-Matches one or more occurrences of the given patterns.
-
-@item @@(@var{pattern-list})
-Matches one of the given patterns.
-
-@item !(@var{pattern-list})
-Matches anything except one of the given patterns.
-@end table
-
-@node Quote Removal
-@subsection Quote Removal
-
-After the preceding expansions, all unquoted occurrences of the
-characters @samp{\}, @samp{'}, and @samp{"} that did not
-result from one of the above expansions are removed.
-
-@node Redirections
-@section Redirections
-@cindex redirection
-
-Before a command is executed, its input and output
-may be @var{redirected}
-using a special notation interpreted by the shell.
-Redirection may also be used to open and close files for the
-current shell execution environment. The following redirection
-operators may precede or appear anywhere within a
-simple command or may follow a command.
-Redirections are processed in the order they appear, from
-left to right.
-
-In the following descriptions, if the file descriptor number is
-omitted, and the first character of the redirection operator is
-@samp{<}, the redirection refers to the standard input (file
-descriptor 0). If the first character of the redirection operator
-is @samp{>}, the redirection refers to the standard output (file
-descriptor 1).
-
-The word following the redirection operator in the following
-descriptions, unless otherwise noted, is subjected to brace expansion,
-tilde expansion, parameter expansion, command substitution, arithmetic
-expansion, quote removal, filename expansion, and word splitting.
-If it expands to more than one word, Bash reports an error.
-
-Note that the order of redirections is significant. For example,
-the command
-@example
-ls > @var{dirlist} 2>&1
-@end example
-@noindent
-directs both standard output (file descriptor 1) and standard error
-(file descriptor 2) to the file @var{dirlist}, while the command
-@example
-ls 2>&1 > @var{dirlist}
-@end example
-@noindent
-directs only the standard output to file @var{dirlist},
-because the standard error was duplicated as standard output
-before the standard output was redirected to @var{dirlist}.
-
-Bash handles several filenames specially when they are used in
-redirections, as described in the following table:
-
-@table @code
-@item /dev/fd/@var{fd}
-If @var{fd} is a valid integer, file descriptor @var{fd} is duplicated.
-
-@item /dev/stdin
-File descriptor 0 is duplicated.
-
-@item /dev/stdout
-File descriptor 1 is duplicated.
-
-@item /dev/stderr
-File descriptor 2 is duplicated.
-
-@item /dev/tcp/@var{host}/@var{port}
-If @var{host} is a valid hostname or Internet address, and @var{port}
-is an integer port number or service name, Bash attempts to open a TCP
-connection to the corresponding socket.
-
-@item /dev/udp/@var{host}/@var{port}
-If @var{host} is a valid hostname or Internet address, and @var{port}
-is an integer port number or service name, Bash attempts to open a UDP
-connection to the corresponding socket.
-
-@end table
-
-A failure to open or create a file causes the redirection to fail.
-
-Redirections using file descriptors greater than 9 should be used with
-care, as they may conflict with file descriptors the shell uses
-internally.
-
-@subsection Redirecting Input
-Redirection of input causes the file whose name results from
-the expansion of @var{word}
-to be opened for reading on file descriptor @code{n},
-or the standard input (file descriptor 0) if @code{n}
-is not specified.
-
-The general format for redirecting input is:
-@example
-[@var{n}]<@var{word}
-@end example
-
-@subsection Redirecting Output
-Redirection of output causes the file whose name results from
-the expansion of @var{word}
-to be opened for writing on file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n}
-is not specified. If the file does not exist it is created;
-if it does exist it is truncated to zero size.
-
-The general format for redirecting output is:
-@example
-[@var{n}]>[|]@var{word}
-@end example
-
-If the redirection operator is @samp{>}, and the @code{noclobber}
-option to the @code{set} builtin has been enabled, the redirection
-will fail if the file whose name results from the expansion of
-@var{word} exists and is a regular file.
-If the redirection operator is @samp{>|}, or the redirection operator is
-@samp{>} and the @code{noclobber} option is not enabled, the redirection
-is attempted even if the file named by @var{word} exists.
-
-@subsection Appending Redirected Output
-Redirection of output in this fashion
-causes the file whose name results from
-the expansion of @var{word}
-to be opened for appending on file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n}
-is not specified. If the file does not exist it is created.
-
-The general format for appending output is:
-@example
-[@var{n}]>>@var{word}
-@end example
-
-@subsection Redirecting Standard Output and Standard Error
-Bash allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be redirected to the file whose name is the
-expansion of @var{word} with this construct.
-
-There are two formats for redirecting standard output and
-standard error:
-@example
-&>@var{word}
-@end example
-@noindent
-and
-@example
->&@var{word}
-@end example
-@noindent
-Of the two forms, the first is preferred.
-This is semantically equivalent to
-@example
->@var{word} 2>&1
-@end example
-
-@subsection Here Documents
-This type of redirection instructs the shell to read input from the
-current source until a line containing only @var{word}
-(with no trailing blanks) is seen. All of
-the lines read up to that point are then used as the standard
-input for a command.
-
-The format of here-documents is:
-@example
-<<[@minus{}]@var{word}
- @var{here-document}
-@var{delimiter}
-@end example
-
-No parameter expansion, command substitution, arithmetic expansion,
-or filename expansion is performed on
-@var{word}. If any characters in @var{word} are quoted, the
-@var{delimiter} is the result of quote removal on @var{word},
-and the lines in the here-document are not expanded.
-If @var{word} is unquoted,
-all lines of the here-document are subjected to parameter expansion,
-command substitution, and arithmetic expansion. In the latter
-case, the character sequence @code{\newline} is ignored, and @samp{\}
-must be used to quote the characters
-@samp{\}, @samp{$}, and @samp{`}.
-
-If the redirection operator is @samp{<<-},
-then all leading tab characters are stripped from input lines and the
-line containing @var{delimiter}.
-This allows here-documents within shell scripts to be indented in a
-natural fashion.
-
-@subsection Here Strings
-A variant of here documents, the format is:
-@example
-<<< @var{word}
-@end example
-
-The @var{word} is expanded and supplied to the command on its standard
-input.
-
-@subsection Duplicating File Descriptors
-The redirection operator
-@example
-[@var{n}]<&@var{word}
-@end example
-@noindent
-is used to duplicate input file descriptors.
-If @var{word}
-expands to one or more digits, the file descriptor denoted by @var{n}
-is made to be a copy of that file descriptor.
-If the digits in @var{word} do not specify a file descriptor open for
-input, a redirection error occurs.
-If @var{word}
-evaluates to @samp{-}, file descriptor @var{n} is closed. If
-@var{n} is not specified, the standard input (file descriptor 0) is used.
-
-The operator
-@example
-[@var{n}]>&@var{word}
-@end example
-@noindent
-is used similarly to duplicate output file descriptors. If
-@var{n} is not specified, the standard output (file descriptor 1) is used.
-If the digits in @var{word} do not specify a file descriptor open for
-output, a redirection error occurs.
-As a special case, if @var{n} is omitted, and @var{word} does not
-expand to one or more digits, the standard output and standard
-error are redirected as described previously.
-
-@subsection Moving File Descriptors
-The redirection operator
-@example
-[@var{n}]<&@var{digit}-
-@end example
-@noindent
-moves the file descriptor @var{digit} to file descriptor @var{n},
-or the standard input (file descriptor 0) if @var{n} is not specified.
-@var{digit} is closed after being duplicated to @var{n}.
-
-Similarly, the redirection operator
-@example
-[@var{n}]>&@var{digit}-
-@end example
-@noindent
-moves the file descriptor @var{digit} to file descriptor @var{n},
-or the standard output (file descriptor 1) if @var{n} is not specified.
-
-@subsection Opening File Descriptors for Reading and Writing
-The redirection operator
-@example
-[@var{n}]<>@var{word}
-@end example
-@noindent
-causes the file whose name is the expansion of @var{word}
-to be opened for both reading and writing on file descriptor
-@var{n}, or on file descriptor 0 if @var{n}
-is not specified. If the file does not exist, it is created.
-
-@node Executing Commands
-@section Executing Commands
-
-@menu
-* Simple Command Expansion:: How Bash expands simple commands before
- executing them.
-* Command Search and Execution:: How Bash finds commands and runs them.
-* Command Execution Environment:: The environment in which Bash
- executes commands that are not
- shell builtins.
-* Environment:: The environment given to a command.
-* Exit Status:: The status returned by commands and how Bash
- interprets it.
-* Signals:: What happens when Bash or a command it runs
- receives a signal.
-@end menu
-
-@node Simple Command Expansion
-@subsection Simple Command Expansion
-@cindex command expansion
-
-When a simple command is executed, the shell performs the following
-expansions, assignments, and redirections, from left to right.
-
-@enumerate
-@item
-The words that the parser has marked as variable assignments (those
-preceding the command name) and redirections are saved for later
-processing.
-
-@item
-The words that are not variable assignments or redirections are
-expanded (@pxref{Shell Expansions}).
-If any words remain after expansion, the first word
-is taken to be the name of the command and the remaining words are
-the arguments.
-
-@item
-Redirections are performed as described above (@pxref{Redirections}).
-
-@item
-The text after the @samp{=} in each variable assignment undergoes tilde
-expansion, parameter expansion, command substitution, arithmetic expansion,
-and quote removal before being assigned to the variable.
-@end enumerate
-
-If no command name results, the variable assignments affect the current
-shell environment. Otherwise, the variables are added to the environment
-of the executed command and do not affect the current shell environment.
-If any of the assignments attempts to assign a value to a readonly variable,
-an error occurs, and the command exits with a non-zero status.
-
-If no command name results, redirections are performed, but do not
-affect the current shell environment. A redirection error causes the
-command to exit with a non-zero status.
-
-If there is a command name left after expansion, execution proceeds as
-described below. Otherwise, the command exits. If one of the expansions
-contained a command substitution, the exit status of the command is
-the exit status of the last command substitution performed. If there
-were no command substitutions, the command exits with a status of zero.
-
-@node Command Search and Execution
-@subsection Command Search and Execution
-@cindex command execution
-@cindex command search
-
-After a command has been split into words, if it results in a
-simple command and an optional list of arguments, the following
-actions are taken.
-
-@enumerate
-@item
-If the command name contains no slashes, the shell attempts to
-locate it. If there exists a shell function by that name, that
-function is invoked as described in @ref{Shell Functions}.
-
-@item
-If the name does not match a function, the shell searches for
-it in the list of shell builtins. If a match is found, that
-builtin is invoked.
-
-@item
-If the name is neither a shell function nor a builtin,
-and contains no slashes, Bash searches each element of
-@env{$PATH} for a directory containing an executable file
-by that name. Bash uses a hash table to remember the full
-pathnames of executable files to avoid multiple @env{PATH} searches
-(see the description of @code{hash} in @ref{Bourne Shell Builtins}).
-A full search of the directories in @env{$PATH}
-is performed only if the command is not found in the hash table.
-If the search is unsuccessful, the shell prints an error
-message and returns an exit status of 127.
-
-@item
-If the search is successful, or if the command name contains
-one or more slashes, the shell executes the named program in
-a separate execution environment.
-Argument 0 is set to the name given, and the remaining arguments
-to the command are set to the arguments supplied, if any.
-
-@item
-If this execution fails because the file is not in executable
-format, and the file is not a directory, it is assumed to be a
-@var{shell script} and the shell executes it as described in
-@ref{Shell Scripts}.
-
-@item
-If the command was not begun asynchronously, the shell waits for
-the command to complete and collects its exit status.
-
-@end enumerate
-
-@node Command Execution Environment
-@subsection Command Execution Environment
-@cindex execution environment
-
-The shell has an @var{execution environment}, which consists of the
-following:
-
-@itemize @bullet
-@item
-open files inherited by the shell at invocation, as modified by
-redirections supplied to the @code{exec} builtin
-
-@item
-the current working directory as set by @code{cd}, @code{pushd}, or
-@code{popd}, or inherited by the shell at invocation
-
-@item
-the file creation mode mask as set by @code{umask} or inherited from
-the shell's parent
-
-@item
-current traps set by @code{trap}
-
-@item
-shell parameters that are set by variable assignment or with @code{set}
-or inherited from the shell's parent in the environment
-
-@item
-shell functions defined during execution or inherited from the shell's
-parent in the environment
-
-@item
-options enabled at invocation (either by default or with command-line
-arguments) or by @code{set}
-
-@item
-options enabled by @code{shopt}
-
-@item
-shell aliases defined with @code{alias} (@pxref{Aliases})
-
-@item
-various process @sc{id}s, including those of background jobs
-(@pxref{Lists}), the value of @code{$$}, and the value of
-@env{$PPID}
-
-@end itemize
-
-When a simple command other than a builtin or shell function
-is to be executed, it
-is invoked in a separate execution environment that consists of
-the following. Unless otherwise noted, the values are inherited
-from the shell.
-
-@itemize @bullet
-@item
-the shell's open files, plus any modifications and additions specified
-by redirections to the command
-
-@item
-the current working directory
-
-@item
-the file creation mode mask
-
-@item
-shell variables and functions marked for export, along with variables
-exported for the command, passed in the environment (@pxref{Environment})
-
-@item
-traps caught by the shell are reset to the values inherited from the
-shell's parent, and traps ignored by the shell are ignored
-
-@end itemize
-
-A command invoked in this separate environment cannot affect the
-shell's execution environment.
-
-Command substitution, commands grouped with parentheses,
-and asynchronous commands are invoked in a
-subshell environment that is a duplicate of the shell environment,
-except that traps caught by the shell are reset to the values
-that the shell inherited from its parent at invocation. Builtin
-commands that are invoked as part of a pipeline are also executed
-in a subshell environment. Changes made to the subshell environment
-cannot affect the shell's execution environment.
-
-If a command is followed by a @samp{&} and job control is not active, the
-default standard input for the command is the empty file @file{/dev/null}.
-Otherwise, the invoked command inherits the file descriptors of the calling
-shell as modified by redirections.
-
-@node Environment
-@subsection Environment
-@cindex environment
-
-When a program is invoked it is given an array of strings
-called the @var{environment}.
-This is a list of name-value pairs, of the form @code{name=value}.
-
-Bash provides several ways to manipulate the environment.
-On invocation, the shell scans its own environment and
-creates a parameter for each name found, automatically marking
-it for @var{export}
-to child processes. Executed commands inherit the environment.
-The @code{export} and @samp{declare -x}
-commands allow parameters and functions to be added to and
-deleted from the environment. If the value of a parameter
-in the environment is modified, the new value becomes part
-of the environment, replacing the old. The environment
-inherited by any executed command consists of the shell's
-initial environment, whose values may be modified in the shell,
-less any pairs removed by the @code{unset} and @samp{export -n}
-commands, plus any additions via the @code{export} and
-@samp{declare -x} commands.
-
-The environment for any simple command
-or function may be augmented temporarily by prefixing it with
-parameter assignments, as described in @ref{Shell Parameters}.
-These assignment statements affect only the environment seen
-by that command.
-
-If the @option{-k} option is set (@pxref{The Set Builtin}), then all
-parameter assignments are placed in the environment for a command,
-not just those that precede the command name.
-
-When Bash invokes an external command, the variable @samp{$_}
-is set to the full path name of the command and passed to that
-command in its environment.
-
-@node Exit Status
-@subsection Exit Status
-@cindex exit status
-
-For the shell's purposes, a command which exits with a
-zero exit status has succeeded.
-A non-zero exit status indicates failure.
-This seemingly counter-intuitive scheme is used so there
-is one well-defined way to indicate success and a variety of
-ways to indicate various failure modes.
-When a command terminates on a fatal signal whose number is @var{N},
-Bash uses the value 128+@var{N} as the exit status.
-
-If a command is not found, the child process created to
-execute it returns a status of 127. If a command is found
-but is not executable, the return status is 126.
-
-If a command fails because of an error during expansion or redirection,
-the exit status is greater than zero.
-
-The exit status is used by the Bash conditional commands
-(@pxref{Conditional Constructs}) and some of the list
-constructs (@pxref{Lists}).
-
-All of the Bash builtins return an exit status of zero if they succeed
-and a non-zero status on failure, so they may be used by the
-conditional and list constructs.
-All builtins return an exit status of 2 to indicate incorrect usage.
-
-@node Signals
-@subsection Signals
-@cindex signal handling
-
-When Bash is interactive, in the absence of any traps, it ignores
-@code{SIGTERM} (so that @samp{kill 0} does not kill an interactive shell),
-and @code{SIGINT}
-is caught and handled (so that the @code{wait} builtin is interruptible).
-When Bash receives a @code{SIGINT}, it breaks out of any executing loops.
-In all cases, Bash ignores @code{SIGQUIT}.
-If job control is in effect (@pxref{Job Control}), Bash
-ignores @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-Non-builtin commands started by Bash have signal handlers set to the
-values inherited by the shell from its parent.
-When job control is not in effect, asynchronous commands
-ignore @code{SIGINT} and @code{SIGQUIT} in addition to these inherited
-handlers.
-Commands run as a result of
-command substitution ignore the keyboard-generated job control signals
-@code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-The shell exits by default upon receipt of a @code{SIGHUP}.
-Before exiting, an interactive shell resends the @code{SIGHUP} to
-all jobs, running or stopped.
-Stopped jobs are sent @code{SIGCONT} to ensure that they receive
-the @code{SIGHUP}.
-To prevent the shell from sending the @code{SIGHUP} signal to a
-particular job, it should be removed
-from the jobs table with the @code{disown}
-builtin (@pxref{Job Control Builtins}) or marked
-to not receive @code{SIGHUP} using @code{disown -h}.
-
-If the @code{huponexit} shell option has been set with @code{shopt}
-(@pxref{Bash Builtins}), Bash sends a @code{SIGHUP} to all jobs when
-an interactive login shell exits.
-
-If Bash is waiting for a command to complete and receives a signal
-for which a trap has been set, the trap will not be executed until
-the command completes.
-When Bash is waiting for an asynchronous
-command via the @code{wait} builtin, the reception of a signal for
-which a trap has been set will cause the @code{wait} builtin to return
-immediately with an exit status greater than 128, immediately after
-which the trap is executed.
-
-@node Shell Scripts
-@section Shell Scripts
-@cindex shell script
-
-A shell script is a text file containing shell commands. When such
-a file is used as the first non-option argument when invoking Bash,
-and neither the @option{-c} nor @option{-s} option is supplied
-(@pxref{Invoking Bash}),
-Bash reads and executes commands from the file, then exits. This
-mode of operation creates a non-interactive shell. The shell first
-searches for the file in the current directory, and looks in the
-directories in @env{$PATH} if not found there.
-
-When Bash runs
-a shell script, it sets the special parameter @code{0} to the name
-of the file, rather than the name of the shell, and the positional
-parameters are set to the remaining arguments, if any are given.
-If no additional arguments are supplied, the positional parameters
-are unset.
-
-A shell script may be made executable by using the @code{chmod} command
-to turn on the execute bit. When Bash finds such a file while
-searching the @env{$PATH} for a command, it spawns a subshell to
-execute it. In other words, executing
-@example
-filename @var{arguments}
-@end example
-@noindent
-is equivalent to executing
-@example
-bash filename @var{arguments}
-@end example
-
-@noindent
-if @code{filename} is an executable shell script.
-This subshell reinitializes itself, so that the effect is as if a
-new shell had been invoked to interpret the script, with the
-exception that the locations of commands remembered by the parent
-(see the description of @code{hash} in @ref{Bourne Shell Builtins})
-are retained by the child.
-
-Most versions of Unix make this a part of the operating system's command
-execution mechanism. If the first line of a script begins with
-the two characters @samp{#!}, the remainder of the line specifies
-an interpreter for the program.
-Thus, you can specify Bash, @code{awk}, Perl, or some other
-interpreter and write the rest of the script file in that language.
-
-The arguments to the interpreter
-consist of a single optional argument following the interpreter
-name on the first line of the script file, followed by the name of
-the script file, followed by the rest of the arguments. Bash
-will perform this action on operating systems that do not handle it
-themselves. Note that some older versions of Unix limit the interpreter
-name and argument to a maximum of 32 characters.
-
-Bash scripts often begin with @code{#! /bin/bash} (assuming that
-Bash has been installed in @file{/bin}), since this ensures that
-Bash will be used to interpret the script, even if it is executed
-under another shell.
-
-@node Shell Builtin Commands
-@chapter Shell Builtin Commands
-
-@menu
-* Bourne Shell Builtins:: Builtin commands inherited from the Bourne
- Shell.
-* Bash Builtins:: Table of builtins specific to Bash.
-* The Set Builtin:: This builtin is so overloaded it
- deserves its own section.
-* Special Builtins:: Builtin commands classified specially by
- POSIX.
-@end menu
-
-Builtin commands are contained within the shell itself.
-When the name of a builtin command is used as the first word of
-a simple command (@pxref{Simple Commands}), the shell executes
-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 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.
-
-Several builtin commands are described in other chapters: builtin
-commands which provide the Bash interface to the job control
-facilities (@pxref{Job Control Builtins}), the directory stack
-(@pxref{Directory Stack Builtins}), the command history
-(@pxref{Bash History Builtins}), and the programmable completion
-facilities (@pxref{Programmable Completion Builtins}).
-
-Many of the builtins have been extended by @sc{posix} or Bash.
-
-Unless otherwise noted, each builtin command documented as accepting
-options preceded by @samp{-} accepts @samp{--}
-to signify the end of the options.
-For example, the @code{:}, @code{true}, @code{false}, and @code{test}
-builtins do not accept options.
-
-@node Bourne Shell Builtins
-@section Bourne Shell Builtins
-
-The following shell builtin commands are inherited from the Bourne Shell.
-These commands are implemented as specified by the @sc{posix} standard.
-
-@table @code
-@item : @r{(a colon)}
-@btindex :
-@example
-: [@var{arguments}]
-@end example
-Do nothing beyond expanding @var{arguments} and performing redirections.
-The return status is zero.
-
-@item . @r{(a period)}
-@btindex .
-@example
-. @var{filename} [@var{arguments}]
-@end example
-Read and execute commands from the @var{filename} argument in the
-current shell context. If @var{filename} does not contain a slash,
-the @env{PATH} variable is used to find @var{filename}.
-When Bash is not in @sc{posix} mode, the current directory is searched
-if @var{filename} is not found in @env{$PATH}.
-If any @var{arguments} are supplied, they become the positional
-parameters when @var{filename} is executed. Otherwise the positional
-parameters are unchanged.
-The return status is the exit status of the last command executed, or
-zero if no commands are executed. If @var{filename} is not found, or
-cannot be read, the return status is non-zero.
-This builtin is equivalent to @code{source}.
-
-@item break
-@btindex break
-@example
-break [@var{n}]
-@end example
-Exit from a @code{for}, @code{while}, @code{until}, or @code{select} loop.
-If @var{n} is supplied, the @var{n}th enclosing loop is exited.
-@var{n} must be greater than or equal to 1.
-The return status is zero unless @var{n} is not greater than or equal to 1.
-
-@item cd
-@btindex cd
-@example
-cd [-L|-P] [@var{directory}]
-@end example
-Change the current working directory to @var{directory}.
-If @var{directory} is not given, the value of the @env{HOME} shell
-variable is used.
-If the shell variable @env{CDPATH} exists, it is used as a search path.
-If @var{directory} begins with a slash, @env{CDPATH} is not used.
-
-The @option{-P} option means to not follow symbolic links; symbolic
-links are followed by default or with the @option{-L} option.
-If @var{directory} is @samp{-}, it is equivalent to @env{$OLDPWD}.
-
-If a non-empty directory name from @env{CDPATH} is used, or if
-@samp{-} is the first argument, and the directory change is
-successful, the absolute pathname of the new working directory is
-written to the standard output.
-
-The return status is zero if the directory is successfully changed,
-non-zero otherwise.
-
-@item continue
-@btindex continue
-@example
-continue [@var{n}]
-@end example
-Resume the next iteration of an enclosing @code{for}, @code{while},
-@code{until}, or @code{select} loop.
-If @var{n} is supplied, the execution of the @var{n}th enclosing loop
-is resumed.
-@var{n} must be greater than or equal to 1.
-The return status is zero unless @var{n} is not greater than or equal to 1.
-
-@item eval
-@btindex eval
-@example
-eval [@var{arguments}]
-@end example
-The arguments are concatenated together into a single command, which is
-then read and executed, and its exit status returned as the exit status
-of @code{eval}.
-If there are no arguments or only empty arguments, the return status is
-zero.
-
-@item exec
-@btindex exec
-@example
-exec [-cl] [-a @var{name}] [@var{command} [@var{arguments}]]
-@end example
-If @var{command}
-is supplied, it replaces the shell without creating a new process.
-If the @option{-l} option is supplied, the shell places a dash at the
-beginning of the zeroth arg passed to @var{command}.
-This is what the @code{login} program does.
-The @option{-c} option causes @var{command} to be executed with an empty
-environment.
-If @option{-a} is supplied, the shell passes @var{name} as the zeroth
-argument to @var{command}.
-If no @var{command} is specified, redirections may be used to affect
-the current shell environment. If there are no redirection errors, the
-return status is zero; otherwise the return status is non-zero.
-
-@item exit
-@btindex exit
-@example
-exit [@var{n}]
-@end example
-Exit the shell, returning a status of @var{n} to the shell's parent.
-If @var{n} is omitted, the exit status is that of the last command executed.
-Any trap on @code{EXIT} is executed before the shell terminates.
-
-@item export
-@btindex export
-@example
-export [-fn] [-p] [@var{name}[=@var{value}]]
-@end example
-Mark each @var{name} to be passed to child processes
-in the environment. If the @option{-f} option is supplied, the @var{name}s
-refer to shell functions; otherwise the names refer to shell variables.
-The @option{-n} option means to no longer mark each @var{name} for export.
-If no @var{names} are supplied, or if the @option{-p} option is given, a
-list of exported names is displayed.
-The @option{-p} option displays output in a form that may be reused as input.
-If a variable name is followed by =@var{value}, the value of
-the variable is set to @var{value}.
-
-The return status is zero unless an invalid option is supplied, one of
-the names is not a valid shell variable name, or @option{-f} is supplied
-with a name that is not a shell function.
-
-@item getopts
-@btindex getopts
-@example
-getopts @var{optstring} @var{name} [@var{args}]
-@end example
-@code{getopts} is used by shell scripts to parse positional parameters.
-@var{optstring} contains the option characters to be recognized; if a
-character is followed by a colon, the option is expected to have an
-argument, which should be separated from it by white space.
-The colon (@samp{:}) and question mark (@samp{?}) may not be
-used as option characters.
-Each time it is invoked, @code{getopts}
-places the next option in the shell variable @var{name}, initializing
-@var{name} if it does not exist,
-and the index of the next argument to be processed into the
-variable @env{OPTIND}.
-@env{OPTIND} is initialized to 1 each time the shell or a shell script
-is invoked.
-When an option requires an argument,
-@code{getopts} places that argument into the variable @env{OPTARG}.
-The shell does not reset @env{OPTIND} automatically; it must be manually
-reset between multiple calls to @code{getopts} within the same shell
-invocation if a new set of parameters is to be used.
-
-When the end of options is encountered, @code{getopts} exits with a
-return value greater than zero.
-@env{OPTIND} is set to the index of the first non-option argument,
-and @code{name} is set to @samp{?}.
-
-@code{getopts}
-normally parses the positional parameters, but if more arguments are
-given in @var{args}, @code{getopts} parses those instead.
-
-@code{getopts} can report errors in two ways. If the first character of
-@var{optstring} is a colon, @var{silent}
-error reporting is used. In normal operation diagnostic messages
-are printed when invalid options or missing option arguments are
-encountered.
-If the variable @env{OPTERR}
-is set to 0, no error messages will be displayed, even if the first
-character of @code{optstring} is not a colon.
-
-If an invalid option is seen,
-@code{getopts} places @samp{?} into @var{name} and, if not silent,
-prints an error message and unsets @env{OPTARG}.
-If @code{getopts} is silent, the option character found is placed in
-@env{OPTARG} and no diagnostic message is printed.
-
-If a required argument is not found, and @code{getopts}
-is not silent, a question mark (@samp{?}) is placed in @var{name},
-@code{OPTARG} is unset, and a diagnostic message is printed.
-If @code{getopts} is silent, then a colon (@samp{:}) is placed in
-@var{name} and @env{OPTARG} is set to the option character found.
-
-@item hash
-@btindex hash
-@example
-hash [-r] [-p @var{filename}] [-dt] [@var{name}]
-@end example
-Remember the full pathnames of commands specified as @var{name} arguments,
-so they need not be searched for on subsequent invocations.
-The commands are found by searching through the directories listed in
-@env{$PATH}.
-The @option{-p} option inhibits the path search, and @var{filename} is
-used as the location of @var{name}.
-The @option{-r} option causes the shell to forget all remembered locations.
-The @option{-d} option causes the shell to forget the remembered location
-of each @var{name}.
-If the @option{-t} option is supplied, the full pathname to which each
-@var{name} corresponds is printed. If multiple @var{name} arguments are
-supplied with @option{-t} the @var{name} is printed before the hashed
-full pathname.
-The @option{-l} option causes output to be displayed in a format
-that may be reused as input.
-If no arguments are given, or if only @option{-l} is supplied,
-information about remembered commands is printed.
-The return status is zero unless a @var{name} is not found or an invalid
-option is supplied.
-
-@item pwd
-@btindex pwd
-@example
-pwd [-LP]
-@end example
-Print the absolute pathname of the current working directory.
-If the @option{-P} option is supplied, the pathname printed will not
-contain symbolic links.
-If the @option{-L} option is supplied, the pathname printed may contain
-symbolic links.
-The return status is zero unless an error is encountered while
-determining the name of the current directory or an invalid option
-is supplied.
-
-@item readonly
-@btindex readonly
-@example
-readonly [-apf] [@var{name}[=@var{value}]] @dots{}
-@end example
-Mark each @var{name} as readonly.
-The values of these names may not be changed by subsequent assignment.
-If the @option{-f} option is supplied, each @var{name} refers to a shell
-function.
-The @option{-a} option means each @var{name} refers to an array variable.
-If no @var{name} arguments are given, or if the @option{-p}
-option is supplied, a list of all readonly names is printed.
-The @option{-p} option causes output to be displayed in a format that
-may be reused as input.
-If a variable name is followed by =@var{value}, the value of
-the variable is set to @var{value}.
-The return status is zero unless an invalid option is supplied, one of
-the @var{name} arguments is not a valid shell variable or function name,
-or the @option{-f} option is supplied with a name that is not a shell function.
-
-@item return
-@btindex return
-@example
-return [@var{n}]
-@end example
-Cause a shell function to exit with the return value @var{n}.
-If @var{n} is not supplied, the return value is the exit status of the
-last command executed in the function.
-This may also be used to terminate execution of a script being executed
-with the @code{.} (or @code{source}) builtin, returning either @var{n} or
-the exit status of the last command executed within the script as the exit
-status of the script.
-Any command associated with the @code{RETURN} trap is executed
-before execution resumes after the function or script.
-The return status is non-zero if @code{return} is used outside a function
-and not during the execution of a script by @code{.} or @code{source}.
-
-@item shift
-@btindex shift
-@example
-shift [@var{n}]
-@end example
-Shift the positional parameters to the left by @var{n}.
-The positional parameters from @var{n}+1 @dots{} @code{$#} are
-renamed to @code{$1} @dots{} @code{$#}-@var{n}+1.
-Parameters represented by the numbers @code{$#} to @var{n}+1 are unset.
-@var{n} must be a non-negative number less than or equal to @code{$#}.
-If @var{n} is zero or greater than @code{$#}, the positional parameters
-are not changed.
-If @var{n} is not supplied, it is assumed to be 1.
-The return status is zero unless @var{n} is greater than @code{$#} or
-less than zero, non-zero otherwise.
-
-@item test
-@itemx [
-@btindex test
-@btindex [
-Evaluate a conditional expression @var{expr}.
-Each operator and operand must be a separate argument.
-Expressions are composed of the primaries described below in
-@ref{Bash Conditional Expressions}.
-@code{test} does not accept any options, nor does it accept and ignore
-an argument of @option{--} as signifying the end of options.
-
-When the @code{[} form is used, the last argument to the command must
-be a @code{]}.
-
-Expressions may be combined using the following operators, listed in
-decreasing order of precedence.
-
-@table @code
-@item ! @var{expr}
-True if @var{expr} is false.
-
-@item ( @var{expr} )
-Returns the value of @var{expr}.
-This may be used to override the normal precedence of operators.
-
-@item @var{expr1} -a @var{expr2}
-True if both @var{expr1} and @var{expr2} are true.
-
-@item @var{expr1} -o @var{expr2}
-True if either @var{expr1} or @var{expr2} is true.
-@end table
-
-The @code{test} and @code{[} builtins evaluate conditional
-expressions using a set of rules based on the number of arguments.
-
-@table @asis
-@item 0 arguments
-The expression is false.
-
-@item 1 argument
-The expression is true if and only if the argument is not null.
-
-@item 2 arguments
-If the first argument is @samp{!}, the expression is true if and
-only if the second argument is null.
-If the first argument is one of the unary conditional operators
-(@pxref{Bash Conditional Expressions}), the expression
-is true if the unary test is true.
-If the first argument is not a valid unary operator, the expression is
-false.
-
-@item 3 arguments
-If the second argument is one of the binary conditional
-operators (@pxref{Bash Conditional Expressions}), the
-result of the expression is the result of the binary test using the
-first and third arguments as operands.
-If the first argument is @samp{!}, the value is the negation of
-the two-argument test using the second and third arguments.
-If the first argument is exactly @samp{(} and the third argument is
-exactly @samp{)}, the result is the one-argument test of the second
-argument.
-Otherwise, the expression is false.
-The @samp{-a} and @samp{-o} operators are considered binary operators
-in this case.
-
-@item 4 arguments
-If the first argument is @samp{!}, the result is the negation of
-the three-argument expression composed of the remaining arguments.
-Otherwise, the expression is parsed and evaluated according to
-precedence using the rules listed above.
-
-@item 5 or more arguments
-The expression is parsed and evaluated according to precedence
-using the rules listed above.
-@end table
-
-@item times
-@btindex times
-@example
-times
-@end example
-Print out the user and system times used by the shell and its children.
-The return status is zero.
-
-@item trap
-@btindex trap
-@example
-trap [-lp] [@var{arg}] [@var{sigspec} @dots{}]
-@end example
-The commands in @var{arg} are to be read and executed when the
-shell receives signal @var{sigspec}. If @var{arg} is absent (and
-there is a single @var{sigspec}) or
-equal to @samp{-}, each specified signal's disposition is reset
-to the value it had when the shell was started.
-If @var{arg} is the null string, then the signal specified by
-each @var{sigspec} is ignored by the shell and commands it invokes.
-If @var{arg} is not present and @option{-p} has been supplied,
-the shell displays the trap commands associated with each @var{sigspec}.
-If no arguments are supplied, or
-only @option{-p} is given, @code{trap} prints the list of commands
-associated with each signal number in a form that may be reused as
-shell input.
-The @option{-l} option causes the shell to print a list of signal names
-and their corresponding numbers.
-Each @var{sigspec} is either a signal name or a signal number.
-Signal names are case insensitive and the @code{SIG} prefix is optional.
-If a @var{sigspec}
-is @code{0} or @code{EXIT}, @var{arg} is executed when the shell exits.
-If a @var{sigspec} is @code{DEBUG}, the command @var{arg} is executed
-before every simple command, @code{for} command, @code{case} command,
-@code{select} command, every arithmetic @code{for} command, and before
-the first command executes in a shell function.
-Refer to the description of the @code{extglob} option to the
-@code{shopt} builtin (@pxref{Bash Builtins}) for details of its
-effect on the @code{DEBUG} trap.
-If a @var{sigspec} is @code{ERR}, the command @var{arg}
-is executed whenever a simple command has a non-zero exit status,
-subject to the following conditions.
-The @code{ERR} trap is not executed if the failed command is part of the
-command list immediately following an @code{until} or @code{while} keyword,
-part of the test in an @code{if} statement,
-part of a @code{&&} or @code{||} list, or if the command's return
-status is being inverted using @code{!}.
-These are the same conditions obeyed by the @code{errexit} option.
-If a @var{sigspec} is @code{RETURN}, the command @var{arg} is executed
-each time a shell function or a script executed with the @code{.} or
-@code{source} builtins finishes executing.
-
-Signals ignored upon entry to the shell cannot be trapped or reset.
-Trapped signals that are not being ignored are reset to their original
-values in a child process when it is created.
-
-The return status is zero unless a @var{sigspec} does not specify a
-valid signal.
-
-@item umask
-@btindex umask
-@example
-umask [-p] [-S] [@var{mode}]
-@end example
-Set the shell process's file creation mask to @var{mode}. If
-@var{mode} begins with a digit, it is interpreted as an octal number;
-if not, it is interpreted as a symbolic mode mask similar
-to that accepted by the @code{chmod} command. If @var{mode} is
-omitted, the current value of the mask is printed. If the @option{-S}
-option is supplied without a @var{mode} argument, the mask is printed
-in a symbolic format.
-If the @option{-p} option is supplied, and @var{mode}
-is omitted, the output is in a form that may be reused as input.
-The return status is zero if the mode is successfully changed or if
-no @var{mode} argument is supplied, and non-zero otherwise.
-
-Note that when the mode is interpreted as an octal number, each number
-of the umask is subtracted from @code{7}. Thus, a umask of @code{022}
-results in permissions of @code{755}.
-
-@item unset
-@btindex unset
-@example
-unset [-fv] [@var{name}]
-@end example
-Each variable or function @var{name} is removed.
-If no options are supplied, or the @option{-v} option is given, each
-@var{name} refers to a shell variable.
-If the @option{-f} option is given, the @var{name}s refer to shell
-functions, and the function definition is removed.
-Readonly variables and functions may not be unset.
-The return status is zero unless a @var{name} is readonly.
-@end table
-
-@node Bash Builtins
-@section Bash Builtin Commands
-
-This section describes builtin commands which are unique to
-or have been extended in Bash.
-Some of these commands are specified in the @sc{posix} standard.
-
-@table @code
-
-@item alias
-@btindex alias
-@example
-alias [@code{-p}] [@var{name}[=@var{value}] @dots{}]
-@end example
-
-Without arguments or with the @option{-p} option, @code{alias} prints
-the list of aliases on the standard output in a form that allows
-them to be reused as input.
-If arguments are supplied, an alias is defined for each @var{name}
-whose @var{value} is given. If no @var{value} is given, the name
-and value of the alias is printed.
-Aliases are described in @ref{Aliases}.
-
-@item bind
-@btindex bind
-@example
-bind [-m @var{keymap}] [-lpsvPSV]
-bind [-m @var{keymap}] [-q @var{function}] [-u @var{function}] [-r @var{keyseq}]
-bind [-m @var{keymap}] -f @var{filename}
-bind [-m @var{keymap}] -x @var{keyseq:shell-command}
-bind [-m @var{keymap}] @var{keyseq:function-name}
-bind @var{readline-command}
-@end example
-
-Display current Readline (@pxref{Command Line Editing})
-key and function bindings,
-bind a key sequence to a Readline function or macro,
-or set a Readline variable.
-Each non-option argument is a command as it would appear in a
-a Readline initialization file (@pxref{Readline Init File}),
-but each binding or command must be passed as a separate argument; e.g.,
-@samp{"\C-x\C-r":re-read-init-file}.
-Options, if supplied, have the following meanings:
-
-@table @code
-@item -m @var{keymap}
-Use @var{keymap} as the keymap to be affected by
-the subsequent bindings. Acceptable @var{keymap}
-names are
-@code{emacs},
-@code{emacs-standard},
-@code{emacs-meta},
-@code{emacs-ctlx},
-@code{vi},
-@code{vi-move},
-@code{vi-command}, and
-@code{vi-insert}.
-@code{vi} is equivalent to @code{vi-command};
-@code{emacs} is equivalent to @code{emacs-standard}.
-
-@item -l
-List the names of all Readline functions.
-
-@item -p
-Display Readline function names and bindings in such a way that they
-can be used as input or in a Readline initialization file.
-
-@item -P
-List current Readline function names and bindings.
-
-@item -v
-Display Readline variable names and values in such a way that they
-can be used as input or in a Readline initialization file.
-
-@item -V
-List current Readline variable names and values.
-
-@item -s
-Display Readline key sequences bound to macros and the strings they output
-in such a way that they can be used as input or in a Readline
-initialization file.
-
-@item -S
-Display Readline key sequences bound to macros and the strings they output.
-
-@item -f @var{filename}
-Read key bindings from @var{filename}.
-
-@item -q @var{function}
-Query about which keys invoke the named @var{function}.
-
-@item -u @var{function}
-Unbind all keys bound to the named @var{function}.
-
-@item -r @var{keyseq}
-Remove any current binding for @var{keyseq}.
-
-@item -x @var{keyseq:shell-command}
-Cause @var{shell-command} to be executed whenever @var{keyseq} is
-entered.
-
-@end table
-
-@noindent
-The return status is zero unless an invalid option is supplied or an
-error occurs.
-
-@item builtin
-@btindex builtin
-@example
-builtin [@var{shell-builtin} [@var{args}]]
-@end example
-Run a shell builtin, passing it @var{args}, and return its exit status.
-This is useful when defining a shell function with the same
-name as a shell builtin, retaining the functionality of the builtin within
-the function.
-The return status is non-zero if @var{shell-builtin} is not a shell
-builtin command.
-
-@item caller
-@btindex caller
-@example
-caller [@var{expr}]
-@end example
-Returns the context of any active subroutine call (a shell function or
-a script executed with the @code{.} or @code{source} builtins).
-
-Without @var{expr}, @code{caller} displays the line number and source
-filename of the current subroutine call.
-If a non-negative integer is supplied as @var{expr}, @code{caller}
-displays the line number, subroutine name, and source file corresponding
-to that position in the current execution call stack. This extra
-information may be used, for example, to print a stack trace. The
-current frame is frame 0.
-
-The return value is 0 unless the shell is not executing a subroutine
-call or @var{expr} does not correspond to a valid position in the
-call stack.
-
-@item command
-@btindex command
-@example
-command [-pVv] @var{command} [@var{arguments} @dots{}]
-@end example
-Runs @var{command} with @var{arguments} ignoring any shell function
-named @var{command}.
-Only shell builtin commands or commands found by searching the
-@env{PATH} are executed.
-If there is a shell function named @code{ls}, running @samp{command ls}
-within the function will execute the external command @code{ls}
-instead of calling the function recursively.
-The @option{-p} option means to use a default value for @env{PATH}
-that is guaranteed to find all of the standard utilities.
-The return status in this case is 127 if @var{command} cannot be
-found or an error occurred, and the exit status of @var{command}
-otherwise.
-
-If either the @option{-V} or @option{-v} option is supplied, a
-description of @var{command} is printed. The @option{-v} option
-causes a single word indicating the command or file name used to
-invoke @var{command} to be displayed; the @option{-V} option produces
-a more verbose description. In this case, the return status is
-zero if @var{command} is found, and non-zero if not.
-
-@item declare
-@btindex declare
-@example
-declare [-afFirtx] [-p] [@var{name}[=@var{value}] @dots{}]
-@end example
-
-Declare variables and give them attributes. If no @var{name}s
-are given, then display the values of variables instead.
-
-The @option{-p} option will display the attributes and values of each
-@var{name}.
-When @option{-p} is used, additional options are ignored.
-The @option{-F} option inhibits the display of function definitions;
-only the function name and attributes are printed.
-If the @code{extdebug} shell option is enabled using @code{shopt}
-(@pxref{Bash Builtins}), the source file name and line number where
-the function is defined are displayed as well.
-@option{-F} implies @option{-f}.
-The following options can be used to restrict output to variables with
-the specified attributes or to give variables attributes:
-
-@table @code
-@item -a
-Each @var{name} is an array variable (@pxref{Arrays}).
-
-@item -f
-Use function names only.
-
-@item -i
-The variable is to be treated as
-an integer; arithmetic evaluation (@pxref{Shell Arithmetic}) is
-performed when the variable is assigned a value.
-
-@item -r
-Make @var{name}s readonly. These names cannot then be assigned values
-by subsequent assignment statements or unset.
-
-@item -t
-Give each @var{name} the @code{trace} attribute.
-Traced functions inherit the @code{DEBUG} and @code{RETURN} traps from
-the calling shell.
-The trace attribute has no special meaning for variables.
-
-@item -x
-Mark each @var{name} for export to subsequent commands via
-the environment.
-@end table
-
-Using @samp{+} instead of @samp{-} turns off the attribute instead.
-When used in a function, @code{declare} makes each @var{name} local,
-as with the @code{local} command. If a variable name is followed by
-=@var{value}, the value of the variable is set to @var{value}.
-
-The return status is zero unless an invalid option is encountered,
-an attempt is made to define a function using @samp{-f foo=bar},
-an attempt is made to assign a value to a readonly variable,
-an attempt is made to assign a value to an array variable without
-using the compound assignment syntax (@pxref{Arrays}),
-one of the @var{names} is not a valid shell variable name,
-an attempt is made to turn off readonly status for a readonly variable,
-an attempt is made to turn off array status for an array variable,
-or an attempt is made to display a non-existent function with @option{-f}.
-
-@item echo
-@btindex echo
-@example
-echo [-neE] [@var{arg} @dots{}]
-@end example
-Output the @var{arg}s, separated by spaces, terminated with a
-newline.
-The return status is always 0.
-If @option{-n} is specified, the trailing newline is suppressed.
-If the @option{-e} option is given, interpretation of the following
-backslash-escaped characters is enabled.
-The @option{-E} option disables the interpretation of these escape characters,
-even on systems where they are interpreted by default.
-The @code{xpg_echo} shell option may be used to
-dynamically determine whether or not @code{echo} expands these
-escape characters by default.
-@code{echo} does not interpret @option{--} to mean the end of options.
-
-@code{echo} interprets the following escape sequences:
-@table @code
-@item \a
-alert (bell)
-@item \b
-backspace
-@item \c
-suppress trailing newline
-@item \e
-escape
-@item \f
-form feed
-@item \n
-new line
-@item \r
-carriage return
-@item \t
-horizontal tab
-@item \v
-vertical tab
-@item \\
-backslash
-@item \0@var{nnn}
-the eight-bit character whose value is the octal value @var{nnn}
-(zero to three octal digits)
-@item \@var{nnn}
-the eight-bit character whose value is the octal value @var{nnn}
-(one to three octal digits)
-@item \x@var{HH}
-the eight-bit character whose value is the hexadecimal value @var{HH}
-(one or two hex digits)
-@end table
-
-@item enable
-@btindex enable
-@example
-enable [-n] [-p] [-f @var{filename}] [-ads] [@var{name} @dots{}]
-@end example
-Enable and disable builtin shell commands.
-Disabling a builtin allows a disk command which has the same name
-as a shell builtin to be executed without specifying a full pathname,
-even though the shell normally searches for builtins before disk commands.
-If @option{-n} is used, the @var{name}s become disabled. Otherwise
-@var{name}s are enabled. For example, to use the @code{test} binary
-found via @env{$PATH} instead of the shell builtin version, type
-@samp{enable -n test}.
-
-If the @option{-p} option is supplied, or no @var{name} arguments appear,
-a list of shell builtins is printed. With no other arguments, the list
-consists of all enabled shell builtins.
-The @option{-a} option means to list
-each builtin with an indication of whether or not it is enabled.
-
-The @option{-f} option means to load the new builtin command @var{name}
-from shared object @var{filename}, on systems that support dynamic loading.
-The @option{-d} option will delete a builtin loaded with @option{-f}.
-
-If there are no options, a list of the shell builtins is displayed.
-The @option{-s} option restricts @code{enable} to the @sc{posix} special
-builtins. If @option{-s} is used with @option{-f}, the new builtin becomes
-a special builtin (@pxref{Special Builtins}).
-
-The return status is zero unless a @var{name} is not a shell builtin
-or there is an error loading a new builtin from a shared object.
-
-@item help
-@btindex help
-@example
-help [-s] [@var{pattern}]
-@end example
-Display helpful information about builtin commands.
-If @var{pattern} is specified, @code{help} gives detailed help
-on all commands matching @var{pattern}, otherwise a list of
-the builtins is printed.
-The @option{-s} option restricts the information displayed to a short
-usage synopsis.
-The return status is zero unless no command matches @var{pattern}.
-
-@item let
-@btindex let
-@example
-let @var{expression} [@var{expression}]
-@end example
-The @code{let} builtin allows arithmetic to be performed on shell
-variables. Each @var{expression} is evaluated according to the
-rules given below in @ref{Shell Arithmetic}. If the
-last @var{expression} evaluates to 0, @code{let} returns 1;
-otherwise 0 is returned.
-
-@item local
-@btindex local
-@example
-local [@var{option}] @var{name}[=@var{value}] @dots{}
-@end example
-For each argument, a local variable named @var{name} is created,
-and assigned @var{value}.
-The @var{option} can be any of the options accepted by @code{declare}.
-@code{local} can only be used within a function; it makes the variable
-@var{name} have a visible scope restricted to that function and its
-children. The return status is zero unless @code{local} is used outside
-a function, an invalid @var{name} is supplied, or @var{name} is a
-readonly variable.
-
-@item logout
-@btindex logout
-@example
-logout [@var{n}]
-@end example
-Exit a login shell, returning a status of @var{n} to the shell's
-parent.
-
-@item printf
-@btindex printf
-@example
-@code{printf} [-v @var{var}] @var{format} [@var{arguments}]
-@end example
-Write the formatted @var{arguments} to the standard output under the
-control of the @var{format}.
-The @var{format} is a character string which contains three types of objects:
-plain characters, which are simply copied to standard output, character
-escape sequences, which are converted and copied to the standard output, and
-format specifications, each of which causes printing of the next successive
-@var{argument}.
-In addition to the standard @code{printf(1)} formats, @samp{%b} causes
-@code{printf} to expand backslash escape sequences in the corresponding
-@var{argument},
-(except that @samp{\c} terminates output, backslashes in
-@samp{\'}, @samp{\"}, and @samp{\?} are not removed, and octal escapes
-beginning with @samp{\0} may contain up to four digits),
-and @samp{%q} causes @code{printf} to output the
-corresponding @var{argument} in a format that can be reused as shell input.
-
-The @option{-v} option causes the output to be assigned to the variable
-@var{var} rather than being printed to the standard output.
-
-The @var{format} is reused as necessary to consume all of the @var{arguments}.
-If the @var{format} requires more @var{arguments} than are supplied, the
-extra format specifications behave as if a zero value or null string, as
-appropriate, had been supplied. The return value is zero on success,
-non-zero on failure.
-
-@item read
-@btindex read
-@example
-read [-ers] [-a @var{aname}] [-d @var{delim}] [-n @var{nchars}] [-p @var{prompt}] [-t @var{timeout}] [-u @var{fd}] [@var{name} @dots{}]
-@end example
-One line is read from the standard input, or from the file descriptor
-@var{fd} supplied as an argument to the @option{-u} option, and the first word
-is assigned to the first @var{name}, the second word to the second @var{name},
-and so on, with leftover words and their intervening separators assigned
-to the last @var{name}.
-If there are fewer words read from the input stream than names,
-the remaining names are assigned empty values.
-The characters in the value of the @env{IFS} variable
-are used to split the line into words.
-The backslash character @samp{\} may be used to remove any special
-meaning for the next character read and for line continuation.
-If no names are supplied, the line read is assigned to the
-variable @env{REPLY}.
-The return code is zero, unless end-of-file is encountered, @code{read}
-times out, or an invalid file descriptor is supplied as the argument to
-@option{-u}.
-Options, if supplied, have the following meanings:
-
-@table @code
-@item -a @var{aname}
-The words are assigned to sequential indices of the array variable
-@var{aname}, starting at 0.
-All elements are removed from @var{aname} before the assignment.
-Other @var{name} arguments are ignored.
-
-@item -d @var{delim}
-The first character of @var{delim} is used to terminate the input line,
-rather than newline.
-
-@item -e
-Readline (@pxref{Command Line Editing}) is used to obtain the line.
-
-@item -n @var{nchars}
-@code{read} returns after reading @var{nchars} characters rather than
-waiting for a complete line of input.
-
-@item -p @var{prompt}
-Display @var{prompt}, without a trailing newline, before attempting
-to read any input.
-The prompt is displayed only if input is coming from a terminal.
-
-@item -r
-If this option is given, backslash does not act as an escape character.
-The backslash is considered to be part of the line.
-In particular, a backslash-newline pair may not be used as a line
-continuation.
-
-@item -s
-Silent mode. If input is coming from a terminal, characters are
-not echoed.
-
-@item -t @var{timeout}
-Cause @code{read} to time out and return failure if a complete line of
-input is not read within @var{timeout} seconds.
-This option has no effect if @code{read} is not reading input from the
-terminal or a pipe.
-
-@item -u @var{fd}
-Read input from file descriptor @var{fd}.
-
-@end table
-
-@item shopt
-@btindex shopt
-@example
-shopt [-pqsu] [-o] [@var{optname} @dots{}]
-@end example
-Toggle the values of variables controlling optional shell behavior.
-With no options, or with the @option{-p} option, a list of all settable
-options is displayed, with an indication of whether or not each is set.
-The @option{-p} option causes output to be displayed in a form that
-may be reused as input.
-Other options have the following meanings:
-
-@table @code
-@item -s
-Enable (set) each @var{optname}.
-
-@item -u
-Disable (unset) each @var{optname}.
-
-@item -q
-Suppresses normal output; the return status
-indicates whether the @var{optname} is set or unset.
-If multiple @var{optname} arguments are given with @option{-q},
-the return status is zero if all @var{optnames} are enabled;
-non-zero otherwise.
-
-@item -o
-Restricts the values of
-@var{optname} to be those defined for the @option{-o} option to the
-@code{set} builtin (@pxref{The Set Builtin}).
-@end table
-
-If either @option{-s} or @option{-u}
-is used with no @var{optname} arguments, the display is limited to
-those options which are set or unset, respectively.
-
-Unless otherwise noted, the @code{shopt} options are disabled (off)
-by default.
-
-The return status when listing options is zero if all @var{optnames}
-are enabled, non-zero otherwise. When setting or unsetting options,
-the return status is zero unless an @var{optname} is not a valid shell
-option.
-
-The list of @code{shopt} options is:
-@table @code
-@item cdable_vars
-If this is set, an argument to the @code{cd}
-builtin command that
-is not a directory is assumed to be the name of a variable whose
-value is the directory to change to.
-
-@item cdspell
-If set, minor errors in the spelling of a directory component in a
-@code{cd} command will be corrected.
-The errors checked for are transposed characters,
-a missing character, and a character too many.
-If a correction is found, the corrected path is printed,
-and the command proceeds.
-This option is only used by interactive shells.
-
-@item checkhash
-If this is set, Bash checks that a command found in the hash
-table exists before trying to execute it. If a hashed command no
-longer exists, a normal path search is performed.
-
-@item checkwinsize
-If set, Bash checks the window size after each command
-and, if necessary, updates the values of
-@env{LINES} and @env{COLUMNS}.
-
-@item cmdhist
-If set, Bash
-attempts to save all lines of a multiple-line
-command in the same history entry. This allows
-easy re-editing of multi-line commands.
-
-@item dotglob
-If set, Bash includes filenames beginning with a `.' in
-the results of filename expansion.
-
-@item execfail
-If this is set, a non-interactive shell will not exit if
-it cannot execute the file specified as an argument to the @code{exec}
-builtin command. An interactive shell does not exit if @code{exec}
-fails.
-
-@item expand_aliases
-If set, aliases are expanded as described below under Aliases,
-@ref{Aliases}.
-This option is enabled by default for interactive shells.
-
-@item extdebug
-If set, behavior intended for use by debuggers is enabled:
-
-@enumerate
-@item
-The @option{-F} option to the @code{declare} builtin (@pxref{Bash Builtins})
-displays the source file name and line number corresponding to each function
-name supplied as an argument.
-
-@item
-If the command run by the @code{DEBUG} trap returns a non-zero value, the
-next command is skipped and not executed.
-
-@item
-If the command run by the @code{DEBUG} trap returns a value of 2, and the
-shell is executing in a subroutine (a shell function or a shell script
-executed by the @code{.} or @code{source} builtins), a call to
-@code{return} is simulated.
-
-@item
-@code{BASH_ARGC} and @code{BASH_ARGV} are updated as described in their
-descriptions (@pxref{Bash Variables}).
-
-@item
-Function tracing is enabled: command substitution, shell functions, and
-subshells invoked with @code{( @var{command} )} inherit the
-@code{DEBUG} and @code{RETURN} traps.
-
-@item
-Error tracing is enabled: command substitution, shell functions, and
-subshells invoked with @code{( @var{command} )} inherit the
-@code{ERROR} trap.
-@end enumerate
-
-@item extglob
-If set, the extended pattern matching features described above
-(@pxref{Pattern Matching}) are enabled.
-
-@item extquote
-If set, @code{$'@var{string}'} and @code{$"@var{string}"} quoting is
-performed within @code{$@{@var{parameter}@}} expansions
-enclosed in double quotes. This option is enabled by default.
-
-@item failglob
-If set, patterns which fail to match filenames during pathname expansion
-result in an expansion error.
-
-@item force_fignore
-If set, the suffixes specified by the @env{FIGNORE} shell variable
-cause words to be ignored when performing word completion even if
-the ignored words are the only possible completions.
-@xref{Bash Variables}, for a description of @env{FIGNORE}.
-This option is enabled by default.
-
-@item gnu_errfmt
-If set, shell error messages are written in the standard @sc{gnu} error
-message format.
-
-@item histappend
-If set, the history list is appended to the file named by the value
-of the @env{HISTFILE}
-variable when the shell exits, rather than overwriting the file.
-
-@item histreedit
-If set, and Readline
-is being used, a user is given the opportunity to re-edit a
-failed history substitution.
-
-@item histverify
-If set, and Readline
-is being used, the results of history substitution are not immediately
-passed to the shell parser. Instead, the resulting line is loaded into
-the Readline editing buffer, allowing further modification.
-
-@item hostcomplete
-If set, and Readline is being used, Bash will attempt to perform
-hostname completion when a word containing a @samp{@@} is being
-completed (@pxref{Commands For Completion}). This option is enabled
-by default.
-
-@item huponexit
-If set, Bash will send @code{SIGHUP} to all jobs when an interactive
-login shell exits (@pxref{Signals}).
-
-@item interactive_comments
-Allow a word beginning with @samp{#}
-to cause that word and all remaining characters on that
-line to be ignored in an interactive shell.
-This option is enabled by default.
-
-@item lithist
-If enabled, and the @code{cmdhist}
-option is enabled, multi-line commands are saved to the history with
-embedded newlines rather than using semicolon separators where possible.
-
-@item login_shell
-The shell sets this option if it is started as a login shell
-(@pxref{Invoking Bash}).
-The value may not be changed.
-
-@item mailwarn
-If set, and a file that Bash is checking for mail has been
-accessed since the last time it was checked, the message
-@code{"The mail in @var{mailfile} has been read"} is displayed.
-
-@item no_empty_cmd_completion
-If set, and Readline is being used, Bash will not attempt to search
-the @env{PATH} for possible completions when completion is attempted
-on an empty line.
-
-@item nocaseglob
-If set, Bash matches filenames in a case-insensitive fashion when
-performing filename expansion.
-
-@item nocasematch
-If set, Bash matches patterns in a case-insensitive fashion when
-performing matching while executing @code{case} or @code{[[}
-conditional commands.
-
-@item nullglob
-If set, Bash allows filename patterns which match no
-files to expand to a null string, rather than themselves.
-
-@item progcomp
-If set, the programmable completion facilities
-(@pxref{Programmable Completion}) are enabled.
-This option is enabled by default.
-
-@item promptvars
-If set, prompt strings undergo
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal after being expanded
-as described below (@pxref{Printing a Prompt}).
-This option is enabled by default.
-
-@item restricted_shell
-The shell sets this option if it is started in restricted mode
-(@pxref{The Restricted Shell}).
-The value may not be changed.
-This is not reset when the startup files are executed, allowing
-the startup files to discover whether or not a shell is restricted.
-
-@item shift_verbose
-If this is set, the @code{shift}
-builtin prints an error message when the shift count exceeds the
-number of positional parameters.
-
-@item sourcepath
-If set, the @code{source} builtin uses the value of @env{PATH}
-to find the directory containing the file supplied as an argument.
-This option is enabled by default.
-
-@item xpg_echo
-If set, the @code{echo} builtin expands backslash-escape sequences
-by default.
-
-@end table
-
-@noindent
-The return status when listing options is zero if all @var{optnames}
-are enabled, non-zero otherwise.
-When setting or unsetting options, the return status is zero unless an
-@var{optname} is not a valid shell option.
-
-@item source
-@btindex source
-@example
-source @var{filename}
-@end example
-A synonym for @code{.} (@pxref{Bourne Shell Builtins}).
-
-@item type
-@btindex type
-@example
-type [-afptP] [@var{name} @dots{}]
-@end example
-For each @var{name}, indicate how it would be interpreted if used as a
-command name.
-
-If the @option{-t} option is used, @code{type} prints a single word
-which is one of @samp{alias}, @samp{function}, @samp{builtin},
-@samp{file} or @samp{keyword},
-if @var{name} is an alias, shell function, shell builtin,
-disk file, or shell reserved word, respectively.
-If the @var{name} is not found, then nothing is printed, and
-@code{type} returns a failure status.
-
-If the @option{-p} option is used, @code{type} either returns the name
-of the disk file that would be executed, or nothing if @option{-t}
-would not return @samp{file}.
-
-The @option{-P} option forces a path search for each @var{name}, even if
-@option{-t} would not return @samp{file}.
-
-If a command is hashed, @option{-p} and @option{-P} print the hashed value,
-not necessarily the file that appears first in @code{$PATH}.
-
-If the @option{-a} option is used, @code{type} returns all of the places
-that contain an executable named @var{file}.
-This includes aliases and functions, if and only if the @option{-p} option
-is not also used.
-
-If the @option{-f} option is used, @code{type} does not attempt to find
-shell functions, as with the @code{command} builtin.
-
-The return status is zero if any of the @var{names} are found, non-zero
-if none are found.
-
-@item typeset
-@btindex typeset
-@example
-typeset [-afFrxi] [-p] [@var{name}[=@var{value}] @dots{}]
-@end example
-The @code{typeset} command is supplied for compatibility with the Korn
-shell; however, it has been deprecated in favor of the @code{declare}
-builtin command.
-
-@item ulimit
-@btindex ulimit
-@example
-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
-option is given, it is interpreted as follows:
-@table @code
-@item -S
-Change and report the soft limit associated with a resource.
-
-@item -H
-Change and report the hard limit associated with a resource.
-
-@item -a
-All current limits are reported.
-
-@item -c
-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 written by the shell and its children.
-
-@item -i
-The maximum number of pending signals.
-
-@item -l
-The maximum size that may be locked into memory.
-
-@item -m
-The maximum resident set size.
-
-@item -n
-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.
-
-@item -t
-The maximum amount of cpu time in seconds.
-
-@item -u
-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;
-the special @var{limit} values @code{hard}, @code{soft}, and
-@code{unlimited} stand for the current hard limit, the current soft limit,
-and no limit, respectively.
-Otherwise, the current value of the soft limit for the specified resource
-is printed, unless the @option{-H} option is supplied.
-When setting new limits, if neither @option{-H} nor @option{-S} is supplied,
-both the hard and soft limits are set.
-If no option is given, then @option{-f} is assumed. Values are in 1024-byte
-increments, except for @option{-t}, which is in seconds, @option{-p},
-which is in units of 512-byte blocks, and @option{-n} and @option{-u}, which
-are unscaled values.
-
-The return status is zero unless an invalid option or argument is supplied,
-or an error occurs while setting a new limit.
-
-@item unalias
-@btindex unalias
-@example
-unalias [-a] [@var{name} @dots{} ]
-@end example
-
-Remove each @var{name} from the list of aliases. If @option{-a} is
-supplied, all aliases are removed.
-Aliases are described in @ref{Aliases}.
-
-@end table
-
-@node The Set Builtin
-@section The Set Builtin
-
-This builtin is so complicated that it deserves its own section.
-
-@table @code
-@item set
-@btindex set
-@example
-set [--abefhkmnptuvxBCHP] [-o @var{option}] [@var{argument} @dots{}]
-@end example
-
-If no options or arguments are supplied, @code{set} displays the names
-and values of all shell variables and functions, sorted according to the
-current locale, in a format that may be reused as input
-for setting or resetting the currently-set variables.
-Read-only variables cannot be reset.
-In @sc{posix} mode, only shell variables are listed.
-
-When options are supplied, they set or unset shell attributes.
-Options, if specified, have the following meanings:
-
-@table @code
-@item -a
-Mark variables and function which are modified or created for export
-to the environment of subsequent commands.
-
-@item -b
-Cause the status of terminated background jobs to be reported
-immediately, rather than before printing the next primary prompt.
-
-@item -e
-Exit immediately if a simple command (@pxref{Simple Commands}) exits
-with a non-zero status, unless the command that fails is part of the
-command list immediately following a @code{while} or @code{until}
-keyword, part of the test in an @code{if} statement,
-part of a @code{&&} or @code{||} list, or if the command's return
-status is being inverted using @code{!}.
-A trap on @code{ERR}, if set, is executed before the shell exits.
-
-@item -f
-Disable file name generation (globbing).
-
-@item -h
-Locate and remember (hash) commands as they are looked up for execution.
-This option is enabled by default.
-
-@item -k
-All arguments in the form of assignment statements are placed
-in the environment for a command, not just those that precede
-the command name.
-
-@item -m
-Job control is enabled (@pxref{Job Control}).
-
-@item -n
-Read commands but do not execute them; this may be used to check a
-script for syntax errors.
-This option is ignored by interactive shells.
-
-@item -o @var{option-name}
-
-Set the option corresponding to @var{option-name}:
-
-@table @code
-@item allexport
-Same as @code{-a}.
-
-@item braceexpand
-Same as @code{-B}.
-
-@item emacs
-Use an @code{emacs}-style line editing interface (@pxref{Command Line Editing}).
-
-@item errexit
-Same as @code{-e}.
-
-@item errtrace
-Same as @code{-E}.
-
-@item functrace
-Same as @code{-T}.
-
-@item hashall
-Same as @code{-h}.
-
-@item histexpand
-Same as @code{-H}.
-
-@item history
-Enable command history, as described in @ref{Bash History Facilities}.
-This option is on by default in interactive shells.
-
-@item ignoreeof
-An interactive shell will not exit upon reading EOF.
-
-@item keyword
-Same as @code{-k}.
-
-@item monitor
-Same as @code{-m}.
-
-@item noclobber
-Same as @code{-C}.
-
-@item noexec
-Same as @code{-n}.
-
-@item noglob
-Same as @code{-f}.
-
-@item nolog
-Currently ignored.
-
-@item notify
-Same as @code{-b}.
-
-@item nounset
-Same as @code{-u}.
-
-@item onecmd
-Same as @code{-t}.
-
-@item physical
-Same as @code{-P}.
-
-@item pipefail
-If set, the return value of a pipeline is the value of the last
-(rightmost) command to exit with a non-zero status, or zero if all
-commands in the pipeline exit successfully.
-This option is disabled by default.
-
-@item posix
-Change the behavior of Bash where the default operation differs
-from the @sc{posix} standard to match the standard
-(@pxref{Bash POSIX Mode}).
-This is intended to make Bash behave as a strict superset of that
-standard.
-
-@item privileged
-Same as @code{-p}.
-
-@item verbose
-Same as @code{-v}.
-
-@item vi
-Use a @code{vi}-style line editing interface.
-
-@item xtrace
-Same as @code{-x}.
-@end table
-
-@item -p
-Turn on privileged mode.
-In this mode, the @env{$BASH_ENV} and @env{$ENV} files are not
-processed, shell functions are not inherited from the environment,
-and the @env{SHELLOPTS} variable, if it appears in the environment,
-is ignored.
-If the shell is started with the effective user (group) id not equal to the
-real user (group) id, and the @code{-p} option is not supplied, these actions
-are taken and the effective user id is set to the real user id.
-If the @code{-p} option is supplied at startup, the effective user id is
-not reset.
-Turning this option off causes the effective user
-and group ids to be set to the real user and group ids.
-
-@item -t
-Exit after reading and executing one command.
-
-@item -u
-Treat unset variables as an error when performing parameter expansion.
-An error message will be written to the standard error, and a non-interactive
-shell will exit.
-
-@item -v
-Print shell input lines as they are read.
-
-@item -x
-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
-the command and its expanded arguments.
-
-@item -B
-The shell will perform brace expansion (@pxref{Brace Expansion}).
-This option is on by default.
-
-@item -C
-Prevent output redirection using @samp{>}, @samp{>&}, and @samp{<>}
-from overwriting existing files.
-
-@item -E
-If set, any trap on @code{ERR} is inherited by shell functions, command
-substitutions, and commands executed in a subshell environment.
-The @code{ERR} trap is normally not inherited in such cases.
-
-@item -H
-Enable @samp{!} style history substitution (@pxref{History Interaction}).
-This option is on by default for interactive shells.
-
-@item -P
-If set, do not follow symbolic links when performing commands such as
-@code{cd} which change the current directory. The physical directory
-is used instead. By default, Bash follows
-the logical chain of directories when performing commands
-which change the current directory.
-
-For example, if @file{/usr/sys} is a symbolic link to @file{/usr/local/sys}
-then:
-@example
-$ cd /usr/sys; echo $PWD
-/usr/sys
-$ cd ..; pwd
-/usr
-@end example
-
-@noindent
-If @code{set -P} is on, then:
-@example
-$ cd /usr/sys; echo $PWD
-/usr/local/sys
-$ cd ..; pwd
-/usr/local
-@end example
-
-@item -T
-If set, any trap on @code{DEBUG} and @code{RETURN} are inherited by
-shell functions, command substitutions, and commands executed
-in a subshell environment.
-The @code{DEBUG} and @code{RETURN} traps are normally not inherited
-in such cases.
-
-@item --
-If no arguments follow this option, then the positional parameters are
-unset. Otherwise, the positional parameters are set to the
-@var{arguments}, even if some of them begin with a @samp{-}.
-
-@item -
-Signal the end of options, cause all remaining @var{arguments}
-to be assigned to the positional parameters. The @option{-x}
-and @option{-v} options are turned off.
-If there are no arguments, the positional parameters remain unchanged.
-@end table
-
-Using @samp{+} rather than @samp{-} causes these options to be
-turned off. The options can also be used upon invocation of the
-shell. The current set of options may be found in @code{$-}.
-
-The remaining N @var{arguments} are positional parameters and are
-assigned, in order, to @code{$1}, @code{$2}, @dots{} @code{$N}.
-The special parameter @code{#} is set to N.
-
-The return status is always zero unless an invalid option is supplied.
-@end table
-
-@node Special Builtins
-@section Special Builtins
-@cindex special builtin
-
-For historical reasons, the @sc{posix} standard has classified
-several builtin commands as @emph{special}.
-When Bash is executing in @sc{posix} mode, the special builtins
-differ from other builtin commands in three respects:
-
-@enumerate
-@item
-Special builtins are found before shell functions during command lookup.
-
-@item
-If a special builtin returns an error status, a non-interactive shell exits.
-
-@item
-Assignment statements preceding the command stay in effect in the shell
-environment after the command completes.
-@end enumerate
-
-When Bash is not executing in @sc{posix} mode, these builtins behave no
-differently than the rest of the Bash builtin commands.
-The Bash @sc{posix} mode is described in @ref{Bash POSIX Mode}.
-
-These are the @sc{posix} special builtins:
-@example
-@w{break : . continue eval exec exit export readonly return set}
-@w{shift trap unset}
-@end example
-
-@node Shell Variables
-@chapter Shell Variables
-
-@menu
-* Bourne Shell Variables:: Variables which Bash uses in the same way
- as the Bourne Shell.
-* Bash Variables:: List of variables that exist in Bash.
-@end menu
-
-This chapter describes the shell variables that Bash uses.
-Bash automatically assigns default values to a number of variables.
-
-@node Bourne Shell Variables
-@section Bourne Shell Variables
-
-Bash uses certain shell variables in the same way as the Bourne shell.
-In some cases, Bash assigns a default value to the variable.
-
-@vtable @code
-
-@item CDPATH
-A colon-separated list of directories used as a search path for
-the @code{cd} builtin command.
-
-@item HOME
-The current user's home directory; the default for the @code{cd} builtin
-command.
-The value of this variable is also used by tilde expansion
-(@pxref{Tilde Expansion}).
-
-@item IFS
-A list of characters that separate fields; used when the shell splits
-words as part of expansion.
-
-@item MAIL
-If this parameter is set to a filename and the @env{MAILPATH} variable
-is not set, Bash informs the user of the arrival of mail in
-the specified file.
-
-@item MAILPATH
-A colon-separated list of filenames which the shell periodically checks
-for new mail.
-Each list entry can specify the message that is printed when new mail
-arrives in the mail file by separating the file name from the message with
-a @samp{?}.
-When used in the text of the message, @code{$_} expands to the name of
-the current mail file.
-
-@item OPTARG
-The value of the last option argument processed by the @code{getopts} builtin.
-
-@item OPTIND
-The index of the last option argument processed by the @code{getopts} builtin.
-
-@item PATH
-A colon-separated list of directories in which the shell looks for
-commands.
-A zero-length (null) directory name in the value of @code{PATH} indicates the
-current directory.
-A null directory name may appear as two adjacent colons, or as an initial
-or trailing colon.
-
-
-@item PS1
-The primary prompt string. The default value is @samp{\s-\v\$ }.
-@xref{Printing a Prompt}, for the complete list of escape
-sequences that are expanded before @env{PS1} is displayed.
-
-@item PS2
-The secondary prompt string. The default value is @samp{> }.
-
-@end vtable
-
-@node Bash Variables
-@section Bash Variables
-
-These variables are set or used by Bash, but other shells
-do not normally treat them specially.
-
-A few variables used by Bash are described in different chapters:
-variables for controlling the job control facilities
-(@pxref{Job Control Variables}).
-
-@vtable @code
-
-@item BASH
-The full pathname used to execute the current instance of Bash.
-
-@item BASH_ARGC
-An array variable whose values are the number of parameters in each
-frame of the current bash execution call stack. The number of
-parameters to the current subroutine (shell function or script executed
-with @code{.} or @code{source}) is at the top of the stack. When a
-subroutine is executed, the number of parameters passed is pushed onto
-@code{BASH_ARGC}.
-The shell sets @code{BASH_ARGC} only when in extended debugging mode
-(see @ref{Bash Builtins}
-for a description of the @code{extdebug} option to the @code{shopt}
-builtin).
-
-@item BASH_ARGV
-An array variable containing all of the parameters in the current bash
-execution call stack. The final parameter of the last subroutine call
-is at the top of the stack; the first parameter of the initial call is
-at the bottom. When a subroutine is executed, the parameters supplied
-are pushed onto @code{BASH_ARGV}.
-The shell sets @code{BASH_ARGV} only when in extended debugging mode
-(see @ref{Bash Builtins}
-for a description of the @code{extdebug} option to the @code{shopt}
-builtin).
-
-@item BASH_COMMAND
-The command currently being executed or about to be executed, unless the
-shell is executing a command as the result of a trap,
-in which case it is the command executing at the time of the trap.
-
-@item BASH_ENV
-If this variable is set when Bash is invoked to execute a shell
-script, its value is expanded and used as the name of a startup file
-to read before executing the script. @xref{Bash Startup Files}.
-
-@item BASH_EXECUTION_STRING
-The command argument to the @option{-c} invocation option.
-
-@item BASH_LINENO
-An array variable whose members are the line numbers in source files
-corresponding to each member of @var{FUNCNAME}.
-@code{$@{BASH_LINENO[$i]@}} is the line number in the source file where
-@code{$@{FUNCNAME[$i]@}} was called.
-The corresponding source file name is @code{$@{BASH_SOURCE[$i]@}}.
-Use @code{LINENO} to obtain the current line number.
-
-@item BASH_REMATCH
-An array variable whose members are assigned by the @samp{=~} binary
-operator to the @code{[[} conditional command
-(@pxref{Conditional Constructs}).
-The element with index 0 is the portion of the string
-matching the entire regular expression.
-The element with index @var{n} is the portion of the
-string matching the @var{n}th parenthesized subexpression.
-This variable is read-only.
-
-@item BASH_SOURCE
-An array variable whose members are the source filenames corresponding
-to the elements in the @code{FUNCNAME} array variable.
-
-@item BASH_SUBSHELL
-Incremented by one each time a subshell or subshell environment is spawned.
-The initial value is 0.
-
-@item BASH_VERSINFO
-A readonly array variable (@pxref{Arrays})
-whose members hold version information for this instance of Bash.
-The values assigned to the array members are as follows:
-
-@table @code
-
-@item BASH_VERSINFO[0]
-The major version number (the @var{release}).
-
-@item BASH_VERSINFO[1]
-The minor version number (the @var{version}).
-
-@item BASH_VERSINFO[2]
-The patch level.
-
-@item BASH_VERSINFO[3]
-The build version.
-
-@item BASH_VERSINFO[4]
-The release status (e.g., @var{beta1}).
-
-@item BASH_VERSINFO[5]
-The value of @env{MACHTYPE}.
-
-@end table
-
-@item BASH_VERSION
-The version number of the current instance of Bash.
-
-@item COLUMNS
-Used by the @code{select} builtin command to determine the terminal width
-when printing selection lists. Automatically set upon receipt of a
-@code{SIGWINCH}.
-
-@item COMP_CWORD
-An index into @env{$@{COMP_WORDS@}} of the word containing the current
-cursor position.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_LINE
-The current command line.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_POINT
-The index of the current cursor position relative to the beginning of
-the current command.
-If the current cursor position is at the end of the current command,
-the value of this variable is equal to @code{$@{#COMP_LINE@}}.
-This variable is available only in shell functions and external
-commands invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMP_WORDBREAKS
-The set of characters that the Readline library treats as word
-separators when performing word completion.
-If @code{COMP_WORDBREAKS} is unset, it loses its special properties,
-even if it is subsequently reset.
-
-@item COMP_WORDS
-An array variable consisting of the individual
-words in the current command line.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (@pxref{Programmable Completion}).
-
-@item COMPREPLY
-An array variable from which Bash reads the possible completions
-generated by a shell function invoked by the programmable completion
-facility (@pxref{Programmable Completion}).
-
-@item DIRSTACK
-An array variable containing the current contents of the directory stack.
-Directories appear in the stack in the order they are displayed by the
-@code{dirs} builtin.
-Assigning to members of this array variable may be used to modify
-directories already in the stack, but the @code{pushd} and @code{popd}
-builtins must be used to add and remove directories.
-Assignment to this variable will not change the current directory.
-If @env{DIRSTACK} is unset, it loses its special properties, even if
-it is subsequently reset.
-
-@item EMACS
-If Bash finds this variable in the environment when the shell
-starts with value @samp{t}, it assumes that the shell is running in an
-emacs shell buffer and disables line editing.
-
-@item EUID
-The numeric effective user id of the current user. This variable
-is readonly.
-
-@item FCEDIT
-The editor used as a default by the @option{-e} option to the @code{fc}
-builtin command.
-
-@item FIGNORE
-A colon-separated list of suffixes to ignore when performing
-filename completion.
-A file name whose suffix matches one of the entries in
-@env{FIGNORE}
-is excluded from the list of matched file names. A sample
-value is @samp{.o:~}
-
-@item FUNCNAME
-An array variable containing the names of all shell functions
-currently in the execution call stack.
-The element with index 0 is the name of any currently-executing
-shell function.
-The bottom-most element is "main".
-This variable exists only when a shell function is executing.
-Assignments to @env{FUNCNAME} have no effect and return an error status.
-If @env{FUNCNAME} is unset, it loses its special properties, even if
-it is subsequently reset.
-
-@item GLOBIGNORE
-A colon-separated list of patterns defining the set of filenames to
-be ignored by filename expansion.
-If a filename matched by a filename expansion pattern also matches one
-of the patterns in @env{GLOBIGNORE}, it is removed from the list
-of matches.
-
-@item GROUPS
-An array variable containing the list of groups of which the current
-user is a member.
-Assignments to @env{GROUPS} have no effect and return an error status.
-If @env{GROUPS} is unset, it loses its special properties, even if it is
-subsequently reset.
-
-@item histchars
-Up to three characters which control history expansion, quick
-substitution, and tokenization (@pxref{History Interaction}).
-The first character is the
-@var{history expansion} character, that is, the character which signifies the
-start of a history expansion, normally @samp{!}. The second character is the
-character which signifies `quick substitution' when seen as the first
-character on a line, normally @samp{^}. The optional third character is the
-character which indicates that the remainder of the line is a comment when
-found as the first character of a word, usually @samp{#}. The history
-comment character causes history substitution to be skipped for the
-remaining words on the line. It does not necessarily cause the shell
-parser to treat the rest of the line as a comment.
-
-@item HISTCMD
-The history number, or index in the history list, of the current
-command. If @env{HISTCMD} is unset, it loses its special properties,
-even if it is subsequently reset.
-
-@item HISTCONTROL
-A colon-separated list of values controlling how commands are saved on
-the history list.
-If the list of values includes @samp{ignorespace}, lines which begin
-with a space character are not saved in the history list.
-A value of @samp{ignoredups} causes lines which match the previous
-history entry to not be saved.
-A value of @samp{ignoreboth} is shorthand for
-@samp{ignorespace} and @samp{ignoredups}.
-A value of @samp{erasedups} causes all previous lines matching the
-current line to be removed from the history list before that line
-is saved.
-Any value not in the above list is ignored.
-If @env{HISTCONTROL} is unset, or does not include a valid value,
-all lines read by the shell parser are saved on the history list,
-subject to the value of @env{HISTIGNORE}.
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-@env{HISTCONTROL}.
-
-@item HISTFILE
-The name of the file to which the command history is saved. The
-default value is @file{~/.bash_history}.
-
-@item HISTFILESIZE
-The maximum number of lines contained in the history file. When this
-variable is assigned a value, the history file is truncated, if
-necessary, by removing the oldest entries,
-to contain no more than that number of lines.
-The history file is also truncated to this size after
-writing it when an interactive shell exits.
-The default value is 500.
-
-@item HISTIGNORE
-A colon-separated list of patterns used to decide which command
-lines should be saved on the history list. Each pattern is
-anchored at the beginning of the line and must match the complete
-line (no implicit @samp{*} is appended). Each pattern is tested
-against the line after the checks specified by @env{HISTCONTROL}
-are applied. In addition to the normal shell pattern matching
-characters, @samp{&} matches the previous history line. @samp{&}
-may be escaped using a backslash; the backslash is removed
-before attempting a match.
-The second and subsequent lines of a multi-line compound command are
-not tested, and are added to the history regardless of the value of
-@env{HISTIGNORE}.
-
-@env{HISTIGNORE} subsumes the function of @env{HISTCONTROL}. A
-pattern of @samp{&} is identical to @code{ignoredups}, and a
-pattern of @samp{[ ]*} is identical to @code{ignorespace}.
-Combining these two patterns, separating them with a colon,
-provides the functionality of @code{ignoreboth}.
-
-@item HISTSIZE
-The maximum number of commands to remember on the history list.
-The default value is 500.
-
-@item HISTTIMEFORMAT
-If this variable is set and not null, its value is used as a format string
-for @var{strftime} to print the time stamp associated with each history
-entry displayed by the @code{history} builtin.
-If this variable is set, time stamps are written to the history file so
-they may be preserved across shell sessions.
-
-@item HOSTFILE
-Contains the name of a file in the same format as @file{/etc/hosts} that
-should be read when the shell needs to complete a hostname.
-The list of possible hostname completions may be changed while the shell
-is running;
-the next time hostname completion is attempted after the
-value is changed, Bash adds the contents of the new file to the
-existing list.
-If @env{HOSTFILE} is set, but has no value, Bash attempts to read
-@file{/etc/hosts} to obtain the list of possible hostname completions.
-When @env{HOSTFILE} is unset, the hostname list is cleared.
-
-@item HOSTNAME
-The name of the current host.
-
-@item HOSTTYPE
-A string describing the machine Bash is running on.
-
-@item IGNOREEOF
-Controls the action of the shell on receipt of an @code{EOF} character
-as the sole input. If set, the value denotes the number
-of consecutive @code{EOF} characters that can be read as the
-first character on an input line
-before the shell will exit. If the variable exists but does not
-have a numeric value (or has no value) then the default is 10.
-If the variable does not exist, then @code{EOF} signifies the end of
-input to the shell. This is only in effect for interactive shells.
-
-@item INPUTRC
-The name of the Readline initialization file, overriding the default
-of @file{~/.inputrc}.
-
-@item LANG
-Used to determine the locale category for any category not specifically
-selected with a variable starting with @code{LC_}.
-
-@item LC_ALL
-This variable overrides the value of @env{LANG} and any other
-@code{LC_} variable specifying a locale category.
-
-@item LC_COLLATE
-This variable determines the collation order used when sorting the
-results of filename expansion, and
-determines the behavior of range expressions, equivalence classes,
-and collating sequences within filename expansion and pattern matching
-(@pxref{Filename Expansion}).
-
-@item LC_CTYPE
-This variable determines the interpretation of characters and the
-behavior of character classes within filename expansion and pattern
-matching (@pxref{Filename Expansion}).
-
-@item LC_MESSAGES
-This variable determines the locale used to translate double-quoted
-strings preceded by a @samp{$} (@pxref{Locale Translation}).
-
-@item LC_NUMERIC
-This variable determines the locale category used for number formatting.
-
-@item LINENO
-The line number in the script or shell function currently executing.
-
-@item LINES
-Used by the @code{select} builtin command to determine the column length
-for printing selection lists. Automatically set upon receipt of a
-@code{SIGWINCH}.
-
-@item MACHTYPE
-A string that fully describes the system type on which Bash
-is executing, in the standard @sc{gnu} @var{cpu-company-system} format.
-
-@item MAILCHECK
-How often (in seconds) that the shell should check for mail in the
-files specified in the @env{MAILPATH} or @env{MAIL} variables.
-The default is 60 seconds. When it is time to check
-for mail, the shell does so before displaying the primary prompt.
-If this variable is unset, or set to a value that is not a number
-greater than or equal to zero, the shell disables mail checking.
-
-@item OLDPWD
-The previous working directory as set by the @code{cd} builtin.
-
-@item OPTERR
-If set to the value 1, Bash displays error messages
-generated by the @code{getopts} builtin command.
-
-@item OSTYPE
-A string describing the operating system Bash is running on.
-
-@item PIPESTATUS
-An array variable (@pxref{Arrays})
-containing a list of exit status values from the processes
-in the most-recently-executed foreground pipeline (which may
-contain only a single command).
-
-@item POSIXLY_CORRECT
-If this variable is in the environment when @code{bash} starts, the shell
-enters @sc{posix} mode (@pxref{Bash POSIX Mode}) before reading the
-startup files, as if the @option{--posix} invocation option had been supplied.
-If it is set while the shell is running, @code{bash} enables @sc{posix} mode,
-as if the command
-@example
-@code{set -o posix}
-@end example
-@noindent
-had been executed.
-
-@item PPID
-The process @sc{id} of the shell's parent process. This variable
-is readonly.
-
-@item PROMPT_COMMAND
-If set, the value is interpreted as a command to execute
-before the printing of each primary prompt (@env{$PS1}).
-
-@item PS3
-The value of this variable is used as the prompt for the
-@code{select} command. If this variable is not set, the
-@code{select} command prompts with @samp{#? }
-
-@item PS4
-The value is the prompt printed before the command line is echoed
-when the @option{-x} option is set (@pxref{The Set Builtin}).
-The first character of @env{PS4} is replicated multiple times, as
-necessary, to indicate multiple levels of indirection.
-The default is @samp{+ }.
-
-@item PWD
-The current working directory as set by the @code{cd} builtin.
-
-@item RANDOM
-Each time this parameter is referenced, a random integer
-between 0 and 32767 is generated. Assigning a value to this
-variable seeds the random number generator.
-
-@item REPLY
-The default variable for the @code{read} builtin.
-
-@item SECONDS
-This variable expands to the number of seconds since the
-shell was started. Assignment to this variable resets
-the count to the value assigned, and the expanded value
-becomes the value assigned plus the number of seconds
-since the assignment.
-
-@item SHELL
-The full pathname to the shell is kept in this environment variable.
-If it is not set when the shell starts,
-Bash assigns to it the full pathname of the current user's login shell.
-
-@item SHELLOPTS
-A colon-separated list of enabled shell options. Each word in
-the list is a valid argument for the @option{-o} option to the
-@code{set} builtin command (@pxref{The Set Builtin}).
-The options appearing in @env{SHELLOPTS} are those reported
-as @samp{on} by @samp{set -o}.
-If this variable is in the environment when Bash
-starts up, each shell option in the list will be enabled before
-reading any startup files. This variable is readonly.
-
-@item SHLVL
-Incremented by one each time a new instance of Bash is started. This is
-intended to be a count of how deeply your Bash shells are nested.
-
-@item TIMEFORMAT
-The value of this parameter is used as a format string specifying
-how the timing information for pipelines prefixed with the @code{time}
-reserved word should be displayed.
-The @samp{%} character introduces an
-escape sequence that is expanded to a time value or other
-information.
-The escape sequences and their meanings are as
-follows; the braces denote optional portions.
-
-@table @code
-
-@item %%
-A literal @samp{%}.
-
-@item %[@var{p}][l]R
-The elapsed time in seconds.
-
-@item %[@var{p}][l]U
-The number of CPU seconds spent in user mode.
-
-@item %[@var{p}][l]S
-The number of CPU seconds spent in system mode.
-
-@item %P
-The CPU percentage, computed as (%U + %S) / %R.
-@end table
-
-The optional @var{p} is a digit specifying the precision, the number of
-fractional digits after a decimal point.
-A value of 0 causes no decimal point or fraction to be output.
-At most three places after the decimal point may be specified; values
-of @var{p} greater than 3 are changed to 3.
-If @var{p} is not specified, the value 3 is used.
-
-The optional @code{l} specifies a longer format, including minutes, of
-the form @var{MM}m@var{SS}.@var{FF}s.
-The value of @var{p} determines whether or not the fraction is included.
-
-If this variable is not set, Bash acts as if it had the value
-@example
-@code{$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'}
-@end example
-If the value is null, no timing information is displayed.
-A trailing newline is added when the format string is displayed.
-
-@item TMOUT
-If set to a value greater than zero, @code{TMOUT} is treated as the
-default timeout for the @code{read} builtin (@pxref{Bash Builtins}).
-The @code{select} command (@pxref{Conditional Constructs}) terminates
-if input does not arrive after @code{TMOUT} seconds when input is coming
-from a terminal.
-
-In an interative shell, the value is interpreted as
-the number of seconds to wait for input after issuing the primary
-prompt when the shell is interactive.
-Bash terminates after that number of seconds if input does
-not arrive.
-
-@item TMPDIR
-If set, Bash uses its value as the name of a directory in which
-Bash creates temporary files for the shell's use.
-
-@item UID
-The numeric real user id of the current user. This variable is readonly.
-
-@end vtable
-
-@node Bash Features
-@chapter Bash Features
-
-This section describes features unique to Bash.
-
-@menu
-* Invoking Bash:: Command line options that you can give
- to Bash.
-* Bash Startup Files:: When and how Bash executes scripts.
-* Interactive Shells:: What an interactive shell is.
-* Bash Conditional Expressions:: Primitives used in composing expressions for
- the @code{test} builtin.
-* Shell Arithmetic:: Arithmetic on shell variables.
-* Aliases:: Substituting one command for another.
-* Arrays:: Array Variables.
-* The Directory Stack:: History of visited directories.
-* Printing a Prompt:: Controlling the PS1 string.
-* The Restricted Shell:: A more controlled mode of shell execution.
-* Bash POSIX Mode:: Making Bash behave more closely to what
- the POSIX standard specifies.
-@end menu
-
-@node Invoking Bash
-@section Invoking Bash
-
-@example
-bash [long-opt] [-ir] [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] [@var{argument} @dots{}]
-bash [long-opt] [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] -c @var{string} [@var{argument} @dots{}]
-bash [long-opt] -s [-abefhkmnptuvxdBCDHP] [-o @var{option}] [-O @var{shopt_option}] [@var{argument} @dots{}]
-@end example
-
-In addition to the single-character shell command-line options
-(@pxref{The Set Builtin}), there are several multi-character
-options that you can use. These options must appear on the command
-line before the single-character options to be recognized.
-
-@table @code
-@item --debugger
-Arrange for the debugger profile to be executed before the shell
-starts. Turns on extended debugging mode (see @ref{Bash Builtins}
-for a description of the @code{extdebug} option to the @code{shopt}
-builtin) and shell function tracing
-(see @ref{The Set Builtin} for a description of the @code{-o functrace}
-option).
-
-@item --dump-po-strings
-A list of all double-quoted strings preceded by @samp{$}
-is printed on the standard output
-in the @sc{gnu} @code{gettext} PO (portable object) file format.
-Equivalent to @option{-D} except for the output format.
-
-@item --dump-strings
-Equivalent to @option{-D}.
-
-@item --help
-Display a usage message on standard output and exit sucessfully.
-
-@item --init-file @var{filename}
-@itemx --rcfile @var{filename}
-Execute commands from @var{filename} (instead of @file{~/.bashrc})
-in an interactive shell.
-
-@item --login
-Equivalent to @option{-l}.
-
-@item --noediting
-Do not use the @sc{gnu} Readline library (@pxref{Command Line Editing})
-to read command lines when the shell is interactive.
-
-@item --noprofile
-Don't load the system-wide startup file @file{/etc/profile}
-or any of the personal initialization files
-@file{~/.bash_profile}, @file{~/.bash_login}, or @file{~/.profile}
-when Bash is invoked as a login shell.
-
-@item --norc
-Don't read the @file{~/.bashrc} initialization file in an
-interactive shell. This is on by default if the shell is
-invoked as @code{sh}.
-
-@item --posix
-Change the behavior of Bash where the default operation differs
-from the @sc{posix} standard to match the standard. This
-is intended to make Bash behave as a strict superset of that
-standard. @xref{Bash POSIX Mode}, for a description of the Bash
-@sc{posix} mode.
-
-@item --restricted
-Make the shell a restricted shell (@pxref{The Restricted Shell}).
-
-@item --verbose
-Equivalent to @option{-v}. Print shell input lines as they're read.
-
-@item --version
-Show version information for this instance of
-Bash on the standard output and exit successfully.
-
-@end table
-
-There are several single-character options that may be supplied at
-invocation which are not available with the @code{set} builtin.
-
-@table @code
-@item -c @var{string}
-Read and execute commands from @var{string} after processing the
-options, then exit. Any remaining arguments are assigned to the
-positional parameters, starting with @code{$0}.
-
-@item -i
-Force the shell to run interactively. Interactive shells are
-described in @ref{Interactive Shells}.
-
-@item -l
-Make this shell act as if it had been directly invoked by login.
-When the shell is interactive, this is equivalent to starting a
-login shell with @samp{exec -l bash}.
-When the shell is not interactive, the login shell startup files will
-be executed.
-@samp{exec bash -l} or @samp{exec bash --login}
-will replace the current shell with a Bash login shell.
-@xref{Bash Startup Files}, for a description of the special behavior
-of a login shell.
-
-@item -r
-Make the shell a restricted shell (@pxref{The Restricted Shell}).
-
-@item -s
-If this option is present, or if no arguments remain after option
-processing, then commands are read from the standard input.
-This option allows the positional parameters to be set
-when invoking an interactive shell.
-
-@item -D
-A list of all double-quoted strings preceded by @samp{$}
-is printed on the standard output.
-These are the strings that
-are subject to language translation when the current locale
-is not @code{C} or @code{POSIX} (@pxref{Locale Translation}).
-This implies the @option{-n} option; no commands will be executed.
-
-@item [-+]O [@var{shopt_option}]
-@var{shopt_option} is one of the shell options accepted by the
-@code{shopt} builtin (@pxref{Shell Builtin Commands}).
-If @var{shopt_option} is present, @option{-O} sets the value of that option;
-@option{+O} unsets it.
-If @var{shopt_option} is not supplied, the names and values of the shell
-options accepted by @code{shopt} are printed on the standard output.
-If the invocation option is @option{+O}, the output is displayed in a format
-that may be reused as input.
-
-@item --
-A @code{--} signals the end of options and disables further option
-processing.
-Any arguments after the @code{--} are treated as filenames and arguments.
-
-@end table
-
-@cindex login shell
-A @emph{login} shell is one whose first character of argument zero is
-@samp{-}, or one invoked with the @option{--login} option.
-
-@cindex interactive shell
-An @emph{interactive} shell is one started without non-option arguments,
-unless @option{-s} is specified,
-without specifying the @option{-c} option, and whose input and output are both
-connected to terminals (as determined by @code{isatty(3)}), or one
-started with the @option{-i} option. @xref{Interactive Shells}, for more
-information.
-
-If arguments remain after option processing, and neither the
-@option{-c} nor the @option{-s}
-option has been supplied, the first argument is assumed to
-be the name of a file containing shell commands (@pxref{Shell Scripts}).
-When Bash is invoked in this fashion, @code{$0}
-is set to the name of the file, and the positional parameters
-are set to the remaining arguments.
-Bash reads and executes commands from this file, then exits.
-Bash's exit status is the exit status of the last command executed
-in the script. If no commands are executed, the exit status is 0.
-
-@node Bash Startup Files
-@section Bash Startup Files
-@cindex startup files
-
-This section describs how Bash executes its startup files.
-If any of the files exist but cannot be read, Bash reports an error.
-Tildes are expanded in file names as described above under
-Tilde Expansion (@pxref{Tilde Expansion}).
-
-Interactive shells are described in @ref{Interactive Shells}.
-
-@subsubheading Invoked as an interactive login shell, or with @option{--login}
-
-When Bash is invoked as an interactive login shell, or as a
-non-interactive shell with the @option{--login} option, it first reads and
-executes commands from the file @file{/etc/profile}, if that file exists.
-After reading that file, it looks for @file{~/.bash_profile},
-@file{~/.bash_login}, and @file{~/.profile}, in that order, and reads
-and executes commands from the first one that exists and is readable.
-The @option{--noprofile} option may be used when the shell is started to
-inhibit this behavior.
-
-When a login shell exits, Bash reads and executes commands from
-the file @file{~/.bash_logout}, if it exists.
-
-@subsubheading Invoked as an interactive non-login shell
-
-When an interactive shell that is not a login shell is started, Bash
-reads and executes commands from @file{~/.bashrc}, if that file exists.
-This may be inhibited by using the @option{--norc} option.
-The @option{--rcfile @var{file}} option will force Bash to read and
-execute commands from @var{file} instead of @file{~/.bashrc}.
-
-So, typically, your @file{~/.bash_profile} contains the line
-@example
-@code{if [ -f ~/.bashrc ]; then . ~/.bashrc; fi}
-@end example
-@noindent
-after (or before) any login-specific initializations.
-
-@subsubheading Invoked non-interactively
-
-When Bash is started non-interactively, to run a shell script,
-for example, it looks for the variable @env{BASH_ENV} in the environment,
-expands its value if it appears there, and uses the expanded value as
-the name of a file to read and execute. Bash behaves as if the
-following command were executed:
-@example
-@code{if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi}
-@end example
-@noindent
-but the value of the @env{PATH} variable is not used to search for the
-file name.
-
-As noted above, if a non-interactive shell is invoked with the
-@option{--login} option, Bash attempts to read and execute commands from the
-login shell startup files.
-
-@subsubheading Invoked with name @code{sh}
-
-If Bash is invoked with the name @code{sh}, it tries to mimic the
-startup behavior of historical versions of @code{sh} as closely as
-possible, while conforming to the @sc{posix} standard as well.
-
-When invoked as an interactive login shell, or as a non-interactive
-shell with the @option{--login} option, it first attempts to read
-and execute commands from @file{/etc/profile} and @file{~/.profile}, in
-that order.
-The @option{--noprofile} option may be used to inhibit this behavior.
-When invoked as an interactive shell with the name @code{sh}, Bash
-looks for the variable @env{ENV}, expands its value if it is defined,
-and uses the expanded value as the name of a file to read and execute.
-Since a shell invoked as @code{sh} does not attempt to read and execute
-commands from any other startup files, the @option{--rcfile} option has
-no effect.
-A non-interactive shell invoked with the name @code{sh} does not attempt
-to read any other startup files.
-
-When invoked as @code{sh}, Bash enters @sc{posix} mode after
-the startup files are read.
-
-@subsubheading Invoked in @sc{posix} mode
-
-When Bash is started in @sc{posix} mode, as with the
-@option{--posix} command line option, it follows the @sc{posix} standard
-for startup files.
-In this mode, interactive shells expand the @env{ENV} variable
-and commands are read and executed from the file whose name is the
-expanded value.
-No other startup files are read.
-
-@subsubheading Invoked by remote shell daemon
-
-Bash attempts to determine when it is being run by the remote shell
-daemon, usually @code{rshd}. If Bash determines it is being run by
-rshd, it reads and executes commands from @file{~/.bashrc}, if that
-file exists and is readable.
-It will not do this if invoked as @code{sh}.
-The @option{--norc} option may be used to inhibit this behavior, and the
-@option{--rcfile} option may be used to force another file to be read, but
-@code{rshd} does not generally invoke the shell with those options or
-allow them to be specified.
-
-@subsubheading Invoked with unequal effective and real @sc{uid/gid}s
-
-If Bash is started with the effective user (group) id not equal to the
-real user (group) id, and the @code{-p} option is not supplied, no startup
-files are read, shell functions are not inherited from the environment,
-the @env{SHELLOPTS} variable, if it appears in the environment, is ignored,
-and the effective user id is set to the real user id.
-If the @code{-p} option is supplied at invocation, the startup behavior is
-the same, but the effective user id is not reset.
-
-@node Interactive Shells
-@section Interactive Shells
-@cindex interactive shell
-@cindex shell, interactive
-
-@menu
-* What is an Interactive Shell?:: What determines whether a shell is Interactive.
-* Is this Shell Interactive?:: How to tell if a shell is interactive.
-* Interactive Shell Behavior:: What changes in a interactive shell?
-@end menu
-
-@node What is an Interactive Shell?
-@subsection What is an Interactive Shell?
-
-An interactive shell
-is one started without non-option arguments, unless @option{-s} is
-specified, without specifiying the @option{-c} option, and
-whose input and error output are both
-connected to terminals (as determined by @code{isatty(3)}),
-or one started with the @option{-i} option.
-
-An interactive shell generally reads from and writes to a user's
-terminal.
-
-The @option{-s} invocation option may be used to set the positional parameters
-when an interactive shell is started.
-
-@node Is this Shell Interactive?
-@subsection Is this Shell Interactive?
-
-To determine within a startup script whether or not Bash is
-running interactively,
-test the value of the @samp{-} special parameter.
-It contains @code{i} when the shell is interactive. For example:
-
-@example
-case "$-" in
-*i*) echo This shell is interactive ;;
-*) echo This shell is not interactive ;;
-esac
-@end example
-
-Alternatively, startup scripts may examine the variable
-@env{PS1}; it is unset in non-interactive shells, and set in
-interactive shells. Thus:
-
-@example
-if [ -z "$PS1" ]; then
- echo This shell is not interactive
-else
- echo This shell is interactive
-fi
-@end example
-
-@node Interactive Shell Behavior
-@subsection Interactive Shell Behavior
-
-When the shell is running interactively, it changes its behavior in
-several ways.
-
-@enumerate
-@item
-Startup files are read and executed as described in @ref{Bash Startup Files}.
-
-@item
-Job Control (@pxref{Job Control}) is enabled by default. When job
-control is in effect, Bash ignores the keyboard-generated job control
-signals @code{SIGTTIN}, @code{SIGTTOU}, and @code{SIGTSTP}.
-
-@item
-Bash expands and displays @env{PS1} before reading the first line
-of a command, and expands and displays @env{PS2} before reading the
-second and subsequent lines of a multi-line command.
-
-@item
-Bash executes the value of the @env{PROMPT_COMMAND} variable as a command
-before printing the primary prompt, @env{$PS1}
-(@pxref{Bash Variables}).
-
-@item
-Readline (@pxref{Command Line Editing}) is used to read commands from
-the user's terminal.
-
-@item
-Bash inspects the value of the @code{ignoreeof} option to @code{set -o}
-instead of exiting immediately when it receives an @code{EOF} on its
-standard input when reading a command (@pxref{The Set Builtin}).
-
-@item
-Command history (@pxref{Bash History Facilities})
-and history expansion (@pxref{History Interaction})
-are enabled by default.
-Bash will save the command history to the file named by @env{$HISTFILE}
-when an interactive shell exits.
-
-@item
-Alias expansion (@pxref{Aliases}) is performed by default.
-
-@item
-In the absence of any traps, Bash ignores @code{SIGTERM}
-(@pxref{Signals}).
-
-@item
-In the absence of any traps, @code{SIGINT} is caught and handled
-((@pxref{Signals}).
-@code{SIGINT} will interrupt some shell builtins.
-
-@item
-An interactive login shell sends a @code{SIGHUP} to all jobs on exit
-if the @code{hupoxexit} shell option has been enabled (@pxref{Signals}).
-
-@item
-The @option{-n} invocation option is ignored, and @samp{set -n} has
-no effect (@pxref{The Set Builtin}).
-
-@item
-Bash will check for mail periodically, depending on the values of the
-@env{MAIL}, @env{MAILPATH}, and @env{MAILCHECK} shell variables
-(@pxref{Bash Variables}).
-
-@item
-Expansion errors due to references to unbound shell variables after
-@samp{set -u} has been enabled will not cause the shell to exit
-(@pxref{The Set Builtin}).
-
-@item
-The shell will not exit on expansion errors caused by @var{var} being unset
-or null in @code{$@{@var{var}:?@var{word}@}} expansions
-(@pxref{Shell Parameter Expansion}).
-
-@item
-Redirection errors encountered by shell builtins will not cause the
-shell to exit.
-
-@item
-When running in @sc{posix} mode, a special builtin returning an error
-status will not cause the shell to exit (@pxref{Bash POSIX Mode}).
-
-@item
-A failed @code{exec} will not cause the shell to exit
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Parser syntax errors will not cause the shell to exit.
-
-@item
-Simple spelling correction for directory arguments to the @code{cd}
-builtin is enabled by default (see the description of the @code{cdspell}
-option to the @code{shopt} builtin in @ref{Bash Builtins}).
-
-@item
-The shell will check the value of the @env{TMOUT} variable and exit
-if a command is not read within the specified number of seconds after
-printing @env{$PS1} (@pxref{Bash Variables}).
-
-@end enumerate
-
-@node Bash Conditional Expressions
-@section Bash Conditional Expressions
-@cindex expressions, conditional
-
-Conditional expressions are used by the @code{[[} compound command
-and the @code{test} and @code{[} builtin commands.
-
-Expressions may be unary or binary.
-Unary expressions are often used to examine the status of a file.
-There are string operators and numeric comparison operators as well.
-If the @var{file} argument to one of the primaries is of the form
-@file{/dev/fd/@var{N}}, then file descriptor @var{N} is checked.
-If the @var{file} argument to one of the primaries is one of
-@file{/dev/stdin}, @file{/dev/stdout}, or @file{/dev/stderr}, file
-descriptor 0, 1, or 2, respectively, is checked.
-
-Unless otherwise specified, primaries that operate on files follow symbolic
-links and operate on the target of the link, rather than the link itself.
-
-@table @code
-@item -a @var{file}
-True if @var{file} exists.
-
-@item -b @var{file}
-True if @var{file} exists and is a block special file.
-
-@item -c @var{file}
-True if @var{file} exists and is a character special file.
-
-@item -d @var{file}
-True if @var{file} exists and is a directory.
-
-@item -e @var{file}
-True if @var{file} exists.
-
-@item -f @var{file}
-True if @var{file} exists and is a regular file.
-
-@item -g @var{file}
-True if @var{file} exists and its set-group-id bit is set.
-
-@item -h @var{file}
-True if @var{file} exists and is a symbolic link.
-
-@item -k @var{file}
-True if @var{file} exists and its "sticky" bit is set.
-
-@item -p @var{file}
-True if @var{file} exists and is a named pipe (FIFO).
-
-@item -r @var{file}
-True if @var{file} exists and is readable.
-
-@item -s @var{file}
-True if @var{file} exists and has a size greater than zero.
-
-@item -t @var{fd}
-True if file descriptor @var{fd} is open and refers to a terminal.
-
-@item -u @var{file}
-True if @var{file} exists and its set-user-id bit is set.
-
-@item -w @var{file}
-True if @var{file} exists and is writable.
-
-@item -x @var{file}
-True if @var{file} exists and is executable.
-
-@item -O @var{file}
-True if @var{file} exists and is owned by the effective user id.
-
-@item -G @var{file}
-True if @var{file} exists and is owned by the effective group id.
-
-@item -L @var{file}
-True if @var{file} exists and is a symbolic link.
-
-@item -S @var{file}
-True if @var{file} exists and is a socket.
-
-@item -N @var{file}
-True if @var{file} exists and has been modified since it was last read.
-
-@item @var{file1} -nt @var{file2}
-True if @var{file1} is newer (according to modification date)
-than @var{file2}, or if @var{file1} exists and @var{file2} does not.
-
-@item @var{file1} -ot @var{file2}
-True if @var{file1} is older than @var{file2},
-or if @var{file2} exists and @var{file1} does not.
-
-@item @var{file1} -ef @var{file2}
-True if @var{file1} and @var{file2} refer to the same device and
-inode numbers.
-
-@item -o @var{optname}
-True if shell option @var{optname} is enabled.
-The list of options appears in the description of the @option{-o}
-option to the @code{set} builtin (@pxref{The Set Builtin}).
-
-@item -z @var{string}
-True if the length of @var{string} is zero.
-
-@item -n @var{string}
-@itemx @var{string}
-True if the length of @var{string} is non-zero.
-
-@item @var{string1} == @var{string2}
-True if the strings are equal.
-@samp{=} may be used in place of @samp{==} for strict @sc{posix} compliance.
-
-@item @var{string1} != @var{string2}
-True if the strings are not equal.
-
-@item @var{string1} < @var{string2}
-True if @var{string1} sorts before @var{string2} lexicographically
-in the current locale.
-
-@item @var{string1} > @var{string2}
-True if @var{string1} sorts after @var{string2} lexicographically
-in the current locale.
-
-@item @var{arg1} OP @var{arg2}
-@code{OP} is one of
-@samp{-eq}, @samp{-ne}, @samp{-lt}, @samp{-le}, @samp{-gt}, or @samp{-ge}.
-These arithmetic binary operators return true if @var{arg1}
-is equal to, not equal to, less than, less than or equal to,
-greater than, or greater than or equal to @var{arg2},
-respectively. @var{Arg1} and @var{arg2}
-may be positive or negative integers.
-
-@end table
-
-@node Shell Arithmetic
-@section Shell Arithmetic
-@cindex arithmetic, shell
-@cindex shell arithmetic
-@cindex expressions, arithmetic
-@cindex evaluation, arithmetic
-@cindex arithmetic evaluation
-
-The shell allows arithmetic expressions to be evaluated, as one of
-the shell expansions or by the @code{let} and the @option{-i} option
-to the @code{declare} builtins.
-
-Evaluation is done in fixed-width integers with no check for overflow,
-though division by 0 is trapped and flagged as an error.
-The operators and their precedence, associativity, and values
-are the same as in the C language.
-The following list of operators is grouped into levels of
-equal-precedence operators.
-The levels are listed in order of decreasing precedence.
-
-@table @code
-
-@item @var{id}++ @var{id}--
-variable post-increment and post-decrement
-
-@item ++@var{id} --@var{id}
-variable pre-increment and pre-decrement
-
-@item - +
-unary minus and plus
-
-@item ! ~
-logical and bitwise negation
-
-@item **
-exponentiation
-
-@item * / %
-multiplication, division, remainder
-
-@item + -
-addition, subtraction
-
-@item << >>
-left and right bitwise shifts
-
-@item <= >= < >
-comparison
-
-@item == !=
-equality and inequality
-
-@item &
-bitwise AND
-
-@item ^
-bitwise exclusive OR
-
-@item |
-bitwise OR
-
-@item &&
-logical AND
-
-@item ||
-logical OR
-
-@item expr ? expr : expr
-conditional operator
-
-@item = *= /= %= += -= <<= >>= &= ^= |=
-assignment
-
-@item expr1 , expr2
-comma
-@end table
-
-Shell variables are allowed as operands; parameter expansion is
-performed before the expression is evaluated.
-Within an expression, shell variables may also be referenced by name
-without using the parameter expansion syntax.
-A shell variable that is null or unset evaluates to 0 when referenced
-by name without using the parameter expansion syntax.
-The value of a variable is evaluated as an arithmetic expression
-when it is referenced, or when a variable which has been given the
-@var{integer} attribute using @samp{declare -i} is assigned a value.
-A null value evaluates to 0.
-A shell variable need not have its integer attribute turned on
-to be used in an expression.
-
-Constants with a leading 0 are interpreted as octal numbers.
-A leading @samp{0x} or @samp{0X} denotes hexadecimal. Otherwise,
-numbers take the form [@var{base}@code{#}]@var{n}, where @var{base}
-is a decimal number between 2 and 64 representing the arithmetic
-base, and @var{n} is a number in that base. If @var{base}@code{#} is
-omitted, then base 10 is used.
-The digits greater than 9 are represented by the lowercase letters,
-the uppercase letters, @samp{@@}, and @samp{_}, in that order.
-If @var{base} is less than or equal to 36, lowercase and uppercase
-letters may be used interchangeably to represent numbers between 10
-and 35.
-
-Operators are evaluated in order of precedence. Sub-expressions in
-parentheses are evaluated first and may override the precedence
-rules above.
-
-@node Aliases
-@section Aliases
-@cindex alias expansion
-
-@var{Aliases} allow a string to be substituted for a word when it is used
-as the first word of a simple command.
-The shell maintains a list of aliases that may be set and unset with
-the @code{alias} and @code{unalias} builtin commands.
-
-The first word of each simple command, if unquoted, is checked to see
-if it has an alias.
-If so, that word is replaced by the text of the alias.
-The characters @samp{/}, @samp{$}, @samp{`}, @samp{=} and any of the
-shell metacharacters or quoting characters listed above may not appear
-in an alias name.
-The replacement text may contain any valid
-shell input, including shell metacharacters.
-The first word of the replacement text is tested for
-aliases, but a word that is identical to an alias being expanded
-is not expanded a second time.
-This means that one may alias @code{ls} to @code{"ls -F"},
-for instance, and Bash does not try to recursively expand the
-replacement text. If the last character of the alias value is a
-space or tab character, then the next command word following the
-alias is also checked for alias expansion.
-
-Aliases are created and listed with the @code{alias}
-command, and removed with the @code{unalias} command.
-
-There is no mechanism for using arguments in the replacement text,
-as in @code{csh}.
-If arguments are needed, a shell function should be used
-(@pxref{Shell Functions}).
-
-Aliases are not expanded when the shell is not interactive,
-unless the @code{expand_aliases} shell option is set using
-@code{shopt} (@pxref{Bash Builtins}).
-
-The rules concerning the definition and use of aliases are
-somewhat confusing. Bash
-always reads at least one complete line
-of input before executing any
-of the commands on that line. Aliases are expanded when a
-command is read, not when it is executed. Therefore, an
-alias definition appearing on the same line as another
-command does not take effect until the next line of input is read.
-The commands following the alias definition
-on that line are not affected by the new alias.
-This behavior is also an issue when functions are executed.
-Aliases are expanded when a function definition is read,
-not when the function is executed, because a function definition
-is itself a compound command. As a consequence, aliases
-defined in a function are not available until after that
-function is executed. To be safe, always put
-alias definitions on a separate line, and do not use @code{alias}
-in compound commands.
-
-For almost every purpose, shell functions are preferred over aliases.
-
-@node Arrays
-@section Arrays
-@cindex arrays
-
-Bash provides one-dimensional array variables. Any variable may be used as
-an array; the @code{declare} builtin will explicitly declare an array.
-There is no maximum
-limit on the size of an array, nor any requirement that members
-be indexed or assigned contiguously. Arrays are zero-based.
-
-An array is created automatically if any variable is assigned to using
-the syntax
-@example
-name[@var{subscript}]=@var{value}
-@end example
-
-@noindent
-The @var{subscript}
-is treated as an arithmetic expression that must evaluate to a number
-greater than or equal to zero. To explicitly declare an array, use
-@example
-declare -a @var{name}
-@end example
-@noindent
-The syntax
-@example
-declare -a @var{name}[@var{subscript}]
-@end example
-@noindent
-is also accepted; the @var{subscript} is ignored. Attributes may be
-specified for an array variable using the @code{declare} and
-@code{readonly} builtins. Each attribute applies to all members of
-an array.
-
-Arrays are assigned to using compound assignments of the form
-@example
-name=(value@var{1} @dots{} value@var{n})
-@end example
-@noindent
-where each
-@var{value} is of the form @code{[[@var{subscript}]=]}@var{string}. If
-the optional subscript is supplied, that index is assigned to;
-otherwise the index of the element assigned is the last index assigned
-to by the statement plus one. Indexing starts at zero.
-This syntax is also accepted by the @code{declare}
-builtin. Individual array elements may be assigned to using the
-@code{name[}@var{subscript}@code{]=}@var{value} syntax introduced above.
-
-Any element of an array may be referenced using
-@code{$@{name[}@var{subscript}@code{]@}}.
-The braces are required to avoid
-conflicts with the shell's filename expansion operators. If the
-@var{subscript} is @samp{@@} or @samp{*}, the word expands to all members
-of the array @var{name}. These subscripts differ only when the word
-appears within double quotes.
-If the word is double-quoted,
-@code{$@{name[*]@}} expands to a single word with
-the value of each array member separated by the first character of the
-@env{IFS} variable, and @code{$@{name[@@]@}} expands each element of
-@var{name} to a separate word. When there are no array members,
-@code{$@{name[@@]@}} expands to nothing.
-If the double-quoted expansion occurs within a word, the expansion of
-the first parameter is joined with the beginning part of the original
-word, and the expansion of the last parameter is joined with the last
-part of the original word.
-This is analogous to the
-expansion of the special parameters @samp{@@} and @samp{*}.
-@code{$@{#name[}@var{subscript}@code{]@}} expands to the length of
-@code{$@{name[}@var{subscript}@code{]@}}.
-If @var{subscript} is @samp{@@} or
-@samp{*}, the expansion is the number of elements in the array.
-Referencing an array variable without a subscript is equivalent to
-referencing element zero.
-
-The @code{unset} builtin is used to destroy arrays.
-@code{unset} @var{name}[@var{subscript}]
-destroys the array element at index @var{subscript}.
-Care must be taken to avoid unwanted side effects caused by filename
-generation.
-@code{unset} @var{name}, where @var{name} is an array, removes the
-entire array. A subscript of @samp{*} or @samp{@@} also removes the
-entire array.
-
-The @code{declare}, @code{local}, and @code{readonly}
-builtins each accept a @option{-a}
-option to specify an array. The @code{read}
-builtin accepts a @option{-a}
-option to assign a list of words read from the standard input
-to an array, and can read values from the standard input into
-individual array elements. The @code{set} and @code{declare}
-builtins display array values in a way that allows them to be
-reused as input.
-
-@node The Directory Stack
-@section The Directory Stack
-@cindex directory stack
-
-@menu
-* Directory Stack Builtins:: Bash builtin commands to manipulate
- the directory stack.
-@end menu
-
-The directory stack is a list of recently-visited directories. The
-@code{pushd} builtin adds directories to the stack as it changes
-the current directory, and the @code{popd} builtin removes specified
-directories from the stack and changes the current directory to
-the directory removed. The @code{dirs} builtin displays the contents
-of the directory stack.
-
-The contents of the directory stack are also visible
-as the value of the @env{DIRSTACK} shell variable.
-
-@node Directory Stack Builtins
-@subsection Directory Stack Builtins
-
-@table @code
-
-@item dirs
-@btindex dirs
-@example
-dirs [+@var{N} | -@var{N}] [-clpv]
-@end example
-Display the list of currently remembered directories. Directories
-are added to the list with the @code{pushd} command; the
-@code{popd} command removes directories from the list.
-@table @code
-@item +@var{N}
-Displays the @var{N}th directory (counting from the left of the
-list printed by @code{dirs} when invoked without options), starting
-with zero.
-@item -@var{N}
-Displays the @var{N}th directory (counting from the right of the
-list printed by @code{dirs} when invoked without options), starting
-with zero.
-@item -c
-Clears the directory stack by deleting all of the elements.
-@item -l
-Produces a longer listing; the default listing format uses a
-tilde to denote the home directory.
-@item -p
-Causes @code{dirs} to print the directory stack with one entry per
-line.
-@item -v
-Causes @code{dirs} to print the directory stack with one entry per
-line, prefixing each entry with its index in the stack.
-@end table
-
-@item popd
-@btindex popd
-@example
-popd [+@var{N} | -@var{N}] [-n]
-@end example
-
-Remove the top entry from the directory stack, and @code{cd}
-to the new top directory.
-When no arguments are given, @code{popd}
-removes the top directory from the stack and
-performs a @code{cd} to the new top directory. The
-elements are numbered from 0 starting at the first directory listed with
-@code{dirs}; i.e., @code{popd} is equivalent to @code{popd +0}.
-@table @code
-@item +@var{N}
-Removes the @var{N}th directory (counting from the left of the
-list printed by @code{dirs}), starting with zero.
-@item -@var{N}
-Removes the @var{N}th directory (counting from the right of the
-list printed by @code{dirs}), starting with zero.
-@item -n
-Suppresses the normal change of directory when removing directories
-from the stack, so that only the stack is manipulated.
-@end table
-
-@btindex pushd
-@item pushd
-@example
-pushd [@var{dir} | @var{+N} | @var{-N}] [-n]
-@end example
-
-Save the current directory on the top of the directory stack
-and then @code{cd} to @var{dir}.
-With no arguments, @code{pushd} exchanges the top two directories.
-
-@table @code
-@item +@var{N}
-Brings the @var{N}th directory (counting from the left of the
-list printed by @code{dirs}, starting with zero) to the top of
-the list by rotating the stack.
-@item -@var{N}
-Brings the @var{N}th directory (counting from the right of the
-list printed by @code{dirs}, starting with zero) to the top of
-the list by rotating the stack.
-@item -n
-Suppresses the normal change of directory when adding directories
-to the stack, so that only the stack is manipulated.
-@item @var{dir}
-Makes the current working directory be the top of the stack, and then
-executes the equivalent of `@code{cd} @var{dir}'.
-@code{cd}s to @var{dir}.
-@end table
-
-@end table
-
-@node Printing a Prompt
-@section Controlling the Prompt
-@cindex prompting
-
-The value of the variable @env{PROMPT_COMMAND} is examined just before
-Bash prints each primary prompt. If @env{PROMPT_COMMAND} is set and
-has a non-null value, then the
-value is executed just as if it had been typed on the command line.
-
-In addition, the following table describes the special characters which
-can appear in the prompt variables:
-
-@table @code
-@item \a
-A bell character.
-@item \d
-The date, in "Weekday Month Date" format (e.g., "Tue May 26").
-@item \D@{@var{format}@}
-The @var{format} is passed to @code{strftime}(3) and the result is inserted
-into the prompt string; an empty @var{format} results in a locale-specific
-time representation. The braces are required.
-@item \e
-An escape character.
-@item \h
-The hostname, up to the first `.'.
-@item \H
-The hostname.
-@item \j
-The number of jobs currently managed by the shell.
-@item \l
-The basename of the shell's terminal device name.
-@item \n
-A newline.
-@item \r
-A carriage return.
-@item \s
-The name of the shell, the basename of @code{$0} (the portion
-following the final slash).
-@item \t
-The time, in 24-hour HH:MM:SS format.
-@item \T
-The time, in 12-hour HH:MM:SS format.
-@item \@@
-The time, in 12-hour am/pm format.
-@item \A
-The time, in 24-hour HH:MM format.
-@item \u
-The username of the current user.
-@item \v
-The version of Bash (e.g., 2.00)
-@item \V
-The release of Bash, version + patchlevel (e.g., 2.00.0)
-@item \w
-The current working directory, with @env{$HOME} abbreviated with a tilde.
-@item \W
-The basename of @env{$PWD}, with @env{$HOME} abbreviated with a tilde.
-@item \!
-The history number of this command.
-@item \#
-The command number of this command.
-@item \$
-If the effective uid is 0, @code{#}, otherwise @code{$}.
-@item \@var{nnn}
-The character whose ASCII code is the octal value @var{nnn}.
-@item \\
-A backslash.
-@item \[
-Begin a sequence of non-printing characters. This could be used to
-embed a terminal control sequence into the prompt.
-@item \]
-End a sequence of non-printing characters.
-@end table
-
-The command number and the history number are usually different:
-the history number of a command is its position in the history
-list, which may include commands restored from the history file
-(@pxref{Bash History Facilities}), while the command number is
-the position in the sequence of commands executed during the current
-shell session.
-
-After the string is decoded, it is expanded via
-parameter expansion, command substitution, arithmetic
-expansion, and quote removal, subject to the value of the
-@code{promptvars} shell option (@pxref{Bash Builtins}).
-
-@node The Restricted Shell
-@section The Restricted Shell
-@cindex restricted shell
-
-If Bash is started with the name @code{rbash}, or the
-@option{--restricted}
-or
-@option{-r}
-option is supplied at invocation, the shell becomes restricted.
-A restricted shell is used to
-set up an environment more controlled than the standard shell.
-A restricted shell behaves identically to @code{bash}
-with the exception that the following are disallowed or not performed:
-
-@itemize @bullet
-@item
-Changing directories with the @code{cd} builtin.
-@item
-Setting or unsetting the values of the @env{SHELL}, @env{PATH},
-@env{ENV}, or @env{BASH_ENV} variables.
-@item
-Specifying command names containing slashes.
-@item
-Specifying a filename containing a slash as an argument to the @code{.}
-builtin command.
-@item
-Specifying a filename containing a slash as an argument to the @option{-p}
-option to the @code{hash} builtin command.
-@item
-Importing function definitions from the shell environment at startup.
-@item
-Parsing the value of @env{SHELLOPTS} from the shell environment at startup.
-@item
-Redirecting output using the @samp{>}, @samp{>|}, @samp{<>}, @samp{>&},
-@samp{&>}, and @samp{>>} redirection operators.
-@item
-Using the @code{exec} builtin to replace the shell with another command.
-@item
-Adding or deleting builtin commands with the
-@option{-f} and @option{-d} options to the @code{enable} builtin.
-@item
-Using the @code{enable} builtin command to enable disabled shell builtins.
-@item
-Specifying the @option{-p} option to the @code{command} builtin.
-@item
-Turning off restricted mode with @samp{set +r} or @samp{set +o restricted}.
-@end itemize
-
-These restrictions are enforced after any startup files are read.
-
-When a command that is found to be a shell script is executed
-(@pxref{Shell Scripts}), @code{rbash} turns off any restrictions in
-the shell spawned to execute the script.
-
-@node Bash POSIX Mode
-@section Bash POSIX Mode
-@cindex POSIX Mode
-
-Starting Bash with the @option{--posix} command-line option or executing
-@samp{set -o posix} while Bash is running will cause Bash to conform more
-closely to the @sc{posix} standard by changing the behavior to
-match that specified by @sc{posix} in areas where the Bash default differs.
-
-When invoked as @code{sh}, Bash enters @sc{posix} mode after reading the
-startup files.
-
-The following list is what's changed when `@sc{posix} mode' is in effect:
-
-@enumerate
-@item
-When a command in the hash table no longer exists, Bash will re-search
-@env{$PATH} to find the new location. This is also available with
-@samp{shopt -s checkhash}.
-
-@item
-The message printed by the job control code and builtins when a job
-exits with a non-zero status is `Done(status)'.
-
-@item
-The message printed by the job control code and builtins when a job
-is stopped is `Stopped(@var{signame})', where @var{signame} is, for
-example, @code{SIGTSTP}.
-
-@item
-The @code{bg} builtin uses the required format to describe each job placed
-in the background, which does not include an indication of whether the job
-is the current or previous job.
-
-@item
-Reserved words appearing in a context where reserved words are recognized
-do not undergo alias expansion.
-
-@item
-The @sc{posix} @env{PS1} and @env{PS2} expansions of @samp{!} to
-the history number and @samp{!!} to @samp{!} are enabled,
-and parameter expansion is performed on the values of @env{PS1} and
-@env{PS2} regardless of the setting of the @code{promptvars} option.
-
-@item
-The @sc{posix} startup files are executed (@env{$ENV}) rather than
-the normal Bash files.
-
-@item
-Tilde expansion is only performed on assignments preceding a command
-name, rather than on all assignment statements on the line.
-
-@item
-The default history file is @file{~/.sh_history} (this is the
-default value of @env{$HISTFILE}).
-
-@item
-The output of @samp{kill -l} prints all the signal names on a single line,
-separated by spaces, without the @samp{SIG} prefix.
-
-@item
-The @code{kill} builtin does not accept signal names with a @samp{SIG}
-prefix.
-
-@item
-Non-interactive shells exit if @var{filename} in @code{.} @var{filename}
-is not found.
-
-@item
-Non-interactive shells exit if a syntax error in an arithmetic expansion
-results in an invalid expression.
-
-@item
-Redirection operators do not perform filename expansion on the word
-in the redirection unless the shell is interactive.
-
-@item
-Redirection operators do not perform word splitting on the word in the
-redirection.
-
-@item
-Function names must be valid shell @code{name}s. That is, they may not
-contain characters other than letters, digits, and underscores, and
-may not start with a digit. Declaring a function with an invalid name
-causes a fatal syntax error in non-interactive shells.
-
-@item
-@sc{posix} special builtins are found before shell functions
-during command lookup.
-
-@item
-If a @sc{posix} special builtin returns an error status, a
-non-interactive shell exits. The fatal errors are those listed in
-the POSIX standard, and include things like passing incorrect options,
-redirection errors, variable assignment errors for assignments preceding
-the command name, and so on.
-
-@item
-If @env{CDPATH} is set, the @code{cd} builtin will not implicitly
-append the current directory to it. This means that @code{cd} will
-fail if no valid directory name can be constructed from
-any of the entries in @env{$CDPATH}, even if the a directory with
-the same name as the name given as an argument to @code{cd} exists
-in the current directory.
-
-@item
-A non-interactive shell exits with an error status if a variable
-assignment error occurs when no command name follows the assignment
-statements.
-A variable assignment error occurs, for example, when trying to assign
-a value to a readonly variable.
-
-@item
-A non-interactive shell exits with an error status if the iteration
-variable in a @code{for} statement or the selection variable in a
-@code{select} statement is a readonly variable.
-
-@item
-Process substitution is not available.
-
-@item
-Assignment statements preceding @sc{posix} special builtins
-persist in the shell environment after the builtin completes.
-
-@item
-Assignment statements preceding shell function calls persist in the
-shell environment after the function returns, as if a @sc{posix}
-special builtin command had been executed.
-
-@item
-The @code{export} and @code{readonly} builtin commands display their
-output in the format required by @sc{posix}.
-
-@item
-The @code{trap} builtin displays signal names without the leading
-@code{SIG}.
-
-@item
-The @code{trap} builtin doesn't check the first argument for a possible
-signal specification and revert the signal handling to the original
-disposition if it is, unless that argument consists solely of digits and
-is a valid signal number. If users want to reset the handler for a given
-signal to the original disposition, they should use @samp{-} as the
-first argument.
-
-@item
-The @code{.} and @code{source} builtins do not search the current directory
-for the filename argument if it is not found by searching @env{PATH}.
-
-@item
-Subshells spawned to execute command substitutions inherit the value of
-the @option{-e} option from the parent shell. When not in @sc{posix} mode,
-Bash clears the @option{-e} option in such subshells.
-
-@item
-Alias expansion is always enabled, even in non-interactive shells.
-
-@item
-When the @code{alias} builtin displays alias definitions, it does not
-display them with a leading @samp{alias } unless the @option{-p} option
-is supplied.
-
-@item
-When the @code{set} builtin is invoked without options, it does not display
-shell function names and definitions.
-
-@item
-When the @code{set} builtin is invoked without options, it displays
-variable values without quotes, unless they contain shell metacharacters,
-even if the result contains nonprinting characters.
-
-@item
-When the @code{cd} builtin is invoked in @var{logical} mode, and the pathname
-constructed from @code{$PWD} and the directory name supplied as an argument
-does not refer to an existing directory, @code{cd} will fail instead of
-falling back to @var{physical} mode.
-
-@item
-When the @code{pwd} builtin is supplied the @option{-P} option, it resets
-@code{$PWD} to a pathname containing no symlinks.
-
-@item
-The @code{pwd} builtin verifies that the value it prints is the same as the
-current directory, even if it is not asked to check the file system with the
-@option{-P} option.
-
-@item
-When listing the history, the @code{fc} builtin does not include an
-indication of whether or not a history entry has been modified.
-
-@item
-The default editor used by @code{fc} is @code{ed}.
-
-@item
-The @code{type} and @code{command} builtins will not report a non-executable
-file as having been found, though the shell will attempt to execute such a
-file if it is the only so-named file found in @code{$PATH}.
-
-@item
-The @code{vi} editing mode will invoke the @code{vi} editor directly when
-the @samp{v} command is run, instead of checking @code{$FCEDIT} and
-@code{$EDITOR}.
-
-@item
-When the @code{xpg_echo} option is enabled, Bash does not attempt to interpret
-any arguments to @code{echo} as options. Each argument is displayed, after
-escape characters are converted.
-
-@end enumerate
-
-There is other @sc{posix} behavior that Bash does not implement by
-default even when in @sc{posix} mode.
-Specifically:
-
-@enumerate
-
-@item
-The @code{fc} builtin checks @code{$EDITOR} as a program to edit history
-entries if @code{FCEDIT} is unset, rather than defaulting directly to
-@code{ed}. @code{fc} uses @code{ed} if @code{EDITOR} is unset.
-
-@item
-As noted above, Bash requires the @code{xpg_echo} option to be enabled for
-the @code{echo} builtin to be fully conformant.
-
-@end enumerate
-
-Bash can be configured to be @sc{posix}-conformant by default, by specifying
-the @option{--enable-strict-posix-default} to @code{configure} when building
-(@pxref{Optional Features}).
-
-@node Job Control
-@chapter Job Control
-
-This chapter discusses what job control is, how it works, and how
-Bash allows you to access its facilities.
-
-@menu
-* Job Control Basics:: How job control works.
-* Job Control Builtins:: Bash builtin commands used to interact
- with job control.
-* Job Control Variables:: Variables Bash uses to customize job
- control.
-@end menu
-
-@node Job Control Basics
-@section Job Control Basics
-@cindex job control
-@cindex foreground
-@cindex background
-@cindex suspending jobs
-
-Job control
-refers to the ability to selectively stop (suspend)
-the execution of processes and continue (resume)
-their execution at a later point. A user typically employs
-this facility via an interactive interface supplied jointly
-by the system's terminal driver and Bash.
-
-The shell associates a @var{job} with each pipeline. It keeps a
-table of currently executing jobs, which may be listed with the
-@code{jobs} command. When Bash starts a job
-asynchronously, it prints a line that looks
-like:
-@example
-[1] 25647
-@end example
-@noindent
-indicating that this job is job number 1 and that the process @sc{id}
-of the last process in the pipeline associated with this job is
-25647. All of the processes in a single pipeline are members of
-the same job. Bash uses the @var{job} abstraction as the
-basis for job control.
-
-To facilitate the implementation of the user interface to job
-control, the operating system maintains the notion of a current terminal
-process group @sc{id}. Members of this process group (processes whose
-process group @sc{id} is equal to the current terminal process group
-@sc{id}) receive keyboard-generated signals such as @code{SIGINT}.
-These processes are said to be in the foreground. Background
-processes are those whose process group @sc{id} differs from the
-terminal's; such processes are immune to keyboard-generated
-signals. Only foreground processes are allowed to read from or
-write to the terminal. Background processes which attempt to
-read from (write to) the terminal are sent a @code{SIGTTIN}
-(@code{SIGTTOU}) signal by the terminal driver, which, unless
-caught, suspends the process.
-
-If the operating system on which Bash is running supports
-job control, Bash contains facilities to use it. Typing the
-@var{suspend} character (typically @samp{^Z}, Control-Z) while a
-process is running causes that process to be stopped and returns
-control to Bash. Typing the @var{delayed suspend} character
-(typically @samp{^Y}, Control-Y) causes the process to be stopped
-when it attempts to read input from the terminal, and control to
-be returned to Bash. The user then manipulates the state of
-this job, using the @code{bg} command to continue it in the
-background, the @code{fg} command to continue it in the
-foreground, or the @code{kill} command to kill it. A @samp{^Z}
-takes effect immediately, and has the additional side effect of
-causing pending output and typeahead to be discarded.
-
-There are a number of ways to refer to a job in the shell. The
-character @samp{%} introduces a job name.
-
-Job number @code{n} may be referred to as @samp{%n}.
-The symbols @samp{%%} and @samp{%+} refer to the shell's notion of the
-current job, which is the last job stopped while it was in the foreground
-or started in the background.
-A single @samp{%} (with no accompanying job specification) also refers
-to the current job.
-The previous job may be referenced using @samp{%-}. In output
-pertaining to jobs (e.g., the output of the @code{jobs} command),
-the current job is always flagged with a @samp{+}, and the
-previous job with a @samp{-}.
-
-A job may also be referred to
-using a prefix of the name used to start it, or using a substring
-that appears in its command line. For example, @samp{%ce} refers
-to a stopped @code{ce} job. Using @samp{%?ce}, on the
-other hand, refers to any job containing the string @samp{ce} in
-its command line. If the prefix or substring matches more than one job,
-Bash reports an error.
-
-Simply naming a job can be used to bring it into the foreground:
-@samp{%1} is a synonym for @samp{fg %1}, bringing job 1 from the
-background into the foreground. Similarly, @samp{%1 &} resumes
-job 1 in the background, equivalent to @samp{bg %1}
-
-The shell learns immediately whenever a job changes state.
-Normally, Bash waits until it is about to print a prompt
-before reporting changes in a job's status so as to not interrupt
-any other output.
-If the @option{-b} option to the @code{set} builtin is enabled,
-Bash reports such changes immediately (@pxref{The Set Builtin}).
-Any trap on @code{SIGCHLD} is executed for each child process
-that exits.
-
-If an attempt to exit Bash is made while jobs are stopped, the
-shell prints a message warning that there are stopped jobs.
-The @code{jobs} command may then be used to inspect their status.
-If a second attempt to exit is made without an intervening command,
-Bash does not print another warning, and the stopped jobs are terminated.
-
-@node Job Control Builtins
-@section Job Control Builtins
-
-@table @code
-
-@item bg
-@btindex bg
-@example
-bg [@var{jobspec} @dots{}]
-@end example
-Resume each suspended job @var{jobspec} in the background, as if it
-had been started with @samp{&}.
-If @var{jobspec} is not supplied, the current job is used.
-The return status is zero unless it is run when job control is not
-enabled, or, when run with job control enabled, any
-@var{jobspec} was not found or specifies a job
-that was started without job control.
-
-@item fg
-@btindex fg
-@example
-fg [@var{jobspec}]
-@end example
-Resume the job @var{jobspec} in the foreground and make it the current job.
-If @var{jobspec} is not supplied, the current job is used.
-The return status is that of the command placed into the foreground,
-or non-zero if run when job control is disabled or, when run with
-job control enabled, @var{jobspec} does not specify a valid job or
-@var{jobspec} specifies a job that was started without job control.
-
-@item jobs
-@btindex jobs
-@example
-jobs [-lnprs] [@var{jobspec}]
-jobs -x @var{command} [@var{arguments}]
-@end example
-
-The first form lists the active jobs. The options have the
-following meanings:
-
-@table @code
-@item -l
-List process @sc{id}s in addition to the normal information.
-
-@item -n
-Display information only about jobs that have changed status since
-the user was last notified of their status.
-
-@item -p
-List only the process @sc{id} of the job's process group leader.
-
-@item -r
-Restrict output to running jobs.
-
-@item -s
-Restrict output to stopped jobs.
-@end table
-
-If @var{jobspec} is given,
-output is restricted to information about that job.
-If @var{jobspec} is not supplied, the status of all jobs is
-listed.
-
-If the @option{-x} option is supplied, @code{jobs} replaces any
-@var{jobspec} found in @var{command} or @var{arguments} with the
-corresponding process group @sc{id}, and executes @var{command},
-passing it @var{argument}s, returning its exit status.
-
-@item kill
-@btindex kill
-@example
-kill [-s @var{sigspec}] [-n @var{signum}] [-@var{sigspec}] @var{jobspec} or @var{pid}
-kill -l [@var{exit_status}]
-@end example
-Send a signal specified by @var{sigspec} or @var{signum} to the process
-named by job specification @var{jobspec} or process @sc{id} @var{pid}.
-@var{sigspec} is either a case-insensitive signal name such as
-@code{SIGINT} (with or without the @code{SIG} prefix)
-or a signal number; @var{signum} is a signal number.
-If @var{sigspec} and @var{signum} are not present, @code{SIGTERM} is used.
-The @option{-l} option lists the signal names.
-If any arguments are supplied when @option{-l} is given, the names of the
-signals corresponding to the arguments are listed, and the return status
-is zero.
-@var{exit_status} is a number specifying a signal number or the exit
-status of a process terminated by a signal.
-The return status is zero if at least one signal was successfully sent,
-or non-zero if an error occurs or an invalid option is encountered.
-
-@item wait
-@btindex wait
-@example
-wait [@var{jobspec} or @var{pid} ...]
-@end example
-Wait until the child process specified by each process @sc{id} @var{pid}
-or job specification @var{jobspec} exits and return the exit status of the
-last command waited for.
-If a job spec is given, all processes in the job are waited for.
-If no arguments are given, all currently active child processes are
-waited for, and the return status is zero.
-If neither @var{jobspec} nor @var{pid} specifies an active child process
-of the shell, the return status is 127.
-
-@item disown
-@btindex disown
-@example
-disown [-ar] [-h] [@var{jobspec} @dots{}]
-@end example
-Without options, each @var{jobspec} is removed from the table of
-active jobs.
-If the @option{-h} option is given, the job is not removed from the table,
-but is marked so that @code{SIGHUP} is not sent to the job if the shell
-receives a @code{SIGHUP}.
-If @var{jobspec} is not present, and neither the @option{-a} nor @option{-r}
-option is supplied, the current job is used.
-If no @var{jobspec} is supplied, the @option{-a} option means to remove or
-mark all jobs; the @option{-r} option without a @var{jobspec}
-argument restricts operation to running jobs.
-
-@item suspend
-@btindex suspend
-@example
-suspend [-f]
-@end example
-Suspend the execution of this shell until it receives a
-@code{SIGCONT} signal. The @option{-f} option means to suspend
-even if the shell is a login shell.
-
-@end table
-
-When job control is not active, the @code{kill} and @code{wait}
-builtins do not accept @var{jobspec} arguments. They must be
-supplied process @sc{id}s.
-
-@node Job Control Variables
-@section Job Control Variables
-
-@vtable @code
-
-@item auto_resume
-This variable controls how the shell interacts with the user and
-job control. If this variable exists then single word simple
-commands without redirections are treated as candidates for resumption
-of an existing job. There is no ambiguity allowed; if there is
-more than one job beginning with the string typed, then
-the most recently accessed job will be selected.
-The name of a stopped job, in this context, is the command line
-used to start it. If this variable is set to the value @samp{exact},
-the string supplied must match the name of a stopped job exactly;
-if set to @samp{substring},
-the string supplied needs to match a substring of the name of a
-stopped job. The @samp{substring} value provides functionality
-analogous to the @samp{%?} job @sc{id} (@pxref{Job Control Basics}).
-If set to any other value, the supplied string must
-be a prefix of a stopped job's name; this provides functionality
-analogous to the @samp{%} job @sc{id}.
-
-@end vtable
-
-@set readline-appendix
-@set history-appendix
-@cindex Readline, how to use
-@include rluser.texi
-@cindex History, how to use
-@include hsuser.texi
-@clear readline-appendix
-@clear history-appendix
-
-@node Installing Bash
-@chapter Installing Bash
-
-This chapter provides basic instructions for installing Bash on
-the various supported platforms. The distribution supports the
-@sc{gnu} operating systems, nearly every version of Unix, and several
-non-Unix systems such as BeOS and Interix.
-Other independent ports exist for
-@sc{ms-dos}, @sc{os/2}, and Windows platforms.
-
-@menu
-* Basic Installation:: Installation instructions.
-* Compilers and Options:: How to set special options for various
- systems.
-* Compiling For Multiple Architectures:: How to compile Bash for more
- than one kind of system from
- the same source tree.
-* Installation Names:: How to set the various paths used by the installation.
-* Specifying the System Type:: How to configure Bash for a particular system.
-* Sharing Defaults:: How to share default configuration values among GNU
- programs.
-* Operation Controls:: Options recognized by the configuration program.
-* Optional Features:: How to enable and disable optional features when
- building Bash.
-@end menu
-
-@node Basic Installation
-@section Basic Installation
-@cindex installation
-@cindex configuration
-@cindex Bash installation
-@cindex Bash configuration
-
-These are installation instructions for Bash.
-
-The simplest way to compile Bash is:
-
-@enumerate
-@item
-@code{cd} to the directory containing the source code and type
-@samp{./configure} to configure Bash for your system. If you're
-using @code{csh} on an old version of System V, you might need to
-type @samp{sh ./configure} instead to prevent @code{csh} from trying
-to execute @code{configure} itself.
-
-Running @code{configure} takes some time.
-While running, it prints messages telling which features it is
-checking for.
-
-@item
-Type @samp{make} to compile Bash and build the @code{bashbug} bug
-reporting script.
-
-@item
-Optionally, type @samp{make tests} to run the Bash test suite.
-
-@item
-Type @samp{make install} to install @code{bash} and @code{bashbug}.
-This will also install the manual pages and Info file.
-
-@end enumerate
-
-The @code{configure} shell script attempts to guess correct
-values for various system-dependent variables used during
-compilation. It uses those values to create a @file{Makefile} in
-each directory of the package (the top directory, the
-@file{builtins}, @file{doc}, and @file{support} directories,
-each directory under @file{lib}, and several others). It also creates a
-@file{config.h} file containing system-dependent definitions.
-Finally, it creates a shell script named @code{config.status} that you
-can run in the future to recreate the current configuration, a
-file @file{config.cache} that saves the results of its tests to
-speed up reconfiguring, and a file @file{config.log} containing
-compiler output (useful mainly for debugging @code{configure}).
-If at some point
-@file{config.cache} contains results you don't want to keep, you
-may remove or edit it.
-
-To find out more about the options and arguments that the
-@code{configure} script understands, type
-
-@example
-bash-2.04$ ./configure --help
-@end example
-
-@noindent
-at the Bash prompt in your Bash source directory.
-
-If you need to do unusual things to compile Bash, please
-try to figure out how @code{configure} could check whether or not
-to do them, and mail diffs or instructions to
-@email{bash-maintainers@@gnu.org} so they can be
-considered for the next release.
-
-The file @file{configure.in} is used to create @code{configure}
-by a program called Autoconf. You only need
-@file{configure.in} if you want to change it or regenerate
-@code{configure} using a newer version of Autoconf. If
-you do this, make sure you are using Autoconf version 2.50 or
-newer.
-
-You can remove the program binaries and object files from the
-source code directory by typing @samp{make clean}. To also remove the
-files that @code{configure} created (so you can compile Bash for
-a different kind of computer), type @samp{make distclean}.
-
-@node Compilers and Options
-@section Compilers and Options
-
-Some systems require unusual options for compilation or linking
-that the @code{configure} script does not know about. You can
-give @code{configure} initial values for variables by setting
-them in the environment. Using a Bourne-compatible shell, you
-can do that on the command line like this:
-
-@example
-CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
-@end example
-
-On systems that have the @code{env} program, you can do it like this:
-
-@example
-env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
-@end example
-
-The configuration process uses GCC to build Bash if it
-is available.
-
-@node Compiling For Multiple Architectures
-@section Compiling For Multiple Architectures
-
-You can compile Bash for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory. To do this, you must use a version of @code{make} that
-supports the @code{VPATH} variable, such as GNU @code{make}.
-@code{cd} to the
-directory where you want the object files and executables to go and run
-the @code{configure} script from the source directory. You may need to
-supply the @option{--srcdir=PATH} argument to tell @code{configure} where the
-source files are. @code{configure} automatically checks for the
-source code in the directory that @code{configure} is in and in `..'.
-
-If you have to use a @code{make} that does not supports the @code{VPATH}
-variable, you can compile Bash for one architecture at a
-time in the source code directory. After you have installed
-Bash for one architecture, use @samp{make distclean} before
-reconfiguring for another architecture.
-
-Alternatively, if your system supports symbolic links, you can use the
-@file{support/mkclone} script to create a build tree which has
-symbolic links back to each file in the source directory. Here's an
-example that creates a build directory in the current directory from a
-source directory @file{/usr/gnu/src/bash-2.0}:
-
-@example
-bash /usr/gnu/src/bash-2.0/support/mkclone -s /usr/gnu/src/bash-2.0 .
-@end example
-
-@noindent
-The @code{mkclone} script requires Bash, so you must have already built
-Bash for at least one architecture before you can create build
-directories for other architectures.
-
-@node Installation Names
-@section Installation Names
-
-By default, @samp{make install} will install into
-@file{/usr/local/bin}, @file{/usr/local/man}, etc. You can
-specify an installation prefix other than @file{/usr/local} by
-giving @code{configure} the option @option{--prefix=@var{PATH}},
-or by specifying a value for the @code{DESTDIR} @samp{make}
-variable when running @samp{make install}.
-
-You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.
-If you give @code{configure} the option
-@option{--exec-prefix=@var{PATH}}, @samp{make install} will use
-@var{PATH} as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
-
-@node Specifying the System Type
-@section Specifying the System Type
-
-There may be some features @code{configure} can not figure out
-automatically, but need to determine by the type of host Bash
-will run on. Usually @code{configure} can figure that
-out, but if it prints a message saying it can not guess the host
-type, give it the @option{--host=TYPE} option. @samp{TYPE} can
-either be a short name for the system type, such as @samp{sun4},
-or a canonical name with three fields: @samp{CPU-COMPANY-SYSTEM}
-(e.g., @samp{i386-unknown-freebsd4.2}).
-
-See the file @file{support/config.sub} for the possible
-values of each field.
-
-@node Sharing Defaults
-@section Sharing Defaults
-
-If you want to set default values for @code{configure} scripts to
-share, you can create a site shell script called
-@code{config.site} that gives default values for variables like
-@code{CC}, @code{cache_file}, and @code{prefix}. @code{configure}
-looks for @file{PREFIX/share/config.site} if it exists, then
-@file{PREFIX/etc/config.site} if it exists. Or, you can set the
-@code{CONFIG_SITE} environment variable to the location of the site
-script. A warning: the Bash @code{configure} looks for a site script,
-but not all @code{configure} scripts do.
-
-@node Operation Controls
-@section Operation Controls
-
-@code{configure} recognizes the following options to control how it
-operates.
-
-@table @code
-
-@item --cache-file=@var{file}
-Use and save the results of the tests in
-@var{file} instead of @file{./config.cache}. Set @var{file} to
-@file{/dev/null} to disable caching, for debugging
-@code{configure}.
-
-@item --help
-Print a summary of the options to @code{configure}, and exit.
-
-@item --quiet
-@itemx --silent
-@itemx -q
-Do not print messages saying which checks are being made.
-
-@item --srcdir=@var{dir}
-Look for the Bash source code in directory @var{dir}. Usually
-@code{configure} can determine that directory automatically.
-
-@item --version
-Print the version of Autoconf used to generate the @code{configure}
-script, and exit.
-@end table
-
-@code{configure} also accepts some other, not widely used, boilerplate
-options. @samp{configure --help} prints the complete list.
-
-@node Optional Features
-@section Optional Features
-
-The Bash @code{configure} has a number of @option{--enable-@var{feature}}
-options, where @var{feature} indicates an optional part of Bash.
-There are also several @option{--with-@var{package}} options,
-where @var{package} is something like @samp{bash-malloc} or @samp{purify}.
-To turn off the default use of a package, use
-@option{--without-@var{package}}. To configure Bash without a feature
-that is enabled by default, use @option{--disable-@var{feature}}.
-
-Here is a complete list of the @option{--enable-} and
-@option{--with-} options that the Bash @code{configure} recognizes.
-
-@table @code
-@item --with-afs
-Define if you are using the Andrew File System from Transarc.
-
-@item --with-bash-malloc
-Use the Bash version of
-@code{malloc} in the directory @file{lib/malloc}. This is not the same
-@code{malloc} that appears in @sc{gnu} libc, but an older version
-originally derived from the 4.2 @sc{bsd} @code{malloc}. This @code{malloc}
-is very fast, but wastes some space on each allocation.
-This option is enabled by default.
-The @file{NOTES} file contains a list of systems for
-which this should be turned off, and @code{configure} disables this
-option automatically for a number of systems.
-
-@item --with-curses
-Use the curses library instead of the termcap library. This should
-be supplied if your system has an inadequate or incomplete termcap
-database.
-
-@item --with-gnu-malloc
-A synonym for @code{--with-bash-malloc}.
-
-@item --with-installed-readline[=@var{PREFIX}]
-Define this to make Bash link with a locally-installed version of Readline
-rather than the version in @file{lib/readline}. This works only with
-Readline 5.0 and later versions. If @var{PREFIX} is @code{yes} or not
-supplied, @code{configure} uses the values of the make variables
-@code{includedir} and @code{libdir}, which are subdirectories of @code{prefix}
-by default, to find the installed version of Readline if it is not in
-the standard system include and library directories.
-If @var{PREFIX} is @code{no}, Bash links with the version in
-@file{lib/readline}.
-If @var{PREFIX} is set to any other value, @code{configure} treats it as
-a directory pathname and looks for
-the installed version of Readline in subdirectories of that directory
-(include files in @var{PREFIX}/@code{include} and the library in
-@var{PREFIX}/@code{lib}).
-
-@item --with-purify
-Define this to use the Purify memory allocation checker from Rational
-Software.
-
-@item --enable-minimal-config
-This produces a shell with minimal features, close to the historical
-Bourne shell.
-@end table
-
-There are several @option{--enable-} options that alter how Bash is
-compiled and linked, rather than changing run-time features.
-
-@table @code
-@item --enable-largefile
-Enable support for @uref{http://www.sas.com/standards/large_file/x_open.20Mar96.html,
-large files} if the operating system requires special compiler options
-to build programs which can access large files. This is enabled by
-default, if the operating system provides large file support.
-
-@item --enable-profiling
-This builds a Bash binary that produces profiling information to be
-processed by @code{gprof} each time it is executed.
-
-@item --enable-static-link
-This causes Bash to be linked statically, if @code{gcc} is being used.
-This could be used to build a version to use as root's shell.
-@end table
-
-The @samp{minimal-config} option can be used to disable all of
-the following options, but it is processed first, so individual
-options may be enabled using @samp{enable-@var{feature}}.
-
-All of the following options except for @samp{disabled-builtins} and
-@samp{xpg-echo-default} are
-enabled by default, unless the operating system does not provide the
-necessary support.
-
-@table @code
-@item --enable-alias
-Allow alias expansion and include the @code{alias} and @code{unalias}
-builtins (@pxref{Aliases}).
-
-@item --enable-arith-for-command
-Include support for the alternate form of the @code{for} command
-that behaves like the C language @code{for} statement
-(@pxref{Looping Constructs}).
-
-@item --enable-array-variables
-Include support for one-dimensional array shell variables
-(@pxref{Arrays}).
-
-@item --enable-bang-history
-Include support for @code{csh}-like history substitution
-(@pxref{History Interaction}).
-
-@item --enable-brace-expansion
-Include @code{csh}-like brace expansion
-( @code{b@{a,b@}c} @expansion{} @code{bac bbc} ).
-See @ref{Brace Expansion}, for a complete description.
-
-@item --enable-command-timing
-Include support for recognizing @code{time} as a reserved word and for
-displaying timing statistics for the pipeline following @code{time}
-(@pxref{Pipelines}).
-This allows pipelines as well as shell builtins and functions to be timed.
-
-@item --enable-cond-command
-Include support for the @code{[[} conditional command.
-(@pxref{Conditional Constructs}).
-
-@item --enable-cond-regexp
-Include support for matching POSIX regular expressions using the
-@samp{=~} binary operator in the @code{[[} conditional command.
-(@pxref{Conditional Constructs}).
-
-@item --enable-debugger
-Include support for the bash debugger (distributed separately).
-
-@item --enable-directory-stack
-Include support for a @code{csh}-like directory stack and the
-@code{pushd}, @code{popd}, and @code{dirs} builtins
-(@pxref{The Directory Stack}).
-
-@item --enable-disabled-builtins
-Allow builtin commands to be invoked via @samp{builtin xxx}
-even after @code{xxx} has been disabled using @samp{enable -n xxx}.
-See @ref{Bash Builtins}, for details of the @code{builtin} and
-@code{enable} builtin commands.
-
-@item --enable-dparen-arithmetic
-Include support for the @code{((@dots{}))} command
-(@pxref{Conditional Constructs}).
-
-@item --enable-extended-glob
-Include support for the extended pattern matching features described
-above under @ref{Pattern Matching}.
-
-@item --enable-help-builtin
-Include the @code{help} builtin, which displays help on shell builtins and
-variables (@pxref{Bash Builtins}).
-
-@item --enable-history
-Include command history and the @code{fc} and @code{history}
-builtin commands (@pxref{Bash History Facilities}).
-
-@item --enable-job-control
-This enables the job control features (@pxref{Job Control}),
-if the operating system supports them.
-
-@item --enable-multibyte
-This enables support for multibyte characters if the operating
-system provides the necessary support.
-
-@item --enable-net-redirections
-This enables the special handling of filenames of the form
-@code{/dev/tcp/@var{host}/@var{port}} and
-@code{/dev/udp/@var{host}/@var{port}}
-when used in redirections (@pxref{Redirections}).
-
-@item --enable-process-substitution
-This enables process substitution (@pxref{Process Substitution}) if
-the operating system provides the necessary support.
-
-@item --enable-progcomp
-Enable the programmable completion facilities
-(@pxref{Programmable Completion}).
-If Readline is not enabled, this option has no effect.
-
-@item --enable-prompt-string-decoding
-Turn on the interpretation of a number of backslash-escaped characters
-in the @env{$PS1}, @env{$PS2}, @env{$PS3}, and @env{$PS4} prompt
-strings. See @ref{Printing a Prompt}, for a complete list of prompt
-string escape sequences.
-
-@item --enable-readline
-Include support for command-line editing and history with the Bash
-version of the Readline library (@pxref{Command Line Editing}).
-
-@item --enable-restricted
-Include support for a @dfn{restricted shell}. If this is enabled, Bash,
-when called as @code{rbash}, enters a restricted mode. See
-@ref{The Restricted Shell}, for a description of restricted mode.
-
-@item --enable-select
-Include the @code{select} builtin, which allows the generation of simple
-menus (@pxref{Conditional Constructs}).
-
-@item --enable-separate-helpfiles
-Use external files for the documentation displayed by the @code{help} builtin
-instead of storing the text internally.
-
-@item --enable-single-help-strings
-Store the text displayed by the @code{help} builtin as a single string for
-each help topic. This aids in translating the text to different languages.
-You may need to disable this if your compiler cannot handle very long string
-literals.
-
-@item --enable-strict-posix-default
-Make Bash @sc{posix}-conformant by default (@pxref{Bash POSIX Mode}).
-
-@item --enable-usg-echo-default
-A synonym for @code{--enable-xpg-echo-default}.
-
-@item --enable-xpg-echo-default
-Make the @code{echo} builtin expand backslash-escaped characters by default,
-without requiring the @option{-e} option.
-This sets the default value of the @code{xpg_echo} shell option to @code{on},
-which makes the Bash @code{echo} behave more like the version specified in
-the Single Unix Specification, version 3.
-@xref{Bash Builtins}, for a description of the escape sequences that
-@code{echo} recognizes.
-
-@end table
-
-The file @file{config-top.h} contains C Preprocessor
-@samp{#define} statements for options which are not settable from
-@code{configure}.
-Some of these are not meant to be changed; beware of the consequences if
-you do.
-Read the comments associated with each definition for more
-information about its effect.
-
-@node Reporting Bugs
-@appendix Reporting Bugs
-
-Please report all bugs you find in Bash.
-But first, you should
-make sure that it really is a bug, and that it appears in the latest
-version of Bash.
-The latest version of Bash is always available for FTP from
-@uref{ftp://ftp.gnu.org/pub/bash/}.
-
-Once you have determined that a bug actually exists, use the
-@code{bashbug} command to submit a bug report.
-If you have a fix, you are encouraged to mail that as well!
-Suggestions and `philosophical' bug reports may be mailed
-to @email{bug-bash@@gnu.org} or posted to the Usenet
-newsgroup @code{gnu.bash.bug}.
-
-All bug reports should include:
-@itemize @bullet
-@item
-The version number of Bash.
-@item
-The hardware and operating system.
-@item
-The compiler used to compile Bash.
-@item
-A description of the bug behaviour.
-@item
-A short script or `recipe' which exercises the bug and may be used
-to reproduce it.
-@end itemize
-
-@noindent
-@code{bashbug} inserts the first three items automatically into
-the template it provides for filing a bug report.
-
-Please send all reports concerning this manual to
-@email{chet@@po.CWRU.Edu}.
-
-@node Major Differences From The Bourne Shell
-@appendix Major Differences From The Bourne Shell
-
-Bash implements essentially the same grammar, parameter and
-variable expansion, redirection, and quoting as the Bourne Shell.
-Bash uses the @sc{posix} standard as the specification of
-how these features are to be implemented. There are some
-differences between the traditional Bourne shell and Bash; this
-section quickly details the differences of significance. A
-number of these differences are explained in greater depth in
-previous sections.
-This section uses the version of @code{sh} included in SVR4.2 (the
-last version of the historical Bourne shell) as the baseline reference.
-
-@itemize @bullet
-
-@item
-Bash is @sc{posix}-conformant, even where the @sc{posix} specification
-differs from traditional @code{sh} behavior (@pxref{Bash POSIX Mode}).
-
-@item
-Bash has multi-character invocation options (@pxref{Invoking Bash}).
-
-@item
-Bash has command-line editing (@pxref{Command Line Editing}) and
-the @code{bind} builtin.
-
-@item
-Bash provides a programmable word completion mechanism
-(@pxref{Programmable Completion}), and two builtin commands,
-@code{complete} and @code{compgen}, to manipulate it.
-
-@item
-Bash has command history (@pxref{Bash History Facilities}) and the
-@code{history} and @code{fc} builtins to manipulate it.
-The Bash history list maintains timestamp information and uses the
-value of the @code{HISTTIMEFORMAT} variable to display it.
-
-@item
-Bash implements @code{csh}-like history expansion
-(@pxref{History Interaction}).
-
-@item
-Bash has one-dimensional array variables (@pxref{Arrays}), and the
-appropriate variable expansions and assignment syntax to use them.
-Several of the Bash builtins take options to act on arrays.
-Bash provides a number of built-in array variables.
-
-@item
-The @code{$'@dots{}'} quoting syntax, which expands ANSI-C
-backslash-escaped characters in the text between the single quotes,
-is supported (@pxref{ANSI-C Quoting}).
-
-@item
-Bash supports the @code{$"@dots{}"} quoting syntax to do
-locale-specific translation of the characters between the double
-quotes. The @option{-D}, @option{--dump-strings}, and @option{--dump-po-strings}
-invocation options list the translatable strings found in a script
-(@pxref{Locale Translation}).
-
-@item
-Bash implements the @code{!} keyword to negate the return value of
-a pipeline (@pxref{Pipelines}).
-Very useful when an @code{if} statement needs to act only if a test fails.
-The Bash @samp{-o pipefail} option to @code{set} will cause a pipeline to
-return a failure status if any command fails.
-
-@item
-Bash has the @code{time} reserved word and command timing (@pxref{Pipelines}).
-The display of the timing statistics may be controlled with the
-@env{TIMEFORMAT} variable.
-
-@item
-Bash implements the @code{for (( @var{expr1} ; @var{expr2} ; @var{expr3} ))}
-arithmetic for command, similar to the C language (@pxref{Looping Constructs}).
-
-@item
-Bash includes the @code{select} compound command, which allows the
-generation of simple menus (@pxref{Conditional Constructs}).
-
-@item
-Bash includes the @code{[[} compound command, which makes conditional
-testing part of the shell grammar (@pxref{Conditional Constructs}), including
-optional regular expression matching.
-
-@item
-Bash provides optional case-insensitive matching for the @code{case} and
-@code{[[} constructs.
-
-@item
-Bash includes brace expansion (@pxref{Brace Expansion}) and tilde
-expansion (@pxref{Tilde Expansion}).
-
-@item
-Bash implements command aliases and the @code{alias} and @code{unalias}
-builtins (@pxref{Aliases}).
-
-@item
-Bash provides shell arithmetic, the @code{((} compound command
-(@pxref{Conditional Constructs}),
-and arithmetic expansion (@pxref{Shell Arithmetic}).
-
-@item
-Variables present in the shell's initial environment are automatically
-exported to child processes. The Bourne shell does not normally do
-this unless the variables are explicitly marked using the @code{export}
-command.
-
-@item
-Bash supports the @samp{+=} assignment operator, which appends to the value
-of the variable named on the left hand side.
-
-@item
-Bash includes the @sc{posix} pattern removal @samp{%}, @samp{#}, @samp{%%}
-and @samp{##} expansions to remove leading or trailing substrings from
-variable values (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{#xx@}}, which returns the length of @code{$@{xx@}},
-is supported (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{var:}@var{offset}@code{[:}@var{length}@code{]@}},
-which expands to the substring of @code{var}'s value of length
-@var{length}, beginning at @var{offset}, is present
-(@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion
-@code{$@{var/[/]}@var{pattern}@code{[/}@var{replacement}@code{]@}},
-which matches @var{pattern} and replaces it with @var{replacement} in
-the value of @code{var}, is available (@pxref{Shell Parameter Expansion}).
-
-@item
-The expansion @code{$@{!@var{prefix@}*}} expansion, which expands to
-the names of all shell variables whose names begin with @var{prefix},
-is available (@pxref{Shell Parameter Expansion}).
-
-@item
-Bash has @var{indirect} variable expansion using @code{$@{!word@}}
-(@pxref{Shell Parameter Expansion}).
-
-@item
-Bash can expand positional parameters beyond @code{$9} using
-@code{$@{@var{num}@}}.
-
-@item
-The @sc{posix} @code{$()} form of command substitution
-is implemented (@pxref{Command Substitution}),
-and preferred to the Bourne shell's @code{``} (which
-is also implemented for backwards compatibility).
-
-@item
-Bash has process substitution (@pxref{Process Substitution}).
-
-@item
-Bash automatically assigns variables that provide information about the
-current user (@env{UID}, @env{EUID}, and @env{GROUPS}), the current host
-(@env{HOSTTYPE}, @env{OSTYPE}, @env{MACHTYPE}, and @env{HOSTNAME}),
-and the instance of Bash that is running (@env{BASH},
-@env{BASH_VERSION}, and @env{BASH_VERSINFO}). @xref{Bash Variables},
-for details.
-
-@item
-The @env{IFS} variable is used to split only the results of expansion,
-not all words (@pxref{Word Splitting}).
-This closes a longstanding shell security hole.
-
-@item
-Bash implements the full set of @sc{posix} filename expansion operators,
-including @var{character classes}, @var{equivalence classes}, and
-@var{collating symbols} (@pxref{Filename Expansion}).
-
-@item
-Bash implements extended pattern matching features when the @code{extglob}
-shell option is enabled (@pxref{Pattern Matching}).
-
-@item
-It is possible to have a variable and a function with the same name;
-@code{sh} does not separate the two name spaces.
-
-@item
-Bash functions are permitted to have local variables using the
-@code{local} builtin, and thus useful recursive functions may be written
-(@pxref{Bash Builtins}).
-
-@item
-Variable assignments preceding commands affect only that command, even
-builtins and functions (@pxref{Environment}).
-In @code{sh}, all variable assignments
-preceding commands are global unless the command is executed from the
-file system.
-
-@item
-Bash performs filename expansion on filenames specified as operands
-to input and output redirection operators (@pxref{Redirections}).
-
-@item
-Bash contains the @samp{<>} redirection operator, allowing a file to be
-opened for both reading and writing, and the @samp{&>} redirection
-operator, for directing standard output and standard error to the same
-file (@pxref{Redirections}).
-
-@item
-Bash includes the @samp{<<<} redirection operator, allowing a string to
-be used as the standard input to a command.
-
-@item
-Bash implements the @samp{[n]<&@var{word}} and @samp{[n]>&@var{word}}
-redirection operators, which move one file descriptor to another.
-
-@item
-Bash treats a number of filenames specially when they are
-used in redirection operators (@pxref{Redirections}).
-
-@item
-Bash can open network connections to arbitrary machines and services
-with the redirection operators (@pxref{Redirections}).
-
-@item
-The @code{noclobber} option is available to avoid overwriting existing
-files with output redirection (@pxref{The Set Builtin}).
-The @samp{>|} redirection operator may be used to override @code{noclobber}.
-
-@item
-The Bash @code{cd} and @code{pwd} builtins (@pxref{Bourne Shell Builtins})
-each take @option{-L} and @option{-P} options to switch between logical and
-physical modes.
-
-@item
-Bash allows a function to override a builtin with the same name, and provides
-access to that builtin's functionality within the function via the
-@code{builtin} and @code{command} builtins (@pxref{Bash Builtins}).
-
-@item
-The @code{command} builtin allows selective disabling of functions
-when command lookup is performed (@pxref{Bash Builtins}).
-
-@item
-Individual builtins may be enabled or disabled using the @code{enable}
-builtin (@pxref{Bash Builtins}).
-
-@item
-The Bash @code{exec} builtin takes additional options that allow users
-to control the contents of the environment passed to the executed
-command, and what the zeroth argument to the command is to be
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Shell functions may be exported to children via the environment
-using @code{export -f} (@pxref{Shell Functions}).
-
-@item
-The Bash @code{export}, @code{readonly}, and @code{declare} builtins can
-take a @option{-f} option to act on shell functions, a @option{-p} option to
-display variables with various attributes set in a format that can be
-used as shell input, a @option{-n} option to remove various variable
-attributes, and @samp{name=value} arguments to set variable attributes
-and values simultaneously.
-
-@item
-The Bash @code{hash} builtin allows a name to be associated with
-an arbitrary filename, even when that filename cannot be found by
-searching the @env{$PATH}, using @samp{hash -p}
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Bash includes a @code{help} builtin for quick reference to shell
-facilities (@pxref{Bash Builtins}).
-
-@item
-The @code{printf} builtin is available to display formatted output
-(@pxref{Bash Builtins}).
-
-@item
-The Bash @code{read} builtin (@pxref{Bash Builtins})
-will read a line ending in @samp{\} with
-the @option{-r} option, and will use the @env{REPLY} variable as a
-default if no non-option arguments are supplied.
-The Bash @code{read} builtin
-also accepts a prompt string with the @option{-p} option and will use
-Readline to obtain the line when given the @option{-e} option.
-The @code{read} builtin also has additional options to control input:
-the @option{-s} option will turn off echoing of input characters as
-they are read, the @option{-t} option will allow @code{read} to time out
-if input does not arrive within a specified number of seconds, the
-@option{-n} option will allow reading only a specified number of
-characters rather than a full line, and the @option{-d} option will read
-until a particular character rather than newline.
-
-@item
-The @code{return} builtin may be used to abort execution of scripts
-executed with the @code{.} or @code{source} builtins
-(@pxref{Bourne Shell Builtins}).
-
-@item
-Bash includes the @code{shopt} builtin, for finer control of shell
-optional capabilities (@pxref{Bash Builtins}), and allows these options
-to be set and unset at shell invocation (@pxref{Invoking Bash}).
-
-@item
-Bash has much more optional behavior controllable with the @code{set}
-builtin (@pxref{The Set Builtin}).
-
-@item
-The @samp{-x} (@code{xtrace}) option displays commands other than
-simple commands when performing an execution trace
-(@pxref{The Set Builtin}).
-
-@item
-The @code{test} builtin (@pxref{Bourne Shell Builtins})
-is slightly different, as it implements the @sc{posix} algorithm,
-which specifies the behavior based on the number of arguments.
-
-@item
-Bash includes the @code{caller} builtin, which displays the context of
-any active subroutine call (a shell function or a script executed with
-the @code{.} or @code{source} builtins). This supports the bash
-debugger.
-
-@item
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a
-@code{DEBUG} pseudo-signal specification, similar to @code{EXIT}.
-Commands specified with a @code{DEBUG} trap are executed before every
-simple command, @code{for} command, @code{case} command,
-@code{select} command, every arithmetic @code{for} command, and before
-the first command executes in a shell function.
-The @code{DEBUG} trap is not inherited by shell functions unless the
-function has been given the @code{trace} attribute or the
-@code{functrace} option has been enabled using the @code{shopt} builtin.
-The @code{extdebug} shell option has additional effects on the
-@code{DEBUG} trap.
-
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows an
-@code{ERR} pseudo-signal specification, similar to @code{EXIT} and @code{DEBUG}.
-Commands specified with an @code{ERR} trap are executed after a simple
-command fails, with a few exceptions.
-The @code{ERR} trap is not inherited by shell functions unless the
-@code{-o errtrace} option to the @code{set} builtin is enabled.
-
-The @code{trap} builtin (@pxref{Bourne Shell Builtins}) allows a
-@code{RETURN} pseudo-signal specification, similar to
-@code{EXIT} and @code{DEBUG}.
-Commands specified with an @code{RETURN} trap are executed before
-execution resumes after a shell function or a shell script executed with
-@code{.} or @code{source} returns.
-The @code{RETURN} trap is not inherited by shell functions unless the
-function has been given the @code{trace} attribute or the
-@code{functrace} option has been enabled using the @code{shopt} builtin.
-
-@item
-The Bash @code{type} builtin is more extensive and gives more information
-about the names it finds (@pxref{Bash Builtins}).
-
-@item
-The Bash @code{umask} builtin permits a @option{-p} option to cause
-the output to be displayed in the form of a @code{umask} command
-that may be reused as input (@pxref{Bourne Shell Builtins}).
-
-@item
-Bash implements a @code{csh}-like directory stack, and provides the
-@code{pushd}, @code{popd}, and @code{dirs} builtins to manipulate it
-(@pxref{The Directory Stack}).
-Bash also makes the directory stack visible as the value of the
-@env{DIRSTACK} shell variable.
-
-@item
-Bash interprets special backslash-escaped characters in the prompt
-strings when interactive (@pxref{Printing a Prompt}).
-
-@item
-The Bash restricted mode is more useful (@pxref{The Restricted Shell});
-the SVR4.2 shell restricted mode is too limited.
-
-@item
-The @code{disown} builtin can remove a job from the internal shell
-job table (@pxref{Job Control Builtins}) or suppress the sending
-of @code{SIGHUP} to a job when the shell exits as the result of a
-@code{SIGHUP}.
-
-@item
-Bash includes a number of features to support a separate debugger for
-shell scripts.
-
-@item
-The SVR4.2 shell has two privilege-related builtins
-(@code{mldmode} and @code{priv}) not present in Bash.
-
-@item
-Bash does not have the @code{stop} or @code{newgrp} builtins.
-
-@item
-Bash does not use the @env{SHACCT} variable or perform shell accounting.
-
-@item
-The SVR4.2 @code{sh} uses a @env{TIMEOUT} variable like Bash uses
-@env{TMOUT}.
-
-@end itemize
-
-@noindent
-More features unique to Bash may be found in @ref{Bash Features}.
-
-
-@appendixsec Implementation Differences From The SVR4.2 Shell
-
-Since Bash is a completely new implementation, it does not suffer from
-many of the limitations of the SVR4.2 shell. For instance:
-
-@itemize @bullet
-
-@item
-Bash does not fork a subshell when redirecting into or out of
-a shell control structure such as an @code{if} or @code{while}
-statement.
-
-@item
-Bash does not allow unbalanced quotes. The SVR4.2 shell will silently
-insert a needed closing quote at @code{EOF} under certain circumstances.
-This can be the cause of some hard-to-find errors.
-
-@item
-The SVR4.2 shell uses a baroque memory management scheme based on
-trapping @code{SIGSEGV}. If the shell is started from a process with
-@code{SIGSEGV} blocked (e.g., by using the @code{system()} C library
-function call), it misbehaves badly.
-
-@item
-In a questionable attempt at security, the SVR4.2 shell,
-when invoked without the @option{-p} option, will alter its real
-and effective @sc{uid} and @sc{gid} if they are less than some
-magic threshold value, commonly 100.
-This can lead to unexpected results.
-
-@item
-The SVR4.2 shell does not allow users to trap @code{SIGSEGV},
-@code{SIGALRM}, or @code{SIGCHLD}.
-
-@item
-The SVR4.2 shell does not allow the @env{IFS}, @env{MAILCHECK},
-@env{PATH}, @env{PS1}, or @env{PS2} variables to be unset.
-
-@item
-The SVR4.2 shell treats @samp{^} as the undocumented equivalent of
-@samp{|}.
-
-@item
-Bash allows multiple option arguments when it is invoked (@code{-x -v});
-the SVR4.2 shell allows only one option argument (@code{-xv}). In
-fact, some versions of the shell dump core if the second argument begins
-with a @samp{-}.
-
-@item
-The SVR4.2 shell exits a script if any builtin fails; Bash exits
-a script only if one of the @sc{posix} special builtins fails, and
-only for certain failures, as enumerated in the @sc{posix} standard.
-
-@item
-The SVR4.2 shell behaves differently when invoked as @code{jsh}
-(it turns on job control).
-@end itemize
-
-@node Copying This Manual
-@appendix Copying This Manual
-
-@menu
-* GNU Free Documentation License:: License for copying this manual.
-@end menu
-
-@include fdl.texi
-
-@node Builtin Index
-@unnumbered Index of Shell Builtin Commands
-@printindex bt
-
-@node Reserved Word Index
-@unnumbered Index of Shell Reserved Words
-@printindex rw
-
-@node Variable Index
-@unnumbered Parameter and Variable Index
-@printindex vr
-
-@node Function Index
-@unnumbered Function Index
-@printindex fn
-
-@node Concept Index
-@unnumbered Concept Index
-@printindex cp
-
-@bye
diff --git a/doc/version.texi~ b/doc/version.texi~
deleted file mode 100644
index 3645f448..00000000
--- a/doc/version.texi~
+++ /dev/null
@@ -1,10 +0,0 @@
-@ignore
-Copyright (C) 1988-2006 Free Software Foundation, Inc.
-@end ignore
-
-@set LASTCHANGE Thu May 11 14:25:33 EDT 2006
-
-@set EDITION 3.2
-@set VERSION 3.2
-@set UPDATED 11 May 2006
-@set UPDATED-MONTH May 2006
diff --git a/error.c~ b/error.c~
deleted file mode 100644
index edb0e2e9..00000000
--- a/error.c~
+++ /dev/null
@@ -1,454 +0,0 @@
-/* error.c -- Functions for handling errors. */
-/* Copyright (C) 1993-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 "bashtypes.h"
-#include <fcntl.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (PREFER_STDARG)
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
-
-#include <stdio.h>
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include "shell.h"
-#include "flags.h"
-#include "input.h"
-
-#if defined (HISTORY)
-# include "bashhist.h"
-#endif
-
-extern int executing_line_number __P((void));
-
-extern int interactive_shell, interactive, startup_state;
-extern char *dollar_vars[];
-extern char *shell_name;
-#if defined (JOB_CONTROL)
-extern pid_t shell_pgrp;
-extern int give_terminal_to __P((pid_t, int));
-#endif /* JOB_CONTROL */
-
-#if defined (ARRAY_VARS)
-extern char *bash_badsub_errmsg;
-#endif
-
-static void error_prolog __P((int));
-
-/* The current maintainer of the shell. You change this in the
- Makefile. */
-#if !defined (MAINTAINER)
-#define MAINTAINER "bash-maintainers@gnu.org"
-#endif
-
-char *the_current_maintainer = MAINTAINER;
-
-int gnu_error_format = 0;
-
-static void
-error_prolog (print_lineno)
- int print_lineno;
-{
- char *ename;
- int line;
-
- ename = get_name_for_error ();
- line = (print_lineno && interactive_shell == 0) ? executing_line_number () : -1;
-
- if (line > 0)
- fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : " line ", line);
- else
- fprintf (stderr, "%s: ", ename);
-}
-
-/* Return the name of the shell or the shell script for error reporting. */
-char *
-get_name_for_error ()
-{
- char *name;
-#if defined (ARRAY_VARS)
- SHELL_VAR *bash_source_v;
- ARRAY *bash_source_a;
-#endif
-
- name = (char *)NULL;
- if (interactive_shell == 0)
- {
-#if defined (ARRAY_VARS)
- bash_source_v = find_variable ("BASH_SOURCE");
- if (bash_source_v && array_p (bash_source_v) &&
- (bash_source_a = array_cell (bash_source_v)))
- name = array_reference (bash_source_a, 0);
- if (name == 0)
-#endif
- name = dollar_vars[0];
- }
- if (name == 0 && shell_name && *shell_name)
- name = base_pathname (shell_name);
- if (name == 0)
-#if defined (PROGRAM)
- name = PROGRAM;
-#else
- name = "bash";
-#endif
-
- return (name);
-}
-
-/* Report an error having to do with FILENAME. This does not use
- sys_error so the filename is not interpreted as a printf-style
- format string. */
-void
-file_error (filename)
- const char *filename;
-{
- report_error ("%s: %s", filename, strerror (errno));
-}
-
-void
-#if defined (PREFER_STDARG)
-programming_error (const char *format, ...)
-#else
-programming_error (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
- char *h;
-
-#if defined (JOB_CONTROL)
- give_terminal_to (shell_pgrp, 0);
-#endif /* JOB_CONTROL */
-
- SH_VA_START (args, format);
-
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
- va_end (args);
-
-#if defined (HISTORY)
- if (remember_on_history)
- {
- h = last_history_line ();
- fprintf (stderr, _("last command: %s\n"), h ? h : "(null)");
- }
-#endif
-
-#if 0
- fprintf (stderr, "Report this to %s\n", the_current_maintainer);
-#endif
-
- fprintf (stderr, _("Aborting..."));
- fflush (stderr);
-
- abort ();
-}
-
-/* Print an error message and, if `set -e' has been executed, exit the
- shell. Used in this file by file_error and programming_error. Used
- outside this file mostly to report substitution and expansion errors,
- and for bad invocation options. */
-void
-#if defined (PREFER_STDARG)
-report_error (const char *format, ...)
-#else
-report_error (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
-
- error_prolog (1);
-
- SH_VA_START (args, format);
-
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
-
- va_end (args);
- if (exit_immediately_on_error)
- exit_shell (1);
-}
-
-void
-#if defined (PREFER_STDARG)
-fatal_error (const char *format, ...)
-#else
-fatal_error (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
-
- error_prolog (0);
-
- SH_VA_START (args, format);
-
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
-
- va_end (args);
- sh_exit (2);
-}
-
-void
-#if defined (PREFER_STDARG)
-internal_error (const char *format, ...)
-#else
-internal_error (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
-
- error_prolog (1);
-
- SH_VA_START (args, format);
-
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
-
- va_end (args);
-}
-
-void
-#if defined (PREFER_STDARG)
-internal_warning (const char *format, ...)
-#else
-internal_warning (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
-
- fprintf (stderr, _("%s: warning: "), get_name_for_error ());
-
- SH_VA_START (args, format);
-
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
-
- va_end (args);
-}
-
-void
-#if defined (PREFER_STDARG)
-sys_error (const char *format, ...)
-#else
-sys_error (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- int e;
- va_list args;
-
- e = errno;
- error_prolog (0);
-
- SH_VA_START (args, format);
-
- vfprintf (stderr, format, args);
- fprintf (stderr, ": %s\n", strerror (e));
-
- va_end (args);
-}
-
-/* An error from the parser takes the general form
-
- shell_name: input file name: line number: message
-
- The input file name and line number are omitted if the shell is
- currently interactive. If the shell is not currently interactive,
- the input file name is inserted only if it is different from the
- shell name. */
-void
-#if defined (PREFER_STDARG)
-parser_error (int lineno, const char *format, ...)
-#else
-parser_error (lineno, format, va_alist)
- int lineno;
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
- char *ename, *iname;
-
- ename = get_name_for_error ();
- iname = yy_input_name ();
-
- if (interactive)
- fprintf (stderr, "%s: ", ename);
- else if (interactive_shell)
- fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : " line ", lineno);
- else if (STREQ (ename, iname))
- fprintf (stderr, "%s:%s%d: ", ename, gnu_error_format ? "" : " line ", lineno);
- else
- fprintf (stderr, "%s: %s:%s%d: ", ename, iname, gnu_error_format ? "" : " line ", lineno);
-
- SH_VA_START (args, format);
-
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
-
- va_end (args);
-
- if (exit_immediately_on_error)
- exit_shell (2);
-}
-
-#ifdef DEBUG
-void
-#if defined (PREFER_STDARG)
-itrace (const char *format, ...)
-#else
-itrace (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
-
- fprintf(stderr, "TRACE: pid %ld: ", (long)getpid());
-
- SH_VA_START (args, format);
-
- vfprintf (stderr, format, args);
- fprintf (stderr, "\n");
-
- va_end (args);
-
- fflush(stderr);
-}
-
-/* A trace function for silent debugging -- doesn't require a control
- terminal. */
-void
-#if defined (PREFER_STDARG)
-trace (const char *format, ...)
-#else
-trace (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
- static FILE *tracefp = (FILE *)NULL;
-
- if (tracefp == NULL)
- tracefp = fopen("/tmp/bash-trace.log", "a+");
-
- if (tracefp == NULL)
- tracefp = stderr;
- else
- fcntl (fileno (tracefp), F_SETFD, 1); /* close-on-exec */
-
- fprintf(tracefp, "TRACE: pid %ld: ", (long)getpid());
-
- SH_VA_START (args, format);
-
- vfprintf (tracefp, format, args);
- fprintf (tracefp, "\n");
-
- va_end (args);
-
- fflush(tracefp);
-}
-
-#endif /* DEBUG */
-
-/* **************************************************************** */
-/* */
-/* Common error reporting */
-/* */
-/* **************************************************************** */
-
-
-static char *cmd_error_table[] = {
- N_("unknown command error"), /* CMDERR_DEFAULT */
- N_("bad command type"), /* CMDERR_BADTYPE */
- N_("bad connector"), /* CMDERR_BADCONN */
- N_("bad jump"), /* CMDERR_BADJUMP */
- 0
-};
-
-void
-command_error (func, code, e, flags)
- const char *func;
- int code, e, flags; /* flags currently unused */
-{
- if (code > CMDERR_LAST)
- code = CMDERR_DEFAULT;
-
- programming_error ("%s: %s: %d", func, _(cmd_error_table[code]), e);
-}
-
-char *
-command_errstr (code)
- int code;
-{
- if (code > CMDERR_LAST)
- code = CMDERR_DEFAULT;
-
- return (_(cmd_error_table[code]));
-}
-
-#ifdef ARRAY_VARS
-void
-err_badarraysub (s)
- const char *s;
-{
- report_error ("%s: %s", s, _(bash_badsub_errmsg));
-}
-#endif
-
-void
-err_unboundvar (s)
- const char *s;
-{
- report_error (_("%s: unbound variable"), s);
-}
-
-void
-err_readonly (s)
- const char *s;
-{
- report_error (_("%s: readonly variable"), s);
-}
diff --git a/examples/scripts/adventure.sh.save1 b/examples/scripts/adventure.sh.save1
deleted file mode 100755
index 4e223939..00000000
--- a/examples/scripts/adventure.sh.save1
+++ /dev/null
@@ -1,549 +0,0 @@
-#!/bin/bash
-# ash -- "Adventure shell"
-# last edit: 86/04/21 D A Gwyn
-# SCCS ID: @(#)ash.sh 1.4
-
-OPATH=$PATH
-
-ask()
-{
- echo -n "$@" '[y/n] '
- read ans
-
- case "$ans" in
- y*|Y*)
- return 0
- ;;
- *)
- return 1
- ;;
- esac
-}
-
-CAT=${PAGER:-more}
-
-ash_inst()
-{
- cat <<- EOF
-
- Instructions for the Adventure shell
-
- Welcome to the Adventure shell! In this exploration of the UNIX file
- system, I will act as your eyes and hands. As you move around, I will
- describe whatever is visible and will carry out your commands. The
- general form of a command is
- Verb Object Extra_stuff.
- Most commands pay no attention to the "Extra_stuff", and many do not
- need an "Object". A typical command is
- get all
- which picks up all files in the current "room" (directory). You can
- find out what you are carrying by typing the command
- inventory
- The command "help" results in a full description of all commands that I
- understand. To quit the Adventure shell, type
- quit
-
- There are UNIX monsters lurking in the background. These are also
- known as "commands with arguments".
-
- Good luck!
- EOF
-}
-
-ash_help()
-{
-echo "I understand the following commands (synonyms in parentheses):"
-echo ""
-
-echo "change OBJECT to NEW_NAME changes the name of the object"
-echo "clone OBJECT as NEW_NAME duplicates the object"
-echo "drop OBJECTS leaves the objects in the room"
-echo "enter (go) PASSAGE takes the labeled passage"
-echo "examine OBJECTS describes the objects in detail"
-echo "feed OBJECT to MONSTER stuffs the object into a UNIX monster"
-echo "get (take) OBJECTS picks up the specified objects"
-echo "gripe (bug) report a problem with the Adventure shell"
-echo "help prints this summary"
-echo "inventory (i) tells what you are carrying"
-echo "kill (destroy) OBJECTS destroys the objects"
-echo "look (l) describes the room, including hidden objects"
-echo "open (read) OBJECT shows the contents of an object"
-echo "quit (exit) leaves the Adventure shell"
-echo "resurrect OBJECTS attempts to restore dead objects"
-echo "steal OBJECT from MONSTER obtains the object from a UNIX monster"
-echo "throw OBJECT at daemon feeds the object to the printer daemon"
-echo "up takes the overhead passage"
-echo "wake MONSTER awakens a UNIX monster"
-echo "where (w) tells you where you are"
-echo "xyzzy moves you to your home"
-}
-
-MAINT=chet@ins.cwru.edu
-
-PATH=/usr/ucb:/bin:/usr/bin:/usr/local/bin:.
-export PATH
-
-trap 'echo Ouch!' 2 3
-#trap '' 18 # disable Berkeley job control
-
-ash_lk(){ echo " $1 " | fgrep " $2 " >&- 2>&-; }
-ash_pr(){ echo $* | tr ' ' '\012' | pr -5 -t -w75 -l$[ ( $# + 4 ) / 5 ]; }
-ash_rm(){ echo " $1 " | sed -e "s/ $2 / /" -e 's/^ //' -e 's/ $//'; }
-
-# enable history, bang history expansion, and emacs editing
-set -o history
-set -o histexpand
-set -o emacs
-
-cd
-LIM=.limbo # $HOME/$LIM contains "destroyed" objects
-mkdir $LIM >&- 2>&-
-KNAP=.knapsack # $HOME/$KNAP contains objects being "carried"
-if [ ! -d $KNAP ]
-then mkdir $KNAP >&- 2>&-
- if [ $? = 0 ]
- then echo 'You found a discarded empty knapsack.'
- else echo 'You have no knapsack to carry things in.'
- exit 1
- fi
-else echo 'One moment while I peek in your old knapsack...'
-fi
-
-kn=`echo \`ls -a $KNAP | sed -e '/^\.$/d' -e '/^\.\.$/d'\``
-
-if ask 'Welcome to the Adventure shell! Do you need instructions?'
-then
- ash_inst
- echo -n 'Type a newline to continue: '
- read
-fi
-
-wiz=false
-cha=false
-prev=$LIM
-while :
-do room=`pwd`
- if [ $room != $prev ]
- then if [ $room = $HOME ]
- then echo 'You are in your own home.'
- else echo "You have entered $room."
- fi
- exs=
- obs=
- hexs=
- hobs=
- f=false
- for i in `ls -a`
- do case $i in
- .|..) ;;
- .*) if [ -f $i ]
- then hobs="$hobs $i"
- elif [ -d $i ]
- then hexs="$hexs $i"
- else f=true
- fi
- ;;
- *) if [ -f $i ]
- then obs="$obs $i"
- elif [ -d $i ]
- then exs="$exs $i"
- else f=true
- fi
- ;;
- esac
- done
- if [ "$obs" ]
- then echo 'This room contains:'
- ash_pr $obs
- else echo 'The room looks empty.'
- fi
- if [ "$exs" ]
- then echo 'There are exits labeled:'
- ash_pr $exs
- echo 'as well as a passage overhead.'
- else echo 'There is a passage overhead.'
- fi
- if sh -c $f
- then echo 'There are shadowy figures in the corner.'
- fi
- prev=$room
- fi
-
- read -e -p '-advsh> ' verb obj x # prompt is '-advsh> '
- if [ $? != 0 ]
- then verb=quit # EOF
- fi
-
- case $verb in
- change) if [ "$obj" ]
- then if ash_lk "$obs $hobs" "$obj"
- then set -- $x
- case "$1" in
- to) if [ "$2" ]
- then if [ -f $2 ]
- then echo "You must destroy $2 first."
- set --
- fi
- if [ "$2" ]
- then if mv $obj $2 >&- 2>&-
- then echo "The $obj shimmers and turns into $2."
- obs=`ash_rm "$2 $obs" "$obj"`
- else echo "There is a cloud of smoke but the $obj is unchanged."
- fi
- fi
- else echo 'To what?'
- fi
- ;;
- *) echo "Change $obj to what?"
- ;;
- esac
- else if ash_lk "$kn" "$obj"
- then echo 'You must drop it first.'
- else echo "I see no $obj here."
- fi
- fi
- else echo 'Change what?'
- fi
- ;;
- clone) if [ "$obj" ]
- then if ash_lk "$obs $hobs" "$obj"
- then if [ ! -r $obj ]
- then echo "The $obj does not wish to be cloned."
- else set -- $x
- case "$1" in
- as) if [ "$2" ]
- then if [ -f $2 ]
- then echo "You must destroy $2 first."
- else if cp $obj $2 >&- 2>&-
- then echo "Poof! When the smoke clears, you see the new $2."
- obs="$obs $2"
- else echo 'You hear a dull thud but no clone appears.'
- fi
- fi
- else echo 'As what?'
- fi
- ;;
- *) echo "Clone $obj as what?"
- ;;
- esac
- fi
- else if ash_lk "$kn" "$obj"
- then echo 'You must drop it first.'
- else echo "I see no $obj here."
- fi
- fi
- else echo 'Clone what?'
- fi
- ;;
- drop) if [ "$obj" ]
- then for it in $obj $x
- do if ash_lk "$kn" "$it"
- then if [ -w $it ]
- then echo "You must destroy $it first."
- else if mv $HOME/$KNAP/$it $it >&- 2>&-
- then echo "$it: dropped."
- kn=`ash_rm "$kn" "$it"`
- obs=`echo $it $obs`
- else echo "The $it is caught in your knapsack."
- fi
- fi
- else echo "You're not carrying the $it!"
- fi
- done
- else echo 'Drop what?'
- fi
- ;;
- enter|go) if [ "$obj" ]
- then if [ $obj != up ]
- then if ash_lk "$exs $hexs" "$obj"
- then if [ -x $obj ]
- then if cd $obj
- then echo 'You squeeze through the passage.'
- else echo "You can't go that direction."
- fi
- else echo 'An invisible force blocks your way.'
- fi
- else echo 'I see no such passage.'
- fi
- else if cd ..
- then echo 'You struggle upwards.'
- else echo "You can't reach that high."
- fi
- fi
- else echo 'Which passage?'
- fi
- ;;
- examine) if [ "$obj" ]
- then if [ $obj = all ]
- then $obj=`echo $obs $exs`
- x=
- fi
- for it in $obj $x
- do if ash_lk "$obs $hobs $exs $hexs" "$it"
- then echo "Upon close inspection of the $it, you see:"
- ls -ld $it 2>&-
- if [ $? != 0 ]
- then echo "-- when you look directly at the $it, it vanishes."
- fi
- else if ash_lk "$kn" "$it"
- then echo 'You must drop it first.'
- else echo "I see no $it here."
- fi
- fi
- done
- else echo 'Examine what?'
- fi
- ;;
- feed) if [ "$obj" ]
- then if ash_lk "$obs $hobs" "$obj"
- then set -- $x
- case "$1" in
- to) if [ "$2" ]
- then shift
- if PATH=$OPATH $* <$obj 2>&-
- then echo "The $1 monster devours your $obj."
- if rm -f $obj >&- 2>&-
- then obs=`ash_rm "$obs" "$obj"`
- else echo 'But he spits it back up.'
- fi
- else echo "The $1 monster holds his nose in disdain."
- fi
- else echo 'To what?'
- fi
- ;;
- *) echo "Feed $obj to what?"
- ;;
- esac
- else if ash_lk "$kn" "$obj"
- then echo 'You must drop it first.'
- else echo "I see no $obj here."
- fi
- fi
- else echo 'Feed what?'
- fi
- ;;
- get|take) if [ "$obj" ]
- then if [ $obj = all ]
- then obj="$obs"
- x=
- fi
- for it in $obj $x
- do if ash_lk "$obs $hobs" "$it"
- then if ash_lk "$kn" "$it"
- then echo 'You already have one.'
- else if mv $it $HOME/$KNAP/$it >&- 2>&-
- then echo "$it: taken."
- kn="$it $kn"
- obs=`ash_rm "$obs" "$it"`
- else echo "The $it is too heavy."
- fi
- fi
- else echo "I see no $it here."
- fi
- done
- else echo 'Get what?'
- fi
- ;;
- gripe|bug) echo 'Please describe the problem and your situation at the time it failed.\nEnd the bug report with a line containing just a Ctrl-D.'
- cat | mail $MAINT -s 'ash bug'
- echo 'Thank you!'
- ;;
- help) ash_help
- ;;
- inventory|i) if [ "$kn" ]
- then echo 'Your knapsack contains:'
- ash_pr $kn
- else echo 'You are poverty-stricken.'
- fi
- ;;
- kill|destroy) if [ "$obj" ]
- then if [ $obj = all ]
- then x=
- if ask "Do you really want to attempt to $verb them all?"
- then obj=`echo $obs`
- else echo 'Chicken!'
- obj=
- fi
- fi
- for it in $obj $x
- do if ash_lk "$obs $hobs" "$it"
- then if mv $it $HOME/$LIM <&- >&- 2>&-
- then if [ $verb = kill ]
- then echo "The $it cannot defend himself; he dies."
- else echo "You have destroyed the $it; it vanishes."
- fi
- obs=`ash_rm "$obs" "$it"`
- else if [ $verb = kill ]
- then echo "Your feeble blows are no match for the $it."
- else echo "The $it is indestructible."
- fi
- fi
- else if ash_lk "$kn" "$it"
- then echo "You must drop the $it first."
- found=false
- else echo "I see no $it here."
- fi
- fi
- done
- else echo 'Kill what?'
- fi
- ;;
- look|l) obs=`echo $obs $hobs`
- hobs=
- if [ "$obs" ]
- then echo 'The room contains:'
- ash_pr $obs
- else echo 'The room is empty.'
- fi
- exs=`echo $exs $hexs`
- hexs=
- if [ "$exs" ]
- then echo 'There are exits plainly labeled:'
- ash_pr $exs
- echo 'and a passage directly overhead.'
- else echo 'The only exit is directly overhead.'
- fi
- ;;
- magic) if [ "$obj" = mode ]
- then if sh -c $cha
- then echo 'You had your chance and you blew it.'
- else if ask 'Are you a wizard?'
- then echo -n 'Prove it! Say the magic word: '
- read obj
- if [ "$obj" = armadillo ]
- then echo 'Yes, master!!'
- wiz=true
- else echo "Homie says: I don't think so"
- cha=true
- fi
- else echo "I didn't think so."
- fi
- fi
- else echo 'Nice try.'
- fi
- ;;
- open|read) if [ "$obj" ]
- then if ash_lk "$obs $hobs" "$obj"
- then if [ -r $obj ]
- then if [ -s $obj ]
- then echo "Opening the $obj reveals:"
- $CAT < $obj
- if [ $? != 0 ]
- then echo '-- oops, you lost the contents!'
- fi
- else echo "There is nothing inside the $obj."
- fi
- else echo "You do not have the proper tools to open the $obj."
- fi
- else if ash_lk "$kn" "$obj"
- then echo 'You must drop it first.'
- found=false
- else echo "I see no $obj here."
- fi
- fi
- else echo 'Open what?'
- fi
- ;;
- quit|exit) if ask 'Do you really want to quit now?'
- then if [ "$kn" ]
- then echo 'The contents of your knapsack will still be there next time.'
- fi
- rm -rf $HOME/$LIM
- echo 'See you later!'
- exit 0
- fi
- ;;
- resurrect) if [ "$obj" ]
- then for it in $obj $x
- do if ash_lk "$obs $hobs" "$it"
- then echo "The $it is already alive and well."
- else if mv $HOME/$LIM/$it $it <&- >&- 2>&-
- then echo "The $it staggers to his feet."
- obs=`echo $it $obs`
- else echo "There are sparks but no $it appears."
- fi
- fi
- done
- else echo 'Resurrect what?'
- fi
- ;;
- steal) if [ "$obj" ]
- then if ash_lk "$obs $hobs" "$obj"
- then echo 'There is already one here.'
- else set -- $x
- case "$1" in
- from) if [ "$2" ]
- then shift
- if PATH=$OPATH $* >$obj 2>&-
- then echo "The $1 monster drops the $obj."
- obs=`echo $obj $obs`
- else echo "The $1 monster runs away as you approach."
- rm -f $obj >&- 2>&-
- fi
- else echo 'From what?'
- fi
- ;;
- *) echo "Steal $obj from what?"
- ;;
- esac
- fi
- else echo 'Steal what?'
- fi
- ;;
- throw) if [ "$obj" ]
- then if ash_lk "$obs $hobs" "$obj"
- then set -- $x
- case "$1" in
- at) case "$2" in
- daemon) if sh -c "lpr -r $obj"
- then echo "The daemon catches the $obj, turns it into paper,\nand leaves it in the basket."
- obs=`ash_rm "$obs" "$obj"`
- else echo "The daemon is nowhere to be found."
- fi
- ;;
- *) echo 'At what?'
- ;;
- esac
- ;;
- *) echo "Throw $obj at what?"
- ;;
- esac
- else if ash_lk "$kn" "$obj"
- then echo 'It is in your knapsack.'
- found=false
- else echo "I see no $obj here."
- fi
- fi
- else echo 'Throw what?'
- fi
- ;;
- u|up) if cd ..
- then echo 'You pull yourself up a level.'
- else echo "You can't reach that high."
- fi
- ;;
- wake) if [ "$obj" ]
- then echo "You awaken the $obj monster:"
- PATH=$OPATH $obj $x
- echo 'The monster slithers back into the darkness.'
- else echo 'Wake what?'
- fi
- ;;
- w|where) echo "You are in $room."
- ;;
- xyzzy) if cd
- then echo 'A strange feeling comes over you.'
- else echo 'Your spell fizzles out.'
- fi
- ;;
- *) if [ "$verb" ]
- then if sh -c $wiz
- then PATH=$OPATH $verb $obj $x
- else echo "I don't know how to \"$verb\"."
- echo 'Type "help" for assistance.'
- fi
- else echo 'Say something!'
- fi
- ;;
- esac
-done
diff --git a/execute_cmd.c~ b/execute_cmd.c~
deleted file mode 100644
index 5d2ae122..00000000
--- a/execute_cmd.c~
+++ /dev/null
@@ -1,4127 +0,0 @@
-/* execute_cmd.c -- Execute a COMMAND structure. */
-
-/* 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 (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
- #pragma alloca
-#endif /* _AIX && RISC6000 && !__GNUC__ */
-
-#include <stdio.h>
-#include "chartypes.h"
-#include "bashtypes.h"
-#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-#include "filecntl.h"
-#include "posixstat.h"
-#include <signal.h>
-#ifndef _MINIX
-# include <sys/param.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "posixtime.h"
-
-#if defined (HAVE_SYS_RESOURCE_H) && !defined (RLIMTYPE)
-# include <sys/resource.h>
-#endif
-
-#if defined (HAVE_SYS_TIMES_H) && defined (HAVE_TIMES)
-# include <sys/times.h>
-#endif
-
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include "memalloc.h"
-#include "shell.h"
-#include <y.tab.h> /* use <...> so we pick it up from the build directory */
-#include "flags.h"
-#include "builtins.h"
-#include "hashlib.h"
-#include "jobs.h"
-#include "execute_cmd.h"
-#include "findcmd.h"
-#include "redir.h"
-#include "trap.h"
-#include "pathexp.h"
-#include "hashcmd.h"
-
-#if defined (COND_COMMAND)
-# include "test.h"
-#endif
-
-#include "builtins/common.h"
-#include "builtins/builtext.h" /* list of builtins */
-
-#include <glob/strmatch.h>
-#include <tilde/tilde.h>
-
-#if defined (BUFFERED_INPUT)
-# include "input.h"
-#endif
-
-#if defined (ALIAS)
-# include "alias.h"
-#endif
-
-#if defined (HISTORY)
-# include "bashhist.h"
-#endif
-
-extern int posixly_correct;
-extern int breaking, continuing, loop_level;
-extern int expand_aliases;
-extern int parse_and_execute_level, running_trap;
-extern int command_string_index, line_number;
-extern int dot_found_in_search;
-extern int already_making_children;
-extern int tempenv_assign_error;
-extern char *the_printed_command, *shell_name;
-extern pid_t last_command_subst_pid;
-extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
-extern char **subshell_argv, **subshell_envp;
-extern int subshell_argc;
-#if 0
-extern char *glob_argv_flags;
-#endif
-
-extern int close __P((int));
-
-/* Static functions defined and used in this file. */
-static void close_pipes __P((int, int));
-static void do_piping __P((int, int));
-static void bind_lastarg __P((char *));
-static int shell_control_structure __P((enum command_type));
-static void cleanup_redirects __P((REDIRECT *));
-
-#if defined (JOB_CONTROL)
-static int restore_signal_mask __P((sigset_t *));
-#endif
-
-static void async_redirect_stdin __P((void));
-
-static int builtin_status __P((int));
-
-static int execute_for_command __P((FOR_COM *));
-#if defined (SELECT_COMMAND)
-static int print_index_and_element __P((int, int, WORD_LIST *));
-static void indent __P((int, int));
-static void print_select_list __P((WORD_LIST *, int, int, int));
-static char *select_query __P((WORD_LIST *, int, char *, int));
-static int execute_select_command __P((SELECT_COM *));
-#endif
-#if defined (DPAREN_ARITHMETIC)
-static int execute_arith_command __P((ARITH_COM *));
-#endif
-#if defined (COND_COMMAND)
-static int execute_cond_node __P((COND_COM *));
-static int execute_cond_command __P((COND_COM *));
-#endif
-#if defined (COMMAND_TIMING)
-static int mkfmt __P((char *, int, int, time_t, int));
-static void print_formatted_time __P((FILE *, char *,
- time_t, int, time_t, int,
- time_t, int, int));
-static int time_command __P((COMMAND *, int, int, int, struct fd_bitmap *));
-#endif
-#if defined (ARITH_FOR_COMMAND)
-static intmax_t eval_arith_for_expr __P((WORD_LIST *, int *));
-static int execute_arith_for_command __P((ARITH_FOR_COM *));
-#endif
-static int execute_case_command __P((CASE_COM *));
-static int execute_while_command __P((WHILE_COM *));
-static int execute_until_command __P((WHILE_COM *));
-static int execute_while_or_until __P((WHILE_COM *, int));
-static int execute_if_command __P((IF_COM *));
-static int execute_null_command __P((REDIRECT *, int, int, int));
-static void fix_assignment_words __P((WORD_LIST *));
-static int execute_simple_command __P((SIMPLE_COM *, int, int, int, struct fd_bitmap *));
-static int execute_builtin __P((sh_builtin_func_t *, WORD_LIST *, int, int));
-static int execute_function __P((SHELL_VAR *, WORD_LIST *, int, struct fd_bitmap *, int, int));
-static int execute_builtin_or_function __P((WORD_LIST *, sh_builtin_func_t *,
- SHELL_VAR *,
- REDIRECT *, struct fd_bitmap *, int));
-static void execute_subshell_builtin_or_function __P((WORD_LIST *, REDIRECT *,
- sh_builtin_func_t *,
- SHELL_VAR *,
- int, int, int,
- struct fd_bitmap *,
- int));
-static void execute_disk_command __P((WORD_LIST *, REDIRECT *, char *,
- int, int, int, struct fd_bitmap *, int));
-
-static char *getinterp __P((char *, int, int *));
-static void initialize_subshell __P((void));
-static int execute_in_subshell __P((COMMAND *, int, int, int, struct fd_bitmap *));
-
-static int execute_pipeline __P((COMMAND *, int, int, int, struct fd_bitmap *));
-
-static int execute_connection __P((COMMAND *, int, int, int, struct fd_bitmap *));
-
-static int execute_intern_function __P((WORD_DESC *, COMMAND *));
-
-/* The line number that the currently executing function starts on. */
-static int function_line_number;
-
-/* Set to 1 if fd 0 was the subject of redirection to a subshell. Global
- so that reader_loop can set it to zero before executing a command. */
-int stdin_redir;
-
-/* The name of the command that is currently being executed.
- `test' needs this, for example. */
-char *this_command_name;
-
-/* The printed representation of the currently-executing command (same as
- the_printed_command), except when a trap is being executed. Useful for
- a debugger to know where exactly the program is currently executing. */
-char *the_printed_command_except_trap;
-
-static COMMAND *currently_executing_command;
-
-struct stat SB; /* used for debugging */
-
-static int special_builtin_failed;
-
-/* XXX - set to 1 if we're running the DEBUG trap and we want to show the line
- number containing the function name. Used by executing_line_number to
- report the correct line number. Kind of a hack. */
-static int showing_function_line;
-
-static int line_number_for_err_trap;
-
-/* For catching RETURN in a function. */
-int return_catch_flag;
-int return_catch_value;
-procenv_t return_catch;
-
-/* The value returned by the last synchronous command. */
-int last_command_exit_value;
-
-/* Whether or not the last command (corresponding to last_command_exit_value)
- was terminated by a signal, and, if so, which one. */
-int last_command_exit_signal;
-
-/* The list of redirections to perform which will undo the redirections
- that I made in the shell. */
-REDIRECT *redirection_undo_list = (REDIRECT *)NULL;
-
-/* The list of redirections to perform which will undo the internal
- redirections performed by the `exec' builtin. These are redirections
- that must be undone even when exec discards redirection_undo_list. */
-REDIRECT *exec_redirection_undo_list = (REDIRECT *)NULL;
-
-/* Non-zero if we have just forked and are currently running in a subshell
- environment. */
-int subshell_environment;
-
-/* Count of nested subshells, like SHLVL. Available via $BASH_SUBSHELL */
-int subshell_level = 0;
-
-/* Currently-executing shell function. */
-SHELL_VAR *this_shell_function;
-
-/* If non-zero, matches in case and [[ ... ]] are case-insensitive */
-int match_ignore_case = 0;
-
-struct fd_bitmap *current_fds_to_close = (struct fd_bitmap *)NULL;
-
-#define FD_BITMAP_DEFAULT_SIZE 32
-
-/* Functions to allocate and deallocate the structures used to pass
- information from the shell to its children about file descriptors
- to close. */
-struct fd_bitmap *
-new_fd_bitmap (size)
- int size;
-{
- struct fd_bitmap *ret;
-
- ret = (struct fd_bitmap *)xmalloc (sizeof (struct fd_bitmap));
-
- ret->size = size;
-
- if (size)
- {
- ret->bitmap = (char *)xmalloc (size);
- memset (ret->bitmap, '\0', size);
- }
- else
- ret->bitmap = (char *)NULL;
- return (ret);
-}
-
-void
-dispose_fd_bitmap (fdbp)
- struct fd_bitmap *fdbp;
-{
- FREE (fdbp->bitmap);
- free (fdbp);
-}
-
-void
-close_fd_bitmap (fdbp)
- struct fd_bitmap *fdbp;
-{
- register int i;
-
- if (fdbp)
- {
- for (i = 0; i < fdbp->size; i++)
- if (fdbp->bitmap[i])
- {
- close (i);
- fdbp->bitmap[i] = 0;
- }
- }
-}
-
-/* Return the line number of the currently executing command. */
-int
-executing_line_number ()
-{
- if (executing && showing_function_line == 0 &&
- (variable_context == 0 || interactive_shell == 0) &&
- currently_executing_command)
- {
-#if defined (COND_COMMAND)
- if (currently_executing_command->type == cm_cond)
- return currently_executing_command->value.Cond->line;
-#endif
-#if defined (DPAREN_ARITHMETIC)
- else if (currently_executing_command->type == cm_arith)
- return currently_executing_command->value.Arith->line;
-#endif
-#if defined (ARITH_FOR_COMMAND)
- else if (currently_executing_command->type == cm_arith_for)
- return currently_executing_command->value.ArithFor->line;
-#endif
-
- return line_number;
- }
- else
- return line_number;
-}
-
-/* Execute the command passed in COMMAND. COMMAND is exactly what
- read_command () places into GLOBAL_COMMAND. See "command.h" for the
- details of the command structure.
-
- EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
- return values. Executing a command with nothing in it returns
- EXECUTION_SUCCESS. */
-int
-execute_command (command)
- COMMAND *command;
-{
- struct fd_bitmap *bitmap;
- int result;
-
- current_fds_to_close = (struct fd_bitmap *)NULL;
- bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
- begin_unwind_frame ("execute-command");
- add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
-
- /* Just do the command, but not asynchronously. */
- result = execute_command_internal (command, 0, NO_PIPE, NO_PIPE, bitmap);
-
- dispose_fd_bitmap (bitmap);
- discard_unwind_frame ("execute-command");
-
-#if defined (PROCESS_SUBSTITUTION)
- /* don't unlink fifos if we're in a shell function; wait until the function
- returns. */
- if (variable_context == 0)
- unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-
- QUIT;
- return (result);
-}
-
-/* Return 1 if TYPE is a shell control structure type. */
-static int
-shell_control_structure (type)
- enum command_type type;
-{
- switch (type)
- {
-#if defined (ARITH_FOR_COMMAND)
- case cm_arith_for:
-#endif
-#if defined (SELECT_COMMAND)
- case cm_select:
-#endif
-#if defined (DPAREN_ARITHMETIC)
- case cm_arith:
-#endif
-#if defined (COND_COMMAND)
- case cm_cond:
-#endif
- case cm_case:
- case cm_while:
- case cm_until:
- case cm_if:
- case cm_for:
- case cm_group:
- case cm_function_def:
- return (1);
-
- default:
- return (0);
- }
-}
-
-/* A function to use to unwind_protect the redirection undo list
- for loops. */
-static void
-cleanup_redirects (list)
- REDIRECT *list;
-{
- do_redirections (list, RX_ACTIVE);
- dispose_redirects (list);
-}
-
-#if 0
-/* Function to unwind_protect the redirections for functions and builtins. */
-static void
-cleanup_func_redirects (list)
- REDIRECT *list;
-{
- do_redirections (list, RX_ACTIVE);
-}
-#endif
-
-void
-dispose_exec_redirects ()
-{
- if (exec_redirection_undo_list)
- {
- dispose_redirects (exec_redirection_undo_list);
- exec_redirection_undo_list = (REDIRECT *)NULL;
- }
-}
-
-#if defined (JOB_CONTROL)
-/* A function to restore the signal mask to its proper value when the shell
- is interrupted or errors occur while creating a pipeline. */
-static int
-restore_signal_mask (set)
- sigset_t *set;
-{
- return (sigprocmask (SIG_SETMASK, set, (sigset_t *)NULL));
-}
-#endif /* JOB_CONTROL */
-
-#ifdef DEBUG
-/* A debugging function that can be called from gdb, for instance. */
-void
-open_files ()
-{
- register int i;
- int f, fd_table_size;
-
- fd_table_size = getdtablesize ();
-
- fprintf (stderr, "pid %ld open files:", (long)getpid ());
- for (i = 3; i < fd_table_size; i++)
- {
- if ((f = fcntl (i, F_GETFD, 0)) != -1)
- fprintf (stderr, " %d (%s)", i, f ? "close" : "open");
- }
- fprintf (stderr, "\n");
-}
-#endif
-
-static void
-async_redirect_stdin ()
-{
- int fd;
-
- fd = open ("/dev/null", O_RDONLY);
- if (fd > 0)
- {
- dup2 (fd, 0);
- close (fd);
- }
- else if (fd < 0)
- internal_error (_("cannot redirect standard input from /dev/null: %s"), strerror (errno));
-}
-
-#define DESCRIBE_PID(pid) do { if (interactive) describe_pid (pid); } while (0)
-
-/* Execute the command passed in COMMAND, perhaps doing it asynchrounously.
- COMMAND is exactly what read_command () places into GLOBAL_COMMAND.
- ASYNCHROUNOUS, if non-zero, says to do this command in the background.
- PIPE_IN and PIPE_OUT are file descriptors saying where input comes
- from and where it goes. They can have the value of NO_PIPE, which means
- I/O is stdin/stdout.
- FDS_TO_CLOSE is a list of file descriptors to close once the child has
- been forked. This list often contains the unusable sides of pipes, etc.
-
- EXECUTION_SUCCESS or EXECUTION_FAILURE are the only possible
- return values. Executing a command with nothing in it returns
- EXECUTION_SUCCESS. */
-int
-execute_command_internal (command, asynchronous, pipe_in, pipe_out,
- fds_to_close)
- COMMAND *command;
- int asynchronous;
- int pipe_in, pipe_out;
- struct fd_bitmap *fds_to_close;
-{
- int exec_result, invert, ignore_return, was_error_trap;
- REDIRECT *my_undo_list, *exec_undo_list;
- volatile int last_pid;
- volatile int save_line_number;
-
- if (command == 0 || breaking || continuing || read_but_dont_execute)
- return (EXECUTION_SUCCESS);
-
- QUIT;
- run_pending_traps ();
-
-#if 0
- if (running_trap == 0)
-#endif
- currently_executing_command = command;
-
- invert = (command->flags & CMD_INVERT_RETURN) != 0;
-
- /* If we're inverting the return value and `set -e' has been executed,
- we don't want a failing command to inadvertently cause the shell
- to exit. */
- if (exit_immediately_on_error && invert) /* XXX */
- command->flags |= CMD_IGNORE_RETURN; /* XXX */
-
- exec_result = EXECUTION_SUCCESS;
-
- /* If a command was being explicitly run in a subshell, or if it is
- a shell control-structure, and it has a pipe, then we do the command
- in a subshell. */
- if (command->type == cm_subshell && (command->flags & CMD_NO_FORK))
- return (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close));
-
- if (command->type == cm_subshell ||
- (command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) ||
- (shell_control_structure (command->type) &&
- (pipe_out != NO_PIPE || pipe_in != NO_PIPE || asynchronous)))
- {
- pid_t paren_pid;
-
- /* Fork a subshell, turn off the subshell bit, turn off job
- control and call execute_command () on the command again. */
- paren_pid = make_child (savestring (make_command_string (command)),
- asynchronous);
- if (paren_pid == 0)
- exit (execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close));
- /* NOTREACHED */
- else
- {
- close_pipes (pipe_in, pipe_out);
-
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
- unlink_fifo_list ();
-#endif
- /* If we are part of a pipeline, and not the end of the pipeline,
- then we should simply return and let the last command in the
- pipe be waited for. If we are not in a pipeline, or are the
- last command in the pipeline, then we wait for the subshell
- and return its exit status as usual. */
- if (pipe_out != NO_PIPE)
- return (EXECUTION_SUCCESS);
-
- stop_pipeline (asynchronous, (COMMAND *)NULL);
-
- if (asynchronous == 0)
- {
- last_command_exit_value = wait_for (paren_pid);
-
- /* If we have to, invert the return value. */
- if (invert)
- exec_result = ((last_command_exit_value == EXECUTION_SUCCESS)
- ? EXECUTION_FAILURE
- : EXECUTION_SUCCESS);
- else
- exec_result = last_command_exit_value;
-
- return (last_command_exit_value = exec_result);
- }
- else
- {
- DESCRIBE_PID (paren_pid);
-
- run_pending_traps ();
-
- return (EXECUTION_SUCCESS);
- }
- }
- }
-
-#if defined (COMMAND_TIMING)
- if (command->flags & CMD_TIME_PIPELINE)
- {
- if (asynchronous)
- {
- command->flags |= CMD_FORCE_SUBSHELL;
- exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close);
- }
- else
- {
- exec_result = time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close);
-#if 0
- if (running_trap == 0)
-#endif
- currently_executing_command = (COMMAND *)NULL;
- }
- return (exec_result);
- }
-#endif /* COMMAND_TIMING */
-
- if (shell_control_structure (command->type) && command->redirects)
- stdin_redir = stdin_redirects (command->redirects);
-
- /* Handle WHILE FOR CASE etc. with redirections. (Also '&' input
- redirection.) */
- if (do_redirections (command->redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
- {
- cleanup_redirects (redirection_undo_list);
- redirection_undo_list = (REDIRECT *)NULL;
- dispose_exec_redirects ();
- return (EXECUTION_FAILURE);
- }
-
- if (redirection_undo_list)
- {
- my_undo_list = (REDIRECT *)copy_redirects (redirection_undo_list);
- dispose_redirects (redirection_undo_list);
- redirection_undo_list = (REDIRECT *)NULL;
- }
- else
- my_undo_list = (REDIRECT *)NULL;
-
- if (exec_redirection_undo_list)
- {
- exec_undo_list = (REDIRECT *)copy_redirects (exec_redirection_undo_list);
- dispose_redirects (exec_redirection_undo_list);
- exec_redirection_undo_list = (REDIRECT *)NULL;
- }
- else
- exec_undo_list = (REDIRECT *)NULL;
-
- if (my_undo_list || exec_undo_list)
- begin_unwind_frame ("loop_redirections");
-
- if (my_undo_list)
- add_unwind_protect ((Function *)cleanup_redirects, my_undo_list);
-
- if (exec_undo_list)
- add_unwind_protect ((Function *)dispose_redirects, exec_undo_list);
-
- ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
- QUIT;
-
- switch (command->type)
- {
- case cm_simple:
- {
- save_line_number = line_number;
- /* We can't rely on variables retaining their values across a
- call to execute_simple_command if a longjmp occurs as the
- result of a `return' builtin. This is true for sure with gcc. */
-#if defined (RECYCLES_PIDS)
- last_made_pid = NO_PID;
-#endif
- last_pid = last_made_pid;
- was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
-
- if (ignore_return && command->value.Simple)
- command->value.Simple->flags |= CMD_IGNORE_RETURN;
- if (command->flags & CMD_STDIN_REDIR)
- command->value.Simple->flags |= CMD_STDIN_REDIR;
-
- line_number_for_err_trap = line_number = command->value.Simple->line;
- exec_result =
- execute_simple_command (command->value.Simple, pipe_in, pipe_out,
- asynchronous, fds_to_close);
- line_number = save_line_number;
-
- /* The temporary environment should be used for only the simple
- command immediately following its definition. */
- dispose_used_env_vars ();
-
-#if (defined (ultrix) && defined (mips)) || defined (C_ALLOCA)
- /* Reclaim memory allocated with alloca () on machines which
- may be using the alloca emulation code. */
- (void) alloca (0);
-#endif /* (ultrix && mips) || C_ALLOCA */
-
- /* If we forked to do the command, then we must wait_for ()
- the child. */
-
- /* XXX - this is something to watch out for if there are problems
- when the shell is compiled without job control. */
- if (already_making_children && pipe_out == NO_PIPE &&
- last_made_pid != last_pid)
- {
- stop_pipeline (asynchronous, (COMMAND *)NULL);
-
- if (asynchronous)
- {
- DESCRIBE_PID (last_made_pid);
- }
- else
-#if !defined (JOB_CONTROL)
- /* Do not wait for asynchronous processes started from
- startup files. */
- if (last_made_pid != last_asynchronous_pid)
-#endif
- /* When executing a shell function that executes other
- commands, this causes the last simple command in
- the function to be waited for twice. This also causes
- subshells forked to execute builtin commands (e.g., in
- pipelines) to be waited for twice. */
- exec_result = wait_for (last_made_pid);
- }
- }
-
- if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
- run_error_trap ();
- }
-
- if (ignore_return == 0 && invert == 0 &&
- ((posixly_correct && interactive == 0 && special_builtin_failed) ||
- (exit_immediately_on_error && (exec_result != EXECUTION_SUCCESS))))
- {
- last_command_exit_value = exec_result;
- run_pending_traps ();
- jump_to_top_level (ERREXIT);
- }
-
- break;
-
- case cm_for:
- if (ignore_return)
- command->value.For->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_for_command (command->value.For);
- break;
-
-#if defined (ARITH_FOR_COMMAND)
- case cm_arith_for:
- if (ignore_return)
- command->value.ArithFor->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_arith_for_command (command->value.ArithFor);
- break;
-#endif
-
-#if defined (SELECT_COMMAND)
- case cm_select:
- if (ignore_return)
- command->value.Select->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_select_command (command->value.Select);
- break;
-#endif
-
- case cm_case:
- if (ignore_return)
- command->value.Case->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_case_command (command->value.Case);
- break;
-
- case cm_while:
- if (ignore_return)
- command->value.While->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_while_command (command->value.While);
- break;
-
- case cm_until:
- if (ignore_return)
- command->value.While->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_until_command (command->value.While);
- break;
-
- case cm_if:
- if (ignore_return)
- command->value.If->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_if_command (command->value.If);
- break;
-
- case cm_group:
-
- /* This code can be executed from either of two paths: an explicit
- '{}' command, or via a function call. If we are executed via a
- function call, we have already taken care of the function being
- executed in the background (down there in execute_simple_command ()),
- and this command should *not* be marked as asynchronous. If we
- are executing a regular '{}' group command, and asynchronous == 1,
- we must want to execute the whole command in the background, so we
- need a subshell, and we want the stuff executed in that subshell
- (this group command) to be executed in the foreground of that
- subshell (i.e. there will not be *another* subshell forked).
-
- What we do is to force a subshell if asynchronous, and then call
- execute_command_internal again with asynchronous still set to 1,
- but with the original group command, so the printed command will
- look right.
-
- The code above that handles forking off subshells will note that
- both subshell and async are on, and turn off async in the child
- after forking the subshell (but leave async set in the parent, so
- the normal call to describe_pid is made). This turning off
- async is *crucial*; if it is not done, this will fall into an
- infinite loop of executions through this spot in subshell after
- subshell until the process limit is exhausted. */
-
- if (asynchronous)
- {
- command->flags |= CMD_FORCE_SUBSHELL;
- exec_result =
- execute_command_internal (command, 1, pipe_in, pipe_out,
- fds_to_close);
- }
- else
- {
- if (ignore_return && command->value.Group->command)
- command->value.Group->command->flags |= CMD_IGNORE_RETURN;
- exec_result =
- execute_command_internal (command->value.Group->command,
- asynchronous, pipe_in, pipe_out,
- fds_to_close);
- }
- break;
-
- case cm_connection:
- exec_result = execute_connection (command, asynchronous,
- pipe_in, pipe_out, fds_to_close);
- break;
-
-#if defined (DPAREN_ARITHMETIC)
- case cm_arith:
- if (ignore_return)
- command->value.Arith->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_arith_command (command->value.Arith);
- break;
-#endif
-
-#if defined (COND_COMMAND)
- case cm_cond:
- if (ignore_return)
- command->value.Cond->flags |= CMD_IGNORE_RETURN;
- save_line_number = line_number;
- exec_result = execute_cond_command (command->value.Cond);
- line_number = save_line_number;
- break;
-#endif
-
- case cm_function_def:
- exec_result = execute_intern_function (command->value.Function_def->name,
- command->value.Function_def->command);
- break;
-
- default:
- command_error ("execute_command", CMDERR_BADTYPE, command->type, 0);
- }
-
- if (my_undo_list)
- {
- do_redirections (my_undo_list, RX_ACTIVE);
- dispose_redirects (my_undo_list);
- }
-
- if (exec_undo_list)
- dispose_redirects (exec_undo_list);
-
- if (my_undo_list || exec_undo_list)
- discard_unwind_frame ("loop_redirections");
-
- /* Invert the return value if we have to */
- if (invert)
- exec_result = (exec_result == EXECUTION_SUCCESS)
- ? 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)
- {
-# 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 ();
-#if 0
- if (running_trap == 0)
-#endif
- currently_executing_command = (COMMAND *)NULL;
- return (last_command_exit_value);
-}
-
-#if defined (COMMAND_TIMING)
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-extern struct timeval *difftimeval __P((struct timeval *, struct timeval *, struct timeval *));
-extern struct timeval *addtimeval __P((struct timeval *, struct timeval *, struct timeval *));
-extern int timeval_to_cpu __P((struct timeval *, struct timeval *, struct timeval *));
-#endif
-
-#define POSIX_TIMEFORMAT "real %2R\nuser %2U\nsys %2S"
-#define BASH_TIMEFORMAT "\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS"
-
-static int precs[] = { 0, 100, 10, 1 };
-
-/* Expand one `%'-prefixed escape sequence from a time format string. */
-static int
-mkfmt (buf, prec, lng, sec, sec_fraction)
- char *buf;
- int prec, lng;
- time_t sec;
- int sec_fraction;
-{
- time_t min;
- char abuf[INT_STRLEN_BOUND(time_t) + 1];
- int ind, aind;
-
- ind = 0;
- abuf[sizeof(abuf) - 1] = '\0';
-
- /* If LNG is non-zero, we want to decompose SEC into minutes and seconds. */
- if (lng)
- {
- min = sec / 60;
- sec %= 60;
- aind = sizeof(abuf) - 2;
- do
- abuf[aind--] = (min % 10) + '0';
- while (min /= 10);
- aind++;
- while (abuf[aind])
- buf[ind++] = abuf[aind++];
- buf[ind++] = 'm';
- }
-
- /* Now add the seconds. */
- aind = sizeof (abuf) - 2;
- do
- abuf[aind--] = (sec % 10) + '0';
- while (sec /= 10);
- aind++;
- while (abuf[aind])
- buf[ind++] = abuf[aind++];
-
- /* We want to add a decimal point and PREC places after it if PREC is
- nonzero. PREC is not greater than 3. SEC_FRACTION is between 0
- and 999. */
- if (prec != 0)
- {
- buf[ind++] = '.';
- for (aind = 1; aind <= prec; aind++)
- {
- buf[ind++] = (sec_fraction / precs[aind]) + '0';
- sec_fraction %= precs[aind];
- }
- }
-
- if (lng)
- buf[ind++] = 's';
- buf[ind] = '\0';
-
- return (ind);
-}
-
-/* Interpret the format string FORMAT, interpolating the following escape
- sequences:
- %[prec][l][RUS]
-
- where the optional `prec' is a precision, meaning the number of
- characters after the decimal point, the optional `l' means to format
- using minutes and seconds (MMmNN[.FF]s), like the `times' builtin',
- and the last character is one of
-
- R number of seconds of `real' time
- U number of seconds of `user' time
- S number of seconds of `system' time
-
- An occurrence of `%%' in the format string is translated to a `%'. The
- result is printed to FP, a pointer to a FILE. The other variables are
- the seconds and thousandths of a second of real, user, and system time,
- resectively. */
-static void
-print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu)
- FILE *fp;
- char *format;
- time_t rs;
- int rsf;
- time_t us;
- int usf;
- time_t ss;
- int ssf, cpu;
-{
- int prec, lng, len;
- char *str, *s, ts[INT_STRLEN_BOUND (time_t) + sizeof ("mSS.FFFF")];
- time_t sum;
- int sum_frac;
- int sindex, ssize;
-
- len = strlen (format);
- ssize = (len + 64) - (len % 64);
- str = (char *)xmalloc (ssize);
- sindex = 0;
-
- for (s = format; *s; s++)
- {
- if (*s != '%' || s[1] == '\0')
- {
- RESIZE_MALLOCED_BUFFER (str, sindex, 1, ssize, 64);
- str[sindex++] = *s;
- }
- else if (s[1] == '%')
- {
- s++;
- RESIZE_MALLOCED_BUFFER (str, sindex, 1, ssize, 64);
- str[sindex++] = *s;
- }
- else if (s[1] == 'P')
- {
- s++;
- if (cpu > 10000)
- cpu = 10000;
- sum = cpu / 100;
- sum_frac = (cpu % 100) * 10;
- len = mkfmt (ts, 2, 0, sum, sum_frac);
- RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64);
- strcpy (str + sindex, ts);
- sindex += len;
- }
- else
- {
- prec = 3; /* default is three places past the decimal point. */
- lng = 0; /* default is to not use minutes or append `s' */
- s++;
- if (DIGIT (*s)) /* `precision' */
- {
- prec = *s++ - '0';
- if (prec > 3) prec = 3;
- }
- if (*s == 'l') /* `length extender' */
- {
- lng = 1;
- s++;
- }
- if (*s == 'R' || *s == 'E')
- len = mkfmt (ts, prec, lng, rs, rsf);
- else if (*s == 'U')
- len = mkfmt (ts, prec, lng, us, usf);
- else if (*s == 'S')
- len = mkfmt (ts, prec, lng, ss, ssf);
- else
- {
- internal_error (_("TIMEFORMAT: `%c': invalid format character"), *s);
- free (str);
- return;
- }
- RESIZE_MALLOCED_BUFFER (str, sindex, len, ssize, 64);
- strcpy (str + sindex, ts);
- sindex += len;
- }
- }
-
- str[sindex] = '\0';
- fprintf (fp, "%s\n", str);
- fflush (fp);
-
- free (str);
-}
-
-static int
-time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
- COMMAND *command;
- int asynchronous, pipe_in, pipe_out;
- struct fd_bitmap *fds_to_close;
-{
- int rv, posix_time, old_flags;
- time_t rs, us, ss;
- int rsf, usf, ssf;
- int cpu;
- char *time_format;
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
- struct timeval real, user, sys;
- struct timeval before, after;
-# if defined (HAVE_STRUCT_TIMEZONE)
- struct timezone dtz; /* posix doesn't define this */
-# endif
- struct rusage selfb, selfa, kidsb, kidsa; /* a = after, b = before */
-#else
-# if defined (HAVE_TIMES)
- clock_t tbefore, tafter, real, user, sys;
- struct tms before, after;
-# endif
-#endif
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-# if defined (HAVE_STRUCT_TIMEZONE)
- gettimeofday (&before, &dtz);
-# else
- gettimeofday (&before, (void *)NULL);
-# endif /* !HAVE_STRUCT_TIMEZONE */
- getrusage (RUSAGE_SELF, &selfb);
- getrusage (RUSAGE_CHILDREN, &kidsb);
-#else
-# if defined (HAVE_TIMES)
- tbefore = times (&before);
-# endif
-#endif
-
- posix_time = (command->flags & CMD_TIME_POSIX);
-
- old_flags = command->flags;
- command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
- rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close);
- command->flags = old_flags;
-
- rs = us = ss = 0;
- rsf = usf = ssf = cpu = 0;
-
-#if defined (HAVE_GETRUSAGE) && defined (HAVE_GETTIMEOFDAY)
-# if defined (HAVE_STRUCT_TIMEZONE)
- gettimeofday (&after, &dtz);
-# else
- gettimeofday (&after, (void *)NULL);
-# endif /* !HAVE_STRUCT_TIMEZONE */
- getrusage (RUSAGE_SELF, &selfa);
- getrusage (RUSAGE_CHILDREN, &kidsa);
-
- difftimeval (&real, &before, &after);
- timeval_to_secs (&real, &rs, &rsf);
-
- addtimeval (&user, difftimeval(&after, &selfb.ru_utime, &selfa.ru_utime),
- difftimeval(&before, &kidsb.ru_utime, &kidsa.ru_utime));
- timeval_to_secs (&user, &us, &usf);
-
- addtimeval (&sys, difftimeval(&after, &selfb.ru_stime, &selfa.ru_stime),
- difftimeval(&before, &kidsb.ru_stime, &kidsa.ru_stime));
- timeval_to_secs (&sys, &ss, &ssf);
-
- cpu = timeval_to_cpu (&real, &user, &sys);
-#else
-# if defined (HAVE_TIMES)
- tafter = times (&after);
-
- real = tafter - tbefore;
- clock_t_to_secs (real, &rs, &rsf);
-
- user = (after.tms_utime - before.tms_utime) + (after.tms_cutime - before.tms_cutime);
- clock_t_to_secs (user, &us, &usf);
-
- sys = (after.tms_stime - before.tms_stime) + (after.tms_cstime - before.tms_cstime);
- clock_t_to_secs (sys, &ss, &ssf);
-
- cpu = (real == 0) ? 0 : ((user + sys) * 10000) / real;
-
-# else
- rs = us = ss = 0;
- rsf = usf = ssf = cpu = 0;
-# endif
-#endif
-
- if (posix_time)
- time_format = POSIX_TIMEFORMAT;
- else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
- time_format = BASH_TIMEFORMAT;
-
- if (time_format && *time_format)
- print_formatted_time (stderr, time_format, rs, rsf, us, usf, ss, ssf, cpu);
-
- return rv;
-}
-#endif /* COMMAND_TIMING */
-
-/* Execute a command that's supposed to be in a subshell. This must be
- called after make_child and we must be running in the child process.
- The caller will return or exit() immediately with the value this returns. */
-static int
-execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close)
- COMMAND *command;
- int asynchronous;
- int pipe_in, pipe_out;
- struct fd_bitmap *fds_to_close;
-{
- int user_subshell, return_code, function_value, should_redir_stdin, invert;
- int ois;
- COMMAND *tcom;
-
- USE_VAR(user_subshell);
- USE_VAR(invert);
- USE_VAR(tcom);
- USE_VAR(asynchronous);
-
- subshell_level++;
- should_redir_stdin = (asynchronous && (command->flags & CMD_STDIN_REDIR) &&
- pipe_in == NO_PIPE &&
- stdin_redirects (command->redirects) == 0);
-
- invert = (command->flags & CMD_INVERT_RETURN) != 0;
- user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0);
-
- command->flags &= ~(CMD_FORCE_SUBSHELL | CMD_WANT_SUBSHELL | CMD_INVERT_RETURN);
-
- /* If a command is asynchronous in a subshell (like ( foo ) & or
- the special case of an asynchronous GROUP command where the
- the subshell bit is turned on down in case cm_group: below),
- turn off `asynchronous', so that two subshells aren't spawned.
- XXX - asynchronous used to be set to 0 in this block, but that
- means that setup_async_signals was never run. Now it's set to
- 0 after subshell_environment is set appropriately and setup_async_signals
- is run.
-
- This seems semantically correct to me. For example,
- ( foo ) & seems to say ``do the command `foo' in a subshell
- environment, but don't wait for that subshell to finish'',
- and "{ foo ; bar ; } &" seems to me to be like functions or
- builtins in the background, which executed in a subshell
- environment. I just don't see the need to fork two subshells. */
-
- /* Don't fork again, we are already in a subshell. A `doubly
- async' shell is not interactive, however. */
- if (asynchronous)
- {
-#if defined (JOB_CONTROL)
- /* If a construct like ( exec xxx yyy ) & is given while job
- control is active, we want to prevent exec from putting the
- subshell back into the original process group, carefully
- undoing all the work we just did in make_child. */
- original_pgrp = -1;
-#endif /* JOB_CONTROL */
- ois = interactive_shell;
- interactive_shell = 0;
- /* This test is to prevent alias expansion by interactive shells that
- run `(command) &' but to allow scripts that have enabled alias
- expansion with `shopt -s expand_alias' to continue to expand
- aliases. */
- if (ois != interactive_shell)
- expand_aliases = 0;
- }
-
- /* Subshells are neither login nor interactive. */
- login_shell = interactive = 0;
-
- if (user_subshell)
- subshell_environment = SUBSHELL_PAREN;
- else
- {
- subshell_environment = 0; /* XXX */
- if (asynchronous)
- subshell_environment |= SUBSHELL_ASYNC;
- if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
- subshell_environment |= SUBSHELL_PIPE;
- }
-
- reset_terminating_signals (); /* in sig.c */
- /* Cancel traps, in trap.c. */
- restore_original_signals ();
-
- /* Make sure restore_original_signals doesn't undo the work done by
- make_child to ensure that asynchronous children are immune to SIGINT
- and SIGQUIT. Turn off asynchronous to make sure more subshells are
- not spawned. */
- if (asynchronous)
- {
- setup_async_signals ();
- asynchronous = 0;
- }
-
-#if defined (JOB_CONTROL)
- set_sigchld_handler ();
-#endif /* JOB_CONTROL */
-
- set_sigint_handler ();
-
-#if defined (JOB_CONTROL)
- /* Delete all traces that there were any jobs running. This is
- only for subshells. */
- without_job_control ();
-#endif /* JOB_CONTROL */
-
- if (fds_to_close)
- close_fd_bitmap (fds_to_close);
-
- do_piping (pipe_in, pipe_out);
-
- /* If this is a user subshell, set a flag if stdin was redirected.
- This is used later to decide whether to redirect fd 0 to
- /dev/null for async commands in the subshell. This adds more
- sh compatibility, but I'm not sure it's the right thing to do. */
- if (user_subshell)
- {
- stdin_redir = stdin_redirects (command->redirects);
- restore_default_signal (0);
- }
-
- /* If this is an asynchronous command (command &), we want to
- redirect the standard input from /dev/null in the absence of
- any specific redirection involving stdin. */
- if (should_redir_stdin && stdin_redir == 0)
- async_redirect_stdin ();
-
- /* Do redirections, then dispose of them before recursive call. */
- if (command->redirects)
- {
- if (do_redirections (command->redirects, RX_ACTIVE) != 0)
- exit (invert ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
-
- dispose_redirects (command->redirects);
- command->redirects = (REDIRECT *)NULL;
- }
-
- tcom = (command->type == cm_subshell) ? command->value.Subshell->command : command;
-
- if (command->flags & CMD_TIME_PIPELINE)
- tcom->flags |= CMD_TIME_PIPELINE;
- if (command->flags & CMD_TIME_POSIX)
- tcom->flags |= CMD_TIME_POSIX;
-
- /* Make sure the subshell inherits any CMD_IGNORE_RETURN flag. */
- if ((command->flags & CMD_IGNORE_RETURN) && tcom != command)
- tcom->flags |= CMD_IGNORE_RETURN;
-
- /* If this is a simple command, tell execute_disk_command that it
- might be able to get away without forking and simply exec.
- This means things like ( sleep 10 ) will only cause one fork.
- If we're timing the command or inverting its return value, however,
- we cannot do this optimization. */
- if (user_subshell && (tcom->type == cm_simple || tcom->type == cm_subshell) &&
- ((tcom->flags & CMD_TIME_PIPELINE) == 0) &&
- ((tcom->flags & CMD_INVERT_RETURN) == 0))
- {
- tcom->flags |= CMD_NO_FORK;
- if (tcom->type == cm_simple)
- tcom->value.Simple->flags |= CMD_NO_FORK;
- }
-
- invert = (tcom->flags & CMD_INVERT_RETURN) != 0;
- tcom->flags &= ~CMD_INVERT_RETURN;
-
- /* If we're inside a function while executing this subshell, we
- need to handle a possible `return'. */
- function_value = 0;
- if (return_catch_flag)
- function_value = setjmp (return_catch);
-
- if (function_value)
- return_code = return_catch_value;
- else
- return_code = execute_command_internal (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close);
-
- /* If we are asked to, invert the return value. */
- if (invert)
- return_code = (return_code == EXECUTION_SUCCESS) ? EXECUTION_FAILURE
- : EXECUTION_SUCCESS;
-
- /* If we were explicitly placed in a subshell with (), we need
- to do the `shell cleanup' things, such as running traps[0]. */
- if (user_subshell && signal_is_trapped (0))
- {
- last_command_exit_value = return_code;
- return_code = run_exit_trap ();
- }
-
- subshell_level--;
- return (return_code);
- /* NOTREACHED */
-}
-
-static int
-execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close)
- COMMAND *command;
- int asynchronous, pipe_in, pipe_out;
- struct fd_bitmap *fds_to_close;
-{
- int prev, fildes[2], new_bitmap_size, dummyfd, ignore_return, exec_result;
- COMMAND *cmd;
- struct fd_bitmap *fd_bitmap;
-
-#if defined (JOB_CONTROL)
- sigset_t set, oset;
- BLOCK_CHILD (set, oset);
-#endif /* JOB_CONTROL */
-
- ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
- prev = pipe_in;
- cmd = command;
-
- while (cmd && cmd->type == cm_connection &&
- cmd->value.Connection && cmd->value.Connection->connector == '|')
- {
- /* Make a pipeline between the two commands. */
- if (pipe (fildes) < 0)
- {
- sys_error ("pipe error");
-#if defined (JOB_CONTROL)
- terminate_current_pipeline ();
- kill_current_pipeline ();
- UNBLOCK_CHILD (oset);
-#endif /* JOB_CONTROL */
- last_command_exit_value = EXECUTION_FAILURE;
- /* The unwind-protects installed below will take care
- of closing all of the open file descriptors. */
- throw_to_top_level ();
- return (EXECUTION_FAILURE); /* XXX */
- }
-
- /* Here is a problem: with the new file close-on-exec
- code, the read end of the pipe (fildes[0]) stays open
- in the first process, so that process will never get a
- SIGPIPE. There is no way to signal the first process
- that it should close fildes[0] after forking, so it
- remains open. No SIGPIPE is ever sent because there
- is still a file descriptor open for reading connected
- to the pipe. We take care of that here. This passes
- around a bitmap of file descriptors that must be
- closed after making a child process in execute_simple_command. */
-
- /* We need fd_bitmap to be at least as big as fildes[0].
- If fildes[0] is less than fds_to_close->size, then
- use fds_to_close->size. */
- new_bitmap_size = (fildes[0] < fds_to_close->size)
- ? fds_to_close->size
- : fildes[0] + 8;
-
- fd_bitmap = new_fd_bitmap (new_bitmap_size);
-
- /* Now copy the old information into the new bitmap. */
- xbcopy ((char *)fds_to_close->bitmap, (char *)fd_bitmap->bitmap, fds_to_close->size);
-
- /* And mark the pipe file descriptors to be closed. */
- fd_bitmap->bitmap[fildes[0]] = 1;
-
- /* In case there are pipe or out-of-processes errors, we
- want all these file descriptors to be closed when
- unwind-protects are run, and the storage used for the
- bitmaps freed up. */
- begin_unwind_frame ("pipe-file-descriptors");
- add_unwind_protect (dispose_fd_bitmap, fd_bitmap);
- add_unwind_protect (close_fd_bitmap, fd_bitmap);
- if (prev >= 0)
- add_unwind_protect (close, prev);
- dummyfd = fildes[1];
- add_unwind_protect (close, dummyfd);
-
-#if defined (JOB_CONTROL)
- add_unwind_protect (restore_signal_mask, &oset);
-#endif /* JOB_CONTROL */
-
- if (ignore_return && cmd->value.Connection->first)
- cmd->value.Connection->first->flags |= CMD_IGNORE_RETURN;
- execute_command_internal (cmd->value.Connection->first, asynchronous,
- prev, fildes[1], fd_bitmap);
-
- if (prev >= 0)
- close (prev);
-
- prev = fildes[0];
- close (fildes[1]);
-
- dispose_fd_bitmap (fd_bitmap);
- discard_unwind_frame ("pipe-file-descriptors");
-
- cmd = cmd->value.Connection->second;
- }
-
- /* Now execute the rightmost command in the pipeline. */
- if (ignore_return && cmd)
- cmd->flags |= CMD_IGNORE_RETURN;
- exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, fds_to_close);
-
- if (prev >= 0)
- close (prev);
-
-#if defined (JOB_CONTROL)
- UNBLOCK_CHILD (oset);
-#endif
-
- return (exec_result);
-}
-
-static int
-execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
- COMMAND *command;
- int asynchronous, pipe_in, pipe_out;
- struct fd_bitmap *fds_to_close;
-{
- REDIRECT *rp;
- COMMAND *tc, *second;
- int ignore_return, exec_result;
-
- ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
- switch (command->value.Connection->connector)
- {
- /* Do the first command asynchronously. */
- case '&':
- tc = command->value.Connection->first;
- if (tc == 0)
- return (EXECUTION_SUCCESS);
-
- rp = tc->redirects;
-
- if (ignore_return)
- tc->flags |= CMD_IGNORE_RETURN;
- tc->flags |= CMD_AMPERSAND;
-
- /* If this shell was compiled without job control support,
- if we are currently in a subshell via `( xxx )', or if job
- control is not active then the standard input for an
- asynchronous command is forced to /dev/null. */
-#if defined (JOB_CONTROL)
- if ((subshell_environment || !job_control) && !stdin_redir)
-#else
- if (!stdin_redir)
-#endif /* JOB_CONTROL */
- tc->flags |= CMD_STDIN_REDIR;
-
- exec_result = execute_command_internal (tc, 1, pipe_in, pipe_out, fds_to_close);
-
- if (tc->flags & CMD_STDIN_REDIR)
- tc->flags &= ~CMD_STDIN_REDIR;
-
- second = command->value.Connection->second;
- if (second)
- {
- if (ignore_return)
- second->flags |= CMD_IGNORE_RETURN;
-
- exec_result = execute_command_internal (second, asynchronous, pipe_in, pipe_out, fds_to_close);
- }
-
- break;
-
- /* Just call execute command on both sides. */
- case ';':
- if (ignore_return)
- {
- if (command->value.Connection->first)
- command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
- if (command->value.Connection->second)
- command->value.Connection->second->flags |= CMD_IGNORE_RETURN;
- }
- QUIT;
- execute_command (command->value.Connection->first);
- QUIT;
- exec_result = execute_command_internal (command->value.Connection->second,
- asynchronous, pipe_in, pipe_out,
- fds_to_close);
- break;
-
- case '|':
- exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);
- break;
-
- case AND_AND:
- case OR_OR:
- if (asynchronous)
- {
- /* If we have something like `a && b &' or `a || b &', run the
- && or || stuff in a subshell. Force a subshell and just call
- execute_command_internal again. Leave asynchronous on
- so that we get a report from the parent shell about the
- background job. */
- command->flags |= CMD_FORCE_SUBSHELL;
- exec_result = execute_command_internal (command, 1, pipe_in, pipe_out, fds_to_close);
- break;
- }
-
- /* Execute the first command. If the result of that is successful
- and the connector is AND_AND, or the result is not successful
- and the connector is OR_OR, then execute the second command,
- otherwise return. */
-
- if (command->value.Connection->first)
- command->value.Connection->first->flags |= CMD_IGNORE_RETURN;
-
- exec_result = execute_command (command->value.Connection->first);
- QUIT;
- if (((command->value.Connection->connector == AND_AND) &&
- (exec_result == EXECUTION_SUCCESS)) ||
- ((command->value.Connection->connector == OR_OR) &&
- (exec_result != EXECUTION_SUCCESS)))
- {
- if (ignore_return && command->value.Connection->second)
- command->value.Connection->second->flags |= CMD_IGNORE_RETURN;
-
- exec_result = execute_command (command->value.Connection->second);
- }
- break;
-
- default:
- command_error ("execute_connection", CMDERR_BADCONN, command->value.Connection->connector, 0);
- jump_to_top_level (DISCARD);
- exec_result = EXECUTION_FAILURE;
- }
-
- return exec_result;
-}
-
-#define REAP() \
- do \
- { \
- if (!interactive_shell) \
- reap_dead_jobs (); \
- } \
- while (0)
-
-/* Execute a FOR command. The syntax is: FOR word_desc IN word_list;
- DO command; DONE */
-static int
-execute_for_command (for_command)
- FOR_COM *for_command;
-{
- register WORD_LIST *releaser, *list;
- SHELL_VAR *v;
- char *identifier;
- int retval, save_line_number;
-#if 0
- SHELL_VAR *old_value = (SHELL_VAR *)NULL; /* Remember the old value of x. */
-#endif
-
- save_line_number = line_number;
- if (check_identifier (for_command->name, 1) == 0)
- {
- if (posixly_correct && interactive_shell == 0)
- {
- last_command_exit_value = EX_USAGE;
- jump_to_top_level (ERREXIT);
- }
- return (EXECUTION_FAILURE);
- }
-
- loop_level++;
- identifier = for_command->name->word;
-
- list = releaser = expand_words_no_vars (for_command->map_list);
-
- begin_unwind_frame ("for");
- add_unwind_protect (dispose_words, releaser);
-
-#if 0
- if (lexical_scoping)
- {
- old_value = copy_variable (find_variable (identifier));
- if (old_value)
- add_unwind_protect (dispose_variable, old_value);
- }
-#endif
-
- if (for_command->flags & CMD_IGNORE_RETURN)
- for_command->action->flags |= CMD_IGNORE_RETURN;
-
- for (retval = EXECUTION_SUCCESS; list; list = list->next)
- {
- QUIT;
-
- line_number = for_command->line;
-
- /* Remember what this command looks like, for debugger. */
- command_string_index = 0;
- print_for_command_head (for_command);
-
- if (echo_command_at_execute)
- xtrace_print_for_command_head (for_command);
-
- /* Save this command unless it's a trap command and we're not running
- a debug trap. */
- 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);
- }
-
- retval = run_debug_trap ();
-#if defined (DEBUGGER)
- /* In debugging mode, if the DEBUG trap returns a non-zero status, we
- skip the command. */
- if (debugging_mode && retval != EXECUTION_SUCCESS)
- continue;
-#endif
-
- this_command_name = (char *)NULL;
- v = bind_variable (identifier, list->word->word, 0);
- if (readonly_p (v) || noassign_p (v))
- {
- line_number = save_line_number;
- if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- jump_to_top_level (FORCE_EOF);
- }
- else
- {
- dispose_words (releaser);
- discard_unwind_frame ("for");
- loop_level--;
- return (EXECUTION_FAILURE);
- }
- }
- retval = execute_command (for_command->action);
- REAP ();
- QUIT;
-
- if (breaking)
- {
- breaking--;
- break;
- }
-
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
- }
-
- loop_level--;
- line_number = save_line_number;
-
-#if 0
- if (lexical_scoping)
- {
- if (!old_value)
- unbind_variable (identifier);
- else
- {
- SHELL_VAR *new_value;
-
- new_value = bind_variable (identifier, value_cell(old_value), 0);
- new_value->attributes = old_value->attributes;
- dispose_variable (old_value);
- }
- }
-#endif
-
- dispose_words (releaser);
- discard_unwind_frame ("for");
- return (retval);
-}
-
-#if defined (ARITH_FOR_COMMAND)
-/* Execute an arithmetic for command. The syntax is
-
- for (( init ; step ; test ))
- do
- body
- done
-
- The execution should be exactly equivalent to
-
- eval \(\( init \)\)
- while eval \(\( test \)\) ; do
- body;
- eval \(\( step \)\)
- done
-*/
-static intmax_t
-eval_arith_for_expr (l, okp)
- WORD_LIST *l;
- int *okp;
-{
- WORD_LIST *new;
- intmax_t expresult;
- int r;
-
- new = expand_words_no_vars (l);
- if (new)
- {
- if (echo_command_at_execute)
- xtrace_print_arith_cmd (new);
- this_command_name = "(("; /* )) for expression error messages */
-
- command_string_index = 0;
- print_arith_command (new);
- if (signal_in_progress (DEBUG_TRAP) == 0)
- {
- FREE (the_printed_command_except_trap);
- the_printed_command_except_trap = savestring (the_printed_command);
- }
-
- r = run_debug_trap ();
- /* In debugging mode, if the DEBUG trap returns a non-zero status, we
- skip the command. */
-#if defined (DEBUGGER)
- if (debugging_mode == 0 || r == EXECUTION_SUCCESS)
- expresult = evalexp (new->word->word, okp);
- else
- {
- expresult = 0;
- if (okp)
- *okp = 1;
- }
-#else
- expresult = evalexp (new->word->word, okp);
-#endif
- dispose_words (new);
- }
- else
- {
- expresult = 0;
- if (okp)
- *okp = 1;
- }
- return (expresult);
-}
-
-static int
-execute_arith_for_command (arith_for_command)
- ARITH_FOR_COM *arith_for_command;
-{
- intmax_t expresult;
- int expok, body_status, arith_lineno, save_lineno;
-
- body_status = EXECUTION_SUCCESS;
- loop_level++;
- save_lineno = line_number;
-
- if (arith_for_command->flags & CMD_IGNORE_RETURN)
- arith_for_command->action->flags |= CMD_IGNORE_RETURN;
-
- this_command_name = "(("; /* )) for expression error messages */
-
- /* save the starting line number of the command so we can reset
- line_number before executing each expression -- for $LINENO
- and the DEBUG trap. */
- line_number = arith_lineno = arith_for_command->line;
- if (variable_context && interactive_shell)
- line_number -= function_line_number;
-
- /* Evaluate the initialization expression. */
- expresult = eval_arith_for_expr (arith_for_command->init, &expok);
- if (expok == 0)
- {
- line_number = save_lineno;
- return (EXECUTION_FAILURE);
- }
-
- while (1)
- {
- /* Evaluate the test expression. */
- line_number = arith_lineno;
- expresult = eval_arith_for_expr (arith_for_command->test, &expok);
- line_number = save_lineno;
-
- if (expok == 0)
- {
- body_status = EXECUTION_FAILURE;
- break;
- }
- REAP ();
- if (expresult == 0)
- break;
-
- /* Execute the body of the arithmetic for command. */
- QUIT;
- body_status = execute_command (arith_for_command->action);
- QUIT;
-
- /* Handle any `break' or `continue' commands executed by the body. */
- if (breaking)
- {
- breaking--;
- break;
- }
-
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
-
- /* Evaluate the step expression. */
- line_number = arith_lineno;
- expresult = eval_arith_for_expr (arith_for_command->step, &expok);
- line_number = save_lineno;
-
- if (expok == 0)
- {
- body_status = EXECUTION_FAILURE;
- break;
- }
- }
-
- loop_level--;
- line_number = save_lineno;
-
- return (body_status);
-}
-#endif
-
-#if defined (SELECT_COMMAND)
-static int LINES, COLS, tabsize;
-
-#define RP_SPACE ") "
-#define RP_SPACE_LEN 2
-
-/* XXX - does not handle numbers > 1000000 at all. */
-#define NUMBER_LEN(s) \
-((s < 10) ? 1 \
- : ((s < 100) ? 2 \
- : ((s < 1000) ? 3 \
- : ((s < 10000) ? 4 \
- : ((s < 100000) ? 5 \
- : 6)))))
-
-static int
-print_index_and_element (len, ind, list)
- int len, ind;
- WORD_LIST *list;
-{
- register WORD_LIST *l;
- register int i;
-
- if (list == 0)
- return (0);
- for (i = ind, l = list; l && --i; l = l->next)
- ;
- fprintf (stderr, "%*d%s%s", len, ind, RP_SPACE, l->word->word);
- return (STRLEN (l->word->word));
-}
-
-static void
-indent (from, to)
- int from, to;
-{
- while (from < to)
- {
- if ((to / tabsize) > (from / tabsize))
- {
- putc ('\t', stderr);
- from += tabsize - from % tabsize;
- }
- else
- {
- putc (' ', stderr);
- from++;
- }
- }
-}
-
-static void
-print_select_list (list, list_len, max_elem_len, indices_len)
- WORD_LIST *list;
- int list_len, max_elem_len, indices_len;
-{
- int ind, row, elem_len, pos, cols, rows;
- int first_column_indices_len, other_indices_len;
-
- if (list == 0)
- {
- putc ('\n', stderr);
- return;
- }
-
- cols = max_elem_len ? COLS / max_elem_len : 1;
- if (cols == 0)
- cols = 1;
- rows = list_len ? list_len / cols + (list_len % cols != 0) : 1;
- cols = list_len ? list_len / rows + (list_len % rows != 0) : 1;
-
- if (rows == 1)
- {
- rows = cols;
- cols = 1;
- }
-
- first_column_indices_len = NUMBER_LEN (rows);
- other_indices_len = indices_len;
-
- for (row = 0; row < rows; row++)
- {
- ind = row;
- pos = 0;
- while (1)
- {
- indices_len = (pos == 0) ? first_column_indices_len : other_indices_len;
- elem_len = print_index_and_element (indices_len, ind + 1, list);
- elem_len += indices_len + RP_SPACE_LEN;
- ind += rows;
- if (ind >= list_len)
- break;
- indent (pos + elem_len, pos + max_elem_len);
- pos += max_elem_len;
- }
- putc ('\n', stderr);
- }
-}
-
-/* Print the elements of LIST, one per line, preceded by an index from 1 to
- LIST_LEN. Then display PROMPT and wait for the user to enter a number.
- If the number is between 1 and LIST_LEN, return that selection. If EOF
- is read, return a null string. If a blank line is entered, or an invalid
- number is entered, the loop is executed again. */
-static char *
-select_query (list, list_len, prompt, print_menu)
- WORD_LIST *list;
- int list_len;
- char *prompt;
- int print_menu;
-{
- int max_elem_len, indices_len, len;
- intmax_t reply;
- WORD_LIST *l;
- char *repl_string, *t;
-
- t = get_string_value ("LINES");
- LINES = (t && *t) ? atoi (t) : 24;
- t = get_string_value ("COLUMNS");
- COLS = (t && *t) ? atoi (t) : 80;
-
-#if 0
- t = get_string_value ("TABSIZE");
- tabsize = (t && *t) ? atoi (t) : 8;
- if (tabsize <= 0)
- tabsize = 8;
-#else
- tabsize = 8;
-#endif
-
- max_elem_len = 0;
- for (l = list; l; l = l->next)
- {
- len = STRLEN (l->word->word);
- if (len > max_elem_len)
- max_elem_len = len;
- }
- indices_len = NUMBER_LEN (list_len);
- max_elem_len += indices_len + RP_SPACE_LEN + 2;
-
- while (1)
- {
- if (print_menu)
- print_select_list (list, list_len, max_elem_len, indices_len);
- fprintf (stderr, "%s", prompt);
- fflush (stderr);
- QUIT;
-
- if (read_builtin ((WORD_LIST *)NULL) == EXECUTION_FAILURE)
- {
- putchar ('\n');
- return ((char *)NULL);
- }
- repl_string = get_string_value ("REPLY");
- if (*repl_string == 0)
- {
- print_menu = 1;
- continue;
- }
- if (legal_number (repl_string, &reply) == 0)
- return "";
- if (reply < 1 || reply > list_len)
- return "";
-
- for (l = list; l && --reply; l = l->next)
- ;
- return (l->word->word);
- }
-}
-
-/* Execute a SELECT command. The syntax is:
- SELECT word IN list DO command_list DONE
- Only `break' or `return' in command_list will terminate
- the command. */
-static int
-execute_select_command (select_command)
- SELECT_COM *select_command;
-{
- WORD_LIST *releaser, *list;
- SHELL_VAR *v;
- char *identifier, *ps3_prompt, *selection;
- int retval, list_len, show_menu, save_line_number;
-
- if (check_identifier (select_command->name, 1) == 0)
- return (EXECUTION_FAILURE);
-
- save_line_number = line_number;
- line_number = select_command->line;
-
- command_string_index = 0;
- print_select_command_head (select_command);
-
- if (echo_command_at_execute)
- xtrace_print_select_command_head (select_command);
-
- 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);
- }
-
- retval = run_debug_trap ();
-#if defined (DEBUGGER)
- /* In debugging mode, if the DEBUG trap returns a non-zero status, we
- skip the command. */
- if (debugging_mode && retval != EXECUTION_SUCCESS)
- return (EXECUTION_SUCCESS);
-#endif
-
- loop_level++;
- identifier = select_command->name->word;
-
- /* command and arithmetic substitution, parameter and variable expansion,
- word splitting, pathname expansion, and quote removal. */
- list = releaser = expand_words_no_vars (select_command->map_list);
- list_len = list_length (list);
- if (list == 0 || list_len == 0)
- {
- if (list)
- dispose_words (list);
- line_number = save_line_number;
- return (EXECUTION_SUCCESS);
- }
-
- begin_unwind_frame ("select");
- add_unwind_protect (dispose_words, releaser);
-
- if (select_command->flags & CMD_IGNORE_RETURN)
- select_command->action->flags |= CMD_IGNORE_RETURN;
-
- retval = EXECUTION_SUCCESS;
- show_menu = 1;
-
- while (1)
- {
- line_number = select_command->line;
- ps3_prompt = get_string_value ("PS3");
- if (ps3_prompt == 0)
- ps3_prompt = "#? ";
-
- QUIT;
- selection = select_query (list, list_len, ps3_prompt, show_menu);
- QUIT;
- if (selection == 0)
- {
- /* select_query returns EXECUTION_FAILURE if the read builtin
- fails, so we want to return failure in this case. */
- retval = EXECUTION_FAILURE;
- break;
- }
-
- v = bind_variable (identifier, selection, 0);
- if (readonly_p (v) || noassign_p (v))
- {
- if (readonly_p (v) && interactive_shell == 0 && posixly_correct)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- jump_to_top_level (FORCE_EOF);
- }
- else
- {
- dispose_words (releaser);
- discard_unwind_frame ("select");
- loop_level--;
- line_number = save_line_number;
- return (EXECUTION_FAILURE);
- }
- }
-
- retval = execute_command (select_command->action);
-
- REAP ();
- QUIT;
-
- if (breaking)
- {
- breaking--;
- break;
- }
-
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
-
-#if defined (KSH_COMPATIBLE_SELECT)
- show_menu = 0;
- selection = get_string_value ("REPLY");
- if (selection && *selection == '\0')
- show_menu = 1;
-#endif
- }
-
- loop_level--;
- line_number = save_line_number;
-
- dispose_words (releaser);
- discard_unwind_frame ("select");
- return (retval);
-}
-#endif /* SELECT_COMMAND */
-
-/* Execute a CASE command. The syntax is: CASE word_desc IN pattern_list ESAC.
- The pattern_list is a linked list of pattern clauses; each clause contains
- some patterns to compare word_desc against, and an associated command to
- execute. */
-static int
-execute_case_command (case_command)
- CASE_COM *case_command;
-{
- register WORD_LIST *list;
- WORD_LIST *wlist, *es;
- PATTERN_LIST *clauses;
- char *word, *pattern;
- int retval, match, ignore_return, save_line_number;
-
- save_line_number = line_number;
- line_number = case_command->line;
-
- command_string_index = 0;
- print_case_command_head (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)))
- {
- FREE (the_printed_command_except_trap);
- the_printed_command_except_trap = savestring (the_printed_command);
- }
-
- retval = run_debug_trap();
-#if defined (DEBUGGER)
- /* In debugging mode, if the DEBUG trap returns a non-zero status, we
- skip the command. */
- if (debugging_mode && retval != EXECUTION_SUCCESS)
- {
- line_number = save_line_number;
- return (EXECUTION_SUCCESS);
- }
-#endif
-
- wlist = expand_word_unsplit (case_command->word, 0);
- word = wlist ? string_list (wlist) : savestring ("");
- dispose_words (wlist);
-
- retval = EXECUTION_SUCCESS;
- ignore_return = case_command->flags & CMD_IGNORE_RETURN;
-
- begin_unwind_frame ("case");
- add_unwind_protect ((Function *)xfree, word);
-
-#define EXIT_CASE() goto exit_case_command
-
- for (clauses = case_command->clauses; clauses; clauses = clauses->next)
- {
- QUIT;
- for (list = clauses->patterns; list; list = list->next)
- {
- es = expand_word_leave_quoted (list->word, 0);
-
- if (es && es->word && es->word->word && *(es->word->word))
- pattern = quote_string_for_globbing (es->word->word, QGLOB_CVTNULL);
- else
- {
- pattern = (char *)xmalloc (1);
- pattern[0] = '\0';
- }
-
- /* Since the pattern does not undergo quote removal (as per
- Posix.2, section 3.9.4.3), the strmatch () call must be able
- to recognize backslashes as escape characters. */
- match = strmatch (pattern, word, FNMATCH_EXTFLAG|FNMATCH_IGNCASE) != FNM_NOMATCH;
- free (pattern);
-
- dispose_words (es);
-
- if (match)
- {
- if (clauses->action && ignore_return)
- clauses->action->flags |= CMD_IGNORE_RETURN;
- retval = execute_command (clauses->action);
- EXIT_CASE ();
- }
-
- QUIT;
- }
- }
-
-exit_case_command:
- free (word);
- discard_unwind_frame ("case");
- line_number = save_line_number;
- return (retval);
-}
-
-#define CMD_WHILE 0
-#define CMD_UNTIL 1
-
-/* The WHILE command. Syntax: WHILE test DO action; DONE.
- Repeatedly execute action while executing test produces
- EXECUTION_SUCCESS. */
-static int
-execute_while_command (while_command)
- WHILE_COM *while_command;
-{
- return (execute_while_or_until (while_command, CMD_WHILE));
-}
-
-/* UNTIL is just like WHILE except that the test result is negated. */
-static int
-execute_until_command (while_command)
- WHILE_COM *while_command;
-{
- return (execute_while_or_until (while_command, CMD_UNTIL));
-}
-
-/* The body for both while and until. The only difference between the
- two is that the test value is treated differently. TYPE is
- CMD_WHILE or CMD_UNTIL. The return value for both commands should
- be EXECUTION_SUCCESS if no commands in the body are executed, and
- the status of the last command executed in the body otherwise. */
-static int
-execute_while_or_until (while_command, type)
- WHILE_COM *while_command;
- int type;
-{
- int return_value, body_status;
-
- body_status = EXECUTION_SUCCESS;
- loop_level++;
-
- while_command->test->flags |= CMD_IGNORE_RETURN;
- if (while_command->flags & CMD_IGNORE_RETURN)
- while_command->action->flags |= CMD_IGNORE_RETURN;
-
- while (1)
- {
- return_value = execute_command (while_command->test);
- REAP ();
-
- /* Need to handle `break' in the test when we would break out of the
- loop. The job control code will set `breaking' to loop_level
- when a job in a loop is stopped with SIGTSTP. If the stopped job
- is in the loop test, `breaking' will not be reset unless we do
- this, and the shell will cease to execute commands. */
- if (type == CMD_WHILE && return_value != EXECUTION_SUCCESS)
- {
- if (breaking)
- breaking--;
- break;
- }
- if (type == CMD_UNTIL && return_value == EXECUTION_SUCCESS)
- {
- if (breaking)
- breaking--;
- break;
- }
-
- QUIT;
- body_status = execute_command (while_command->action);
- QUIT;
-
- if (breaking)
- {
- breaking--;
- break;
- }
-
- if (continuing)
- {
- continuing--;
- if (continuing)
- break;
- }
- }
- loop_level--;
-
- return (body_status);
-}
-
-/* IF test THEN command [ELSE command].
- IF also allows ELIF in the place of ELSE IF, but
- the parser makes *that* stupidity transparent. */
-static int
-execute_if_command (if_command)
- IF_COM *if_command;
-{
- int return_value, save_line_number;
-
- save_line_number = line_number;
- if_command->test->flags |= CMD_IGNORE_RETURN;
- return_value = execute_command (if_command->test);
- line_number = save_line_number;
-
- if (return_value == EXECUTION_SUCCESS)
- {
- QUIT;
-
- if (if_command->true_case && (if_command->flags & CMD_IGNORE_RETURN))
- if_command->true_case->flags |= CMD_IGNORE_RETURN;
-
- return (execute_command (if_command->true_case));
- }
- else
- {
- QUIT;
-
- if (if_command->false_case && (if_command->flags & CMD_IGNORE_RETURN))
- if_command->false_case->flags |= CMD_IGNORE_RETURN;
-
- return (execute_command (if_command->false_case));
- }
-}
-
-#if defined (DPAREN_ARITHMETIC)
-static int
-execute_arith_command (arith_command)
- ARITH_COM *arith_command;
-{
- int expok, save_line_number, retval;
- intmax_t expresult;
- WORD_LIST *new;
- char *exp;
-
- expresult = 0;
-
- save_line_number = line_number;
- this_command_name = "(("; /* )) */
- line_number = arith_command->line;
- /* If we're in a function, update the line number information. */
- if (variable_context && interactive_shell)
- line_number -= function_line_number;
-
- command_string_index = 0;
- print_arith_command (arith_command->exp);
-
- if (signal_in_progress (DEBUG_TRAP) == 0)
- {
- FREE (the_printed_command_except_trap);
- the_printed_command_except_trap = savestring (the_printed_command);
- }
-
- /* Run the debug trap before each arithmetic command, but do it after we
- update the line number information and before we expand the various
- words in the expression. */
- retval = run_debug_trap ();
-#if defined (DEBUGGER)
- /* In debugging mode, if the DEBUG trap returns a non-zero status, we
- skip the command. */
- if (debugging_mode && retval != EXECUTION_SUCCESS)
- {
- line_number = save_line_number;
- return (EXECUTION_SUCCESS);
- }
-#endif
-
- new = expand_words_no_vars (arith_command->exp);
-
- /* If we're tracing, make a new word list with `((' at the front and `))'
- at the back and print it. */
- if (echo_command_at_execute)
- xtrace_print_arith_cmd (new);
-
- if (new)
- {
- 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
- {
- expresult = 0;
- expok = 1;
- }
-
- if (expok == 0)
- return (EXECUTION_FAILURE);
-
- return (expresult == 0 ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
-}
-#endif /* DPAREN_ARITHMETIC */
-
-#if defined (COND_COMMAND)
-
-static char *nullstr = "";
-
-static int
-execute_cond_node (cond)
- COND_COM *cond;
-{
- int result, invert, patmatch, rmatch, mflags;
- char *arg1, *arg2;
-
- invert = (cond->flags & CMD_INVERT_RETURN);
-
- if (cond->type == COND_EXPR)
- result = execute_cond_node (cond->left);
- else if (cond->type == COND_OR)
- {
- result = execute_cond_node (cond->left);
- if (result != EXECUTION_SUCCESS)
- result = execute_cond_node (cond->right);
- }
- else if (cond->type == COND_AND)
- {
- result = execute_cond_node (cond->left);
- if (result == EXECUTION_SUCCESS)
- result = execute_cond_node (cond->right);
- }
- else if (cond->type == COND_UNARY)
- {
- arg1 = cond_expand_word (cond->left->op, 0);
- if (arg1 == 0)
- arg1 = nullstr;
- if (echo_command_at_execute)
- xtrace_print_cond_term (cond->type, invert, cond->op, arg1, (char *)NULL);
- result = unary_test (cond->op->word, arg1) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
- if (arg1 != nullstr)
- free (arg1);
- }
- else if (cond->type == COND_BINARY)
- {
- rmatch = 0;
- patmatch = ((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') &&
- (cond->op->word[0] == '!' || cond->op->word[0] == '=') ||
- (cond->op->word[0] == '=' && cond->op->word[1] == '\0'));
-#if defined (COND_REGEXP)
- rmatch = (cond->op->word[0] == '=' && cond->op->word[1] == '~' &&
- cond->op->word[2] == '\0');
-#endif
-
- arg1 = cond_expand_word (cond->left->op, 0);
- if (arg1 == 0)
- arg1 = nullstr;
- arg2 = cond_expand_word (cond->right->op, patmatch||rmatch);
- if (arg2 == 0)
- arg2 = nullstr;
-
- if (echo_command_at_execute)
- xtrace_print_cond_term (cond->type, invert, cond->op, arg1, arg2);
-
-#if defined (COND_REGEXP)
- if (rmatch)
- {
- mflags = SHMAT_PWARN;
-#if defined (ARRAY_VARS)
- mflags |= SHMAT_SUBEXP;
-#endif
-
- result = sh_regmatch (arg1, arg2, mflags);
- }
- else
-#endif /* COND_REGEXP */
- {
- int oe;
- oe = extended_glob;
- extended_glob = 1;
- result = binary_test (cond->op->word, arg1, arg2, TEST_PATMATCH|TEST_ARITHEXP)
- ? EXECUTION_SUCCESS
- : EXECUTION_FAILURE;
- extended_glob = oe;
- }
- if (arg1 != nullstr)
- free (arg1);
- if (arg2 != nullstr)
- free (arg2);
- }
- else
- {
- command_error ("execute_cond_node", CMDERR_BADTYPE, cond->type, 0);
- jump_to_top_level (DISCARD);
- result = EXECUTION_FAILURE;
- }
-
- if (invert)
- result = (result == EXECUTION_SUCCESS) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
-
- return result;
-}
-
-static int
-execute_cond_command (cond_command)
- COND_COM *cond_command;
-{
- int retval, save_line_number;
-
- retval = EXECUTION_SUCCESS;
- save_line_number = line_number;
-
- this_command_name = "[[";
- line_number = cond_command->line;
- /* If we're in a function, update the line number information. */
- if (variable_context && interactive_shell)
- line_number -= function_line_number;
-
- command_string_index = 0;
- print_cond_command (cond_command);
-
- if (signal_in_progress (DEBUG_TRAP) == 0)
- {
- FREE (the_printed_command_except_trap);
- the_printed_command_except_trap = savestring (the_printed_command);
- }
-
- /* Run the debug trap before each conditional command, but do it after we
- update the line number information. */
- retval = run_debug_trap ();
-#if defined (DEBUGGER)
- /* In debugging mode, if the DEBUG trap returns a non-zero status, we
- skip the command. */
- if (debugging_mode && retval != EXECUTION_SUCCESS)
- {
- line_number = save_line_number;
- return (EXECUTION_SUCCESS);
- }
-#endif
-
-#if 0
- debug_print_cond_command (cond_command);
-#endif
-
- last_command_exit_value = retval = execute_cond_node (cond_command);
- line_number = save_line_number;
- return (retval);
-}
-#endif /* COND_COMMAND */
-
-static void
-bind_lastarg (arg)
- char *arg;
-{
- SHELL_VAR *var;
-
- if (arg == 0)
- arg = "";
- var = bind_variable ("_", arg, 0);
- VUNSETATTR (var, att_exported);
-}
-
-/* Execute a null command. Fork a subshell if the command uses pipes or is
- to be run asynchronously. This handles all the side effects that are
- supposed to take place. */
-static int
-execute_null_command (redirects, pipe_in, pipe_out, async)
- REDIRECT *redirects;
- int pipe_in, pipe_out, async;
-{
- int r;
-
- if (pipe_in != NO_PIPE || pipe_out != NO_PIPE || async)
- {
- /* We have a null command, but we really want a subshell to take
- care of it. Just fork, do piping and redirections, and exit. */
- if (make_child ((char *)NULL, async) == 0)
- {
- /* Cancel traps, in trap.c. */
- restore_original_signals (); /* XXX */
-
- do_piping (pipe_in, pipe_out);
-
- if (async)
- subshell_environment |= SUBSHELL_ASYNC;
- if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
- subshell_environment |= SUBSHELL_PIPE;
-
- if (do_redirections (redirects, RX_ACTIVE) == 0)
- exit (EXECUTION_SUCCESS);
- else
- exit (EXECUTION_FAILURE);
- }
- else
- {
- close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
- unlink_fifo_list ();
-#endif
- return (EXECUTION_SUCCESS);
- }
- }
- else
- {
- /* Even if there aren't any command names, pretend to do the
- redirections that are specified. The user expects the side
- effects to take place. If the redirections fail, then return
- failure. Otherwise, if a command substitution took place while
- expanding the command or a redirection, return the value of that
- substitution. Otherwise, return EXECUTION_SUCCESS. */
-
- r = do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE);
- cleanup_redirects (redirection_undo_list);
- redirection_undo_list = (REDIRECT *)NULL;
-
- if (r != 0)
- return (EXECUTION_FAILURE);
- else if (last_command_subst_pid != NO_PID)
- return (last_command_exit_value);
- else
- return (EXECUTION_SUCCESS);
- }
-}
-
-/* This is a hack to suppress word splitting for assignment statements
- given as arguments to builtins with the ASSIGNMENT_BUILTIN flag set. */
-static void
-fix_assignment_words (words)
- WORD_LIST *words;
-{
- WORD_LIST *w;
- struct builtin *b;
-
- if (words == 0)
- return;
-
- b = 0;
-
- for (w = words; w; w = w->next)
- if (w->word->flags & W_ASSIGNMENT)
- {
- if (b == 0)
- {
- b = builtin_address_internal (words->word->word, 0);
- if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
- return;
- else if (b && (b->flags & ASSIGNMENT_BUILTIN))
- words->word->flags |= W_ASSNBLTIN;
- }
- w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG);
- }
-}
-
-/* The meaty part of all the executions. We have to start hacking the
- real execution of commands here. Fork a process, set things up,
- execute the command. */
-static int
-execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close)
- SIMPLE_COM *simple_command;
- int pipe_in, pipe_out, async;
- struct fd_bitmap *fds_to_close;
-{
- WORD_LIST *words, *lastword;
- char *command_line, *lastarg, *temp;
- int first_word_quoted, result, builtin_is_special, already_forked, dofork;
- pid_t old_last_async_pid;
- sh_builtin_func_t *builtin;
- SHELL_VAR *func;
-
- result = EXECUTION_SUCCESS;
- special_builtin_failed = builtin_is_special = 0;
- command_line = (char *)0;
-
- /* If we're in a function, update the line number information. */
- if (variable_context && interactive_shell)
- line_number -= function_line_number;
-
- /* Remember what this command line looks like at invocation. */
- command_string_index = 0;
- print_simple_command (simple_command);
-
- 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 = the_printed_command ? savestring (the_printed_command) : (char *)0;
- }
-
- /* Run the debug trap before each simple command, but do it after we
- update the line number information. */
- result = run_debug_trap ();
-#if defined (DEBUGGER)
- /* In debugging mode, if the DEBUG trap returns a non-zero status, we
- skip the command. */
- if (debugging_mode && result != EXECUTION_SUCCESS)
- return (EXECUTION_SUCCESS);
-#endif
-
- first_word_quoted =
- simple_command->words ? (simple_command->words->word->flags & W_QUOTED): 0;
-
- last_command_subst_pid = NO_PID;
- old_last_async_pid = last_asynchronous_pid;
-
- already_forked = dofork = 0;
-
- /* If we're in a pipeline or run in the background, set DOFORK so we
- make the child early, before word expansion. This keeps assignment
- statements from affecting the parent shell's environment when they
- should not. */
- dofork = pipe_in != NO_PIPE || pipe_out != NO_PIPE || async;
-
- /* Something like `%2 &' should restart job 2 in the background, not cause
- the shell to fork here. */
- if (dofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE &&
- simple_command->words && simple_command->words->word &&
- simple_command->words->word->word &&
- (simple_command->words->word->word[0] == '%'))
- dofork = 0;
-
- if (dofork)
- {
- /* Do this now, because execute_disk_command will do it anyway in the
- vast majority of cases. */
- maybe_make_export_env ();
-
- /* Don't let a DEBUG trap overwrite the command string to be saved with
- the process/job associated with this child. */
- if (make_child (savestring (the_printed_command_except_trap), async) == 0)
- {
- already_forked = 1;
- simple_command->flags |= CMD_NO_FORK;
-
- subshell_environment = SUBSHELL_FORK;
- if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
- subshell_environment |= SUBSHELL_PIPE;
- if (async)
- subshell_environment |= SUBSHELL_ASYNC;
-
- /* We need to do this before piping to handle some really
- pathological cases where one of the pipe file descriptors
- is < 2. */
- if (fds_to_close)
- close_fd_bitmap (fds_to_close);
-
- do_piping (pipe_in, pipe_out);
- pipe_in = pipe_out = NO_PIPE;
-
- last_asynchronous_pid = old_last_async_pid;
- }
- else
- {
- close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
- unlink_fifo_list ();
-#endif
- command_line = (char *)NULL; /* don't free this. */
- bind_lastarg ((char *)NULL);
- return (result);
- }
- }
-
- /* If we are re-running this as the result of executing the `command'
- builtin, do not expand the command words a second time. */
- if ((simple_command->flags & CMD_INHIBIT_EXPANSION) == 0)
- {
- current_fds_to_close = fds_to_close;
- fix_assignment_words (simple_command->words);
- words = expand_words (simple_command->words);
- current_fds_to_close = (struct fd_bitmap *)NULL;
- }
- else
- words = copy_word_list (simple_command->words);
-
- /* It is possible for WORDS not to have anything left in it.
- Perhaps all the words consisted of `$foo', and there was
- no variable `$foo'. */
- if (words == 0)
- {
- this_command_name = 0;
- result = execute_null_command (simple_command->redirects,
- pipe_in, pipe_out,
- already_forked ? 0 : async);
- if (already_forked)
- exit (result);
- else
- {
- bind_lastarg ((char *)NULL);
- set_pipestatus_from_exit (result);
- return (result);
- }
- }
-
- lastarg = (char *)NULL;
-
- begin_unwind_frame ("simple-command");
-
- if (echo_command_at_execute)
- xtrace_print_word_list (words, 1);
-
- builtin = (sh_builtin_func_t *)NULL;
- func = (SHELL_VAR *)NULL;
- if ((simple_command->flags & CMD_NO_FUNCTIONS) == 0)
- {
- /* Posix.2 says special builtins are found before functions. We
- don't set builtin_is_special anywhere other than here, because
- this path is followed only when the `command' builtin is *not*
- being used, and we don't want to exit the shell if a special
- builtin executed with `command builtin' fails. `command' is not
- a special builtin. */
- if (posixly_correct)
- {
- builtin = find_special_builtin (words->word->word);
- if (builtin)
- builtin_is_special = 1;
- }
- if (builtin == 0)
- func = find_function (words->word->word);
- }
-
- /* In POSIX mode, assignment errors in the temporary environment cause a
- non-interactive shell to exit. */
- if (builtin_is_special && interactive_shell == 0 && tempenv_assign_error)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- jump_to_top_level (ERREXIT);
- }
-
- add_unwind_protect (dispose_words, words);
- QUIT;
-
- /* Bind the last word in this command to "$_" after execution. */
- for (lastword = words; lastword->next; lastword = lastword->next)
- ;
- lastarg = lastword->word->word;
-
-#if defined (JOB_CONTROL)
- /* Is this command a job control related thing? */
- if (words->word->word[0] == '%' && already_forked == 0)
- {
- this_command_name = async ? "bg" : "fg";
- last_shell_builtin = this_shell_builtin;
- this_shell_builtin = builtin_address (this_command_name);
- result = (*this_shell_builtin) (words);
- goto return_result;
- }
-
- /* One other possiblilty. The user may want to resume an existing job.
- If they do, find out whether this word is a candidate for a running
- job. */
- if (job_control && already_forked == 0 && async == 0 &&
- !first_word_quoted &&
- !words->next &&
- words->word->word[0] &&
- !simple_command->redirects &&
- pipe_in == NO_PIPE &&
- pipe_out == NO_PIPE &&
- (temp = get_string_value ("auto_resume")))
- {
- int job, jflags, started_status;
-
- jflags = JM_STOPPED|JM_FIRSTMATCH;
- if (STREQ (temp, "exact"))
- jflags |= JM_EXACT;
- else if (STREQ (temp, "substring"))
- jflags |= JM_SUBSTRING;
- else
- jflags |= JM_PREFIX;
- job = get_job_by_name (words->word->word, jflags);
- if (job != NO_JOB)
- {
- run_unwind_frame ("simple-command");
- this_command_name = "fg";
- last_shell_builtin = this_shell_builtin;
- this_shell_builtin = builtin_address ("fg");
-
- started_status = start_job (job, 1);
- return ((started_status < 0) ? EXECUTION_FAILURE : started_status);
- }
- }
-#endif /* JOB_CONTROL */
-
- /* Remember the name of this command globally. */
- this_command_name = words->word->word;
-
- QUIT;
-
- /* This command could be a shell builtin or a user-defined function.
- We have already found special builtins by this time, so we do not
- set builtin_is_special. If this is a function or builtin, and we
- have pipes, then fork a subshell in here. Otherwise, just execute
- the command directly. */
- if (func == 0 && builtin == 0)
- builtin = find_shell_builtin (this_command_name);
-
- last_shell_builtin = this_shell_builtin;
- this_shell_builtin = builtin;
-
- if (builtin || func)
- {
- if (already_forked)
- {
- /* reset_terminating_signals (); */ /* XXX */
- /* Cancel traps, in trap.c. */
- restore_original_signals ();
-
- if (async)
- {
- if ((simple_command->flags & CMD_STDIN_REDIR) &&
- pipe_in == NO_PIPE &&
- (stdin_redirects (simple_command->redirects) == 0))
- async_redirect_stdin ();
- setup_async_signals ();
- }
-
- subshell_level++;
- execute_subshell_builtin_or_function
- (words, simple_command->redirects, builtin, func,
- pipe_in, pipe_out, async, fds_to_close,
- simple_command->flags);
- subshell_level--;
- }
- else
- {
- result = execute_builtin_or_function
- (words, builtin, func, simple_command->redirects, fds_to_close,
- simple_command->flags);
- if (builtin)
- {
- if (result > EX_SHERRBASE)
- {
- result = builtin_status (result);
- if (builtin_is_special)
- special_builtin_failed = 1;
- }
- /* In POSIX mode, if there are assignment statements preceding
- a special builtin, they persist after the builtin
- completes. */
- if (posixly_correct && builtin_is_special && temporary_env)
- merge_temporary_env ();
- }
- else /* function */
- {
- if (result == EX_USAGE)
- result = EX_BADUSAGE;
- else if (result > EX_SHERRBASE)
- result = EXECUTION_FAILURE;
- }
-
- set_pipestatus_from_exit (result);
-
- goto return_result;
- }
- }
-
- if (command_line == 0)
- command_line = savestring (the_printed_command_except_trap);
-
- execute_disk_command (words, simple_command->redirects, command_line,
- pipe_in, pipe_out, async, fds_to_close,
- simple_command->flags);
-
- return_result:
- bind_lastarg (lastarg);
- FREE (command_line);
- dispose_words (words);
- discard_unwind_frame ("simple-command");
- this_command_name = (char *)NULL; /* points to freed memory now */
- return (result);
-}
-
-/* Translate the special builtin exit statuses. We don't really need a
- function for this; it's a placeholder for future work. */
-static int
-builtin_status (result)
- int result;
-{
- int r;
-
- switch (result)
- {
- case EX_USAGE:
- r = EX_BADUSAGE;
- break;
- case EX_REDIRFAIL:
- case EX_BADSYNTAX:
- case EX_BADASSIGN:
- case EX_EXPFAIL:
- r = EXECUTION_FAILURE;
- break;
- default:
- r = EXECUTION_SUCCESS;
- break;
- }
- return (r);
-}
-
-static int
-execute_builtin (builtin, words, flags, subshell)
- sh_builtin_func_t *builtin;
- WORD_LIST *words;
- int flags, subshell;
-{
- int old_e_flag, result, eval_unwind;
- int isbltinenv;
-
- old_e_flag = exit_immediately_on_error;
- /* The eval builtin calls parse_and_execute, which does not know about
- the setting of flags, and always calls the execution functions with
- flags that will exit the shell on an error if -e is set. If the
- eval builtin is being called, and we're supposed to ignore the exit
- value of the command, we turn the -e flag off ourselves, then
- restore it when the command completes. */
- if (subshell == 0 && builtin == eval_builtin && (flags & CMD_IGNORE_RETURN))
- {
- begin_unwind_frame ("eval_builtin");
- unwind_protect_int (exit_immediately_on_error);
- exit_immediately_on_error = 0;
- eval_unwind = 1;
- }
- else
- eval_unwind = 0;
-
- /* The temporary environment for a builtin is supposed to apply to
- all commands executed by that builtin. Currently, this is a
- problem only with the `unset', `source' and `eval' builtins. */
-
- isbltinenv = (builtin == source_builtin || builtin == eval_builtin || builtin == unset_builtin);
-
- if (isbltinenv)
- {
- if (subshell == 0)
- begin_unwind_frame ("builtin_env");
-
- if (temporary_env)
- {
- push_scope (VC_BLTNENV, temporary_env);
- if (subshell == 0)
- add_unwind_protect (pop_scope, (flags & CMD_COMMAND_BUILTIN) ? 0 : "1");
- temporary_env = (HASH_TABLE *)NULL;
- }
- }
-
- /* `return' does a longjmp() back to a saved environment in execute_function.
- If a variable assignment list preceded the command, and the shell is
- running in POSIX mode, we need to merge that into the shell_variables
- table, since `return' is a POSIX special builtin. */
- if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
- {
- begin_unwind_frame ("return_temp_env");
- add_unwind_protect (merge_temporary_env, (char *)NULL);
- }
-
- result = ((*builtin) (words->next));
-
- /* This shouldn't happen, but in case `return' comes back instead of
- longjmp'ing, we need to unwind. */
- if (posixly_correct && subshell == 0 && builtin == return_builtin && temporary_env)
- discard_unwind_frame ("return_temp_env");
-
- if (subshell == 0 && isbltinenv)
- run_unwind_frame ("builtin_env");
-
- if (eval_unwind)
- {
- exit_immediately_on_error += old_e_flag;
- discard_unwind_frame ("eval_builtin");
- }
-
- return (result);
-}
-
-static int
-execute_function (var, words, flags, fds_to_close, async, subshell)
- SHELL_VAR *var;
- WORD_LIST *words;
- int flags;
- struct fd_bitmap *fds_to_close;
- int async, subshell;
-{
- int return_val, result;
- COMMAND *tc, *fc, *save_current;
- char *debug_trap, *error_trap, *return_trap;
-#if defined (ARRAY_VARS)
- SHELL_VAR *funcname_v, *nfv, *bash_source_v, *bash_lineno_v;
- ARRAY *funcname_a, *bash_source_a, *bash_lineno_a;
-#endif
- FUNCTION_DEF *shell_fn;
- char *sfile, *t;
- static int funcnest = 0;
-
- USE_VAR(fc);
-
-#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);
-#endif
-
- tc = (COMMAND *)copy_command (function_cell (var));
- if (tc && (flags & CMD_IGNORE_RETURN))
- tc->flags |= CMD_IGNORE_RETURN;
-
- if (subshell == 0)
- {
- begin_unwind_frame ("function_calling");
- push_context (var->name, subshell, temporary_env);
- add_unwind_protect (pop_context, (char *)NULL);
- unwind_protect_int (line_number);
- unwind_protect_int (return_catch_flag);
- unwind_protect_jmp_buf (return_catch);
- add_unwind_protect (dispose_command, (char *)tc);
- unwind_protect_pointer (this_shell_function);
- unwind_protect_int (loop_level);
- }
- else
- push_context (var->name, subshell, temporary_env); /* don't unwind-protect for subshells */
-
- temporary_env = (HASH_TABLE *)NULL;
-
- this_shell_function = var;
- make_funcname_visible (1);
-
- debug_trap = TRAP_STRING(DEBUG_TRAP);
- error_trap = TRAP_STRING(ERROR_TRAP);
- return_trap = TRAP_STRING(RETURN_TRAP);
-
- /* The order of the unwind protects for debug_trap, error_trap and
- return_trap is important here! unwind-protect commands are run
- in reverse order of registration. If this causes problems, take
- out the xfree unwind-protect calls and live with the small memory leak. */
-
- /* function_trace_mode != 0 means that all functions inherit the DEBUG trap.
- if the function has the trace attribute set, it inherits the DEBUG trap */
- if (debug_trap && ((trace_p (var) == 0) && function_trace_mode == 0))
- {
- if (subshell == 0)
- {
- debug_trap = savestring (debug_trap);
- add_unwind_protect (xfree, debug_trap);
- add_unwind_protect (set_debug_trap, debug_trap);
- }
- restore_default_signal (DEBUG_TRAP);
- }
-
- /* error_trace_mode != 0 means that functions inherit the ERR trap. */
- if (error_trap && error_trace_mode == 0)
- {
- if (subshell == 0)
- {
- error_trap = savestring (error_trap);
- add_unwind_protect (xfree, error_trap);
- add_unwind_protect (set_error_trap, error_trap);
- }
- restore_default_signal (ERROR_TRAP);
- }
-
- /* Shell functions inherit the RETURN trap if function tracing is on
- globally or on individually for this function. */
-#if 0
- if (return_trap && ((trace_p (var) == 0) && function_trace_mode == 0))
-#else
- if (return_trap && (signal_in_progress (DEBUG_TRAP) || ((trace_p (var) == 0) && function_trace_mode == 0)))
-#endif
- {
- if (subshell == 0)
- {
- return_trap = savestring (return_trap);
- add_unwind_protect (xfree, return_trap);
- add_unwind_protect (set_return_trap, return_trap);
- }
- restore_default_signal (RETURN_TRAP);
- }
-
- funcnest++;
-#if defined (ARRAY_VARS)
- /* This is quite similar to the code in shell.c and elsewhere. */
- shell_fn = find_function_def (this_shell_function->name);
- sfile = shell_fn ? shell_fn->source_file : "";
- array_push (funcname_a, this_shell_function->name);
-
- array_push (bash_source_a, sfile);
- t = itos (executing_line_number ());
- array_push (bash_lineno_a, t);
- free (t);
-#endif
-
- /* The temporary environment for a function is supposed to apply to
- all commands executed within the function body. */
-
- remember_args (words->next, 1);
-
- /* Update BASH_ARGV and BASH_ARGC */
- if (debugging_mode)
- push_args (words->next);
-
- /* Number of the line on which the function body starts. */
- line_number = function_line_number = tc->line;
-
-#if defined (JOB_CONTROL)
- if (subshell)
- stop_pipeline (async, (COMMAND *)NULL);
-#endif
-
- fc = tc;
-
- return_catch_flag++;
- return_val = setjmp (return_catch);
-
- if (return_val)
- {
- result = return_catch_value;
- /* Run the RETURN trap in the function's context. */
- save_current = currently_executing_command;
- run_return_trap ();
- currently_executing_command = save_current;
- }
- else
- {
- /* Run the debug trap here so we can trap at the start of a function's
- execution rather than the execution of the body's first command. */
- showing_function_line = 1;
- save_current = currently_executing_command;
- result = run_debug_trap ();
-#if defined (DEBUGGER)
- /* In debugging mode, if the DEBUG trap returns a non-zero status, we
- skip the command. */
- if (debugging_mode == 0 || result == EXECUTION_SUCCESS)
- {
- showing_function_line = 0;
- currently_executing_command = save_current;
- result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close);
-
- /* Run the RETURN trap in the function's context */
- save_current = currently_executing_command;
- run_return_trap ();
- currently_executing_command = save_current;
- }
-#else
- result = execute_command_internal (fc, 0, NO_PIPE, NO_PIPE, fds_to_close);
-
- save_current = currently_executing_command;
- run_return_trap ();
- currently_executing_command = save_current;
-#endif
- showing_function_line = 0;
- }
-
- /* Restore BASH_ARGC and BASH_ARGV */
- if (debugging_mode)
- pop_args ();
-
- if (subshell == 0)
- run_unwind_frame ("function_calling");
-
- funcnest--;
-#if defined (ARRAY_VARS)
- /* These two variables cannot be unset, and cannot be affected by the
- function. */
- array_pop (bash_source_a);
- array_pop (bash_lineno_a);
-
- /* FUNCNAME can be unset, and so can potentially be changed by the
- function. */
- GET_ARRAY_FROM_VAR ("FUNCNAME", nfv, funcname_a);
- if (nfv == funcname_v)
- array_pop (funcname_a);
-#endif
-
- if (variable_context == 0 || this_shell_function == 0)
- make_funcname_visible (0);
-
- return (result);
-}
-
-/* A convenience routine for use by other parts of the shell to execute
- a particular shell function. */
-int
-execute_shell_function (var, words)
- SHELL_VAR *var;
- WORD_LIST *words;
-{
- int ret;
- struct fd_bitmap *bitmap;
-
- bitmap = new_fd_bitmap (FD_BITMAP_DEFAULT_SIZE);
- begin_unwind_frame ("execute-shell-function");
- add_unwind_protect (dispose_fd_bitmap, (char *)bitmap);
-
- ret = execute_function (var, words, 0, bitmap, 0, 0);
-
- dispose_fd_bitmap (bitmap);
- discard_unwind_frame ("execute-shell-function");
-
- return ret;
-}
-
-/* Execute a shell builtin or function in a subshell environment. This
- routine does not return; it only calls exit(). If BUILTIN is non-null,
- it points to a function to call to execute a shell builtin; otherwise
- VAR points at the body of a function to execute. WORDS is the arguments
- to the command, REDIRECTS specifies redirections to perform before the
- command is executed. */
-static void
-execute_subshell_builtin_or_function (words, redirects, builtin, var,
- pipe_in, pipe_out, async, fds_to_close,
- flags)
- WORD_LIST *words;
- REDIRECT *redirects;
- sh_builtin_func_t *builtin;
- SHELL_VAR *var;
- int pipe_in, pipe_out, async;
- struct fd_bitmap *fds_to_close;
- int flags;
-{
- int result, r, funcvalue;
-#if defined (JOB_CONTROL)
- int jobs_hack;
-
- jobs_hack = (builtin == jobs_builtin) &&
- ((subshell_environment & SUBSHELL_ASYNC) == 0 || pipe_out != NO_PIPE);
-#endif
-
- /* A subshell is neither a login shell nor interactive. */
- login_shell = interactive = 0;
-
- if (async)
- subshell_environment |= SUBSHELL_ASYNC;
- if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
- subshell_environment |= SUBSHELL_PIPE;
-
- maybe_make_export_env (); /* XXX - is this needed? */
-
-#if defined (JOB_CONTROL)
- /* Eradicate all traces of job control after we fork the subshell, so
- all jobs begun by this subshell are in the same process group as
- the shell itself. */
-
- /* Allow the output of `jobs' to be piped. */
- if (jobs_hack)
- kill_current_pipeline ();
- else
- without_job_control ();
-
- set_sigchld_handler ();
-#endif /* JOB_CONTROL */
-
- set_sigint_handler ();
-
- if (fds_to_close)
- close_fd_bitmap (fds_to_close);
-
- do_piping (pipe_in, pipe_out);
-
- if (do_redirections (redirects, RX_ACTIVE) != 0)
- exit (EXECUTION_FAILURE);
-
- if (builtin)
- {
- /* Give builtins a place to jump back to on failure,
- so we don't go back up to main(). */
- result = setjmp (top_level);
-
- /* Give the return builtin a place to jump to when executed in a subshell
- or pipeline */
- funcvalue = 0;
- if (return_catch_flag && builtin == return_builtin)
- funcvalue = setjmp (return_catch);
-
- if (result == EXITPROG)
- exit (last_command_exit_value);
- else if (result)
- exit (EXECUTION_FAILURE);
- else if (funcvalue)
- exit (return_catch_value);
- else
- {
- r = execute_builtin (builtin, words, flags, 1);
- if (r == EX_USAGE)
- r = EX_BADUSAGE;
- exit (r);
- }
- }
- else
- exit (execute_function (var, words, flags, fds_to_close, async, 1));
-}
-
-/* Execute a builtin or function in the current shell context. If BUILTIN
- is non-null, it is the builtin command to execute, otherwise VAR points
- to the body of a function. WORDS are the command's arguments, REDIRECTS
- are the redirections to perform. FDS_TO_CLOSE is the usual bitmap of
- file descriptors to close.
-
- If BUILTIN is exec_builtin, the redirections specified in REDIRECTS are
- not undone before this function returns. */
-static int
-execute_builtin_or_function (words, builtin, var, redirects,
- fds_to_close, flags)
- WORD_LIST *words;
- sh_builtin_func_t *builtin;
- SHELL_VAR *var;
- REDIRECT *redirects;
- struct fd_bitmap *fds_to_close;
- int flags;
-{
- int result;
- REDIRECT *saved_undo_list;
- sh_builtin_func_t *saved_this_shell_builtin;
-
- if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
- {
- cleanup_redirects (redirection_undo_list);
- redirection_undo_list = (REDIRECT *)NULL;
- dispose_exec_redirects ();
- return (EX_REDIRFAIL); /* was EXECUTION_FAILURE */
- }
-
- saved_this_shell_builtin = this_shell_builtin;
- saved_undo_list = redirection_undo_list;
-
- /* Calling the "exec" builtin changes redirections forever. */
- if (builtin == exec_builtin)
- {
- dispose_redirects (saved_undo_list);
- saved_undo_list = exec_redirection_undo_list;
- exec_redirection_undo_list = (REDIRECT *)NULL;
- }
- else
- dispose_exec_redirects ();
-
- if (saved_undo_list)
- {
- begin_unwind_frame ("saved redirects");
- add_unwind_protect (cleanup_redirects, (char *)saved_undo_list);
- }
-
- redirection_undo_list = (REDIRECT *)NULL;
-
- if (builtin)
- result = execute_builtin (builtin, words, flags, 0);
- else
- result = execute_function (var, words, flags, fds_to_close, 0, 0);
-
- /* We do this before undoing the effects of any redirections. */
- if (ferror (stdout))
- clearerr (stdout);
-
- /* If we are executing the `command' builtin, but this_shell_builtin is
- set to `exec_builtin', we know that we have something like
- `command exec [redirection]', since otherwise `exec' would have
- overwritten the shell and we wouldn't get here. In this case, we
- want to behave as if the `command' builtin had not been specified
- and preserve the redirections. */
- if (builtin == command_builtin && this_shell_builtin == exec_builtin)
- {
- if (saved_undo_list)
- dispose_redirects (saved_undo_list);
- redirection_undo_list = exec_redirection_undo_list;
- saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;
- discard_unwind_frame ("saved_redirects");
- }
-
- if (saved_undo_list)
- {
- redirection_undo_list = saved_undo_list;
- discard_unwind_frame ("saved redirects");
- }
-
- if (redirection_undo_list)
- {
- cleanup_redirects (redirection_undo_list);
- redirection_undo_list = (REDIRECT *)NULL;
- }
-
- return (result);
-}
-
-void
-setup_async_signals ()
-{
-#if defined (__BEOS__)
- set_signal_handler (SIGHUP, SIG_IGN); /* they want csh-like behavior */
-#endif
-
-#if defined (JOB_CONTROL)
- if (job_control == 0)
-#endif
- {
- set_signal_handler (SIGINT, SIG_IGN);
- set_signal_ignored (SIGINT);
- set_signal_handler (SIGQUIT, SIG_IGN);
- set_signal_ignored (SIGQUIT);
- }
-}
-
-/* Execute a simple command that is hopefully defined in a disk file
- somewhere.
-
- 1) fork ()
- 2) connect pipes
- 3) look up the command
- 4) do redirections
- 5) execve ()
- 6) If the execve failed, see if the file has executable mode set.
- If so, and it isn't a directory, then execute its contents as
- a shell script.
-
- Note that the filename hashing stuff has to take place up here,
- in the parent. This is probably why the Bourne style shells
- don't handle it, since that would require them to go through
- this gnarly hair, for no good reason.
-
- NOTE: callers expect this to fork or exit(). */
-static void
-execute_disk_command (words, redirects, command_line, pipe_in, pipe_out,
- async, fds_to_close, cmdflags)
- WORD_LIST *words;
- REDIRECT *redirects;
- char *command_line;
- int pipe_in, pipe_out, async;
- struct fd_bitmap *fds_to_close;
- int cmdflags;
-{
- char *pathname, *command, **args;
- int nofork;
- pid_t pid;
-
- nofork = (cmdflags & CMD_NO_FORK); /* Don't fork, just exec, if no pipes */
- pathname = words->word->word;
-
-#if defined (RESTRICTED_SHELL)
- command = (char *)NULL;
- if (restricted && xstrchr (pathname, '/'))
- {
- internal_error (_("%s: restricted: cannot specify `/' in command names"),
- pathname);
- last_command_exit_value = EXECUTION_FAILURE;
-
- /* If we're not going to fork below, we must already be in a child
- process or a context in which it's safe to call exit(2). */
- if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
- exit (last_command_exit_value);
- else
- goto parent_return;
- }
-#endif /* RESTRICTED_SHELL */
-
- command = search_for_command (pathname);
-
- if (command)
- {
- maybe_make_export_env ();
- put_command_name_into_env (command);
- }
-
- /* We have to make the child before we check for the non-existence
- of COMMAND, since we want the error messages to be redirected. */
- /* If we can get away without forking and there are no pipes to deal with,
- don't bother to fork, just directly exec the command. */
- if (nofork && pipe_in == NO_PIPE && pipe_out == NO_PIPE)
- pid = 0;
- else
- pid = make_child (savestring (command_line), async);
-
- if (pid == 0)
- {
- int old_interactive;
-
-#if 0
- /* This has been disabled for the time being. */
-#if !defined (ARG_MAX) || ARG_MAX >= 10240
- if (posixly_correct == 0)
- put_gnu_argv_flags_into_env ((long)getpid (), glob_argv_flags);
-#endif
-#endif
-
- /* Cancel traps, in trap.c. */
- restore_original_signals ();
-
- /* restore_original_signals may have undone the work done
- by make_child to ensure that SIGINT and SIGQUIT are ignored
- in asynchronous children. */
- if (async)
- {
- if ((cmdflags & CMD_STDIN_REDIR) &&
- pipe_in == NO_PIPE &&
- (stdin_redirects (redirects) == 0))
- async_redirect_stdin ();
- setup_async_signals ();
- }
-
- /* This functionality is now provided by close-on-exec of the
- file descriptors manipulated by redirection and piping.
- Some file descriptors still need to be closed in all children
- because of the way bash does pipes; fds_to_close is a
- bitmap of all such file descriptors. */
- if (fds_to_close)
- close_fd_bitmap (fds_to_close);
-
- do_piping (pipe_in, pipe_out);
-
- old_interactive = interactive;
- if (async)
- interactive = 0;
-
- subshell_environment = SUBSHELL_FORK;
-
- if (redirects && (do_redirections (redirects, RX_ACTIVE) != 0))
- {
-#if defined (PROCESS_SUBSTITUTION)
- /* Try to remove named pipes that may have been created as the
- result of redirections. */
- unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
- exit (EXECUTION_FAILURE);
- }
-
- if (async)
- interactive = old_interactive;
-
- if (command == 0)
- {
- internal_error (_("%s: command not found"), pathname);
- exit (EX_NOTFOUND); /* Posix.2 says the exit status is 127 */
- }
-
- /* Execve expects the command name to be in args[0]. So we
- leave it there, in the same format that the user used to
- type it in. */
- args = strvec_from_word_list (words, 0, 0, (int *)NULL);
- exit (shell_execve (command, args, export_env));
- }
- else
- {
-parent_return:
- /* Make sure that the pipes are closed in the parent. */
- close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
- unlink_fifo_list ();
-#endif
- FREE (command);
- }
-}
-
-/* CPP defines to decide whether a particular index into the #! line
- corresponds to a valid interpreter name or argument character, or
- whitespace. The MSDOS define is to allow \r to be treated the same
- as \n. */
-
-#if !defined (MSDOS)
-# define STRINGCHAR(ind) \
- (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n')
-# define WHITECHAR(ind) \
- (ind < sample_len && whitespace (sample[ind]))
-#else /* MSDOS */
-# define STRINGCHAR(ind) \
- (ind < sample_len && !whitespace (sample[ind]) && sample[ind] != '\n' && sample[ind] != '\r')
-# define WHITECHAR(ind) \
- (ind < sample_len && whitespace (sample[ind]))
-#endif /* MSDOS */
-
-static char *
-getinterp (sample, sample_len, endp)
- char *sample;
- int sample_len, *endp;
-{
- register int i;
- char *execname;
- int start;
-
- /* Find the name of the interpreter to exec. */
- for (i = 2; i < sample_len && whitespace (sample[i]); i++)
- ;
-
- for (start = i; STRINGCHAR(i); i++)
- ;
-
- execname = substring (sample, start, i);
-
- if (endp)
- *endp = i;
- return execname;
-}
-
-#if !defined (HAVE_HASH_BANG_EXEC)
-/* If the operating system on which we're running does not handle
- the #! executable format, then help out. SAMPLE is the text read
- from the file, SAMPLE_LEN characters. COMMAND is the name of
- the script; it and ARGS, the arguments given by the user, will
- become arguments to the specified interpreter. ENV is the environment
- to pass to the interpreter.
-
- The word immediately following the #! is the interpreter to execute.
- A single argument to the interpreter is allowed. */
-
-static int
-execute_shell_script (sample, sample_len, command, args, env)
- char *sample;
- int sample_len;
- char *command;
- char **args, **env;
-{
- char *execname, *firstarg;
- int i, start, size_increment, larry;
-
- /* Find the name of the interpreter to exec. */
- execname = getinterp (sample, sample_len, &i);
- size_increment = 1;
-
- /* Now the argument, if any. */
- for (firstarg = (char *)NULL, start = i; WHITECHAR(i); i++)
- ;
-
- /* If there is more text on the line, then it is an argument for the
- interpreter. */
-
- if (STRINGCHAR(i))
- {
- for (start = i; STRINGCHAR(i); i++)
- ;
- firstarg = substring ((char *)sample, start, i);
- size_increment = 2;
- }
-
- larry = strvec_len (args) + size_increment;
- args = strvec_resize (args, larry + 1);
-
- for (i = larry - 1; i; i--)
- args[i] = args[i - size_increment];
-
- args[0] = execname;
- if (firstarg)
- {
- args[1] = firstarg;
- args[2] = command;
- }
- else
- args[1] = command;
-
- args[larry] = (char *)NULL;
-
- return (shell_execve (execname, args, env));
-}
-#undef STRINGCHAR
-#undef WHITECHAR
-
-#endif /* !HAVE_HASH_BANG_EXEC */
-
-static void
-initialize_subshell ()
-{
-#if defined (ALIAS)
- /* Forget about any aliases that we knew of. We are in a subshell. */
- delete_all_aliases ();
-#endif /* ALIAS */
-
-#if defined (HISTORY)
- /* Forget about the history lines we have read. This is a non-interactive
- subshell. */
- history_lines_this_session = 0;
-#endif
-
-#if defined (JOB_CONTROL)
- /* Forget about the way job control was working. We are in a subshell. */
- without_job_control ();
- set_sigchld_handler ();
- init_job_stats ();
-#endif /* JOB_CONTROL */
-
- /* Reset the values of the shell flags and options. */
- reset_shell_flags ();
- reset_shell_options ();
- reset_shopt_options ();
-
- /* Zero out builtin_env, since this could be a shell script run from a
- sourced file with a temporary environment supplied to the `source/.'
- builtin. Such variables are not supposed to be exported (empirical
- testing with sh and ksh). Just throw it away; don't worry about a
- memory leak. */
- if (vc_isbltnenv (shell_variables))
- shell_variables = shell_variables->down;
-
- clear_unwind_protect_list (0);
-
- /* We're no longer inside a shell function. */
- variable_context = return_catch_flag = 0;
-
- /* If we're not interactive, close the file descriptor from which we're
- reading the current shell script. */
- if (interactive_shell == 0)
- unset_bash_input (0);
-}
-
-#if defined (HAVE_SETOSTYPE) && defined (_POSIX_SOURCE)
-# define SETOSTYPE(x) __setostype(x)
-#else
-# define SETOSTYPE(x)
-#endif
-
-#define READ_SAMPLE_BUF(file, buf, len) \
- do \
- { \
- fd = open(file, O_RDONLY); \
- if (fd >= 0) \
- { \
- len = read (fd, buf, 80); \
- close (fd); \
- } \
- else \
- len = -1; \
- } \
- while (0)
-
-/* Call execve (), handling interpreting shell scripts, and handling
- exec failures. */
-int
-shell_execve (command, args, env)
- char *command;
- char **args, **env;
-{
- struct stat finfo;
- int larray, i, fd;
- char sample[80];
- int sample_len;
-
- SETOSTYPE (0); /* Some systems use for USG/POSIX semantics */
- execve (command, args, env);
- i = errno; /* error from execve() */
- SETOSTYPE (1);
-
- /* If we get to this point, then start checking out the file.
- Maybe it is something we can hack ourselves. */
- if (i != ENOEXEC)
- {
- if ((stat (command, &finfo) == 0) && (S_ISDIR (finfo.st_mode)))
- internal_error (_("%s: is a directory"), command);
- else if (executable_file (command) == 0)
- {
- errno = i;
- file_error (command);
- }
- /* errors not involving the path argument to execve. */
- else if (i == E2BIG || i == ENOMEM)
- {
- errno = i;
- file_error (command);
- }
- else
- {
- /* The file has the execute bits set, but the kernel refuses to
- run it for some reason. See why. */
-#if defined (HAVE_HASH_BANG_EXEC)
- READ_SAMPLE_BUF (command, sample, sample_len);
- if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
- {
- char *interp;
- int ilen;
-
- interp = getinterp (sample, sample_len, (int *)NULL);
- ilen = strlen (interp);
- errno = i;
- if (interp[ilen - 1] == '\r')
- {
- interp = xrealloc (interp, ilen + 2);
- interp[ilen - 1] = '^';
- interp[ilen] = 'M';
- interp[ilen + 1] = '\0';
- }
- sys_error (_("%s: %s: bad interpreter"), command, interp ? interp : "");
- FREE (interp);
- return (EX_NOEXEC);
- }
-#endif
- errno = i;
- file_error (command);
- }
- return ((i == ENOENT) ? EX_NOTFOUND : EX_NOEXEC); /* XXX Posix.2 says that exit status is 126 */
- }
-
- /* This file is executable.
- If it begins with #!, then help out people with losing operating
- systems. Otherwise, check to see if it is a binary file by seeing
- if the contents of the first line (or up to 80 characters) are in the
- ASCII set. If it's a text file, execute the contents as shell commands,
- otherwise return 126 (EX_BINARY_FILE). */
- READ_SAMPLE_BUF (command, sample, sample_len);
-
- if (sample_len == 0)
- return (EXECUTION_SUCCESS);
-
- /* Is this supposed to be an executable script?
- If so, the format of the line is "#! interpreter [argument]".
- A single argument is allowed. The BSD kernel restricts
- the length of the entire line to 32 characters (32 bytes
- being the size of the BSD exec header), but we allow 80
- characters. */
- if (sample_len > 0)
- {
-#if !defined (HAVE_HASH_BANG_EXEC)
- if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
- return (execute_shell_script (sample, sample_len, command, args, env));
- else
-#endif
- if (check_binary_file (sample, sample_len))
- {
- internal_error (_("%s: cannot execute binary file"), command);
- return (EX_BINARY_FILE);
- }
- }
-
- /* We have committed to attempting to execute the contents of this file
- as shell commands. */
-
- initialize_subshell ();
-
- set_sigint_handler ();
-
- /* Insert the name of this shell into the argument list. */
- larray = strvec_len (args) + 1;
- args = strvec_resize (args, larray + 1);
-
- for (i = larray - 1; i; i--)
- args[i] = args[i - 1];
-
- args[0] = shell_name;
- args[1] = command;
- args[larray] = (char *)NULL;
-
- if (args[0][0] == '-')
- args[0]++;
-
-#if defined (RESTRICTED_SHELL)
- if (restricted)
- change_flag ('r', FLAG_OFF);
-#endif
-
- if (subshell_argv)
- {
- /* Can't free subshell_argv[0]; that is shell_name. */
- for (i = 1; i < subshell_argc; i++)
- free (subshell_argv[i]);
- free (subshell_argv);
- }
-
- dispose_command (currently_executing_command); /* XXX */
- currently_executing_command = (COMMAND *)NULL;
-
- subshell_argc = larray;
- subshell_argv = args;
- subshell_envp = env;
-
- unbind_args (); /* remove the positional parameters */
-
- longjmp (subshell_top_level, 1);
- /*NOTREACHED*/
-}
-
-static int
-execute_intern_function (name, function)
- WORD_DESC *name;
- COMMAND *function;
-{
- SHELL_VAR *var;
-
- if (check_identifier (name, posixly_correct) == 0)
- {
- if (posixly_correct && interactive_shell == 0)
- {
- last_command_exit_value = EX_USAGE;
- jump_to_top_level (ERREXIT);
- }
- return (EXECUTION_FAILURE);
- }
-
- var = find_function (name->word);
- if (var && (readonly_p (var) || noassign_p (var)))
- {
- if (readonly_p (var))
- internal_error (_("%s: readonly function"), var->name);
- return (EXECUTION_FAILURE);
- }
-
- bind_function (name->word, function);
- return (EXECUTION_SUCCESS);
-}
-
-#if defined (INCLUDE_UNUSED)
-#if defined (PROCESS_SUBSTITUTION)
-void
-close_all_files ()
-{
- register int i, fd_table_size;
-
- fd_table_size = getdtablesize ();
- if (fd_table_size > 256) /* clamp to a reasonable value */
- fd_table_size = 256;
-
- for (i = 3; i < fd_table_size; i++)
- close (i);
-}
-#endif /* PROCESS_SUBSTITUTION */
-#endif
-
-static void
-close_pipes (in, out)
- int in, out;
-{
- if (in >= 0)
- close (in);
- if (out >= 0)
- close (out);
-}
-
-static void
-dup_error (oldd, newd)
- int oldd, newd;
-{
- sys_error (_("cannot duplicate fd %d to fd %d"), oldd, newd);
-}
-
-/* Redirect input and output to be from and to the specified pipes.
- NO_PIPE and REDIRECT_BOTH are handled correctly. */
-static void
-do_piping (pipe_in, pipe_out)
- int pipe_in, pipe_out;
-{
- if (pipe_in != NO_PIPE)
- {
- if (dup2 (pipe_in, 0) < 0)
- dup_error (pipe_in, 0);
- if (pipe_in > 0)
- close (pipe_in);
- }
- if (pipe_out != NO_PIPE)
- {
- if (pipe_out != REDIRECT_BOTH)
- {
- if (dup2 (pipe_out, 1) < 0)
- dup_error (pipe_out, 1);
- if (pipe_out == 0 || pipe_out > 1)
- close (pipe_out);
- }
- else
- {
- if (dup2 (1, 2) < 0)
- dup_error (1, 2);
- }
- }
-}
diff --git a/expr.c~ b/expr.c~
deleted file mode 100644
index ed00c845..00000000
--- a/expr.c~
+++ /dev/null
@@ -1,1348 +0,0 @@
-/* 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/externs.h~ b/externs.h~
deleted file mode 100644
index d2cd6fb8..00000000
--- a/externs.h~
+++ /dev/null
@@ -1,396 +0,0 @@
-/* externs.h -- extern function declarations which do not appear in their
- own header file. */
-
-/* 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. */
-
-/* Make sure that this is included *after* config.h! */
-
-#if !defined (_EXTERNS_H_)
-# define _EXTERNS_H_
-
-#include "stdc.h"
-
-/* Functions from expr.c. */
-extern intmax_t evalexp __P((char *, int *));
-
-/* Functions from print_cmd.c. */
-extern char *make_command_string __P((COMMAND *));
-extern char *named_function_string __P((char *, COMMAND *, int));
-
-extern void print_command __P((COMMAND *));
-extern void print_simple_command __P((SIMPLE_COM *));
-extern void print_word_list __P((WORD_LIST *, char *));
-
-/* debugger support */
-extern void print_for_command_head __P((FOR_COM *));
-#if defined (SELECT_COMMAND)
-extern void print_select_command_head __P((SELECT_COM *));
-#endif
-extern void print_case_command_head __P((CASE_COM *));
-#if defined (DPAREN_ARITHMETIC)
-extern void print_arith_command __P((WORD_LIST *));
-#endif
-#if defined (COND_COMMAND)
-extern void print_cond_command __P((COND_COM *));
-#endif
-
-/* set -x support */
-extern char *indirection_level_string __P((void));
-extern void xtrace_print_assignment __P((char *, char *, int, int));
-extern void xtrace_print_word_list __P((WORD_LIST *, int));
-extern void xtrace_print_for_command_head __P((FOR_COM *));
-#if defined (SELECT_COMMAND)
-extern void xtrace_print_select_command_head __P((SELECT_COM *));
-#endif
-extern void xtrace_print_case_command_head __P((CASE_COM *));
-#if defined (DPAREN_ARITHMETIC)
-extern void xtrace_print_arith_cmd __P((WORD_LIST *));
-#endif
-#if defined (COND_COMMAND)
-extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *));
-#endif
-
-/* Functions from shell.c. */
-extern void exit_shell __P((int)) __attribute__((__noreturn__));
-extern void sh_exit __P((int)) __attribute__((__noreturn__));
-extern void disable_priv_mode __P((void));
-extern void unbind_args __P((void));
-
-#if defined (RESTRICTED_SHELL)
-extern int shell_is_restricted __P((char *));
-extern int maybe_make_restricted __P((char *));
-#endif
-
-extern void unset_bash_input __P((int));
-extern void get_current_user_info __P((void));
-
-/* Functions from eval.c. */
-extern int reader_loop __P((void));
-extern int parse_command __P((void));
-extern int read_command __P((void));
-
-/* Functions from braces.c. */
-#if defined (BRACE_EXPANSION)
-extern char **brace_expand __P((char *));
-#endif
-
-/* Miscellaneous functions from parse.y */
-extern int yyparse __P((void));
-extern int return_EOF __P((void));
-extern void reset_parser __P((void));
-extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
-
-extern void free_pushed_string_input __P((void));
-
-extern char *decode_prompt_string __P((char *));
-
-extern int get_current_prompt_level __P((void));
-extern void set_current_prompt_level __P((int));
-
-#if defined (HISTORY)
-extern char *history_delimiting_chars __P((void));
-#endif
-
-/* Declarations for functions defined in locale.c */
-extern void set_default_locale __P((void));
-extern void set_default_locale_vars __P((void));
-extern int set_locale_var __P((char *, char *));
-extern int set_lang __P((char *, char *));
-extern void set_default_lang __P((void));
-extern char *get_locale_var __P((char *));
-extern char *localetrans __P((char *, int, int *));
-extern char *mk_msgstr __P((char *, int *));
-extern char *localeexpand __P((char *, int, int, int, int *));
-
-/* Declarations for functions defined in list.c. */
-extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *));
-extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *));
-extern GENERIC_LIST *list_reverse ();
-extern int list_length ();
-extern GENERIC_LIST *list_append ();
-extern GENERIC_LIST *list_remove ();
-
-/* Declarations for functions defined in stringlib.c */
-extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
-extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int));
-extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int));
-
-extern char *substring __P((char *, int, int));
-extern char *strsub __P((char *, char *, char *, int));
-extern char *strcreplace __P((char *, int, char *, int));
-extern void strip_leading __P((char *));
-extern void strip_trailing __P((char *, int, int));
-extern void xbcopy __P((char *, char *, int));
-
-/* Functions from version.c. */
-extern char *shell_version_string __P((void));
-extern void show_shell_version __P((int));
-
-/* Functions from the bash library, lib/sh/libsh.a. These should really
- go into a separate include file. */
-
-/* declarations for functions defined in lib/sh/clktck.c */
-extern long get_clk_tck __P((void));
-
-/* declarations for functions defined in lib/sh/clock.c */
-extern void clock_t_to_secs ();
-extern void print_clock_t ();
-
-/* Declarations for functions defined in lib/sh/fmtulong.c */
-#define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
-#define FL_ADDBASE 0x02 /* add base# prefix to converted value */
-#define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
-#define FL_UNSIGNED 0x08 /* don't add any sign */
-
-extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
-
-/* Declarations for functions defined in lib/sh/fmtulong.c */
-#if defined (HAVE_LONG_LONG)
-extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
-#endif
-
-/* Declarations for functions defined in lib/sh/fmtumax.c */
-extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
-
-/* Declarations for functions defined in lib/sh/getcwd.c */
-#if !defined (HAVE_GETCWD)
-extern char *getcwd __P((char *, size_t));
-#endif
-
-/* Declarations for functions defined in lib/sh/itos.c */
-extern char *inttostr __P((intmax_t, char *, size_t));
-extern char *itos __P((intmax_t));
-extern char *uinttostr __P((uintmax_t, char *, size_t));
-extern char *uitos __P((uintmax_t));
-
-/* declarations for functions defined in lib/sh/makepath.c */
-#define MP_DOTILDE 0x01
-#define MP_DOCWD 0x02
-#define MP_RMDOT 0x04
-
-extern char *sh_makepath __P((const char *, const char *, int));
-
-/* declarations for functions defined in lib/sh/netconn.c */
-extern int isnetconn __P((int));
-
-/* declarations for functions defined in lib/sh/netopen.c */
-extern int netopen __P((char *));
-
-/* Declarations for functions defined in lib/sh/oslib.c */
-
-#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
-extern int dup2 __P((int, int));
-#endif
-
-#if !defined (HAVE_GETDTABLESIZE)
-extern int getdtablesize __P((void));
-#endif /* !HAVE_GETDTABLESIZE */
-
-#if !defined (HAVE_GETHOSTNAME)
-extern int gethostname __P((char *, int));
-#endif /* !HAVE_GETHOSTNAME */
-
-extern int getmaxgroups __P((void));
-extern long getmaxchild __P((void));
-
-/* declarations for functions defined in lib/sh/pathcanon.c */
-#define PATH_CHECKDOTDOT 0x0001
-#define PATH_CHECKEXISTS 0x0002
-#define PATH_HARDPATH 0x0004
-#define PATH_NOALLOC 0x0008
-
-extern char *sh_canonpath __P((char *, int));
-
-/* declarations for functions defined in lib/sh/pathphys.c */
-extern char *sh_physpath __P((char *, int));
-extern char *sh_realpath __P((const char *, char *));
-
-/* declarations for functions defined in lib/sh/setlinebuf.c */
-#ifdef NEED_SH_SETLINEBUF_DECL
-extern int sh_setlinebuf __P((FILE *));
-#endif
-
-/* declarations for functions defined in lib/sh/shaccess.c */
-extern int sh_eaccess __P((char *, int));
-
-/* declarations for functions defined in lib/sh/shmatch.c */
-extern int sh_regmatch __P((const char *, const char *, int));
-
-/* defines for flags argument to sh_regmatch. */
-#define SHMAT_SUBEXP 0x001 /* save subexpressions in SH_REMATCH */
-#define SHMAT_PWARN 0x002 /* print a warning message on invalid regexp */
-
-/* declarations for functions defined in lib/sh/shquote.c */
-extern char *sh_single_quote __P((char *));
-extern char *sh_double_quote __P((char *));
-extern char *sh_mkdoublequoted __P((const char *, int, int));
-extern char *sh_un_double_quote __P((char *));
-extern char *sh_backslash_quote __P((char *));
-extern char *sh_backslash_quote_for_double_quotes __P((char *));
-extern int sh_contains_shell_metas __P((char *));
-
-/* declarations for functions defined in lib/sh/spell.c */
-extern int spname __P((char *, char *));
-
-/* declarations for functions defined in lib/sh/strcasecmp.c */
-#if !defined (HAVE_STRCASECMP)
-extern int strncasecmp __P((const char *, const char *, int));
-extern int strcasecmp __P((const char *, const char *));
-#endif /* HAVE_STRCASECMP */
-
-/* declarations for functions defined in lib/sh/strerror.c */
-#if !defined (strerror)
-extern char *strerror __P((int));
-#endif
-
-/* declarations for functions defined in lib/sh/strftime.c */
-#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL)
-extern size_t strftime __P((char *, size_t, const char *, const struct tm *));
-#endif
-
-/* declarations for functions defined in lib/sh/strindex.c */
-extern char *strindex __P((const char *, const char *));
-
-/* declarations for functions and structures defined in lib/sh/stringlist.c */
-
-/* This is a general-purpose argv-style array struct. */
-typedef struct _list_of_strings {
- char **list;
- int list_size;
- int list_len;
-} STRINGLIST;
-
-typedef int sh_strlist_map_func_t __P((char *));
-
-extern STRINGLIST *strlist_create __P((int));
-extern STRINGLIST *strlist_resize __P((STRINGLIST *, int));
-extern void strlist_flush __P((STRINGLIST *));
-extern void strlist_dispose __P((STRINGLIST *));
-extern int strlist_remove __P((STRINGLIST *, char *));
-extern STRINGLIST *strlist_copy __P((STRINGLIST *));
-extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *));
-extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *));
-extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *));
-extern void strlist_print __P((STRINGLIST *, char *));
-extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *));
-extern void strlist_sort __P((STRINGLIST *));
-
-/* declarations for functions defined in lib/sh/stringvec.c */
-
-extern char **strvec_create __P((int));
-extern char **strvec_resize __P((char **, int));
-extern void strvec_flush __P((char **));
-extern void strvec_dispose __P((char **));
-extern int strvec_remove __P((char **, char *));
-extern int strvec_len __P((char **));
-extern int strvec_search __P((char **, char *));
-extern char **strvec_copy __P((char **));
-extern int strvec_strcmp __P((char **, char **));
-extern void strvec_sort __P((char **));
-
-extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
-extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
-
-/* declarations for functions defined in lib/sh/strnlen.c */
-#if !defined (HAVE_STRNLEN)
-extern size_t strnlen __P((const char *, size_t));
-#endif
-
-/* declarations for functions defined in lib/sh/strpbrk.c */
-#if !defined (HAVE_STRPBRK)
-extern char *strpbrk __P((const char *, const char *));
-#endif
-
-/* declarations for functions defined in lib/sh/strtod.c */
-#if !defined (HAVE_STRTOD)
-extern double strtod __P((const char *, char **));
-#endif
-
-/* declarations for functions defined in lib/sh/strtol.c */
-#if !HAVE_DECL_STRTOL
-extern long strtol __P((const char *, char **, int));
-#endif
-
-/* declarations for functions defined in lib/sh/strtoll.c */
-#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOLL
-extern long long strtoll __P((const char *, char **, int));
-#endif
-
-/* declarations for functions defined in lib/sh/strtoul.c */
-#if !HAVE_DECL_STRTOUL
-extern unsigned long strtoul __P((const char *, char **, int));
-#endif
-
-/* declarations for functions defined in lib/sh/strtoull.c */
-#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOULL
-extern unsigned long long strtoull __P((const char *, char **, int));
-#endif
-
-/* declarations for functions defined in lib/sh/strimax.c */
-#if !HAVE_DECL_STRTOIMAX
-extern intmax_t strtoimax __P((const char *, char **, int));
-#endif
-
-/* declarations for functions defined in lib/sh/strumax.c */
-#if !HAVE_DECL_STRTOUMAX
-extern uintmax_t strtoumax __P((const char *, char **, int));
-#endif
-
-/* declarations for functions defined in lib/sh/strtrans.c */
-extern char *ansicstr __P((char *, int, int, int *, int *));
-extern char *ansic_quote __P((char *, int, int *));
-extern int ansic_shouldquote __P((const char *));
-extern char *ansiexpand __P((char *, int, int, int *));
-
-/* declarations for functions defined in lib/sh/timeval.c. No prototypes
- so we don't have to count on having a definition of struct timeval in
- scope when this file is included. */
-extern void timeval_to_secs ();
-extern void print_timeval ();
-
-/* declarations for functions defined in lib/sh/tmpfile.c */
-#define MT_USETMPDIR 0x0001
-#define MT_READWRITE 0x0002
-#define MT_USERANDOM 0x0004
-
-extern char *sh_mktmpname __P((char *, int));
-extern int sh_mktmpfd __P((char *, int, char **));
-/* extern FILE *sh_mktmpfp __P((char *, int, char **)); */
-
-/* declarations for functions defined in lib/sh/winsize.c */
-extern void get_new_window_size __P((int, int *, int *));
-
-/* declarations for functions defined in lib/sh/xstrchr.c */
-#undef xstrchr
-extern char *xstrchr __P((const char *, int));
-
-/* declarations for functions defined in lib/sh/zcatfd.c */
-extern int zcatfd __P((int, int, char *));
-
-/* declarations for functions defined in lib/sh/zread.c */
-extern ssize_t zread __P((int, char *, size_t));
-extern ssize_t zreadintr __P((int, char *, size_t));
-extern ssize_t zreadc __P((int, char *));
-extern void zreset __P((void));
-extern void zsyncfd __P((int));
-
-/* declarations for functions defined in lib/sh/zwrite.c */
-extern int zwrite __P((int, char *, size_t));
-
-#endif /* _EXTERNS_H_ */
diff --git a/general.c~ b/general.c~
deleted file mode 100644
index 20dbd444..00000000
--- a/general.c~
+++ /dev/null
@@ -1,1030 +0,0 @@
-/* general.c -- Stuff that is used by all files. */
-
-/* Copyright (C) 1987-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"
-
-#include "bashtypes.h"
-#ifndef _MINIX
-# include <sys/param.h>
-#endif
-#include "posixstat.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "filecntl.h"
-#include "bashansi.h"
-#include <stdio.h>
-#include "chartypes.h"
-#include <errno.h>
-
-#include "bashintl.h"
-
-#include "shell.h"
-#include "test.h"
-
-#include <tilde/tilde.h>
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-extern int expand_aliases;
-extern int interrupt_immediately;
-extern int interactive_comments;
-extern int check_hashed_filenames;
-extern int source_uses_path;
-extern int source_searches_cwd;
-
-static char *bash_special_tilde_expansions __P((char *));
-static int unquoted_tilde_word __P((const char *));
-static void initialize_group_array __P((void));
-
-/* A standard error message to use when getcwd() returns NULL. */
-char *bash_getcwd_errstr = N_("getcwd: cannot access parent directories");
-
-/* Do whatever is necessary to initialize `Posix mode'. */
-void
-posix_initialize (on)
- int on;
-{
- /* Things that should be turned on when posix mode is enabled. */
- if (on != 0)
- {
- interactive_comments = source_uses_path = expand_aliases = 1;
- }
-
- /* Things that should be turned on when posix mode is disabled. */
- if (on == 0)
- {
- source_searches_cwd = 1;
- expand_aliases = interactive_shell;
- }
-}
-
-/* **************************************************************** */
-/* */
-/* Functions to convert to and from and display non-standard types */
-/* */
-/* **************************************************************** */
-
-#if defined (RLIMTYPE)
-RLIMTYPE
-string_to_rlimtype (s)
- char *s;
-{
- RLIMTYPE ret;
- int neg;
-
- ret = 0;
- neg = 0;
- while (s && *s && whitespace (*s))
- s++;
- if (*s == '-' || *s == '+')
- {
- neg = *s == '-';
- s++;
- }
- for ( ; s && *s && DIGIT (*s); s++)
- ret = (ret * 10) + TODIGIT (*s);
- return (neg ? -ret : ret);
-}
-
-void
-print_rlimtype (n, addnl)
- RLIMTYPE n;
- int addnl;
-{
- char s[INT_STRLEN_BOUND (RLIMTYPE) + 1], *p;
-
- p = s + sizeof(s);
- *--p = '\0';
-
- if (n < 0)
- {
- do
- *--p = '0' - n % 10;
- while ((n /= 10) != 0);
-
- *--p = '-';
- }
- else
- {
- do
- *--p = '0' + n % 10;
- while ((n /= 10) != 0);
- }
-
- printf ("%s%s", p, addnl ? "\n" : "");
-}
-#endif /* RLIMTYPE */
-
-/* **************************************************************** */
-/* */
-/* Input Validation Functions */
-/* */
-/* **************************************************************** */
-
-/* Return non-zero if all of the characters in STRING are digits. */
-int
-all_digits (string)
- char *string;
-{
- register char *s;
-
- for (s = string; *s; s++)
- if (DIGIT (*s) == 0)
- return (0);
-
- return (1);
-}
-
-/* Return non-zero if the characters pointed to by STRING constitute a
- valid number. Stuff the converted number into RESULT if RESULT is
- not null. */
-int
-legal_number (string, result)
- char *string;
- intmax_t *result;
-{
- intmax_t value;
- char *ep;
-
- if (result)
- *result = 0;
-
- errno = 0;
- value = strtoimax (string, &ep, 10);
- if (errno)
- return 0; /* errno is set on overflow or underflow */
-
- /* Skip any trailing whitespace, since strtoimax does not. */
- while (whitespace (*ep))
- ep++;
-
- /* If *string is not '\0' but *ep is '\0' on return, the entire string
- is valid. */
- if (string && *string && *ep == '\0')
- {
- if (result)
- *result = value;
- /* The SunOS4 implementation of strtol() will happily ignore
- overflow conditions, so this cannot do overflow correctly
- on those systems. */
- return 1;
- }
-
- return (0);
-}
-
-/* Return 1 if this token is a legal shell `identifier'; that is, it consists
- solely of letters, digits, and underscores, and does not begin with a
- digit. */
-int
-legal_identifier (name)
- char *name;
-{
- register char *s;
- unsigned char c;
-
- if (!name || !(c = *name) || (legal_variable_starter (c) == 0))
- return (0);
-
- for (s = name + 1; (c = *s) != 0; s++)
- {
- if (legal_variable_char (c) == 0)
- return (0);
- }
- return (1);
-}
-
-/* Make sure that WORD is a valid shell identifier, i.e.
- does not contain a dollar sign, nor is quoted in any way. Nor
- does it consist of all digits. If CHECK_WORD is non-zero,
- the word is checked to ensure that it consists of only letters,
- digits, and underscores. */
-int
-check_identifier (word, check_word)
- WORD_DESC *word;
- int check_word;
-{
- if ((word->flags & (W_HASDOLLAR|W_QUOTED)) || all_digits (word->word))
- {
- internal_error (_("`%s': not a valid identifier"), word->word);
- return (0);
- }
- else if (check_word && legal_identifier (word->word) == 0)
- {
- internal_error (_("`%s': not a valid identifier"), word->word);
- return (0);
- }
- else
- return (1);
-}
-
-/* Return 1 if STRING comprises a valid alias name. The shell accepts
- essentially all characters except those which must be quoted to the
- parser (which disqualifies them from alias expansion anyway) and `/'. */
-int
-legal_alias_name (string, flags)
- char *string;
- int flags;
-{
- register char *s;
-
- for (s = string; *s; s++)
- if (shellbreak (*s) || shellxquote (*s) || shellexp (*s) || (*s == '/'))
- return 0;
- return 1;
-}
-
-/* Returns non-zero if STRING is an assignment statement. The returned value
- is the index of the `=' sign. */
-int
-assignment (string, flags)
- const char *string;
- int flags;
-{
- register unsigned char c;
- register int newi, indx;
-
- c = string[indx = 0];
-
-#if defined (ARRAY_VARS)
- if ((legal_variable_starter (c) == 0) && (flags == 0 || c != '[')) /* ] */
-#else
- if (legal_variable_starter (c) == 0)
-#endif
- return (0);
-
- while (c = string[indx])
- {
- /* The following is safe. Note that '=' at the start of a word
- is not an assignment statement. */
- if (c == '=')
- return (indx);
-
-#if defined (ARRAY_VARS)
- if (c == '[')
- {
- newi = skipsubscript (string, indx);
- if (string[newi++] != ']')
- return (0);
- if (string[newi] == '+' && string[newi+1] == '=')
- return (newi + 1);
- return ((string[newi] == '=') ? newi : 0);
- }
-#endif /* ARRAY_VARS */
-
- /* Check for `+=' */
- if (c == '+' && string[indx+1] == '=')
- return (indx + 1);
-
- /* Variable names in assignment statements may contain only letters,
- digits, and `_'. */
- if (legal_variable_char (c) == 0)
- return (0);
-
- indx++;
- }
- return (0);
-}
-
-/* **************************************************************** */
-/* */
-/* Functions to manage files and file descriptors */
-/* */
-/* **************************************************************** */
-
-/* A function to unset no-delay mode on a file descriptor. Used in shell.c
- to unset it on the fd passed as stdin. Should be called on stdin if
- readline gets an EAGAIN or EWOULDBLOCK when trying to read input. */
-
-#if !defined (O_NDELAY)
-# if defined (FNDELAY)
-# define O_NDELAY FNDELAY
-# endif
-#endif /* O_NDELAY */
-
-/* Make sure no-delay mode is not set on file descriptor FD. */
-int
-sh_unset_nodelay_mode (fd)
- int fd;
-{
- int flags, bflags;
-
- if ((flags = fcntl (fd, F_GETFL, 0)) < 0)
- return -1;
-
- bflags = 0;
-
- /* This is defined to O_NDELAY in filecntl.h if O_NONBLOCK is not present
- and O_NDELAY is defined. */
-#ifdef O_NONBLOCK
- bflags |= O_NONBLOCK;
-#endif
-
-#ifdef O_NDELAY
- bflags |= O_NDELAY;
-#endif
-
- if (flags & bflags)
- {
- flags &= ~bflags;
- return (fcntl (fd, F_SETFL, flags));
- }
-
- return 0;
-}
-
-/* Return 1 if file descriptor FD is valid; 0 otherwise. */
-int
-sh_validfd (fd)
- int fd;
-{
- return (fcntl (fd, F_GETFD, 0) >= 0);
-}
-
-/* There is a bug in the NeXT 2.1 rlogind that causes opens
- of /dev/tty to fail. */
-
-#if defined (__BEOS__)
-/* On BeOS, opening in non-blocking mode exposes a bug in BeOS, so turn it
- into a no-op. This should probably go away in the future. */
-# undef O_NONBLOCK
-# define O_NONBLOCK 0
-#endif /* __BEOS__ */
-
-void
-check_dev_tty ()
-{
- int tty_fd;
- char *tty;
-
- tty_fd = open ("/dev/tty", O_RDWR|O_NONBLOCK);
-
- if (tty_fd < 0)
- {
- tty = (char *)ttyname (fileno (stdin));
- if (tty == 0)
- return;
- tty_fd = open (tty, O_RDWR|O_NONBLOCK);
- }
- close (tty_fd);
-}
-
-/* Return 1 if PATH1 and PATH2 are the same file. This is kind of
- expensive. If non-NULL STP1 and STP2 point to stat structures
- corresponding to PATH1 and PATH2, respectively. */
-int
-same_file (path1, path2, stp1, stp2)
- char *path1, *path2;
- struct stat *stp1, *stp2;
-{
- struct stat st1, st2;
-
- if (stp1 == NULL)
- {
- if (stat (path1, &st1) != 0)
- return (0);
- stp1 = &st1;
- }
-
- if (stp2 == NULL)
- {
- if (stat (path2, &st2) != 0)
- return (0);
- stp2 = &st2;
- }
-
- return ((stp1->st_dev == stp2->st_dev) && (stp1->st_ino == stp2->st_ino));
-}
-
-/* Move FD to a number close to the maximum number of file descriptors
- allowed in the shell process, to avoid the user stepping on it with
- redirection and causing us extra work. If CHECK_NEW is non-zero,
- we check whether or not the file descriptors are in use before
- duplicating FD onto them. MAXFD says where to start checking the
- file descriptors. If it's less than 20, we get the maximum value
- available from getdtablesize(2). */
-int
-move_to_high_fd (fd, check_new, maxfd)
- int fd, check_new, maxfd;
-{
- int script_fd, nfds, ignore;
-
- if (maxfd < 20)
- {
- nfds = getdtablesize ();
- if (nfds <= 0)
- nfds = 20;
- if (nfds > HIGH_FD_MAX)
- nfds = HIGH_FD_MAX; /* reasonable maximum */
- }
- else
- nfds = maxfd;
-
- for (nfds--; check_new && nfds > 3; nfds--)
- if (fcntl (nfds, F_GETFD, &ignore) == -1)
- break;
-
- if (nfds > 3 && fd != nfds && (script_fd = dup2 (fd, nfds)) != -1)
- {
- if (check_new == 0 || fd != fileno (stderr)) /* don't close stderr */
- close (fd);
- return (script_fd);
- }
-
- /* OK, we didn't find one less than our artificial maximum; return the
- original file descriptor. */
- return (fd);
-}
-
-/* Return non-zero if the characters from SAMPLE are not all valid
- characters to be found in the first line of a shell script. We
- check up to the first newline, or SAMPLE_LEN, whichever comes first.
- All of the characters must be printable or whitespace. */
-
-int
-check_binary_file (sample, sample_len)
- char *sample;
- int sample_len;
-{
- register int i;
- unsigned char c;
-
- for (i = 0; i < sample_len; i++)
- {
- c = sample[i];
- if (c == '\n')
- return (0);
-
-#if 0
- if (ISSPACE (c) == 0 && ISPRINT (c) == 0)
-#else
- if (c == '\0')
-#endif
- return (1);
-
- }
-
- return (0);
-}
-
-/* **************************************************************** */
-/* */
-/* Functions to inspect pathnames */
-/* */
-/* **************************************************************** */
-
-int
-file_isdir (fn)
- char *fn;
-{
- struct stat sb;
-
- return ((stat (fn, &sb) == 0) && S_ISDIR (sb.st_mode));
-}
-
-int
-file_iswdir (fn)
- char *fn;
-{
- return (file_isdir (fn) && sh_eaccess (fn, W_OK) == 0);
-}
-
-/* Return 1 if STRING contains an absolute pathname, else 0. Used by `cd'
- to decide whether or not to look up a directory name in $CDPATH. */
-int
-absolute_pathname (string)
- const char *string;
-{
- if (string == 0 || *string == '\0')
- return (0);
-
- if (ABSPATH(string))
- return (1);
-
- if (string[0] == '.' && PATHSEP(string[1])) /* . and ./ */
- return (1);
-
- if (string[0] == '.' && string[1] == '.' && PATHSEP(string[2])) /* .. and ../ */
- return (1);
-
- return (0);
-}
-
-/* Return 1 if STRING is an absolute program name; it is absolute if it
- contains any slashes. This is used to decide whether or not to look
- up through $PATH. */
-int
-absolute_program (string)
- const char *string;
-{
- return ((char *)xstrchr (string, '/') != (char *)NULL);
-}
-
-/* **************************************************************** */
-/* */
-/* Functions to manipulate pathnames */
-/* */
-/* **************************************************************** */
-
-/* Turn STRING (a pathname) into an absolute pathname, assuming that
- DOT_PATH contains the symbolic location of `.'. This always
- returns a new string, even if STRING was an absolute pathname to
- begin with. */
-char *
-make_absolute (string, dot_path)
- char *string, *dot_path;
-{
- char *result;
-
- if (dot_path == 0 || ABSPATH(string))
-#ifdef __CYGWIN__
- {
- char pathbuf[PATH_MAX + 1];
-
- cygwin_conv_to_full_posix_path (string, pathbuf);
- result = savestring (pathbuf);
- }
-#else
- result = savestring (string);
-#endif
- else
- result = sh_makepath (dot_path, string, 0);
-
- return (result);
-}
-
-/* Return the `basename' of the pathname in STRING (the stuff after the
- last '/'). If STRING is `/', just return it. */
-char *
-base_pathname (string)
- char *string;
-{
- char *p;
-
-#if 0
- if (absolute_pathname (string) == 0)
- return (string);
-#endif
-
- if (string[0] == '/' && string[1] == 0)
- return (string);
-
- p = (char *)strrchr (string, '/');
- return (p ? ++p : string);
-}
-
-/* Return the full pathname of FILE. Easy. Filenames that begin
- with a '/' are returned as themselves. Other filenames have
- the current working directory prepended. A new string is
- returned in either case. */
-char *
-full_pathname (file)
- char *file;
-{
- char *ret;
-
- file = (*file == '~') ? bash_tilde_expand (file, 0) : savestring (file);
-
- if (ABSPATH(file))
- return (file);
-
- ret = sh_makepath ((char *)NULL, file, (MP_DOCWD|MP_RMDOT));
- free (file);
-
- return (ret);
-}
-
-/* A slightly related function. Get the prettiest name of this
- directory possible. */
-static char tdir[PATH_MAX];
-
-/* Return a pretty pathname. If the first part of the pathname is
- the same as $HOME, then replace that with `~'. */
-char *
-polite_directory_format (name)
- char *name;
-{
- char *home;
- int l;
-
- home = get_string_value ("HOME");
- l = home ? strlen (home) : 0;
- if (l > 1 && strncmp (home, name, l) == 0 && (!name[l] || name[l] == '/'))
- {
- strncpy (tdir + 1, name + l, sizeof(tdir) - 2);
- tdir[0] = '~';
- tdir[sizeof(tdir) - 1] = '\0';
- return (tdir);
- }
- else
- return (name);
-}
-
-/* Given a string containing units of information separated by colons,
- return the next one pointed to by (P_INDEX), or NULL if there are no more.
- Advance (P_INDEX) to the character after the colon. */
-char *
-extract_colon_unit (string, p_index)
- char *string;
- int *p_index;
-{
- int i, start, len;
- char *value;
-
- if (string == 0)
- return (string);
-
- len = strlen (string);
- if (*p_index >= len)
- return ((char *)NULL);
-
- i = *p_index;
-
- /* Each call to this routine leaves the index pointing at a colon if
- there is more to the path. If I is > 0, then increment past the
- `:'. If I is 0, then the path has a leading colon. Trailing colons
- are handled OK by the `else' part of the if statement; an empty
- string is returned in that case. */
- if (i && string[i] == ':')
- i++;
-
- for (start = i; string[i] && string[i] != ':'; i++)
- ;
-
- *p_index = i;
-
- if (i == start)
- {
- if (string[i])
- (*p_index)++;
- /* Return "" in the case of a trailing `:'. */
- value = (char *)xmalloc (1);
- value[0] = '\0';
- }
- else
- value = substring (string, start, i);
-
- return (value);
-}
-
-/* **************************************************************** */
-/* */
-/* Tilde Initialization and Expansion */
-/* */
-/* **************************************************************** */
-
-#if defined (PUSHD_AND_POPD)
-extern char *get_dirstack_from_string __P((char *));
-#endif
-
-static char **bash_tilde_prefixes;
-static char **bash_tilde_prefixes2;
-static char **bash_tilde_suffixes;
-static char **bash_tilde_suffixes2;
-
-/* If tilde_expand hasn't been able to expand the text, perhaps it
- is a special shell expansion. This function is installed as the
- tilde_expansion_preexpansion_hook. It knows how to expand ~- and ~+.
- If PUSHD_AND_POPD is defined, ~[+-]N expands to directories from the
- directory stack. */
-static char *
-bash_special_tilde_expansions (text)
- char *text;
-{
- char *result;
-
- result = (char *)NULL;
-
- if (text[0] == '+' && text[1] == '\0')
- result = get_string_value ("PWD");
- else if (text[0] == '-' && text[1] == '\0')
- result = get_string_value ("OLDPWD");
-#if defined (PUSHD_AND_POPD)
- else if (DIGIT (*text) || ((*text == '+' || *text == '-') && DIGIT (text[1])))
- result = get_dirstack_from_string (text);
-#endif
-
- return (result ? savestring (result) : (char *)NULL);
-}
-
-/* Initialize the tilde expander. In Bash, we handle `~-' and `~+', as
- well as handling special tilde prefixes; `:~" and `=~' are indications
- that we should do tilde expansion. */
-void
-tilde_initialize ()
-{
- static int times_called = 0;
-
- /* Tell the tilde expander that we want a crack first. */
- tilde_expansion_preexpansion_hook = bash_special_tilde_expansions;
-
- /* Tell the tilde expander about special strings which start a tilde
- expansion, and the special strings that end one. Only do this once.
- tilde_initialize () is called from within bashline_reinitialize (). */
- if (times_called++ == 0)
- {
- bash_tilde_prefixes = strvec_create (3);
- bash_tilde_prefixes[0] = "=~";
- bash_tilde_prefixes[1] = ":~";
- bash_tilde_prefixes[2] = (char *)NULL;
-
- bash_tilde_prefixes2 = strvec_create (2);
- bash_tilde_prefixes2[0] = ":~";
- bash_tilde_prefixes2[1] = (char *)NULL;
-
- tilde_additional_prefixes = bash_tilde_prefixes;
-
- bash_tilde_suffixes = strvec_create (3);
- bash_tilde_suffixes[0] = ":";
- bash_tilde_suffixes[1] = "=~"; /* XXX - ?? */
- bash_tilde_suffixes[2] = (char *)NULL;
-
- tilde_additional_suffixes = bash_tilde_suffixes;
-
- bash_tilde_suffixes2 = strvec_create (2);
- bash_tilde_suffixes2[0] = ":";
- bash_tilde_suffixes2[1] = (char *)NULL;
- }
-}
-
-/* POSIX.2, 3.6.1: A tilde-prefix consists of an unquoted tilde character
- at the beginning of the word, followed by all of the characters preceding
- the first unquoted slash in the word, or all the characters in the word
- if there is no slash...If none of the characters in the tilde-prefix are
- quoted, the characters in the tilde-prefix following the tilde shell be
- treated as a possible login name. */
-
-#define TILDE_END(c) ((c) == '\0' || (c) == '/' || (c) == ':')
-
-static int
-unquoted_tilde_word (s)
- const char *s;
-{
- const char *r;
-
- for (r = s; TILDE_END(*r) == 0; r++)
- {
- switch (*r)
- {
- case '\\':
- case '\'':
- case '"':
- return 0;
- }
- }
- return 1;
-}
-
-/* Find the end of the tilde-prefix starting at S, and return the tilde
- prefix in newly-allocated memory. Return the length of the string in
- *LENP. FLAGS tells whether or not we're in an assignment context --
- if so, `:' delimits the end of the tilde prefix as well. */
-char *
-bash_tilde_find_word (s, flags, lenp)
- const char *s;
- int flags, *lenp;
-{
- const char *r;
- char *ret;
- int l;
-
- for (r = s; *r && *r != '/'; r++)
- {
- /* Short-circuit immediately if we see a quote character. Even though
- POSIX says that `the first unquoted slash' (or `:') terminates the
- tilde-prefix, in practice, any quoted portion of the tilde prefix
- will cause it to not be expanded. */
- if (*r == '\\' || *r == '\'' || *r == '"')
- {
- ret = savestring (s);
- if (lenp)
- *lenp = 0;
- return ret;
- }
- else if (flags && *r == ':')
- break;
- }
- l = r - s;
- ret = xmalloc (l + 1);
- strncpy (ret, s, l);
- ret[l] = '\0';
- if (lenp)
- *lenp = l;
- return ret;
-}
-
-/* Tilde-expand S by running it through the tilde expansion library.
- ASSIGN_P is 1 if this is a variable assignment, so the alternate
- tilde prefixes should be enabled (`=~' and `:~', see above). If
- ASSIGN_P is 2, we are expanding the rhs of an assignment statement,
- so `=~' is not valid. */
-char *
-bash_tilde_expand (s, assign_p)
- const char *s;
- int assign_p;
-{
- int old_immed, r;
- char *ret;
-
- old_immed = interrupt_immediately;
- interrupt_immediately = 1;
-
- tilde_additional_prefixes = assign_p == 0 ? (char **)0
- : (assign_p == 2 ? bash_tilde_prefixes2 : bash_tilde_prefixes);
- if (assign_p == 2)
- tilde_additional_suffixes = bash_tilde_suffixes2;
-
- r = (*s == '~') ? unquoted_tilde_word (s) : 1;
- ret = r ? tilde_expand (s) : savestring (s);
- interrupt_immediately = old_immed;
- return (ret);
-}
-
-/* **************************************************************** */
-/* */
-/* Functions to manipulate and search the group list */
-/* */
-/* **************************************************************** */
-
-static int ngroups, maxgroups;
-
-/* The set of groups that this user is a member of. */
-static GETGROUPS_T *group_array = (GETGROUPS_T *)NULL;
-
-#if !defined (NOGROUP)
-# define NOGROUP (gid_t) -1
-#endif
-
-static void
-initialize_group_array ()
-{
- register int i;
-
- if (maxgroups == 0)
- maxgroups = getmaxgroups ();
-
- ngroups = 0;
- group_array = (GETGROUPS_T *)xrealloc (group_array, maxgroups * sizeof (GETGROUPS_T));
-
-#if defined (HAVE_GETGROUPS)
- ngroups = getgroups (maxgroups, group_array);
-#endif
-
- /* If getgroups returns nothing, or the OS does not support getgroups(),
- make sure the groups array includes at least the current gid. */
- if (ngroups == 0)
- {
- group_array[0] = current_user.gid;
- ngroups = 1;
- }
-
- /* If the primary group is not in the groups array, add it as group_array[0]
- and shuffle everything else up 1, if there's room. */
- for (i = 0; i < ngroups; i++)
- if (current_user.gid == (gid_t)group_array[i])
- break;
- if (i == ngroups && ngroups < maxgroups)
- {
- for (i = ngroups; i > 0; i--)
- group_array[i] = group_array[i - 1];
- group_array[0] = current_user.gid;
- ngroups++;
- }
-
- /* If the primary group is not group_array[0], swap group_array[0] and
- whatever the current group is. The vast majority of systems should
- not need this; a notable exception is Linux. */
- if (group_array[0] != current_user.gid)
- {
- for (i = 0; i < ngroups; i++)
- if (group_array[i] == current_user.gid)
- break;
- if (i < ngroups)
- {
- group_array[i] = group_array[0];
- group_array[0] = current_user.gid;
- }
- }
-}
-
-/* Return non-zero if GID is one that we have in our groups list. */
-int
-#if defined (__STDC__) || defined ( _MINIX)
-group_member (gid_t gid)
-#else
-group_member (gid)
- gid_t gid;
-#endif /* !__STDC__ && !_MINIX */
-{
-#if defined (HAVE_GETGROUPS)
- register int i;
-#endif
-
- /* Short-circuit if possible, maybe saving a call to getgroups(). */
- if (gid == current_user.gid || gid == current_user.egid)
- return (1);
-
-#if defined (HAVE_GETGROUPS)
- if (ngroups == 0)
- initialize_group_array ();
-
- /* In case of error, the user loses. */
- if (ngroups <= 0)
- return (0);
-
- /* Search through the list looking for GID. */
- for (i = 0; i < ngroups; i++)
- if (gid == (gid_t)group_array[i])
- return (1);
-#endif
-
- return (0);
-}
-
-char **
-get_group_list (ngp)
- int *ngp;
-{
- static char **group_vector = (char **)NULL;
- register int i;
-
- if (group_vector)
- {
- if (ngp)
- *ngp = ngroups;
- return group_vector;
- }
-
- if (ngroups == 0)
- initialize_group_array ();
-
- if (ngroups <= 0)
- {
- if (ngp)
- *ngp = 0;
- return (char **)NULL;
- }
-
- group_vector = strvec_create (ngroups);
- for (i = 0; i < ngroups; i++)
- group_vector[i] = itos (group_array[i]);
-
- if (ngp)
- *ngp = ngroups;
- return group_vector;
-}
-
-int *
-get_group_array (ngp)
- int *ngp;
-{
- int i;
- static int *group_iarray = (int *)NULL;
-
- if (group_iarray)
- {
- if (ngp)
- *ngp = ngroups;
- return (group_iarray);
- }
-
- if (ngroups == 0)
- initialize_group_array ();
-
- if (ngroups <= 0)
- {
- if (ngp)
- *ngp = 0;
- return (int *)NULL;
- }
-
- group_iarray = (int *)xmalloc (ngroups * sizeof (int));
- for (i = 0; i < ngroups; i++)
- group_iarray[i] = (int)group_array[i];
-
- if (ngp)
- *ngp = ngroups;
- return group_iarray;
-}
diff --git a/include/memalloc.h.save b/include/memalloc.h.save
deleted file mode 100644
index a1a27069..00000000
--- a/include/memalloc.h.save
+++ /dev/null
@@ -1,58 +0,0 @@
-/* memalloc.h -- consolidate code for including alloca.h or malloc.h and
- defining alloca. */
-
-/* Copyright (C) 1993 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 (_MEMALLOC_H_)
-# define _MEMALLOC_H_
-
-#if defined (sparc) && defined (sun) && !defined (HAVE_ALLOCA_H)
-# define HAVE_ALLOCA_H
-#endif
-
-#if defined (__GNUC__) && !defined (HAVE_ALLOCA)
-# define HAVE_ALLOCA
-#endif
-
-#if defined (HAVE_ALLOCA_H) && !defined (HAVE_ALLOCA)
-# define HAVE_ALLOCA
-#endif /* HAVE_ALLOCA_H && !HAVE_ALLOCA */
-
-#if defined (__GNUC__) && !defined (C_ALLOCA)
-# undef alloca
-# define alloca __builtin_alloca
-#else /* !__GNUC__ || C_ALLOCA */
-# if defined (HAVE_ALLOCA_H) && !defined (C_ALLOCA)
-# if defined (IBMESA)
-# include <malloc.h>
-# else /* !IBMESA */
-# include <alloca.h>
-# endif /* !IBMESA */
-# else /* !HAVE_ALLOCA_H || C_ALLOCA */
-# if defined (__hpux) && defined (__STDC__) && !defined (alloca)
-extern void *alloca ();
-# else
-# if !defined (alloca)
-extern char *alloca ();
-# endif /* !alloca */
-# endif /* !__hpux || !__STDC__ && !alloca */
-# endif /* !HAVE_ALLOCA_H || C_ALLOCA */
-#endif /* !__GNUC__ || C_ALLOCA */
-
-#endif /* _MEMALLOC_H_ */
diff --git a/input.c~ b/input.c~
deleted file mode 100644
index f6af14c2..00000000
--- a/input.c~
+++ /dev/null
@@ -1,625 +0,0 @@
-/* input.c -- functions to perform buffered input with synchronization. */
-
-/* Copyright (C) 1992 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"
-#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-#include "filecntl.h"
-#include "posixstat.h"
-#include <stdio.h>
-#include <errno.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include "command.h"
-#include "general.h"
-#include "input.h"
-#include "error.h"
-#include "externs.h"
-#include "quit.h"
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-/* Functions to handle reading input on systems that don't restart read(2)
- if a signal is received. */
-
-static char localbuf[128];
-static int local_index = 0, local_bufused = 0;
-
-/* Posix and USG systems do not guarantee to restart read () if it is
- interrupted by a signal. We do the read ourselves, and restart it
- if it returns EINTR. */
-int
-getc_with_restart (stream)
- FILE *stream;
-{
- unsigned char uc;
-
- CHECK_TERMSIG;
-
- /* Try local buffering to reduce the number of read(2) calls. */
- if (local_index == local_bufused || local_bufused == 0)
- {
- while (1)
- {
- CHECK_TERMSIG;
- local_bufused = read (fileno (stream), localbuf, sizeof(localbuf));
- if (local_bufused > 0)
- break;
- else if (local_bufused == 0 || errno != EINTR)
- {
- local_index = 0;
- return EOF;
- }
- }
- local_index = 0;
- }
- uc = localbuf[local_index++];
- return uc;
-}
-
-int
-ungetc_with_restart (c, stream)
- int c;
- FILE *stream;
-{
- if (local_index == 0 || c == EOF)
- return EOF;
- localbuf[--local_index] = c;
- return c;
-}
-
-#if defined (BUFFERED_INPUT)
-
-/* A facility similar to stdio, but input-only. */
-
-#if defined (USING_BASH_MALLOC)
-# define MAX_INPUT_BUFFER_SIZE 8176
-#else
-# define MAX_INPUT_BUFFER_SIZE 8192
-#endif
-
-#if !defined (SEEK_CUR)
-# define SEEK_CUR 1
-#endif /* !SEEK_CUR */
-
-#ifdef max
-# undef max
-#endif
-#define max(a, b) (((a) > (b)) ? (a) : (b))
-#ifdef min
-# undef min
-#endif
-#define min(a, b) ((a) > (b) ? (b) : (a))
-
-extern int interactive_shell;
-
-int bash_input_fd_changed;
-
-/* This provides a way to map from a file descriptor to the buffer
- associated with that file descriptor, rather than just the other
- way around. This is needed so that buffers are managed properly
- in constructs like 3<&4. buffers[x]->b_fd == x -- that is how the
- correspondence is maintained. */
-static BUFFERED_STREAM **buffers = (BUFFERED_STREAM **)NULL;
-static int nbuffers;
-
-#define ALLOCATE_BUFFERS(n) \
- do { if ((n) >= nbuffers) allocate_buffers (n); } while (0)
-
-/* Make sure `buffers' has at least N elements. */
-static void
-allocate_buffers (n)
- int n;
-{
- register int i, orig_nbuffers;
-
- orig_nbuffers = nbuffers;
- nbuffers = n + 20;
- buffers = (BUFFERED_STREAM **)xrealloc
- (buffers, nbuffers * sizeof (BUFFERED_STREAM *));
-
- /* Zero out the new buffers. */
- for (i = orig_nbuffers; i < nbuffers; i++)
- buffers[i] = (BUFFERED_STREAM *)NULL;
-}
-
-/* Construct and return a BUFFERED_STREAM corresponding to file descriptor
- FD, using BUFFER. */
-static BUFFERED_STREAM *
-make_buffered_stream (fd, buffer, bufsize)
- int fd;
- char *buffer;
- size_t bufsize;
-{
- BUFFERED_STREAM *bp;
-
- bp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
- ALLOCATE_BUFFERS (fd);
- buffers[fd] = bp;
- bp->b_fd = fd;
- bp->b_buffer = buffer;
- bp->b_size = bufsize;
- bp->b_used = bp->b_inputp = bp->b_flag = 0;
- if (bufsize == 1)
- bp->b_flag |= B_UNBUFF;
- return (bp);
-}
-
-/* Allocate a new BUFFERED_STREAM, copy BP to it, and return the new copy. */
-static BUFFERED_STREAM *
-copy_buffered_stream (bp)
- BUFFERED_STREAM *bp;
-{
- BUFFERED_STREAM *nbp;
-
- if (!bp)
- return ((BUFFERED_STREAM *)NULL);
-
- nbp = (BUFFERED_STREAM *)xmalloc (sizeof (BUFFERED_STREAM));
- xbcopy ((char *)bp, (char *)nbp, sizeof (BUFFERED_STREAM));
- return (nbp);
-}
-
-int
-set_bash_input_fd (fd)
- int fd;
-{
- if (bash_input.type == st_bstream)
- bash_input.location.buffered_fd = fd;
- else if (interactive_shell == 0)
- default_buffered_input = fd;
- return 0;
-}
-
-int
-fd_is_bash_input (fd)
- int fd;
-{
- if (bash_input.type == st_bstream && bash_input.location.buffered_fd == fd)
- return 1;
- else if (interactive_shell == 0 && default_buffered_input == fd)
- return 1;
- return 0;
-}
-
-/* Save the buffered stream corresponding to file descriptor FD (which bash
- is using to read input) to a buffered stream associated with NEW_FD. If
- NEW_FD is -1, a new file descriptor is allocated with fcntl. The new
- file descriptor is returned on success, -1 on error. */
-int
-save_bash_input (fd, new_fd)
- int fd, new_fd;
-{
- int nfd;
-
- /* Sync the stream so we can re-read from the new file descriptor. We
- might be able to avoid this by copying the buffered stream verbatim
- to the new file descriptor. */
- if (buffers[fd])
- sync_buffered_stream (fd);
-
- /* Now take care of duplicating the file descriptor that bash is
- using for input, so we can reinitialize it later. */
- nfd = (new_fd == -1) ? fcntl (fd, F_DUPFD, 10) : new_fd;
- if (nfd == -1)
- {
- if (fcntl (fd, F_GETFD, 0) == 0)
- sys_error (_("cannot allocate new file descriptor for bash input from fd %d"), fd);
- return -1;
- }
-
- if (buffers[nfd])
- {
- /* What's this? A stray buffer without an associated open file
- descriptor? Free up the buffer and report the error. */
- internal_error (_("save_bash_input: buffer already exists for new fd %d"), nfd);
- free_buffered_stream (buffers[nfd]);
- }
-
- /* Reinitialize bash_input.location. */
- if (bash_input.type == st_bstream)
- {
- bash_input.location.buffered_fd = nfd;
- fd_to_buffered_stream (nfd);
- close_buffered_fd (fd); /* XXX */
- }
- else
- /* If the current input type is not a buffered stream, but the shell
- is not interactive and therefore using a buffered stream to read
- input (e.g. with an `eval exec 3>output' inside a script), note
- that the input fd has been changed. pop_stream() looks at this
- value and adjusts the input fd to the new value of
- default_buffered_input accordingly. */
- bash_input_fd_changed++;
-
- if (default_buffered_input == fd)
- default_buffered_input = nfd;
-
- SET_CLOSE_ON_EXEC (nfd);
- return nfd;
-}
-
-/* Check that file descriptor FD is not the one that bash is currently
- using to read input from a script. FD is about to be duplicated onto,
- which means that the kernel will close it for us. If FD is the bash
- input file descriptor, we need to seek backwards in the script (if
- possible and necessary -- scripts read from stdin are still unbuffered),
- allocate a new file descriptor to use for bash input, and re-initialize
- the buffered stream. Make sure the file descriptor used to save bash
- input is set close-on-exec. Returns 0 on success, -1 on failure. This
- works only if fd is > 0 -- if fd == 0 and bash is reading input from
- fd 0, save_bash_input is used instead, to cooperate with input
- redirection (look at redir.c:add_undo_redirect()). */
-int
-check_bash_input (fd)
- int fd;
-{
- if (fd_is_bash_input (fd))
- {
- if (fd > 0)
- return ((save_bash_input (fd, -1) == -1) ? -1 : 0);
- else if (fd == 0)
- return ((sync_buffered_stream (fd) == -1) ? -1 : 0);
- }
- return 0;
-}
-
-/* This is the buffered stream analogue of dup2(fd1, fd2). The
- BUFFERED_STREAM corresponding to fd2 is deallocated, if one exists.
- BUFFERS[fd1] is copied to BUFFERS[fd2]. This is called by the
- redirect code for constructs like 4<&0 and 3</etc/rc.local. */
-int
-duplicate_buffered_stream (fd1, fd2)
- int fd1, fd2;
-{
- int is_bash_input, m;
-
- if (fd1 == fd2)
- return 0;
-
- m = max (fd1, fd2);
- ALLOCATE_BUFFERS (m);
-
- /* If FD2 is the file descriptor bash is currently using for shell input,
- we need to do some extra work to make sure that the buffered stream
- actually exists (it might not if fd1 was not active, and the copy
- didn't actually do anything). */
- is_bash_input = (bash_input.type == st_bstream) &&
- (bash_input.location.buffered_fd == fd2);
-
- if (buffers[fd2])
- {
- /* If the two objects share the same b_buffer, don't free it. */
- if (buffers[fd1] && buffers[fd1]->b_buffer && buffers[fd1]->b_buffer == buffers[fd2]->b_buffer)
- buffers[fd2] = (BUFFERED_STREAM *)NULL;
- else
- free_buffered_stream (buffers[fd2]);
- }
- buffers[fd2] = copy_buffered_stream (buffers[fd1]);
- if (buffers[fd2])
- buffers[fd2]->b_fd = fd2;
-
- if (is_bash_input)
- {
- if (!buffers[fd2])
- fd_to_buffered_stream (fd2);
- buffers[fd2]->b_flag |= B_WASBASHINPUT;
- }
-
- return (fd2);
-}
-
-/* Return 1 if a seek on FD will succeed. */
-#ifndef __CYGWIN__
-# define fd_is_seekable(fd) (lseek ((fd), 0L, SEEK_CUR) >= 0)
-#else
-# define fd_is_seekable(fd) 0
-#endif /* __CYGWIN__ */
-
-/* Take FD, a file descriptor, and create and return a buffered stream
- corresponding to it. If something is wrong and the file descriptor
- is invalid, return a NULL stream. */
-BUFFERED_STREAM *
-fd_to_buffered_stream (fd)
- int fd;
-{
- char *buffer;
- size_t size;
- struct stat sb;
-
- if (fstat (fd, &sb) < 0)
- {
- close (fd);
- return ((BUFFERED_STREAM *)NULL);
- }
-
- size = (fd_is_seekable (fd)) ? min (sb.st_size, MAX_INPUT_BUFFER_SIZE) : 1;
- if (size == 0)
- size = 1;
- buffer = (char *)xmalloc (size);
-
- return (make_buffered_stream (fd, buffer, size));
-}
-
-/* Return a buffered stream corresponding to FILE, a file name. */
-BUFFERED_STREAM *
-open_buffered_stream (file)
- char *file;
-{
- int fd;
-
- fd = open (file, O_RDONLY);
- return ((fd >= 0) ? fd_to_buffered_stream (fd) : (BUFFERED_STREAM *)NULL);
-}
-
-/* Deallocate a buffered stream and free up its resources. Make sure we
- zero out the slot in BUFFERS that points to BP. */
-void
-free_buffered_stream (bp)
- BUFFERED_STREAM *bp;
-{
- int n;
-
- if (!bp)
- return;
-
- n = bp->b_fd;
- if (bp->b_buffer)
- free (bp->b_buffer);
- free (bp);
- buffers[n] = (BUFFERED_STREAM *)NULL;
-}
-
-/* Close the file descriptor associated with BP, a buffered stream, and free
- up the stream. Return the status of closing BP's file descriptor. */
-int
-close_buffered_stream (bp)
- BUFFERED_STREAM *bp;
-{
- int fd;
-
- if (!bp)
- return (0);
- fd = bp->b_fd;
- free_buffered_stream (bp);
- return (close (fd));
-}
-
-/* Deallocate the buffered stream associated with file descriptor FD, and
- close FD. Return the status of the close on FD. */
-int
-close_buffered_fd (fd)
- int fd;
-{
- if (fd < 0)
- {
- errno = EBADF;
- return -1;
- }
- if (fd >= nbuffers || !buffers || !buffers[fd])
- return (close (fd));
- return (close_buffered_stream (buffers[fd]));
-}
-
-/* Make the BUFFERED_STREAM associcated with buffers[FD] be BP, and return
- the old BUFFERED_STREAM. */
-BUFFERED_STREAM *
-set_buffered_stream (fd, bp)
- int fd;
- BUFFERED_STREAM *bp;
-{
- BUFFERED_STREAM *ret;
-
- ret = buffers[fd];
- buffers[fd] = bp;
- return ret;
-}
-
-/* Read a buffer full of characters from BP, a buffered stream. */
-static int
-b_fill_buffer (bp)
- BUFFERED_STREAM *bp;
-{
- ssize_t nr;
-
- CHECK_TERMSIG;
- nr = zread (bp->b_fd, bp->b_buffer, bp->b_size);
- if (nr <= 0)
- {
- bp->b_used = 0;
- bp->b_buffer[0] = 0;
- if (nr == 0)
- bp->b_flag |= B_EOF;
- else
- bp->b_flag |= B_ERROR;
- return (EOF);
- }
-
-#if defined (__CYGWIN__)
- /* If on cygwin, translate \r\n to \n. */
- if (nr >= 2 && bp->b_buffer[nr - 2] == '\r' && bp->b_buffer[nr - 1] == '\n')
- {
- bp->b_buffer[nr - 2] = '\n';
- nr--;
- }
-#endif
-
- bp->b_used = nr;
- bp->b_inputp = 0;
- return (bp->b_buffer[bp->b_inputp++] & 0xFF);
-}
-
-/* Get a character from buffered stream BP. */
-#define bufstream_getc(bp) \
- (bp->b_inputp == bp->b_used || !bp->b_used) \
- ? b_fill_buffer (bp) \
- : bp->b_buffer[bp->b_inputp++] & 0xFF
-
-/* Push C back onto buffered stream BP. */
-static int
-bufstream_ungetc(c, bp)
- int c;
- BUFFERED_STREAM *bp;
-{
- if (c == EOF || bp->b_inputp == 0)
- return (EOF);
-
- bp->b_buffer[--bp->b_inputp] = c;
- return (c);
-}
-
-/* Seek backwards on file BFD to synchronize what we've read so far
- with the underlying file pointer. */
-int
-sync_buffered_stream (bfd)
- int bfd;
-{
- BUFFERED_STREAM *bp;
- off_t chars_left;
-
- if (buffers == 0 || (bp = buffers[bfd]) == 0)
- return (-1);
-
- chars_left = bp->b_used - bp->b_inputp;
- if (chars_left)
- lseek (bp->b_fd, -chars_left, SEEK_CUR);
- bp->b_used = bp->b_inputp = 0;
- return (0);
-}
-
-int
-buffered_getchar ()
-{
- CHECK_TERMSIG;
-
-#if !defined (DJGPP)
- return (bufstream_getc (buffers[bash_input.location.buffered_fd]));
-#else
- /* On DJGPP, ignore \r. */
- int ch;
- while ((ch = bufstream_getc (buffers[bash_input.location.buffered_fd])) == '\r')
- ;
- return ch;
-#endif
-}
-
-int
-buffered_ungetchar (c)
- int c;
-{
- return (bufstream_ungetc (c, buffers[bash_input.location.buffered_fd]));
-}
-
-/* Make input come from file descriptor BFD through a buffered stream. */
-void
-with_input_from_buffered_stream (bfd, name)
- int bfd;
- char *name;
-{
- INPUT_STREAM location;
- BUFFERED_STREAM *bp;
-
- location.buffered_fd = bfd;
- /* Make sure the buffered stream exists. */
- bp = fd_to_buffered_stream (bfd);
- init_yy_io (bp == 0 ? return_EOF : buffered_getchar,
- buffered_ungetchar, st_bstream, name, location);
-}
-
-#if defined (TEST)
-void *
-xmalloc(s)
-int s;
-{
- return (malloc (s));
-}
-
-void *
-xrealloc(s, size)
-char *s;
-int size;
-{
- if (!s)
- return(malloc (size));
- else
- return(realloc (s, size));
-}
-
-void
-init_yy_io ()
-{
-}
-
-process(bp)
-BUFFERED_STREAM *bp;
-{
- int c;
-
- while ((c = bufstream_getc(bp)) != EOF)
- putchar(c);
-}
-
-BASH_INPUT bash_input;
-
-struct stat dsb; /* can be used from gdb */
-
-/* imitate /bin/cat */
-main(argc, argv)
-int argc;
-char **argv;
-{
- register int i;
- BUFFERED_STREAM *bp;
-
- if (argc == 1) {
- bp = fd_to_buffered_stream (0);
- process(bp);
- exit(0);
- }
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-' && argv[i][1] == '\0') {
- bp = fd_to_buffered_stream (0);
- if (!bp)
- continue;
- process(bp);
- free_buffered_stream (bp);
- } else {
- bp = open_buffered_stream (argv[i]);
- if (!bp)
- continue;
- process(bp);
- close_buffered_stream (bp);
- }
- }
- exit(0);
-}
-#endif /* TEST */
-#endif /* BUFFERED_INPUT */
diff --git a/jobs.c.diff b/jobs.c.diff
deleted file mode 100644
index f1ea4e0c..00000000
--- a/jobs.c.diff
+++ /dev/null
@@ -1,521 +0,0 @@
-*** ../bash-3.1/jobs.c Fri Nov 11 23:13:27 2005
---- jobs.c Wed Feb 1 13:55:38 2006
-***************
-*** 4,8 ****
- control. */
-
-! /* Copyright (C) 1989-2005 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
---- 4,8 ----
- control. */
-
-! /* Copyright (C) 1989-2006 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-***************
-*** 78,82 ****
-
- #define DEFAULT_CHILD_MAX 32
-! #define MAX_JOBS_IN_ARRAY 4096 /* testing */
-
- /* Take care of system dependencies that must be handled when waiting for
---- 78,90 ----
-
- #define DEFAULT_CHILD_MAX 32
-! #if !defined (DEBUG)
-! #define MAX_JOBS_IN_ARRAY 4096 /* production */
-! #else
-! #define MAX_JOBS_IN_ARRAY 128 /* testing */
-! #endif
-!
-! /* Flag values for second argument to delete_job */
-! #define DEL_WARNSTOPPED 1 /* warn about deleting stopped jobs */
-! #define DEL_NOBGPID 2 /* don't add pgrp leader to bgpids */
-
- /* Take care of system dependencies that must be handled when waiting for
-***************
-*** 308,311 ****
---- 316,323 ----
- static char retcode_name_buffer[64];
-
-+ /* flags to detect pid wraparound */
-+ static pid_t first_pid = NO_PID;
-+ static int pid_wrap = -1;
-+
- #if !defined (_POSIX_VERSION)
-
-***************
-*** 329,337 ****
- #endif /* !_POSIX_VERSION */
-
-! /* Initialize the global job stats structure. */
- void
- init_job_stats ()
- {
- js = zerojs;
- }
-
---- 341,351 ----
- #endif /* !_POSIX_VERSION */
-
-! /* Initialize the global job stats structure and other bookkeeping variables */
- void
- init_job_stats ()
- {
- js = zerojs;
-+ first_pid = NO_PID;
-+ pid_wrap = -1;
- }
-
-***************
-*** 620,625 ****
- * the parent gives it away.
- *
- */
-! if (job_control && newjob->pgrp)
- give_terminal_to (newjob->pgrp, 0);
- }
---- 634,642 ----
- * the parent gives it away.
- *
-+ * Don't give the terminal away if this shell is an asynchronous
-+ * subshell.
-+ *
- */
-! if (job_control && newjob->pgrp && (subshell_environment&SUBSHELL_ASYNC) == 0)
- give_terminal_to (newjob->pgrp, 0);
- }
-***************
-*** 806,810 ****
- QUEUE_SIGCHLD(os);
-
-! /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
---- 823,827 ----
- QUEUE_SIGCHLD(os);
-
-! /* XXX could use js.j_firstj and js.j_lastj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-***************
-*** 812,815 ****
---- 829,834 ----
- if (i < js.j_firstj && jobs[i])
- itrace("cleanup_dead_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-+ if (i > js.j_lastj && jobs[i])
-+ itrace("cleanup_dead_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
- #endif
-
-***************
-*** 838,841 ****
---- 857,884 ----
- }
-
-+ static void
-+ delete_old_job (pid)
-+ pid_t pid;
-+ {
-+ PROCESS *p;
-+ int job;
-+
-+ job = find_job (pid, 0, &p);
-+ if (job != NO_JOB)
-+ {
-+ #ifdef DEBUG
-+ itrace ("delete_old_job: found pid %d in job %d with state %d", pid, job, jobs[job]->state);
-+ #endif
-+ if (JOBSTATE (job) == JDEAD)
-+ delete_job (job, DEL_NOBGPID);
-+ else
-+ {
-+ internal_warning (_("forked pid %d appears in running job %d"), pid, job);
-+ if (p)
-+ p->pid = 0;
-+ }
-+ }
-+ }
-+
- /* Reallocate and compress the jobs list. This returns with a jobs array
- whose size is a multiple of JOB_SLOTS and can hold the current number of
-***************
-*** 845,851 ****
- {
- sigset_t set, oset;
-! int nsize, i, j;
- JOB **nlist;
-
- nsize = ((js.j_njobs + JOB_SLOTS - 1) / JOB_SLOTS);
- nsize *= JOB_SLOTS;
---- 888,895 ----
- {
- sigset_t set, oset;
-! int nsize, i, j, ncur, nprev;
- JOB **nlist;
-
-+ ncur = nprev = NO_JOB;
- nsize = ((js.j_njobs + JOB_SLOTS - 1) / JOB_SLOTS);
- nsize *= JOB_SLOTS;
-***************
-*** 855,869 ****
-
- BLOCK_CHILD (set, oset);
-! nlist = (JOB **) xmalloc (nsize * sizeof (JOB *));
- for (i = j = 0; i < js.j_jobslots; i++)
- if (jobs[i])
-! nlist[j++] = jobs[i];
-
- js.j_firstj = 0;
-! js.j_lastj = (j > 0) ? j - 1: 0;
- js.j_jobslots = nsize;
-
-! free (jobs);
-! jobs = nlist;
-
- UNBLOCK_CHILD (oset);
---- 899,947 ----
-
- BLOCK_CHILD (set, oset);
-! nlist = (js.j_jobslots == nsize) ? jobs : (JOB **) xmalloc (nsize * sizeof (JOB *));
-!
- for (i = j = 0; i < js.j_jobslots; i++)
- if (jobs[i])
-! {
-! if (i == js.j_current)
-! ncur = j;
-! if (i == js.j_previous)
-! nprev = j;
-! nlist[j++] = jobs[i];
-! }
-!
-! #if defined (DEBUG)
-! itrace ("realloc_jobs_list: resize jobs list from %d to %d", js.j_jobslots, nsize);
-! itrace ("realloc_jobs_list: j_lastj changed from %d to %d", js.j_lastj, (j > 0) ? j - 1 : 0);
-! itrace ("realloc_jobs_list: j_njobs changed from %d to %d", js.j_njobs, (j > 0) ? j - 1 : 0);
-! #endif
-
- js.j_firstj = 0;
-! js.j_lastj = (j > 0) ? j - 1 : 0;
-! js.j_njobs = j;
- js.j_jobslots = nsize;
-
-! /* Zero out remaining slots in new jobs list */
-! for ( ; j < nsize; j++)
-! nlist[j] = (JOB *)NULL;
-!
-! if (jobs != nlist)
-! {
-! free (jobs);
-! jobs = nlist;
-! }
-!
-! if (ncur != NO_JOB)
-! js.j_current = ncur;
-! if (nprev != NO_JOB)
-! js.j_previous = nprev;
-!
-! /* Need to reset these */
-! if (js.j_current == NO_JOB || js.j_previous == NO_JOB || js.j_current > js.j_lastj || js.j_previous > js.j_lastj)
-! reset_current ();
-!
-! #ifdef DEBUG
-! itrace ("realloc_jobs_list: reset js.j_current (%d) and js.j_previous (%d)", js.j_current, js.j_previous);
-! #endif
-
- UNBLOCK_CHILD (oset);
-***************
-*** 874,878 ****
- the foreground process (subshell_environment != 0). Returns the first
- available slot in the compacted list. If that value is js.j_jobslots, then
-! the list needs to be reallocated. The jobs array is in new memory if
- this returns > 0 and < js.j_jobslots. FLAGS is reserved for future use. */
- static int
---- 952,956 ----
- the foreground process (subshell_environment != 0). Returns the first
- available slot in the compacted list. If that value is js.j_jobslots, then
-! the list needs to be reallocated. The jobs array may be in new memory if
- this returns > 0 and < js.j_jobslots. FLAGS is reserved for future use. */
- static int
-***************
-*** 892,897 ****
- with SIGCHLD blocked. */
- void
-! delete_job (job_index, warn_stopped)
-! int job_index, warn_stopped;
- {
- register JOB *temp;
---- 970,975 ----
- with SIGCHLD blocked. */
- void
-! delete_job (job_index, dflags)
-! int job_index, dflags;
- {
- register JOB *temp;
-***************
-*** 903,918 ****
- return;
-
-! if (warn_stopped && subshell_environment == 0 && STOPPED (job_index))
- internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
- temp = jobs[job_index];
- if (job_index == js.j_current || job_index == js.j_previous)
- reset_current ();
-
-! proc = find_last_proc (job_index, 0);
-! /* Could do this just for J_ASYNC jobs, but we save all. */
-! bgp_add (proc->pid, process_exit_status (proc->status));
-
- jobs[job_index] = (JOB *)NULL;
--
- if (temp == js.j_lastmade)
- js.j_lastmade = 0;
---- 981,1001 ----
- return;
-
-! if ((dflags & DEL_WARNSTOPPED) && subshell_environment == 0 && STOPPED (job_index))
- internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
- temp = jobs[job_index];
-+ if (temp == 0)
-+ return;
- if (job_index == js.j_current || job_index == js.j_previous)
- reset_current ();
-
-! if ((dflags & DEL_NOBGPID) == 0)
-! {
-! proc = find_last_proc (job_index, 0);
-! /* Could do this just for J_ASYNC jobs, but we save all. */
-! if (proc)
-! bgp_add (proc->pid, process_exit_status (proc->status));
-! }
-
- jobs[job_index] = (JOB *)NULL;
- if (temp == js.j_lastmade)
- js.j_lastmade = 0;
-***************
-*** 1092,1095 ****
---- 1175,1180 ----
- if (i < js.j_firstj && jobs[i])
- itrace("map_over_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-+ if (i > js.j_lastj && jobs[i])
-+ itrace("map_over_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
- #endif
- if (jobs[i])
-***************
-*** 1224,1228 ****
- PROCESS *p;
-
-! /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
---- 1309,1313 ----
- PROCESS *p;
-
-! /* XXX could use js.j_firstj here, and should check js.j_lastj */
- for (i = 0; i < js.j_jobslots; i++)
- {
-***************
-*** 1230,1233 ****
---- 1315,1320 ----
- if (i < js.j_firstj && jobs[i])
- itrace("find_job: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-+ if (i > js.j_lastj && jobs[i])
-+ itrace("find_job: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
- #endif
- if (jobs[i])
-***************
-*** 1656,1660 ****
- shell's process group (we could be in the middle of a
- pipeline, for example). */
-! if (async_p == 0 && pipeline_pgrp != shell_pgrp)
- give_terminal_to (pipeline_pgrp, 0);
-
---- 1743,1747 ----
- shell's process group (we could be in the middle of a
- pipeline, for example). */
-! if (async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&SUBSHELL_ASYNC) == 0))
- give_terminal_to (pipeline_pgrp, 0);
-
-***************
-*** 1698,1701 ****
---- 1785,1795 ----
- as the proper pgrp if this is the first child. */
-
-+ if (first_pid == NO_PID)
-+ first_pid = pid;
-+ else if (pid_wrap == -1 && pid < first_pid)
-+ pid_wrap = 0;
-+ else if (pid_wrap == 0 && pid >= first_pid)
-+ pid_wrap = 1;
-+
- if (job_control)
- {
-***************
-*** 1731,1734 ****
---- 1825,1831 ----
- #endif
-
-+ if (pid_wrap > 0)
-+ delete_old_job (pid);
-+
- #if !defined (RECYCLES_PIDS)
- /* Only check for saved status if we've saved more than CHILD_MAX
-***************
-*** 1915,1919 ****
-
- p = jobs[job]->pipe;
-! while (p->next != jobs[job]->pipe)
- p = p->next;
-
---- 2012,2016 ----
-
- p = jobs[job]->pipe;
-! while (p && p->next != jobs[job]->pipe)
- p = p->next;
-
-***************
-*** 1999,2003 ****
-
- /* find first running job; if none running in foreground, break */
-! /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
---- 2096,2100 ----
-
- /* find first running job; if none running in foreground, break */
-! /* XXX could use js.j_firstj and js.j_lastj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-***************
-*** 2005,2008 ****
---- 2102,2107 ----
- if (i < js.j_firstj && jobs[i])
- itrace("wait_for_background_pids: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-+ if (i > js.j_lastj && jobs[i])
-+ itrace("wait_for_background_pids: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
- #endif
- if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0)
-***************
-*** 2199,2203 ****
- wait_sigint_received = 0;
- if (job_control == 0)
-! old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
-
- termination_state = last_command_exit_value;
---- 2298,2306 ----
- wait_sigint_received = 0;
- if (job_control == 0)
-! {
-! old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
-! if (old_sigint_handler == SIG_IGN)
-! set_signal_handler (SIGINT, old_sigint_handler);
-! }
-
- termination_state = last_command_exit_value;
-***************
-*** 2266,2269 ****
---- 2369,2373 ----
- child->running = PS_DONE;
- child->status = 0; /* XXX -- can't find true status */
-+ js.c_living = 0; /* no living child processes */
- if (job != NO_JOB)
- {
-***************
-*** 2317,2321 ****
- itrace("wait_for: job == NO_JOB, giving the terminal to shell_pgrp (%ld)", (long)shell_pgrp);
- #endif
--
- give_terminal_to (shell_pgrp, 0);
- }
---- 2421,2424 ----
-***************
-*** 2866,2869 ****
---- 2969,2973 ----
- if (sigchld || block == 0)
- waitpid_flags |= WNOHANG;
-+ CHECK_TERMSIG;
- pid = WAITPID (-1, &status, waitpid_flags);
-
-***************
-*** 2892,2895 ****
---- 2996,3000 ----
- /* If waitpid returns 0, there are running children. If it returns -1,
- the only other error POSIX says it can return is EINTR. */
-+ CHECK_TERMSIG;
- if (pid <= 0)
- continue; /* jumps right to the test */
-***************
-*** 2898,2902 ****
- run the trap if a process is just being continued. */
- if (WIFCONTINUED(status) == 0)
-! children_exited++;
-
- /* Locate our PROCESS for this pid. */
---- 3003,3010 ----
- run the trap if a process is just being continued. */
- if (WIFCONTINUED(status) == 0)
-! {
-! children_exited++;
-! js.c_living--;
-! }
-
- /* Locate our PROCESS for this pid. */
-***************
-*** 3123,3127 ****
- restore_sigint_handler ();
- if (temp_handler == SIG_DFL)
-! termination_unwind_protect (SIGINT);
- else if (temp_handler != SIG_IGN)
- (*temp_handler) (SIGINT);
---- 3231,3235 ----
- restore_sigint_handler ();
- if (temp_handler == SIG_DFL)
-! termsig_handler (SIGINT);
- else if (temp_handler != SIG_IGN)
- (*temp_handler) (SIGINT);
-***************
-*** 3638,3644 ****
- if (i < js.j_firstj && jobs[i])
- itrace("delete_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- #endif
- if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
-! delete_job (i, 1);
- }
- if (running_only == 0)
---- 3746,3754 ----
- if (i < js.j_firstj && jobs[i])
- itrace("delete_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-+ if (i > js.j_lastj && jobs[i])
-+ itrace("delete_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
- #endif
- if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
-! delete_job (i, DEL_WARNSTOPPED);
- }
- if (running_only == 0)
-***************
-*** 3692,3695 ****
---- 3802,3807 ----
- if (i < js.j_firstj && jobs[i])
- itrace("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-+ if (i > js.j_lastj && jobs[i])
-+ itrace("count_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
- #endif
- if (jobs[i] && DEADJOB(i) == 0)
-***************
-*** 3765,3768 ****
---- 3877,3882 ----
- if (i < js.j_firstj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-+ if (i > js.j_lastj && jobs[i])
-+ itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
- #endif
- if (jobs[i] && DEADJOB (i))
-***************
-*** 3816,3819 ****
---- 3930,3935 ----
- if (i < js.j_firstj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-+ if (i > js.j_lastj && jobs[i])
-+ itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
- #endif
- /* If marking this job as notified would drop us down below
diff --git a/jobs.c.save b/jobs.c.save
deleted file mode 100644
index d7563c29..00000000
--- a/jobs.c.save
+++ /dev/null
@@ -1,3952 +0,0 @@
-/* The thing that makes children, remembers them, and contains wait loops. */
-
-/* This file works with both POSIX and BSD systems. It implements job
- control. */
-
-/* Copyright (C) 1989-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 "trap.h"
-#include <stdio.h>
-#include <signal.h>
-#include <errno.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "posixtime.h"
-
-#if defined (HAVE_SYS_RESOURCE_H) && defined (HAVE_WAIT3) && !defined (_POSIX_VERSION) && !defined (RLIMTYPE)
-# include <sys/resource.h>
-#endif /* !_POSIX_VERSION && HAVE_SYS_RESOURCE_H && HAVE_WAIT3 && !RLIMTYPE */
-
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-
-#include "filecntl.h"
-#include <sys/ioctl.h>
-#include <sys/param.h>
-
-#if defined (BUFFERED_INPUT)
-# include "input.h"
-#endif
-
-/* Need to include this up here for *_TTY_DRIVER definitions. */
-#include "shtty.h"
-
-/* Define this if your output is getting swallowed. It's a no-op on
- machines with the termio or termios tty drivers. */
-/* #define DRAIN_OUTPUT */
-
-/* For the TIOCGPGRP and TIOCSPGRP ioctl parameters on HP-UX */
-#if defined (hpux) && !defined (TERMIOS_TTY_DRIVER)
-# include <bsdtty.h>
-#endif /* hpux && !TERMIOS_TTY_DRIVER */
-
-#include "bashansi.h"
-#include "bashintl.h"
-#include "shell.h"
-#include "jobs.h"
-#include "flags.h"
-
-#include "builtins/builtext.h"
-#include "builtins/common.h"
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#define DEFAULT_CHILD_MAX 32
-#define MAX_JOBS_IN_ARRAY 4096 /* testing */
-
-/* Take care of system dependencies that must be handled when waiting for
- children. The arguments to the WAITPID macro match those to the Posix.1
- waitpid() function. */
-
-#if defined (ultrix) && defined (mips) && defined (_POSIX_VERSION)
-# define WAITPID(pid, statusp, options) \
- wait3 ((union wait *)statusp, options, (struct rusage *)0)
-#else
-# if defined (_POSIX_VERSION) || defined (HAVE_WAITPID)
-# define WAITPID(pid, statusp, options) \
- waitpid ((pid_t)pid, statusp, options)
-# else
-# if defined (HAVE_WAIT3)
-# define WAITPID(pid, statusp, options) \
- wait3 (statusp, options, (struct rusage *)0)
-# else
-# define WAITPID(pid, statusp, options) \
- wait3 (statusp, options, (int *)0)
-# endif /* HAVE_WAIT3 */
-# endif /* !_POSIX_VERSION && !HAVE_WAITPID*/
-#endif /* !(Ultrix && mips && _POSIX_VERSION) */
-
-/* getpgrp () varies between systems. Even systems that claim to be
- Posix.1 compatible lie sometimes (Ultrix, SunOS4, apollo). */
-#if defined (GETPGRP_VOID)
-# define getpgid(p) getpgrp ()
-#else
-# define getpgid(p) getpgrp (p)
-#endif /* !GETPGRP_VOID */
-
-/* If the system needs it, REINSTALL_SIGCHLD_HANDLER will reinstall the
- handler for SIGCHLD. */
-#if defined (MUST_REINSTALL_SIGHANDLERS)
-# define REINSTALL_SIGCHLD_HANDLER signal (SIGCHLD, sigchld_handler)
-#else
-# define REINSTALL_SIGCHLD_HANDLER
-#endif /* !MUST_REINSTALL_SIGHANDLERS */
-
-/* Some systems let waitpid(2) tell callers about stopped children. */
-#if !defined (WCONTINUED) || defined (WCONTINUED_BROKEN)
-# undef WCONTINUED
-# define WCONTINUED 0
-#endif
-#if !defined (WIFCONTINUED)
-# define WIFCONTINUED(s) (0)
-#endif
-
-/* The number of additional slots to allocate when we run out. */
-#define JOB_SLOTS 8
-
-typedef int sh_job_map_func_t __P((JOB *, int, int, int));
-
-/* Variables used here but defined in other files. */
-extern int subshell_environment, line_number;
-extern int posixly_correct, shell_level;
-extern int interrupt_immediately;
-extern int last_command_exit_value, last_command_exit_signal;
-extern int loop_level, breaking;
-extern int sourcelevel;
-extern sh_builtin_func_t *this_shell_builtin;
-extern char *shell_name, *this_command_name;
-extern sigset_t top_level_mask;
-extern procenv_t wait_intr_buf;
-extern int wait_signal_received;
-extern WORD_LIST *subst_assign_varlist;
-
-static struct jobstats zerojs = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
-struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
-
-struct bgpids bgpids = { 0, 0, 0 };
-
-/* The array of known jobs. */
-JOB **jobs = (JOB **)NULL;
-
-#if 0
-/* The number of slots currently allocated to JOBS. */
-int job_slots = 0;
-#endif
-
-/* The controlling tty for this shell. */
-int shell_tty = -1;
-
-/* The shell's process group. */
-pid_t shell_pgrp = NO_PID;
-
-/* The terminal's process group. */
-pid_t terminal_pgrp = NO_PID;
-
-/* The process group of the shell's parent. */
-pid_t original_pgrp = NO_PID;
-
-/* The process group of the pipeline currently being made. */
-pid_t pipeline_pgrp = (pid_t)0;
-
-#if defined (PGRP_PIPE)
-/* Pipes which each shell uses to communicate with the process group leader
- until all of the processes in a pipeline have been started. Then the
- process leader is allowed to continue. */
-int pgrp_pipe[2] = { -1, -1 };
-#endif
-
-#if 0
-/* The job which is current; i.e. the one that `%+' stands for. */
-int current_job = NO_JOB;
-
-/* The previous job; i.e. the one that `%-' stands for. */
-int previous_job = NO_JOB;
-#endif
-
-/* Last child made by the shell. */
-pid_t last_made_pid = NO_PID;
-
-/* Pid of the last asynchronous child. */
-pid_t last_asynchronous_pid = NO_PID;
-
-/* The pipeline currently being built. */
-PROCESS *the_pipeline = (PROCESS *)NULL;
-
-/* If this is non-zero, do job control. */
-int job_control = 1;
-
-/* Call this when you start making children. */
-int already_making_children = 0;
-
-/* If this is non-zero, $LINES and $COLUMNS are reset after every process
- exits from get_tty_state(). */
-int check_window_size;
-
-/* Functions local to this file. */
-
-static void run_sigchld_trap __P((int));
-
-static sighandler wait_sigint_handler __P((int));
-static sighandler sigchld_handler __P((int));
-static sighandler sigcont_sighandler __P((int));
-static sighandler sigstop_sighandler __P((int));
-
-static int waitchld __P((pid_t, int));
-
-static PROCESS *find_pipeline __P((pid_t, int, int *));
-static PROCESS *find_process __P((pid_t, int, int *));
-
-static char *current_working_directory __P((void));
-static char *job_working_directory __P((void));
-static char *j_strsignal __P((int));
-static char *printable_job_status __P((int, PROCESS *, int));
-
-static PROCESS *find_last_proc __P((int, int));
-static pid_t find_last_pid __P((int, int));
-
-static int set_new_line_discipline __P((int));
-static int map_over_jobs __P((sh_job_map_func_t *, int, int));
-static int job_last_stopped __P((int));
-static int job_last_running __P((int));
-static int most_recent_job_in_state __P((int, JOB_STATE));
-static int find_job __P((pid_t, int, PROCESS **));
-static int print_job __P((JOB *, int, int, int));
-static int process_exit_status __P((WAIT));
-static int process_exit_signal __P((WAIT));
-static int job_exit_status __P((int));
-static int job_exit_signal __P((int));
-static int set_job_status_and_cleanup __P((int));
-
-static WAIT raw_job_exit_status __P((int));
-
-static void notify_of_job_status __P((void));
-static void reset_job_indices __P((void));
-static void cleanup_dead_jobs __P((void));
-static int processes_in_job __P((int));
-static void realloc_jobs_list __P((void));
-static int compact_jobs_list __P((int));
-static int discard_pipeline __P((PROCESS *));
-static void add_process __P((char *, pid_t));
-static void print_pipeline __P((PROCESS *, int, int, FILE *));
-static void pretty_print_job __P((int, int, FILE *));
-static void set_current_job __P((int));
-static void reset_current __P((void));
-static void set_job_running __P((int));
-static void setjstatus __P((int));
-static void mark_all_jobs_as_dead __P((void));
-static void mark_dead_jobs_as_notified __P((int));
-static void restore_sigint_handler __P((void));
-#if defined (PGRP_PIPE)
-static void pipe_read __P((int *));
-static void pipe_close __P((int *));
-#endif
-
-static struct pidstat *bgp_alloc __P((pid_t, int));
-static struct pidstat *bgp_add __P((pid_t, int));
-static int bgp_delete __P((pid_t));
-static void bgp_clear __P((void));
-static int bgp_search __P((pid_t));
-static void bgp_prune __P((void));
-
-#if defined (ARRAY_VARS)
-static int *pstatuses; /* list of pipeline statuses */
-static int statsize;
-#endif
-
-/* Used to synchronize between wait_for and other functions and the SIGCHLD
- signal handler. */
-static int sigchld;
-static int queue_sigchld;
-
-#define QUEUE_SIGCHLD(os) (os) = sigchld, queue_sigchld++
-
-#define UNQUEUE_SIGCHLD(os) \
- do { \
- queue_sigchld--; \
- if (queue_sigchld == 0 && os != sigchld) \
- waitchld (-1, 0); \
- } while (0)
-
-static SigHandler *old_tstp, *old_ttou, *old_ttin;
-static SigHandler *old_cont = (SigHandler *)SIG_DFL;
-
-/* A place to temporarily save the current pipeline. */
-static PROCESS *saved_pipeline;
-static int saved_already_making_children;
-
-/* Set this to non-zero whenever you don't want the jobs list to change at
- all: no jobs deleted and no status change notifications. This is used,
- for example, when executing SIGCHLD traps, which may run arbitrary
- commands. */
-static int jobs_list_frozen;
-
-static char retcode_name_buffer[64];
-
-#if !defined (_POSIX_VERSION)
-
-/* These are definitions to map POSIX 1003.1 functions onto existing BSD
- library functions and system calls. */
-#define setpgid(pid, pgrp) setpgrp (pid, pgrp)
-#define tcsetpgrp(fd, pgrp) ioctl ((fd), TIOCSPGRP, &(pgrp))
-
-pid_t
-tcgetpgrp (fd)
- int fd;
-{
- pid_t pgrp;
-
- /* ioctl will handle setting errno correctly. */
- if (ioctl (fd, TIOCGPGRP, &pgrp) < 0)
- return (-1);
- return (pgrp);
-}
-
-#endif /* !_POSIX_VERSION */
-
-/* Initialize the global job stats structure. */
-void
-init_job_stats ()
-{
- js = zerojs;
-}
-
-/* Return the working directory for the current process. Unlike
- job_working_directory, this does not call malloc (), nor do any
- of the functions it calls. This is so that it can safely be called
- from a signal handler. */
-static char *
-current_working_directory ()
-{
- char *dir;
- static char d[PATH_MAX];
-
- dir = get_string_value ("PWD");
-
- if (dir == 0 && the_current_working_directory && no_symbolic_links)
- dir = the_current_working_directory;
-
- if (dir == 0)
- {
- dir = getcwd (d, sizeof(d));
- if (dir)
- dir = d;
- }
-
- return (dir == 0) ? "<unknown>" : dir;
-}
-
-/* Return the working directory for the current process. */
-static char *
-job_working_directory ()
-{
- char *dir;
-
- dir = get_string_value ("PWD");
- if (dir)
- return (savestring (dir));
-
- dir = get_working_directory ("job-working-directory");
- if (dir)
- return (dir);
-
- return (savestring ("<unknown>"));
-}
-
-void
-making_children ()
-{
- if (already_making_children)
- return;
-
- already_making_children = 1;
- start_pipeline ();
-}
-
-void
-stop_making_children ()
-{
- already_making_children = 0;
-}
-
-void
-cleanup_the_pipeline ()
-{
- PROCESS *disposer;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
- disposer = the_pipeline;
- the_pipeline = (PROCESS *)NULL;
- UNBLOCK_CHILD (oset);
-
- if (disposer)
- discard_pipeline (disposer);
-}
-
-void
-save_pipeline (clear)
- int clear;
-{
- saved_pipeline = the_pipeline;
- if (clear)
- the_pipeline = (PROCESS *)NULL;
- saved_already_making_children = already_making_children;
-}
-
-void
-restore_pipeline (discard)
- int discard;
-{
- PROCESS *old_pipeline;
-
- old_pipeline = the_pipeline;
- the_pipeline = saved_pipeline;
- already_making_children = saved_already_making_children;
- if (discard)
- discard_pipeline (old_pipeline);
-}
-
-/* Start building a pipeline. */
-void
-start_pipeline ()
-{
- if (the_pipeline)
- {
- cleanup_the_pipeline ();
- pipeline_pgrp = 0;
-#if defined (PGRP_PIPE)
- pipe_close (pgrp_pipe);
-#endif
- }
-
-#if defined (PGRP_PIPE)
- if (job_control)
- {
- if (pipe (pgrp_pipe) == -1)
- sys_error ("start_pipeline: pgrp pipe");
- }
-#endif
-}
-
-/* Stop building a pipeline. Install the process list in the job array.
- This returns the index of the newly installed job.
- DEFERRED is a command structure to be executed upon satisfactory
- execution exit of this pipeline. */
-int
-stop_pipeline (async, deferred)
- int async;
- COMMAND *deferred;
-{
- register int i, j;
- JOB *newjob;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
-#if defined (PGRP_PIPE)
- /* The parent closes the process group synchronization pipe. */
- pipe_close (pgrp_pipe);
-#endif
-
- cleanup_dead_jobs ();
-
- if (js.j_jobslots == 0)
- {
- js.j_jobslots = JOB_SLOTS;
- jobs = (JOB **)xmalloc (js.j_jobslots * sizeof (JOB *));
-
- /* Now blank out these new entries. */
- for (i = 0; i < js.j_jobslots; i++)
- jobs[i] = (JOB *)NULL;
-
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
-
- /* Scan from the last slot backward, looking for the next free one. */
- /* XXX - revisit this interactive assumption */
- /* XXX - this way for now */
- if (interactive)
- {
- for (i = js.j_jobslots; i; i--)
- if (jobs[i - 1])
- break;
- }
- else
- {
-#if 0
- /* This wraps around, but makes it inconvenient to extend the array */
- for (i = js.j_lastj+1; i != js.j_lastj; i++)
- {
- if (i >= js.j_jobslots)
- i = 0;
- if (jobs[i] == 0)
- break;
- }
- if (i == js.j_lastj)
- i = js.j_jobslots;
-#else
- /* This doesn't wrap around yet. */
- for (i = js.j_lastj ? js.j_lastj + 1 : js.j_lastj; i < js.j_jobslots; i++)
- if (jobs[i] == 0)
- break;
-#endif
- }
-
- /* Do we need more room? */
-
- /* First try compaction */
- if ((interactive_shell == 0 || subshell_environment) && i == js.j_jobslots && js.j_jobslots >= MAX_JOBS_IN_ARRAY)
- i = compact_jobs_list (0);
-
- /* If we can't compact, reallocate */
- if (i == js.j_jobslots)
- {
- js.j_jobslots += JOB_SLOTS;
- jobs = (JOB **)xrealloc (jobs, (js.j_jobslots * sizeof (JOB *)));
-
- for (j = i; j < js.j_jobslots; j++)
- jobs[j] = (JOB *)NULL;
- }
-
- /* Add the current pipeline to the job list. */
- if (the_pipeline)
- {
- register PROCESS *p;
- int any_running, any_stopped, n;
-
- newjob = (JOB *)xmalloc (sizeof (JOB));
-
- for (n = 1, p = the_pipeline; p->next != the_pipeline; n++, p = p->next)
- ;
- p->next = (PROCESS *)NULL;
- newjob->pipe = REVERSE_LIST (the_pipeline, PROCESS *);
- for (p = newjob->pipe; p->next; p = p->next)
- ;
- p->next = newjob->pipe;
-
- the_pipeline = (PROCESS *)NULL;
- newjob->pgrp = pipeline_pgrp;
- pipeline_pgrp = 0;
-
- newjob->flags = 0;
-
- /* Flag to see if in another pgrp. */
- if (job_control)
- newjob->flags |= J_JOBCONTROL;
-
- /* Set the state of this pipeline. */
- p = newjob->pipe;
- any_running = any_stopped = 0;
- do
- {
- any_running |= PRUNNING (p);
- any_stopped |= PSTOPPED (p);
- p = p->next;
- }
- while (p != newjob->pipe);
-
- newjob->state = any_running ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
- newjob->wd = job_working_directory ();
- newjob->deferred = deferred;
-
- newjob->j_cleanup = (sh_vptrfunc_t *)NULL;
- newjob->cleanarg = (PTR_T) NULL;
-
- jobs[i] = newjob;
- if (newjob->state == JDEAD && (newjob->flags & J_FOREGROUND))
- setjstatus (i);
- if (newjob->state == JDEAD)
- {
- js.c_reaped += n; /* wouldn't have been done since this was not part of a job */
- js.j_ndead++;
- }
- js.c_injobs += n;
-
- js.j_lastj = i;
- js.j_njobs++;
- }
- else
- newjob = (JOB *)NULL;
-
- if (newjob)
- js.j_lastmade = newjob;
-
- if (async)
- {
- if (newjob)
- {
- newjob->flags &= ~J_FOREGROUND;
- newjob->flags |= J_ASYNC;
- js.j_lastasync = newjob;
- }
- reset_current ();
- }
- else
- {
- if (newjob)
- {
- newjob->flags |= J_FOREGROUND;
- /*
- * !!!!! NOTE !!!!! (chet@ins.cwru.edu)
- *
- * The currently-accepted job control wisdom says to set the
- * terminal's process group n+1 times in an n-step pipeline:
- * once in the parent and once in each child. This is where
- * the parent gives it away.
- *
- */
- if (job_control && newjob->pgrp)
- give_terminal_to (newjob->pgrp, 0);
- }
- }
-
- stop_making_children ();
- UNBLOCK_CHILD (oset);
- return (js.j_current);
-}
-
-/* Functions to manage the list of exited background pids whose status has
- been saved. */
-
-static struct pidstat *
-bgp_alloc (pid, status)
- pid_t pid;
- int status;
-{
- struct pidstat *ps;
-
- ps = (struct pidstat *)xmalloc (sizeof (struct pidstat));
- ps->pid = pid;
- ps->status = status;
- ps->next = (struct pidstat *)0;
- return ps;
-}
-
-static struct pidstat *
-bgp_add (pid, status)
- pid_t pid;
- int status;
-{
- struct pidstat *ps;
-
-itrace("bgp_add: adding pid %d with status %d", pid, status);
- ps = bgp_alloc (pid, status);
-
- if (bgpids.list == 0)
- {
- bgpids.list = bgpids.end = ps;
- bgpids.npid = 0; /* just to make sure */
- }
- else
- {
- bgpids.end->next = ps;
- bgpids.end = ps;
- }
- bgpids.npid++;
-
- if (bgpids.npid > js.c_childmax)
- bgp_prune ();
-
- return ps;
-}
-
-static int
-bgp_delete (pid)
- pid_t pid;
-{
- struct pidstat *prev, *p;
-
- for (prev = p = bgpids.list; p; prev = p, p = p->next)
- if (p->pid == pid)
- {
- prev->next = p->next; /* remove from list */
- break;
- }
-
- if (p == 0)
- return 0; /* not found */
-
-#if defined (DEBUG)
- itrace("bgp_delete: deleting %d", pid);
-#endif
-
- /* Housekeeping in the border cases. */
- if (p == bgpids.list)
- bgpids.list = bgpids.list->next;
- else if (p == bgpids.end)
- bgpids.end = prev;
-
- bgpids.npid--;
- if (bgpids.npid == 0)
- bgpids.list = bgpids.end = 0;
- else if (bgpids.npid == 1)
- bgpids.end = bgpids.list; /* just to make sure */
-
- free (p);
- return 1;
-}
-
-/* Clear out the list of saved statuses */
-static void
-bgp_clear ()
-{
- struct pidstat *ps, *p;
-
- for (ps = bgpids.list; ps; )
- {
- p = ps;
- ps = ps->next;
- free (p);
- }
- bgpids.list = bgpids.end = 0;
- bgpids.npid = 0;
-}
-
-/* Search for PID in the list of saved background pids; return its status if
- found. If not found, return -1. */
-static int
-bgp_search (pid)
- pid_t pid;
-{
- struct pidstat *ps;
-
- for (ps = bgpids.list ; ps; ps = ps->next)
- if (ps->pid == pid)
- return ps->status;
- return -1;
-}
-
-static void
-bgp_prune ()
-{
- struct pidstat *ps, *p;
-
- while (bgpids.npid > js.c_childmax)
- {
- ps = bgpids.list;
- bgpids.list = bgpids.list->next;
- free (ps);
- bgpids.npid--;
- }
-}
-
-/* Reset the values of js.j_lastj and js.j_firstj after one or both have
- been deleted. The caller should check whether js.j_njobs is 0 before
- calling this. This wraps around, but the rest of the code does not. At
- this point, it should not matter. */
-static void
-reset_job_indices ()
-{
- int old;
-
- if (jobs[js.j_firstj] == 0)
- {
- old = js.j_firstj++;
- while (js.j_firstj != old)
- {
- if (js.j_firstj >= js.j_jobslots)
- js.j_firstj = 0;
- if (jobs[js.j_firstj])
- break;
- js.j_firstj++;
- }
- if (js.j_firstj == old)
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
- if (jobs[js.j_lastj] == 0)
- {
- old = js.j_lastj--;
- while (js.j_lastj != old)
- {
- if (js.j_lastj < 0)
- js.j_lastj = js.j_jobslots - 1;
- if (jobs[js.j_lastj])
- break;
- js.j_lastj--;
- }
- if (js.j_lastj == old)
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
-}
-
-/* Delete all DEAD jobs that the user had received notification about. */
-static void
-cleanup_dead_jobs ()
-{
- register int i;
- int os;
-
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return;
-
- QUEUE_SIGCHLD(os);
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("cleanup_dead_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-#endif
-
- if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i))
- delete_job (i, 0);
- }
- UNQUEUE_SIGCHLD(os);
-}
-
-static int
-processes_in_job (job)
-{
- int nproc;
- register PROCESS *p;
-
- nproc = 0;
- p = jobs[job]->pipe;
- do
- {
- p = p->next;
- nproc++;
- }
- while (p != jobs[job]->pipe);
-
- return nproc;
-}
-
-/* Reallocate and compress the jobs list. This returns with a jobs array
- whose size is a multiple of JOB_SLOTS and can hold the current number of
- jobs. Heuristics are used to minimize the number of new reallocs. */
-static void
-realloc_jobs_list ()
-{
- sigset_t set, oset;
- int nsize, i, j;
- JOB **nlist;
-
- nsize = ((js.j_njobs + JOB_SLOTS - 1) / JOB_SLOTS);
- nsize *= JOB_SLOTS;
- i = js.j_njobs % JOB_SLOTS;
- if (i == 0 || i > (JOB_SLOTS >> 1))
- nsize += JOB_SLOTS;
-
- BLOCK_CHILD (set, oset);
- nlist = (JOB **) xmalloc (nsize * sizeof (JOB *));
- for (i = j = 0; i < js.j_jobslots; i++)
- if (jobs[i])
- nlist[j++] = jobs[i];
-
- js.j_firstj = 0;
- js.j_lastj = (j > 0) ? j - 1: 0;
- js.j_jobslots = nsize;
-
- free (jobs);
- jobs = nlist;
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Compact the jobs list by removing dead jobs. Assumed that we have filled
- the jobs array to some predefined maximum. Called when the shell is not
- the foreground process (subshell_environment != 0). Returns the first
- available slot in the compacted list. If that value is js.j_jobslots, then
- the list needs to be reallocated. The jobs array is in new memory if
- this returns > 0 and < js.j_jobslots. FLAGS is reserved for future use. */
-static int
-compact_jobs_list (flags)
- int flags;
-{
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return js.j_jobslots;
-
- reap_dead_jobs ();
- realloc_jobs_list ();
-
- return (js.j_lastj);
-}
-
-/* Delete the job at INDEX from the job list. Must be called
- with SIGCHLD blocked. */
-void
-delete_job (job_index, warn_stopped)
- int job_index, warn_stopped;
-{
- register JOB *temp;
- PROCESS *proc;
- int ndel, status;
- pid_t pid;
-
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return;
-
- if (warn_stopped && subshell_environment == 0 && STOPPED (job_index))
- internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
- temp = jobs[job_index];
- if (job_index == js.j_current || job_index == js.j_previous)
- reset_current ();
-
- proc = find_last_proc (job_index, 0);
- /* Could do this just for J_ASYNC jobs, but we save all. */
- bgp_add (proc->pid, process_exit_status (proc->status));
-
- jobs[job_index] = (JOB *)NULL;
-itrace("delete_job: setting jobs[%d] (pgrp %d) to NULL", job_index, proc->pid);
- if (temp == js.j_lastmade)
- js.j_lastmade = 0;
- else if (temp == js.j_lastasync)
- js.j_lastasync = 0;
-
- free (temp->wd);
- ndel = discard_pipeline (temp->pipe);
-
- js.c_injobs -= ndel;
- if (temp->state == JDEAD)
- {
- js.c_reaped -= ndel;
- js.j_ndead--;
- if (js.c_reaped < 0)
- {
-#ifdef DEBUG
- itrace("delete_job (%d pgrp %d): js.c_reaped (%d) < 0 ndel = %d js.j_ndead = %d", job_index, temp->pgrp, js.c_reaped, ndel, js.j_ndead);
-#endif
- js.c_reaped = 0;
- }
- }
-
- if (temp->deferred)
- dispose_command (temp->deferred);
-
- free (temp);
-
- js.j_njobs--;
- if (js.j_njobs == 0)
- js.j_firstj = js.j_lastj = 0;
- else if (jobs[js.j_firstj] == 0 || jobs[js.j_lastj] == 0)
- reset_job_indices ();
-}
-
-/* Must be called with SIGCHLD blocked. */
-void
-nohup_job (job_index)
- int job_index;
-{
- register JOB *temp;
-
- if (js.j_jobslots == 0)
- return;
-
- if (temp = jobs[job_index])
- temp->flags |= J_NOHUP;
-}
-
-/* Get rid of the data structure associated with a process chain. */
-static int
-discard_pipeline (chain)
- register PROCESS *chain;
-{
- register PROCESS *this, *next;
- int n;
-
- this = chain;
- n = 0;
- do
- {
- next = this->next;
- FREE (this->command);
- free (this);
- n++;
- this = next;
- }
- while (this != chain);
-
- return n;
-}
-
-/* Add this process to the chain being built in the_pipeline.
- NAME is the command string that will be exec'ed later.
- PID is the process id of the child. */
-static void
-add_process (name, pid)
- char *name;
- pid_t pid;
-{
- PROCESS *t, *p;
-
-#if defined (RECYCLES_PIDS)
- int j;
- p = find_process (pid, 0, &j);
- if (p)
- {
-# ifdef DEBUG
- if (j == NO_JOB)
- internal_warning ("add_process: process %5ld (%s) in the_pipeline", (long)p->pid, p->command);
-# endif
- if (PALIVE (p))
- internal_warning ("add_process: pid %5ld (%s) marked as still alive", (long)p->pid, p->command);
- p->running = PS_RECYCLED; /* mark as recycled */
- }
-#endif
-
- t = (PROCESS *)xmalloc (sizeof (PROCESS));
- t->next = the_pipeline;
- t->pid = pid;
- WSTATUS (t->status) = 0;
- t->running = PS_RUNNING;
- t->command = name;
- the_pipeline = t;
-
- if (t->next == 0)
- t->next = t;
- else
- {
- p = t->next;
- while (p->next != t->next)
- p = p->next;
- p->next = t;
- }
-}
-
-#if 0
-/* Take the last job and make it the first job. Must be called with
- SIGCHLD blocked. */
-int
-rotate_the_pipeline ()
-{
- PROCESS *p;
-
- if (the_pipeline->next == the_pipeline)
- return;
- for (p = the_pipeline; p->next != the_pipeline; p = p->next)
- ;
- the_pipeline = p;
-}
-
-/* Reverse the order of the processes in the_pipeline. Must be called with
- SIGCHLD blocked. */
-int
-reverse_the_pipeline ()
-{
- PROCESS *p, *n;
-
- if (the_pipeline->next == the_pipeline)
- return;
-
- for (p = the_pipeline; p->next != the_pipeline; p = p->next)
- ;
- p->next = (PROCESS *)NULL;
-
- n = REVERSE_LIST (the_pipeline, PROCESS *);
-
- the_pipeline = n;
- for (p = the_pipeline; p->next; p = p->next)
- ;
- p->next = the_pipeline;
-}
-#endif
-
-/* Map FUNC over the list of jobs. If FUNC returns non-zero,
- then it is time to stop mapping, and that is the return value
- for map_over_jobs. FUNC is called with a JOB, arg1, arg2,
- and INDEX. */
-static int
-map_over_jobs (func, arg1, arg2)
- sh_job_map_func_t *func;
- int arg1, arg2;
-{
- register int i;
- int result;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return 0;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX could use js.j_firstj here */
- for (i = result = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("map_over_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-#endif
- if (jobs[i])
- {
- result = (*func)(jobs[i], arg1, arg2, i);
- if (result)
- break;
- }
- }
-
- UNBLOCK_CHILD (oset);
-
- return (result);
-}
-
-/* Cause all the jobs in the current pipeline to exit. */
-void
-terminate_current_pipeline ()
-{
- if (pipeline_pgrp && pipeline_pgrp != shell_pgrp)
- {
- killpg (pipeline_pgrp, SIGTERM);
- killpg (pipeline_pgrp, SIGCONT);
- }
-}
-
-/* Cause all stopped jobs to exit. */
-void
-terminate_stopped_jobs ()
-{
- register int i;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && STOPPED (i))
- {
- killpg (jobs[i]->pgrp, SIGTERM);
- killpg (jobs[i]->pgrp, SIGCONT);
- }
- }
-}
-
-/* Cause all jobs, running or stopped, to receive a hangup signal. If
- a job is marked J_NOHUP, don't send the SIGHUP. */
-void
-hangup_all_jobs ()
-{
- register int i;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i])
- {
- if ((jobs[i]->flags & J_NOHUP) == 0)
- killpg (jobs[i]->pgrp, SIGHUP);
- if (STOPPED (i))
- killpg (jobs[i]->pgrp, SIGCONT);
- }
- }
-}
-
-void
-kill_current_pipeline ()
-{
- stop_making_children ();
- start_pipeline ();
-}
-
-/* Return the pipeline that PID belongs to. Note that the pipeline
- doesn't have to belong to a job. Must be called with SIGCHLD blocked.
- If JOBP is non-null, return the index of the job containing PID. */
-static PROCESS *
-find_pipeline (pid, alive_only, jobp)
- pid_t pid;
- int alive_only;
- int *jobp; /* index into jobs list or NO_JOB */
-{
- int job;
- PROCESS *p;
-
- /* See if this process is in the pipeline that we are building. */
- if (jobp)
- *jobp = NO_JOB;
- if (the_pipeline)
- {
- p = the_pipeline;
- do
- {
- /* Return it if we found it. Don't ever return a recycled pid. */
- if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
- return (p);
-
- p = p->next;
- }
- while (p != the_pipeline);
- }
-
- job = find_job (pid, alive_only, &p);
- if (jobp)
- *jobp = job;
- return (job == NO_JOB) ? (PROCESS *)NULL : jobs[job]->pipe;
-}
-
-/* Return the PROCESS * describing PID. If JOBP is non-null return the index
- into the jobs array of the job containing PID. Must be called with
- SIGCHLD blocked. */
-static PROCESS *
-find_process (pid, alive_only, jobp)
- pid_t pid;
- int alive_only;
- int *jobp; /* index into jobs list or NO_JOB */
-{
- PROCESS *p;
-
- p = find_pipeline (pid, alive_only, jobp);
- while (p && p->pid != pid)
- p = p->next;
- return p;
-}
-
-/* Return the job index that PID belongs to, or NO_JOB if it doesn't
- belong to any job. Must be called with SIGCHLD blocked. */
-static int
-find_job (pid, alive_only, procp)
- pid_t pid;
- int alive_only;
- PROCESS **procp;
-{
- register int i;
- PROCESS *p;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("find_job: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-#endif
- if (jobs[i])
- {
- p = jobs[i]->pipe;
-
- do
- {
- if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
- {
- if (procp)
- *procp = p;
- return (i);
- }
-
- p = p->next;
- }
- while (p != jobs[i]->pipe);
- }
- }
-
- return (NO_JOB);
-}
-
-/* Find a job given a PID. If BLOCK is non-zero, block SIGCHLD as
- required by find_job. */
-int
-get_job_by_pid (pid, block)
- pid_t pid;
- int block;
-{
- int job;
- sigset_t set, oset;
-
- if (block)
- BLOCK_CHILD (set, oset);
-
- job = find_job (pid, 0, NULL);
-
- if (block)
- UNBLOCK_CHILD (oset);
-
- return job;
-}
-
-/* Print descriptive information about the job with leader pid PID. */
-void
-describe_pid (pid)
- pid_t pid;
-{
- int job;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- job = find_job (pid, 0, NULL);
-
- if (job != NO_JOB)
- fprintf (stderr, "[%d] %ld\n", job + 1, (long)pid);
- else
- programming_error (_("describe_pid: %ld: no such pid"), (long)pid);
-
- UNBLOCK_CHILD (oset);
-}
-
-static char *
-j_strsignal (s)
- int s;
-{
- char *x;
-
- x = strsignal (s);
- if (x == 0)
- {
- x = retcode_name_buffer;
- sprintf (x, "Signal %d", s);
- }
- return x;
-}
-
-static char *
-printable_job_status (j, p, format)
- int j;
- PROCESS *p;
- int format;
-{
- static char *temp;
- int es;
-
- temp = "Done";
-
- if (STOPPED (j) && format == 0)
- {
- if (posixly_correct == 0 || p == 0 || (WIFSTOPPED (p->status) == 0))
- temp = "Stopped";
- else
- {
- temp = retcode_name_buffer;
- sprintf (temp, "Stopped(%s)", signal_name (WSTOPSIG (p->status)));
- }
- }
- else if (RUNNING (j))
- temp = "Running";
- else
- {
- if (WIFSTOPPED (p->status))
- temp = j_strsignal (WSTOPSIG (p->status));
- else if (WIFSIGNALED (p->status))
- temp = j_strsignal (WTERMSIG (p->status));
- else if (WIFEXITED (p->status))
- {
- temp = retcode_name_buffer;
- es = WEXITSTATUS (p->status);
- if (es == 0)
- strcpy (temp, "Done");
- else if (posixly_correct)
- sprintf (temp, "Done(%d)", es);
- else
- sprintf (temp, "Exit %d", es);
- }
- else
- temp = "Unknown status";
- }
-
- return temp;
-}
-
-/* This is the way to print out information on a job if you
- know the index. FORMAT is:
-
- JLIST_NORMAL) [1]+ Running emacs
- JLIST_LONG ) [1]+ 2378 Running emacs
- -1 ) [1]+ 2378 emacs
-
- JLIST_NORMAL) [1]+ Stopped ls | more
- JLIST_LONG ) [1]+ 2369 Stopped ls
- 2367 | more
- JLIST_PID_ONLY)
- Just list the pid of the process group leader (really
- the process group).
- JLIST_CHANGED_ONLY)
- Use format JLIST_NORMAL, but list only jobs about which
- the user has not been notified. */
-
-/* Print status for pipeline P. If JOB_INDEX is >= 0, it is the index into
- the JOBS array corresponding to this pipeline. FORMAT is as described
- above. Must be called with SIGCHLD blocked.
-
- If you're printing a pipeline that's not in the jobs array, like the
- current pipeline as it's being created, pass -1 for JOB_INDEX */
-static void
-print_pipeline (p, job_index, format, stream)
- PROCESS *p;
- int job_index, format;
- FILE *stream;
-{
- PROCESS *first, *last, *show;
- int es, name_padding;
- char *temp;
-
- if (p == 0)
- return;
-
- first = last = p;
- while (last->next != first)
- last = last->next;
-
- for (;;)
- {
- if (p != first)
- fprintf (stream, format ? " " : " |");
-
- if (format != JLIST_STANDARD)
- fprintf (stream, "%5ld", (long)p->pid);
-
- fprintf (stream, " ");
-
- if (format > -1 && job_index >= 0)
- {
- show = format ? p : last;
- temp = printable_job_status (job_index, show, format);
-
- if (p != first)
- {
- if (format)
- {
- if (show->running == first->running &&
- WSTATUS (show->status) == WSTATUS (first->status))
- temp = "";
- }
- else
- temp = (char *)NULL;
- }
-
- if (temp)
- {
- fprintf (stream, "%s", temp);
-
- es = STRLEN (temp);
- if (es == 0)
- es = 2; /* strlen ("| ") */
- name_padding = LONGEST_SIGNAL_DESC - es;
-
- fprintf (stream, "%*s", name_padding, "");
-
- if ((WIFSTOPPED (show->status) == 0) &&
- (WIFCONTINUED (show->status) == 0) &&
- WIFCORED (show->status))
- fprintf (stream, "(core dumped) ");
- }
- }
-
- if (p != first && format)
- fprintf (stream, "| ");
-
- if (p->command)
- fprintf (stream, "%s", p->command);
-
- if (p == last && job_index >= 0)
- {
- temp = current_working_directory ();
-
- if (RUNNING (job_index) && (IS_FOREGROUND (job_index) == 0))
- fprintf (stream, " &");
-
- if (strcmp (temp, jobs[job_index]->wd) != 0)
- fprintf (stream,
- " (wd: %s)", polite_directory_format (jobs[job_index]->wd));
- }
-
- if (format || (p == last))
- {
- /* We need to add a CR only if this is an interactive shell, and
- we're reporting the status of a completed job asynchronously.
- We can't really check whether this particular job is being
- reported asynchronously, so just add the CR if the shell is
- currently interactive and asynchronous notification is enabled. */
- if (asynchronous_notification && interactive)
- fprintf (stream, "\r\n");
- else
- fprintf (stream, "\n");
- }
-
- if (p == last)
- break;
- p = p->next;
- }
- fflush (stream);
-}
-
-/* Print information to STREAM about jobs[JOB_INDEX] according to FORMAT.
- Must be called with SIGCHLD blocked or queued with queue_sigchld */
-static void
-pretty_print_job (job_index, format, stream)
- int job_index, format;
- FILE *stream;
-{
- register PROCESS *p;
-
- /* Format only pid information about the process group leader? */
- if (format == JLIST_PID_ONLY)
- {
- fprintf (stream, "%ld\n", (long)jobs[job_index]->pipe->pid);
- return;
- }
-
- if (format == JLIST_CHANGED_ONLY)
- {
- if (IS_NOTIFIED (job_index))
- return;
- format = JLIST_STANDARD;
- }
-
- if (format != JLIST_NONINTERACTIVE)
- fprintf (stream, "[%d]%c ", job_index + 1,
- (job_index == js.j_current) ? '+':
- (job_index == js.j_previous) ? '-' : ' ');
-
- if (format == JLIST_NONINTERACTIVE)
- format = JLIST_LONG;
-
- p = jobs[job_index]->pipe;
-
- print_pipeline (p, job_index, format, stream);
-
- /* We have printed information about this job. When the job's
- status changes, waitchld () sets the notification flag to 0. */
- jobs[job_index]->flags |= J_NOTIFIED;
-}
-
-static int
-print_job (job, format, state, job_index)
- JOB *job;
- int format, state, job_index;
-{
- if (state == -1 || (JOB_STATE)state == job->state)
- pretty_print_job (job_index, format, stdout);
- return (0);
-}
-
-void
-list_one_job (job, format, ignore, job_index)
- JOB *job;
- int format, ignore, job_index;
-{
- pretty_print_job (job_index, format, stdout);
-}
-
-void
-list_stopped_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, (int)JSTOPPED);
-}
-
-void
-list_running_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, (int)JRUNNING);
-}
-
-/* List jobs. If FORMAT is non-zero, then the long form of the information
- is printed, else just a short version. */
-void
-list_all_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, -1);
-}
-
-/* Fork, handling errors. Returns the pid of the newly made child, or 0.
- COMMAND is just for remembering the name of the command; we don't do
- anything else with it. ASYNC_P says what to do with the tty. If
- non-zero, then don't give it away. */
-pid_t
-make_child (command, async_p)
- char *command;
- int async_p;
-{
- sigset_t set, oset;
- pid_t pid;
-
- sigemptyset (&set);
- sigaddset (&set, SIGCHLD);
- sigaddset (&set, SIGINT);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
-
- making_children ();
-
-#if defined (BUFFERED_INPUT)
- /* If default_buffered_input is active, we are reading a script. If
- the command is asynchronous, we have already duplicated /dev/null
- as fd 0, but have not changed the buffered stream corresponding to
- the old fd 0. We don't want to sync the stream in this case. */
- if (default_buffered_input != -1 &&
- (!async_p || default_buffered_input > 0))
- sync_buffered_stream (default_buffered_input);
-#endif /* BUFFERED_INPUT */
-
- /* Create the child, handle severe errors. */
- if ((pid = fork ()) < 0)
- {
- sys_error ("fork");
-
- /* Kill all of the processes in the current pipeline. */
- terminate_current_pipeline ();
-
- /* Discard the current pipeline, if any. */
- if (the_pipeline)
- kill_current_pipeline ();
-
- throw_to_top_level (); /* Reset signals, etc. */
- }
-
- if (pid == 0)
- {
- /* In the child. Give this child the right process group, set the
- signals to the default state for a new process. */
- pid_t mypid;
-
- mypid = getpid ();
-#if defined (BUFFERED_INPUT)
- /* Close default_buffered_input if it's > 0. We don't close it if it's
- 0 because that's the file descriptor used when redirecting input,
- and it's wrong to close the file in that case. */
- unset_bash_input (0);
-#endif /* BUFFERED_INPUT */
-
- /* Restore top-level signal mask. */
- sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
-
- if (job_control)
- {
- /* All processes in this pipeline belong in the same
- process group. */
-
- if (pipeline_pgrp == 0) /* This is the first child. */
- pipeline_pgrp = mypid;
-
- /* Check for running command in backquotes. */
- if (pipeline_pgrp == shell_pgrp)
- ignore_tty_job_signals ();
- else
- default_tty_job_signals ();
-
- /* Set the process group before trying to mess with the terminal's
- process group. This is mandated by POSIX. */
- /* This is in accordance with the Posix 1003.1 standard,
- section B.7.2.4, which says that trying to set the terminal
- process group with tcsetpgrp() to an unused pgrp value (like
- this would have for the first child) is an error. Section
- B.4.3.3, p. 237 also covers this, in the context of job control
- shells. */
- if (setpgid (mypid, pipeline_pgrp) < 0)
- sys_error ("child setpgid (%ld to %ld)", (long)mypid, (long)pipeline_pgrp);
-
- /* By convention (and assumption above), if
- pipeline_pgrp == shell_pgrp, we are making a child for
- command substitution.
- In this case, we don't want to give the terminal to the
- shell's process group (we could be in the middle of a
- pipeline, for example). */
- if (async_p == 0 && pipeline_pgrp != shell_pgrp)
- give_terminal_to (pipeline_pgrp, 0);
-
-#if defined (PGRP_PIPE)
- if (pipeline_pgrp == mypid)
- pipe_read (pgrp_pipe);
-#endif
- }
- else /* Without job control... */
- {
- if (pipeline_pgrp == 0)
- pipeline_pgrp = shell_pgrp;
-
- /* If these signals are set to SIG_DFL, we encounter the curious
- situation of an interactive ^Z to a running process *working*
- and stopping the process, but being unable to do anything with
- that process to change its state. On the other hand, if they
- are set to SIG_IGN, jobs started from scripts do not stop when
- the shell running the script gets a SIGTSTP and stops. */
-
- default_tty_job_signals ();
- }
-
-#if defined (PGRP_PIPE)
- /* Release the process group pipe, since our call to setpgid ()
- is done. The last call to pipe_close is done in stop_pipeline. */
- pipe_close (pgrp_pipe);
-#endif /* PGRP_PIPE */
-
- if (async_p)
- last_asynchronous_pid = mypid;
-#if defined (RECYCLES_PIDS)
- else if (last_asynchronous_pid == mypid)
- /* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
- last_asynchronous_pid = 1;
-#endif
- }
- else
- {
- /* In the parent. Remember the pid of the child just created
- as the proper pgrp if this is the first child. */
-
- if (job_control)
- {
- if (pipeline_pgrp == 0)
- {
- pipeline_pgrp = pid;
- /* Don't twiddle terminal pgrps in the parent! This is the bug,
- not the good thing of twiddling them in the child! */
- /* give_terminal_to (pipeline_pgrp, 0); */
- }
- /* This is done on the recommendation of the Rationale section of
- the POSIX 1003.1 standard, where it discusses job control and
- shells. It is done to avoid possible race conditions. (Ref.
- 1003.1 Rationale, section B.4.3.3, page 236). */
- setpgid (pid, pipeline_pgrp);
- }
- else
- {
- if (pipeline_pgrp == 0)
- pipeline_pgrp = shell_pgrp;
- }
-
- /* Place all processes into the jobs array regardless of the
- state of job_control. */
- add_process (command, pid);
-
- if (async_p)
- last_asynchronous_pid = pid;
-#if defined (RECYCLES_PIDS)
- else if (last_asynchronous_pid == pid)
- /* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
- last_asynchronous_pid = 1;
-#endif
-
-#if !defined (RECYCLES_PIDS)
- /* Only check for saved status if we've saved more than CHILD_MAX
- statuses, unless the system recycles pids. */
- if ((js.c_reaped + bgpids.npid) >= js.c_childmax)
-#endif
- bgp_delete (pid); /* new process, discard any saved status */
-
- last_made_pid = pid;
-
- /* keep stats */
- js.c_totforked++;
- js.c_living++;
-
- /* Unblock SIGINT and SIGCHLD unless creating a pipeline, in which case
- SIGCHLD remains blocked until all commands in the pipeline have been
- created. */
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- }
-
- return (pid);
-}
-
-/* These two functions are called only in child processes. */
-void
-ignore_tty_job_signals ()
-{
- set_signal_handler (SIGTSTP, SIG_IGN);
- set_signal_handler (SIGTTIN, SIG_IGN);
- set_signal_handler (SIGTTOU, SIG_IGN);
-}
-
-void
-default_tty_job_signals ()
-{
- set_signal_handler (SIGTSTP, SIG_DFL);
- set_signal_handler (SIGTTIN, SIG_DFL);
- set_signal_handler (SIGTTOU, SIG_DFL);
-}
-
-/* When we end a job abnormally, or if we stop a job, we set the tty to the
- state kept in here. When a job ends normally, we set the state in here
- to the state of the tty. */
-
-static TTYSTRUCT shell_tty_info;
-
-#if defined (NEW_TTY_DRIVER)
-static struct tchars shell_tchars;
-static struct ltchars shell_ltchars;
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (NEW_TTY_DRIVER) && defined (DRAIN_OUTPUT)
-/* Since the BSD tty driver does not allow us to change the tty modes
- while simultaneously waiting for output to drain and preserving
- typeahead, we have to drain the output ourselves before calling
- ioctl. We cheat by finding the length of the output queue, and
- using select to wait for an appropriate length of time. This is
- a hack, and should be labeled as such (it's a hastily-adapted
- mutation of a `usleep' implementation). It's only reason for
- existing is the flaw in the BSD tty driver. */
-
-static int ttspeeds[] =
-{
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
- 1800, 2400, 4800, 9600, 19200, 38400
-};
-
-static void
-draino (fd, ospeed)
- int fd, ospeed;
-{
- register int delay = ttspeeds[ospeed];
- int n;
-
- if (!delay)
- return;
-
- while ((ioctl (fd, TIOCOUTQ, &n) == 0) && n)
- {
- if (n > (delay / 100))
- {
- struct timeval tv;
-
- n *= 10; /* 2 bits more for conservativeness. */
- tv.tv_sec = n / delay;
- tv.tv_usec = ((n % delay) * 1000000) / delay;
- select (fd, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
- }
- else
- break;
- }
-}
-#endif /* NEW_TTY_DRIVER && DRAIN_OUTPUT */
-
-/* Return the fd from which we are actually getting input. */
-#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
-
-/* Fill the contents of shell_tty_info with the current tty info. */
-int
-get_tty_state ()
-{
- int tty;
-
- tty = input_tty ();
- if (tty != -1)
- {
-#if defined (NEW_TTY_DRIVER)
- ioctl (tty, TIOCGETP, &shell_tty_info);
- ioctl (tty, TIOCGETC, &shell_tchars);
- ioctl (tty, TIOCGLTC, &shell_ltchars);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
- ioctl (tty, TCGETA, &shell_tty_info);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
- if (tcgetattr (tty, &shell_tty_info) < 0)
- {
-#if 0
- /* Only print an error message if we're really interactive at
- this time. */
- if (interactive)
- sys_error ("[%ld: %d] tcgetattr", (long)getpid (), shell_level);
-#endif
- return -1;
- }
-#endif /* TERMIOS_TTY_DRIVER */
- if (check_window_size)
- get_new_window_size (0, (int *)0, (int *)0);
- }
- return 0;
-}
-
-/* Make the current tty use the state in shell_tty_info. */
-int
-set_tty_state ()
-{
- int tty;
-
- tty = input_tty ();
- if (tty != -1)
- {
-#if defined (NEW_TTY_DRIVER)
-# if defined (DRAIN_OUTPUT)
- draino (tty, shell_tty_info.sg_ospeed);
-# endif /* DRAIN_OUTPUT */
- ioctl (tty, TIOCSETN, &shell_tty_info);
- ioctl (tty, TIOCSETC, &shell_tchars);
- ioctl (tty, TIOCSLTC, &shell_ltchars);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
- ioctl (tty, TCSETAW, &shell_tty_info);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
- if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
- {
- /* Only print an error message if we're really interactive at
- this time. */
- if (interactive)
- sys_error ("[%ld: %d] tcsetattr", (long)getpid (), shell_level);
- return -1;
- }
-#endif /* TERMIOS_TTY_DRIVER */
- }
- return 0;
-}
-
-/* Given an index into the jobs array JOB, return the PROCESS struct of the last
- process in that job's pipeline. This is the one whose exit status
- counts. Must be called with SIGCHLD blocked or queued. */
-static PROCESS *
-find_last_proc (job, block)
- int job;
- int block;
-{
- register PROCESS *p;
- sigset_t set, oset;
-
- if (block)
- BLOCK_CHILD (set, oset);
-
- p = jobs[job]->pipe;
- while (p && p->next != jobs[job]->pipe)
- p = p->next;
-
- if (block)
- UNBLOCK_CHILD (oset);
-
- return (p);
-}
-
-static pid_t
-find_last_pid (job, block)
- int job;
- int block;
-{
- PROCESS *p;
-
- p = find_last_proc (job, block);
- /* Possible race condition here. */
- return p->pid;
-}
-
-/* Wait for a particular child of the shell to finish executing.
- This low-level function prints an error message if PID is not
- a child of this shell. It returns -1 if it fails, or whatever
- wait_for returns otherwise. If the child is not found in the
- jobs table, it returns 127. */
-int
-wait_for_single_pid (pid)
- pid_t pid;
-{
- register PROCESS *child;
- sigset_t set, oset;
- int r, job;
-
- BLOCK_CHILD (set, oset);
- child = find_pipeline (pid, 0, (int *)NULL);
- UNBLOCK_CHILD (oset);
-
- if (child == 0)
- {
- r = bgp_search (pid);
- if (r >= 0)
- return r;
- }
-
- if (child == 0)
- {
- internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
- return (127);
- }
-
- r = wait_for (pid);
-
- /* POSIX.2: if we just waited for a job, we can remove it from the jobs
- table. */
- BLOCK_CHILD (set, oset);
- job = find_job (pid, 0, NULL);
- if (job != NO_JOB && jobs[job] && DEADJOB (job))
- jobs[job]->flags |= J_NOTIFIED;
- UNBLOCK_CHILD (oset);
-
- /* If running in posix mode, remove the job from the jobs table immediately */
- if (posixly_correct)
- {
- cleanup_dead_jobs ();
- bgp_delete (pid);
- }
-
- return r;
-}
-
-/* Wait for all of the backgrounds of this shell to finish. */
-void
-wait_for_background_pids ()
-{
- register int i, r, waited_for;
- sigset_t set, oset;
- pid_t pid;
-
- for (waited_for = 0;;)
- {
- BLOCK_CHILD (set, oset);
-
- /* find first running job; if none running in foreground, break */
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("wait_for_background_pids: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-#endif
- if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0)
- break;
- }
- if (i == js.j_jobslots)
- {
- UNBLOCK_CHILD (oset);
- break;
- }
-
- /* now wait for the last pid in that job. */
- pid = find_last_pid (i, 0);
- UNBLOCK_CHILD (oset);
- QUIT;
- errno = 0; /* XXX */
- r = wait_for_single_pid (pid);
- if (r == -1)
- {
- /* If we're mistaken about job state, compensate. */
- if (errno == ECHILD)
- mark_all_jobs_as_dead ();
- }
- else
- waited_for++;
- }
-
- /* POSIX.2 says the shell can discard the statuses of all completed jobs if
- `wait' is called with no arguments. */
- mark_dead_jobs_as_notified (1);
- cleanup_dead_jobs ();
- bgp_clear ();
-}
-
-/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
-#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
-static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
-
-static void
-restore_sigint_handler ()
-{
- if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
- {
- set_signal_handler (SIGINT, old_sigint_handler);
- old_sigint_handler = INVALID_SIGNAL_HANDLER;
- }
-}
-
-static int wait_sigint_received;
-
-/* Handle SIGINT while we are waiting for children in a script to exit.
- The `wait' builtin should be interruptible, but all others should be
- effectively ignored (i.e. not cause the shell to exit). */
-static sighandler
-wait_sigint_handler (sig)
- int sig;
-{
- SigHandler *sigint_handler;
-
- if (interrupt_immediately ||
- (this_shell_builtin && this_shell_builtin == wait_builtin))
- {
- last_command_exit_value = EXECUTION_FAILURE;
- restore_sigint_handler ();
- /* If we got a SIGINT while in `wait', and SIGINT is trapped, do
- what POSIX.2 says (see builtins/wait.def for more info). */
- if (this_shell_builtin && this_shell_builtin == wait_builtin &&
- signal_is_trapped (SIGINT) &&
- ((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler))
- {
- interrupt_immediately = 0;
- trap_handler (SIGINT); /* set pending_traps[SIGINT] */
- wait_signal_received = SIGINT;
- longjmp (wait_intr_buf, 1);
- }
-
- ADDINTERRUPT;
- QUIT;
- }
-
- /* XXX - should this be interrupt_state? If it is, the shell will act
- as if it got the SIGINT interrupt. */
- wait_sigint_received = 1;
-
- /* Otherwise effectively ignore the SIGINT and allow the running job to
- be killed. */
- SIGRETURN (0);
-}
-
-static int
-process_exit_signal (status)
- WAIT status;
-{
- return (WIFSIGNALED (status) ? WTERMSIG (status) : 0);
-}
-
-static int
-process_exit_status (status)
- WAIT status;
-{
- if (WIFSIGNALED (status))
- return (128 + WTERMSIG (status));
- else if (WIFSTOPPED (status) == 0)
- return (WEXITSTATUS (status));
- else
- return (EXECUTION_SUCCESS);
-}
-
-/* Return the exit status of the last process in the pipeline for job JOB.
- This is the exit status of the entire job. */
-static WAIT
-raw_job_exit_status (job)
- int job;
-{
- register PROCESS *p;
- int fail;
-
- if (pipefail_opt)
- {
- fail = 0;
- p = jobs[job]->pipe;
- do
- {
- if (p->status != EXECUTION_SUCCESS) fail = p->status;
- p = p->next;
- }
- while (p != jobs[job]->pipe);
- return fail;
- }
-
- for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
- ;
- return (p->status);
-}
-
-/* Return the exit status of job JOB. This is the exit status of the last
- (rightmost) process in the job's pipeline, modified if the job was killed
- by a signal or stopped. */
-static int
-job_exit_status (job)
- int job;
-{
- return (process_exit_status (raw_job_exit_status (job)));
-}
-
-static int
-job_exit_signal (job)
- int job;
-{
- return (process_exit_signal (raw_job_exit_status (job)));
-}
-
-#define FIND_CHILD(pid, child) \
- do \
- { \
- child = find_pipeline (pid, 0, (int *)NULL); \
- if (child == 0) \
- { \
- give_terminal_to (shell_pgrp, 0); \
- UNBLOCK_CHILD (oset); \
- internal_error (_("wait_for: No record of process %ld"), (long)pid); \
- restore_sigint_handler (); \
- return (termination_state = 127); \
- } \
- } \
- while (0)
-
-/* Wait for pid (one of our children) to terminate, then
- return the termination state. Returns 127 if PID is not found in
- the jobs table. Returns -1 if waitchld() returns -1, indicating
- that there are no unwaited-for child processes. */
-int
-wait_for (pid)
- pid_t pid;
-{
- int job, termination_state, r;
- WAIT s;
- register PROCESS *child;
- sigset_t set, oset;
- register PROCESS *p;
-
- /* In the case that this code is interrupted, and we longjmp () out of it,
- we are relying on the code in throw_to_top_level () to restore the
- top-level signal mask. */
- BLOCK_CHILD (set, oset);
-
- /* Ignore interrupts while waiting for a job run without job control
- to finish. We don't want the shell to exit if an interrupt is
- received, only if one of the jobs run is killed via SIGINT. If
- job control is not set, the job will be run in the same pgrp as
- the shell, and the shell will see any signals the job gets. */
-
- /* This is possibly a race condition -- should it go in stop_pipeline? */
- wait_sigint_received = 0;
- if (job_control == 0)
- old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
-
- termination_state = last_command_exit_value;
-
- if (interactive && job_control == 0)
- QUIT;
-
- /* If we say wait_for (), then we have a record of this child somewhere.
- If it and none of its peers are running, don't call waitchld(). */
-
- job = NO_JOB;
- do
- {
- FIND_CHILD (pid, child);
-
- /* If this child is part of a job, then we are really waiting for the
- job to finish. Otherwise, we are waiting for the child to finish.
- We check for JDEAD in case the job state has been set by waitchld
- after receipt of a SIGCHLD. */
- if (job == NO_JOB)
- job = find_job (pid, 0, NULL);
-
- /* waitchld() takes care of setting the state of the job. If the job
- has already exited before this is called, sigchld_handler will have
- called waitchld and the state will be set to JDEAD. */
-
- if (PRUNNING(child) || (job != NO_JOB && RUNNING (job)))
- {
-#if defined (WAITPID_BROKEN) /* SCOv4 */
- sigset_t suspend_set;
- sigemptyset (&suspend_set);
- sigsuspend (&suspend_set);
-#else /* !WAITPID_BROKEN */
-# if defined (MUST_UNBLOCK_CHLD)
- struct sigaction act, oact;
- sigset_t nullset, chldset;
-
- sigemptyset (&nullset);
- sigemptyset (&chldset);
- sigprocmask (SIG_SETMASK, &nullset, &chldset);
- act.sa_handler = SIG_DFL;
- sigemptyset (&act.sa_mask);
- sigemptyset (&oact.sa_mask);
- act.sa_flags = 0;
- sigaction (SIGCHLD, &act, &oact);
-# endif
- queue_sigchld = 1;
- r = waitchld (pid, 1);
-# if defined (MUST_UNBLOCK_CHLD)
- sigaction (SIGCHLD, &oact, (struct sigaction *)NULL);
- sigprocmask (SIG_SETMASK, &chldset, (sigset_t *)NULL);
-# endif
- queue_sigchld = 0;
- if (r == -1 && errno == ECHILD && this_shell_builtin == wait_builtin)
- {
- termination_state = -1;
- goto wait_for_return;
- }
-
- /* If child is marked as running, but waitpid() returns -1/ECHILD,
- there is something wrong. Somewhere, wait should have returned
- that child's pid. Mark the child as not running and the job,
- if it exists, as JDEAD. */
- if (r == -1 && errno == ECHILD)
- {
- child->running = PS_DONE;
- child->status = 0; /* XXX -- can't find true status */
- if (job != NO_JOB)
- {
- jobs[job]->state = JDEAD;
- js.c_reaped++;
- js.j_ndead++;
- }
- }
-#endif /* WAITPID_BROKEN */
- }
-
- /* If the shell is interactive, and job control is disabled, see
- if the foreground process has died due to SIGINT and jump out
- of the wait loop if it has. waitchld has already restored the
- old SIGINT signal handler. */
- if (interactive && job_control == 0)
- QUIT;
- }
- while (PRUNNING (child) || (job != NO_JOB && RUNNING (job)));
-
- /* The exit state of the command is either the termination state of the
- child, or the termination state of the job. If a job, the status
- of the last child in the pipeline is the significant one. If the command
- or job was terminated by a signal, note that value also. */
- termination_state = (job != NO_JOB) ? job_exit_status (job)
- : process_exit_status (child->status);
- last_command_exit_signal = (job != NO_JOB) ? job_exit_signal (job)
- : process_exit_signal (child->status);
-
- /* XXX */
- if ((job != NO_JOB && JOBSTATE (job) == JSTOPPED) || WIFSTOPPED (child->status))
- termination_state = 128 + WSTOPSIG (child->status);
-
- if (job == NO_JOB || IS_JOBCONTROL (job))
- {
- /* XXX - under what circumstances is a job not present in the jobs
- table (job == NO_JOB)?
- 1. command substitution
-
- In the case of command substitution, at least, it's probably not
- the right thing to give the terminal to the shell's process group,
- even though there is code in subst.c:command_substitute to work
- around it.
-
- Things that don't:
- $PROMPT_COMMAND execution
- process substitution
- */
-#if 0
-if (job == NO_JOB)
- itrace("wait_for: job == NO_JOB, giving the terminal to shell_pgrp (%ld)", (long)shell_pgrp);
-#endif
-
- give_terminal_to (shell_pgrp, 0);
- }
-
- /* If the command did not exit cleanly, or the job is just
- being stopped, then reset the tty state back to what it
- was before this command. Reset the tty state and notify
- the user of the job termination only if the shell is
- interactive. Clean up any dead jobs in either case. */
- if (job != NO_JOB)
- {
- if (interactive_shell && subshell_environment == 0)
- {
- /* This used to use `child->status'. That's wrong, however, for
- pipelines. `child' is the first process in the pipeline. It's
- likely that the process we want to check for abnormal termination
- or stopping is the last process in the pipeline, especially if
- it's long-lived and the first process is short-lived. Since we
- know we have a job here, we can check all the processes in this
- job's pipeline and see if one of them stopped or terminated due
- to a signal. We might want to change this later to just check
- the last process in the pipeline. If no process exits due to a
- signal, S is left as the status of the last job in the pipeline. */
- p = jobs[job]->pipe;
- do
- {
- s = p->status;
- if (WIFSIGNALED(s) || WIFSTOPPED(s))
- break;
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- if (WIFSIGNALED (s) || WIFSTOPPED (s))
- {
- set_tty_state ();
-
- /* If the current job was stopped or killed by a signal, and
- the user has requested it, get a possibly new window size */
- if (check_window_size && (job == js.j_current || IS_FOREGROUND (job)))
- get_new_window_size (0, (int *)0, (int *)0);
- }
- else
- get_tty_state ();
-
- /* If job control is enabled, the job was started with job
- control, the job was the foreground job, and it was killed
- by SIGINT, then print a newline to compensate for the kernel
- printing the ^C without a trailing newline. */
- if (job_control && IS_JOBCONTROL (job) && IS_FOREGROUND (job) &&
- WIFSIGNALED (s) && WTERMSIG (s) == SIGINT)
- {
- /* If SIGINT is not trapped and the shell is in a for, while,
- or until loop, act as if the shell received SIGINT as
- well, so the loop can be broken. This doesn't call the
- SIGINT signal handler; maybe it should. */
- if (signal_is_trapped (SIGINT) == 0 && loop_level)
- ADDINTERRUPT;
- else
- {
- putchar ('\n');
- fflush (stdout);
- }
- }
- }
-
- /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
- signal handler path */
- if (DEADJOB (job) && IS_FOREGROUND (job) /*&& subshell_environment == 0*/)
- setjstatus (job);
-
- /* If this job is dead, notify the user of the status. If the shell
- is interactive, this will display a message on the terminal. If
- the shell is not interactive, make sure we turn on the notify bit
- so we don't get an unwanted message about the job's termination,
- and so delete_job really clears the slot in the jobs table. */
- notify_and_cleanup ();
- }
-
-wait_for_return:
-
- UNBLOCK_CHILD (oset);
-
- /* Restore the original SIGINT signal handler before we return. */
- restore_sigint_handler ();
-
- return (termination_state);
-}
-
-/* Wait for the last process in the pipeline for JOB. Returns whatever
- wait_for returns: the last process's termination state or -1 if there
- are no unwaited-for child processes or an error occurs. */
-int
-wait_for_job (job)
- int job;
-{
- pid_t pid;
- int r;
- sigset_t set, oset;
-
- BLOCK_CHILD(set, oset);
- if (JOBSTATE (job) == JSTOPPED)
- internal_warning (_("wait_for_job: job %d is stopped"), job+1);
-
- pid = find_last_pid (job, 0);
- UNBLOCK_CHILD(oset);
- r = wait_for (pid);
-
- /* POSIX.2: we can remove the job from the jobs table if we just waited
- for it. */
- BLOCK_CHILD (set, oset);
- if (job != NO_JOB && jobs[job] && DEADJOB (job))
- jobs[job]->flags |= J_NOTIFIED;
- UNBLOCK_CHILD (oset);
-
- return r;
-}
-
-/* Print info about dead jobs, and then delete them from the list
- of known jobs. This does not actually delete jobs when the
- shell is not interactive, because the dead jobs are not marked
- as notified. */
-void
-notify_and_cleanup ()
-{
- if (jobs_list_frozen)
- return;
-
- if (interactive || interactive_shell == 0 || sourcelevel)
- notify_of_job_status ();
-
- cleanup_dead_jobs ();
-}
-
-/* Make dead jobs disappear from the jobs array without notification.
- This is used when the shell is not interactive. */
-void
-reap_dead_jobs ()
-{
- mark_dead_jobs_as_notified (0);
- cleanup_dead_jobs ();
-}
-
-/* Return the next closest (chronologically) job to JOB which is in
- STATE. STATE can be JSTOPPED, JRUNNING. NO_JOB is returned if
- there is no next recent job. */
-static int
-most_recent_job_in_state (job, state)
- int job;
- JOB_STATE state;
-{
- register int i, result;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- for (result = NO_JOB, i = job - 1; i >= 0; i--)
- {
- if (jobs[i] && (JOBSTATE (i) == state))
- {
- result = i;
- break;
- }
- }
-
- UNBLOCK_CHILD (oset);
-
- return (result);
-}
-
-/* Return the newest *stopped* job older than JOB, or NO_JOB if not
- found. */
-static int
-job_last_stopped (job)
- int job;
-{
- return (most_recent_job_in_state (job, JSTOPPED));
-}
-
-/* Return the newest *running* job older than JOB, or NO_JOB if not
- found. */
-static int
-job_last_running (job)
- int job;
-{
- return (most_recent_job_in_state (job, JRUNNING));
-}
-
-/* Make JOB be the current job, and make previous be useful. Must be
- called with SIGCHLD blocked. */
-static void
-set_current_job (job)
- int job;
-{
- int candidate;
-
- if (js.j_current != job)
- {
- js.j_previous = js.j_current;
- js.j_current = job;
- }
-
- /* First choice for previous job is the old current job. */
- if (js.j_previous != js.j_current &&
- js.j_previous != NO_JOB &&
- jobs[js.j_previous] &&
- STOPPED (js.j_previous))
- return;
-
- /* Second choice: Newest stopped job that is older than
- the current job. */
- candidate = NO_JOB;
- if (STOPPED (js.j_current))
- {
- candidate = job_last_stopped (js.j_current);
-
- if (candidate != NO_JOB)
- {
- js.j_previous = candidate;
- return;
- }
- }
-
- /* If we get here, there is either only one stopped job, in which case it is
- the current job and the previous job should be set to the newest running
- job, or there are only running jobs and the previous job should be set to
- the newest running job older than the current job. We decide on which
- alternative to use based on whether or not JOBSTATE(js.j_current) is
- JSTOPPED. */
-
- candidate = RUNNING (js.j_current) ? job_last_running (js.j_current)
- : job_last_running (js.j_jobslots);
-
- if (candidate != NO_JOB)
- {
- js.j_previous = candidate;
- return;
- }
-
- /* There is only a single job, and it is both `+' and `-'. */
- js.j_previous = js.j_current;
-}
-
-/* Make current_job be something useful, if it isn't already. */
-
-/* Here's the deal: The newest non-running job should be `+', and the
- next-newest non-running job should be `-'. If there is only a single
- stopped job, the js.j_previous is the newest non-running job. If there
- are only running jobs, the newest running job is `+' and the
- next-newest running job is `-'. Must be called with SIGCHLD blocked. */
-
-static void
-reset_current ()
-{
- int candidate;
-
- if (js.j_jobslots && js.j_current != NO_JOB && jobs[js.j_current] && STOPPED (js.j_current))
- candidate = js.j_current;
- else
- {
- candidate = NO_JOB;
-
- /* First choice: the previous job. */
- if (js.j_previous != NO_JOB && jobs[js.j_previous] && STOPPED (js.j_previous))
- candidate = js.j_previous;
-
- /* Second choice: the most recently stopped job. */
- if (candidate == NO_JOB)
- candidate = job_last_stopped (js.j_jobslots);
-
- /* Third choice: the newest running job. */
- if (candidate == NO_JOB)
- candidate = job_last_running (js.j_jobslots);
- }
-
- /* If we found a job to use, then use it. Otherwise, there
- are no jobs period. */
- if (candidate != NO_JOB)
- set_current_job (candidate);
- else
- js.j_current = js.j_previous = NO_JOB;
-}
-
-/* Set up the job structures so we know the job and its processes are
- all running. */
-static void
-set_job_running (job)
- int job;
-{
- register PROCESS *p;
-
- /* Each member of the pipeline is now running. */
- p = jobs[job]->pipe;
-
- do
- {
- if (WIFSTOPPED (p->status))
- p->running = PS_RUNNING; /* XXX - could be PS_STOPPED */
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- /* This means that the job is running. */
- JOBSTATE (job) = JRUNNING;
-}
-
-/* Start a job. FOREGROUND if non-zero says to do that. Otherwise,
- start the job in the background. JOB is a zero-based index into
- JOBS. Returns -1 if it is unable to start a job, and the return
- status of the job otherwise. */
-int
-start_job (job, foreground)
- int job, foreground;
-{
- register PROCESS *p;
- int already_running;
- sigset_t set, oset;
- char *wd, *s;
- static TTYSTRUCT save_stty;
-
- BLOCK_CHILD (set, oset);
-
- if (DEADJOB (job))
- {
- internal_error (_("%s: job has terminated"), this_command_name);
- UNBLOCK_CHILD (oset);
- return (-1);
- }
-
- already_running = RUNNING (job);
-
- if (foreground == 0 && already_running)
- {
- internal_error (_("%s: job %d already in background"), this_command_name, job + 1);
- UNBLOCK_CHILD (oset);
- return (0); /* XPG6/SUSv3 says this is not an error */
- }
-
- wd = current_working_directory ();
-
- /* You don't know about the state of this job. Do you? */
- jobs[job]->flags &= ~J_NOTIFIED;
-
- if (foreground)
- {
- set_current_job (job);
- jobs[job]->flags |= J_FOREGROUND;
- }
-
- /* Tell the outside world what we're doing. */
- p = jobs[job]->pipe;
-
- if (foreground == 0)
- {
- /* POSIX.2 says `bg' doesn't give any indication about current or
- previous job. */
- if (posixly_correct == 0)
- s = (job == js.j_current) ? "+ ": ((job == js.j_previous) ? "- " : " ");
- else
- s = " ";
- printf ("[%d]%s", job + 1, s);
- }
-
- do
- {
- printf ("%s%s",
- p->command ? p->command : "",
- p->next != jobs[job]->pipe? " | " : "");
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- if (foreground == 0)
- printf (" &");
-
- if (strcmp (wd, jobs[job]->wd) != 0)
- printf (" (wd: %s)", polite_directory_format (jobs[job]->wd));
-
- printf ("\n");
-
- /* Run the job. */
- if (already_running == 0)
- set_job_running (job);
-
- /* Save the tty settings before we start the job in the foreground. */
- if (foreground)
- {
- get_tty_state ();
- save_stty = shell_tty_info;
- /* Give the terminal to this job. */
- if (IS_JOBCONTROL (job))
- give_terminal_to (jobs[job]->pgrp, 0);
- }
- else
- jobs[job]->flags &= ~J_FOREGROUND;
-
- /* If the job is already running, then don't bother jump-starting it. */
- if (already_running == 0)
- {
- jobs[job]->flags |= J_NOTIFIED;
- killpg (jobs[job]->pgrp, SIGCONT);
- }
-
- if (foreground)
- {
- pid_t pid;
- int s;
-
- pid = find_last_pid (job, 0);
- UNBLOCK_CHILD (oset);
- s = wait_for (pid);
- shell_tty_info = save_stty;
- set_tty_state ();
- return (s);
- }
- else
- {
- reset_current ();
- UNBLOCK_CHILD (oset);
- return (0);
- }
-}
-
-/* Give PID SIGNAL. This determines what job the pid belongs to (if any).
- If PID does belong to a job, and the job is stopped, then CONTinue the
- job after giving it SIGNAL. Returns -1 on failure. If GROUP is non-null,
- then kill the process group associated with PID. */
-int
-kill_pid (pid, sig, group)
- pid_t pid;
- int sig, group;
-{
- register PROCESS *p;
- int job, result, negative;
- sigset_t set, oset;
-
- if (pid < -1)
- {
- pid = -pid;
- group = negative = 1;
- }
- else
- negative = 0;
-
- result = EXECUTION_SUCCESS;
- if (group)
- {
- BLOCK_CHILD (set, oset);
- p = find_pipeline (pid, 0, &job);
-
- if (job != NO_JOB)
- {
- jobs[job]->flags &= ~J_NOTIFIED;
-
- /* Kill process in backquotes or one started without job control? */
-
- /* If we're passed a pid < -1, just call killpg and see what happens */
- if (negative && jobs[job]->pgrp == shell_pgrp)
- result = killpg (pid, sig);
- /* If we're killing using job control notification, for example,
- without job control active, we have to do things ourselves. */
- else if (jobs[job]->pgrp == shell_pgrp)
- {
- p = jobs[job]->pipe;
- do
- {
- if (PALIVE (p) == 0)
- continue; /* avoid pid recycling problem */
- kill (p->pid, sig);
- if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
- kill (p->pid, SIGCONT);
- p = p->next;
- }
- while (p != jobs[job]->pipe);
- }
- else
- {
- result = killpg (jobs[job]->pgrp, sig);
- if (p && STOPPED (job) && (sig == SIGTERM || sig == SIGHUP))
- killpg (jobs[job]->pgrp, SIGCONT);
- /* If we're continuing a stopped job via kill rather than bg or
- fg, emulate the `bg' behavior. */
- if (p && STOPPED (job) && (sig == SIGCONT))
- {
- set_job_running (job);
- jobs[job]->flags &= ~J_FOREGROUND;
- jobs[job]->flags |= J_NOTIFIED;
- }
- }
- }
- else
- result = killpg (pid, sig);
-
- UNBLOCK_CHILD (oset);
- }
- else
- result = kill (pid, sig);
-
- return (result);
-}
-
-/* sigchld_handler () flushes at least one of the children that we are
- waiting for. It gets run when we have gotten a SIGCHLD signal. */
-static sighandler
-sigchld_handler (sig)
- int sig;
-{
- int n, oerrno;
-
- oerrno = errno;
- REINSTALL_SIGCHLD_HANDLER;
- sigchld++;
- n = 0;
- if (queue_sigchld == 0)
- n = waitchld (-1, 0);
- errno = oerrno;
- SIGRETURN (n);
-}
-
-/* waitchld() reaps dead or stopped children. It's called by wait_for and
- sigchld_handler, and runs until there aren't any children terminating any
- more.
- If BLOCK is 1, this is to be a blocking wait for a single child, although
- an arriving SIGCHLD could cause the wait to be non-blocking. It returns
- the number of children reaped, or -1 if there are no unwaited-for child
- processes. */
-static int
-waitchld (wpid, block)
- pid_t wpid;
- int block;
-{
- WAIT status;
- PROCESS *child;
- pid_t pid;
- int call_set_current, last_stopped_job, job, children_exited, waitpid_flags;
- static int wcontinued = WCONTINUED; /* run-time fix for glibc problem */
-
- call_set_current = children_exited = 0;
- last_stopped_job = NO_JOB;
-
- do
- {
- /* We don't want to be notified about jobs stopping if job control
- is not active. XXX - was interactive_shell instead of job_control */
- waitpid_flags = (job_control && subshell_environment == 0)
- ? (WUNTRACED|wcontinued)
- : 0;
- if (sigchld || block == 0)
- waitpid_flags |= WNOHANG;
- pid = WAITPID (-1, &status, waitpid_flags);
-
- /* WCONTINUED may be rejected by waitpid as invalid even when defined */
- if (wcontinued && pid < 0 && errno == EINVAL)
- {
- wcontinued = 0;
- continue; /* jump back to the test and retry without WCONTINUED */
- }
-
- /* The check for WNOHANG is to make sure we decrement sigchld only
- if it was non-zero before we called waitpid. */
- if (sigchld > 0 && (waitpid_flags & WNOHANG))
- sigchld--;
-
- /* If waitpid returns -1 with errno == ECHILD, there are no more
- unwaited-for child processes of this shell. */
- if (pid < 0 && errno == ECHILD)
- {
- if (children_exited == 0)
- return -1;
- else
- break;
- }
-
- /* If waitpid returns 0, there are running children. If it returns -1,
- the only other error POSIX says it can return is EINTR. */
- if (pid <= 0)
- continue; /* jumps right to the test */
-
- /* children_exited is used to run traps on SIGCHLD. We don't want to
- run the trap if a process is just being continued. */
- if (WIFCONTINUED(status) == 0)
- children_exited++;
-
- /* Locate our PROCESS for this pid. */
- child = find_process (pid, 1, &job); /* want living procs only */
-
- /* It is not an error to have a child terminate that we did
- not have a record of. This child could have been part of
- a pipeline in backquote substitution. Even so, I'm not
- sure child is ever non-zero. */
- if (child == 0)
- continue;
-
- /* Remember status, and whether or not the process is running. */
- child->status = status;
- child->running = WIFCONTINUED(status) ? PS_RUNNING : PS_DONE;
-
- if (PEXITED (child))
- {
- js.c_totreaped++;
- if (job != NO_JOB)
- js.c_reaped++;
- }
-
- if (job == NO_JOB)
- continue;
-
- call_set_current += set_job_status_and_cleanup (job);
-
- if (STOPPED (job))
- last_stopped_job = job;
- else if (DEADJOB (job) && last_stopped_job == job)
- last_stopped_job = NO_JOB;
- }
- while ((sigchld || block == 0) && pid > (pid_t)0);
-
- /* If a job was running and became stopped, then set the current
- job. Otherwise, don't change a thing. */
- if (call_set_current)
- {
- if (last_stopped_job != NO_JOB)
- set_current_job (last_stopped_job);
- else
- reset_current ();
- }
-
- /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
- if (job_control && signal_is_trapped (SIGCHLD) && children_exited &&
- trap_list[SIGCHLD] != (char *)IGNORE_SIG)
- run_sigchld_trap (children_exited);
-
- /* We have successfully recorded the useful information about this process
- that has just changed state. If we notify asynchronously, and the job
- that this process belongs to is no longer running, then notify the user
- of that fact now. */
- if (asynchronous_notification && interactive)
- notify_of_job_status ();
-
- return (children_exited);
-}
-
-/* Set the status of JOB and perform any necessary cleanup if the job is
- marked as JDEAD.
-
- Currently, the cleanup activity is restricted to handling any SIGINT
- received while waiting for a foreground job to finish. */
-static int
-set_job_status_and_cleanup (job)
- int job;
-{
- PROCESS *child;
- int tstatus, job_state, any_stopped, any_tstped, call_set_current;
- SigHandler *temp_handler;
-
- child = jobs[job]->pipe;
- jobs[job]->flags &= ~J_NOTIFIED;
-
- call_set_current = 0;
-
- /*
- * COMPUTE JOB STATUS
- */
-
- /* If all children are not running, but any of them is stopped, then
- the job is stopped, not dead. */
- job_state = any_stopped = any_tstped = 0;
- do
- {
- job_state |= PRUNNING (child);
-#if 0
- if (PEXITED (child) && (WIFSTOPPED (child->status)))
-#else
- /* Only checking for WIFSTOPPED now, not for PS_DONE */
- if (PSTOPPED (child))
-#endif
- {
- any_stopped = 1;
- any_tstped |= interactive && job_control &&
- (WSTOPSIG (child->status) == SIGTSTP);
- }
- child = child->next;
- }
- while (child != jobs[job]->pipe);
-
- /* If job_state != 0, the job is still running, so don't bother with
- setting the process exit status and job state unless we're
- transitioning from stopped to running. */
- if (job_state != 0 && JOBSTATE(job) != JSTOPPED)
- return 0;
-
- /*
- * SET JOB STATUS
- */
-
- /* The job is either stopped or dead. Set the state of the job accordingly. */
- if (any_stopped)
- {
- jobs[job]->state = JSTOPPED;
- jobs[job]->flags &= ~J_FOREGROUND;
- call_set_current++;
- /* Suspending a job with SIGTSTP breaks all active loops. */
- if (any_tstped && loop_level)
- breaking = loop_level;
- }
- else if (job_state != 0) /* was stopped, now running */
- {
- jobs[job]->state = JRUNNING;
- call_set_current++;
- }
- else
- {
- jobs[job]->state = JDEAD;
- js.j_ndead++;
-
-#if 0
- if (IS_FOREGROUND (job))
- setjstatus (job);
-#endif
-
- /* If this job has a cleanup function associated with it, call it
- with `cleanarg' as the single argument, then set the function
- pointer to NULL so it is not inadvertently called twice. The
- cleanup function is responsible for deallocating cleanarg. */
- if (jobs[job]->j_cleanup)
- {
- (*jobs[job]->j_cleanup) (jobs[job]->cleanarg);
- jobs[job]->j_cleanup = (sh_vptrfunc_t *)NULL;
- }
- }
-
- /*
- * CLEANUP
- *
- * Currently, we just do special things if we got a SIGINT while waiting
- * for a foreground job to complete
- */
-
- if (JOBSTATE (job) == JDEAD)
- {
- /* If we're running a shell script and we get a SIGINT with a
- SIGINT trap handler, but the foreground job handles it and
- does not exit due to SIGINT, run the trap handler but do not
- otherwise act as if we got the interrupt. */
- if (wait_sigint_received && interactive_shell == 0 &&
- WIFSIGNALED (child->status) == 0 && IS_FOREGROUND (job) &&
- signal_is_trapped (SIGINT))
- {
- int old_frozen;
- wait_sigint_received = 0;
- last_command_exit_value = process_exit_status (child->status);
-
- old_frozen = jobs_list_frozen;
- jobs_list_frozen = 1;
- tstatus = maybe_call_trap_handler (SIGINT);
- jobs_list_frozen = old_frozen;
- }
-
- /* If the foreground job is killed by SIGINT when job control is not
- active, we need to perform some special handling.
-
- The check of wait_sigint_received is a way to determine if the
- SIGINT came from the keyboard (in which case the shell has already
- seen it, and wait_sigint_received is non-zero, because keyboard
- signals are sent to process groups) or via kill(2) to the foreground
- process by another process (or itself). If the shell did receive the
- SIGINT, it needs to perform normal SIGINT processing. */
- else if (wait_sigint_received && (WTERMSIG (child->status) == SIGINT) &&
- IS_FOREGROUND (job) && IS_JOBCONTROL (job) == 0)
- {
- int old_frozen;
-
- wait_sigint_received = 0;
-
- /* If SIGINT is trapped, set the exit status so that the trap
- handler can see it. */
- if (signal_is_trapped (SIGINT))
- last_command_exit_value = process_exit_status (child->status);
-
- /* If the signal is trapped, let the trap handler get it no matter
- what and simply return if the trap handler returns.
- maybe_call_trap_handler() may cause dead jobs to be removed from
- the job table because of a call to execute_command. We work
- around this by setting JOBS_LIST_FROZEN. */
- old_frozen = jobs_list_frozen;
- jobs_list_frozen = 1;
- tstatus = maybe_call_trap_handler (SIGINT);
- jobs_list_frozen = old_frozen;
- if (tstatus == 0 && old_sigint_handler != INVALID_SIGNAL_HANDLER)
- {
- /* wait_sigint_handler () has already seen SIGINT and
- allowed the wait builtin to jump out. We need to
- call the original SIGINT handler, if necessary. If
- the original handler is SIG_DFL, we need to resend
- the signal to ourselves. */
-
- temp_handler = old_sigint_handler;
-
- /* Bogus. If we've reset the signal handler as the result
- of a trap caught on SIGINT, then old_sigint_handler
- will point to trap_handler, which now knows nothing about
- SIGINT (if we reset the sighandler to the default).
- In this case, we have to fix things up. What a crock. */
- if (temp_handler == trap_handler && signal_is_trapped (SIGINT) == 0)
- temp_handler = trap_to_sighandler (SIGINT);
- restore_sigint_handler ();
- if (temp_handler == SIG_DFL)
- termination_unwind_protect (SIGINT);
- else if (temp_handler != SIG_IGN)
- (*temp_handler) (SIGINT);
- }
- }
- }
-
- return call_set_current;
-}
-
-/* Build the array of values for the $PIPESTATUS variable from the set of
- exit statuses of all processes in the job J. */
-static void
-setjstatus (j)
- int j;
-{
-#if defined (ARRAY_VARS)
- register int i;
- register PROCESS *p;
-
- for (i = 1, p = jobs[j]->pipe; p->next != jobs[j]->pipe; p = p->next, i++)
- ;
- i++;
- if (statsize < i)
- {
- pstatuses = (int *)xrealloc (pstatuses, i * sizeof (int));
- statsize = i;
- }
- i = 0;
- p = jobs[j]->pipe;
- do
- {
- pstatuses[i++] = process_exit_status (p->status);
- p = p->next;
- }
- while (p != jobs[j]->pipe);
-
- pstatuses[i] = -1; /* sentinel */
- set_pipestatus_array (pstatuses, i);
-#endif
-}
-
-static void
-run_sigchld_trap (nchild)
- int nchild;
-{
- char *trap_command;
- int i;
-
- /* Turn off the trap list during the call to parse_and_execute ()
- to avoid potentially infinite recursive calls. Preserve the
- values of last_command_exit_value, last_made_pid, and the_pipeline
- around the execution of the trap commands. */
- trap_command = savestring (trap_list[SIGCHLD]);
-
- begin_unwind_frame ("SIGCHLD trap");
- unwind_protect_int (last_command_exit_value);
- unwind_protect_int (last_command_exit_signal);
- unwind_protect_var (last_made_pid);
- unwind_protect_int (interrupt_immediately);
- unwind_protect_int (jobs_list_frozen);
- unwind_protect_pointer (the_pipeline);
- unwind_protect_pointer (subst_assign_varlist);
-
- /* We have to add the commands this way because they will be run
- in reverse order of adding. We don't want maybe_set_sigchld_trap ()
- to reference freed memory. */
- add_unwind_protect (xfree, trap_command);
- add_unwind_protect (maybe_set_sigchld_trap, trap_command);
-
- subst_assign_varlist = (WORD_LIST *)NULL;
- the_pipeline = (PROCESS *)NULL;
-
- restore_default_signal (SIGCHLD);
- jobs_list_frozen = 1;
- for (i = 0; i < nchild; i++)
- {
- interrupt_immediately = 1;
- parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE);
- }
-
- run_unwind_frame ("SIGCHLD trap");
-}
-
-/* Function to call when you want to notify people of changes
- in job status. This prints out all jobs which are pending
- notification to stderr, and marks those printed as already
- notified, thus making them candidates for cleanup. */
-static void
-notify_of_job_status ()
-{
- register int job, termsig;
- char *dir;
- sigset_t set, oset;
- WAIT s;
-
- if (jobs == 0 || js.j_jobslots == 0)
- return;
-
- if (old_ttou != 0)
- {
- sigemptyset (&set);
- sigaddset (&set, SIGCHLD);
- sigaddset (&set, SIGTTOU);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
- }
- else
- queue_sigchld++;
-
- /* XXX could use js.j_firstj here */
- for (job = 0, dir = (char *)NULL; job < js.j_jobslots; job++)
- {
- if (jobs[job] && IS_NOTIFIED (job) == 0)
- {
- s = raw_job_exit_status (job);
- termsig = WTERMSIG (s);
-
- /* POSIX.2 says we have to hang onto the statuses of at most the
- last CHILD_MAX background processes if the shell is running a
- script. If the shell is running a script, either from a file
- or standard input, don't print anything unless the job was
- killed by a signal. */
- if (startup_state == 0 && WIFSIGNALED (s) == 0 &&
- ((DEADJOB (job) && IS_FOREGROUND (job) == 0) || STOPPED (job)))
- continue;
-
-#if 0
- /* If job control is disabled, don't print the status messages.
- Mark dead jobs as notified so that they get cleaned up. If
- startup_state == 2, we were started to run `-c command', so
- don't print anything. */
- if ((job_control == 0 && interactive_shell) || startup_state == 2)
-#else
- /* If job control is disabled, don't print the status messages.
- Mark dead jobs as notified so that they get cleaned up. If
- startup_state == 2 and subshell_environment has the
- SUBSHELL_COMSUB bit turned on, we were started to run a command
- substitution, so don't print anything. */
- if ((job_control == 0 && interactive_shell) ||
- (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)))
-#endif
- {
- /* POSIX.2 compatibility: if the shell is not interactive,
- hang onto the job corresponding to the last asynchronous
- pid until the user has been notified of its status or does
- a `wait'. */
- if (DEADJOB (job) && (interactive_shell || (find_last_pid (job, 0) != last_asynchronous_pid)))
- jobs[job]->flags |= J_NOTIFIED;
- continue;
- }
-
- /* Print info on jobs that are running in the background,
- and on foreground jobs that were killed by anything
- except SIGINT (and possibly SIGPIPE). */
- switch (JOBSTATE (job))
- {
- case JDEAD:
- if (interactive_shell == 0 && termsig && WIFSIGNALED (s) &&
- termsig != SIGINT &&
-#if defined (DONT_REPORT_SIGPIPE)
- termsig != SIGPIPE &&
-#endif
- signal_is_trapped (termsig) == 0)
- {
- /* Don't print `0' for a line number. */
- fprintf (stderr, "%s: line %d: ", get_name_for_error (), (line_number == 0) ? 1 : line_number);
- pretty_print_job (job, JLIST_NONINTERACTIVE, stderr);
- }
- else if (IS_FOREGROUND (job))
- {
-#if !defined (DONT_REPORT_SIGPIPE)
- if (termsig && WIFSIGNALED (s) && termsig != SIGINT)
-#else
- if (termsig && WIFSIGNALED (s) && termsig != SIGINT && termsig != SIGPIPE)
-#endif
- {
- fprintf (stderr, "%s", j_strsignal (termsig));
-
- if (WIFCORED (s))
- fprintf (stderr, " (core dumped)");
-
- fprintf (stderr, "\n");
- }
- }
- else if (job_control) /* XXX job control test added */
- {
- if (dir == 0)
- dir = current_working_directory ();
- pretty_print_job (job, JLIST_STANDARD, stderr);
- if (dir && strcmp (dir, jobs[job]->wd) != 0)
- fprintf (stderr,
- "(wd now: %s)\n", polite_directory_format (dir));
- }
-
- jobs[job]->flags |= J_NOTIFIED;
- break;
-
- case JSTOPPED:
- fprintf (stderr, "\n");
- if (dir == 0)
- dir = current_working_directory ();
- pretty_print_job (job, JLIST_STANDARD, stderr);
- if (dir && (strcmp (dir, jobs[job]->wd) != 0))
- fprintf (stderr,
- "(wd now: %s)\n", polite_directory_format (dir));
- jobs[job]->flags |= J_NOTIFIED;
- break;
-
- case JRUNNING:
- case JMIXED:
- break;
-
- default:
- programming_error ("notify_of_job_status");
- }
- }
- }
- if (old_ttou != 0)
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- else
- queue_sigchld--;
-}
-
-/* Initialize the job control mechanism, and set up the tty stuff. */
-int
-initialize_job_control (force)
- int force;
-{
- shell_pgrp = getpgid (0);
-
- if (shell_pgrp == -1)
- {
- sys_error ("initialize_job_control: getpgrp failed");
- exit (1);
- }
-
- /* We can only have job control if we are interactive. */
- if (interactive == 0)
- {
- job_control = 0;
- original_pgrp = NO_PID;
- shell_tty = fileno (stderr);
- }
- else
- {
- /* Get our controlling terminal. If job_control is set, or
- interactive is set, then this is an interactive shell no
- matter where fd 2 is directed. */
- shell_tty = dup (fileno (stderr)); /* fd 2 */
-
- shell_tty = move_to_high_fd (shell_tty, 1, -1);
-
- /* Compensate for a bug in systems that compiled the BSD
- rlogind with DEBUG defined, like NeXT and Alliant. */
- if (shell_pgrp == 0)
- {
- shell_pgrp = getpid ();
- setpgid (0, shell_pgrp);
- tcsetpgrp (shell_tty, shell_pgrp);
- }
-
- while ((terminal_pgrp = tcgetpgrp (shell_tty)) != -1)
- {
- if (shell_pgrp != terminal_pgrp)
- {
- SigHandler *ottin;
-
- ottin = set_signal_handler(SIGTTIN, SIG_DFL);
- kill (0, SIGTTIN);
- set_signal_handler (SIGTTIN, ottin);
- continue;
- }
- break;
- }
-
- /* Make sure that we are using the new line discipline. */
- if (set_new_line_discipline (shell_tty) < 0)
- {
- sys_error ("initialize_job_control: line discipline");
- job_control = 0;
- }
- else
- {
- original_pgrp = shell_pgrp;
- shell_pgrp = getpid ();
-
- if ((original_pgrp != shell_pgrp) && (setpgid (0, shell_pgrp) < 0))
- {
- sys_error ("initialize_job_control: setpgid");
- shell_pgrp = original_pgrp;
- }
-
- job_control = 1;
-
- /* If (and only if) we just set our process group to our pid,
- thereby becoming a process group leader, and the terminal
- is not in the same process group as our (new) process group,
- then set the terminal's process group to our (new) process
- group. If that fails, set our process group back to what it
- was originally (so we can still read from the terminal) and
- turn off job control. */
- if (shell_pgrp != original_pgrp && shell_pgrp != terminal_pgrp)
- {
- if (give_terminal_to (shell_pgrp, 0) < 0)
- {
- setpgid (0, original_pgrp);
- shell_pgrp = original_pgrp;
- job_control = 0;
- }
- }
- }
- if (job_control == 0)
- internal_error (_("no job control in this shell"));
- }
-
- if (shell_tty != fileno (stderr))
- SET_CLOSE_ON_EXEC (shell_tty);
-
- set_signal_handler (SIGCHLD, sigchld_handler);
-
- change_flag ('m', job_control ? '-' : '+');
-
- if (interactive)
- get_tty_state ();
-
- if (js.c_childmax < 0)
- js.c_childmax = getmaxchild ();
- if (js.c_childmax < 0)
- js.c_childmax = DEFAULT_CHILD_MAX;
-
- return job_control;
-}
-
-#ifdef DEBUG
-void
-debug_print_pgrps ()
-{
- itrace("original_pgrp = %ld shell_pgrp = %ld terminal_pgrp = %ld",
- (long)original_pgrp, (long)shell_pgrp, (long)terminal_pgrp);
- itrace("tcgetpgrp(%d) -> %ld, getpgid(0) -> %ld",
- shell_tty, (long)tcgetpgrp (shell_tty), (long)getpgid(0));
-}
-#endif
-
-/* Set the line discipline to the best this system has to offer.
- Return -1 if this is not possible. */
-static int
-set_new_line_discipline (tty)
- int tty;
-{
-#if defined (NEW_TTY_DRIVER)
- int ldisc;
-
- if (ioctl (tty, TIOCGETD, &ldisc) < 0)
- return (-1);
-
- if (ldisc != NTTYDISC)
- {
- ldisc = NTTYDISC;
-
- if (ioctl (tty, TIOCSETD, &ldisc) < 0)
- return (-1);
- }
- return (0);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
-# if defined (TERMIO_LDISC) && (NTTYDISC)
- if (ioctl (tty, TCGETA, &shell_tty_info) < 0)
- return (-1);
-
- if (shell_tty_info.c_line != NTTYDISC)
- {
- shell_tty_info.c_line = NTTYDISC;
- if (ioctl (tty, TCSETAW, &shell_tty_info) < 0)
- return (-1);
- }
-# endif /* TERMIO_LDISC && NTTYDISC */
- return (0);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
-# if defined (TERMIOS_LDISC) && defined (NTTYDISC)
- if (tcgetattr (tty, &shell_tty_info) < 0)
- return (-1);
-
- if (shell_tty_info.c_line != NTTYDISC)
- {
- shell_tty_info.c_line = NTTYDISC;
- if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
- return (-1);
- }
-# endif /* TERMIOS_LDISC && NTTYDISC */
- return (0);
-#endif /* TERMIOS_TTY_DRIVER */
-
-#if !defined (NEW_TTY_DRIVER) && !defined (TERMIO_TTY_DRIVER) && !defined (TERMIOS_TTY_DRIVER)
- return (-1);
-#endif
-}
-
-/* Setup this shell to handle C-C, etc. */
-void
-initialize_job_signals ()
-{
- if (interactive)
- {
- set_signal_handler (SIGINT, sigint_sighandler);
- set_signal_handler (SIGTSTP, SIG_IGN);
- set_signal_handler (SIGTTOU, SIG_IGN);
- set_signal_handler (SIGTTIN, SIG_IGN);
- }
- else if (job_control)
- {
- old_tstp = set_signal_handler (SIGTSTP, sigstop_sighandler);
- old_ttin = set_signal_handler (SIGTTIN, sigstop_sighandler);
- old_ttou = set_signal_handler (SIGTTOU, sigstop_sighandler);
- }
- /* Leave these things alone for non-interactive shells without job
- control. */
-}
-
-/* Here we handle CONT signals. */
-static sighandler
-sigcont_sighandler (sig)
- int sig;
-{
- initialize_job_signals ();
- set_signal_handler (SIGCONT, old_cont);
- kill (getpid (), SIGCONT);
-
- SIGRETURN (0);
-}
-
-/* Here we handle stop signals while we are running not as a login shell. */
-static sighandler
-sigstop_sighandler (sig)
- int sig;
-{
- set_signal_handler (SIGTSTP, old_tstp);
- set_signal_handler (SIGTTOU, old_ttou);
- set_signal_handler (SIGTTIN, old_ttin);
-
- old_cont = set_signal_handler (SIGCONT, sigcont_sighandler);
-
- give_terminal_to (shell_pgrp, 0);
-
- kill (getpid (), sig);
-
- SIGRETURN (0);
-}
-
-/* Give the terminal to PGRP. */
-int
-give_terminal_to (pgrp, force)
- pid_t pgrp;
- int force;
-{
- sigset_t set, oset;
- int r;
-
- r = 0;
- if (job_control || force)
- {
- sigemptyset (&set);
- sigaddset (&set, SIGTTOU);
- sigaddset (&set, SIGTTIN);
- sigaddset (&set, SIGTSTP);
- sigaddset (&set, SIGCHLD);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
-
- if (tcsetpgrp (shell_tty, pgrp) < 0)
- {
- /* Maybe we should print an error message? */
-#if 0
- sys_error ("tcsetpgrp(%d) failed: pid %ld to pgrp %ld",
- shell_tty, (long)getpid(), (long)pgrp);
-#endif
- r = -1;
- }
- else
- terminal_pgrp = pgrp;
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- }
-
- return r;
-}
-
-/* Clear out any jobs in the job array. This is intended to be used by
- children of the shell, who should not have any job structures as baggage
- when they start executing (forking subshells for parenthesized execution
- and functions with pipes are the two that spring to mind). If RUNNING_ONLY
- is nonzero, only running jobs are removed from the table. */
-void
-delete_all_jobs (running_only)
- int running_only;
-{
- register int i;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX - need to set j_lastj, j_firstj appropriately if running_only != 0. */
- if (js.j_jobslots)
- {
- js.j_current = js.j_previous = NO_JOB;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("delete_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-#endif
- if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
- delete_job (i, 1);
- }
- if (running_only == 0)
- {
- free ((char *)jobs);
- js.j_jobslots = 0;
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
- }
-
- if (running_only == 0)
- bgp_clear ();
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Mark all jobs in the job array so that they don't get a SIGHUP when the
- shell gets one. If RUNNING_ONLY is nonzero, mark only running jobs. */
-void
-nohup_all_jobs (running_only)
- int running_only;
-{
- register int i;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- if (js.j_jobslots)
- {
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
- nohup_job (i);
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-int
-count_all_jobs ()
-{
- int i, n;
- sigset_t set, oset;
-
- /* This really counts all non-dead jobs. */
- BLOCK_CHILD (set, oset);
- /* XXX could use js.j_firstj here */
- for (i = n = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-#endif
- if (jobs[i] && DEADJOB(i) == 0)
- n++;
- }
- UNBLOCK_CHILD (oset);
- return n;
-}
-
-static void
-mark_all_jobs_as_dead ()
-{
- register int i;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- if (jobs[i])
- {
- jobs[i]->state = JDEAD;
- js.j_ndead++;
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Mark all dead jobs as notified, so delete_job () cleans them out
- of the job table properly. POSIX.2 says we need to save the
- status of the last CHILD_MAX jobs, so we count the number of dead
- jobs and mark only enough as notified to save CHILD_MAX statuses. */
-static void
-mark_dead_jobs_as_notified (force)
- int force;
-{
- register int i, ndead, ndeadproc;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return;
-
- BLOCK_CHILD (set, oset);
-
- /* If FORCE is non-zero, we don't have to keep CHILD_MAX statuses
- around; just run through the array. */
- if (force)
- {
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
- jobs[i]->flags |= J_NOTIFIED;
- }
- UNBLOCK_CHILD (oset);
- return;
- }
-
- /* Mark enough dead jobs as notified to keep CHILD_MAX processes left in the
- array with the corresponding not marked as notified. This is a better
- way to avoid pid aliasing and reuse problems than keeping the POSIX-
- mandated CHILD_MAX jobs around. delete_job() takes care of keeping the
- bgpids list regulated. */
-
- /* Count the number of dead jobs */
- /* XXX could use js.j_firstj here */
- for (i = ndead = ndeadproc = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-#endif
- if (jobs[i] && DEADJOB (i))
- {
- ndead++;
- ndeadproc += processes_in_job (i);
- }
- }
-
-#ifdef DEBUG
- if (ndeadproc != js.c_reaped)
- itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped);
- if (ndead != js.j_ndead)
- itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead);
-#endif
-
- if (js.c_childmax < 0)
- js.c_childmax = getmaxchild ();
- if (js.c_childmax < 0)
- js.c_childmax = DEFAULT_CHILD_MAX;
-
- /* Don't do anything if the number of dead processes is less than CHILD_MAX
- and we're not forcing a cleanup. */
- if (ndeadproc <= js.c_childmax)
- {
- UNBLOCK_CHILD (oset);
- return;
- }
-
-#if 0
-itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", js.c_childmax, ndead, ndeadproc);
-#endif
-
- /* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
- the list. This isn't exactly right yet; changes need to be made
- to stop_pipeline so we don't mark the newer jobs after we've
- created CHILD_MAX slots in the jobs array. This needs to be
- integrated with a way to keep the jobs array from growing without
- bound. Maybe we wrap back around to 0 after we reach some max
- limit, and there are sufficient job slots free (keep track of total
- size of jobs array (js.j_jobslots) and running count of number of jobs
- in jobs array. Then keep a job index corresponding to the `oldest job'
- and start this loop there, wrapping around as necessary. In effect,
- we turn the list into a circular buffer. */
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
-#endif
- /* If marking this job as notified would drop us down below
- child_max, don't mark it so we can keep at least child_max
- statuses. XXX -- need to check what Posix actually says
- about keeping statuses. */
- if ((ndeadproc -= processes_in_job (i)) <= js.c_childmax)
- break;
- jobs[i]->flags |= J_NOTIFIED;
- }
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Here to allow other parts of the shell (like the trap stuff) to
- unfreeze the jobs list. */
-void
-unfreeze_jobs_list ()
-{
- jobs_list_frozen = 0;
-}
-
-/* Allow or disallow job control to take place. Returns the old value
- of job_control. */
-int
-set_job_control (arg)
- int arg;
-{
- int old;
-
- old = job_control;
- job_control = arg;
-
- /* If we're turning on job control, reset pipeline_pgrp so make_child will
- put new child processes into the right pgrp */
- if (job_control != old && job_control)
- pipeline_pgrp = 0;
-
- return (old);
-}
-
-/* Turn off all traces of job control. This is run by children of the shell
- which are going to do shellsy things, like wait (), etc. */
-void
-without_job_control ()
-{
- stop_making_children ();
- start_pipeline ();
-#if defined (PGRP_PIPE)
- pipe_close (pgrp_pipe);
-#endif
- delete_all_jobs (0);
- set_job_control (0);
-}
-
-/* If this shell is interactive, terminate all stopped jobs and
- restore the original terminal process group. This is done
- before the `exec' builtin calls shell_execve. */
-void
-end_job_control ()
-{
- if (interactive_shell) /* XXX - should it be interactive? */
- {
- terminate_stopped_jobs ();
-
- if (original_pgrp >= 0)
- give_terminal_to (original_pgrp, 1);
- }
-
- if (original_pgrp >= 0)
- setpgid (0, original_pgrp);
-}
-
-/* Restart job control by closing shell tty and reinitializing. This is
- called after an exec fails in an interactive shell and we do not exit. */
-void
-restart_job_control ()
-{
- if (shell_tty != -1)
- close (shell_tty);
- initialize_job_control (0);
-}
-
-/* Set the handler to run when the shell receives a SIGCHLD signal. */
-void
-set_sigchld_handler ()
-{
- set_signal_handler (SIGCHLD, sigchld_handler);
-}
-
-#if defined (PGRP_PIPE)
-/* Read from the read end of a pipe. This is how the process group leader
- blocks until all of the processes in a pipeline have been made. */
-static void
-pipe_read (pp)
- int *pp;
-{
- char ch;
-
- if (pp[1] >= 0)
- {
- close (pp[1]);
- pp[1] = -1;
- }
-
- if (pp[0] >= 0)
- {
- while (read (pp[0], &ch, 1) == -1 && errno == EINTR)
- ;
- }
-}
-
-/* Close the read and write ends of PP, an array of file descriptors. */
-static void
-pipe_close (pp)
- int *pp;
-{
- if (pp[0] >= 0)
- close (pp[0]);
-
- if (pp[1] >= 0)
- close (pp[1]);
-
- pp[0] = pp[1] = -1;
-}
-
-/* Functional interface closes our local-to-job-control pipes. */
-void
-close_pgrp_pipe ()
-{
- pipe_close (pgrp_pipe);
-}
-
-#endif /* PGRP_PIPE */
diff --git a/jobs.c.save1 b/jobs.c.save1
deleted file mode 100644
index 6c85f24b..00000000
--- a/jobs.c.save1
+++ /dev/null
@@ -1,4053 +0,0 @@
-/* The thing that makes children, remembers them, and contains wait loops. */
-
-/* This file works with both POSIX and BSD systems. It implements job
- control. */
-
-/* Copyright (C) 1989-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 "bashtypes.h"
-#include "trap.h"
-#include <stdio.h>
-#include <signal.h>
-#include <errno.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "posixtime.h"
-
-#if defined (HAVE_SYS_RESOURCE_H) && defined (HAVE_WAIT3) && !defined (_POSIX_VERSION) && !defined (RLIMTYPE)
-# include <sys/resource.h>
-#endif /* !_POSIX_VERSION && HAVE_SYS_RESOURCE_H && HAVE_WAIT3 && !RLIMTYPE */
-
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-
-#include "filecntl.h"
-#include <sys/ioctl.h>
-#include <sys/param.h>
-
-#if defined (BUFFERED_INPUT)
-# include "input.h"
-#endif
-
-/* Need to include this up here for *_TTY_DRIVER definitions. */
-#include "shtty.h"
-
-/* Define this if your output is getting swallowed. It's a no-op on
- machines with the termio or termios tty drivers. */
-/* #define DRAIN_OUTPUT */
-
-/* For the TIOCGPGRP and TIOCSPGRP ioctl parameters on HP-UX */
-#if defined (hpux) && !defined (TERMIOS_TTY_DRIVER)
-# include <bsdtty.h>
-#endif /* hpux && !TERMIOS_TTY_DRIVER */
-
-#include "bashansi.h"
-#include "bashintl.h"
-#include "shell.h"
-#include "jobs.h"
-#include "flags.h"
-
-#include "builtins/builtext.h"
-#include "builtins/common.h"
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#define DEFAULT_CHILD_MAX 32
-#if 1
-#define MAX_JOBS_IN_ARRAY 4096 /* production*/
-#else
-#define MAX_JOBS_IN_ARRAY 128 /* testing */
-#endif
-
-/* Flag values for second argument to delete_job */
-#define DEL_WARNSTOPPED 1 /* warn about deleting stopped jobs */
-#define DEL_NOBGPID 2 /* don't add pgrp leader to bgpids */
-
-/* Take care of system dependencies that must be handled when waiting for
- children. The arguments to the WAITPID macro match those to the Posix.1
- waitpid() function. */
-
-#if defined (ultrix) && defined (mips) && defined (_POSIX_VERSION)
-# define WAITPID(pid, statusp, options) \
- wait3 ((union wait *)statusp, options, (struct rusage *)0)
-#else
-# if defined (_POSIX_VERSION) || defined (HAVE_WAITPID)
-# define WAITPID(pid, statusp, options) \
- waitpid ((pid_t)pid, statusp, options)
-# else
-# if defined (HAVE_WAIT3)
-# define WAITPID(pid, statusp, options) \
- wait3 (statusp, options, (struct rusage *)0)
-# else
-# define WAITPID(pid, statusp, options) \
- wait3 (statusp, options, (int *)0)
-# endif /* HAVE_WAIT3 */
-# endif /* !_POSIX_VERSION && !HAVE_WAITPID*/
-#endif /* !(Ultrix && mips && _POSIX_VERSION) */
-
-/* getpgrp () varies between systems. Even systems that claim to be
- Posix.1 compatible lie sometimes (Ultrix, SunOS4, apollo). */
-#if defined (GETPGRP_VOID)
-# define getpgid(p) getpgrp ()
-#else
-# define getpgid(p) getpgrp (p)
-#endif /* !GETPGRP_VOID */
-
-/* If the system needs it, REINSTALL_SIGCHLD_HANDLER will reinstall the
- handler for SIGCHLD. */
-#if defined (MUST_REINSTALL_SIGHANDLERS)
-# define REINSTALL_SIGCHLD_HANDLER signal (SIGCHLD, sigchld_handler)
-#else
-# define REINSTALL_SIGCHLD_HANDLER
-#endif /* !MUST_REINSTALL_SIGHANDLERS */
-
-/* Some systems let waitpid(2) tell callers about stopped children. */
-#if !defined (WCONTINUED) || defined (WCONTINUED_BROKEN)
-# undef WCONTINUED
-# define WCONTINUED 0
-#endif
-#if !defined (WIFCONTINUED)
-# define WIFCONTINUED(s) (0)
-#endif
-
-/* The number of additional slots to allocate when we run out. */
-#define JOB_SLOTS 8
-
-typedef int sh_job_map_func_t __P((JOB *, int, int, int));
-
-/* Variables used here but defined in other files. */
-extern int subshell_environment, line_number;
-extern int posixly_correct, shell_level;
-extern int interrupt_immediately;
-extern int last_command_exit_value, last_command_exit_signal;
-extern int loop_level, breaking;
-extern int sourcelevel;
-extern sh_builtin_func_t *this_shell_builtin;
-extern char *shell_name, *this_command_name;
-extern sigset_t top_level_mask;
-extern procenv_t wait_intr_buf;
-extern int wait_signal_received;
-extern WORD_LIST *subst_assign_varlist;
-
-static struct jobstats zerojs = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
-struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
-
-struct bgpids bgpids = { 0, 0, 0 };
-
-/* The array of known jobs. */
-JOB **jobs = (JOB **)NULL;
-
-#if 0
-/* The number of slots currently allocated to JOBS. */
-int job_slots = 0;
-#endif
-
-/* The controlling tty for this shell. */
-int shell_tty = -1;
-
-/* The shell's process group. */
-pid_t shell_pgrp = NO_PID;
-
-/* The terminal's process group. */
-pid_t terminal_pgrp = NO_PID;
-
-/* The process group of the shell's parent. */
-pid_t original_pgrp = NO_PID;
-
-/* The process group of the pipeline currently being made. */
-pid_t pipeline_pgrp = (pid_t)0;
-
-#if defined (PGRP_PIPE)
-/* Pipes which each shell uses to communicate with the process group leader
- until all of the processes in a pipeline have been started. Then the
- process leader is allowed to continue. */
-int pgrp_pipe[2] = { -1, -1 };
-#endif
-
-#if 0
-/* The job which is current; i.e. the one that `%+' stands for. */
-int current_job = NO_JOB;
-
-/* The previous job; i.e. the one that `%-' stands for. */
-int previous_job = NO_JOB;
-#endif
-
-/* Last child made by the shell. */
-pid_t last_made_pid = NO_PID;
-
-/* Pid of the last asynchronous child. */
-pid_t last_asynchronous_pid = NO_PID;
-
-/* The pipeline currently being built. */
-PROCESS *the_pipeline = (PROCESS *)NULL;
-
-/* If this is non-zero, do job control. */
-int job_control = 1;
-
-/* Call this when you start making children. */
-int already_making_children = 0;
-
-/* If this is non-zero, $LINES and $COLUMNS are reset after every process
- exits from get_tty_state(). */
-int check_window_size;
-
-/* Functions local to this file. */
-
-static void run_sigchld_trap __P((int));
-
-static sighandler wait_sigint_handler __P((int));
-static sighandler sigchld_handler __P((int));
-static sighandler sigcont_sighandler __P((int));
-static sighandler sigstop_sighandler __P((int));
-
-static int waitchld __P((pid_t, int));
-
-static PROCESS *find_pipeline __P((pid_t, int, int *));
-static PROCESS *find_process __P((pid_t, int, int *));
-
-static char *current_working_directory __P((void));
-static char *job_working_directory __P((void));
-static char *j_strsignal __P((int));
-static char *printable_job_status __P((int, PROCESS *, int));
-
-static PROCESS *find_last_proc __P((int, int));
-static pid_t find_last_pid __P((int, int));
-
-static int set_new_line_discipline __P((int));
-static int map_over_jobs __P((sh_job_map_func_t *, int, int));
-static int job_last_stopped __P((int));
-static int job_last_running __P((int));
-static int most_recent_job_in_state __P((int, JOB_STATE));
-static int find_job __P((pid_t, int, PROCESS **));
-static int print_job __P((JOB *, int, int, int));
-static int process_exit_status __P((WAIT));
-static int process_exit_signal __P((WAIT));
-static int job_exit_status __P((int));
-static int job_exit_signal __P((int));
-static int set_job_status_and_cleanup __P((int));
-
-static WAIT raw_job_exit_status __P((int));
-
-static void notify_of_job_status __P((void));
-static void reset_job_indices __P((void));
-static void cleanup_dead_jobs __P((void));
-static int processes_in_job __P((int));
-static void realloc_jobs_list __P((void));
-static int compact_jobs_list __P((int));
-static int discard_pipeline __P((PROCESS *));
-static void add_process __P((char *, pid_t));
-static void print_pipeline __P((PROCESS *, int, int, FILE *));
-static void pretty_print_job __P((int, int, FILE *));
-static void set_current_job __P((int));
-static void reset_current __P((void));
-static void set_job_running __P((int));
-static void setjstatus __P((int));
-static void mark_all_jobs_as_dead __P((void));
-static void mark_dead_jobs_as_notified __P((int));
-static void restore_sigint_handler __P((void));
-#if defined (PGRP_PIPE)
-static void pipe_read __P((int *));
-static void pipe_close __P((int *));
-#endif
-
-static struct pidstat *bgp_alloc __P((pid_t, int));
-static struct pidstat *bgp_add __P((pid_t, int));
-static int bgp_delete __P((pid_t));
-static void bgp_clear __P((void));
-static int bgp_search __P((pid_t));
-static void bgp_prune __P((void));
-
-#if defined (ARRAY_VARS)
-static int *pstatuses; /* list of pipeline statuses */
-static int statsize;
-#endif
-
-/* Used to synchronize between wait_for and other functions and the SIGCHLD
- signal handler. */
-static int sigchld;
-static int queue_sigchld;
-
-#define QUEUE_SIGCHLD(os) (os) = sigchld, queue_sigchld++
-
-#define UNQUEUE_SIGCHLD(os) \
- do { \
- queue_sigchld--; \
- if (queue_sigchld == 0 && os != sigchld) \
- waitchld (-1, 0); \
- } while (0)
-
-static SigHandler *old_tstp, *old_ttou, *old_ttin;
-static SigHandler *old_cont = (SigHandler *)SIG_DFL;
-
-/* A place to temporarily save the current pipeline. */
-static PROCESS *saved_pipeline;
-static int saved_already_making_children;
-
-/* Set this to non-zero whenever you don't want the jobs list to change at
- all: no jobs deleted and no status change notifications. This is used,
- for example, when executing SIGCHLD traps, which may run arbitrary
- commands. */
-static int jobs_list_frozen;
-
-static char retcode_name_buffer[64];
-
-/* flags to detect pid wraparound */
-static pid_t first_pid = NO_PID;
-static int pid_wrap = -1;
-
-#if !defined (_POSIX_VERSION)
-
-/* These are definitions to map POSIX 1003.1 functions onto existing BSD
- library functions and system calls. */
-#define setpgid(pid, pgrp) setpgrp (pid, pgrp)
-#define tcsetpgrp(fd, pgrp) ioctl ((fd), TIOCSPGRP, &(pgrp))
-
-pid_t
-tcgetpgrp (fd)
- int fd;
-{
- pid_t pgrp;
-
- /* ioctl will handle setting errno correctly. */
- if (ioctl (fd, TIOCGPGRP, &pgrp) < 0)
- return (-1);
- return (pgrp);
-}
-
-#endif /* !_POSIX_VERSION */
-
-/* Initialize the global job stats structure and other bookkeeping variables */
-void
-init_job_stats ()
-{
- js = zerojs;
- first_pid = NO_PID;
- pid_wrap = -1;
-}
-
-/* Return the working directory for the current process. Unlike
- job_working_directory, this does not call malloc (), nor do any
- of the functions it calls. This is so that it can safely be called
- from a signal handler. */
-static char *
-current_working_directory ()
-{
- char *dir;
- static char d[PATH_MAX];
-
- dir = get_string_value ("PWD");
-
- if (dir == 0 && the_current_working_directory && no_symbolic_links)
- dir = the_current_working_directory;
-
- if (dir == 0)
- {
- dir = getcwd (d, sizeof(d));
- if (dir)
- dir = d;
- }
-
- return (dir == 0) ? "<unknown>" : dir;
-}
-
-/* Return the working directory for the current process. */
-static char *
-job_working_directory ()
-{
- char *dir;
-
- dir = get_string_value ("PWD");
- if (dir)
- return (savestring (dir));
-
- dir = get_working_directory ("job-working-directory");
- if (dir)
- return (dir);
-
- return (savestring ("<unknown>"));
-}
-
-void
-making_children ()
-{
- if (already_making_children)
- return;
-
- already_making_children = 1;
- start_pipeline ();
-}
-
-void
-stop_making_children ()
-{
- already_making_children = 0;
-}
-
-void
-cleanup_the_pipeline ()
-{
- PROCESS *disposer;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
- disposer = the_pipeline;
- the_pipeline = (PROCESS *)NULL;
- UNBLOCK_CHILD (oset);
-
- if (disposer)
- discard_pipeline (disposer);
-}
-
-void
-save_pipeline (clear)
- int clear;
-{
- saved_pipeline = the_pipeline;
- if (clear)
- the_pipeline = (PROCESS *)NULL;
- saved_already_making_children = already_making_children;
-}
-
-void
-restore_pipeline (discard)
- int discard;
-{
- PROCESS *old_pipeline;
-
- old_pipeline = the_pipeline;
- the_pipeline = saved_pipeline;
- already_making_children = saved_already_making_children;
- if (discard)
- discard_pipeline (old_pipeline);
-}
-
-/* Start building a pipeline. */
-void
-start_pipeline ()
-{
- if (the_pipeline)
- {
- cleanup_the_pipeline ();
- pipeline_pgrp = 0;
-#if defined (PGRP_PIPE)
- pipe_close (pgrp_pipe);
-#endif
- }
-
-#if defined (PGRP_PIPE)
- if (job_control)
- {
- if (pipe (pgrp_pipe) == -1)
- sys_error ("start_pipeline: pgrp pipe");
- }
-#endif
-}
-
-/* Stop building a pipeline. Install the process list in the job array.
- This returns the index of the newly installed job.
- DEFERRED is a command structure to be executed upon satisfactory
- execution exit of this pipeline. */
-int
-stop_pipeline (async, deferred)
- int async;
- COMMAND *deferred;
-{
- register int i, j;
- JOB *newjob;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
-#if defined (PGRP_PIPE)
- /* The parent closes the process group synchronization pipe. */
- pipe_close (pgrp_pipe);
-#endif
-
- cleanup_dead_jobs ();
-
- if (js.j_jobslots == 0)
- {
- js.j_jobslots = JOB_SLOTS;
- jobs = (JOB **)xmalloc (js.j_jobslots * sizeof (JOB *));
-
- /* Now blank out these new entries. */
- for (i = 0; i < js.j_jobslots; i++)
- jobs[i] = (JOB *)NULL;
-
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
-
- /* Scan from the last slot backward, looking for the next free one. */
- /* XXX - revisit this interactive assumption */
- /* XXX - this way for now */
- if (interactive)
- {
- for (i = js.j_jobslots; i; i--)
- if (jobs[i - 1])
- break;
- }
- else
- {
-#if 0
- /* This wraps around, but makes it inconvenient to extend the array */
- for (i = js.j_lastj+1; i != js.j_lastj; i++)
- {
- if (i >= js.j_jobslots)
- i = 0;
- if (jobs[i] == 0)
- break;
- }
- if (i == js.j_lastj)
- i = js.j_jobslots;
-#else
- /* This doesn't wrap around yet. */
- for (i = js.j_lastj ? js.j_lastj + 1 : js.j_lastj; i < js.j_jobslots; i++)
- if (jobs[i] == 0)
- break;
-#endif
- }
-
- /* Do we need more room? */
-
- /* First try compaction */
- if ((interactive_shell == 0 || subshell_environment) && i == js.j_jobslots && js.j_jobslots >= MAX_JOBS_IN_ARRAY)
- i = compact_jobs_list (0);
-
- /* If we can't compact, reallocate */
- if (i == js.j_jobslots)
- {
- js.j_jobslots += JOB_SLOTS;
- jobs = (JOB **)xrealloc (jobs, (js.j_jobslots * sizeof (JOB *)));
-
- for (j = i; j < js.j_jobslots; j++)
- jobs[j] = (JOB *)NULL;
- }
-
- /* Add the current pipeline to the job list. */
- if (the_pipeline)
- {
- register PROCESS *p;
- int any_running, any_stopped, n;
-
- newjob = (JOB *)xmalloc (sizeof (JOB));
-
- for (n = 1, p = the_pipeline; p->next != the_pipeline; n++, p = p->next)
- ;
- p->next = (PROCESS *)NULL;
- newjob->pipe = REVERSE_LIST (the_pipeline, PROCESS *);
- for (p = newjob->pipe; p->next; p = p->next)
- ;
- p->next = newjob->pipe;
-
- the_pipeline = (PROCESS *)NULL;
- newjob->pgrp = pipeline_pgrp;
- pipeline_pgrp = 0;
-
- newjob->flags = 0;
-
- /* Flag to see if in another pgrp. */
- if (job_control)
- newjob->flags |= J_JOBCONTROL;
-
- /* Set the state of this pipeline. */
- p = newjob->pipe;
- any_running = any_stopped = 0;
- do
- {
- any_running |= PRUNNING (p);
- any_stopped |= PSTOPPED (p);
- p = p->next;
- }
- while (p != newjob->pipe);
-
- newjob->state = any_running ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
- newjob->wd = job_working_directory ();
- newjob->deferred = deferred;
-
- newjob->j_cleanup = (sh_vptrfunc_t *)NULL;
- newjob->cleanarg = (PTR_T) NULL;
-
- jobs[i] = newjob;
- if (newjob->state == JDEAD && (newjob->flags & J_FOREGROUND))
- setjstatus (i);
- if (newjob->state == JDEAD)
- {
- js.c_reaped += n; /* wouldn't have been done since this was not part of a job */
- js.j_ndead++;
- }
- js.c_injobs += n;
-
- js.j_lastj = i;
- js.j_njobs++;
- }
- else
- newjob = (JOB *)NULL;
-
- if (newjob)
- js.j_lastmade = newjob;
-
- if (async)
- {
- if (newjob)
- {
- newjob->flags &= ~J_FOREGROUND;
- newjob->flags |= J_ASYNC;
- js.j_lastasync = newjob;
- }
- reset_current ();
- }
- else
- {
- if (newjob)
- {
- newjob->flags |= J_FOREGROUND;
- /*
- * !!!!! NOTE !!!!! (chet@ins.cwru.edu)
- *
- * The currently-accepted job control wisdom says to set the
- * terminal's process group n+1 times in an n-step pipeline:
- * once in the parent and once in each child. This is where
- * the parent gives it away.
- *
- */
- if (job_control && newjob->pgrp)
- give_terminal_to (newjob->pgrp, 0);
- }
- }
-
- stop_making_children ();
- UNBLOCK_CHILD (oset);
- return (js.j_current);
-}
-
-/* Functions to manage the list of exited background pids whose status has
- been saved. */
-
-static struct pidstat *
-bgp_alloc (pid, status)
- pid_t pid;
- int status;
-{
- struct pidstat *ps;
-
- ps = (struct pidstat *)xmalloc (sizeof (struct pidstat));
- ps->pid = pid;
- ps->status = status;
- ps->next = (struct pidstat *)0;
- return ps;
-}
-
-static struct pidstat *
-bgp_add (pid, status)
- pid_t pid;
- int status;
-{
- struct pidstat *ps;
-
- ps = bgp_alloc (pid, status);
-
- if (bgpids.list == 0)
- {
- bgpids.list = bgpids.end = ps;
- bgpids.npid = 0; /* just to make sure */
- }
- else
- {
- bgpids.end->next = ps;
- bgpids.end = ps;
- }
- bgpids.npid++;
-
- if (bgpids.npid > js.c_childmax)
- bgp_prune ();
-
- return ps;
-}
-
-static int
-bgp_delete (pid)
- pid_t pid;
-{
- struct pidstat *prev, *p;
-
- for (prev = p = bgpids.list; p; prev = p, p = p->next)
- if (p->pid == pid)
- {
- prev->next = p->next; /* remove from list */
- break;
- }
-
- if (p == 0)
- return 0; /* not found */
-
-#if defined (DEBUG)
- itrace("bgp_delete: deleting %d", pid);
-#endif
-
- /* Housekeeping in the border cases. */
- if (p == bgpids.list)
- bgpids.list = bgpids.list->next;
- else if (p == bgpids.end)
- bgpids.end = prev;
-
- bgpids.npid--;
- if (bgpids.npid == 0)
- bgpids.list = bgpids.end = 0;
- else if (bgpids.npid == 1)
- bgpids.end = bgpids.list; /* just to make sure */
-
- free (p);
- return 1;
-}
-
-/* Clear out the list of saved statuses */
-static void
-bgp_clear ()
-{
- struct pidstat *ps, *p;
-
- for (ps = bgpids.list; ps; )
- {
- p = ps;
- ps = ps->next;
- free (p);
- }
- bgpids.list = bgpids.end = 0;
- bgpids.npid = 0;
-}
-
-/* Search for PID in the list of saved background pids; return its status if
- found. If not found, return -1. */
-static int
-bgp_search (pid)
- pid_t pid;
-{
- struct pidstat *ps;
-
- for (ps = bgpids.list ; ps; ps = ps->next)
- if (ps->pid == pid)
- return ps->status;
- return -1;
-}
-
-static void
-bgp_prune ()
-{
- struct pidstat *ps, *p;
-
- while (bgpids.npid > js.c_childmax)
- {
- ps = bgpids.list;
- bgpids.list = bgpids.list->next;
- free (ps);
- bgpids.npid--;
- }
-}
-
-/* Reset the values of js.j_lastj and js.j_firstj after one or both have
- been deleted. The caller should check whether js.j_njobs is 0 before
- calling this. This wraps around, but the rest of the code does not. At
- this point, it should not matter. */
-static void
-reset_job_indices ()
-{
- int old;
-
- if (jobs[js.j_firstj] == 0)
- {
- old = js.j_firstj++;
- while (js.j_firstj != old)
- {
- if (js.j_firstj >= js.j_jobslots)
- js.j_firstj = 0;
- if (jobs[js.j_firstj])
- break;
- js.j_firstj++;
- }
- if (js.j_firstj == old)
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
- if (jobs[js.j_lastj] == 0)
- {
- old = js.j_lastj--;
- while (js.j_lastj != old)
- {
- if (js.j_lastj < 0)
- js.j_lastj = js.j_jobslots - 1;
- if (jobs[js.j_lastj])
- break;
- js.j_lastj--;
- }
- if (js.j_lastj == old)
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
-}
-
-/* Delete all DEAD jobs that the user had received notification about. */
-static void
-cleanup_dead_jobs ()
-{
- register int i;
- int os;
-
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return;
-
- QUEUE_SIGCHLD(os);
-
- /* XXX could use js.j_firstj and js.j_lastj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("cleanup_dead_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("cleanup_dead_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
-
- if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i))
- delete_job (i, 0);
- }
- UNQUEUE_SIGCHLD(os);
-}
-
-static int
-processes_in_job (job)
-{
- int nproc;
- register PROCESS *p;
-
- nproc = 0;
- p = jobs[job]->pipe;
- do
- {
- p = p->next;
- nproc++;
- }
- while (p != jobs[job]->pipe);
-
- return nproc;
-}
-
-static void
-delete_old_job (pid)
- pid_t pid;
-{
- PROCESS *p;
- int job;
-
- job = find_job (pid, 0, &p);
- if (job != NO_JOB)
- itrace ("delete_old_job: found pid %d in job %d with state %d", pid, job, jobs[job]->state);
-}
-
-/* Reallocate and compress the jobs list. This returns with a jobs array
- whose size is a multiple of JOB_SLOTS and can hold the current number of
- jobs. Heuristics are used to minimize the number of new reallocs. */
-static void
-realloc_jobs_list ()
-{
- sigset_t set, oset;
- int nsize, i, j, ncur, nprev;
- JOB **nlist;
-
- ncur = nprev = NO_JOB;
- nsize = ((js.j_njobs + JOB_SLOTS - 1) / JOB_SLOTS);
- nsize *= JOB_SLOTS;
- i = js.j_njobs % JOB_SLOTS;
- if (i == 0 || i > (JOB_SLOTS >> 1))
- nsize += JOB_SLOTS;
-
- BLOCK_CHILD (set, oset);
- nlist = (js.j_jobslots == nsize) ? jobs : (JOB **) xmalloc (nsize * sizeof (JOB *));
-
- for (i = j = 0; i < js.j_jobslots; i++)
- if (jobs[i])
- {
- if (i == js.j_current)
- ncur = j;
- if (i == js.j_previous)
- nprev = j;
- nlist[j++] = jobs[i];
- }
-
-#if defined (DEBUG)
- itrace ("realloc_jobs_list: resize jobs list from %d to %d", js.j_jobslots, nsize);
- itrace ("realloc_jobs_list: j_lastj changed from %d to %d", js.j_lastj, (j > 0) ? j - 1 : 0);
- itrace ("realloc_jobs_list: j_njobs changed from %d to %d", js.j_njobs, (j > 0) ? j - 1 : 0);
-#endif
-
- js.j_firstj = 0;
- js.j_lastj = (j > 0) ? j - 1 : 0;
- js.j_njobs = j;
- js.j_jobslots = nsize;
-
- /* Zero out remaining slots in new jobs list */
- for ( ; j < nsize; j++)
- nlist[j] = (JOB *)NULL;
-
- if (jobs != nlist)
- {
- free (jobs);
- jobs = nlist;
- }
-
- if (ncur != NO_JOB)
- js.j_current = ncur;
- if (nprev != NO_JOB)
- js.j_previous = nprev;
-
- /* Need to reset these */
- if (js.j_current == NO_JOB || js.j_previous == NO_JOB || js.j_current > js.j_lastj || js.j_previous > js.j_lastj)
- reset_current ();
-
-#ifdef DEBUG
- itrace ("realloc_jobs_list: reset js.j_current (%d) and js.j_previous (%d)", js.j_current, js.j_previous);
-#endif
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Compact the jobs list by removing dead jobs. Assumed that we have filled
- the jobs array to some predefined maximum. Called when the shell is not
- the foreground process (subshell_environment != 0). Returns the first
- available slot in the compacted list. If that value is js.j_jobslots, then
- the list needs to be reallocated. The jobs array may be in new memory if
- this returns > 0 and < js.j_jobslots. FLAGS is reserved for future use. */
-static int
-compact_jobs_list (flags)
- int flags;
-{
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return js.j_jobslots;
-
- reap_dead_jobs ();
- realloc_jobs_list ();
-
- return (js.j_lastj);
-}
-
-/* Delete the job at INDEX from the job list. Must be called
- with SIGCHLD blocked. */
-void
-delete_job (job_index, dflags)
- int job_index, dflags;
-{
- register JOB *temp;
- PROCESS *proc;
- int ndel, status;
- pid_t pid;
-
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return;
-
- if ((dflags & DEL_WARNSTOPPED) && subshell_environment == 0 && STOPPED (job_index))
- internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
- temp = jobs[job_index];
- if (temp == 0)
- return;
- if (job_index == js.j_current || job_index == js.j_previous)
- reset_current ();
-
- if ((dflags & DEL_NOBGPID) == 0)
- {
- proc = find_last_proc (job_index, 0);
- /* Could do this just for J_ASYNC jobs, but we save all. */
- if (proc)
- bgp_add (proc->pid, process_exit_status (proc->status));
- }
-
- jobs[job_index] = (JOB *)NULL;
- if (temp == js.j_lastmade)
- js.j_lastmade = 0;
- else if (temp == js.j_lastasync)
- js.j_lastasync = 0;
-
- free (temp->wd);
- ndel = discard_pipeline (temp->pipe);
-
- js.c_injobs -= ndel;
- if (temp->state == JDEAD)
- {
- js.c_reaped -= ndel;
- js.j_ndead--;
- if (js.c_reaped < 0)
- {
-#ifdef DEBUG
- itrace("delete_job (%d pgrp %d): js.c_reaped (%d) < 0 ndel = %d js.j_ndead = %d", job_index, temp->pgrp, js.c_reaped, ndel, js.j_ndead);
-#endif
- js.c_reaped = 0;
- }
- }
-
- if (temp->deferred)
- dispose_command (temp->deferred);
-
- free (temp);
-
- js.j_njobs--;
- if (js.j_njobs == 0)
- js.j_firstj = js.j_lastj = 0;
- else if (jobs[js.j_firstj] == 0 || jobs[js.j_lastj] == 0)
- reset_job_indices ();
-}
-
-/* Must be called with SIGCHLD blocked. */
-void
-nohup_job (job_index)
- int job_index;
-{
- register JOB *temp;
-
- if (js.j_jobslots == 0)
- return;
-
- if (temp = jobs[job_index])
- temp->flags |= J_NOHUP;
-}
-
-/* Get rid of the data structure associated with a process chain. */
-static int
-discard_pipeline (chain)
- register PROCESS *chain;
-{
- register PROCESS *this, *next;
- int n;
-
- this = chain;
- n = 0;
- do
- {
- next = this->next;
- FREE (this->command);
- free (this);
- n++;
- this = next;
- }
- while (this != chain);
-
- return n;
-}
-
-/* Add this process to the chain being built in the_pipeline.
- NAME is the command string that will be exec'ed later.
- PID is the process id of the child. */
-static void
-add_process (name, pid)
- char *name;
- pid_t pid;
-{
- PROCESS *t, *p;
-
-#if defined (RECYCLES_PIDS)
- int j;
- p = find_process (pid, 0, &j);
- if (p)
- {
-# ifdef DEBUG
- if (j == NO_JOB)
- internal_warning ("add_process: process %5ld (%s) in the_pipeline", (long)p->pid, p->command);
-# endif
- if (PALIVE (p))
- internal_warning ("add_process: pid %5ld (%s) marked as still alive", (long)p->pid, p->command);
- p->running = PS_RECYCLED; /* mark as recycled */
- }
-#endif
-
- t = (PROCESS *)xmalloc (sizeof (PROCESS));
- t->next = the_pipeline;
- t->pid = pid;
- WSTATUS (t->status) = 0;
- t->running = PS_RUNNING;
- t->command = name;
- the_pipeline = t;
-
- if (t->next == 0)
- t->next = t;
- else
- {
- p = t->next;
- while (p->next != t->next)
- p = p->next;
- p->next = t;
- }
-}
-
-#if 0
-/* Take the last job and make it the first job. Must be called with
- SIGCHLD blocked. */
-int
-rotate_the_pipeline ()
-{
- PROCESS *p;
-
- if (the_pipeline->next == the_pipeline)
- return;
- for (p = the_pipeline; p->next != the_pipeline; p = p->next)
- ;
- the_pipeline = p;
-}
-
-/* Reverse the order of the processes in the_pipeline. Must be called with
- SIGCHLD blocked. */
-int
-reverse_the_pipeline ()
-{
- PROCESS *p, *n;
-
- if (the_pipeline->next == the_pipeline)
- return;
-
- for (p = the_pipeline; p->next != the_pipeline; p = p->next)
- ;
- p->next = (PROCESS *)NULL;
-
- n = REVERSE_LIST (the_pipeline, PROCESS *);
-
- the_pipeline = n;
- for (p = the_pipeline; p->next; p = p->next)
- ;
- p->next = the_pipeline;
-}
-#endif
-
-/* Map FUNC over the list of jobs. If FUNC returns non-zero,
- then it is time to stop mapping, and that is the return value
- for map_over_jobs. FUNC is called with a JOB, arg1, arg2,
- and INDEX. */
-static int
-map_over_jobs (func, arg1, arg2)
- sh_job_map_func_t *func;
- int arg1, arg2;
-{
- register int i;
- int result;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return 0;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX could use js.j_firstj here */
- for (i = result = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("map_over_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("map_over_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i])
- {
- result = (*func)(jobs[i], arg1, arg2, i);
- if (result)
- break;
- }
- }
-
- UNBLOCK_CHILD (oset);
-
- return (result);
-}
-
-/* Cause all the jobs in the current pipeline to exit. */
-void
-terminate_current_pipeline ()
-{
- if (pipeline_pgrp && pipeline_pgrp != shell_pgrp)
- {
- killpg (pipeline_pgrp, SIGTERM);
- killpg (pipeline_pgrp, SIGCONT);
- }
-}
-
-/* Cause all stopped jobs to exit. */
-void
-terminate_stopped_jobs ()
-{
- register int i;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && STOPPED (i))
- {
- killpg (jobs[i]->pgrp, SIGTERM);
- killpg (jobs[i]->pgrp, SIGCONT);
- }
- }
-}
-
-/* Cause all jobs, running or stopped, to receive a hangup signal. If
- a job is marked J_NOHUP, don't send the SIGHUP. */
-void
-hangup_all_jobs ()
-{
- register int i;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i])
- {
- if ((jobs[i]->flags & J_NOHUP) == 0)
- killpg (jobs[i]->pgrp, SIGHUP);
- if (STOPPED (i))
- killpg (jobs[i]->pgrp, SIGCONT);
- }
- }
-}
-
-void
-kill_current_pipeline ()
-{
- stop_making_children ();
- start_pipeline ();
-}
-
-/* Return the pipeline that PID belongs to. Note that the pipeline
- doesn't have to belong to a job. Must be called with SIGCHLD blocked.
- If JOBP is non-null, return the index of the job containing PID. */
-static PROCESS *
-find_pipeline (pid, alive_only, jobp)
- pid_t pid;
- int alive_only;
- int *jobp; /* index into jobs list or NO_JOB */
-{
- int job;
- PROCESS *p;
-
- /* See if this process is in the pipeline that we are building. */
- if (jobp)
- *jobp = NO_JOB;
- if (the_pipeline)
- {
- p = the_pipeline;
- do
- {
- /* Return it if we found it. Don't ever return a recycled pid. */
- if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
- return (p);
-
- p = p->next;
- }
- while (p != the_pipeline);
- }
-
- job = find_job (pid, alive_only, &p);
- if (jobp)
- *jobp = job;
- return (job == NO_JOB) ? (PROCESS *)NULL : jobs[job]->pipe;
-}
-
-/* Return the PROCESS * describing PID. If JOBP is non-null return the index
- into the jobs array of the job containing PID. Must be called with
- SIGCHLD blocked. */
-static PROCESS *
-find_process (pid, alive_only, jobp)
- pid_t pid;
- int alive_only;
- int *jobp; /* index into jobs list or NO_JOB */
-{
- PROCESS *p;
-
- p = find_pipeline (pid, alive_only, jobp);
- while (p && p->pid != pid)
- p = p->next;
- return p;
-}
-
-/* Return the job index that PID belongs to, or NO_JOB if it doesn't
- belong to any job. Must be called with SIGCHLD blocked. */
-static int
-find_job (pid, alive_only, procp)
- pid_t pid;
- int alive_only;
- PROCESS **procp;
-{
- register int i;
- PROCESS *p;
-
- /* XXX could use js.j_firstj here, and should check js.j_lastj */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("find_job: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("find_job: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i])
- {
- p = jobs[i]->pipe;
-
- do
- {
- if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
- {
- if (procp)
- *procp = p;
- return (i);
- }
-
- p = p->next;
- }
- while (p != jobs[i]->pipe);
- }
- }
-
- return (NO_JOB);
-}
-
-/* Find a job given a PID. If BLOCK is non-zero, block SIGCHLD as
- required by find_job. */
-int
-get_job_by_pid (pid, block)
- pid_t pid;
- int block;
-{
- int job;
- sigset_t set, oset;
-
- if (block)
- BLOCK_CHILD (set, oset);
-
- job = find_job (pid, 0, NULL);
-
- if (block)
- UNBLOCK_CHILD (oset);
-
- return job;
-}
-
-/* Print descriptive information about the job with leader pid PID. */
-void
-describe_pid (pid)
- pid_t pid;
-{
- int job;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- job = find_job (pid, 0, NULL);
-
- if (job != NO_JOB)
- fprintf (stderr, "[%d] %ld\n", job + 1, (long)pid);
- else
- programming_error (_("describe_pid: %ld: no such pid"), (long)pid);
-
- UNBLOCK_CHILD (oset);
-}
-
-static char *
-j_strsignal (s)
- int s;
-{
- char *x;
-
- x = strsignal (s);
- if (x == 0)
- {
- x = retcode_name_buffer;
- sprintf (x, "Signal %d", s);
- }
- return x;
-}
-
-static char *
-printable_job_status (j, p, format)
- int j;
- PROCESS *p;
- int format;
-{
- static char *temp;
- int es;
-
- temp = "Done";
-
- if (STOPPED (j) && format == 0)
- {
- if (posixly_correct == 0 || p == 0 || (WIFSTOPPED (p->status) == 0))
- temp = "Stopped";
- else
- {
- temp = retcode_name_buffer;
- sprintf (temp, "Stopped(%s)", signal_name (WSTOPSIG (p->status)));
- }
- }
- else if (RUNNING (j))
- temp = "Running";
- else
- {
- if (WIFSTOPPED (p->status))
- temp = j_strsignal (WSTOPSIG (p->status));
- else if (WIFSIGNALED (p->status))
- temp = j_strsignal (WTERMSIG (p->status));
- else if (WIFEXITED (p->status))
- {
- temp = retcode_name_buffer;
- es = WEXITSTATUS (p->status);
- if (es == 0)
- strcpy (temp, "Done");
- else if (posixly_correct)
- sprintf (temp, "Done(%d)", es);
- else
- sprintf (temp, "Exit %d", es);
- }
- else
- temp = "Unknown status";
- }
-
- return temp;
-}
-
-/* This is the way to print out information on a job if you
- know the index. FORMAT is:
-
- JLIST_NORMAL) [1]+ Running emacs
- JLIST_LONG ) [1]+ 2378 Running emacs
- -1 ) [1]+ 2378 emacs
-
- JLIST_NORMAL) [1]+ Stopped ls | more
- JLIST_LONG ) [1]+ 2369 Stopped ls
- 2367 | more
- JLIST_PID_ONLY)
- Just list the pid of the process group leader (really
- the process group).
- JLIST_CHANGED_ONLY)
- Use format JLIST_NORMAL, but list only jobs about which
- the user has not been notified. */
-
-/* Print status for pipeline P. If JOB_INDEX is >= 0, it is the index into
- the JOBS array corresponding to this pipeline. FORMAT is as described
- above. Must be called with SIGCHLD blocked.
-
- If you're printing a pipeline that's not in the jobs array, like the
- current pipeline as it's being created, pass -1 for JOB_INDEX */
-static void
-print_pipeline (p, job_index, format, stream)
- PROCESS *p;
- int job_index, format;
- FILE *stream;
-{
- PROCESS *first, *last, *show;
- int es, name_padding;
- char *temp;
-
- if (p == 0)
- return;
-
- first = last = p;
- while (last->next != first)
- last = last->next;
-
- for (;;)
- {
- if (p != first)
- fprintf (stream, format ? " " : " |");
-
- if (format != JLIST_STANDARD)
- fprintf (stream, "%5ld", (long)p->pid);
-
- fprintf (stream, " ");
-
- if (format > -1 && job_index >= 0)
- {
- show = format ? p : last;
- temp = printable_job_status (job_index, show, format);
-
- if (p != first)
- {
- if (format)
- {
- if (show->running == first->running &&
- WSTATUS (show->status) == WSTATUS (first->status))
- temp = "";
- }
- else
- temp = (char *)NULL;
- }
-
- if (temp)
- {
- fprintf (stream, "%s", temp);
-
- es = STRLEN (temp);
- if (es == 0)
- es = 2; /* strlen ("| ") */
- name_padding = LONGEST_SIGNAL_DESC - es;
-
- fprintf (stream, "%*s", name_padding, "");
-
- if ((WIFSTOPPED (show->status) == 0) &&
- (WIFCONTINUED (show->status) == 0) &&
- WIFCORED (show->status))
- fprintf (stream, "(core dumped) ");
- }
- }
-
- if (p != first && format)
- fprintf (stream, "| ");
-
- if (p->command)
- fprintf (stream, "%s", p->command);
-
- if (p == last && job_index >= 0)
- {
- temp = current_working_directory ();
-
- if (RUNNING (job_index) && (IS_FOREGROUND (job_index) == 0))
- fprintf (stream, " &");
-
- if (strcmp (temp, jobs[job_index]->wd) != 0)
- fprintf (stream,
- " (wd: %s)", polite_directory_format (jobs[job_index]->wd));
- }
-
- if (format || (p == last))
- {
- /* We need to add a CR only if this is an interactive shell, and
- we're reporting the status of a completed job asynchronously.
- We can't really check whether this particular job is being
- reported asynchronously, so just add the CR if the shell is
- currently interactive and asynchronous notification is enabled. */
- if (asynchronous_notification && interactive)
- fprintf (stream, "\r\n");
- else
- fprintf (stream, "\n");
- }
-
- if (p == last)
- break;
- p = p->next;
- }
- fflush (stream);
-}
-
-/* Print information to STREAM about jobs[JOB_INDEX] according to FORMAT.
- Must be called with SIGCHLD blocked or queued with queue_sigchld */
-static void
-pretty_print_job (job_index, format, stream)
- int job_index, format;
- FILE *stream;
-{
- register PROCESS *p;
-
- /* Format only pid information about the process group leader? */
- if (format == JLIST_PID_ONLY)
- {
- fprintf (stream, "%ld\n", (long)jobs[job_index]->pipe->pid);
- return;
- }
-
- if (format == JLIST_CHANGED_ONLY)
- {
- if (IS_NOTIFIED (job_index))
- return;
- format = JLIST_STANDARD;
- }
-
- if (format != JLIST_NONINTERACTIVE)
- fprintf (stream, "[%d]%c ", job_index + 1,
- (job_index == js.j_current) ? '+':
- (job_index == js.j_previous) ? '-' : ' ');
-
- if (format == JLIST_NONINTERACTIVE)
- format = JLIST_LONG;
-
- p = jobs[job_index]->pipe;
-
- print_pipeline (p, job_index, format, stream);
-
- /* We have printed information about this job. When the job's
- status changes, waitchld () sets the notification flag to 0. */
- jobs[job_index]->flags |= J_NOTIFIED;
-}
-
-static int
-print_job (job, format, state, job_index)
- JOB *job;
- int format, state, job_index;
-{
- if (state == -1 || (JOB_STATE)state == job->state)
- pretty_print_job (job_index, format, stdout);
- return (0);
-}
-
-void
-list_one_job (job, format, ignore, job_index)
- JOB *job;
- int format, ignore, job_index;
-{
- pretty_print_job (job_index, format, stdout);
-}
-
-void
-list_stopped_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, (int)JSTOPPED);
-}
-
-void
-list_running_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, (int)JRUNNING);
-}
-
-/* List jobs. If FORMAT is non-zero, then the long form of the information
- is printed, else just a short version. */
-void
-list_all_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, -1);
-}
-
-/* Fork, handling errors. Returns the pid of the newly made child, or 0.
- COMMAND is just for remembering the name of the command; we don't do
- anything else with it. ASYNC_P says what to do with the tty. If
- non-zero, then don't give it away. */
-pid_t
-make_child (command, async_p)
- char *command;
- int async_p;
-{
- sigset_t set, oset;
- pid_t pid;
-
- sigemptyset (&set);
- sigaddset (&set, SIGCHLD);
- sigaddset (&set, SIGINT);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
-
- making_children ();
-
-#if defined (BUFFERED_INPUT)
- /* If default_buffered_input is active, we are reading a script. If
- the command is asynchronous, we have already duplicated /dev/null
- as fd 0, but have not changed the buffered stream corresponding to
- the old fd 0. We don't want to sync the stream in this case. */
- if (default_buffered_input != -1 &&
- (!async_p || default_buffered_input > 0))
- sync_buffered_stream (default_buffered_input);
-#endif /* BUFFERED_INPUT */
-
- /* Create the child, handle severe errors. */
- if ((pid = fork ()) < 0)
- {
- sys_error ("fork");
-
- /* Kill all of the processes in the current pipeline. */
- terminate_current_pipeline ();
-
- /* Discard the current pipeline, if any. */
- if (the_pipeline)
- kill_current_pipeline ();
-
- throw_to_top_level (); /* Reset signals, etc. */
- }
-
- if (pid == 0)
- {
- /* In the child. Give this child the right process group, set the
- signals to the default state for a new process. */
- pid_t mypid;
-
- mypid = getpid ();
-#if defined (BUFFERED_INPUT)
- /* Close default_buffered_input if it's > 0. We don't close it if it's
- 0 because that's the file descriptor used when redirecting input,
- and it's wrong to close the file in that case. */
- unset_bash_input (0);
-#endif /* BUFFERED_INPUT */
-
- /* Restore top-level signal mask. */
- sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
-
- if (job_control)
- {
- /* All processes in this pipeline belong in the same
- process group. */
-
- if (pipeline_pgrp == 0) /* This is the first child. */
- pipeline_pgrp = mypid;
-
- /* Check for running command in backquotes. */
- if (pipeline_pgrp == shell_pgrp)
- ignore_tty_job_signals ();
- else
- default_tty_job_signals ();
-
- /* Set the process group before trying to mess with the terminal's
- process group. This is mandated by POSIX. */
- /* This is in accordance with the Posix 1003.1 standard,
- section B.7.2.4, which says that trying to set the terminal
- process group with tcsetpgrp() to an unused pgrp value (like
- this would have for the first child) is an error. Section
- B.4.3.3, p. 237 also covers this, in the context of job control
- shells. */
- if (setpgid (mypid, pipeline_pgrp) < 0)
- sys_error ("child setpgid (%ld to %ld)", (long)mypid, (long)pipeline_pgrp);
-
- /* By convention (and assumption above), if
- pipeline_pgrp == shell_pgrp, we are making a child for
- command substitution.
- In this case, we don't want to give the terminal to the
- shell's process group (we could be in the middle of a
- pipeline, for example). */
- if (async_p == 0 && pipeline_pgrp != shell_pgrp)
- give_terminal_to (pipeline_pgrp, 0);
-
-#if defined (PGRP_PIPE)
- if (pipeline_pgrp == mypid)
- pipe_read (pgrp_pipe);
-#endif
- }
- else /* Without job control... */
- {
- if (pipeline_pgrp == 0)
- pipeline_pgrp = shell_pgrp;
-
- /* If these signals are set to SIG_DFL, we encounter the curious
- situation of an interactive ^Z to a running process *working*
- and stopping the process, but being unable to do anything with
- that process to change its state. On the other hand, if they
- are set to SIG_IGN, jobs started from scripts do not stop when
- the shell running the script gets a SIGTSTP and stops. */
-
- default_tty_job_signals ();
- }
-
-#if defined (PGRP_PIPE)
- /* Release the process group pipe, since our call to setpgid ()
- is done. The last call to pipe_close is done in stop_pipeline. */
- pipe_close (pgrp_pipe);
-#endif /* PGRP_PIPE */
-
- if (async_p)
- last_asynchronous_pid = mypid;
-#if defined (RECYCLES_PIDS)
- else if (last_asynchronous_pid == mypid)
- /* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
- last_asynchronous_pid = 1;
-#endif
- }
- else
- {
- /* In the parent. Remember the pid of the child just created
- as the proper pgrp if this is the first child. */
-
- if (first_pid == NO_PID)
- first_pid = pid;
- else if (pid_wrap == -1 && pid < first_pid)
-{
- pid_wrap = 0;
-itrace("make_child: PID CYCLE: first_pid = %d pid = %d", first_pid, pid);
-}
- else if (pid_wrap == 0 && pid >= first_pid)
-{
- pid_wrap = 1;
-itrace("make_child: PID WRAP: first_pid = %d pid = %d", first_pid, pid);
-}
-
- if (job_control)
- {
- if (pipeline_pgrp == 0)
- {
- pipeline_pgrp = pid;
- /* Don't twiddle terminal pgrps in the parent! This is the bug,
- not the good thing of twiddling them in the child! */
- /* give_terminal_to (pipeline_pgrp, 0); */
- }
- /* This is done on the recommendation of the Rationale section of
- the POSIX 1003.1 standard, where it discusses job control and
- shells. It is done to avoid possible race conditions. (Ref.
- 1003.1 Rationale, section B.4.3.3, page 236). */
- setpgid (pid, pipeline_pgrp);
- }
- else
- {
- if (pipeline_pgrp == 0)
- pipeline_pgrp = shell_pgrp;
- }
-
- /* Place all processes into the jobs array regardless of the
- state of job_control. */
- add_process (command, pid);
-
- if (async_p)
- last_asynchronous_pid = pid;
-#if defined (RECYCLES_PIDS)
- else if (last_asynchronous_pid == pid)
- /* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
- last_asynchronous_pid = 1;
-#endif
-
- if (pid_wrap > 0)
- delete_old_job (pid);
-
-#if !defined (RECYCLES_PIDS)
- /* Only check for saved status if we've saved more than CHILD_MAX
- statuses, unless the system recycles pids. */
- if ((js.c_reaped + bgpids.npid) >= js.c_childmax)
-#endif
- bgp_delete (pid); /* new process, discard any saved status */
-
- last_made_pid = pid;
-
- /* keep stats */
- js.c_totforked++;
- js.c_living++;
-
- /* Unblock SIGINT and SIGCHLD unless creating a pipeline, in which case
- SIGCHLD remains blocked until all commands in the pipeline have been
- created. */
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- }
-
- return (pid);
-}
-
-/* These two functions are called only in child processes. */
-void
-ignore_tty_job_signals ()
-{
- set_signal_handler (SIGTSTP, SIG_IGN);
- set_signal_handler (SIGTTIN, SIG_IGN);
- set_signal_handler (SIGTTOU, SIG_IGN);
-}
-
-void
-default_tty_job_signals ()
-{
- set_signal_handler (SIGTSTP, SIG_DFL);
- set_signal_handler (SIGTTIN, SIG_DFL);
- set_signal_handler (SIGTTOU, SIG_DFL);
-}
-
-/* When we end a job abnormally, or if we stop a job, we set the tty to the
- state kept in here. When a job ends normally, we set the state in here
- to the state of the tty. */
-
-static TTYSTRUCT shell_tty_info;
-
-#if defined (NEW_TTY_DRIVER)
-static struct tchars shell_tchars;
-static struct ltchars shell_ltchars;
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (NEW_TTY_DRIVER) && defined (DRAIN_OUTPUT)
-/* Since the BSD tty driver does not allow us to change the tty modes
- while simultaneously waiting for output to drain and preserving
- typeahead, we have to drain the output ourselves before calling
- ioctl. We cheat by finding the length of the output queue, and
- using select to wait for an appropriate length of time. This is
- a hack, and should be labeled as such (it's a hastily-adapted
- mutation of a `usleep' implementation). It's only reason for
- existing is the flaw in the BSD tty driver. */
-
-static int ttspeeds[] =
-{
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
- 1800, 2400, 4800, 9600, 19200, 38400
-};
-
-static void
-draino (fd, ospeed)
- int fd, ospeed;
-{
- register int delay = ttspeeds[ospeed];
- int n;
-
- if (!delay)
- return;
-
- while ((ioctl (fd, TIOCOUTQ, &n) == 0) && n)
- {
- if (n > (delay / 100))
- {
- struct timeval tv;
-
- n *= 10; /* 2 bits more for conservativeness. */
- tv.tv_sec = n / delay;
- tv.tv_usec = ((n % delay) * 1000000) / delay;
- select (fd, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
- }
- else
- break;
- }
-}
-#endif /* NEW_TTY_DRIVER && DRAIN_OUTPUT */
-
-/* Return the fd from which we are actually getting input. */
-#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
-
-/* Fill the contents of shell_tty_info with the current tty info. */
-int
-get_tty_state ()
-{
- int tty;
-
- tty = input_tty ();
- if (tty != -1)
- {
-#if defined (NEW_TTY_DRIVER)
- ioctl (tty, TIOCGETP, &shell_tty_info);
- ioctl (tty, TIOCGETC, &shell_tchars);
- ioctl (tty, TIOCGLTC, &shell_ltchars);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
- ioctl (tty, TCGETA, &shell_tty_info);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
- if (tcgetattr (tty, &shell_tty_info) < 0)
- {
-#if 0
- /* Only print an error message if we're really interactive at
- this time. */
- if (interactive)
- sys_error ("[%ld: %d] tcgetattr", (long)getpid (), shell_level);
-#endif
- return -1;
- }
-#endif /* TERMIOS_TTY_DRIVER */
- if (check_window_size)
- get_new_window_size (0, (int *)0, (int *)0);
- }
- return 0;
-}
-
-/* Make the current tty use the state in shell_tty_info. */
-int
-set_tty_state ()
-{
- int tty;
-
- tty = input_tty ();
- if (tty != -1)
- {
-#if defined (NEW_TTY_DRIVER)
-# if defined (DRAIN_OUTPUT)
- draino (tty, shell_tty_info.sg_ospeed);
-# endif /* DRAIN_OUTPUT */
- ioctl (tty, TIOCSETN, &shell_tty_info);
- ioctl (tty, TIOCSETC, &shell_tchars);
- ioctl (tty, TIOCSLTC, &shell_ltchars);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
- ioctl (tty, TCSETAW, &shell_tty_info);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
- if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
- {
- /* Only print an error message if we're really interactive at
- this time. */
- if (interactive)
- sys_error ("[%ld: %d] tcsetattr", (long)getpid (), shell_level);
- return -1;
- }
-#endif /* TERMIOS_TTY_DRIVER */
- }
- return 0;
-}
-
-/* Given an index into the jobs array JOB, return the PROCESS struct of the last
- process in that job's pipeline. This is the one whose exit status
- counts. Must be called with SIGCHLD blocked or queued. */
-static PROCESS *
-find_last_proc (job, block)
- int job;
- int block;
-{
- register PROCESS *p;
- sigset_t set, oset;
-
- if (block)
- BLOCK_CHILD (set, oset);
-
- p = jobs[job]->pipe;
- while (p && p->next != jobs[job]->pipe)
- p = p->next;
-
- if (block)
- UNBLOCK_CHILD (oset);
-
- return (p);
-}
-
-static pid_t
-find_last_pid (job, block)
- int job;
- int block;
-{
- PROCESS *p;
-
- p = find_last_proc (job, block);
- /* Possible race condition here. */
- return p->pid;
-}
-
-/* Wait for a particular child of the shell to finish executing.
- This low-level function prints an error message if PID is not
- a child of this shell. It returns -1 if it fails, or whatever
- wait_for returns otherwise. If the child is not found in the
- jobs table, it returns 127. */
-int
-wait_for_single_pid (pid)
- pid_t pid;
-{
- register PROCESS *child;
- sigset_t set, oset;
- int r, job;
-
- BLOCK_CHILD (set, oset);
- child = find_pipeline (pid, 0, (int *)NULL);
- UNBLOCK_CHILD (oset);
-
- if (child == 0)
- {
- r = bgp_search (pid);
- if (r >= 0)
- return r;
- }
-
- if (child == 0)
- {
- internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
- return (127);
- }
-
- r = wait_for (pid);
-
- /* POSIX.2: if we just waited for a job, we can remove it from the jobs
- table. */
- BLOCK_CHILD (set, oset);
- job = find_job (pid, 0, NULL);
- if (job != NO_JOB && jobs[job] && DEADJOB (job))
- jobs[job]->flags |= J_NOTIFIED;
- UNBLOCK_CHILD (oset);
-
- /* If running in posix mode, remove the job from the jobs table immediately */
- if (posixly_correct)
- {
- cleanup_dead_jobs ();
- bgp_delete (pid);
- }
-
- return r;
-}
-
-/* Wait for all of the backgrounds of this shell to finish. */
-void
-wait_for_background_pids ()
-{
- register int i, r, waited_for;
- sigset_t set, oset;
- pid_t pid;
-
- for (waited_for = 0;;)
- {
- BLOCK_CHILD (set, oset);
-
- /* find first running job; if none running in foreground, break */
- /* XXX could use js.j_firstj and js.j_lastj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("wait_for_background_pids: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("wait_for_background_pids: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0)
- break;
- }
- if (i == js.j_jobslots)
- {
- UNBLOCK_CHILD (oset);
- break;
- }
-
- /* now wait for the last pid in that job. */
- pid = find_last_pid (i, 0);
- UNBLOCK_CHILD (oset);
- QUIT;
- errno = 0; /* XXX */
- r = wait_for_single_pid (pid);
- if (r == -1)
- {
- /* If we're mistaken about job state, compensate. */
- if (errno == ECHILD)
- mark_all_jobs_as_dead ();
- }
- else
- waited_for++;
- }
-
- /* POSIX.2 says the shell can discard the statuses of all completed jobs if
- `wait' is called with no arguments. */
- mark_dead_jobs_as_notified (1);
- cleanup_dead_jobs ();
- bgp_clear ();
-}
-
-/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
-#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
-static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
-
-static void
-restore_sigint_handler ()
-{
- if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
- {
- set_signal_handler (SIGINT, old_sigint_handler);
- old_sigint_handler = INVALID_SIGNAL_HANDLER;
- }
-}
-
-static int wait_sigint_received;
-
-/* Handle SIGINT while we are waiting for children in a script to exit.
- The `wait' builtin should be interruptible, but all others should be
- effectively ignored (i.e. not cause the shell to exit). */
-static sighandler
-wait_sigint_handler (sig)
- int sig;
-{
- SigHandler *sigint_handler;
-
- if (interrupt_immediately ||
- (this_shell_builtin && this_shell_builtin == wait_builtin))
- {
- last_command_exit_value = EXECUTION_FAILURE;
- restore_sigint_handler ();
- /* If we got a SIGINT while in `wait', and SIGINT is trapped, do
- what POSIX.2 says (see builtins/wait.def for more info). */
- if (this_shell_builtin && this_shell_builtin == wait_builtin &&
- signal_is_trapped (SIGINT) &&
- ((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler))
- {
- interrupt_immediately = 0;
- trap_handler (SIGINT); /* set pending_traps[SIGINT] */
- wait_signal_received = SIGINT;
- longjmp (wait_intr_buf, 1);
- }
-
- ADDINTERRUPT;
- QUIT;
- }
-
- /* XXX - should this be interrupt_state? If it is, the shell will act
- as if it got the SIGINT interrupt. */
- wait_sigint_received = 1;
-
- /* Otherwise effectively ignore the SIGINT and allow the running job to
- be killed. */
- SIGRETURN (0);
-}
-
-static int
-process_exit_signal (status)
- WAIT status;
-{
- return (WIFSIGNALED (status) ? WTERMSIG (status) : 0);
-}
-
-static int
-process_exit_status (status)
- WAIT status;
-{
- if (WIFSIGNALED (status))
- return (128 + WTERMSIG (status));
- else if (WIFSTOPPED (status) == 0)
- return (WEXITSTATUS (status));
- else
- return (EXECUTION_SUCCESS);
-}
-
-/* Return the exit status of the last process in the pipeline for job JOB.
- This is the exit status of the entire job. */
-static WAIT
-raw_job_exit_status (job)
- int job;
-{
- register PROCESS *p;
- int fail;
-
- if (pipefail_opt)
- {
- fail = 0;
- p = jobs[job]->pipe;
- do
- {
- if (p->status != EXECUTION_SUCCESS) fail = p->status;
- p = p->next;
- }
- while (p != jobs[job]->pipe);
- return fail;
- }
-
- for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
- ;
- return (p->status);
-}
-
-/* Return the exit status of job JOB. This is the exit status of the last
- (rightmost) process in the job's pipeline, modified if the job was killed
- by a signal or stopped. */
-static int
-job_exit_status (job)
- int job;
-{
- return (process_exit_status (raw_job_exit_status (job)));
-}
-
-static int
-job_exit_signal (job)
- int job;
-{
- return (process_exit_signal (raw_job_exit_status (job)));
-}
-
-#define FIND_CHILD(pid, child) \
- do \
- { \
- child = find_pipeline (pid, 0, (int *)NULL); \
- if (child == 0) \
- { \
- give_terminal_to (shell_pgrp, 0); \
- UNBLOCK_CHILD (oset); \
- internal_error (_("wait_for: No record of process %ld"), (long)pid); \
- restore_sigint_handler (); \
- return (termination_state = 127); \
- } \
- } \
- while (0)
-
-/* Wait for pid (one of our children) to terminate, then
- return the termination state. Returns 127 if PID is not found in
- the jobs table. Returns -1 if waitchld() returns -1, indicating
- that there are no unwaited-for child processes. */
-int
-wait_for (pid)
- pid_t pid;
-{
- int job, termination_state, r;
- WAIT s;
- register PROCESS *child;
- sigset_t set, oset;
- register PROCESS *p;
-
- /* In the case that this code is interrupted, and we longjmp () out of it,
- we are relying on the code in throw_to_top_level () to restore the
- top-level signal mask. */
- BLOCK_CHILD (set, oset);
-
- /* Ignore interrupts while waiting for a job run without job control
- to finish. We don't want the shell to exit if an interrupt is
- received, only if one of the jobs run is killed via SIGINT. If
- job control is not set, the job will be run in the same pgrp as
- the shell, and the shell will see any signals the job gets. */
-
- /* This is possibly a race condition -- should it go in stop_pipeline? */
- wait_sigint_received = 0;
- if (job_control == 0)
- old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
-
- termination_state = last_command_exit_value;
-
- if (interactive && job_control == 0)
- QUIT;
-
- /* If we say wait_for (), then we have a record of this child somewhere.
- If it and none of its peers are running, don't call waitchld(). */
-
- job = NO_JOB;
- do
- {
- FIND_CHILD (pid, child);
-
- /* If this child is part of a job, then we are really waiting for the
- job to finish. Otherwise, we are waiting for the child to finish.
- We check for JDEAD in case the job state has been set by waitchld
- after receipt of a SIGCHLD. */
- if (job == NO_JOB)
- job = find_job (pid, 0, NULL);
-
- /* waitchld() takes care of setting the state of the job. If the job
- has already exited before this is called, sigchld_handler will have
- called waitchld and the state will be set to JDEAD. */
-
- if (PRUNNING(child) || (job != NO_JOB && RUNNING (job)))
- {
-#if defined (WAITPID_BROKEN) /* SCOv4 */
- sigset_t suspend_set;
- sigemptyset (&suspend_set);
- sigsuspend (&suspend_set);
-#else /* !WAITPID_BROKEN */
-# if defined (MUST_UNBLOCK_CHLD)
- struct sigaction act, oact;
- sigset_t nullset, chldset;
-
- sigemptyset (&nullset);
- sigemptyset (&chldset);
- sigprocmask (SIG_SETMASK, &nullset, &chldset);
- act.sa_handler = SIG_DFL;
- sigemptyset (&act.sa_mask);
- sigemptyset (&oact.sa_mask);
- act.sa_flags = 0;
- sigaction (SIGCHLD, &act, &oact);
-# endif
- queue_sigchld = 1;
- r = waitchld (pid, 1);
-# if defined (MUST_UNBLOCK_CHLD)
- sigaction (SIGCHLD, &oact, (struct sigaction *)NULL);
- sigprocmask (SIG_SETMASK, &chldset, (sigset_t *)NULL);
-# endif
- queue_sigchld = 0;
- if (r == -1 && errno == ECHILD && this_shell_builtin == wait_builtin)
- {
- termination_state = -1;
- goto wait_for_return;
- }
-
- /* If child is marked as running, but waitpid() returns -1/ECHILD,
- there is something wrong. Somewhere, wait should have returned
- that child's pid. Mark the child as not running and the job,
- if it exists, as JDEAD. */
- if (r == -1 && errno == ECHILD)
- {
- child->running = PS_DONE;
- child->status = 0; /* XXX -- can't find true status */
- js.c_living = 0; /* no living child processes */
- if (job != NO_JOB)
- {
- jobs[job]->state = JDEAD;
- js.c_reaped++;
- js.j_ndead++;
- }
- }
-#endif /* WAITPID_BROKEN */
- }
-
- /* If the shell is interactive, and job control is disabled, see
- if the foreground process has died due to SIGINT and jump out
- of the wait loop if it has. waitchld has already restored the
- old SIGINT signal handler. */
- if (interactive && job_control == 0)
- QUIT;
- }
- while (PRUNNING (child) || (job != NO_JOB && RUNNING (job)));
-
- /* The exit state of the command is either the termination state of the
- child, or the termination state of the job. If a job, the status
- of the last child in the pipeline is the significant one. If the command
- or job was terminated by a signal, note that value also. */
- termination_state = (job != NO_JOB) ? job_exit_status (job)
- : process_exit_status (child->status);
- last_command_exit_signal = (job != NO_JOB) ? job_exit_signal (job)
- : process_exit_signal (child->status);
-
- /* XXX */
- if ((job != NO_JOB && JOBSTATE (job) == JSTOPPED) || WIFSTOPPED (child->status))
- termination_state = 128 + WSTOPSIG (child->status);
-
- if (job == NO_JOB || IS_JOBCONTROL (job))
- {
- /* XXX - under what circumstances is a job not present in the jobs
- table (job == NO_JOB)?
- 1. command substitution
-
- In the case of command substitution, at least, it's probably not
- the right thing to give the terminal to the shell's process group,
- even though there is code in subst.c:command_substitute to work
- around it.
-
- Things that don't:
- $PROMPT_COMMAND execution
- process substitution
- */
-#if 0
-if (job == NO_JOB)
- itrace("wait_for: job == NO_JOB, giving the terminal to shell_pgrp (%ld)", (long)shell_pgrp);
-#endif
-
- give_terminal_to (shell_pgrp, 0);
- }
-
- /* If the command did not exit cleanly, or the job is just
- being stopped, then reset the tty state back to what it
- was before this command. Reset the tty state and notify
- the user of the job termination only if the shell is
- interactive. Clean up any dead jobs in either case. */
- if (job != NO_JOB)
- {
- if (interactive_shell && subshell_environment == 0)
- {
- /* This used to use `child->status'. That's wrong, however, for
- pipelines. `child' is the first process in the pipeline. It's
- likely that the process we want to check for abnormal termination
- or stopping is the last process in the pipeline, especially if
- it's long-lived and the first process is short-lived. Since we
- know we have a job here, we can check all the processes in this
- job's pipeline and see if one of them stopped or terminated due
- to a signal. We might want to change this later to just check
- the last process in the pipeline. If no process exits due to a
- signal, S is left as the status of the last job in the pipeline. */
- p = jobs[job]->pipe;
- do
- {
- s = p->status;
- if (WIFSIGNALED(s) || WIFSTOPPED(s))
- break;
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- if (WIFSIGNALED (s) || WIFSTOPPED (s))
- {
- set_tty_state ();
-
- /* If the current job was stopped or killed by a signal, and
- the user has requested it, get a possibly new window size */
- if (check_window_size && (job == js.j_current || IS_FOREGROUND (job)))
- get_new_window_size (0, (int *)0, (int *)0);
- }
- else
- get_tty_state ();
-
- /* If job control is enabled, the job was started with job
- control, the job was the foreground job, and it was killed
- by SIGINT, then print a newline to compensate for the kernel
- printing the ^C without a trailing newline. */
- if (job_control && IS_JOBCONTROL (job) && IS_FOREGROUND (job) &&
- WIFSIGNALED (s) && WTERMSIG (s) == SIGINT)
- {
- /* If SIGINT is not trapped and the shell is in a for, while,
- or until loop, act as if the shell received SIGINT as
- well, so the loop can be broken. This doesn't call the
- SIGINT signal handler; maybe it should. */
- if (signal_is_trapped (SIGINT) == 0 && loop_level)
- ADDINTERRUPT;
- else
- {
- putchar ('\n');
- fflush (stdout);
- }
- }
- }
-
- /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
- signal handler path */
- if (DEADJOB (job) && IS_FOREGROUND (job) /*&& subshell_environment == 0*/)
- setjstatus (job);
-
- /* If this job is dead, notify the user of the status. If the shell
- is interactive, this will display a message on the terminal. If
- the shell is not interactive, make sure we turn on the notify bit
- so we don't get an unwanted message about the job's termination,
- and so delete_job really clears the slot in the jobs table. */
- notify_and_cleanup ();
- }
-
-wait_for_return:
-
- UNBLOCK_CHILD (oset);
-
- /* Restore the original SIGINT signal handler before we return. */
- restore_sigint_handler ();
-
- return (termination_state);
-}
-
-/* Wait for the last process in the pipeline for JOB. Returns whatever
- wait_for returns: the last process's termination state or -1 if there
- are no unwaited-for child processes or an error occurs. */
-int
-wait_for_job (job)
- int job;
-{
- pid_t pid;
- int r;
- sigset_t set, oset;
-
- BLOCK_CHILD(set, oset);
- if (JOBSTATE (job) == JSTOPPED)
- internal_warning (_("wait_for_job: job %d is stopped"), job+1);
-
- pid = find_last_pid (job, 0);
- UNBLOCK_CHILD(oset);
- r = wait_for (pid);
-
- /* POSIX.2: we can remove the job from the jobs table if we just waited
- for it. */
- BLOCK_CHILD (set, oset);
- if (job != NO_JOB && jobs[job] && DEADJOB (job))
- jobs[job]->flags |= J_NOTIFIED;
- UNBLOCK_CHILD (oset);
-
- return r;
-}
-
-/* Print info about dead jobs, and then delete them from the list
- of known jobs. This does not actually delete jobs when the
- shell is not interactive, because the dead jobs are not marked
- as notified. */
-void
-notify_and_cleanup ()
-{
- if (jobs_list_frozen)
- return;
-
- if (interactive || interactive_shell == 0 || sourcelevel)
- notify_of_job_status ();
-
- cleanup_dead_jobs ();
-}
-
-/* Make dead jobs disappear from the jobs array without notification.
- This is used when the shell is not interactive. */
-void
-reap_dead_jobs ()
-{
- mark_dead_jobs_as_notified (0);
- cleanup_dead_jobs ();
-}
-
-/* Return the next closest (chronologically) job to JOB which is in
- STATE. STATE can be JSTOPPED, JRUNNING. NO_JOB is returned if
- there is no next recent job. */
-static int
-most_recent_job_in_state (job, state)
- int job;
- JOB_STATE state;
-{
- register int i, result;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- for (result = NO_JOB, i = job - 1; i >= 0; i--)
- {
- if (jobs[i] && (JOBSTATE (i) == state))
- {
- result = i;
- break;
- }
- }
-
- UNBLOCK_CHILD (oset);
-
- return (result);
-}
-
-/* Return the newest *stopped* job older than JOB, or NO_JOB if not
- found. */
-static int
-job_last_stopped (job)
- int job;
-{
- return (most_recent_job_in_state (job, JSTOPPED));
-}
-
-/* Return the newest *running* job older than JOB, or NO_JOB if not
- found. */
-static int
-job_last_running (job)
- int job;
-{
- return (most_recent_job_in_state (job, JRUNNING));
-}
-
-/* Make JOB be the current job, and make previous be useful. Must be
- called with SIGCHLD blocked. */
-static void
-set_current_job (job)
- int job;
-{
- int candidate;
-
- if (js.j_current != job)
- {
- js.j_previous = js.j_current;
- js.j_current = job;
- }
-
- /* First choice for previous job is the old current job. */
- if (js.j_previous != js.j_current &&
- js.j_previous != NO_JOB &&
- jobs[js.j_previous] &&
- STOPPED (js.j_previous))
- return;
-
- /* Second choice: Newest stopped job that is older than
- the current job. */
- candidate = NO_JOB;
- if (STOPPED (js.j_current))
- {
- candidate = job_last_stopped (js.j_current);
-
- if (candidate != NO_JOB)
- {
- js.j_previous = candidate;
- return;
- }
- }
-
- /* If we get here, there is either only one stopped job, in which case it is
- the current job and the previous job should be set to the newest running
- job, or there are only running jobs and the previous job should be set to
- the newest running job older than the current job. We decide on which
- alternative to use based on whether or not JOBSTATE(js.j_current) is
- JSTOPPED. */
-
- candidate = RUNNING (js.j_current) ? job_last_running (js.j_current)
- : job_last_running (js.j_jobslots);
-
- if (candidate != NO_JOB)
- {
- js.j_previous = candidate;
- return;
- }
-
- /* There is only a single job, and it is both `+' and `-'. */
- js.j_previous = js.j_current;
-}
-
-/* Make current_job be something useful, if it isn't already. */
-
-/* Here's the deal: The newest non-running job should be `+', and the
- next-newest non-running job should be `-'. If there is only a single
- stopped job, the js.j_previous is the newest non-running job. If there
- are only running jobs, the newest running job is `+' and the
- next-newest running job is `-'. Must be called with SIGCHLD blocked. */
-
-static void
-reset_current ()
-{
- int candidate;
-
- if (js.j_jobslots && js.j_current != NO_JOB && jobs[js.j_current] && STOPPED (js.j_current))
- candidate = js.j_current;
- else
- {
- candidate = NO_JOB;
-
- /* First choice: the previous job. */
- if (js.j_previous != NO_JOB && jobs[js.j_previous] && STOPPED (js.j_previous))
- candidate = js.j_previous;
-
- /* Second choice: the most recently stopped job. */
- if (candidate == NO_JOB)
- candidate = job_last_stopped (js.j_jobslots);
-
- /* Third choice: the newest running job. */
- if (candidate == NO_JOB)
- candidate = job_last_running (js.j_jobslots);
- }
-
- /* If we found a job to use, then use it. Otherwise, there
- are no jobs period. */
- if (candidate != NO_JOB)
- set_current_job (candidate);
- else
- js.j_current = js.j_previous = NO_JOB;
-}
-
-/* Set up the job structures so we know the job and its processes are
- all running. */
-static void
-set_job_running (job)
- int job;
-{
- register PROCESS *p;
-
- /* Each member of the pipeline is now running. */
- p = jobs[job]->pipe;
-
- do
- {
- if (WIFSTOPPED (p->status))
- p->running = PS_RUNNING; /* XXX - could be PS_STOPPED */
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- /* This means that the job is running. */
- JOBSTATE (job) = JRUNNING;
-}
-
-/* Start a job. FOREGROUND if non-zero says to do that. Otherwise,
- start the job in the background. JOB is a zero-based index into
- JOBS. Returns -1 if it is unable to start a job, and the return
- status of the job otherwise. */
-int
-start_job (job, foreground)
- int job, foreground;
-{
- register PROCESS *p;
- int already_running;
- sigset_t set, oset;
- char *wd, *s;
- static TTYSTRUCT save_stty;
-
- BLOCK_CHILD (set, oset);
-
- if (DEADJOB (job))
- {
- internal_error (_("%s: job has terminated"), this_command_name);
- UNBLOCK_CHILD (oset);
- return (-1);
- }
-
- already_running = RUNNING (job);
-
- if (foreground == 0 && already_running)
- {
- internal_error (_("%s: job %d already in background"), this_command_name, job + 1);
- UNBLOCK_CHILD (oset);
- return (0); /* XPG6/SUSv3 says this is not an error */
- }
-
- wd = current_working_directory ();
-
- /* You don't know about the state of this job. Do you? */
- jobs[job]->flags &= ~J_NOTIFIED;
-
- if (foreground)
- {
- set_current_job (job);
- jobs[job]->flags |= J_FOREGROUND;
- }
-
- /* Tell the outside world what we're doing. */
- p = jobs[job]->pipe;
-
- if (foreground == 0)
- {
- /* POSIX.2 says `bg' doesn't give any indication about current or
- previous job. */
- if (posixly_correct == 0)
- s = (job == js.j_current) ? "+ ": ((job == js.j_previous) ? "- " : " ");
- else
- s = " ";
- printf ("[%d]%s", job + 1, s);
- }
-
- do
- {
- printf ("%s%s",
- p->command ? p->command : "",
- p->next != jobs[job]->pipe? " | " : "");
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- if (foreground == 0)
- printf (" &");
-
- if (strcmp (wd, jobs[job]->wd) != 0)
- printf (" (wd: %s)", polite_directory_format (jobs[job]->wd));
-
- printf ("\n");
-
- /* Run the job. */
- if (already_running == 0)
- set_job_running (job);
-
- /* Save the tty settings before we start the job in the foreground. */
- if (foreground)
- {
- get_tty_state ();
- save_stty = shell_tty_info;
- /* Give the terminal to this job. */
- if (IS_JOBCONTROL (job))
- give_terminal_to (jobs[job]->pgrp, 0);
- }
- else
- jobs[job]->flags &= ~J_FOREGROUND;
-
- /* If the job is already running, then don't bother jump-starting it. */
- if (already_running == 0)
- {
- jobs[job]->flags |= J_NOTIFIED;
- killpg (jobs[job]->pgrp, SIGCONT);
- }
-
- if (foreground)
- {
- pid_t pid;
- int s;
-
- pid = find_last_pid (job, 0);
- UNBLOCK_CHILD (oset);
- s = wait_for (pid);
- shell_tty_info = save_stty;
- set_tty_state ();
- return (s);
- }
- else
- {
- reset_current ();
- UNBLOCK_CHILD (oset);
- return (0);
- }
-}
-
-/* Give PID SIGNAL. This determines what job the pid belongs to (if any).
- If PID does belong to a job, and the job is stopped, then CONTinue the
- job after giving it SIGNAL. Returns -1 on failure. If GROUP is non-null,
- then kill the process group associated with PID. */
-int
-kill_pid (pid, sig, group)
- pid_t pid;
- int sig, group;
-{
- register PROCESS *p;
- int job, result, negative;
- sigset_t set, oset;
-
- if (pid < -1)
- {
- pid = -pid;
- group = negative = 1;
- }
- else
- negative = 0;
-
- result = EXECUTION_SUCCESS;
- if (group)
- {
- BLOCK_CHILD (set, oset);
- p = find_pipeline (pid, 0, &job);
-
- if (job != NO_JOB)
- {
- jobs[job]->flags &= ~J_NOTIFIED;
-
- /* Kill process in backquotes or one started without job control? */
-
- /* If we're passed a pid < -1, just call killpg and see what happens */
- if (negative && jobs[job]->pgrp == shell_pgrp)
- result = killpg (pid, sig);
- /* If we're killing using job control notification, for example,
- without job control active, we have to do things ourselves. */
- else if (jobs[job]->pgrp == shell_pgrp)
- {
- p = jobs[job]->pipe;
- do
- {
- if (PALIVE (p) == 0)
- continue; /* avoid pid recycling problem */
- kill (p->pid, sig);
- if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
- kill (p->pid, SIGCONT);
- p = p->next;
- }
- while (p != jobs[job]->pipe);
- }
- else
- {
- result = killpg (jobs[job]->pgrp, sig);
- if (p && STOPPED (job) && (sig == SIGTERM || sig == SIGHUP))
- killpg (jobs[job]->pgrp, SIGCONT);
- /* If we're continuing a stopped job via kill rather than bg or
- fg, emulate the `bg' behavior. */
- if (p && STOPPED (job) && (sig == SIGCONT))
- {
- set_job_running (job);
- jobs[job]->flags &= ~J_FOREGROUND;
- jobs[job]->flags |= J_NOTIFIED;
- }
- }
- }
- else
- result = killpg (pid, sig);
-
- UNBLOCK_CHILD (oset);
- }
- else
- result = kill (pid, sig);
-
- return (result);
-}
-
-/* sigchld_handler () flushes at least one of the children that we are
- waiting for. It gets run when we have gotten a SIGCHLD signal. */
-static sighandler
-sigchld_handler (sig)
- int sig;
-{
- int n, oerrno;
-
- oerrno = errno;
- REINSTALL_SIGCHLD_HANDLER;
- sigchld++;
- n = 0;
- if (queue_sigchld == 0)
- n = waitchld (-1, 0);
- errno = oerrno;
- SIGRETURN (n);
-}
-
-/* waitchld() reaps dead or stopped children. It's called by wait_for and
- sigchld_handler, and runs until there aren't any children terminating any
- more.
- If BLOCK is 1, this is to be a blocking wait for a single child, although
- an arriving SIGCHLD could cause the wait to be non-blocking. It returns
- the number of children reaped, or -1 if there are no unwaited-for child
- processes. */
-static int
-waitchld (wpid, block)
- pid_t wpid;
- int block;
-{
- WAIT status;
- PROCESS *child;
- pid_t pid;
- int call_set_current, last_stopped_job, job, children_exited, waitpid_flags;
- static int wcontinued = WCONTINUED; /* run-time fix for glibc problem */
-
- call_set_current = children_exited = 0;
- last_stopped_job = NO_JOB;
-
- do
- {
- /* We don't want to be notified about jobs stopping if job control
- is not active. XXX - was interactive_shell instead of job_control */
- waitpid_flags = (job_control && subshell_environment == 0)
- ? (WUNTRACED|wcontinued)
- : 0;
- if (sigchld || block == 0)
- waitpid_flags |= WNOHANG;
- pid = WAITPID (-1, &status, waitpid_flags);
-
- /* WCONTINUED may be rejected by waitpid as invalid even when defined */
- if (wcontinued && pid < 0 && errno == EINVAL)
- {
- wcontinued = 0;
- continue; /* jump back to the test and retry without WCONTINUED */
- }
-
- /* The check for WNOHANG is to make sure we decrement sigchld only
- if it was non-zero before we called waitpid. */
- if (sigchld > 0 && (waitpid_flags & WNOHANG))
- sigchld--;
-
- /* If waitpid returns -1 with errno == ECHILD, there are no more
- unwaited-for child processes of this shell. */
- if (pid < 0 && errno == ECHILD)
- {
- if (children_exited == 0)
- return -1;
- else
- break;
- }
-
- /* If waitpid returns 0, there are running children. If it returns -1,
- the only other error POSIX says it can return is EINTR. */
- if (pid <= 0)
- continue; /* jumps right to the test */
-
- /* children_exited is used to run traps on SIGCHLD. We don't want to
- run the trap if a process is just being continued. */
- if (WIFCONTINUED(status) == 0)
- {
- children_exited++;
- js.c_living--;
- }
-
- /* Locate our PROCESS for this pid. */
- child = find_process (pid, 1, &job); /* want living procs only */
-
- /* It is not an error to have a child terminate that we did
- not have a record of. This child could have been part of
- a pipeline in backquote substitution. Even so, I'm not
- sure child is ever non-zero. */
- if (child == 0)
- continue;
-
- /* Remember status, and whether or not the process is running. */
- child->status = status;
- child->running = WIFCONTINUED(status) ? PS_RUNNING : PS_DONE;
-
- if (PEXITED (child))
- {
- js.c_totreaped++;
- if (job != NO_JOB)
- js.c_reaped++;
- }
-
- if (job == NO_JOB)
- continue;
-
- call_set_current += set_job_status_and_cleanup (job);
-
- if (STOPPED (job))
- last_stopped_job = job;
- else if (DEADJOB (job) && last_stopped_job == job)
- last_stopped_job = NO_JOB;
- }
- while ((sigchld || block == 0) && pid > (pid_t)0);
-
- /* If a job was running and became stopped, then set the current
- job. Otherwise, don't change a thing. */
- if (call_set_current)
- {
- if (last_stopped_job != NO_JOB)
- set_current_job (last_stopped_job);
- else
- reset_current ();
- }
-
- /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
- if (job_control && signal_is_trapped (SIGCHLD) && children_exited &&
- trap_list[SIGCHLD] != (char *)IGNORE_SIG)
- run_sigchld_trap (children_exited);
-
- /* We have successfully recorded the useful information about this process
- that has just changed state. If we notify asynchronously, and the job
- that this process belongs to is no longer running, then notify the user
- of that fact now. */
- if (asynchronous_notification && interactive)
- notify_of_job_status ();
-
- return (children_exited);
-}
-
-/* Set the status of JOB and perform any necessary cleanup if the job is
- marked as JDEAD.
-
- Currently, the cleanup activity is restricted to handling any SIGINT
- received while waiting for a foreground job to finish. */
-static int
-set_job_status_and_cleanup (job)
- int job;
-{
- PROCESS *child;
- int tstatus, job_state, any_stopped, any_tstped, call_set_current;
- SigHandler *temp_handler;
-
- child = jobs[job]->pipe;
- jobs[job]->flags &= ~J_NOTIFIED;
-
- call_set_current = 0;
-
- /*
- * COMPUTE JOB STATUS
- */
-
- /* If all children are not running, but any of them is stopped, then
- the job is stopped, not dead. */
- job_state = any_stopped = any_tstped = 0;
- do
- {
- job_state |= PRUNNING (child);
-#if 0
- if (PEXITED (child) && (WIFSTOPPED (child->status)))
-#else
- /* Only checking for WIFSTOPPED now, not for PS_DONE */
- if (PSTOPPED (child))
-#endif
- {
- any_stopped = 1;
- any_tstped |= interactive && job_control &&
- (WSTOPSIG (child->status) == SIGTSTP);
- }
- child = child->next;
- }
- while (child != jobs[job]->pipe);
-
- /* If job_state != 0, the job is still running, so don't bother with
- setting the process exit status and job state unless we're
- transitioning from stopped to running. */
- if (job_state != 0 && JOBSTATE(job) != JSTOPPED)
- return 0;
-
- /*
- * SET JOB STATUS
- */
-
- /* The job is either stopped or dead. Set the state of the job accordingly. */
- if (any_stopped)
- {
- jobs[job]->state = JSTOPPED;
- jobs[job]->flags &= ~J_FOREGROUND;
- call_set_current++;
- /* Suspending a job with SIGTSTP breaks all active loops. */
- if (any_tstped && loop_level)
- breaking = loop_level;
- }
- else if (job_state != 0) /* was stopped, now running */
- {
- jobs[job]->state = JRUNNING;
- call_set_current++;
- }
- else
- {
- jobs[job]->state = JDEAD;
- js.j_ndead++;
-
-#if 0
- if (IS_FOREGROUND (job))
- setjstatus (job);
-#endif
-
- /* If this job has a cleanup function associated with it, call it
- with `cleanarg' as the single argument, then set the function
- pointer to NULL so it is not inadvertently called twice. The
- cleanup function is responsible for deallocating cleanarg. */
- if (jobs[job]->j_cleanup)
- {
- (*jobs[job]->j_cleanup) (jobs[job]->cleanarg);
- jobs[job]->j_cleanup = (sh_vptrfunc_t *)NULL;
- }
- }
-
- /*
- * CLEANUP
- *
- * Currently, we just do special things if we got a SIGINT while waiting
- * for a foreground job to complete
- */
-
- if (JOBSTATE (job) == JDEAD)
- {
- /* If we're running a shell script and we get a SIGINT with a
- SIGINT trap handler, but the foreground job handles it and
- does not exit due to SIGINT, run the trap handler but do not
- otherwise act as if we got the interrupt. */
- if (wait_sigint_received && interactive_shell == 0 &&
- WIFSIGNALED (child->status) == 0 && IS_FOREGROUND (job) &&
- signal_is_trapped (SIGINT))
- {
- int old_frozen;
- wait_sigint_received = 0;
- last_command_exit_value = process_exit_status (child->status);
-
- old_frozen = jobs_list_frozen;
- jobs_list_frozen = 1;
- tstatus = maybe_call_trap_handler (SIGINT);
- jobs_list_frozen = old_frozen;
- }
-
- /* If the foreground job is killed by SIGINT when job control is not
- active, we need to perform some special handling.
-
- The check of wait_sigint_received is a way to determine if the
- SIGINT came from the keyboard (in which case the shell has already
- seen it, and wait_sigint_received is non-zero, because keyboard
- signals are sent to process groups) or via kill(2) to the foreground
- process by another process (or itself). If the shell did receive the
- SIGINT, it needs to perform normal SIGINT processing. */
- else if (wait_sigint_received && (WTERMSIG (child->status) == SIGINT) &&
- IS_FOREGROUND (job) && IS_JOBCONTROL (job) == 0)
- {
- int old_frozen;
-
- wait_sigint_received = 0;
-
- /* If SIGINT is trapped, set the exit status so that the trap
- handler can see it. */
- if (signal_is_trapped (SIGINT))
- last_command_exit_value = process_exit_status (child->status);
-
- /* If the signal is trapped, let the trap handler get it no matter
- what and simply return if the trap handler returns.
- maybe_call_trap_handler() may cause dead jobs to be removed from
- the job table because of a call to execute_command. We work
- around this by setting JOBS_LIST_FROZEN. */
- old_frozen = jobs_list_frozen;
- jobs_list_frozen = 1;
- tstatus = maybe_call_trap_handler (SIGINT);
- jobs_list_frozen = old_frozen;
- if (tstatus == 0 && old_sigint_handler != INVALID_SIGNAL_HANDLER)
- {
- /* wait_sigint_handler () has already seen SIGINT and
- allowed the wait builtin to jump out. We need to
- call the original SIGINT handler, if necessary. If
- the original handler is SIG_DFL, we need to resend
- the signal to ourselves. */
-
- temp_handler = old_sigint_handler;
-
- /* Bogus. If we've reset the signal handler as the result
- of a trap caught on SIGINT, then old_sigint_handler
- will point to trap_handler, which now knows nothing about
- SIGINT (if we reset the sighandler to the default).
- In this case, we have to fix things up. What a crock. */
- if (temp_handler == trap_handler && signal_is_trapped (SIGINT) == 0)
- temp_handler = trap_to_sighandler (SIGINT);
- restore_sigint_handler ();
- if (temp_handler == SIG_DFL)
- termination_unwind_protect (SIGINT);
- else if (temp_handler != SIG_IGN)
- (*temp_handler) (SIGINT);
- }
- }
- }
-
- return call_set_current;
-}
-
-/* Build the array of values for the $PIPESTATUS variable from the set of
- exit statuses of all processes in the job J. */
-static void
-setjstatus (j)
- int j;
-{
-#if defined (ARRAY_VARS)
- register int i;
- register PROCESS *p;
-
- for (i = 1, p = jobs[j]->pipe; p->next != jobs[j]->pipe; p = p->next, i++)
- ;
- i++;
- if (statsize < i)
- {
- pstatuses = (int *)xrealloc (pstatuses, i * sizeof (int));
- statsize = i;
- }
- i = 0;
- p = jobs[j]->pipe;
- do
- {
- pstatuses[i++] = process_exit_status (p->status);
- p = p->next;
- }
- while (p != jobs[j]->pipe);
-
- pstatuses[i] = -1; /* sentinel */
- set_pipestatus_array (pstatuses, i);
-#endif
-}
-
-static void
-run_sigchld_trap (nchild)
- int nchild;
-{
- char *trap_command;
- int i;
-
- /* Turn off the trap list during the call to parse_and_execute ()
- to avoid potentially infinite recursive calls. Preserve the
- values of last_command_exit_value, last_made_pid, and the_pipeline
- around the execution of the trap commands. */
- trap_command = savestring (trap_list[SIGCHLD]);
-
- begin_unwind_frame ("SIGCHLD trap");
- unwind_protect_int (last_command_exit_value);
- unwind_protect_int (last_command_exit_signal);
- unwind_protect_var (last_made_pid);
- unwind_protect_int (interrupt_immediately);
- unwind_protect_int (jobs_list_frozen);
- unwind_protect_pointer (the_pipeline);
- unwind_protect_pointer (subst_assign_varlist);
-
- /* We have to add the commands this way because they will be run
- in reverse order of adding. We don't want maybe_set_sigchld_trap ()
- to reference freed memory. */
- add_unwind_protect (xfree, trap_command);
- add_unwind_protect (maybe_set_sigchld_trap, trap_command);
-
- subst_assign_varlist = (WORD_LIST *)NULL;
- the_pipeline = (PROCESS *)NULL;
-
- restore_default_signal (SIGCHLD);
- jobs_list_frozen = 1;
- for (i = 0; i < nchild; i++)
- {
- interrupt_immediately = 1;
- parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE);
- }
-
- run_unwind_frame ("SIGCHLD trap");
-}
-
-/* Function to call when you want to notify people of changes
- in job status. This prints out all jobs which are pending
- notification to stderr, and marks those printed as already
- notified, thus making them candidates for cleanup. */
-static void
-notify_of_job_status ()
-{
- register int job, termsig;
- char *dir;
- sigset_t set, oset;
- WAIT s;
-
- if (jobs == 0 || js.j_jobslots == 0)
- return;
-
- if (old_ttou != 0)
- {
- sigemptyset (&set);
- sigaddset (&set, SIGCHLD);
- sigaddset (&set, SIGTTOU);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
- }
- else
- queue_sigchld++;
-
- /* XXX could use js.j_firstj here */
- for (job = 0, dir = (char *)NULL; job < js.j_jobslots; job++)
- {
- if (jobs[job] && IS_NOTIFIED (job) == 0)
- {
- s = raw_job_exit_status (job);
- termsig = WTERMSIG (s);
-
- /* POSIX.2 says we have to hang onto the statuses of at most the
- last CHILD_MAX background processes if the shell is running a
- script. If the shell is running a script, either from a file
- or standard input, don't print anything unless the job was
- killed by a signal. */
- if (startup_state == 0 && WIFSIGNALED (s) == 0 &&
- ((DEADJOB (job) && IS_FOREGROUND (job) == 0) || STOPPED (job)))
- continue;
-
-#if 0
- /* If job control is disabled, don't print the status messages.
- Mark dead jobs as notified so that they get cleaned up. If
- startup_state == 2, we were started to run `-c command', so
- don't print anything. */
- if ((job_control == 0 && interactive_shell) || startup_state == 2)
-#else
- /* If job control is disabled, don't print the status messages.
- Mark dead jobs as notified so that they get cleaned up. If
- startup_state == 2 and subshell_environment has the
- SUBSHELL_COMSUB bit turned on, we were started to run a command
- substitution, so don't print anything. */
- if ((job_control == 0 && interactive_shell) ||
- (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)))
-#endif
- {
- /* POSIX.2 compatibility: if the shell is not interactive,
- hang onto the job corresponding to the last asynchronous
- pid until the user has been notified of its status or does
- a `wait'. */
- if (DEADJOB (job) && (interactive_shell || (find_last_pid (job, 0) != last_asynchronous_pid)))
- jobs[job]->flags |= J_NOTIFIED;
- continue;
- }
-
- /* Print info on jobs that are running in the background,
- and on foreground jobs that were killed by anything
- except SIGINT (and possibly SIGPIPE). */
- switch (JOBSTATE (job))
- {
- case JDEAD:
- if (interactive_shell == 0 && termsig && WIFSIGNALED (s) &&
- termsig != SIGINT &&
-#if defined (DONT_REPORT_SIGPIPE)
- termsig != SIGPIPE &&
-#endif
- signal_is_trapped (termsig) == 0)
- {
- /* Don't print `0' for a line number. */
- fprintf (stderr, "%s: line %d: ", get_name_for_error (), (line_number == 0) ? 1 : line_number);
- pretty_print_job (job, JLIST_NONINTERACTIVE, stderr);
- }
- else if (IS_FOREGROUND (job))
- {
-#if !defined (DONT_REPORT_SIGPIPE)
- if (termsig && WIFSIGNALED (s) && termsig != SIGINT)
-#else
- if (termsig && WIFSIGNALED (s) && termsig != SIGINT && termsig != SIGPIPE)
-#endif
- {
- fprintf (stderr, "%s", j_strsignal (termsig));
-
- if (WIFCORED (s))
- fprintf (stderr, " (core dumped)");
-
- fprintf (stderr, "\n");
- }
- }
- else if (job_control) /* XXX job control test added */
- {
- if (dir == 0)
- dir = current_working_directory ();
- pretty_print_job (job, JLIST_STANDARD, stderr);
- if (dir && strcmp (dir, jobs[job]->wd) != 0)
- fprintf (stderr,
- "(wd now: %s)\n", polite_directory_format (dir));
- }
-
- jobs[job]->flags |= J_NOTIFIED;
- break;
-
- case JSTOPPED:
- fprintf (stderr, "\n");
- if (dir == 0)
- dir = current_working_directory ();
- pretty_print_job (job, JLIST_STANDARD, stderr);
- if (dir && (strcmp (dir, jobs[job]->wd) != 0))
- fprintf (stderr,
- "(wd now: %s)\n", polite_directory_format (dir));
- jobs[job]->flags |= J_NOTIFIED;
- break;
-
- case JRUNNING:
- case JMIXED:
- break;
-
- default:
- programming_error ("notify_of_job_status");
- }
- }
- }
- if (old_ttou != 0)
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- else
- queue_sigchld--;
-}
-
-/* Initialize the job control mechanism, and set up the tty stuff. */
-int
-initialize_job_control (force)
- int force;
-{
- shell_pgrp = getpgid (0);
-
- if (shell_pgrp == -1)
- {
- sys_error ("initialize_job_control: getpgrp failed");
- exit (1);
- }
-
- /* We can only have job control if we are interactive. */
- if (interactive == 0)
- {
- job_control = 0;
- original_pgrp = NO_PID;
- shell_tty = fileno (stderr);
- }
- else
- {
- /* Get our controlling terminal. If job_control is set, or
- interactive is set, then this is an interactive shell no
- matter where fd 2 is directed. */
- shell_tty = dup (fileno (stderr)); /* fd 2 */
-
- shell_tty = move_to_high_fd (shell_tty, 1, -1);
-
- /* Compensate for a bug in systems that compiled the BSD
- rlogind with DEBUG defined, like NeXT and Alliant. */
- if (shell_pgrp == 0)
- {
- shell_pgrp = getpid ();
- setpgid (0, shell_pgrp);
- tcsetpgrp (shell_tty, shell_pgrp);
- }
-
- while ((terminal_pgrp = tcgetpgrp (shell_tty)) != -1)
- {
- if (shell_pgrp != terminal_pgrp)
- {
- SigHandler *ottin;
-
- ottin = set_signal_handler(SIGTTIN, SIG_DFL);
- kill (0, SIGTTIN);
- set_signal_handler (SIGTTIN, ottin);
- continue;
- }
- break;
- }
-
- /* Make sure that we are using the new line discipline. */
- if (set_new_line_discipline (shell_tty) < 0)
- {
- sys_error ("initialize_job_control: line discipline");
- job_control = 0;
- }
- else
- {
- original_pgrp = shell_pgrp;
- shell_pgrp = getpid ();
-
- if ((original_pgrp != shell_pgrp) && (setpgid (0, shell_pgrp) < 0))
- {
- sys_error ("initialize_job_control: setpgid");
- shell_pgrp = original_pgrp;
- }
-
- job_control = 1;
-
- /* If (and only if) we just set our process group to our pid,
- thereby becoming a process group leader, and the terminal
- is not in the same process group as our (new) process group,
- then set the terminal's process group to our (new) process
- group. If that fails, set our process group back to what it
- was originally (so we can still read from the terminal) and
- turn off job control. */
- if (shell_pgrp != original_pgrp && shell_pgrp != terminal_pgrp)
- {
- if (give_terminal_to (shell_pgrp, 0) < 0)
- {
- setpgid (0, original_pgrp);
- shell_pgrp = original_pgrp;
- job_control = 0;
- }
- }
- }
- if (job_control == 0)
- internal_error (_("no job control in this shell"));
- }
-
- if (shell_tty != fileno (stderr))
- SET_CLOSE_ON_EXEC (shell_tty);
-
- set_signal_handler (SIGCHLD, sigchld_handler);
-
- change_flag ('m', job_control ? '-' : '+');
-
- if (interactive)
- get_tty_state ();
-
- if (js.c_childmax < 0)
- js.c_childmax = getmaxchild ();
- if (js.c_childmax < 0)
- js.c_childmax = DEFAULT_CHILD_MAX;
-
- return job_control;
-}
-
-#ifdef DEBUG
-void
-debug_print_pgrps ()
-{
- itrace("original_pgrp = %ld shell_pgrp = %ld terminal_pgrp = %ld",
- (long)original_pgrp, (long)shell_pgrp, (long)terminal_pgrp);
- itrace("tcgetpgrp(%d) -> %ld, getpgid(0) -> %ld",
- shell_tty, (long)tcgetpgrp (shell_tty), (long)getpgid(0));
-}
-#endif
-
-/* Set the line discipline to the best this system has to offer.
- Return -1 if this is not possible. */
-static int
-set_new_line_discipline (tty)
- int tty;
-{
-#if defined (NEW_TTY_DRIVER)
- int ldisc;
-
- if (ioctl (tty, TIOCGETD, &ldisc) < 0)
- return (-1);
-
- if (ldisc != NTTYDISC)
- {
- ldisc = NTTYDISC;
-
- if (ioctl (tty, TIOCSETD, &ldisc) < 0)
- return (-1);
- }
- return (0);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
-# if defined (TERMIO_LDISC) && (NTTYDISC)
- if (ioctl (tty, TCGETA, &shell_tty_info) < 0)
- return (-1);
-
- if (shell_tty_info.c_line != NTTYDISC)
- {
- shell_tty_info.c_line = NTTYDISC;
- if (ioctl (tty, TCSETAW, &shell_tty_info) < 0)
- return (-1);
- }
-# endif /* TERMIO_LDISC && NTTYDISC */
- return (0);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
-# if defined (TERMIOS_LDISC) && defined (NTTYDISC)
- if (tcgetattr (tty, &shell_tty_info) < 0)
- return (-1);
-
- if (shell_tty_info.c_line != NTTYDISC)
- {
- shell_tty_info.c_line = NTTYDISC;
- if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
- return (-1);
- }
-# endif /* TERMIOS_LDISC && NTTYDISC */
- return (0);
-#endif /* TERMIOS_TTY_DRIVER */
-
-#if !defined (NEW_TTY_DRIVER) && !defined (TERMIO_TTY_DRIVER) && !defined (TERMIOS_TTY_DRIVER)
- return (-1);
-#endif
-}
-
-/* Setup this shell to handle C-C, etc. */
-void
-initialize_job_signals ()
-{
- if (interactive)
- {
- set_signal_handler (SIGINT, sigint_sighandler);
- set_signal_handler (SIGTSTP, SIG_IGN);
- set_signal_handler (SIGTTOU, SIG_IGN);
- set_signal_handler (SIGTTIN, SIG_IGN);
- }
- else if (job_control)
- {
- old_tstp = set_signal_handler (SIGTSTP, sigstop_sighandler);
- old_ttin = set_signal_handler (SIGTTIN, sigstop_sighandler);
- old_ttou = set_signal_handler (SIGTTOU, sigstop_sighandler);
- }
- /* Leave these things alone for non-interactive shells without job
- control. */
-}
-
-/* Here we handle CONT signals. */
-static sighandler
-sigcont_sighandler (sig)
- int sig;
-{
- initialize_job_signals ();
- set_signal_handler (SIGCONT, old_cont);
- kill (getpid (), SIGCONT);
-
- SIGRETURN (0);
-}
-
-/* Here we handle stop signals while we are running not as a login shell. */
-static sighandler
-sigstop_sighandler (sig)
- int sig;
-{
- set_signal_handler (SIGTSTP, old_tstp);
- set_signal_handler (SIGTTOU, old_ttou);
- set_signal_handler (SIGTTIN, old_ttin);
-
- old_cont = set_signal_handler (SIGCONT, sigcont_sighandler);
-
- give_terminal_to (shell_pgrp, 0);
-
- kill (getpid (), sig);
-
- SIGRETURN (0);
-}
-
-/* Give the terminal to PGRP. */
-int
-give_terminal_to (pgrp, force)
- pid_t pgrp;
- int force;
-{
- sigset_t set, oset;
- int r;
-
- r = 0;
- if (job_control || force)
- {
- sigemptyset (&set);
- sigaddset (&set, SIGTTOU);
- sigaddset (&set, SIGTTIN);
- sigaddset (&set, SIGTSTP);
- sigaddset (&set, SIGCHLD);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
-
- if (tcsetpgrp (shell_tty, pgrp) < 0)
- {
- /* Maybe we should print an error message? */
-#if 0
- sys_error ("tcsetpgrp(%d) failed: pid %ld to pgrp %ld",
- shell_tty, (long)getpid(), (long)pgrp);
-#endif
- r = -1;
- }
- else
- terminal_pgrp = pgrp;
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- }
-
- return r;
-}
-
-/* Clear out any jobs in the job array. This is intended to be used by
- children of the shell, who should not have any job structures as baggage
- when they start executing (forking subshells for parenthesized execution
- and functions with pipes are the two that spring to mind). If RUNNING_ONLY
- is nonzero, only running jobs are removed from the table. */
-void
-delete_all_jobs (running_only)
- int running_only;
-{
- register int i;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX - need to set j_lastj, j_firstj appropriately if running_only != 0. */
- if (js.j_jobslots)
- {
- js.j_current = js.j_previous = NO_JOB;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("delete_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("delete_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
- delete_job (i, DEL_WARNSTOPPED);
- }
- if (running_only == 0)
- {
- free ((char *)jobs);
- js.j_jobslots = 0;
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
- }
-
- if (running_only == 0)
- bgp_clear ();
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Mark all jobs in the job array so that they don't get a SIGHUP when the
- shell gets one. If RUNNING_ONLY is nonzero, mark only running jobs. */
-void
-nohup_all_jobs (running_only)
- int running_only;
-{
- register int i;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- if (js.j_jobslots)
- {
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
- nohup_job (i);
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-int
-count_all_jobs ()
-{
- int i, n;
- sigset_t set, oset;
-
- /* This really counts all non-dead jobs. */
- BLOCK_CHILD (set, oset);
- /* XXX could use js.j_firstj here */
- for (i = n = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("count_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i] && DEADJOB(i) == 0)
- n++;
- }
- UNBLOCK_CHILD (oset);
- return n;
-}
-
-static void
-mark_all_jobs_as_dead ()
-{
- register int i;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- if (jobs[i])
- {
- jobs[i]->state = JDEAD;
- js.j_ndead++;
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Mark all dead jobs as notified, so delete_job () cleans them out
- of the job table properly. POSIX.2 says we need to save the
- status of the last CHILD_MAX jobs, so we count the number of dead
- jobs and mark only enough as notified to save CHILD_MAX statuses. */
-static void
-mark_dead_jobs_as_notified (force)
- int force;
-{
- register int i, ndead, ndeadproc;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return;
-
- BLOCK_CHILD (set, oset);
-
- /* If FORCE is non-zero, we don't have to keep CHILD_MAX statuses
- around; just run through the array. */
- if (force)
- {
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
- jobs[i]->flags |= J_NOTIFIED;
- }
- UNBLOCK_CHILD (oset);
- return;
- }
-
- /* Mark enough dead jobs as notified to keep CHILD_MAX processes left in the
- array with the corresponding not marked as notified. This is a better
- way to avoid pid aliasing and reuse problems than keeping the POSIX-
- mandated CHILD_MAX jobs around. delete_job() takes care of keeping the
- bgpids list regulated. */
-
- /* Count the number of dead jobs */
- /* XXX could use js.j_firstj here */
- for (i = ndead = ndeadproc = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i] && DEADJOB (i))
- {
- ndead++;
- ndeadproc += processes_in_job (i);
- }
- }
-
-#ifdef DEBUG
- if (ndeadproc != js.c_reaped)
- itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped);
- if (ndead != js.j_ndead)
- itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead);
-#endif
-
- if (js.c_childmax < 0)
- js.c_childmax = getmaxchild ();
- if (js.c_childmax < 0)
- js.c_childmax = DEFAULT_CHILD_MAX;
-
- /* Don't do anything if the number of dead processes is less than CHILD_MAX
- and we're not forcing a cleanup. */
- if (ndeadproc <= js.c_childmax)
- {
- UNBLOCK_CHILD (oset);
- return;
- }
-
-#if 0
-itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", js.c_childmax, ndead, ndeadproc);
-#endif
-
- /* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
- the list. This isn't exactly right yet; changes need to be made
- to stop_pipeline so we don't mark the newer jobs after we've
- created CHILD_MAX slots in the jobs array. This needs to be
- integrated with a way to keep the jobs array from growing without
- bound. Maybe we wrap back around to 0 after we reach some max
- limit, and there are sufficient job slots free (keep track of total
- size of jobs array (js.j_jobslots) and running count of number of jobs
- in jobs array. Then keep a job index corresponding to the `oldest job'
- and start this loop there, wrapping around as necessary. In effect,
- we turn the list into a circular buffer. */
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- /* If marking this job as notified would drop us down below
- child_max, don't mark it so we can keep at least child_max
- statuses. XXX -- need to check what Posix actually says
- about keeping statuses. */
- if ((ndeadproc -= processes_in_job (i)) <= js.c_childmax)
- break;
- jobs[i]->flags |= J_NOTIFIED;
- }
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Here to allow other parts of the shell (like the trap stuff) to
- unfreeze the jobs list. */
-void
-unfreeze_jobs_list ()
-{
- jobs_list_frozen = 0;
-}
-
-/* Allow or disallow job control to take place. Returns the old value
- of job_control. */
-int
-set_job_control (arg)
- int arg;
-{
- int old;
-
- old = job_control;
- job_control = arg;
-
- /* If we're turning on job control, reset pipeline_pgrp so make_child will
- put new child processes into the right pgrp */
- if (job_control != old && job_control)
- pipeline_pgrp = 0;
-
- return (old);
-}
-
-/* Turn off all traces of job control. This is run by children of the shell
- which are going to do shellsy things, like wait (), etc. */
-void
-without_job_control ()
-{
- stop_making_children ();
- start_pipeline ();
-#if defined (PGRP_PIPE)
- pipe_close (pgrp_pipe);
-#endif
- delete_all_jobs (0);
- set_job_control (0);
-}
-
-/* If this shell is interactive, terminate all stopped jobs and
- restore the original terminal process group. This is done
- before the `exec' builtin calls shell_execve. */
-void
-end_job_control ()
-{
- if (interactive_shell) /* XXX - should it be interactive? */
- {
- terminate_stopped_jobs ();
-
- if (original_pgrp >= 0)
- give_terminal_to (original_pgrp, 1);
- }
-
- if (original_pgrp >= 0)
- setpgid (0, original_pgrp);
-}
-
-/* Restart job control by closing shell tty and reinitializing. This is
- called after an exec fails in an interactive shell and we do not exit. */
-void
-restart_job_control ()
-{
- if (shell_tty != -1)
- close (shell_tty);
- initialize_job_control (0);
-}
-
-/* Set the handler to run when the shell receives a SIGCHLD signal. */
-void
-set_sigchld_handler ()
-{
- set_signal_handler (SIGCHLD, sigchld_handler);
-}
-
-#if defined (PGRP_PIPE)
-/* Read from the read end of a pipe. This is how the process group leader
- blocks until all of the processes in a pipeline have been made. */
-static void
-pipe_read (pp)
- int *pp;
-{
- char ch;
-
- if (pp[1] >= 0)
- {
- close (pp[1]);
- pp[1] = -1;
- }
-
- if (pp[0] >= 0)
- {
- while (read (pp[0], &ch, 1) == -1 && errno == EINTR)
- ;
- }
-}
-
-/* Close the read and write ends of PP, an array of file descriptors. */
-static void
-pipe_close (pp)
- int *pp;
-{
- if (pp[0] >= 0)
- close (pp[0]);
-
- if (pp[1] >= 0)
- close (pp[1]);
-
- pp[0] = pp[1] = -1;
-}
-
-/* Functional interface closes our local-to-job-control pipes. */
-void
-close_pgrp_pipe ()
-{
- pipe_close (pgrp_pipe);
-}
-
-#endif /* PGRP_PIPE */
diff --git a/jobs.c~ b/jobs.c~
deleted file mode 100644
index 9a970cd9..00000000
--- a/jobs.c~
+++ /dev/null
@@ -1,4067 +0,0 @@
-/* The thing that makes children, remembers them, and contains wait loops. */
-
-/* This file works with both POSIX and BSD systems. It implements job
- control. */
-
-/* Copyright (C) 1989-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 "bashtypes.h"
-#include "trap.h"
-#include <stdio.h>
-#include <signal.h>
-#include <errno.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "posixtime.h"
-
-#if defined (HAVE_SYS_RESOURCE_H) && defined (HAVE_WAIT3) && !defined (_POSIX_VERSION) && !defined (RLIMTYPE)
-# include <sys/resource.h>
-#endif /* !_POSIX_VERSION && HAVE_SYS_RESOURCE_H && HAVE_WAIT3 && !RLIMTYPE */
-
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-
-#include "filecntl.h"
-#include <sys/ioctl.h>
-#include <sys/param.h>
-
-#if defined (BUFFERED_INPUT)
-# include "input.h"
-#endif
-
-/* Need to include this up here for *_TTY_DRIVER definitions. */
-#include "shtty.h"
-
-/* Define this if your output is getting swallowed. It's a no-op on
- machines with the termio or termios tty drivers. */
-/* #define DRAIN_OUTPUT */
-
-/* For the TIOCGPGRP and TIOCSPGRP ioctl parameters on HP-UX */
-#if defined (hpux) && !defined (TERMIOS_TTY_DRIVER)
-# include <bsdtty.h>
-#endif /* hpux && !TERMIOS_TTY_DRIVER */
-
-#include "bashansi.h"
-#include "bashintl.h"
-#include "shell.h"
-#include "jobs.h"
-#include "flags.h"
-
-#include "builtins/builtext.h"
-#include "builtins/common.h"
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#define DEFAULT_CHILD_MAX 32
-#if !defined (DEBUG)
-#define MAX_JOBS_IN_ARRAY 4096 /* production */
-#else
-#define MAX_JOBS_IN_ARRAY 128 /* testing */
-#endif
-
-/* Flag values for second argument to delete_job */
-#define DEL_WARNSTOPPED 1 /* warn about deleting stopped jobs */
-#define DEL_NOBGPID 2 /* don't add pgrp leader to bgpids */
-
-/* Take care of system dependencies that must be handled when waiting for
- children. The arguments to the WAITPID macro match those to the Posix.1
- waitpid() function. */
-
-#if defined (ultrix) && defined (mips) && defined (_POSIX_VERSION)
-# define WAITPID(pid, statusp, options) \
- wait3 ((union wait *)statusp, options, (struct rusage *)0)
-#else
-# if defined (_POSIX_VERSION) || defined (HAVE_WAITPID)
-# define WAITPID(pid, statusp, options) \
- waitpid ((pid_t)pid, statusp, options)
-# else
-# if defined (HAVE_WAIT3)
-# define WAITPID(pid, statusp, options) \
- wait3 (statusp, options, (struct rusage *)0)
-# else
-# define WAITPID(pid, statusp, options) \
- wait3 (statusp, options, (int *)0)
-# endif /* HAVE_WAIT3 */
-# endif /* !_POSIX_VERSION && !HAVE_WAITPID*/
-#endif /* !(Ultrix && mips && _POSIX_VERSION) */
-
-/* getpgrp () varies between systems. Even systems that claim to be
- Posix.1 compatible lie sometimes (Ultrix, SunOS4, apollo). */
-#if defined (GETPGRP_VOID)
-# define getpgid(p) getpgrp ()
-#else
-# define getpgid(p) getpgrp (p)
-#endif /* !GETPGRP_VOID */
-
-/* If the system needs it, REINSTALL_SIGCHLD_HANDLER will reinstall the
- handler for SIGCHLD. */
-#if defined (MUST_REINSTALL_SIGHANDLERS)
-# define REINSTALL_SIGCHLD_HANDLER signal (SIGCHLD, sigchld_handler)
-#else
-# define REINSTALL_SIGCHLD_HANDLER
-#endif /* !MUST_REINSTALL_SIGHANDLERS */
-
-/* Some systems let waitpid(2) tell callers about stopped children. */
-#if !defined (WCONTINUED) || defined (WCONTINUED_BROKEN)
-# undef WCONTINUED
-# define WCONTINUED 0
-#endif
-#if !defined (WIFCONTINUED)
-# define WIFCONTINUED(s) (0)
-#endif
-
-/* The number of additional slots to allocate when we run out. */
-#define JOB_SLOTS 8
-
-typedef int sh_job_map_func_t __P((JOB *, int, int, int));
-
-/* Variables used here but defined in other files. */
-extern int subshell_environment, line_number;
-extern int posixly_correct, shell_level;
-extern int last_command_exit_value, last_command_exit_signal;
-extern int loop_level, breaking;
-extern int sourcelevel;
-extern int running_trap;
-extern sh_builtin_func_t *this_shell_builtin;
-extern char *shell_name, *this_command_name;
-extern sigset_t top_level_mask;
-extern procenv_t wait_intr_buf;
-extern int wait_signal_received;
-extern WORD_LIST *subst_assign_varlist;
-
-static struct jobstats zerojs = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
-struct jobstats js = { -1L, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NO_JOB, NO_JOB, 0, 0 };
-
-struct bgpids bgpids = { 0, 0, 0 };
-
-/* The array of known jobs. */
-JOB **jobs = (JOB **)NULL;
-
-#if 0
-/* The number of slots currently allocated to JOBS. */
-int job_slots = 0;
-#endif
-
-/* The controlling tty for this shell. */
-int shell_tty = -1;
-
-/* The shell's process group. */
-pid_t shell_pgrp = NO_PID;
-
-/* The terminal's process group. */
-pid_t terminal_pgrp = NO_PID;
-
-/* The process group of the shell's parent. */
-pid_t original_pgrp = NO_PID;
-
-/* The process group of the pipeline currently being made. */
-pid_t pipeline_pgrp = (pid_t)0;
-
-#if defined (PGRP_PIPE)
-/* Pipes which each shell uses to communicate with the process group leader
- until all of the processes in a pipeline have been started. Then the
- process leader is allowed to continue. */
-int pgrp_pipe[2] = { -1, -1 };
-#endif
-
-#if 0
-/* The job which is current; i.e. the one that `%+' stands for. */
-int current_job = NO_JOB;
-
-/* The previous job; i.e. the one that `%-' stands for. */
-int previous_job = NO_JOB;
-#endif
-
-/* Last child made by the shell. */
-pid_t last_made_pid = NO_PID;
-
-/* Pid of the last asynchronous child. */
-pid_t last_asynchronous_pid = NO_PID;
-
-/* The pipeline currently being built. */
-PROCESS *the_pipeline = (PROCESS *)NULL;
-
-/* If this is non-zero, do job control. */
-int job_control = 1;
-
-/* Call this when you start making children. */
-int already_making_children = 0;
-
-/* If this is non-zero, $LINES and $COLUMNS are reset after every process
- exits from get_tty_state(). */
-int check_window_size;
-
-/* Functions local to this file. */
-
-static void run_sigchld_trap __P((int));
-
-static sighandler wait_sigint_handler __P((int));
-static sighandler sigchld_handler __P((int));
-static sighandler sigcont_sighandler __P((int));
-static sighandler sigstop_sighandler __P((int));
-
-static int waitchld __P((pid_t, int));
-
-static PROCESS *find_pipeline __P((pid_t, int, int *));
-static PROCESS *find_process __P((pid_t, int, int *));
-
-static char *current_working_directory __P((void));
-static char *job_working_directory __P((void));
-static char *j_strsignal __P((int));
-static char *printable_job_status __P((int, PROCESS *, int));
-
-static PROCESS *find_last_proc __P((int, int));
-static pid_t find_last_pid __P((int, int));
-
-static int set_new_line_discipline __P((int));
-static int map_over_jobs __P((sh_job_map_func_t *, int, int));
-static int job_last_stopped __P((int));
-static int job_last_running __P((int));
-static int most_recent_job_in_state __P((int, JOB_STATE));
-static int find_job __P((pid_t, int, PROCESS **));
-static int print_job __P((JOB *, int, int, int));
-static int process_exit_status __P((WAIT));
-static int process_exit_signal __P((WAIT));
-static int job_exit_status __P((int));
-static int job_exit_signal __P((int));
-static int set_job_status_and_cleanup __P((int));
-
-static WAIT raw_job_exit_status __P((int));
-
-static void notify_of_job_status __P((void));
-static void reset_job_indices __P((void));
-static void cleanup_dead_jobs __P((void));
-static int processes_in_job __P((int));
-static void realloc_jobs_list __P((void));
-static int compact_jobs_list __P((int));
-static int discard_pipeline __P((PROCESS *));
-static void add_process __P((char *, pid_t));
-static void print_pipeline __P((PROCESS *, int, int, FILE *));
-static void pretty_print_job __P((int, int, FILE *));
-static void set_current_job __P((int));
-static void reset_current __P((void));
-static void set_job_running __P((int));
-static void setjstatus __P((int));
-static void mark_all_jobs_as_dead __P((void));
-static void mark_dead_jobs_as_notified __P((int));
-static void restore_sigint_handler __P((void));
-#if defined (PGRP_PIPE)
-static void pipe_read __P((int *));
-static void pipe_close __P((int *));
-#endif
-
-static struct pidstat *bgp_alloc __P((pid_t, int));
-static struct pidstat *bgp_add __P((pid_t, int));
-static int bgp_delete __P((pid_t));
-static void bgp_clear __P((void));
-static int bgp_search __P((pid_t));
-static void bgp_prune __P((void));
-
-#if defined (ARRAY_VARS)
-static int *pstatuses; /* list of pipeline statuses */
-static int statsize;
-#endif
-
-/* Used to synchronize between wait_for and other functions and the SIGCHLD
- signal handler. */
-static int sigchld;
-static int queue_sigchld;
-
-#define QUEUE_SIGCHLD(os) (os) = sigchld, queue_sigchld++
-
-#define UNQUEUE_SIGCHLD(os) \
- do { \
- queue_sigchld--; \
- if (queue_sigchld == 0 && os != sigchld) \
- waitchld (-1, 0); \
- } while (0)
-
-static SigHandler *old_tstp, *old_ttou, *old_ttin;
-static SigHandler *old_cont = (SigHandler *)SIG_DFL;
-
-/* A place to temporarily save the current pipeline. */
-static PROCESS *saved_pipeline;
-static int saved_already_making_children;
-
-/* Set this to non-zero whenever you don't want the jobs list to change at
- all: no jobs deleted and no status change notifications. This is used,
- for example, when executing SIGCHLD traps, which may run arbitrary
- commands. */
-static int jobs_list_frozen;
-
-static char retcode_name_buffer[64];
-
-/* flags to detect pid wraparound */
-static pid_t first_pid = NO_PID;
-static int pid_wrap = -1;
-
-#if !defined (_POSIX_VERSION)
-
-/* These are definitions to map POSIX 1003.1 functions onto existing BSD
- library functions and system calls. */
-#define setpgid(pid, pgrp) setpgrp (pid, pgrp)
-#define tcsetpgrp(fd, pgrp) ioctl ((fd), TIOCSPGRP, &(pgrp))
-
-pid_t
-tcgetpgrp (fd)
- int fd;
-{
- pid_t pgrp;
-
- /* ioctl will handle setting errno correctly. */
- if (ioctl (fd, TIOCGPGRP, &pgrp) < 0)
- return (-1);
- return (pgrp);
-}
-
-#endif /* !_POSIX_VERSION */
-
-/* Initialize the global job stats structure and other bookkeeping variables */
-void
-init_job_stats ()
-{
- js = zerojs;
- first_pid = NO_PID;
- pid_wrap = -1;
-}
-
-/* Return the working directory for the current process. Unlike
- job_working_directory, this does not call malloc (), nor do any
- of the functions it calls. This is so that it can safely be called
- from a signal handler. */
-static char *
-current_working_directory ()
-{
- char *dir;
- static char d[PATH_MAX];
-
- dir = get_string_value ("PWD");
-
- if (dir == 0 && the_current_working_directory && no_symbolic_links)
- dir = the_current_working_directory;
-
- if (dir == 0)
- {
- dir = getcwd (d, sizeof(d));
- if (dir)
- dir = d;
- }
-
- return (dir == 0) ? "<unknown>" : dir;
-}
-
-/* Return the working directory for the current process. */
-static char *
-job_working_directory ()
-{
- char *dir;
-
- dir = get_string_value ("PWD");
- if (dir)
- return (savestring (dir));
-
- dir = get_working_directory ("job-working-directory");
- if (dir)
- return (dir);
-
- return (savestring ("<unknown>"));
-}
-
-void
-making_children ()
-{
- if (already_making_children)
- return;
-
- already_making_children = 1;
- start_pipeline ();
-}
-
-void
-stop_making_children ()
-{
- already_making_children = 0;
-}
-
-void
-cleanup_the_pipeline ()
-{
- PROCESS *disposer;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
- disposer = the_pipeline;
- the_pipeline = (PROCESS *)NULL;
- UNBLOCK_CHILD (oset);
-
- if (disposer)
- discard_pipeline (disposer);
-}
-
-void
-save_pipeline (clear)
- int clear;
-{
- saved_pipeline = the_pipeline;
- if (clear)
- the_pipeline = (PROCESS *)NULL;
- saved_already_making_children = already_making_children;
-}
-
-void
-restore_pipeline (discard)
- int discard;
-{
- PROCESS *old_pipeline;
-
- old_pipeline = the_pipeline;
- the_pipeline = saved_pipeline;
- already_making_children = saved_already_making_children;
- if (discard)
- discard_pipeline (old_pipeline);
-}
-
-/* Start building a pipeline. */
-void
-start_pipeline ()
-{
- if (the_pipeline)
- {
- cleanup_the_pipeline ();
- pipeline_pgrp = 0;
-#if defined (PGRP_PIPE)
- pipe_close (pgrp_pipe);
-#endif
- }
-
-#if defined (PGRP_PIPE)
- if (job_control)
- {
- if (pipe (pgrp_pipe) == -1)
- sys_error ("start_pipeline: pgrp pipe");
- }
-#endif
-}
-
-/* Stop building a pipeline. Install the process list in the job array.
- This returns the index of the newly installed job.
- DEFERRED is a command structure to be executed upon satisfactory
- execution exit of this pipeline. */
-int
-stop_pipeline (async, deferred)
- int async;
- COMMAND *deferred;
-{
- register int i, j;
- JOB *newjob;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
-#if defined (PGRP_PIPE)
- /* The parent closes the process group synchronization pipe. */
- pipe_close (pgrp_pipe);
-#endif
-
- cleanup_dead_jobs ();
-
- if (js.j_jobslots == 0)
- {
- js.j_jobslots = JOB_SLOTS;
- jobs = (JOB **)xmalloc (js.j_jobslots * sizeof (JOB *));
-
- /* Now blank out these new entries. */
- for (i = 0; i < js.j_jobslots; i++)
- jobs[i] = (JOB *)NULL;
-
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
-
- /* Scan from the last slot backward, looking for the next free one. */
- /* XXX - revisit this interactive assumption */
- /* XXX - this way for now */
- if (interactive)
- {
- for (i = js.j_jobslots; i; i--)
- if (jobs[i - 1])
- break;
- }
- else
- {
-#if 0
- /* This wraps around, but makes it inconvenient to extend the array */
- for (i = js.j_lastj+1; i != js.j_lastj; i++)
- {
- if (i >= js.j_jobslots)
- i = 0;
- if (jobs[i] == 0)
- break;
- }
- if (i == js.j_lastj)
- i = js.j_jobslots;
-#else
- /* This doesn't wrap around yet. */
- for (i = js.j_lastj ? js.j_lastj + 1 : js.j_lastj; i < js.j_jobslots; i++)
- if (jobs[i] == 0)
- break;
-#endif
- }
-
- /* Do we need more room? */
-
- /* First try compaction */
- if ((interactive_shell == 0 || subshell_environment) && i == js.j_jobslots && js.j_jobslots >= MAX_JOBS_IN_ARRAY)
- i = compact_jobs_list (0);
-
- /* If we can't compact, reallocate */
- if (i == js.j_jobslots)
- {
- js.j_jobslots += JOB_SLOTS;
- jobs = (JOB **)xrealloc (jobs, (js.j_jobslots * sizeof (JOB *)));
-
- for (j = i; j < js.j_jobslots; j++)
- jobs[j] = (JOB *)NULL;
- }
-
- /* Add the current pipeline to the job list. */
- if (the_pipeline)
- {
- register PROCESS *p;
- int any_running, any_stopped, n;
-
- newjob = (JOB *)xmalloc (sizeof (JOB));
-
- for (n = 1, p = the_pipeline; p->next != the_pipeline; n++, p = p->next)
- ;
- p->next = (PROCESS *)NULL;
- newjob->pipe = REVERSE_LIST (the_pipeline, PROCESS *);
- for (p = newjob->pipe; p->next; p = p->next)
- ;
- p->next = newjob->pipe;
-
- the_pipeline = (PROCESS *)NULL;
- newjob->pgrp = pipeline_pgrp;
- pipeline_pgrp = 0;
-
- newjob->flags = 0;
-
- /* Flag to see if in another pgrp. */
- if (job_control)
- newjob->flags |= J_JOBCONTROL;
-
- /* Set the state of this pipeline. */
- p = newjob->pipe;
- any_running = any_stopped = 0;
- do
- {
- any_running |= PRUNNING (p);
- any_stopped |= PSTOPPED (p);
- p = p->next;
- }
- while (p != newjob->pipe);
-
- newjob->state = any_running ? JRUNNING : (any_stopped ? JSTOPPED : JDEAD);
- newjob->wd = job_working_directory ();
- newjob->deferred = deferred;
-
- newjob->j_cleanup = (sh_vptrfunc_t *)NULL;
- newjob->cleanarg = (PTR_T) NULL;
-
- jobs[i] = newjob;
- if (newjob->state == JDEAD && (newjob->flags & J_FOREGROUND))
- setjstatus (i);
- if (newjob->state == JDEAD)
- {
- js.c_reaped += n; /* wouldn't have been done since this was not part of a job */
- js.j_ndead++;
- }
- js.c_injobs += n;
-
- js.j_lastj = i;
- js.j_njobs++;
- }
- else
- newjob = (JOB *)NULL;
-
- if (newjob)
- js.j_lastmade = newjob;
-
- if (async)
- {
- if (newjob)
- {
- newjob->flags &= ~J_FOREGROUND;
- newjob->flags |= J_ASYNC;
- js.j_lastasync = newjob;
- }
- reset_current ();
- }
- else
- {
- if (newjob)
- {
- newjob->flags |= J_FOREGROUND;
- /*
- * !!!!! NOTE !!!!! (chet@ins.cwru.edu)
- *
- * The currently-accepted job control wisdom says to set the
- * terminal's process group n+1 times in an n-step pipeline:
- * once in the parent and once in each child. This is where
- * the parent gives it away.
- *
- * Don't give the terminal away if this shell is an asynchronous
- * subshell.
- *
- */
- if (job_control && newjob->pgrp && (subshell_environment&SUBSHELL_ASYNC) == 0)
- give_terminal_to (newjob->pgrp, 0);
- }
- }
-
- stop_making_children ();
- UNBLOCK_CHILD (oset);
- return (js.j_current);
-}
-
-/* Functions to manage the list of exited background pids whose status has
- been saved. */
-
-static struct pidstat *
-bgp_alloc (pid, status)
- pid_t pid;
- int status;
-{
- struct pidstat *ps;
-
- ps = (struct pidstat *)xmalloc (sizeof (struct pidstat));
- ps->pid = pid;
- ps->status = status;
- ps->next = (struct pidstat *)0;
- return ps;
-}
-
-static struct pidstat *
-bgp_add (pid, status)
- pid_t pid;
- int status;
-{
- struct pidstat *ps;
-
- ps = bgp_alloc (pid, status);
-
- if (bgpids.list == 0)
- {
- bgpids.list = bgpids.end = ps;
- bgpids.npid = 0; /* just to make sure */
- }
- else
- {
- bgpids.end->next = ps;
- bgpids.end = ps;
- }
- bgpids.npid++;
-
- if (bgpids.npid > js.c_childmax)
- bgp_prune ();
-
- return ps;
-}
-
-static int
-bgp_delete (pid)
- pid_t pid;
-{
- struct pidstat *prev, *p;
-
- for (prev = p = bgpids.list; p; prev = p, p = p->next)
- if (p->pid == pid)
- {
- prev->next = p->next; /* remove from list */
- break;
- }
-
- if (p == 0)
- return 0; /* not found */
-
-#if defined (DEBUG)
- itrace("bgp_delete: deleting %d", pid);
-#endif
-
- /* Housekeeping in the border cases. */
- if (p == bgpids.list)
- bgpids.list = bgpids.list->next;
- else if (p == bgpids.end)
- bgpids.end = prev;
-
- bgpids.npid--;
- if (bgpids.npid == 0)
- bgpids.list = bgpids.end = 0;
- else if (bgpids.npid == 1)
- bgpids.end = bgpids.list; /* just to make sure */
-
- free (p);
- return 1;
-}
-
-/* Clear out the list of saved statuses */
-static void
-bgp_clear ()
-{
- struct pidstat *ps, *p;
-
- for (ps = bgpids.list; ps; )
- {
- p = ps;
- ps = ps->next;
- free (p);
- }
- bgpids.list = bgpids.end = 0;
- bgpids.npid = 0;
-}
-
-/* Search for PID in the list of saved background pids; return its status if
- found. If not found, return -1. */
-static int
-bgp_search (pid)
- pid_t pid;
-{
- struct pidstat *ps;
-
- for (ps = bgpids.list ; ps; ps = ps->next)
- if (ps->pid == pid)
- return ps->status;
- return -1;
-}
-
-static void
-bgp_prune ()
-{
- struct pidstat *ps;
-
- while (bgpids.npid > js.c_childmax)
- {
- ps = bgpids.list;
- bgpids.list = bgpids.list->next;
- free (ps);
- bgpids.npid--;
- }
-}
-
-/* Reset the values of js.j_lastj and js.j_firstj after one or both have
- been deleted. The caller should check whether js.j_njobs is 0 before
- calling this. This wraps around, but the rest of the code does not. At
- this point, it should not matter. */
-static void
-reset_job_indices ()
-{
- int old;
-
- if (jobs[js.j_firstj] == 0)
- {
- old = js.j_firstj++;
- while (js.j_firstj != old)
- {
- if (js.j_firstj >= js.j_jobslots)
- js.j_firstj = 0;
- if (jobs[js.j_firstj])
- break;
- js.j_firstj++;
- }
- if (js.j_firstj == old)
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
- if (jobs[js.j_lastj] == 0)
- {
- old = js.j_lastj--;
- while (js.j_lastj != old)
- {
- if (js.j_lastj < 0)
- js.j_lastj = js.j_jobslots - 1;
- if (jobs[js.j_lastj])
- break;
- js.j_lastj--;
- }
- if (js.j_lastj == old)
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
-}
-
-/* Delete all DEAD jobs that the user had received notification about. */
-static void
-cleanup_dead_jobs ()
-{
- register int i;
- int os;
-
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return;
-
- QUEUE_SIGCHLD(os);
-
- /* XXX could use js.j_firstj and js.j_lastj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("cleanup_dead_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("cleanup_dead_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
-
- if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i))
- delete_job (i, 0);
- }
- UNQUEUE_SIGCHLD(os);
-}
-
-static int
-processes_in_job (job)
-{
- int nproc;
- register PROCESS *p;
-
- nproc = 0;
- p = jobs[job]->pipe;
- do
- {
- p = p->next;
- nproc++;
- }
- while (p != jobs[job]->pipe);
-
- return nproc;
-}
-
-static void
-delete_old_job (pid)
- pid_t pid;
-{
- PROCESS *p;
- int job;
-
- job = find_job (pid, 0, &p);
- if (job != NO_JOB)
- {
-#ifdef DEBUG
- itrace ("delete_old_job: found pid %d in job %d with state %d", pid, job, jobs[job]->state);
-#endif
- if (JOBSTATE (job) == JDEAD)
- delete_job (job, DEL_NOBGPID);
- else
- {
- internal_warning (_("forked pid %d appears in running job %d"), pid, job);
- if (p)
- p->pid = 0;
- }
- }
-}
-
-/* Reallocate and compress the jobs list. This returns with a jobs array
- whose size is a multiple of JOB_SLOTS and can hold the current number of
- jobs. Heuristics are used to minimize the number of new reallocs. */
-static void
-realloc_jobs_list ()
-{
- sigset_t set, oset;
- int nsize, i, j, ncur, nprev;
- JOB **nlist;
-
- ncur = nprev = NO_JOB;
- nsize = ((js.j_njobs + JOB_SLOTS - 1) / JOB_SLOTS);
- nsize *= JOB_SLOTS;
- i = js.j_njobs % JOB_SLOTS;
- if (i == 0 || i > (JOB_SLOTS >> 1))
- nsize += JOB_SLOTS;
-
- BLOCK_CHILD (set, oset);
- nlist = (js.j_jobslots == nsize) ? jobs : (JOB **) xmalloc (nsize * sizeof (JOB *));
-
- for (i = j = 0; i < js.j_jobslots; i++)
- if (jobs[i])
- {
- if (i == js.j_current)
- ncur = j;
- if (i == js.j_previous)
- nprev = j;
- nlist[j++] = jobs[i];
- }
-
-#if defined (DEBUG)
- itrace ("realloc_jobs_list: resize jobs list from %d to %d", js.j_jobslots, nsize);
- itrace ("realloc_jobs_list: j_lastj changed from %d to %d", js.j_lastj, (j > 0) ? j - 1 : 0);
- itrace ("realloc_jobs_list: j_njobs changed from %d to %d", js.j_njobs, (j > 0) ? j - 1 : 0);
-#endif
-
- js.j_firstj = 0;
- js.j_lastj = (j > 0) ? j - 1 : 0;
- js.j_njobs = j;
- js.j_jobslots = nsize;
-
- /* Zero out remaining slots in new jobs list */
- for ( ; j < nsize; j++)
- nlist[j] = (JOB *)NULL;
-
- if (jobs != nlist)
- {
- free (jobs);
- jobs = nlist;
- }
-
- if (ncur != NO_JOB)
- js.j_current = ncur;
- if (nprev != NO_JOB)
- js.j_previous = nprev;
-
- /* Need to reset these */
- if (js.j_current == NO_JOB || js.j_previous == NO_JOB || js.j_current > js.j_lastj || js.j_previous > js.j_lastj)
- reset_current ();
-
-#ifdef DEBUG
- itrace ("realloc_jobs_list: reset js.j_current (%d) and js.j_previous (%d)", js.j_current, js.j_previous);
-#endif
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Compact the jobs list by removing dead jobs. Assumed that we have filled
- the jobs array to some predefined maximum. Called when the shell is not
- the foreground process (subshell_environment != 0). Returns the first
- available slot in the compacted list. If that value is js.j_jobslots, then
- the list needs to be reallocated. The jobs array may be in new memory if
- this returns > 0 and < js.j_jobslots. FLAGS is reserved for future use. */
-static int
-compact_jobs_list (flags)
- int flags;
-{
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return js.j_jobslots;
-
- reap_dead_jobs ();
- realloc_jobs_list ();
-
- return (js.j_lastj);
-}
-
-/* Delete the job at INDEX from the job list. Must be called
- with SIGCHLD blocked. */
-void
-delete_job (job_index, dflags)
- int job_index, dflags;
-{
- register JOB *temp;
- PROCESS *proc;
- int ndel;
-
- if (js.j_jobslots == 0 || jobs_list_frozen)
- return;
-
- if ((dflags & DEL_WARNSTOPPED) && subshell_environment == 0 && STOPPED (job_index))
- internal_warning (_("deleting stopped job %d with process group %ld"), job_index+1, (long)jobs[job_index]->pgrp);
- temp = jobs[job_index];
- if (temp == 0)
- return;
- if (job_index == js.j_current || job_index == js.j_previous)
- reset_current ();
-
- if ((dflags & DEL_NOBGPID) == 0)
- {
- proc = find_last_proc (job_index, 0);
- /* Could do this just for J_ASYNC jobs, but we save all. */
- if (proc)
- bgp_add (proc->pid, process_exit_status (proc->status));
- }
-
- jobs[job_index] = (JOB *)NULL;
- if (temp == js.j_lastmade)
- js.j_lastmade = 0;
- else if (temp == js.j_lastasync)
- js.j_lastasync = 0;
-
- free (temp->wd);
- ndel = discard_pipeline (temp->pipe);
-
- js.c_injobs -= ndel;
- if (temp->state == JDEAD)
- {
- js.c_reaped -= ndel;
- js.j_ndead--;
- if (js.c_reaped < 0)
- {
-#ifdef DEBUG
- itrace("delete_job (%d pgrp %d): js.c_reaped (%d) < 0 ndel = %d js.j_ndead = %d", job_index, temp->pgrp, js.c_reaped, ndel, js.j_ndead);
-#endif
- js.c_reaped = 0;
- }
- }
-
- if (temp->deferred)
- dispose_command (temp->deferred);
-
- free (temp);
-
- js.j_njobs--;
- if (js.j_njobs == 0)
- js.j_firstj = js.j_lastj = 0;
- else if (jobs[js.j_firstj] == 0 || jobs[js.j_lastj] == 0)
- reset_job_indices ();
-}
-
-/* Must be called with SIGCHLD blocked. */
-void
-nohup_job (job_index)
- int job_index;
-{
- register JOB *temp;
-
- if (js.j_jobslots == 0)
- return;
-
- if (temp = jobs[job_index])
- temp->flags |= J_NOHUP;
-}
-
-/* Get rid of the data structure associated with a process chain. */
-static int
-discard_pipeline (chain)
- register PROCESS *chain;
-{
- register PROCESS *this, *next;
- int n;
-
- this = chain;
- n = 0;
- do
- {
- next = this->next;
- FREE (this->command);
- free (this);
- n++;
- this = next;
- }
- while (this != chain);
-
- return n;
-}
-
-/* Add this process to the chain being built in the_pipeline.
- NAME is the command string that will be exec'ed later.
- PID is the process id of the child. */
-static void
-add_process (name, pid)
- char *name;
- pid_t pid;
-{
- PROCESS *t, *p;
-
-#if defined (RECYCLES_PIDS)
- int j;
- p = find_process (pid, 0, &j);
- if (p)
- {
-# ifdef DEBUG
- if (j == NO_JOB)
- internal_warning ("add_process: process %5ld (%s) in the_pipeline", (long)p->pid, p->command);
-# endif
- if (PALIVE (p))
- internal_warning ("add_process: pid %5ld (%s) marked as still alive", (long)p->pid, p->command);
- p->running = PS_RECYCLED; /* mark as recycled */
- }
-#endif
-
- t = (PROCESS *)xmalloc (sizeof (PROCESS));
- t->next = the_pipeline;
- t->pid = pid;
- WSTATUS (t->status) = 0;
- t->running = PS_RUNNING;
- t->command = name;
- the_pipeline = t;
-
- if (t->next == 0)
- t->next = t;
- else
- {
- p = t->next;
- while (p->next != t->next)
- p = p->next;
- p->next = t;
- }
-}
-
-#if 0
-/* Take the last job and make it the first job. Must be called with
- SIGCHLD blocked. */
-int
-rotate_the_pipeline ()
-{
- PROCESS *p;
-
- if (the_pipeline->next == the_pipeline)
- return;
- for (p = the_pipeline; p->next != the_pipeline; p = p->next)
- ;
- the_pipeline = p;
-}
-
-/* Reverse the order of the processes in the_pipeline. Must be called with
- SIGCHLD blocked. */
-int
-reverse_the_pipeline ()
-{
- PROCESS *p, *n;
-
- if (the_pipeline->next == the_pipeline)
- return;
-
- for (p = the_pipeline; p->next != the_pipeline; p = p->next)
- ;
- p->next = (PROCESS *)NULL;
-
- n = REVERSE_LIST (the_pipeline, PROCESS *);
-
- the_pipeline = n;
- for (p = the_pipeline; p->next; p = p->next)
- ;
- p->next = the_pipeline;
-}
-#endif
-
-/* Map FUNC over the list of jobs. If FUNC returns non-zero,
- then it is time to stop mapping, and that is the return value
- for map_over_jobs. FUNC is called with a JOB, arg1, arg2,
- and INDEX. */
-static int
-map_over_jobs (func, arg1, arg2)
- sh_job_map_func_t *func;
- int arg1, arg2;
-{
- register int i;
- int result;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return 0;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX could use js.j_firstj here */
- for (i = result = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("map_over_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("map_over_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i])
- {
- result = (*func)(jobs[i], arg1, arg2, i);
- if (result)
- break;
- }
- }
-
- UNBLOCK_CHILD (oset);
-
- return (result);
-}
-
-/* Cause all the jobs in the current pipeline to exit. */
-void
-terminate_current_pipeline ()
-{
- if (pipeline_pgrp && pipeline_pgrp != shell_pgrp)
- {
- killpg (pipeline_pgrp, SIGTERM);
- killpg (pipeline_pgrp, SIGCONT);
- }
-}
-
-/* Cause all stopped jobs to exit. */
-void
-terminate_stopped_jobs ()
-{
- register int i;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && STOPPED (i))
- {
- killpg (jobs[i]->pgrp, SIGTERM);
- killpg (jobs[i]->pgrp, SIGCONT);
- }
- }
-}
-
-/* Cause all jobs, running or stopped, to receive a hangup signal. If
- a job is marked J_NOHUP, don't send the SIGHUP. */
-void
-hangup_all_jobs ()
-{
- register int i;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i])
- {
- if (jobs[i]->flags & J_NOHUP)
- continue;
- killpg (jobs[i]->pgrp, SIGHUP);
- if (STOPPED (i))
- killpg (jobs[i]->pgrp, SIGCONT);
- }
- }
-}
-
-void
-kill_current_pipeline ()
-{
- stop_making_children ();
- start_pipeline ();
-}
-
-/* Return the pipeline that PID belongs to. Note that the pipeline
- doesn't have to belong to a job. Must be called with SIGCHLD blocked.
- If JOBP is non-null, return the index of the job containing PID. */
-static PROCESS *
-find_pipeline (pid, alive_only, jobp)
- pid_t pid;
- int alive_only;
- int *jobp; /* index into jobs list or NO_JOB */
-{
- int job;
- PROCESS *p;
-
- /* See if this process is in the pipeline that we are building. */
- if (jobp)
- *jobp = NO_JOB;
- if (the_pipeline)
- {
- p = the_pipeline;
- do
- {
- /* Return it if we found it. Don't ever return a recycled pid. */
- if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
- return (p);
-
- p = p->next;
- }
- while (p != the_pipeline);
- }
-
- job = find_job (pid, alive_only, &p);
- if (jobp)
- *jobp = job;
- return (job == NO_JOB) ? (PROCESS *)NULL : jobs[job]->pipe;
-}
-
-/* Return the PROCESS * describing PID. If JOBP is non-null return the index
- into the jobs array of the job containing PID. Must be called with
- SIGCHLD blocked. */
-static PROCESS *
-find_process (pid, alive_only, jobp)
- pid_t pid;
- int alive_only;
- int *jobp; /* index into jobs list or NO_JOB */
-{
- PROCESS *p;
-
- p = find_pipeline (pid, alive_only, jobp);
- while (p && p->pid != pid)
- p = p->next;
- return p;
-}
-
-/* Return the job index that PID belongs to, or NO_JOB if it doesn't
- belong to any job. Must be called with SIGCHLD blocked. */
-static int
-find_job (pid, alive_only, procp)
- pid_t pid;
- int alive_only;
- PROCESS **procp;
-{
- register int i;
- PROCESS *p;
-
- /* XXX could use js.j_firstj here, and should check js.j_lastj */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("find_job: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("find_job: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i])
- {
- p = jobs[i]->pipe;
-
- do
- {
- if (p->pid == pid && ((alive_only == 0 && PRECYCLED(p) == 0) || PALIVE(p)))
- {
- if (procp)
- *procp = p;
- return (i);
- }
-
- p = p->next;
- }
- while (p != jobs[i]->pipe);
- }
- }
-
- return (NO_JOB);
-}
-
-/* Find a job given a PID. If BLOCK is non-zero, block SIGCHLD as
- required by find_job. */
-int
-get_job_by_pid (pid, block)
- pid_t pid;
- int block;
-{
- int job;
- sigset_t set, oset;
-
- if (block)
- BLOCK_CHILD (set, oset);
-
- job = find_job (pid, 0, NULL);
-
- if (block)
- UNBLOCK_CHILD (oset);
-
- return job;
-}
-
-/* Print descriptive information about the job with leader pid PID. */
-void
-describe_pid (pid)
- pid_t pid;
-{
- int job;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- job = find_job (pid, 0, NULL);
-
- if (job != NO_JOB)
- fprintf (stderr, "[%d] %ld\n", job + 1, (long)pid);
- else
- programming_error (_("describe_pid: %ld: no such pid"), (long)pid);
-
- UNBLOCK_CHILD (oset);
-}
-
-static char *
-j_strsignal (s)
- int s;
-{
- char *x;
-
- x = strsignal (s);
- if (x == 0)
- {
- x = retcode_name_buffer;
- sprintf (x, "Signal %d", s);
- }
- return x;
-}
-
-static char *
-printable_job_status (j, p, format)
- int j;
- PROCESS *p;
- int format;
-{
- static char *temp;
- int es;
-
- temp = "Done";
-
- if (STOPPED (j) && format == 0)
- {
- if (posixly_correct == 0 || p == 0 || (WIFSTOPPED (p->status) == 0))
- temp = "Stopped";
- else
- {
- temp = retcode_name_buffer;
- sprintf (temp, "Stopped(%s)", signal_name (WSTOPSIG (p->status)));
- }
- }
- else if (RUNNING (j))
- temp = "Running";
- else
- {
- if (WIFSTOPPED (p->status))
- temp = j_strsignal (WSTOPSIG (p->status));
- else if (WIFSIGNALED (p->status))
- temp = j_strsignal (WTERMSIG (p->status));
- else if (WIFEXITED (p->status))
- {
- temp = retcode_name_buffer;
- es = WEXITSTATUS (p->status);
- if (es == 0)
- strcpy (temp, "Done");
- else if (posixly_correct)
- sprintf (temp, "Done(%d)", es);
- else
- sprintf (temp, "Exit %d", es);
- }
- else
- temp = "Unknown status";
- }
-
- return temp;
-}
-
-/* This is the way to print out information on a job if you
- know the index. FORMAT is:
-
- JLIST_NORMAL) [1]+ Running emacs
- JLIST_LONG ) [1]+ 2378 Running emacs
- -1 ) [1]+ 2378 emacs
-
- JLIST_NORMAL) [1]+ Stopped ls | more
- JLIST_LONG ) [1]+ 2369 Stopped ls
- 2367 | more
- JLIST_PID_ONLY)
- Just list the pid of the process group leader (really
- the process group).
- JLIST_CHANGED_ONLY)
- Use format JLIST_NORMAL, but list only jobs about which
- the user has not been notified. */
-
-/* Print status for pipeline P. If JOB_INDEX is >= 0, it is the index into
- the JOBS array corresponding to this pipeline. FORMAT is as described
- above. Must be called with SIGCHLD blocked.
-
- If you're printing a pipeline that's not in the jobs array, like the
- current pipeline as it's being created, pass -1 for JOB_INDEX */
-static void
-print_pipeline (p, job_index, format, stream)
- PROCESS *p;
- int job_index, format;
- FILE *stream;
-{
- PROCESS *first, *last, *show;
- int es, name_padding;
- char *temp;
-
- if (p == 0)
- return;
-
- first = last = p;
- while (last->next != first)
- last = last->next;
-
- for (;;)
- {
- if (p != first)
- fprintf (stream, format ? " " : " |");
-
- if (format != JLIST_STANDARD)
- fprintf (stream, "%5ld", (long)p->pid);
-
- fprintf (stream, " ");
-
- if (format > -1 && job_index >= 0)
- {
- show = format ? p : last;
- temp = printable_job_status (job_index, show, format);
-
- if (p != first)
- {
- if (format)
- {
- if (show->running == first->running &&
- WSTATUS (show->status) == WSTATUS (first->status))
- temp = "";
- }
- else
- temp = (char *)NULL;
- }
-
- if (temp)
- {
- fprintf (stream, "%s", temp);
-
- es = STRLEN (temp);
- if (es == 0)
- es = 2; /* strlen ("| ") */
- name_padding = LONGEST_SIGNAL_DESC - es;
-
- fprintf (stream, "%*s", name_padding, "");
-
- if ((WIFSTOPPED (show->status) == 0) &&
- (WIFCONTINUED (show->status) == 0) &&
- WIFCORED (show->status))
- fprintf (stream, "(core dumped) ");
- }
- }
-
- if (p != first && format)
- fprintf (stream, "| ");
-
- if (p->command)
- fprintf (stream, "%s", p->command);
-
- if (p == last && job_index >= 0)
- {
- temp = current_working_directory ();
-
- if (RUNNING (job_index) && (IS_FOREGROUND (job_index) == 0))
- fprintf (stream, " &");
-
- if (strcmp (temp, jobs[job_index]->wd) != 0)
- fprintf (stream,
- " (wd: %s)", polite_directory_format (jobs[job_index]->wd));
- }
-
- if (format || (p == last))
- {
- /* We need to add a CR only if this is an interactive shell, and
- we're reporting the status of a completed job asynchronously.
- We can't really check whether this particular job is being
- reported asynchronously, so just add the CR if the shell is
- currently interactive and asynchronous notification is enabled. */
- if (asynchronous_notification && interactive)
- fprintf (stream, "\r\n");
- else
- fprintf (stream, "\n");
- }
-
- if (p == last)
- break;
- p = p->next;
- }
- fflush (stream);
-}
-
-/* Print information to STREAM about jobs[JOB_INDEX] according to FORMAT.
- Must be called with SIGCHLD blocked or queued with queue_sigchld */
-static void
-pretty_print_job (job_index, format, stream)
- int job_index, format;
- FILE *stream;
-{
- register PROCESS *p;
-
- /* Format only pid information about the process group leader? */
- if (format == JLIST_PID_ONLY)
- {
- fprintf (stream, "%ld\n", (long)jobs[job_index]->pipe->pid);
- return;
- }
-
- if (format == JLIST_CHANGED_ONLY)
- {
- if (IS_NOTIFIED (job_index))
- return;
- format = JLIST_STANDARD;
- }
-
- if (format != JLIST_NONINTERACTIVE)
- fprintf (stream, "[%d]%c ", job_index + 1,
- (job_index == js.j_current) ? '+':
- (job_index == js.j_previous) ? '-' : ' ');
-
- if (format == JLIST_NONINTERACTIVE)
- format = JLIST_LONG;
-
- p = jobs[job_index]->pipe;
-
- print_pipeline (p, job_index, format, stream);
-
- /* We have printed information about this job. When the job's
- status changes, waitchld () sets the notification flag to 0. */
- jobs[job_index]->flags |= J_NOTIFIED;
-}
-
-static int
-print_job (job, format, state, job_index)
- JOB *job;
- int format, state, job_index;
-{
- if (state == -1 || (JOB_STATE)state == job->state)
- pretty_print_job (job_index, format, stdout);
- return (0);
-}
-
-void
-list_one_job (job, format, ignore, job_index)
- JOB *job;
- int format, ignore, job_index;
-{
- pretty_print_job (job_index, format, stdout);
-}
-
-void
-list_stopped_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, (int)JSTOPPED);
-}
-
-void
-list_running_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, (int)JRUNNING);
-}
-
-/* List jobs. If FORMAT is non-zero, then the long form of the information
- is printed, else just a short version. */
-void
-list_all_jobs (format)
- int format;
-{
- cleanup_dead_jobs ();
- map_over_jobs (print_job, format, -1);
-}
-
-/* Fork, handling errors. Returns the pid of the newly made child, or 0.
- COMMAND is just for remembering the name of the command; we don't do
- anything else with it. ASYNC_P says what to do with the tty. If
- non-zero, then don't give it away. */
-pid_t
-make_child (command, async_p)
- char *command;
- int async_p;
-{
- sigset_t set, oset;
- pid_t pid;
-
- sigemptyset (&set);
- sigaddset (&set, SIGCHLD);
- sigaddset (&set, SIGINT);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
-
- making_children ();
-
-#if defined (BUFFERED_INPUT)
- /* If default_buffered_input is active, we are reading a script. If
- the command is asynchronous, we have already duplicated /dev/null
- as fd 0, but have not changed the buffered stream corresponding to
- the old fd 0. We don't want to sync the stream in this case. */
- if (default_buffered_input != -1 &&
- (!async_p || default_buffered_input > 0))
- sync_buffered_stream (default_buffered_input);
-#endif /* BUFFERED_INPUT */
-
- /* Create the child, handle severe errors. */
- if ((pid = fork ()) < 0)
- {
- sys_error ("fork");
-
- /* Kill all of the processes in the current pipeline. */
- terminate_current_pipeline ();
-
- /* Discard the current pipeline, if any. */
- if (the_pipeline)
- kill_current_pipeline ();
-
- throw_to_top_level (); /* Reset signals, etc. */
- }
-
- if (pid == 0)
- {
- /* In the child. Give this child the right process group, set the
- signals to the default state for a new process. */
- pid_t mypid;
-
- mypid = getpid ();
-#if defined (BUFFERED_INPUT)
- /* Close default_buffered_input if it's > 0. We don't close it if it's
- 0 because that's the file descriptor used when redirecting input,
- and it's wrong to close the file in that case. */
- unset_bash_input (0);
-#endif /* BUFFERED_INPUT */
-
- /* Restore top-level signal mask. */
- sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
-
- if (job_control)
- {
- /* All processes in this pipeline belong in the same
- process group. */
-
- if (pipeline_pgrp == 0) /* This is the first child. */
- pipeline_pgrp = mypid;
-
- /* Check for running command in backquotes. */
- if (pipeline_pgrp == shell_pgrp)
- ignore_tty_job_signals ();
- else
- default_tty_job_signals ();
-
- /* Set the process group before trying to mess with the terminal's
- process group. This is mandated by POSIX. */
- /* This is in accordance with the Posix 1003.1 standard,
- section B.7.2.4, which says that trying to set the terminal
- process group with tcsetpgrp() to an unused pgrp value (like
- this would have for the first child) is an error. Section
- B.4.3.3, p. 237 also covers this, in the context of job control
- shells. */
- if (setpgid (mypid, pipeline_pgrp) < 0)
- sys_error ("child setpgid (%ld to %ld)", (long)mypid, (long)pipeline_pgrp);
-
- /* By convention (and assumption above), if
- pipeline_pgrp == shell_pgrp, we are making a child for
- command substitution.
- In this case, we don't want to give the terminal to the
- shell's process group (we could be in the middle of a
- pipeline, for example). */
- if (async_p == 0 && pipeline_pgrp != shell_pgrp && ((subshell_environment&SUBSHELL_ASYNC) == 0))
- give_terminal_to (pipeline_pgrp, 0);
-
-#if defined (PGRP_PIPE)
- if (pipeline_pgrp == mypid)
- pipe_read (pgrp_pipe);
-#endif
- }
- else /* Without job control... */
- {
- if (pipeline_pgrp == 0)
- pipeline_pgrp = shell_pgrp;
-
- /* If these signals are set to SIG_DFL, we encounter the curious
- situation of an interactive ^Z to a running process *working*
- and stopping the process, but being unable to do anything with
- that process to change its state. On the other hand, if they
- are set to SIG_IGN, jobs started from scripts do not stop when
- the shell running the script gets a SIGTSTP and stops. */
-
- default_tty_job_signals ();
- }
-
-#if defined (PGRP_PIPE)
- /* Release the process group pipe, since our call to setpgid ()
- is done. The last call to pipe_close is done in stop_pipeline. */
- pipe_close (pgrp_pipe);
-#endif /* PGRP_PIPE */
-
- if (async_p)
- last_asynchronous_pid = mypid;
-#if defined (RECYCLES_PIDS)
- else if (last_asynchronous_pid == mypid)
- /* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
- last_asynchronous_pid = 1;
-#endif
- }
- else
- {
- /* In the parent. Remember the pid of the child just created
- as the proper pgrp if this is the first child. */
-
- if (first_pid == NO_PID)
- first_pid = pid;
- else if (pid_wrap == -1 && pid < first_pid)
- pid_wrap = 0;
- else if (pid_wrap == 0 && pid >= first_pid)
- pid_wrap = 1;
-
- if (job_control)
- {
- if (pipeline_pgrp == 0)
- {
- pipeline_pgrp = pid;
- /* Don't twiddle terminal pgrps in the parent! This is the bug,
- not the good thing of twiddling them in the child! */
- /* give_terminal_to (pipeline_pgrp, 0); */
- }
- /* This is done on the recommendation of the Rationale section of
- the POSIX 1003.1 standard, where it discusses job control and
- shells. It is done to avoid possible race conditions. (Ref.
- 1003.1 Rationale, section B.4.3.3, page 236). */
- setpgid (pid, pipeline_pgrp);
- }
- else
- {
- if (pipeline_pgrp == 0)
- pipeline_pgrp = shell_pgrp;
- }
-
- /* Place all processes into the jobs array regardless of the
- state of job_control. */
- add_process (command, pid);
-
- if (async_p)
- last_asynchronous_pid = pid;
-#if defined (RECYCLES_PIDS)
- else if (last_asynchronous_pid == pid)
- /* Avoid pid aliasing. 1 seems like a safe, unusual pid value. */
- last_asynchronous_pid = 1;
-#endif
-
- if (pid_wrap > 0)
- delete_old_job (pid);
-
-#if !defined (RECYCLES_PIDS)
- /* Only check for saved status if we've saved more than CHILD_MAX
- statuses, unless the system recycles pids. */
- if ((js.c_reaped + bgpids.npid) >= js.c_childmax)
-#endif
- bgp_delete (pid); /* new process, discard any saved status */
-
- last_made_pid = pid;
-
- /* keep stats */
- js.c_totforked++;
- js.c_living++;
-
- /* Unblock SIGINT and SIGCHLD unless creating a pipeline, in which case
- SIGCHLD remains blocked until all commands in the pipeline have been
- created. */
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- }
-
- return (pid);
-}
-
-/* These two functions are called only in child processes. */
-void
-ignore_tty_job_signals ()
-{
- set_signal_handler (SIGTSTP, SIG_IGN);
- set_signal_handler (SIGTTIN, SIG_IGN);
- set_signal_handler (SIGTTOU, SIG_IGN);
-}
-
-void
-default_tty_job_signals ()
-{
- set_signal_handler (SIGTSTP, SIG_DFL);
- set_signal_handler (SIGTTIN, SIG_DFL);
- set_signal_handler (SIGTTOU, SIG_DFL);
-}
-
-/* When we end a job abnormally, or if we stop a job, we set the tty to the
- state kept in here. When a job ends normally, we set the state in here
- to the state of the tty. */
-
-static TTYSTRUCT shell_tty_info;
-
-#if defined (NEW_TTY_DRIVER)
-static struct tchars shell_tchars;
-static struct ltchars shell_ltchars;
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (NEW_TTY_DRIVER) && defined (DRAIN_OUTPUT)
-/* Since the BSD tty driver does not allow us to change the tty modes
- while simultaneously waiting for output to drain and preserving
- typeahead, we have to drain the output ourselves before calling
- ioctl. We cheat by finding the length of the output queue, and
- using select to wait for an appropriate length of time. This is
- a hack, and should be labeled as such (it's a hastily-adapted
- mutation of a `usleep' implementation). It's only reason for
- existing is the flaw in the BSD tty driver. */
-
-static int ttspeeds[] =
-{
- 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
- 1800, 2400, 4800, 9600, 19200, 38400
-};
-
-static void
-draino (fd, ospeed)
- int fd, ospeed;
-{
- register int delay = ttspeeds[ospeed];
- int n;
-
- if (!delay)
- return;
-
- while ((ioctl (fd, TIOCOUTQ, &n) == 0) && n)
- {
- if (n > (delay / 100))
- {
- struct timeval tv;
-
- n *= 10; /* 2 bits more for conservativeness. */
- tv.tv_sec = n / delay;
- tv.tv_usec = ((n % delay) * 1000000) / delay;
- select (fd, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
- }
- else
- break;
- }
-}
-#endif /* NEW_TTY_DRIVER && DRAIN_OUTPUT */
-
-/* Return the fd from which we are actually getting input. */
-#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
-
-/* Fill the contents of shell_tty_info with the current tty info. */
-int
-get_tty_state ()
-{
- int tty;
-
- tty = input_tty ();
- if (tty != -1)
- {
-#if defined (NEW_TTY_DRIVER)
- ioctl (tty, TIOCGETP, &shell_tty_info);
- ioctl (tty, TIOCGETC, &shell_tchars);
- ioctl (tty, TIOCGLTC, &shell_ltchars);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
- ioctl (tty, TCGETA, &shell_tty_info);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
- if (tcgetattr (tty, &shell_tty_info) < 0)
- {
-#if 0
- /* Only print an error message if we're really interactive at
- this time. */
- if (interactive)
- sys_error ("[%ld: %d] tcgetattr", (long)getpid (), shell_level);
-#endif
- return -1;
- }
-#endif /* TERMIOS_TTY_DRIVER */
- if (check_window_size)
- get_new_window_size (0, (int *)0, (int *)0);
- }
- return 0;
-}
-
-/* Make the current tty use the state in shell_tty_info. */
-int
-set_tty_state ()
-{
- int tty;
-
- tty = input_tty ();
- if (tty != -1)
- {
-#if defined (NEW_TTY_DRIVER)
-# if defined (DRAIN_OUTPUT)
- draino (tty, shell_tty_info.sg_ospeed);
-# endif /* DRAIN_OUTPUT */
- ioctl (tty, TIOCSETN, &shell_tty_info);
- ioctl (tty, TIOCSETC, &shell_tchars);
- ioctl (tty, TIOCSLTC, &shell_ltchars);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
- ioctl (tty, TCSETAW, &shell_tty_info);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
- if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
- {
- /* Only print an error message if we're really interactive at
- this time. */
- if (interactive)
- sys_error ("[%ld: %d] tcsetattr", (long)getpid (), shell_level);
- return -1;
- }
-#endif /* TERMIOS_TTY_DRIVER */
- }
- return 0;
-}
-
-/* Given an index into the jobs array JOB, return the PROCESS struct of the last
- process in that job's pipeline. This is the one whose exit status
- counts. Must be called with SIGCHLD blocked or queued. */
-static PROCESS *
-find_last_proc (job, block)
- int job;
- int block;
-{
- register PROCESS *p;
- sigset_t set, oset;
-
- if (block)
- BLOCK_CHILD (set, oset);
-
- p = jobs[job]->pipe;
- while (p && p->next != jobs[job]->pipe)
- p = p->next;
-
- if (block)
- UNBLOCK_CHILD (oset);
-
- return (p);
-}
-
-static pid_t
-find_last_pid (job, block)
- int job;
- int block;
-{
- PROCESS *p;
-
- p = find_last_proc (job, block);
- /* Possible race condition here. */
- return p->pid;
-}
-
-/* Wait for a particular child of the shell to finish executing.
- This low-level function prints an error message if PID is not
- a child of this shell. It returns -1 if it fails, or whatever
- wait_for returns otherwise. If the child is not found in the
- jobs table, it returns 127. */
-int
-wait_for_single_pid (pid)
- pid_t pid;
-{
- register PROCESS *child;
- sigset_t set, oset;
- int r, job;
-
- BLOCK_CHILD (set, oset);
- child = find_pipeline (pid, 0, (int *)NULL);
- UNBLOCK_CHILD (oset);
-
- if (child == 0)
- {
- r = bgp_search (pid);
- if (r >= 0)
- return r;
- }
-
- if (child == 0)
- {
- internal_error (_("wait: pid %ld is not a child of this shell"), (long)pid);
- return (127);
- }
-
- r = wait_for (pid);
-
- /* POSIX.2: if we just waited for a job, we can remove it from the jobs
- table. */
- BLOCK_CHILD (set, oset);
- job = find_job (pid, 0, NULL);
- if (job != NO_JOB && jobs[job] && DEADJOB (job))
- jobs[job]->flags |= J_NOTIFIED;
- UNBLOCK_CHILD (oset);
-
- /* If running in posix mode, remove the job from the jobs table immediately */
- if (posixly_correct)
- {
- cleanup_dead_jobs ();
- bgp_delete (pid);
- }
-
- return r;
-}
-
-/* Wait for all of the backgrounds of this shell to finish. */
-void
-wait_for_background_pids ()
-{
- register int i, r, waited_for;
- sigset_t set, oset;
- pid_t pid;
-
- for (waited_for = 0;;)
- {
- BLOCK_CHILD (set, oset);
-
- /* find first running job; if none running in foreground, break */
- /* XXX could use js.j_firstj and js.j_lastj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("wait_for_background_pids: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("wait_for_background_pids: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i] && RUNNING (i) && IS_FOREGROUND (i) == 0)
- break;
- }
- if (i == js.j_jobslots)
- {
- UNBLOCK_CHILD (oset);
- break;
- }
-
- /* now wait for the last pid in that job. */
- pid = find_last_pid (i, 0);
- UNBLOCK_CHILD (oset);
- QUIT;
- errno = 0; /* XXX */
- r = wait_for_single_pid (pid);
- if (r == -1)
- {
- /* If we're mistaken about job state, compensate. */
- if (errno == ECHILD)
- mark_all_jobs_as_dead ();
- }
- else
- waited_for++;
- }
-
- /* POSIX.2 says the shell can discard the statuses of all completed jobs if
- `wait' is called with no arguments. */
- mark_dead_jobs_as_notified (1);
- cleanup_dead_jobs ();
- bgp_clear ();
-}
-
-/* Make OLD_SIGINT_HANDLER the SIGINT signal handler. */
-#define INVALID_SIGNAL_HANDLER (SigHandler *)wait_for_background_pids
-static SigHandler *old_sigint_handler = INVALID_SIGNAL_HANDLER;
-
-static void
-restore_sigint_handler ()
-{
- if (old_sigint_handler != INVALID_SIGNAL_HANDLER)
- {
- set_signal_handler (SIGINT, old_sigint_handler);
- old_sigint_handler = INVALID_SIGNAL_HANDLER;
- }
-}
-
-static int wait_sigint_received;
-
-/* Handle SIGINT while we are waiting for children in a script to exit.
- The `wait' builtin should be interruptible, but all others should be
- effectively ignored (i.e. not cause the shell to exit). */
-static sighandler
-wait_sigint_handler (sig)
- int sig;
-{
- SigHandler *sigint_handler;
-
- if (interrupt_immediately ||
- (this_shell_builtin && this_shell_builtin == wait_builtin))
- {
- last_command_exit_value = EXECUTION_FAILURE;
- restore_sigint_handler ();
- /* If we got a SIGINT while in `wait', and SIGINT is trapped, do
- what POSIX.2 says (see builtins/wait.def for more info). */
- if (this_shell_builtin && this_shell_builtin == wait_builtin &&
- signal_is_trapped (SIGINT) &&
- ((sigint_handler = trap_to_sighandler (SIGINT)) == trap_handler))
- {
- interrupt_immediately = 0;
- trap_handler (SIGINT); /* set pending_traps[SIGINT] */
- wait_signal_received = SIGINT;
- longjmp (wait_intr_buf, 1);
- }
-
- ADDINTERRUPT;
- QUIT;
- }
-
- /* XXX - should this be interrupt_state? If it is, the shell will act
- as if it got the SIGINT interrupt. */
- wait_sigint_received = 1;
-
- /* Otherwise effectively ignore the SIGINT and allow the running job to
- be killed. */
- SIGRETURN (0);
-}
-
-static int
-process_exit_signal (status)
- WAIT status;
-{
- return (WIFSIGNALED (status) ? WTERMSIG (status) : 0);
-}
-
-static int
-process_exit_status (status)
- WAIT status;
-{
- if (WIFSIGNALED (status))
- return (128 + WTERMSIG (status));
- else if (WIFSTOPPED (status) == 0)
- return (WEXITSTATUS (status));
- else
- return (EXECUTION_SUCCESS);
-}
-
-/* Return the exit status of the last process in the pipeline for job JOB.
- This is the exit status of the entire job. */
-static WAIT
-raw_job_exit_status (job)
- int job;
-{
- register PROCESS *p;
- int fail;
-
- if (pipefail_opt)
- {
- fail = 0;
- p = jobs[job]->pipe;
- do
- {
- if (p->status != EXECUTION_SUCCESS) fail = p->status;
- p = p->next;
- }
- while (p != jobs[job]->pipe);
- return fail;
- }
-
- for (p = jobs[job]->pipe; p->next != jobs[job]->pipe; p = p->next)
- ;
- return (p->status);
-}
-
-/* Return the exit status of job JOB. This is the exit status of the last
- (rightmost) process in the job's pipeline, modified if the job was killed
- by a signal or stopped. */
-static int
-job_exit_status (job)
- int job;
-{
- return (process_exit_status (raw_job_exit_status (job)));
-}
-
-static int
-job_exit_signal (job)
- int job;
-{
- return (process_exit_signal (raw_job_exit_status (job)));
-}
-
-#define FIND_CHILD(pid, child) \
- do \
- { \
- child = find_pipeline (pid, 0, (int *)NULL); \
- if (child == 0) \
- { \
- give_terminal_to (shell_pgrp, 0); \
- UNBLOCK_CHILD (oset); \
- internal_error (_("wait_for: No record of process %ld"), (long)pid); \
- restore_sigint_handler (); \
- return (termination_state = 127); \
- } \
- } \
- while (0)
-
-/* Wait for pid (one of our children) to terminate, then
- return the termination state. Returns 127 if PID is not found in
- the jobs table. Returns -1 if waitchld() returns -1, indicating
- that there are no unwaited-for child processes. */
-int
-wait_for (pid)
- pid_t pid;
-{
- int job, termination_state, r;
- WAIT s;
- register PROCESS *child;
- sigset_t set, oset;
- register PROCESS *p;
-
- /* In the case that this code is interrupted, and we longjmp () out of it,
- we are relying on the code in throw_to_top_level () to restore the
- top-level signal mask. */
- BLOCK_CHILD (set, oset);
-
- /* Ignore interrupts while waiting for a job run without job control
- to finish. We don't want the shell to exit if an interrupt is
- received, only if one of the jobs run is killed via SIGINT. If
- job control is not set, the job will be run in the same pgrp as
- the shell, and the shell will see any signals the job gets. */
-
- /* This is possibly a race condition -- should it go in stop_pipeline? */
- wait_sigint_received = 0;
- if (job_control == 0)
- {
- old_sigint_handler = set_signal_handler (SIGINT, wait_sigint_handler);
- if (old_sigint_handler == SIG_IGN)
- set_signal_handler (SIGINT, old_sigint_handler);
- }
-
- termination_state = last_command_exit_value;
-
- if (interactive && job_control == 0)
- QUIT;
-
- /* If we say wait_for (), then we have a record of this child somewhere.
- If it and none of its peers are running, don't call waitchld(). */
-
- job = NO_JOB;
- do
- {
- FIND_CHILD (pid, child);
-
- /* If this child is part of a job, then we are really waiting for the
- job to finish. Otherwise, we are waiting for the child to finish.
- We check for JDEAD in case the job state has been set by waitchld
- after receipt of a SIGCHLD. */
- if (job == NO_JOB)
- job = find_job (pid, 0, NULL);
-
- /* waitchld() takes care of setting the state of the job. If the job
- has already exited before this is called, sigchld_handler will have
- called waitchld and the state will be set to JDEAD. */
-
- if (PRUNNING(child) || (job != NO_JOB && RUNNING (job)))
- {
-#if defined (WAITPID_BROKEN) /* SCOv4 */
- sigset_t suspend_set;
- sigemptyset (&suspend_set);
- sigsuspend (&suspend_set);
-#else /* !WAITPID_BROKEN */
-# if defined (MUST_UNBLOCK_CHLD)
- struct sigaction act, oact;
- sigset_t nullset, chldset;
-
- sigemptyset (&nullset);
- sigemptyset (&chldset);
- sigprocmask (SIG_SETMASK, &nullset, &chldset);
- act.sa_handler = SIG_DFL;
- sigemptyset (&act.sa_mask);
- sigemptyset (&oact.sa_mask);
- act.sa_flags = 0;
- sigaction (SIGCHLD, &act, &oact);
-# endif
- queue_sigchld = 1;
- r = waitchld (pid, 1);
-# if defined (MUST_UNBLOCK_CHLD)
- sigaction (SIGCHLD, &oact, (struct sigaction *)NULL);
- sigprocmask (SIG_SETMASK, &chldset, (sigset_t *)NULL);
-# endif
- queue_sigchld = 0;
- if (r == -1 && errno == ECHILD && this_shell_builtin == wait_builtin)
- {
- termination_state = -1;
- goto wait_for_return;
- }
-
- /* If child is marked as running, but waitpid() returns -1/ECHILD,
- there is something wrong. Somewhere, wait should have returned
- that child's pid. Mark the child as not running and the job,
- if it exists, as JDEAD. */
- if (r == -1 && errno == ECHILD)
- {
- child->running = PS_DONE;
- child->status = 0; /* XXX -- can't find true status */
- js.c_living = 0; /* no living child processes */
- if (job != NO_JOB)
- {
- jobs[job]->state = JDEAD;
- js.c_reaped++;
- js.j_ndead++;
- }
- }
-#endif /* WAITPID_BROKEN */
- }
-
- /* If the shell is interactive, and job control is disabled, see
- if the foreground process has died due to SIGINT and jump out
- of the wait loop if it has. waitchld has already restored the
- old SIGINT signal handler. */
- if (interactive && job_control == 0)
- QUIT;
- }
- while (PRUNNING (child) || (job != NO_JOB && RUNNING (job)));
-
- /* The exit state of the command is either the termination state of the
- child, or the termination state of the job. If a job, the status
- of the last child in the pipeline is the significant one. If the command
- or job was terminated by a signal, note that value also. */
- termination_state = (job != NO_JOB) ? job_exit_status (job)
- : process_exit_status (child->status);
- last_command_exit_signal = (job != NO_JOB) ? job_exit_signal (job)
- : process_exit_signal (child->status);
-
- /* XXX */
- if ((job != NO_JOB && JOBSTATE (job) == JSTOPPED) || WIFSTOPPED (child->status))
- termination_state = 128 + WSTOPSIG (child->status);
-
- if (job == NO_JOB || IS_JOBCONTROL (job))
- {
- /* XXX - under what circumstances is a job not present in the jobs
- table (job == NO_JOB)?
- 1. command substitution
-
- In the case of command substitution, at least, it's probably not
- the right thing to give the terminal to the shell's process group,
- even though there is code in subst.c:command_substitute to work
- around it.
-
- Things that don't:
- $PROMPT_COMMAND execution
- process substitution
- */
-#if 0
-if (job == NO_JOB)
- itrace("wait_for: job == NO_JOB, giving the terminal to shell_pgrp (%ld)", (long)shell_pgrp);
-#endif
- give_terminal_to (shell_pgrp, 0);
- }
-
- /* If the command did not exit cleanly, or the job is just
- being stopped, then reset the tty state back to what it
- was before this command. Reset the tty state and notify
- the user of the job termination only if the shell is
- interactive. Clean up any dead jobs in either case. */
- if (job != NO_JOB)
- {
- if (interactive_shell && subshell_environment == 0)
- {
- /* This used to use `child->status'. That's wrong, however, for
- pipelines. `child' is the first process in the pipeline. It's
- likely that the process we want to check for abnormal termination
- or stopping is the last process in the pipeline, especially if
- it's long-lived and the first process is short-lived. Since we
- know we have a job here, we can check all the processes in this
- job's pipeline and see if one of them stopped or terminated due
- to a signal. We might want to change this later to just check
- the last process in the pipeline. If no process exits due to a
- signal, S is left as the status of the last job in the pipeline. */
- p = jobs[job]->pipe;
- do
- {
- s = p->status;
- if (WIFSIGNALED(s) || WIFSTOPPED(s))
- break;
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- if (WIFSIGNALED (s) || WIFSTOPPED (s))
- {
- set_tty_state ();
-
- /* If the current job was stopped or killed by a signal, and
- the user has requested it, get a possibly new window size */
- if (check_window_size && (job == js.j_current || IS_FOREGROUND (job)))
- get_new_window_size (0, (int *)0, (int *)0);
- }
- else
- get_tty_state ();
-
- /* If job control is enabled, the job was started with job
- control, the job was the foreground job, and it was killed
- by SIGINT, then print a newline to compensate for the kernel
- printing the ^C without a trailing newline. */
- if (job_control && IS_JOBCONTROL (job) && IS_FOREGROUND (job) &&
- WIFSIGNALED (s) && WTERMSIG (s) == SIGINT)
- {
- /* If SIGINT is not trapped and the shell is in a for, while,
- or until loop, act as if the shell received SIGINT as
- well, so the loop can be broken. This doesn't call the
- SIGINT signal handler; maybe it should. */
- if (signal_is_trapped (SIGINT) == 0 && loop_level)
- ADDINTERRUPT;
- else
- {
- putchar ('\n');
- fflush (stdout);
- }
- }
- }
-
- /* Moved here from set_job_status_and_cleanup, which is in the SIGCHLD
- signal handler path */
- if (DEADJOB (job) && IS_FOREGROUND (job) /*&& subshell_environment == 0*/)
- setjstatus (job);
-
- /* If this job is dead, notify the user of the status. If the shell
- is interactive, this will display a message on the terminal. If
- the shell is not interactive, make sure we turn on the notify bit
- so we don't get an unwanted message about the job's termination,
- and so delete_job really clears the slot in the jobs table. */
- notify_and_cleanup ();
- }
-
-wait_for_return:
-
- UNBLOCK_CHILD (oset);
-
- /* Restore the original SIGINT signal handler before we return. */
- restore_sigint_handler ();
-
- return (termination_state);
-}
-
-/* Wait for the last process in the pipeline for JOB. Returns whatever
- wait_for returns: the last process's termination state or -1 if there
- are no unwaited-for child processes or an error occurs. */
-int
-wait_for_job (job)
- int job;
-{
- pid_t pid;
- int r;
- sigset_t set, oset;
-
- BLOCK_CHILD(set, oset);
- if (JOBSTATE (job) == JSTOPPED)
- internal_warning (_("wait_for_job: job %d is stopped"), job+1);
-
- pid = find_last_pid (job, 0);
- UNBLOCK_CHILD(oset);
- r = wait_for (pid);
-
- /* POSIX.2: we can remove the job from the jobs table if we just waited
- for it. */
- BLOCK_CHILD (set, oset);
- if (job != NO_JOB && jobs[job] && DEADJOB (job))
- jobs[job]->flags |= J_NOTIFIED;
- UNBLOCK_CHILD (oset);
-
- return r;
-}
-
-/* Print info about dead jobs, and then delete them from the list
- of known jobs. This does not actually delete jobs when the
- shell is not interactive, because the dead jobs are not marked
- as notified. */
-void
-notify_and_cleanup ()
-{
- if (jobs_list_frozen)
- return;
-
- if (interactive || interactive_shell == 0 || sourcelevel)
- notify_of_job_status ();
-
- cleanup_dead_jobs ();
-}
-
-/* Make dead jobs disappear from the jobs array without notification.
- This is used when the shell is not interactive. */
-void
-reap_dead_jobs ()
-{
- mark_dead_jobs_as_notified (0);
- cleanup_dead_jobs ();
-}
-
-/* Return the next closest (chronologically) job to JOB which is in
- STATE. STATE can be JSTOPPED, JRUNNING. NO_JOB is returned if
- there is no next recent job. */
-static int
-most_recent_job_in_state (job, state)
- int job;
- JOB_STATE state;
-{
- register int i, result;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- for (result = NO_JOB, i = job - 1; i >= 0; i--)
- {
- if (jobs[i] && (JOBSTATE (i) == state))
- {
- result = i;
- break;
- }
- }
-
- UNBLOCK_CHILD (oset);
-
- return (result);
-}
-
-/* Return the newest *stopped* job older than JOB, or NO_JOB if not
- found. */
-static int
-job_last_stopped (job)
- int job;
-{
- return (most_recent_job_in_state (job, JSTOPPED));
-}
-
-/* Return the newest *running* job older than JOB, or NO_JOB if not
- found. */
-static int
-job_last_running (job)
- int job;
-{
- return (most_recent_job_in_state (job, JRUNNING));
-}
-
-/* Make JOB be the current job, and make previous be useful. Must be
- called with SIGCHLD blocked. */
-static void
-set_current_job (job)
- int job;
-{
- int candidate;
-
- if (js.j_current != job)
- {
- js.j_previous = js.j_current;
- js.j_current = job;
- }
-
- /* First choice for previous job is the old current job. */
- if (js.j_previous != js.j_current &&
- js.j_previous != NO_JOB &&
- jobs[js.j_previous] &&
- STOPPED (js.j_previous))
- return;
-
- /* Second choice: Newest stopped job that is older than
- the current job. */
- candidate = NO_JOB;
- if (STOPPED (js.j_current))
- {
- candidate = job_last_stopped (js.j_current);
-
- if (candidate != NO_JOB)
- {
- js.j_previous = candidate;
- return;
- }
- }
-
- /* If we get here, there is either only one stopped job, in which case it is
- the current job and the previous job should be set to the newest running
- job, or there are only running jobs and the previous job should be set to
- the newest running job older than the current job. We decide on which
- alternative to use based on whether or not JOBSTATE(js.j_current) is
- JSTOPPED. */
-
- candidate = RUNNING (js.j_current) ? job_last_running (js.j_current)
- : job_last_running (js.j_jobslots);
-
- if (candidate != NO_JOB)
- {
- js.j_previous = candidate;
- return;
- }
-
- /* There is only a single job, and it is both `+' and `-'. */
- js.j_previous = js.j_current;
-}
-
-/* Make current_job be something useful, if it isn't already. */
-
-/* Here's the deal: The newest non-running job should be `+', and the
- next-newest non-running job should be `-'. If there is only a single
- stopped job, the js.j_previous is the newest non-running job. If there
- are only running jobs, the newest running job is `+' and the
- next-newest running job is `-'. Must be called with SIGCHLD blocked. */
-
-static void
-reset_current ()
-{
- int candidate;
-
- if (js.j_jobslots && js.j_current != NO_JOB && jobs[js.j_current] && STOPPED (js.j_current))
- candidate = js.j_current;
- else
- {
- candidate = NO_JOB;
-
- /* First choice: the previous job. */
- if (js.j_previous != NO_JOB && jobs[js.j_previous] && STOPPED (js.j_previous))
- candidate = js.j_previous;
-
- /* Second choice: the most recently stopped job. */
- if (candidate == NO_JOB)
- candidate = job_last_stopped (js.j_jobslots);
-
- /* Third choice: the newest running job. */
- if (candidate == NO_JOB)
- candidate = job_last_running (js.j_jobslots);
- }
-
- /* If we found a job to use, then use it. Otherwise, there
- are no jobs period. */
- if (candidate != NO_JOB)
- set_current_job (candidate);
- else
- js.j_current = js.j_previous = NO_JOB;
-}
-
-/* Set up the job structures so we know the job and its processes are
- all running. */
-static void
-set_job_running (job)
- int job;
-{
- register PROCESS *p;
-
- /* Each member of the pipeline is now running. */
- p = jobs[job]->pipe;
-
- do
- {
- if (WIFSTOPPED (p->status))
- p->running = PS_RUNNING; /* XXX - could be PS_STOPPED */
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- /* This means that the job is running. */
- JOBSTATE (job) = JRUNNING;
-}
-
-/* Start a job. FOREGROUND if non-zero says to do that. Otherwise,
- start the job in the background. JOB is a zero-based index into
- JOBS. Returns -1 if it is unable to start a job, and the return
- status of the job otherwise. */
-int
-start_job (job, foreground)
- int job, foreground;
-{
- register PROCESS *p;
- int already_running;
- sigset_t set, oset;
- char *wd, *s;
- static TTYSTRUCT save_stty;
-
- BLOCK_CHILD (set, oset);
-
- if (DEADJOB (job))
- {
- internal_error (_("%s: job has terminated"), this_command_name);
- UNBLOCK_CHILD (oset);
- return (-1);
- }
-
- already_running = RUNNING (job);
-
- if (foreground == 0 && already_running)
- {
- internal_error (_("%s: job %d already in background"), this_command_name, job + 1);
- UNBLOCK_CHILD (oset);
- return (0); /* XPG6/SUSv3 says this is not an error */
- }
-
- wd = current_working_directory ();
-
- /* You don't know about the state of this job. Do you? */
- jobs[job]->flags &= ~J_NOTIFIED;
-
- if (foreground)
- {
- set_current_job (job);
- jobs[job]->flags |= J_FOREGROUND;
- }
-
- /* Tell the outside world what we're doing. */
- p = jobs[job]->pipe;
-
- if (foreground == 0)
- {
- /* POSIX.2 says `bg' doesn't give any indication about current or
- previous job. */
- if (posixly_correct == 0)
- s = (job == js.j_current) ? "+ ": ((job == js.j_previous) ? "- " : " ");
- else
- s = " ";
- printf ("[%d]%s", job + 1, s);
- }
-
- do
- {
- printf ("%s%s",
- p->command ? p->command : "",
- p->next != jobs[job]->pipe? " | " : "");
- p = p->next;
- }
- while (p != jobs[job]->pipe);
-
- if (foreground == 0)
- printf (" &");
-
- if (strcmp (wd, jobs[job]->wd) != 0)
- printf (" (wd: %s)", polite_directory_format (jobs[job]->wd));
-
- printf ("\n");
-
- /* Run the job. */
- if (already_running == 0)
- set_job_running (job);
-
- /* Save the tty settings before we start the job in the foreground. */
- if (foreground)
- {
- get_tty_state ();
- save_stty = shell_tty_info;
- /* Give the terminal to this job. */
- if (IS_JOBCONTROL (job))
- give_terminal_to (jobs[job]->pgrp, 0);
- }
- else
- jobs[job]->flags &= ~J_FOREGROUND;
-
- /* If the job is already running, then don't bother jump-starting it. */
- if (already_running == 0)
- {
- jobs[job]->flags |= J_NOTIFIED;
- killpg (jobs[job]->pgrp, SIGCONT);
- }
-
- if (foreground)
- {
- pid_t pid;
- int s;
-
- pid = find_last_pid (job, 0);
- UNBLOCK_CHILD (oset);
- s = wait_for (pid);
- shell_tty_info = save_stty;
- set_tty_state ();
- return (s);
- }
- else
- {
- reset_current ();
- UNBLOCK_CHILD (oset);
- return (0);
- }
-}
-
-/* Give PID SIGNAL. This determines what job the pid belongs to (if any).
- If PID does belong to a job, and the job is stopped, then CONTinue the
- job after giving it SIGNAL. Returns -1 on failure. If GROUP is non-null,
- then kill the process group associated with PID. */
-int
-kill_pid (pid, sig, group)
- pid_t pid;
- int sig, group;
-{
- register PROCESS *p;
- int job, result, negative;
- sigset_t set, oset;
-
- if (pid < -1)
- {
- pid = -pid;
- group = negative = 1;
- }
- else
- negative = 0;
-
- result = EXECUTION_SUCCESS;
- if (group)
- {
- BLOCK_CHILD (set, oset);
- p = find_pipeline (pid, 0, &job);
-
- if (job != NO_JOB)
- {
- jobs[job]->flags &= ~J_NOTIFIED;
-
- /* Kill process in backquotes or one started without job control? */
-
- /* If we're passed a pid < -1, just call killpg and see what happens */
- if (negative && jobs[job]->pgrp == shell_pgrp)
- result = killpg (pid, sig);
- /* If we're killing using job control notification, for example,
- without job control active, we have to do things ourselves. */
- else if (jobs[job]->pgrp == shell_pgrp)
- {
- p = jobs[job]->pipe;
- do
- {
- if (PALIVE (p) == 0)
- continue; /* avoid pid recycling problem */
- kill (p->pid, sig);
- if (PEXITED (p) && (sig == SIGTERM || sig == SIGHUP))
- kill (p->pid, SIGCONT);
- p = p->next;
- }
- while (p != jobs[job]->pipe);
- }
- else
- {
- result = killpg (jobs[job]->pgrp, sig);
- if (p && STOPPED (job) && (sig == SIGTERM || sig == SIGHUP))
- killpg (jobs[job]->pgrp, SIGCONT);
- /* If we're continuing a stopped job via kill rather than bg or
- fg, emulate the `bg' behavior. */
- if (p && STOPPED (job) && (sig == SIGCONT))
- {
- set_job_running (job);
- jobs[job]->flags &= ~J_FOREGROUND;
- jobs[job]->flags |= J_NOTIFIED;
- }
- }
- }
- else
- result = killpg (pid, sig);
-
- UNBLOCK_CHILD (oset);
- }
- else
- result = kill (pid, sig);
-
- return (result);
-}
-
-/* sigchld_handler () flushes at least one of the children that we are
- waiting for. It gets run when we have gotten a SIGCHLD signal. */
-static sighandler
-sigchld_handler (sig)
- int sig;
-{
- int n, oerrno;
-
- oerrno = errno;
- REINSTALL_SIGCHLD_HANDLER;
- sigchld++;
- n = 0;
- if (queue_sigchld == 0)
- n = waitchld (-1, 0);
- errno = oerrno;
- SIGRETURN (n);
-}
-
-/* waitchld() reaps dead or stopped children. It's called by wait_for and
- sigchld_handler, and runs until there aren't any children terminating any
- more.
- If BLOCK is 1, this is to be a blocking wait for a single child, although
- an arriving SIGCHLD could cause the wait to be non-blocking. It returns
- the number of children reaped, or -1 if there are no unwaited-for child
- processes. */
-static int
-waitchld (wpid, block)
- pid_t wpid;
- int block;
-{
- WAIT status;
- PROCESS *child;
- pid_t pid;
- int call_set_current, last_stopped_job, job, children_exited, waitpid_flags;
- static int wcontinued = WCONTINUED; /* run-time fix for glibc problem */
-
- call_set_current = children_exited = 0;
- last_stopped_job = NO_JOB;
-
- do
- {
- /* We don't want to be notified about jobs stopping if job control
- is not active. XXX - was interactive_shell instead of job_control */
- waitpid_flags = (job_control && subshell_environment == 0)
- ? (WUNTRACED|wcontinued)
- : 0;
- if (sigchld || block == 0)
- waitpid_flags |= WNOHANG;
- CHECK_TERMSIG;
- pid = WAITPID (-1, &status, waitpid_flags);
-
- /* WCONTINUED may be rejected by waitpid as invalid even when defined */
- if (wcontinued && pid < 0 && errno == EINVAL)
- {
- wcontinued = 0;
- continue; /* jump back to the test and retry without WCONTINUED */
- }
-
- /* The check for WNOHANG is to make sure we decrement sigchld only
- if it was non-zero before we called waitpid. */
- if (sigchld > 0 && (waitpid_flags & WNOHANG))
- sigchld--;
-
- /* If waitpid returns -1 with errno == ECHILD, there are no more
- unwaited-for child processes of this shell. */
- if (pid < 0 && errno == ECHILD)
- {
- if (children_exited == 0)
- return -1;
- else
- break;
- }
-
- /* If waitpid returns 0, there are running children. If it returns -1,
- the only other error POSIX says it can return is EINTR. */
- CHECK_TERMSIG;
- if (pid <= 0)
- continue; /* jumps right to the test */
-
- /* children_exited is used to run traps on SIGCHLD. We don't want to
- run the trap if a process is just being continued. */
- if (WIFCONTINUED(status) == 0)
- {
- children_exited++;
- js.c_living--;
- }
-
- /* Locate our PROCESS for this pid. */
- child = find_process (pid, 1, &job); /* want living procs only */
-
- /* It is not an error to have a child terminate that we did
- not have a record of. This child could have been part of
- a pipeline in backquote substitution. Even so, I'm not
- sure child is ever non-zero. */
- if (child == 0)
- continue;
-
- /* Remember status, and whether or not the process is running. */
- child->status = status;
- child->running = WIFCONTINUED(status) ? PS_RUNNING : PS_DONE;
-
- if (PEXITED (child))
- {
- js.c_totreaped++;
- if (job != NO_JOB)
- js.c_reaped++;
- }
-
- if (job == NO_JOB)
- continue;
-
- call_set_current += set_job_status_and_cleanup (job);
-
- if (STOPPED (job))
- last_stopped_job = job;
- else if (DEADJOB (job) && last_stopped_job == job)
- last_stopped_job = NO_JOB;
- }
- while ((sigchld || block == 0) && pid > (pid_t)0);
-
- /* If a job was running and became stopped, then set the current
- job. Otherwise, don't change a thing. */
- if (call_set_current)
- {
- if (last_stopped_job != NO_JOB)
- set_current_job (last_stopped_job);
- else
- reset_current ();
- }
-
- /* Call a SIGCHLD trap handler for each child that exits, if one is set. */
- if (job_control && signal_is_trapped (SIGCHLD) && children_exited &&
- trap_list[SIGCHLD] != (char *)IGNORE_SIG)
- run_sigchld_trap (children_exited);
-
- /* We have successfully recorded the useful information about this process
- that has just changed state. If we notify asynchronously, and the job
- that this process belongs to is no longer running, then notify the user
- of that fact now. */
- if (asynchronous_notification && interactive)
- notify_of_job_status ();
-
- return (children_exited);
-}
-
-/* Set the status of JOB and perform any necessary cleanup if the job is
- marked as JDEAD.
-
- Currently, the cleanup activity is restricted to handling any SIGINT
- received while waiting for a foreground job to finish. */
-static int
-set_job_status_and_cleanup (job)
- int job;
-{
- PROCESS *child;
- int tstatus, job_state, any_stopped, any_tstped, call_set_current;
- SigHandler *temp_handler;
-
- child = jobs[job]->pipe;
- jobs[job]->flags &= ~J_NOTIFIED;
-
- call_set_current = 0;
-
- /*
- * COMPUTE JOB STATUS
- */
-
- /* If all children are not running, but any of them is stopped, then
- the job is stopped, not dead. */
- job_state = any_stopped = any_tstped = 0;
- do
- {
- job_state |= PRUNNING (child);
-#if 0
- if (PEXITED (child) && (WIFSTOPPED (child->status)))
-#else
- /* Only checking for WIFSTOPPED now, not for PS_DONE */
- if (PSTOPPED (child))
-#endif
- {
- any_stopped = 1;
- any_tstped |= interactive && job_control &&
- (WSTOPSIG (child->status) == SIGTSTP);
- }
- child = child->next;
- }
- while (child != jobs[job]->pipe);
-
- /* If job_state != 0, the job is still running, so don't bother with
- setting the process exit status and job state unless we're
- transitioning from stopped to running. */
- if (job_state != 0 && JOBSTATE(job) != JSTOPPED)
- return 0;
-
- /*
- * SET JOB STATUS
- */
-
- /* The job is either stopped or dead. Set the state of the job accordingly. */
- if (any_stopped)
- {
- jobs[job]->state = JSTOPPED;
- jobs[job]->flags &= ~J_FOREGROUND;
- call_set_current++;
- /* Suspending a job with SIGTSTP breaks all active loops. */
- if (any_tstped && loop_level)
- breaking = loop_level;
- }
- else if (job_state != 0) /* was stopped, now running */
- {
- jobs[job]->state = JRUNNING;
- call_set_current++;
- }
- else
- {
- jobs[job]->state = JDEAD;
- js.j_ndead++;
-
-#if 0
- if (IS_FOREGROUND (job))
- setjstatus (job);
-#endif
-
- /* If this job has a cleanup function associated with it, call it
- with `cleanarg' as the single argument, then set the function
- pointer to NULL so it is not inadvertently called twice. The
- cleanup function is responsible for deallocating cleanarg. */
- if (jobs[job]->j_cleanup)
- {
- (*jobs[job]->j_cleanup) (jobs[job]->cleanarg);
- jobs[job]->j_cleanup = (sh_vptrfunc_t *)NULL;
- }
- }
-
- /*
- * CLEANUP
- *
- * Currently, we just do special things if we got a SIGINT while waiting
- * for a foreground job to complete
- */
-
- if (JOBSTATE (job) == JDEAD)
- {
- /* If we're running a shell script and we get a SIGINT with a
- SIGINT trap handler, but the foreground job handles it and
- does not exit due to SIGINT, run the trap handler but do not
- otherwise act as if we got the interrupt. */
- if (wait_sigint_received && interactive_shell == 0 &&
- WIFSIGNALED (child->status) == 0 && IS_FOREGROUND (job) &&
- signal_is_trapped (SIGINT))
- {
- int old_frozen;
- wait_sigint_received = 0;
- last_command_exit_value = process_exit_status (child->status);
-
- old_frozen = jobs_list_frozen;
- jobs_list_frozen = 1;
- tstatus = maybe_call_trap_handler (SIGINT);
- jobs_list_frozen = old_frozen;
- }
-
- /* If the foreground job is killed by SIGINT when job control is not
- active, we need to perform some special handling.
-
- The check of wait_sigint_received is a way to determine if the
- SIGINT came from the keyboard (in which case the shell has already
- seen it, and wait_sigint_received is non-zero, because keyboard
- signals are sent to process groups) or via kill(2) to the foreground
- process by another process (or itself). If the shell did receive the
- SIGINT, it needs to perform normal SIGINT processing. */
- else if (wait_sigint_received && (WTERMSIG (child->status) == SIGINT) &&
- IS_FOREGROUND (job) && IS_JOBCONTROL (job) == 0)
- {
- int old_frozen;
-
- wait_sigint_received = 0;
-
- /* If SIGINT is trapped, set the exit status so that the trap
- handler can see it. */
- if (signal_is_trapped (SIGINT))
- last_command_exit_value = process_exit_status (child->status);
-
- /* If the signal is trapped, let the trap handler get it no matter
- what and simply return if the trap handler returns.
- maybe_call_trap_handler() may cause dead jobs to be removed from
- the job table because of a call to execute_command. We work
- around this by setting JOBS_LIST_FROZEN. */
- old_frozen = jobs_list_frozen;
- jobs_list_frozen = 1;
- tstatus = maybe_call_trap_handler (SIGINT);
- jobs_list_frozen = old_frozen;
- if (tstatus == 0 && old_sigint_handler != INVALID_SIGNAL_HANDLER)
- {
- /* wait_sigint_handler () has already seen SIGINT and
- allowed the wait builtin to jump out. We need to
- call the original SIGINT handler, if necessary. If
- the original handler is SIG_DFL, we need to resend
- the signal to ourselves. */
-
- temp_handler = old_sigint_handler;
-
- /* Bogus. If we've reset the signal handler as the result
- of a trap caught on SIGINT, then old_sigint_handler
- will point to trap_handler, which now knows nothing about
- SIGINT (if we reset the sighandler to the default).
- In this case, we have to fix things up. What a crock. */
- if (temp_handler == trap_handler && signal_is_trapped (SIGINT) == 0)
- temp_handler = trap_to_sighandler (SIGINT);
- restore_sigint_handler ();
- if (temp_handler == SIG_DFL)
- termsig_handler (SIGINT);
- else if (temp_handler != SIG_IGN)
- (*temp_handler) (SIGINT);
- }
- }
- }
-
- return call_set_current;
-}
-
-/* Build the array of values for the $PIPESTATUS variable from the set of
- exit statuses of all processes in the job J. */
-static void
-setjstatus (j)
- int j;
-{
-#if defined (ARRAY_VARS)
- register int i;
- register PROCESS *p;
-
- for (i = 1, p = jobs[j]->pipe; p->next != jobs[j]->pipe; p = p->next, i++)
- ;
- i++;
- if (statsize < i)
- {
- pstatuses = (int *)xrealloc (pstatuses, i * sizeof (int));
- statsize = i;
- }
- i = 0;
- p = jobs[j]->pipe;
- do
- {
- pstatuses[i++] = process_exit_status (p->status);
- p = p->next;
- }
- while (p != jobs[j]->pipe);
-
- pstatuses[i] = -1; /* sentinel */
- set_pipestatus_array (pstatuses, i);
-#endif
-}
-
-static void
-run_sigchld_trap (nchild)
- int nchild;
-{
- char *trap_command;
- int i;
-
- /* Turn off the trap list during the call to parse_and_execute ()
- to avoid potentially infinite recursive calls. Preserve the
- values of last_command_exit_value, last_made_pid, and the_pipeline
- around the execution of the trap commands. */
- trap_command = savestring (trap_list[SIGCHLD]);
-
- begin_unwind_frame ("SIGCHLD trap");
- unwind_protect_int (last_command_exit_value);
- unwind_protect_int (last_command_exit_signal);
- unwind_protect_var (last_made_pid);
- unwind_protect_int (interrupt_immediately);
- unwind_protect_int (jobs_list_frozen);
- unwind_protect_pointer (the_pipeline);
- unwind_protect_pointer (subst_assign_varlist);
-
- /* We have to add the commands this way because they will be run
- in reverse order of adding. We don't want maybe_set_sigchld_trap ()
- to reference freed memory. */
- add_unwind_protect (xfree, trap_command);
- add_unwind_protect (maybe_set_sigchld_trap, trap_command);
-
- subst_assign_varlist = (WORD_LIST *)NULL;
- the_pipeline = (PROCESS *)NULL;
-
- restore_default_signal (SIGCHLD);
- jobs_list_frozen = 1;
- for (i = 0; i < nchild; i++)
- {
- interrupt_immediately = 1;
- parse_and_execute (savestring (trap_command), "trap", SEVAL_NOHIST|SEVAL_RESETLINE);
- }
-
- run_unwind_frame ("SIGCHLD trap");
-}
-
-/* Function to call when you want to notify people of changes
- in job status. This prints out all jobs which are pending
- notification to stderr, and marks those printed as already
- notified, thus making them candidates for cleanup. */
-static void
-notify_of_job_status ()
-{
- register int job, termsig;
- char *dir;
- sigset_t set, oset;
- WAIT s;
-
- if (jobs == 0 || js.j_jobslots == 0)
- return;
-
- if (old_ttou != 0)
- {
- sigemptyset (&set);
- sigaddset (&set, SIGCHLD);
- sigaddset (&set, SIGTTOU);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
- }
- else
- queue_sigchld++;
-
- /* XXX could use js.j_firstj here */
- for (job = 0, dir = (char *)NULL; job < js.j_jobslots; job++)
- {
- if (jobs[job] && IS_NOTIFIED (job) == 0)
- {
- s = raw_job_exit_status (job);
- termsig = WTERMSIG (s);
-
- /* POSIX.2 says we have to hang onto the statuses of at most the
- last CHILD_MAX background processes if the shell is running a
- script. If the shell is running a script, either from a file
- or standard input, don't print anything unless the job was
- killed by a signal. */
- if (startup_state == 0 && WIFSIGNALED (s) == 0 &&
- ((DEADJOB (job) && IS_FOREGROUND (job) == 0) || STOPPED (job)))
- continue;
-
-#if 0
- /* If job control is disabled, don't print the status messages.
- Mark dead jobs as notified so that they get cleaned up. If
- startup_state == 2, we were started to run `-c command', so
- don't print anything. */
- if ((job_control == 0 && interactive_shell) || startup_state == 2)
-#else
- /* If job control is disabled, don't print the status messages.
- Mark dead jobs as notified so that they get cleaned up. If
- startup_state == 2 and subshell_environment has the
- SUBSHELL_COMSUB bit turned on, we were started to run a command
- substitution, so don't print anything. */
- if ((job_control == 0 && interactive_shell) ||
- (startup_state == 2 && (subshell_environment & SUBSHELL_COMSUB)))
-#endif
- {
- /* POSIX.2 compatibility: if the shell is not interactive,
- hang onto the job corresponding to the last asynchronous
- pid until the user has been notified of its status or does
- a `wait'. */
- if (DEADJOB (job) && (interactive_shell || (find_last_pid (job, 0) != last_asynchronous_pid)))
- jobs[job]->flags |= J_NOTIFIED;
- continue;
- }
-
- /* Print info on jobs that are running in the background,
- and on foreground jobs that were killed by anything
- except SIGINT (and possibly SIGPIPE). */
- switch (JOBSTATE (job))
- {
- case JDEAD:
- if (interactive_shell == 0 && termsig && WIFSIGNALED (s) &&
- termsig != SIGINT &&
-#if defined (DONT_REPORT_SIGPIPE)
- termsig != SIGPIPE &&
-#endif
- signal_is_trapped (termsig) == 0)
- {
- /* Don't print `0' for a line number. */
- fprintf (stderr, "%s: line %d: ", get_name_for_error (), (line_number == 0) ? 1 : line_number);
- pretty_print_job (job, JLIST_NONINTERACTIVE, stderr);
- }
- else if (IS_FOREGROUND (job))
- {
-#if !defined (DONT_REPORT_SIGPIPE)
- if (termsig && WIFSIGNALED (s) && termsig != SIGINT)
-#else
- if (termsig && WIFSIGNALED (s) && termsig != SIGINT && termsig != SIGPIPE)
-#endif
- {
- fprintf (stderr, "%s", j_strsignal (termsig));
-
- if (WIFCORED (s))
- fprintf (stderr, " (core dumped)");
-
- fprintf (stderr, "\n");
- }
- }
- else if (job_control) /* XXX job control test added */
- {
- if (dir == 0)
- dir = current_working_directory ();
- pretty_print_job (job, JLIST_STANDARD, stderr);
- if (dir && strcmp (dir, jobs[job]->wd) != 0)
- fprintf (stderr,
- "(wd now: %s)\n", polite_directory_format (dir));
- }
-
- jobs[job]->flags |= J_NOTIFIED;
- break;
-
- case JSTOPPED:
- fprintf (stderr, "\n");
- if (dir == 0)
- dir = current_working_directory ();
- pretty_print_job (job, JLIST_STANDARD, stderr);
- if (dir && (strcmp (dir, jobs[job]->wd) != 0))
- fprintf (stderr,
- "(wd now: %s)\n", polite_directory_format (dir));
- jobs[job]->flags |= J_NOTIFIED;
- break;
-
- case JRUNNING:
- case JMIXED:
- break;
-
- default:
- programming_error ("notify_of_job_status");
- }
- }
- }
- if (old_ttou != 0)
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- else
- queue_sigchld--;
-}
-
-/* Initialize the job control mechanism, and set up the tty stuff. */
-int
-initialize_job_control (force)
- int force;
-{
- shell_pgrp = getpgid (0);
-
- if (shell_pgrp == -1)
- {
- sys_error ("initialize_job_control: getpgrp failed");
- exit (1);
- }
-
- /* We can only have job control if we are interactive. */
- if (interactive == 0)
- {
- job_control = 0;
- original_pgrp = NO_PID;
- shell_tty = fileno (stderr);
- }
- else
- {
- /* Get our controlling terminal. If job_control is set, or
- interactive is set, then this is an interactive shell no
- matter where fd 2 is directed. */
- shell_tty = dup (fileno (stderr)); /* fd 2 */
-
- shell_tty = move_to_high_fd (shell_tty, 1, -1);
-
- /* Compensate for a bug in systems that compiled the BSD
- rlogind with DEBUG defined, like NeXT and Alliant. */
- if (shell_pgrp == 0)
- {
- shell_pgrp = getpid ();
- setpgid (0, shell_pgrp);
- tcsetpgrp (shell_tty, shell_pgrp);
- }
-
- while ((terminal_pgrp = tcgetpgrp (shell_tty)) != -1)
- {
- if (shell_pgrp != terminal_pgrp)
- {
- SigHandler *ottin;
-
- ottin = set_signal_handler(SIGTTIN, SIG_DFL);
- kill (0, SIGTTIN);
- set_signal_handler (SIGTTIN, ottin);
- continue;
- }
- break;
- }
-
- /* Make sure that we are using the new line discipline. */
- if (set_new_line_discipline (shell_tty) < 0)
- {
- sys_error ("initialize_job_control: line discipline");
- job_control = 0;
- }
- else
- {
- original_pgrp = shell_pgrp;
- shell_pgrp = getpid ();
-
- if ((original_pgrp != shell_pgrp) && (setpgid (0, shell_pgrp) < 0))
- {
- sys_error ("initialize_job_control: setpgid");
- shell_pgrp = original_pgrp;
- }
-
- job_control = 1;
-
- /* If (and only if) we just set our process group to our pid,
- thereby becoming a process group leader, and the terminal
- is not in the same process group as our (new) process group,
- then set the terminal's process group to our (new) process
- group. If that fails, set our process group back to what it
- was originally (so we can still read from the terminal) and
- turn off job control. */
- if (shell_pgrp != original_pgrp && shell_pgrp != terminal_pgrp)
- {
- if (give_terminal_to (shell_pgrp, 0) < 0)
- {
- setpgid (0, original_pgrp);
- shell_pgrp = original_pgrp;
- job_control = 0;
- }
- }
- }
- if (job_control == 0)
- internal_error (_("no job control in this shell"));
- }
-
- if (shell_tty != fileno (stderr))
- SET_CLOSE_ON_EXEC (shell_tty);
-
- set_signal_handler (SIGCHLD, sigchld_handler);
-
- change_flag ('m', job_control ? '-' : '+');
-
- if (interactive)
- get_tty_state ();
-
- if (js.c_childmax < 0)
- js.c_childmax = getmaxchild ();
- if (js.c_childmax < 0)
- js.c_childmax = DEFAULT_CHILD_MAX;
-
- return job_control;
-}
-
-#ifdef DEBUG
-void
-debug_print_pgrps ()
-{
- itrace("original_pgrp = %ld shell_pgrp = %ld terminal_pgrp = %ld",
- (long)original_pgrp, (long)shell_pgrp, (long)terminal_pgrp);
- itrace("tcgetpgrp(%d) -> %ld, getpgid(0) -> %ld",
- shell_tty, (long)tcgetpgrp (shell_tty), (long)getpgid(0));
-}
-#endif
-
-/* Set the line discipline to the best this system has to offer.
- Return -1 if this is not possible. */
-static int
-set_new_line_discipline (tty)
- int tty;
-{
-#if defined (NEW_TTY_DRIVER)
- int ldisc;
-
- if (ioctl (tty, TIOCGETD, &ldisc) < 0)
- return (-1);
-
- if (ldisc != NTTYDISC)
- {
- ldisc = NTTYDISC;
-
- if (ioctl (tty, TIOCSETD, &ldisc) < 0)
- return (-1);
- }
- return (0);
-#endif /* NEW_TTY_DRIVER */
-
-#if defined (TERMIO_TTY_DRIVER)
-# if defined (TERMIO_LDISC) && (NTTYDISC)
- if (ioctl (tty, TCGETA, &shell_tty_info) < 0)
- return (-1);
-
- if (shell_tty_info.c_line != NTTYDISC)
- {
- shell_tty_info.c_line = NTTYDISC;
- if (ioctl (tty, TCSETAW, &shell_tty_info) < 0)
- return (-1);
- }
-# endif /* TERMIO_LDISC && NTTYDISC */
- return (0);
-#endif /* TERMIO_TTY_DRIVER */
-
-#if defined (TERMIOS_TTY_DRIVER)
-# if defined (TERMIOS_LDISC) && defined (NTTYDISC)
- if (tcgetattr (tty, &shell_tty_info) < 0)
- return (-1);
-
- if (shell_tty_info.c_line != NTTYDISC)
- {
- shell_tty_info.c_line = NTTYDISC;
- if (tcsetattr (tty, TCSADRAIN, &shell_tty_info) < 0)
- return (-1);
- }
-# endif /* TERMIOS_LDISC && NTTYDISC */
- return (0);
-#endif /* TERMIOS_TTY_DRIVER */
-
-#if !defined (NEW_TTY_DRIVER) && !defined (TERMIO_TTY_DRIVER) && !defined (TERMIOS_TTY_DRIVER)
- return (-1);
-#endif
-}
-
-/* Setup this shell to handle C-C, etc. */
-void
-initialize_job_signals ()
-{
- if (interactive)
- {
- set_signal_handler (SIGINT, sigint_sighandler);
- set_signal_handler (SIGTSTP, SIG_IGN);
- set_signal_handler (SIGTTOU, SIG_IGN);
- set_signal_handler (SIGTTIN, SIG_IGN);
- }
- else if (job_control)
- {
- old_tstp = set_signal_handler (SIGTSTP, sigstop_sighandler);
- old_ttin = set_signal_handler (SIGTTIN, sigstop_sighandler);
- old_ttou = set_signal_handler (SIGTTOU, sigstop_sighandler);
- }
- /* Leave these things alone for non-interactive shells without job
- control. */
-}
-
-/* Here we handle CONT signals. */
-static sighandler
-sigcont_sighandler (sig)
- int sig;
-{
- initialize_job_signals ();
- set_signal_handler (SIGCONT, old_cont);
- kill (getpid (), SIGCONT);
-
- SIGRETURN (0);
-}
-
-/* Here we handle stop signals while we are running not as a login shell. */
-static sighandler
-sigstop_sighandler (sig)
- int sig;
-{
- set_signal_handler (SIGTSTP, old_tstp);
- set_signal_handler (SIGTTOU, old_ttou);
- set_signal_handler (SIGTTIN, old_ttin);
-
- old_cont = set_signal_handler (SIGCONT, sigcont_sighandler);
-
- give_terminal_to (shell_pgrp, 0);
-
- kill (getpid (), sig);
-
- SIGRETURN (0);
-}
-
-/* Give the terminal to PGRP. */
-int
-give_terminal_to (pgrp, force)
- pid_t pgrp;
- int force;
-{
- sigset_t set, oset;
- int r;
-
- r = 0;
- if (job_control || force)
- {
- sigemptyset (&set);
- sigaddset (&set, SIGTTOU);
- sigaddset (&set, SIGTTIN);
- sigaddset (&set, SIGTSTP);
- sigaddset (&set, SIGCHLD);
- sigemptyset (&oset);
- sigprocmask (SIG_BLOCK, &set, &oset);
-
- if (tcsetpgrp (shell_tty, pgrp) < 0)
- {
- /* Maybe we should print an error message? */
-#if 0
- sys_error ("tcsetpgrp(%d) failed: pid %ld to pgrp %ld",
- shell_tty, (long)getpid(), (long)pgrp);
-#endif
- r = -1;
- }
- else
- terminal_pgrp = pgrp;
- sigprocmask (SIG_SETMASK, &oset, (sigset_t *)NULL);
- }
-
- return r;
-}
-
-/* Clear out any jobs in the job array. This is intended to be used by
- children of the shell, who should not have any job structures as baggage
- when they start executing (forking subshells for parenthesized execution
- and functions with pipes are the two that spring to mind). If RUNNING_ONLY
- is nonzero, only running jobs are removed from the table. */
-void
-delete_all_jobs (running_only)
- int running_only;
-{
- register int i;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX - need to set j_lastj, j_firstj appropriately if running_only != 0. */
- if (js.j_jobslots)
- {
- js.j_current = js.j_previous = NO_JOB;
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("delete_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("delete_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
- delete_job (i, DEL_WARNSTOPPED);
- }
- if (running_only == 0)
- {
- free ((char *)jobs);
- js.j_jobslots = 0;
- js.j_firstj = js.j_lastj = js.j_njobs = 0;
- }
- }
-
- if (running_only == 0)
- bgp_clear ();
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Mark all jobs in the job array so that they don't get a SIGHUP when the
- shell gets one. If RUNNING_ONLY is nonzero, mark only running jobs. */
-void
-nohup_all_jobs (running_only)
- int running_only;
-{
- register int i;
- sigset_t set, oset;
-
- BLOCK_CHILD (set, oset);
-
- if (js.j_jobslots)
- {
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- if (jobs[i] && (running_only == 0 || (running_only && RUNNING(i))))
- nohup_job (i);
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-int
-count_all_jobs ()
-{
- int i, n;
- sigset_t set, oset;
-
- /* This really counts all non-dead jobs. */
- BLOCK_CHILD (set, oset);
- /* XXX could use js.j_firstj here */
- for (i = n = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("count_all_jobs: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("count_all_jobs: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i] && DEADJOB(i) == 0)
- n++;
- }
- UNBLOCK_CHILD (oset);
- return n;
-}
-
-static void
-mark_all_jobs_as_dead ()
-{
- register int i;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return;
-
- BLOCK_CHILD (set, oset);
-
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- if (jobs[i])
- {
- jobs[i]->state = JDEAD;
- js.j_ndead++;
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Mark all dead jobs as notified, so delete_job () cleans them out
- of the job table properly. POSIX.2 says we need to save the
- status of the last CHILD_MAX jobs, so we count the number of dead
- jobs and mark only enough as notified to save CHILD_MAX statuses. */
-static void
-mark_dead_jobs_as_notified (force)
- int force;
-{
- register int i, ndead, ndeadproc;
- sigset_t set, oset;
-
- if (js.j_jobslots == 0)
- return;
-
- BLOCK_CHILD (set, oset);
-
- /* If FORCE is non-zero, we don't have to keep CHILD_MAX statuses
- around; just run through the array. */
- if (force)
- {
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
- jobs[i]->flags |= J_NOTIFIED;
- }
- UNBLOCK_CHILD (oset);
- return;
- }
-
- /* Mark enough dead jobs as notified to keep CHILD_MAX processes left in the
- array with the corresponding not marked as notified. This is a better
- way to avoid pid aliasing and reuse problems than keeping the POSIX-
- mandated CHILD_MAX jobs around. delete_job() takes care of keeping the
- bgpids list regulated. */
-
- /* Count the number of dead jobs */
- /* XXX could use js.j_firstj here */
- for (i = ndead = ndeadproc = 0; i < js.j_jobslots; i++)
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- if (jobs[i] && DEADJOB (i))
- {
- ndead++;
- ndeadproc += processes_in_job (i);
- }
- }
-
-#ifdef DEBUG
- if (ndeadproc != js.c_reaped)
- itrace("mark_dead_jobs_as_notified: ndeadproc (%d) != js.c_reaped (%d)", ndeadproc, js.c_reaped);
- if (ndead != js.j_ndead)
- itrace("mark_dead_jobs_as_notified: ndead (%d) != js.j_ndead (%d)", ndead, js.j_ndead);
-#endif
-
- if (js.c_childmax < 0)
- js.c_childmax = getmaxchild ();
- if (js.c_childmax < 0)
- js.c_childmax = DEFAULT_CHILD_MAX;
-
- /* Don't do anything if the number of dead processes is less than CHILD_MAX
- and we're not forcing a cleanup. */
- if (ndeadproc <= js.c_childmax)
- {
- UNBLOCK_CHILD (oset);
- return;
- }
-
-#if 0
-itrace("mark_dead_jobs_as_notified: child_max = %d ndead = %d ndeadproc = %d", js.c_childmax, ndead, ndeadproc);
-#endif
-
- /* Mark enough dead jobs as notified that we keep CHILD_MAX jobs in
- the list. This isn't exactly right yet; changes need to be made
- to stop_pipeline so we don't mark the newer jobs after we've
- created CHILD_MAX slots in the jobs array. This needs to be
- integrated with a way to keep the jobs array from growing without
- bound. Maybe we wrap back around to 0 after we reach some max
- limit, and there are sufficient job slots free (keep track of total
- size of jobs array (js.j_jobslots) and running count of number of jobs
- in jobs array. Then keep a job index corresponding to the `oldest job'
- and start this loop there, wrapping around as necessary. In effect,
- we turn the list into a circular buffer. */
- /* XXX could use js.j_firstj here */
- for (i = 0; i < js.j_jobslots; i++)
- {
- if (jobs[i] && DEADJOB (i) && (interactive_shell || (find_last_pid (i, 0) != last_asynchronous_pid)))
- {
-#if defined (DEBUG)
- if (i < js.j_firstj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null before js.j_firstj (%d)", i, js.j_firstj);
- if (i > js.j_lastj && jobs[i])
- itrace("mark_dead_jobs_as_notified: job %d non-null after js.j_lastj (%d)", i, js.j_lastj);
-#endif
- /* If marking this job as notified would drop us down below
- child_max, don't mark it so we can keep at least child_max
- statuses. XXX -- need to check what Posix actually says
- about keeping statuses. */
- if ((ndeadproc -= processes_in_job (i)) <= js.c_childmax)
- break;
- jobs[i]->flags |= J_NOTIFIED;
- }
- }
-
- UNBLOCK_CHILD (oset);
-}
-
-/* Here to allow other parts of the shell (like the trap stuff) to
- unfreeze the jobs list. */
-void
-unfreeze_jobs_list ()
-{
- jobs_list_frozen = 0;
-}
-
-/* Allow or disallow job control to take place. Returns the old value
- of job_control. */
-int
-set_job_control (arg)
- int arg;
-{
- int old;
-
- old = job_control;
- job_control = arg;
-
- /* If we're turning on job control, reset pipeline_pgrp so make_child will
- put new child processes into the right pgrp */
- if (job_control != old && job_control)
- pipeline_pgrp = 0;
-
- return (old);
-}
-
-/* Turn off all traces of job control. This is run by children of the shell
- which are going to do shellsy things, like wait (), etc. */
-void
-without_job_control ()
-{
- stop_making_children ();
- start_pipeline ();
-#if defined (PGRP_PIPE)
- pipe_close (pgrp_pipe);
-#endif
- delete_all_jobs (0);
- set_job_control (0);
-}
-
-/* If this shell is interactive, terminate all stopped jobs and
- restore the original terminal process group. This is done
- before the `exec' builtin calls shell_execve. */
-void
-end_job_control ()
-{
- if (interactive_shell) /* XXX - should it be interactive? */
- {
- terminate_stopped_jobs ();
-
- if (original_pgrp >= 0)
- give_terminal_to (original_pgrp, 1);
- }
-
- if (original_pgrp >= 0)
- setpgid (0, original_pgrp);
-}
-
-/* Restart job control by closing shell tty and reinitializing. This is
- called after an exec fails in an interactive shell and we do not exit. */
-void
-restart_job_control ()
-{
- if (shell_tty != -1)
- close (shell_tty);
- initialize_job_control (0);
-}
-
-/* Set the handler to run when the shell receives a SIGCHLD signal. */
-void
-set_sigchld_handler ()
-{
- set_signal_handler (SIGCHLD, sigchld_handler);
-}
-
-#if defined (PGRP_PIPE)
-/* Read from the read end of a pipe. This is how the process group leader
- blocks until all of the processes in a pipeline have been made. */
-static void
-pipe_read (pp)
- int *pp;
-{
- char ch;
-
- if (pp[1] >= 0)
- {
- close (pp[1]);
- pp[1] = -1;
- }
-
- if (pp[0] >= 0)
- {
- while (read (pp[0], &ch, 1) == -1 && errno == EINTR)
- ;
- }
-}
-
-/* Close the read and write ends of PP, an array of file descriptors. */
-static void
-pipe_close (pp)
- int *pp;
-{
- if (pp[0] >= 0)
- close (pp[0]);
-
- if (pp[1] >= 0)
- close (pp[1]);
-
- pp[0] = pp[1] = -1;
-}
-
-/* Functional interface closes our local-to-job-control pipes. */
-void
-close_pgrp_pipe ()
-{
- pipe_close (pgrp_pipe);
-}
-
-#endif /* PGRP_PIPE */
diff --git a/lib/glob/glob.c~ b/lib/glob/glob.c~
deleted file mode 100644
index 5395bcbb..00000000
--- a/lib/glob/glob.c~
+++ /dev/null
@@ -1,891 +0,0 @@
-/* glob.c -- file-name wildcard pattern matching for Bash.
-
- Copyright (C) 1985-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. */
-
-/* To whomever it may concern: I have never seen the code which most
- Unix programs use to perform this function. I wrote this from scratch
- based on specifications for the pattern matching. --RMS. */
-
-#include <config.h>
-
-#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
- #pragma alloca
-#endif /* _AIX && RISC6000 && !__GNUC__ */
-
-#include "bashtypes.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "bashansi.h"
-#include "posixdir.h"
-#include "posixstat.h"
-#include "shmbutil.h"
-#include "xmalloc.h"
-
-#include "filecntl.h"
-#if !defined (F_OK)
-# define F_OK 0
-#endif
-
-#include "stdc.h"
-#include "memalloc.h"
-#include "quit.h"
-
-#include "glob.h"
-#include "strmatch.h"
-
-#if !defined (HAVE_BCOPY) && !defined (bcopy)
-# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
-#endif /* !HAVE_BCOPY && !bcopy */
-
-#if !defined (NULL)
-# if defined (__STDC__)
-# define NULL ((void *) 0)
-# else
-# define NULL 0x0
-# endif /* __STDC__ */
-#endif /* !NULL */
-
-#if !defined (FREE)
-# define FREE(x) if (x) free (x)
-#endif
-
-/* Don't try to alloca() more than this much memory for `struct globval'
- in glob_vector() */
-#ifndef ALLOCA_MAX
-# define ALLOCA_MAX 100000
-#endif
-
-extern void throw_to_top_level __P((void));
-extern int sh_eaccess __P((char *, int));
-
-extern int extended_glob;
-
-/* Global variable which controls whether or not * matches .*.
- Non-zero means don't match .*. */
-int noglob_dot_filenames = 1;
-
-/* Global variable which controls whether or not filename globbing
- is done without regard to case. */
-int glob_ignore_case = 0;
-
-/* Global variable to return to signify an error in globbing. */
-char *glob_error_return;
-
-/* Some forward declarations. */
-static int skipname __P((char *, char *));
-#if HANDLE_MULTIBYTE
-static int mbskipname __P((char *, char *));
-#endif
-#if HANDLE_MULTIBYTE
-static void udequote_pathname __P((char *));
-static void wdequote_pathname __P((char *));
-#else
-# define dequote_pathname udequote_pathname
-#endif
-static void dequote_pathname __P((char *));
-static int glob_testdir __P((char *));
-static char **glob_dir_to_array __P((char *, char **, int));
-
-/* Compile `glob_loop.c' for single-byte characters. */
-#define CHAR unsigned char
-#define INT int
-#define L(CS) CS
-#define INTERNAL_GLOB_PATTERN_P internal_glob_pattern_p
-#include "glob_loop.c"
-
-/* Compile `glob_loop.c' again for multibyte characters. */
-#if HANDLE_MULTIBYTE
-
-#define CHAR wchar_t
-#define INT wint_t
-#define L(CS) L##CS
-#define INTERNAL_GLOB_PATTERN_P internal_glob_wpattern_p
-#include "glob_loop.c"
-
-#endif /* HANDLE_MULTIBYTE */
-
-/* And now a function that calls either the single-byte or multibyte version
- of internal_glob_pattern_p. */
-int
-glob_pattern_p (pattern)
- const char *pattern;
-{
-#if HANDLE_MULTIBYTE
- size_t n;
- wchar_t *wpattern;
- int r;
-
- if (MB_CUR_MAX == 1)
- return (internal_glob_pattern_p ((unsigned char *)pattern));
-
- /* Convert strings to wide chars, and call the multibyte version. */
- n = xdupmbstowcs (&wpattern, NULL, pattern);
- if (n == (size_t)-1)
- /* Oops. Invalid multibyte sequence. Try it as single-byte sequence. */
- return (internal_glob_pattern_p ((unsigned char *)pattern));
-
- r = internal_glob_wpattern_p (wpattern);
- free (wpattern);
-
- return r;
-#else
- return (internal_glob_pattern_p (pattern));
-#endif
-}
-
-/* Return 1 if DNAME should be skipped according to PAT. Mostly concerned
- with matching leading `.'. */
-
-static int
-skipname (pat, dname)
- char *pat;
- char *dname;
-{
- /* If a leading dot need not be explicitly matched, and the pattern
- doesn't start with a `.', don't match `.' or `..' */
- if (noglob_dot_filenames == 0 && pat[0] != '.' &&
- (pat[0] != '\\' || pat[1] != '.') &&
- (dname[0] == '.' &&
- (dname[1] == '\0' || (dname[1] == '.' && dname[2] == '\0'))))
- return 1;
-
- /* If a dot must be explicity matched, check to see if they do. */
- else if (noglob_dot_filenames && dname[0] == '.' && pat[0] != '.' &&
- (pat[0] != '\\' || pat[1] != '.'))
- return 1;
-
- return 0;
-}
-
-#if HANDLE_MULTIBYTE
-/* Return 1 if DNAME should be skipped according to PAT. Handles multibyte
- characters in PAT and DNAME. Mostly concerned with matching leading `.'. */
-
-static int
-mbskipname (pat, dname)
- char *pat, *dname;
-{
- int ret;
- wchar_t *pat_wc, *dn_wc;
- size_t pat_n, dn_n, n;
-
- pat_n = xdupmbstowcs (&pat_wc, NULL, pat);
- dn_n = xdupmbstowcs (&dn_wc, NULL, dname);
-
- ret = 0;
- if (pat_n != (size_t)-1 && dn_n !=(size_t)-1)
- {
- /* If a leading dot need not be explicitly matched, and the
- pattern doesn't start with a `.', don't match `.' or `..' */
- if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' &&
- (pat_wc[0] != L'\\' || pat_wc[1] != L'.') &&
- (dn_wc[0] == L'.' &&
- (dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0'))))
- ret = 1;
-
- /* If a leading dot must be explicity matched, check to see if the
- pattern and dirname both have one. */
- else if (noglob_dot_filenames && dn_wc[0] == L'.' &&
- pat_wc[0] != L'.' &&
- (pat_wc[0] != L'\\' || pat_wc[1] != L'.'))
- ret = 1;
- }
-
- FREE (pat_wc);
- FREE (dn_wc);
-
- return ret;
-}
-#endif /* HANDLE_MULTIBYTE */
-
-/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
-static void
-udequote_pathname (pathname)
- char *pathname;
-{
- register int i, j;
-
- for (i = j = 0; pathname && pathname[i]; )
- {
- if (pathname[i] == '\\')
- i++;
-
- pathname[j++] = pathname[i++];
-
- if (pathname[i - 1] == 0)
- break;
- }
- pathname[j] = '\0';
-}
-
-#if HANDLE_MULTIBYTE
-/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
-static void
-wdequote_pathname (pathname)
- char *pathname;
-{
- mbstate_t ps;
- size_t len, n;
- wchar_t *wpathname;
- int i, j;
- wchar_t *orig_wpathname;
-
- len = strlen (pathname);
- /* Convert the strings into wide characters. */
- n = xdupmbstowcs (&wpathname, NULL, pathname);
- if (n == (size_t) -1)
- /* Something wrong. */
- return;
- orig_wpathname = wpathname;
-
- for (i = j = 0; wpathname && wpathname[i]; )
- {
- if (wpathname[i] == L'\\')
- i++;
-
- wpathname[j++] = wpathname[i++];
-
- if (wpathname[i - 1] == L'\0')
- break;
- }
- wpathname[j] = L'\0';
-
- /* Convert the wide character string into unibyte character set. */
- memset (&ps, '\0', sizeof(mbstate_t));
- n = wcsrtombs(pathname, (const wchar_t **)&wpathname, len, &ps);
- pathname[len] = '\0';
-
- /* Can't just free wpathname here; wcsrtombs changes it in many cases. */
- free (orig_wpathname);
-}
-
-static void
-dequote_pathname (pathname)
- char *pathname;
-{
- if (MB_CUR_MAX > 1)
- wdequote_pathname (pathname);
- else
- udequote_pathname (pathname);
-}
-#endif /* HANDLE_MULTIBYTE */
-
-/* Test whether NAME exists. */
-
-#if defined (HAVE_LSTAT)
-# define GLOB_TESTNAME(name) (lstat (name, &finfo))
-#else /* !HAVE_LSTAT */
-# if !defined (AFS)
-# define GLOB_TESTNAME(name) (sh_eaccess (nextname, F_OK))
-# else /* AFS */
-# define GLOB_TESTNAME(name) (access (nextname, F_OK))
-# endif /* AFS */
-#endif /* !HAVE_LSTAT */
-
-/* Return 0 if DIR is a directory, -1 otherwise. */
-static int
-glob_testdir (dir)
- char *dir;
-{
- struct stat finfo;
-
- if (stat (dir, &finfo) < 0)
- return (-1);
-
- if (S_ISDIR (finfo.st_mode) == 0)
- return (-1);
-
- return (0);
-}
-
-/* Return a vector of names of files in directory DIR
- whose names match glob pattern PAT.
- The names are not in any particular order.
- Wildcards at the beginning of PAT do not match an initial period.
-
- The vector is terminated by an element that is a null pointer.
-
- To free the space allocated, first free the vector's elements,
- then free the vector.
-
- Return 0 if cannot get enough memory to hold the pointer
- and the names.
-
- Return -1 if cannot access directory DIR.
- Look in errno for more information. */
-
-char **
-glob_vector (pat, dir, flags)
- char *pat;
- char *dir;
- int flags;
-{
- struct globval
- {
- struct globval *next;
- char *name;
- };
-
- DIR *d;
- register struct dirent *dp;
- struct globval *lastlink;
- register struct globval *nextlink;
- register char *nextname, *npat;
- unsigned int count;
- int lose, skip;
- register char **name_vector;
- register unsigned int i;
- int mflags; /* Flags passed to strmatch (). */
- int nalloca;
- struct globval *firstmalloc, *tmplink;
-
- lastlink = 0;
- count = lose = skip = 0;
-
- firstmalloc = 0;
- nalloca = 0;
-
- /* If PAT is empty, skip the loop, but return one (empty) filename. */
- if (pat == 0 || *pat == '\0')
- {
- if (glob_testdir (dir) < 0)
- return ((char **) &glob_error_return);
-
- nextlink = (struct globval *)alloca (sizeof (struct globval));
- if (nextlink == NULL)
- return ((char **) NULL);
-
- nextlink->next = (struct globval *)0;
- nextname = (char *) malloc (1);
- if (nextname == 0)
- lose = 1;
- else
- {
- lastlink = nextlink;
- nextlink->name = nextname;
- nextname[0] = '\0';
- count = 1;
- }
-
- skip = 1;
- }
-
- /* If the filename pattern (PAT) does not contain any globbing characters,
- we can dispense with reading the directory, and just see if there is
- a filename `DIR/PAT'. If there is, and we can access it, just make the
- vector to return and bail immediately. */
- if (skip == 0 && glob_pattern_p (pat) == 0)
- {
- int dirlen;
- struct stat finfo;
-
- if (glob_testdir (dir) < 0)
- return ((char **) &glob_error_return);
-
- dirlen = strlen (dir);
- nextname = (char *)malloc (dirlen + strlen (pat) + 2);
- npat = (char *)malloc (strlen (pat) + 1);
- if (nextname == 0 || npat == 0)
- lose = 1;
- else
- {
- strcpy (npat, pat);
- dequote_pathname (npat);
-
- strcpy (nextname, dir);
- nextname[dirlen++] = '/';
- strcpy (nextname + dirlen, npat);
-
- if (GLOB_TESTNAME (nextname) >= 0)
- {
- free (nextname);
- nextlink = (struct globval *)alloca (sizeof (struct globval));
- if (nextlink)
- {
- nextlink->next = (struct globval *)0;
- lastlink = nextlink;
- nextlink->name = npat;
- count = 1;
- }
- else
- lose = 1;
- }
- else
- {
- free (nextname);
- free (npat);
- }
- }
-
- skip = 1;
- }
-
- if (skip == 0)
- {
- /* Open the directory, punting immediately if we cannot. If opendir
- is not robust (i.e., it opens non-directories successfully), test
- that DIR is a directory and punt if it's not. */
-#if defined (OPENDIR_NOT_ROBUST)
- if (glob_testdir (dir) < 0)
- return ((char **) &glob_error_return);
-#endif
-
- d = opendir (dir);
- if (d == NULL)
- return ((char **) &glob_error_return);
-
- /* Compute the flags that will be passed to strmatch(). We don't
- need to do this every time through the loop. */
- mflags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
-
-#ifdef FNM_CASEFOLD
- if (glob_ignore_case)
- mflags |= FNM_CASEFOLD;
-#endif
-
- if (extended_glob)
- mflags |= FNM_EXTMATCH;
-
- /* Scan the directory, finding all names that match.
- For each name that matches, allocate a struct globval
- on the stack and store the name in it.
- Chain those structs together; lastlink is the front of the chain. */
- while (1)
- {
- /* Make globbing interruptible in the shell. */
- if (interrupt_state)
- {
- lose = 1;
- break;
- }
-
- dp = readdir (d);
- if (dp == NULL)
- break;
-
- /* If this directory entry is not to be used, try again. */
- if (REAL_DIR_ENTRY (dp) == 0)
- continue;
-
-#if 0
- if (dp->d_name == 0 || *dp->d_name == 0)
- continue;
-#endif
-
-#if HANDLE_MULTIBYTE
- if (MB_CUR_MAX > 1 && mbskipname (pat, dp->d_name))
- continue;
- else
-#endif
- if (skipname (pat, dp->d_name))
- continue;
-
- if (strmatch (pat, dp->d_name, mflags) != FNM_NOMATCH)
- {
- if (nalloca < ALLOCA_MAX)
- {
- nextlink = (struct globval *) alloca (sizeof (struct globval));
- nalloca += sizeof (struct globval);
- }
- else
- {
- nextlink = (struct globval *) malloc (sizeof (struct globval));
- if (firstmalloc == 0)
- firstmalloc = nextlink;
- }
- nextname = (char *) malloc (D_NAMLEN (dp) + 1);
- if (nextlink == 0 || nextname == 0)
- {
- lose = 1;
- break;
- }
- nextlink->next = lastlink;
- lastlink = nextlink;
- nextlink->name = nextname;
- bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
- ++count;
- }
- }
-
- (void) closedir (d);
- }
-
- if (lose == 0)
- {
- name_vector = (char **) malloc ((count + 1) * sizeof (char *));
- lose |= name_vector == NULL;
- }
-
- /* Have we run out of memory? */
- if (lose)
- {
- tmplink = 0;
-
- /* Here free the strings we have got. */
- while (lastlink)
- {
- /* Since we build the list in reverse order, the first N entries
- will be allocated with malloc, if firstmalloc is set, from
- lastlink to firstmalloc. */
- if (firstmalloc)
- {
- if (lastlink == firstmalloc)
- firstmalloc = 0;
- tmplink = lastlink;
- }
- else
- tmplink = 0;
- free (lastlink->name);
- lastlink = lastlink->next;
- FREE (tmplink);
- }
-
- QUIT;
-
- return ((char **)NULL);
- }
-
- /* Copy the name pointers from the linked list into the vector. */
- for (tmplink = lastlink, i = 0; i < count; ++i)
- {
- name_vector[i] = tmplink->name;
- tmplink = tmplink->next;
- }
-
- name_vector[count] = NULL;
-
- /* If we allocated some of the struct globvals, free them now. */
- if (firstmalloc)
- {
- tmplink = 0;
- while (lastlink)
- {
- tmplink = lastlink;
- if (lastlink == firstmalloc)
- lastlink = firstmalloc = 0;
- else
- lastlink = lastlink->next;
- free (tmplink);
- }
- }
-
- return (name_vector);
-}
-
-/* Return a new array which is the concatenation of each string in ARRAY
- to DIR. This function expects you to pass in an allocated ARRAY, and
- it takes care of free()ing that array. Thus, you might think of this
- function as side-effecting ARRAY. This should handle GX_MARKDIRS. */
-static char **
-glob_dir_to_array (dir, array, flags)
- char *dir, **array;
- int flags;
-{
- register unsigned int i, l;
- int add_slash;
- char **result, *new;
- struct stat sb;
-
- l = strlen (dir);
- if (l == 0)
- {
- if (flags & GX_MARKDIRS)
- for (i = 0; array[i]; i++)
- {
- if ((stat (array[i], &sb) == 0) && S_ISDIR (sb.st_mode))
- {
- l = strlen (array[i]);
- new = (char *)realloc (array[i], l + 2);
- if (new == 0)
- return NULL;
- new[l] = '/';
- new[l+1] = '\0';
- array[i] = new;
- }
- }
- return (array);
- }
-
- add_slash = dir[l - 1] != '/';
-
- i = 0;
- while (array[i] != NULL)
- ++i;
-
- result = (char **) malloc ((i + 1) * sizeof (char *));
- if (result == NULL)
- return (NULL);
-
- for (i = 0; array[i] != NULL; i++)
- {
- /* 3 == 1 for NUL, 1 for slash at end of DIR, 1 for GX_MARKDIRS */
- result[i] = (char *) malloc (l + strlen (array[i]) + 3);
-
- if (result[i] == NULL)
- return (NULL);
-
- strcpy (result[i], dir);
- if (add_slash)
- result[i][l] = '/';
- strcpy (result[i] + l + add_slash, array[i]);
- if (flags & GX_MARKDIRS)
- {
- if ((stat (result[i], &sb) == 0) && S_ISDIR (sb.st_mode))
- {
- size_t rlen;
- rlen = strlen (result[i]);
- result[i][rlen] = '/';
- result[i][rlen+1] = '\0';
- }
- }
- }
- result[i] = NULL;
-
- /* Free the input array. */
- for (i = 0; array[i] != NULL; i++)
- free (array[i]);
- free ((char *) array);
-
- return (result);
-}
-
-/* Do globbing on PATHNAME. Return an array of pathnames that match,
- marking the end of the array with a null-pointer as an element.
- If no pathnames match, then the array is empty (first element is null).
- If there isn't enough memory, then return NULL.
- If a file system error occurs, return -1; `errno' has the error code. */
-char **
-glob_filename (pathname, flags)
- char *pathname;
- int flags;
-{
- char **result;
- unsigned int result_size;
- char *directory_name, *filename;
- unsigned int directory_len;
- int free_dirname; /* flag */
-
- result = (char **) malloc (sizeof (char *));
- result_size = 1;
- if (result == NULL)
- return (NULL);
-
- result[0] = NULL;
-
- directory_name = NULL;
-
- /* Find the filename. */
- filename = strrchr (pathname, '/');
- if (filename == NULL)
- {
- filename = pathname;
- directory_name = "";
- directory_len = 0;
- free_dirname = 0;
- }
- else
- {
- directory_len = (filename - pathname) + 1;
- directory_name = (char *) malloc (directory_len + 1);
-
- if (directory_name == 0) /* allocation failed? */
- return (NULL);
-
- bcopy (pathname, directory_name, directory_len);
- directory_name[directory_len] = '\0';
- ++filename;
- free_dirname = 1;
- }
-
- /* If directory_name contains globbing characters, then we
- have to expand the previous levels. Just recurse. */
- if (glob_pattern_p (directory_name))
- {
- char **directories;
- register unsigned int i;
-
- if (directory_name[directory_len - 1] == '/')
- directory_name[directory_len - 1] = '\0';
-
- directories = glob_filename (directory_name, flags & ~GX_MARKDIRS);
-
- if (free_dirname)
- {
- free (directory_name);
- directory_name = NULL;
- }
-
- if (directories == NULL)
- goto memory_error;
- else if (directories == (char **)&glob_error_return)
- {
- free ((char *) result);
- return ((char **) &glob_error_return);
- }
- else if (*directories == NULL)
- {
- free ((char *) directories);
- free ((char *) result);
- return ((char **) &glob_error_return);
- }
-
- /* We have successfully globbed the preceding directory name.
- For each name in DIRECTORIES, call glob_vector on it and
- FILENAME. Concatenate the results together. */
- for (i = 0; directories[i] != NULL; ++i)
- {
- char **temp_results;
-
- /* Scan directory even on a NULL pathname. That way, `*h/'
- returns only directories ending in `h', instead of all
- files ending in `h' with a `/' appended. */
- temp_results = glob_vector (filename, directories[i], flags & ~GX_MARKDIRS);
-
- /* Handle error cases. */
- if (temp_results == NULL)
- goto memory_error;
- else if (temp_results == (char **)&glob_error_return)
- /* This filename is probably not a directory. Ignore it. */
- ;
- else
- {
- char **array;
- register unsigned int l;
-
- array = glob_dir_to_array (directories[i], temp_results, flags);
- l = 0;
- while (array[l] != NULL)
- ++l;
-
- result =
- (char **)realloc (result, (result_size + l) * sizeof (char *));
-
- if (result == NULL)
- goto memory_error;
-
- for (l = 0; array[l] != NULL; ++l)
- result[result_size++ - 1] = array[l];
-
- result[result_size - 1] = NULL;
-
- /* Note that the elements of ARRAY are not freed. */
- free ((char *) array);
- }
- }
- /* Free the directories. */
- for (i = 0; directories[i]; i++)
- free (directories[i]);
-
- free ((char *) directories);
-
- return (result);
- }
-
- /* If there is only a directory name, return it. */
- if (*filename == '\0')
- {
- result = (char **) realloc ((char *) result, 2 * sizeof (char *));
- if (result == NULL)
- return (NULL);
- /* Handle GX_MARKDIRS here. */
- result[0] = (char *) malloc (directory_len + 1);
- if (result[0] == NULL)
- goto memory_error;
- bcopy (directory_name, result[0], directory_len + 1);
- if (free_dirname)
- free (directory_name);
- result[1] = NULL;
- return (result);
- }
- else
- {
- char **temp_results;
-
- /* There are no unquoted globbing characters in DIRECTORY_NAME.
- Dequote it before we try to open the directory since there may
- be quoted globbing characters which should be treated verbatim. */
- if (directory_len > 0)
- dequote_pathname (directory_name);
-
- /* We allocated a small array called RESULT, which we won't be using.
- Free that memory now. */
- free (result);
-
- /* Just return what glob_vector () returns appended to the
- directory name. */
- temp_results = glob_vector (filename,
- (directory_len == 0 ? "." : directory_name),
- flags & ~GX_MARKDIRS);
-
- if (temp_results == NULL || temp_results == (char **)&glob_error_return)
- {
- if (free_dirname)
- free (directory_name);
- return (temp_results);
- }
-
- result = glob_dir_to_array (directory_name, temp_results, flags);
- if (free_dirname)
- free (directory_name);
- return (result);
- }
-
- /* We get to memory_error if the program has run out of memory, or
- if this is the shell, and we have been interrupted. */
- memory_error:
- if (result != NULL)
- {
- register unsigned int i;
- for (i = 0; result[i] != NULL; ++i)
- free (result[i]);
- free ((char *) result);
- }
-
- if (free_dirname && directory_name)
- free (directory_name);
-
- QUIT;
-
- return (NULL);
-}
-
-#if defined (TEST)
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- unsigned int i;
-
- for (i = 1; i < argc; ++i)
- {
- char **value = glob_filename (argv[i], 0);
- if (value == NULL)
- puts ("Out of memory.");
- else if (value == &glob_error_return)
- perror (argv[i]);
- else
- for (i = 0; value[i] != NULL; i++)
- puts (value[i]);
- }
-
- exit (0);
-}
-#endif /* TEST. */
diff --git a/lib/glob/xmbsrtowcs.c~ b/lib/glob/xmbsrtowcs.c~
deleted file mode 100644
index f8c29b91..00000000
--- a/lib/glob/xmbsrtowcs.c~
+++ /dev/null
@@ -1,250 +0,0 @@
-/* xmbsrtowcs.c -- replacement function for mbsrtowcs */
-
-/* Copyright (C) 2002-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>
-
-#include <bashansi.h>
-
-/* <wchar.h>, <wctype.h> and <stdlib.h> are included in "shmbutil.h".
- If <wchar.h>, <wctype.h>, mbsrtowcs(), exist, HANDLE_MULTIBYTE
- is defined as 1. */
-#include <shmbutil.h>
-
-#if HANDLE_MULTIBYTE
-/* On some locales (ex. ja_JP.sjis), mbsrtowc doesn't convert 0x5c to U<0x5c>.
- So, this function is made for converting 0x5c to U<0x5c>. */
-
-static mbstate_t local_state;
-static int local_state_use = 0;
-
-size_t
-xmbsrtowcs (dest, src, len, pstate)
- wchar_t *dest;
- const char **src;
- size_t len;
- mbstate_t *pstate;
-{
- mbstate_t *ps;
- size_t mblength, wclength, n;
-
- ps = pstate;
- if (pstate == NULL)
- {
- if (!local_state_use)
- {
- memset (&local_state, '\0', sizeof(mbstate_t));
- local_state_use = 1;
- }
- ps = &local_state;
- }
-
- n = strlen (*src);
-
- if (dest == NULL)
- {
- wchar_t *wsbuf;
- const char *mbs;
- mbstate_t psbuf;
-
- /* It doesn't matter if malloc fails here, since mbsrtowcs should do
- the right thing with a NULL first argument. */
- wsbuf = (wchar_t *) malloc ((n + 1) * sizeof(wchar_t));
- mbs = *src;
- psbuf = *ps;
-
- wclength = mbsrtowcs (wsbuf, &mbs, n, &psbuf);
-
- if (wsbuf)
- free (wsbuf);
- return wclength;
- }
-
- for (wclength = 0; wclength < len; wclength++, dest++)
- {
- if (mbsinit(ps))
- {
- if (**src == '\0')
- {
- *dest = L'\0';
- *src = NULL;
- return (wclength);
- }
- else if (**src == '\\')
- {
- *dest = L'\\';
- mblength = 1;
- }
- else
- mblength = mbrtowc(dest, *src, n, ps);
- }
- else
- mblength = mbrtowc(dest, *src, n, ps);
-
- /* Cannot convert multibyte character to wide character. */
- if (mblength == (size_t)-1 || mblength == (size_t)-2)
- return (size_t)-1;
-
- *src += mblength;
- n -= mblength;
-
- /* The multibyte string has been completely converted,
- including the terminating '\0'. */
- if (*dest == L'\0')
- {
- *src = NULL;
- break;
- }
- }
-
- return (wclength);
-}
-
-/* Convert a multibyte string to a wide character string. Memory for the
- new wide character string is obtained with malloc.
-
- The return value is the length of the wide character string. Returns a
- pointer to the wide character string in DESTP. If INDICESP is not NULL,
- INDICESP stores the pointer to the pointer array. Each pointer is to
- the first byte of each multibyte character. Memory for the pointer array
- is obtained with malloc, too.
- If conversion is failed, the return value is (size_t)-1 and the values
- of DESTP and INDICESP are NULL. */
-
-#define WSBUF_INC 32
-
-size_t
-xdupmbstowcs (destp, indicesp, src)
- wchar_t **destp; /* Store the pointer to the wide character string */
- char ***indicesp; /* Store the pointer to the pointer array. */
- const char *src; /* Multibyte character string */
-{
- const char *p; /* Conversion start position of src */
- wchar_t wc; /* Created wide character by conversion */
- wchar_t *wsbuf; /* Buffer for wide characters. */
- char **indices; /* Buffer for indices. */
- size_t wsbuf_size; /* Size of WSBUF */
- size_t wcnum; /* Number of wide characters in WSBUF */
- mbstate_t state; /* Conversion State */
-
- /* In case SRC or DESP is NULL, conversion doesn't take place. */
- if (src == NULL || destp == NULL)
- {
- *destp = NULL;
- return (size_t)-1;
- }
-
- memset (&state, '\0', sizeof(mbstate_t));
- wsbuf_size = WSBUF_INC;
-
- wsbuf = (wchar_t *) malloc (wsbuf_size * sizeof(wchar_t));
- if (wsbuf == NULL)
- {
- *destp = NULL;
- return (size_t)-1;
- }
-
- indices = (char **) malloc (wsbuf_size * sizeof(char *));
- if (indices == NULL)
- {
- free (wsbuf);
- *destp = NULL;
- return (size_t)-1;
- }
-
- p = src;
- wcnum = 0;
- do
- {
- size_t mblength; /* Byte length of one multibyte character. */
-
- if (mbsinit (&state))
- {
- if (*p == '\0')
- {
- wc = L'\0';
- mblength = 1;
- }
- else if (*p == '\\')
- {
- wc = L'\\';
- mblength = 1;
- }
- else
- mblength = mbrtowc(&wc, p, MB_LEN_MAX, &state);
- }
- else
- mblength = mbrtowc(&wc, p, MB_LEN_MAX, &state);
-
- /* Conversion failed. */
- if (MB_INVALIDCH (mblength))
- {
- free (wsbuf);
- free (indices);
- *destp = NULL;
- return (size_t)-1;
- }
-
- ++wcnum;
-
- /* Resize buffers when they are not large enough. */
- if (wsbuf_size < wcnum)
- {
- wchar_t *wstmp;
- char **idxtmp;
-
- wsbuf_size += WSBUF_INC;
-
- wstmp = (wchar_t *) realloc (wsbuf, wsbuf_size * sizeof (wchar_t));
- if (wstmp == NULL)
- {
- free (wsbuf);
- free (indices);
- *destp = NULL;
- return (size_t)-1;
- }
- wsbuf = wstmp;
-
- idxtmp = (char **) realloc (indices, wsbuf_size * sizeof (char **));
- if (idxtmp == NULL)
- {
- free (wsbuf);
- free (indices);
- *destp = NULL;
- return (size_t)-1;
- }
- indices = idxtmp;
- }
-
- wsbuf[wcnum - 1] = wc;
- indices[wcnum - 1] = (char *)p;
- p += mblength;
- }
- while (MB_NULLWCH (wc) == 0);
-
- /* Return the length of the wide character string, not including `\0'. */
- *destp = wsbuf;
- if (indicesp != NULL)
- *indicesp = indices;
- else
- free (indices);
-
- return (wcnum - 1);
-}
-
-#endif /* HANDLE_MULTIBYTE */
diff --git a/lib/malloc/stats.c~ b/lib/malloc/stats.c~
deleted file mode 100644
index 18c3cef5..00000000
--- a/lib/malloc/stats.c~
+++ /dev/null
@@ -1,202 +0,0 @@
-/* stats.c - malloc statistics */
-
-/* Copyright (C) 2001-2003 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. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "imalloc.h"
-
-#ifdef MALLOC_STATS
-
-#include <stdio.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include "mstats.h"
-
-extern int malloc_free_blocks __P((int));
-
-extern struct _malstats _mstats;
-
-extern FILE *_imalloc_fopen __P((char *, char *, char *, char *, size_t));
-
-struct bucket_stats
-malloc_bucket_stats (size)
- int size;
-{
- struct bucket_stats v;
-
- v.nfree = 0;
-
- if (size < 0 || size >= NBUCKETS)
- {
- v.blocksize = 0;
- v.nused = v.nmal = v.nmorecore = v.nlesscore = v.nsplit = 0;
- return v;
- }
-
- v.blocksize = 1 << (size + 3);
- v.nused = _mstats.nmalloc[size];
- v.nmal = _mstats.tmalloc[size];
- v.nmorecore = _mstats.nmorecore[size];
- v.nlesscore = _mstats.nlesscore[size];
- v.nsplit = _mstats.nsplit[size];
- v.ncoalesce = _mstats.ncoalesce[size];
-
- v.nfree = malloc_free_blocks (size); /* call back to malloc.c */
-
- return v;
-}
-
-/* Return a copy of _MSTATS, with two additional fields filled in:
- BYTESFREE is the total number of bytes on free lists. BYTESUSED
- is the total number of bytes in use. These two fields are fairly
- expensive to compute, so we do it only when asked to. */
-struct _malstats
-malloc_stats ()
-{
- struct _malstats result;
- struct bucket_stats v;
- register int i;
-
- result = _mstats;
- result.bytesused = result.bytesfree = 0;
- for (i = 0; i < NBUCKETS; i++)
- {
- v = malloc_bucket_stats (i);
- result.bytesfree += v.nfree * v.blocksize;
- result.bytesused += v.nused * v.blocksize;
- }
- return (result);
-}
-
-static void
-_print_malloc_stats (s, fp)
- char *s;
- FILE *fp;
-{
- register int i;
- unsigned long totused, totfree;
- struct bucket_stats v;
-
- fprintf (fp, "Memory allocation statistics: %s\n size\tfree\tin use\ttotal\tmorecore lesscore split\tcoalesce\n", s ? s : "");
- for (i = totused = totfree = 0; i < NBUCKETS; i++)
- {
- v = malloc_bucket_stats (i);
- if (v.nmal > 0)
- fprintf (fp, "%8lu\t%4d\t%6d\t%5d\t%8d\t%d %5d %8d\n", (unsigned long)v.blocksize, v.nfree, v.nused, v.nmal, v.nmorecore, v.nlesscore, v.nsplit, v.ncoalesce);
- totfree += v.nfree * v.blocksize;
- totused += v.nused * v.blocksize;
- }
- fprintf (fp, "\nTotal bytes in use: %lu, total bytes free: %lu\n",
- totused, totfree);
- fprintf (fp, "\nTotal bytes requested by application: %lu\n", _mstats.bytesreq);
- fprintf (fp, "Total mallocs: %d, total frees: %d, total reallocs: %d (%d copies)\n",
- _mstats.nmal, _mstats.nfre, _mstats.nrealloc, _mstats.nrcopy);
- fprintf (fp, "Total sbrks: %d, total bytes via sbrk: %d\n",
- _mstats.nsbrk, _mstats.tsbrk);
- fprintf (fp, "Total blocks split: %d, total block coalesces: %d\n",
- _mstats.tbsplit, _mstats.tbcoalesce);
-}
-
-void
-print_malloc_stats (s)
- char *s;
-{
- _print_malloc_stats (s, stderr);
-}
-
-void
-fprint_malloc_stats (s, fp)
- char *s;
- FILE *fp;
-{
- _print_malloc_stats (s, fp);
-}
-
-#define TRACEROOT "/var/tmp/maltrace/stats."
-
-void
-trace_malloc_stats (s, fn)
- char *s, *fn;
-{
- FILE *fp;
- char defname[sizeof (TRACEROOT) + 64];
- static char mallbuf[1024];
-
- fp = _imalloc_fopen (s, fn, TRACEROOT, defname, sizeof (defname));
- if (fp)
- {
- setvbuf (fp, mallbuf, _IOFBF, sizeof (mallbuf));
- _print_malloc_stats (s, fp);
- fflush(fp);
- fclose(fp);
- }
-}
-
-#endif /* MALLOC_STATS */
-
-#if defined (MALLOC_STATS) || defined (MALLOC_TRACE)
-FILE *
-_imalloc_fopen (s, fn, def, defbuf, defsiz)
- char *s;
- char *fn;
- char *def;
- char *defbuf;
- size_t defsiz;
-{
- char fname[1024];
- long l;
- FILE *fp;
-
- l = (long)getpid ();
- if (fn == 0)
- {
- sprintf (defbuf, "%s%ld", def, l);
- fp = fopen(defbuf, "w");
- }
- else
- {
- char *p, *q, *r;
- char pidbuf[32];
- int sp;
-
- sprintf (pidbuf, "%ld", l);
- if ((strlen (pidbuf) + strlen (fn) + 2) >= sizeof (fname))
- return;
- for (sp = 0, p = fname, q = fn; *q; )
- {
- if (sp == 0 && *q == '%' && q[1] == 'p')
- {
- sp = 1;
- for (r = pidbuf; *r; )
- *p++ = *r++;
- q += 2;
- }
- else
- *p++ = *q++;
- }
- *p = '\0';
- fp = fopen (fname, "w");
- }
-
- return fp;
-}
-#endif /* MALLOC_STATS || MALLOC_TRACE */
diff --git a/lib/malloc/table.c~ b/lib/malloc/table.c~
deleted file mode 100644
index ee37b3a7..00000000
--- a/lib/malloc/table.c~
+++ /dev/null
@@ -1,290 +0,0 @@
-/* table.c - bookkeeping functions for allocated memory */
-
-/* Copyright (C) 2001-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. */
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include "imalloc.h"
-#include "table.h"
-
-extern int malloc_register;
-
-#ifdef MALLOC_REGISTER
-
-#define FIND_ALLOC 0x01 /* allocate new entry or find existing */
-#define FIND_EXIST 0x02 /* find existing entry */
-
-static int table_count = 0;
-static int table_allocated = 0;
-static mr_table_t mem_table[REG_TABLE_SIZE];
-static mr_table_t mem_overflow;
-
-/*
- * NOTE: taken from dmalloc (http://dmalloc.com) and modified.
- */
-static unsigned int
-mt_hash (key)
- const PTR_T key;
-{
- unsigned int a, b, c;
- unsigned long x;
-
- /* set up the internal state */
- a = 0x9e3779b9; /* the golden ratio; an arbitrary value */
- x = (unsigned long)key; /* truncation is OK */
- b = x >> 8;
- c = x >> 3; /* XXX - was >> 4 */
-
- HASH_MIX(a, b, c);
- return c;
-}
-
-#if 0
-static unsigned int
-which_bucket (mem)
- PTR_T mem;
-{
- return (mt_hash ((unsigned char *)mem) & (REG_TABLE_SIZE-1));
-}
-#else
-#define which_bucket(mem) (mt_hash ((unsigned char *)(mem)) & (REG_TABLE_SIZE-1));
-#endif
-
-static mr_table_t *
-find_entry (mem, flags)
- PTR_T mem;
- int flags;
-{
- unsigned int bucket;
- register mr_table_t *tp;
- mr_table_t *endp, *lastp;
-
- if (mem_overflow.mem == mem)
- return (&mem_overflow);
-
- bucket = which_bucket (mem); /* get initial hash */
- tp = endp = mem_table + bucket;
- lastp = mem_table + REG_TABLE_SIZE;
-
- while (1)
- {
- if (tp->mem == mem)
- return (tp);
- if (tp->mem == 0 && (flags & FIND_ALLOC))
- {
- table_count++;
- return (tp);
- }
-
- tp++;
-
- if (tp == lastp) /* wrap around */
- tp = mem_table;
-
- if (tp == endp && (flags & FIND_EXIST))
- return ((mr_table_t *)NULL);
-
- if (tp == endp && (flags & FIND_ALLOC))
- break;
- }
-
- /* oops. table is full. replace an existing free entry. */
- do
- {
- /* If there are no free entries, punt right away without searching. */
- if (table_allocated == REG_TABLE_SIZE)
- break;
-
- if (tp->flags & MT_FREE)
- {
- memset(tp, 0, sizeof (mr_table_t));
- return (tp);
- }
- tp++;
-
- if (tp == lastp)
- tp = mem_table;
- }
- while (tp != endp);
-
- /* wow. entirely full. return mem_overflow dummy entry. */
- tp = &mem_overflow;
- memset (tp, 0, sizeof (mr_table_t));
- return tp;
-}
-
-mr_table_t *
-mr_table_entry (mem)
- PTR_T mem;
-{
- return (find_entry (mem, FIND_EXIST));
-}
-
-void
-mregister_describe_mem (mem, fp)
- PTR_T mem;
- FILE *fp;
-{
- mr_table_t *entry;
-
- entry = find_entry (mem, FIND_EXIST);
- if (entry == 0)
- return;
- fprintf (fp, "malloc: %p: %s: last %s from %s:%d\n",
- mem,
- (entry->flags & MT_ALLOC) ? "allocated" : "free",
- (entry->flags & MT_ALLOC) ? "allocated" : "freed",
- entry->file ? entry->file : "unknown",
- entry->line);
-}
-
-void
-mregister_alloc (tag, mem, size, file, line)
- const char *tag;
- PTR_T mem;
- size_t size;
- const char *file;
- int line;
-{
- mr_table_t *tentry;
-
- tentry = find_entry (mem, FIND_ALLOC);
-
- if (tentry == 0)
- {
- /* oops. table is full. punt. */
- fprintf (stderr, _("register_alloc: alloc table is full with FIND_ALLOC?\n"));
- return;
- }
-
- if (tentry->flags & MT_ALLOC)
- {
- /* oops. bad bookkeeping. ignore for now */
- fprintf (stderr, _("register_alloc: %p already in table as allocated?\n"), mem);
- }
-
- tentry->mem = mem;
- tentry->size = size;
- tentry->func = tag;
- tentry->flags = MT_ALLOC;
- tentry->file = file;
- tentry->line = line;
- tentry->nalloc++;
-
- if (tentry != &mem_overflow)
- table_allocated++;
-}
-
-void
-mregister_free (mem, size, file, line)
- PTR_T mem;
- int size;
- const char *file;
- int line;
-{
- mr_table_t *tentry;
-
- tentry = find_entry (mem, FIND_EXIST);
- if (tentry == 0)
- {
- /* oops. not found. */
-#if 0
- fprintf (stderr, "register_free: %p not in allocation table?\n", mem);
-#endif
- return;
- }
- if (tentry->flags & MT_FREE)
- {
- /* oops. bad bookkeeping. ignore for now */
- fprintf (stderr, _("register_free: %p already in table as free?\n"), mem);
- }
-
- tentry->flags = MT_FREE;
- tentry->func = "free";
- tentry->file = file;
- tentry->line = line;
- tentry->nfree++;
-
- if (tentry != &mem_overflow)
- table_allocated--;
-}
-
-/* If we ever add more flags, this will require changes. */
-static char *
-_entry_flags(x)
- int x;
-{
- if (x & MT_FREE)
- return "free";
- else if (x & MT_ALLOC)
- return "allocated";
- else
- return "undetermined?";
-}
-
-static void
-_register_dump_table(fp)
- FILE *fp;
-{
- register int i;
- mr_table_t entry;
-
- for (i = 0; i < REG_TABLE_SIZE; i++)
- {
- entry = mem_table[i];
- if (entry.mem)
- fprintf (fp, "[%d] %p:%d:%s:%s:%s:%d:%d:%d\n", i,
- entry.mem, entry.size,
- _entry_flags(entry.flags),
- entry.func ? entry.func : "unknown",
- entry.file ? entry.file : "unknown",
- entry.line,
- entry.nalloc, entry.nfree);
- }
-}
-
-void
-mregister_dump_table()
-{
- _register_dump_table (stderr);
-}
-
-void
-mregister_table_init ()
-{
- memset (mem_table, 0, sizeof(mr_table_t) * REG_TABLE_SIZE);
- memset (&mem_overflow, 0, sizeof (mr_table_t));
- table_count = 0;
-}
-
-#endif /* MALLOC_REGISTER */
-
-int
-malloc_set_register(n)
- int n;
-{
- int old;
-
- old = malloc_register;
- malloc_register = n;
- return old;
-}
diff --git a/lib/readline/bind.c~ b/lib/readline/bind.c~
deleted file mode 100644
index 6a3e48c4..00000000
--- a/lib/readline/bind.c~
+++ /dev/null
@@ -1,2309 +0,0 @@
-/* bind.c -- key binding and startup file support for the readline library. */
-
-/* Copyright (C) 1987-2006 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 - 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 (c == ESC)
- {
- kseq[i++] = '\\';
- c = 'e';
- }
- 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 (c == ESC)
- {
- *r++ = '\\';
- c = 'e';
- }
- else if (CTRL_CHAR (c))
- {
- *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 == 0)
- 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)
- {
- map = FUNCTION_TO_KEYMAP (map, ESC);
- ic = UNMETA (ic);
- }
- /* XXX - should we just return NULL here, since this obviously
- doesn't match? */
- else
- {
- if (type)
- *type = map[ESC].type;
-
- return (map[ESC].function);
- }
- }
-
- if (map[ic].type == ISKMAP)
- {
- /* If this is the last key in the key sequence, return the
- map. */
- if (keyseq[i + 1] == '\0')
- {
- if (type)
- *type = ISKMAP;
-
- return (map[ic].function);
- }
- else
- map = FUNCTION_TO_KEYMAP (map, ic);
- }
- /* If we're not at the end of the key sequence, and the current key
- is bound to something other than a keymap, then the entire key
- sequence is not bound. */
- else if (map[ic].type != ISKMAP && keyseq[i+1])
- return ((rl_command_func_t *)NULL);
- else /* map[ic].type != ISKMAP && keyseq[i+1] == 0 */
- {
- 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
- 4. /etc/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 == 0)
- {
- filename = DEFAULT_INPUTRC;
- /* Try to read DEFAULT_INPUTRC; fall back to SYS_INPUTRC on failure */
- if (_rl_read_init_file (filename, 0) == 0)
- return 0;
- filename = SYS_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 ESC is the meta prefix and we're converting chars
- with the eighth bit set to ESC-prefixed sequences, then
- we can use \M-. Otherwise we need to use the sequence
- for ESC. */
- if (_rl_convert_meta_chars_to_ascii && map[ESC].type == ISKMAP)
- sprintf (keyname, "\\M-");
- else
- sprintf (keyname, "\\e");
- }
- 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.save b/lib/readline/callback.c.save
deleted file mode 100644
index 697066e0..00000000
--- a/lib/readline/callback.c.save
+++ /dev/null
@@ -1,261 +0,0 @@
-/* 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"
-#include "xmalloc.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/callback.c~ b/lib/readline/callback.c~
deleted file mode 100644
index 9120969c..00000000
--- a/lib/readline/callback.c~
+++ /dev/null
@@ -1,260 +0,0 @@
-/* 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/complete.c.orig b/lib/readline/complete.c.orig
deleted file mode 100644
index 7126d9e9..00000000
--- a/lib/readline/complete.c.orig
+++ /dev/null
@@ -1,2216 +0,0 @@
-/* complete.c -- filename completion 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 <sys/types.h>
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.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 */
-
-#include <stdio.h>
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#if defined (HAVE_PWD_H)
-#include <pwd.h>
-#endif
-
-#include "posixdir.h"
-#include "posixstat.h"
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "xmalloc.h"
-#include "rlprivate.h"
-
-#ifdef __STDC__
-typedef int QSFUNC (const void *, const void *);
-#else
-typedef int QSFUNC ();
-#endif
-
-#ifdef HAVE_LSTAT
-# define LSTAT lstat
-#else
-# define LSTAT stat
-#endif
-
-/* Unix version of a hidden file. Could be different on other systems. */
-#define HIDDEN_FILE(fname) ((fname)[0] == '.')
-
-/* Most systems don't declare getpwent in <pwd.h> if _POSIX_SOURCE is
- defined. */
-#if defined (HAVE_GETPWENT) && (!defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE))
-extern struct passwd *getpwent PARAMS((void));
-#endif /* HAVE_GETPWENT && (!HAVE_GETPW_DECLS || _POSIX_SOURCE) */
-
-/* If non-zero, then this is the address of a function to call when
- completing a word would normally display the list of possible matches.
- This function is called instead of actually doing the display.
- It takes three arguments: (char **matches, int num_matches, int max_length)
- where MATCHES is the array of strings that matched, NUM_MATCHES is the
- number of strings in that array, and MAX_LENGTH is the length of the
- longest string in that array. */
-rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
-
-#if defined (VISIBLE_STATS)
-# if !defined (X_OK)
-# define X_OK 1
-# endif
-static int stat_char PARAMS((char *));
-#endif
-
-static int path_isdir PARAMS((const char *));
-
-static char *rl_quote_filename PARAMS((char *, int, char *));
-
-static void set_completion_defaults PARAMS((int));
-static int get_y_or_n PARAMS((int));
-static int _rl_internal_pager PARAMS((int));
-static char *printable_part PARAMS((char *));
-static int fnwidth PARAMS((const char *));
-static int fnprint PARAMS((const char *));
-static int print_filename PARAMS((char *, char *));
-
-static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
-
-static char **remove_duplicate_matches PARAMS((char **));
-static void insert_match PARAMS((char *, int, int, char *));
-static int append_to_match PARAMS((char *, int, int, int));
-static void insert_all_matches PARAMS((char **, int, char *));
-static void display_matches PARAMS((char **));
-static int compute_lcd_of_matches PARAMS((char **, int, const char *));
-static int postprocess_matches PARAMS((char ***, int));
-
-static char *make_quoted_replacement PARAMS((char *, int, char *));
-
-/* **************************************************************** */
-/* */
-/* Completion matching, from readline's point of view. */
-/* */
-/* **************************************************************** */
-
-/* Variables known only to the readline library. */
-
-/* If non-zero, non-unique completions always show the list of matches. */
-int _rl_complete_show_all = 0;
-
-/* If non-zero, non-unique completions show the list of matches, unless it
- is not possible to do partial completion and modify the line. */
-int _rl_complete_show_unmodified = 0;
-
-/* If non-zero, completed directory names have a slash appended. */
-int _rl_complete_mark_directories = 1;
-
-/* If non-zero, the symlinked directory completion behavior introduced in
- readline-4.2a is disabled, and symlinks that point to directories have
- a slash appended (subject to the value of _rl_complete_mark_directories).
- This is user-settable via the mark-symlinked-directories variable. */
-int _rl_complete_mark_symlink_dirs = 0;
-
-/* If non-zero, completions are printed horizontally in alphabetical order,
- like `ls -x'. */
-int _rl_print_completions_horizontally;
-
-/* Non-zero means that case is not significant in filename completion. */
-#if defined (__MSDOS__) && !defined (__DJGPP__)
-int _rl_completion_case_fold = 1;
-#else
-int _rl_completion_case_fold;
-#endif
-
-/* If non-zero, don't match hidden files (filenames beginning with a `.' on
- Unix) when doing filename completion. */
-int _rl_match_hidden_files = 1;
-
-/* Global variables available to applications using readline. */
-
-#if defined (VISIBLE_STATS)
-/* Non-zero means add an additional character to each filename displayed
- during listing completion iff rl_filename_completion_desired which helps
- to indicate the type of file being listed. */
-int rl_visible_stats = 0;
-#endif /* VISIBLE_STATS */
-
-/* If non-zero, then this is the address of a function to call when
- completing on a directory name. The function is called with
- the address of a string (the current directory name) as an arg. */
-rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
-
-rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
-
-/* Non-zero means readline completion functions perform tilde expansion. */
-int rl_complete_with_tilde_expansion = 0;
-
-/* Pointer to the generator function for completion_matches ().
- NULL means to use rl_filename_completion_function (), the default filename
- completer. */
-rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL;
-
-/* Pointer to alternative function to create matches.
- Function is called with TEXT, START, and END.
- START and END are indices in RL_LINE_BUFFER saying what the boundaries
- of TEXT are.
- If this function exists and returns NULL then call the value of
- rl_completion_entry_function to try to match, otherwise use the
- array of strings returned. */
-rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL;
-
-/* Non-zero means to suppress normal filename completion after the
- user-specified completion function has been called. */
-int rl_attempted_completion_over = 0;
-
-/* Set to a character indicating the type of completion being performed
- by rl_complete_internal, available for use by application completion
- functions. */
-int rl_completion_type = 0;
-
-/* Up to this many items will be displayed in response to a
- possible-completions call. After that, we ask the user if
- she is sure she wants to see them all. A negative value means
- don't ask. */
-int rl_completion_query_items = 100;
-
-int _rl_page_completions = 1;
-
-/* The basic list of characters that signal a break between words for the
- completer routine. The contents of this variable is what breaks words
- in the shell, i.e. " \t\n\"\\'`@$><=" */
-const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */
-
-/* List of basic quoting characters. */
-const char *rl_basic_quote_characters = "\"'";
-
-/* The list of characters that signal a break between words for
- rl_complete_internal. The default list is the contents of
- rl_basic_word_break_characters. */
-/*const*/ char *rl_completer_word_break_characters = (/*const*/ char *)NULL;
-
-/* Hook function to allow an application to set the completion word
- break characters before readline breaks up the line. Allows
- position-dependent word break characters. */
-rl_cpvfunc_t *rl_completion_word_break_hook = (rl_cpvfunc_t *)NULL;
-
-/* List of characters which can be used to quote a substring of the line.
- Completion occurs on the entire substring, and within the substring
- rl_completer_word_break_characters are treated as any other character,
- unless they also appear within this list. */
-const char *rl_completer_quote_characters = (const char *)NULL;
-
-/* List of characters that should be quoted in filenames by the completer. */
-const char *rl_filename_quote_characters = (const char *)NULL;
-
-/* List of characters that are word break characters, but should be left
- in TEXT when it is passed to the completion function. The shell uses
- this to help determine what kind of completing to do. */
-const char *rl_special_prefixes = (const char *)NULL;
-
-/* If non-zero, then disallow duplicates in the matches. */
-int rl_ignore_completion_duplicates = 1;
-
-/* Non-zero means that the results of the matches are to be treated
- as filenames. This is ALWAYS zero on entry, and can only be changed
- within a completion entry finder function. */
-int rl_filename_completion_desired = 0;
-
-/* Non-zero means that the results of the matches are to be quoted using
- double quotes (or an application-specific quoting mechanism) if the
- filename contains any characters in rl_filename_quote_chars. This is
- ALWAYS non-zero on entry, and can only be changed within a completion
- entry finder function. */
-int rl_filename_quoting_desired = 1;
-
-/* This function, if defined, is called by the completer when real
- filename completion is done, after all the matching names have been
- generated. It is passed a (char**) known as matches in the code below.
- It consists of a NULL-terminated array of pointers to potential
- matching strings. The 1st element (matches[0]) is the maximal
- substring that is common to all matches. This function can re-arrange
- the list of matches as required, but all elements of the array must be
- free()'d if they are deleted. The main intent of this function is
- to implement FIGNORE a la SunOS csh. */
-rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL;
-
-/* Set to a function to quote a filename in an application-specific fashion.
- Called with the text to quote, the type of match found (single or multiple)
- and a pointer to the quoting character to be used, which the function can
- reset if desired. */
-rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename;
-
-/* Function to call to remove quoting characters from a filename. Called
- before completion is attempted, so the embedded quotes do not interfere
- with matching names in the file system. Readline doesn't do anything
- with this; it's set only by applications. */
-rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL;
-
-/* Function to call to decide whether or not a word break character is
- quoted. If a character is quoted, it does not break words for the
- completer. */
-rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL;
-
-/* If non-zero, the completion functions don't append anything except a
- possible closing quote. This is set to 0 by rl_complete_internal and
- may be changed by an application-specific completion function. */
-int rl_completion_suppress_append = 0;
-
-/* Character appended to completed words when at the end of the line. The
- default is a space. */
-int rl_completion_append_character = ' ';
-
-/* If non-zero, the completion functions don't append any closing quote.
- This is set to 0 by rl_complete_internal and may be changed by an
- application-specific completion function. */
-int rl_completion_suppress_quote = 0;
-
-/* Set to any quote character readline thinks it finds before any application
- completion function is called. */
-int rl_completion_quote_character;
-
-/* Set to a non-zero value if readline found quoting anywhere in the word to
- be completed; set before any application completion function is called. */
-int rl_completion_found_quote;
-
-/* If non-zero, a slash will be appended to completed filenames that are
- symbolic links to directory names, subject to the value of the
- mark-directories variable (which is user-settable). This exists so
- that application completion functions can override the user's preference
- (set via the mark-symlinked-directories variable) if appropriate.
- It's set to the value of _rl_complete_mark_symlink_dirs in
- rl_complete_internal before any application-specific completion
- function is called, so without that function doing anything, the user's
- preferences are honored. */
-int rl_completion_mark_symlink_dirs;
-
-/* If non-zero, inhibit completion (temporarily). */
-int rl_inhibit_completion;
-
-/* Variables local to this file. */
-
-/* Local variable states what happened during the last completion attempt. */
-static int completion_changed_buffer;
-
-/*************************************/
-/* */
-/* Bindable completion functions */
-/* */
-/*************************************/
-
-/* Complete the word at or before point. You have supplied the function
- that does the initial simple matching selection algorithm (see
- rl_completion_matches ()). The default is to do filename completion. */
-int
-rl_complete (ignore, invoking_key)
- int ignore, invoking_key;
-{
- if (rl_inhibit_completion)
- return (_rl_insert_char (ignore, invoking_key));
- else if (rl_last_func == rl_complete && !completion_changed_buffer)
- return (rl_complete_internal ('?'));
- else if (_rl_complete_show_all)
- return (rl_complete_internal ('!'));
- else if (_rl_complete_show_unmodified)
- return (rl_complete_internal ('@'));
- else
- return (rl_complete_internal (TAB));
-}
-
-/* List the possible completions. See description of rl_complete (). */
-int
-rl_possible_completions (ignore, invoking_key)
- int ignore, invoking_key;
-{
- return (rl_complete_internal ('?'));
-}
-
-int
-rl_insert_completions (ignore, invoking_key)
- int ignore, invoking_key;
-{
- return (rl_complete_internal ('*'));
-}
-
-/* Return the correct value to pass to rl_complete_internal performing
- the same tests as rl_complete. This allows consecutive calls to an
- application's completion function to list possible completions and for
- an application-specific completion function to honor the
- show-all-if-ambiguous readline variable. */
-int
-rl_completion_mode (cfunc)
- rl_command_func_t *cfunc;
-{
- if (rl_last_func == cfunc && !completion_changed_buffer)
- return '?';
- else if (_rl_complete_show_all)
- return '!';
- else if (_rl_complete_show_unmodified)
- return '@';
- else
- return TAB;
-}
-
-/************************************/
-/* */
-/* Completion utility functions */
-/* */
-/************************************/
-
-/* Set default values for readline word completion. These are the variables
- that application completion functions can change or inspect. */
-static void
-set_completion_defaults (what_to_do)
- int what_to_do;
-{
- /* Only the completion entry function can change these. */
- rl_filename_completion_desired = 0;
- rl_filename_quoting_desired = 1;
- rl_completion_type = what_to_do;
- rl_completion_suppress_append = rl_completion_suppress_quote = 0;
-
- /* The completion entry function may optionally change this. */
- rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;
-}
-
-/* The user must press "y" or "n". Non-zero return means "y" pressed. */
-static int
-get_y_or_n (for_pager)
- int for_pager;
-{
- int c;
-
- for (;;)
- {
- RL_SETSTATE(RL_STATE_MOREINPUT);
- c = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
- if (c == 'y' || c == 'Y' || c == ' ')
- return (1);
- if (c == 'n' || c == 'N' || c == RUBOUT)
- return (0);
- if (c == ABORT_CHAR)
- _rl_abort_internal ();
- if (for_pager && (c == NEWLINE || c == RETURN))
- return (2);
- if (for_pager && (c == 'q' || c == 'Q'))
- return (0);
- rl_ding ();
- }
-}
-
-static int
-_rl_internal_pager (lines)
- int lines;
-{
- int i;
-
- fprintf (rl_outstream, "--More--");
- fflush (rl_outstream);
- i = get_y_or_n (1);
- _rl_erase_entire_line ();
- if (i == 0)
- return -1;
- else if (i == 2)
- return (lines - 1);
- else
- return 0;
-}
-
-static int
-path_isdir (filename)
- const char *filename;
-{
- struct stat finfo;
-
- return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode));
-}
-
-#if defined (VISIBLE_STATS)
-/* Return the character which best describes FILENAME.
- `@' for symbolic links
- `/' for directories
- `*' for executables
- `=' for sockets
- `|' for FIFOs
- `%' for character special devices
- `#' for block special devices */
-static int
-stat_char (filename)
- char *filename;
-{
- struct stat finfo;
- int character, r;
-
-#if defined (HAVE_LSTAT) && defined (S_ISLNK)
- r = lstat (filename, &finfo);
-#else
- r = stat (filename, &finfo);
-#endif
-
- if (r == -1)
- return (0);
-
- character = 0;
- if (S_ISDIR (finfo.st_mode))
- character = '/';
-#if defined (S_ISCHR)
- else if (S_ISCHR (finfo.st_mode))
- character = '%';
-#endif /* S_ISCHR */
-#if defined (S_ISBLK)
- else if (S_ISBLK (finfo.st_mode))
- character = '#';
-#endif /* S_ISBLK */
-#if defined (S_ISLNK)
- else if (S_ISLNK (finfo.st_mode))
- character = '@';
-#endif /* S_ISLNK */
-#if defined (S_ISSOCK)
- else if (S_ISSOCK (finfo.st_mode))
- character = '=';
-#endif /* S_ISSOCK */
-#if defined (S_ISFIFO)
- else if (S_ISFIFO (finfo.st_mode))
- character = '|';
-#endif
- else if (S_ISREG (finfo.st_mode))
- {
- if (access (filename, X_OK) == 0)
- character = '*';
- }
- return (character);
-}
-#endif /* VISIBLE_STATS */
-
-/* Return the portion of PATHNAME that should be output when listing
- possible completions. If we are hacking filename completion, we
- are only interested in the basename, the portion following the
- final slash. Otherwise, we return what we were passed. Since
- printing empty strings is not very informative, if we're doing
- filename completion, and the basename is the empty string, we look
- for the previous slash and return the portion following that. If
- there's no previous slash, we just return what we were passed. */
-static char *
-printable_part (pathname)
- char *pathname;
-{
- char *temp, *x;
-
- if (rl_filename_completion_desired == 0) /* don't need to do anything */
- return (pathname);
-
- temp = strrchr (pathname, '/');
-#if defined (__MSDOS__)
- if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
- temp = pathname + 1;
-#endif
-
- if (temp == 0 || *temp == '\0')
- return (pathname);
- /* If the basename is NULL, we might have a pathname like '/usr/src/'.
- Look for a previous slash and, if one is found, return the portion
- following that slash. If there's no previous slash, just return the
- pathname we were passed. */
- else if (temp[1] == '\0')
- {
- for (x = temp - 1; x > pathname; x--)
- if (*x == '/')
- break;
- return ((*x == '/') ? x + 1 : pathname);
- }
- else
- return ++temp;
-}
-
-/* Compute width of STRING when displayed on screen by print_filename */
-static int
-fnwidth (string)
- const char *string;
-{
- int width, pos;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps;
- int left, w;
- size_t clen;
- wchar_t wc;
-
- left = strlen (string) + 1;
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
-
- width = pos = 0;
- while (string[pos])
- {
- if (CTRL_CHAR (*string) || *string == RUBOUT)
- {
- width += 2;
- pos++;
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- clen = mbrtowc (&wc, string + pos, left - pos, &ps);
- if (MB_INVALIDCH (clen))
- {
- width++;
- pos++;
- memset (&ps, 0, sizeof (mbstate_t));
- }
- else if (MB_NULLWCH (clen))
- break;
- else
- {
- pos += clen;
- w = wcwidth (wc);
- width += (w >= 0) ? w : 1;
- }
-#else
- width++;
- pos++;
-#endif
- }
- }
-
- return width;
-}
-
-static int
-fnprint (to_print)
- const char *to_print;
-{
- int printed_len;
- const char *s;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps;
- const char *end;
- size_t tlen;
- int width, w;
- wchar_t wc;
-
- end = to_print + strlen (to_print) + 1;
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
-
- printed_len = 0;
- s = to_print;
- while (*s)
- {
- if (CTRL_CHAR (*s))
- {
- putc ('^', rl_outstream);
- putc (UNCTRL (*s), rl_outstream);
- printed_len += 2;
- s++;
-#if defined (HANDLE_MULTIBYTE)
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
- }
- else if (*s == RUBOUT)
- {
- putc ('^', rl_outstream);
- putc ('?', rl_outstream);
- printed_len += 2;
- s++;
-#if defined (HANDLE_MULTIBYTE)
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- tlen = mbrtowc (&wc, s, end - s, &ps);
- if (MB_INVALIDCH (tlen))
- {
- tlen = 1;
- width = 1;
- memset (&ps, 0, sizeof (mbstate_t));
- }
- else if (MB_NULLWCH (tlen))
- break;
- else
- {
- w = wcwidth (wc);
- width = (w >= 0) ? w : 1;
- }
- fwrite (s, 1, tlen, rl_outstream);
- s += tlen;
- printed_len += width;
-#else
- putc (*s, rl_outstream);
- s++;
- printed_len++;
-#endif
- }
- }
-
- return printed_len;
-}
-
-/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
- are using it, check for and output a single character for `special'
- filenames. Return the number of characters we output. */
-
-static int
-print_filename (to_print, full_pathname)
- char *to_print, *full_pathname;
-{
- int printed_len, extension_char, slen, tlen;
- char *s, c, *new_full_pathname, *dn;
-
- extension_char = 0;
- printed_len = fnprint (to_print);
-
-#if defined (VISIBLE_STATS)
- if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories))
-#else
- if (rl_filename_completion_desired && _rl_complete_mark_directories)
-#endif
- {
- /* If to_print != full_pathname, to_print is the basename of the
- path passed. In this case, we try to expand the directory
- name before checking for the stat character. */
- if (to_print != full_pathname)
- {
- /* Terminate the directory name. */
- c = to_print[-1];
- to_print[-1] = '\0';
-
- /* If setting the last slash in full_pathname to a NUL results in
- full_pathname being the empty string, we are trying to complete
- files in the root directory. If we pass a null string to the
- bash directory completion hook, for example, it will expand it
- to the current directory. We just want the `/'. */
- if (full_pathname == 0 || *full_pathname == 0)
- dn = "/";
- else if (full_pathname[0] != '/')
- dn = full_pathname;
- else if (full_pathname[1] == 0)
- dn = "//"; /* restore trailing slash to `//' */
- else if (full_pathname[1] == '/' && full_pathname[2] == 0)
- dn = "/"; /* don't turn /// into // */
- else
- dn = full_pathname;
- s = tilde_expand (dn);
- if (rl_directory_completion_hook)
- (*rl_directory_completion_hook) (&s);
-
- slen = strlen (s);
- tlen = strlen (to_print);
- new_full_pathname = (char *)xmalloc (slen + tlen + 2);
- strcpy (new_full_pathname, s);
- if (s[slen - 1] == '/')
- slen--;
- else
- new_full_pathname[slen] = '/';
- new_full_pathname[slen] = '/';
- strcpy (new_full_pathname + slen + 1, to_print);
-
-#if defined (VISIBLE_STATS)
- if (rl_visible_stats)
- extension_char = stat_char (new_full_pathname);
- else
-#endif
- if (path_isdir (new_full_pathname))
- extension_char = '/';
-
- free (new_full_pathname);
- to_print[-1] = c;
- }
- else
- {
- s = tilde_expand (full_pathname);
-#if defined (VISIBLE_STATS)
- if (rl_visible_stats)
- extension_char = stat_char (s);
- else
-#endif
- if (path_isdir (s))
- extension_char = '/';
- }
-
- free (s);
- if (extension_char)
- {
- putc (extension_char, rl_outstream);
- printed_len++;
- }
- }
-
- return printed_len;
-}
-
-static char *
-rl_quote_filename (s, rtype, qcp)
- char *s;
- int rtype;
- char *qcp;
-{
- char *r;
-
- r = (char *)xmalloc (strlen (s) + 2);
- *r = *rl_completer_quote_characters;
- strcpy (r + 1, s);
- if (qcp)
- *qcp = *rl_completer_quote_characters;
- return r;
-}
-
-/* Find the bounds of the current word for completion purposes, and leave
- rl_point set to the end of the word. This function skips quoted
- substrings (characters between matched pairs of characters in
- rl_completer_quote_characters). First we try to find an unclosed
- quoted substring on which to do matching. If one is not found, we use
- the word break characters to find the boundaries of the current word.
- We call an application-specific function to decide whether or not a
- particular word break character is quoted; if that function returns a
- non-zero result, the character does not break a word. This function
- returns the opening quote character if we found an unclosed quoted
- substring, '\0' otherwise. FP, if non-null, is set to a value saying
- which (shell-like) quote characters we found (single quote, double
- quote, or backslash) anywhere in the string. DP, if non-null, is set to
- the value of the delimiter character that caused a word break. */
-
-char
-_rl_find_completion_word (fp, dp)
- int *fp, *dp;
-{
- int scan, end, found_quote, delimiter, pass_next, isbrk;
- char quote_char, *brkchars;
-
- end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- brkchars = 0;
- if (rl_completion_word_break_hook)
- brkchars = (*rl_completion_word_break_hook) ();
- if (brkchars == 0)
- brkchars = rl_completer_word_break_characters;
-
- if (rl_completer_quote_characters)
- {
- /* We have a list of characters which can be used in pairs to
- quote substrings for the completer. Try to find the start
- of an unclosed quoted substring. */
- /* FOUND_QUOTE is set so we know what kind of quotes we found. */
- for (scan = pass_next = 0; scan < end; scan = MB_NEXTCHAR (rl_line_buffer, scan, 1, MB_FIND_ANY))
- {
- if (pass_next)
- {
- pass_next = 0;
- continue;
- }
-
- /* Shell-like semantics for single quotes -- don't allow backslash
- to quote anything in single quotes, especially not the closing
- quote. If you don't like this, take out the check on the value
- of quote_char. */
- if (quote_char != '\'' && rl_line_buffer[scan] == '\\')
- {
- pass_next = 1;
- found_quote |= RL_QF_BACKSLASH;
- continue;
- }
-
- if (quote_char != '\0')
- {
- /* Ignore everything until the matching close quote char. */
- if (rl_line_buffer[scan] == quote_char)
- {
- /* Found matching close. Abandon this substring. */
- quote_char = '\0';
- rl_point = end;
- }
- }
- else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan]))
- {
- /* Found start of a quoted substring. */
- quote_char = rl_line_buffer[scan];
- rl_point = scan + 1;
- /* Shell-like quoting conventions. */
- if (quote_char == '\'')
- found_quote |= RL_QF_SINGLE_QUOTE;
- else if (quote_char == '"')
- found_quote |= RL_QF_DOUBLE_QUOTE;
- else
- found_quote |= RL_QF_OTHER_QUOTE;
- }
- }
- }
-
- if (rl_point == end && quote_char == '\0')
- {
- /* We didn't find an unclosed quoted substring upon which to do
- completion, so use the word break characters to find the
- substring on which to complete. */
- while (rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_ANY))
- {
- scan = rl_line_buffer[rl_point];
-
- if (strchr (brkchars, scan) == 0)
- continue;
-
- /* Call the application-specific function to tell us whether
- this word break character is quoted and should be skipped. */
- if (rl_char_is_quoted_p && found_quote &&
- (*rl_char_is_quoted_p) (rl_line_buffer, rl_point))
- continue;
-
- /* Convoluted code, but it avoids an n^2 algorithm with calls
- to char_is_quoted. */
- break;
- }
- }
-
- /* If we are at an unquoted word break, then advance past it. */
- scan = rl_line_buffer[rl_point];
-
- /* If there is an application-specific function to say whether or not
- a character is quoted and we found a quote character, let that
- function decide whether or not a character is a word break, even
- if it is found in rl_completer_word_break_characters. Don't bother
- if we're at the end of the line, though. */
- if (scan)
- {
- if (rl_char_is_quoted_p)
- isbrk = (found_quote == 0 ||
- (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) &&
- strchr (brkchars, scan) != 0;
- else
- isbrk = strchr (brkchars, scan) != 0;
-
- if (isbrk)
- {
- /* If the character that caused the word break was a quoting
- character, then remember it as the delimiter. */
- if (rl_basic_quote_characters &&
- strchr (rl_basic_quote_characters, scan) &&
- (end - rl_point) > 1)
- delimiter = scan;
-
- /* If the character isn't needed to determine something special
- about what kind of completion to perform, then advance past it. */
- if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0)
- rl_point++;
- }
- }
-
- if (fp)
- *fp = found_quote;
- if (dp)
- *dp = delimiter;
-
- return (quote_char);
-}
-
-static char **
-gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
- char *text;
- int start, end;
- rl_compentry_func_t *our_func;
- int found_quote, quote_char;
-{
- char **matches, *temp;
-
- rl_completion_found_quote = found_quote;
- rl_completion_quote_character = quote_char;
-
- /* If the user wants to TRY to complete, but then wants to give
- up and use the default completion function, they set the
- variable rl_attempted_completion_function. */
- if (rl_attempted_completion_function)
- {
- matches = (*rl_attempted_completion_function) (text, start, end);
-
- if (matches || rl_attempted_completion_over)
- {
- rl_attempted_completion_over = 0;
- return (matches);
- }
- }
-
- /* Beware -- we're stripping the quotes here. Do this only if we know
- we are doing filename completion and the application has defined a
- filename dequoting function. */
- /* XXX -- can move this into rl_filename_completion_function and use
- rl_completion_found_quote and rl_completion_quote_char. Should be
- after the directory rewriting hook and maybe the directory completion
- hook. Also need to change bash_directory_expansion in the same way
- as rl_filename_completion_function. */
- temp = (char *)NULL;
-
- if (found_quote && our_func == rl_filename_completion_function &&
- rl_filename_dequoting_function)
- {
- /* delete single and double quotes */
- temp = (*rl_filename_dequoting_function) (text, quote_char);
- text = temp; /* not freeing text is not a memory leak */
- }
-
- matches = rl_completion_matches (text, our_func);
- FREE (temp);
- return matches;
-}
-
-/* Filter out duplicates in MATCHES. This frees up the strings in
- MATCHES. */
-static char **
-remove_duplicate_matches (matches)
- char **matches;
-{
- char *lowest_common;
- int i, j, newlen;
- char dead_slot;
- char **temp_array;
-
- /* Sort the items. */
- for (i = 0; matches[i]; i++)
- ;
-
- /* Sort the array without matches[0], since we need it to
- stay in place no matter what. */
- if (i)
- qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
-
- /* Remember the lowest common denominator for it may be unique. */
- lowest_common = savestring (matches[0]);
-
- for (i = newlen = 0; matches[i + 1]; i++)
- {
- if (strcmp (matches[i], matches[i + 1]) == 0)
- {
- free (matches[i]);
- matches[i] = (char *)&dead_slot;
- }
- else
- newlen++;
- }
-
- /* We have marked all the dead slots with (char *)&dead_slot.
- Copy all the non-dead entries into a new array. */
- temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));
- for (i = j = 1; matches[i]; i++)
- {
- if (matches[i] != (char *)&dead_slot)
- temp_array[j++] = matches[i];
- }
- temp_array[j] = (char *)NULL;
-
- if (matches[0] != (char *)&dead_slot)
- free (matches[0]);
-
- /* Place the lowest common denominator back in [0]. */
- temp_array[0] = lowest_common;
-
- /* If there is one string left, and it is identical to the
- lowest common denominator, then the LCD is the string to
- insert. */
- if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0)
- {
- free (temp_array[1]);
- temp_array[1] = (char *)NULL;
- }
- return (temp_array);
-}
-
-/* Find the common prefix of the list of matches, and put it into
- matches[0]. */
-static int
-compute_lcd_of_matches (match_list, matches, text)
- char **match_list;
- int matches;
- const char *text;
-{
- register int i, c1, c2, si;
- int low; /* Count of max-matched characters. */
- char *dtext; /* dequoted TEXT, if needed */
-#if defined (HANDLE_MULTIBYTE)
- int v;
- mbstate_t ps1, ps2;
- wchar_t wc1, wc2;
-#endif
-
- /* If only one match, just use that. Otherwise, compare each
- member of the list with the next, finding out where they
- stop matching. */
- if (matches == 1)
- {
- match_list[0] = match_list[1];
- match_list[1] = (char *)NULL;
- return 1;
- }
-
- for (i = 1, low = 100000; i < matches; i++)
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- memset (&ps1, 0, sizeof (mbstate_t));
- memset (&ps2, 0, sizeof (mbstate_t));
- }
-#endif
- if (_rl_completion_case_fold)
- {
- for (si = 0;
- (c1 = _rl_to_lower(match_list[i][si])) &&
- (c2 = _rl_to_lower(match_list[i + 1][si]));
- si++)
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
- mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
- wc1 = towlower (wc1);
- wc2 = towlower (wc2);
- if (wc1 != wc2)
- break;
- else if (v > 1)
- si += v - 1;
- }
- else
-#endif
- if (c1 != c2)
- break;
- }
- else
- {
- for (si = 0;
- (c1 = match_list[i][si]) &&
- (c2 = match_list[i + 1][si]);
- si++)
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- mbstate_t ps_back = ps1;
- if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2))
- break;
- else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1)
- si += v - 1;
- }
- else
-#endif
- if (c1 != c2)
- break;
- }
-
- if (low > si)
- low = si;
- }
-
- /* If there were multiple matches, but none matched up to even the
- first character, and the user typed something, use that as the
- value of matches[0]. */
- if (low == 0 && text && *text)
- {
- match_list[0] = (char *)xmalloc (strlen (text) + 1);
- strcpy (match_list[0], text);
- }
- else
- {
- match_list[0] = (char *)xmalloc (low + 1);
-
- /* XXX - this might need changes in the presence of multibyte chars */
-
- /* If we are ignoring case, try to preserve the case of the string
- the user typed in the face of multiple matches differing in case. */
- if (_rl_completion_case_fold)
- {
- /* We're making an assumption here:
- IF we're completing filenames AND
- the application has defined a filename dequoting function AND
- we found a quote character AND
- the application has requested filename quoting
- THEN
- we assume that TEXT was dequoted before checking against
- the file system and needs to be dequoted here before we
- check against the list of matches
- FI */
- dtext = (char *)NULL;
- if (rl_filename_completion_desired &&
- rl_filename_dequoting_function &&
- rl_completion_found_quote &&
- rl_filename_quoting_desired)
- {
- dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
- text = dtext;
- }
-
- /* sort the list to get consistent answers. */
- qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
-
- si = strlen (text);
- if (si <= low)
- {
- for (i = 1; i <= matches; i++)
- if (strncmp (match_list[i], text, si) == 0)
- {
- strncpy (match_list[0], match_list[i], low);
- break;
- }
- /* no casematch, use first entry */
- if (i > matches)
- strncpy (match_list[0], match_list[1], low);
- }
- else
- /* otherwise, just use the text the user typed. */
- strncpy (match_list[0], text, low);
-
- FREE (dtext);
- }
- else
- strncpy (match_list[0], match_list[1], low);
-
- match_list[0][low] = '\0';
- }
-
- return matches;
-}
-
-static int
-postprocess_matches (matchesp, matching_filenames)
- char ***matchesp;
- int matching_filenames;
-{
- char *t, **matches, **temp_matches;
- int nmatch, i;
-
- matches = *matchesp;
-
- if (matches == 0)
- return 0;
-
- /* It seems to me that in all the cases we handle we would like
- to ignore duplicate possiblilities. Scan for the text to
- insert being identical to the other completions. */
- if (rl_ignore_completion_duplicates)
- {
- temp_matches = remove_duplicate_matches (matches);
- free (matches);
- matches = temp_matches;
- }
-
- /* If we are matching filenames, then here is our chance to
- do clever processing by re-examining the list. Call the
- ignore function with the array as a parameter. It can
- munge the array, deleting matches as it desires. */
- if (rl_ignore_some_completions_function && matching_filenames)
- {
- for (nmatch = 1; matches[nmatch]; nmatch++)
- ;
- (void)(*rl_ignore_some_completions_function) (matches);
- if (matches == 0 || matches[0] == 0)
- {
- FREE (matches);
- *matchesp = (char **)0;
- return 0;
- }
- else
- {
- /* If we removed some matches, recompute the common prefix. */
- for (i = 1; matches[i]; i++)
- ;
- if (i > 1 && i < nmatch)
- {
- t = matches[0];
- compute_lcd_of_matches (matches, i - 1, t);
- FREE (t);
- }
- }
- }
-
- *matchesp = matches;
- return (1);
-}
-
-/* A convenience function for displaying a list of strings in
- columnar format on readline's output stream. MATCHES is the list
- of strings, in argv format, LEN is the number of strings in MATCHES,
- and MAX is the length of the longest string in MATCHES. */
-void
-rl_display_match_list (matches, len, max)
- char **matches;
- int len, max;
-{
- int count, limit, printed_len, lines;
- int i, j, k, l;
- char *temp;
-
- /* How many items of MAX length can we fit in the screen window? */
- max += 2;
- limit = _rl_screenwidth / max;
- if (limit != 1 && (limit * max == _rl_screenwidth))
- limit--;
-
- /* Avoid a possible floating exception. If max > _rl_screenwidth,
- limit will be 0 and a divide-by-zero fault will result. */
- if (limit == 0)
- limit = 1;
-
- /* How many iterations of the printing loop? */
- count = (len + (limit - 1)) / limit;
-
- /* Watch out for special case. If LEN is less than LIMIT, then
- just do the inner printing loop.
- 0 < len <= limit implies count = 1. */
-
- /* Sort the items if they are not already sorted. */
- if (rl_ignore_completion_duplicates == 0)
- qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
-
- rl_crlf ();
-
- lines = 0;
- if (_rl_print_completions_horizontally == 0)
- {
- /* Print the sorted items, up-and-down alphabetically, like ls. */
- for (i = 1; i <= count; i++)
- {
- for (j = 0, l = i; j < limit; j++)
- {
- if (l > len || matches[l] == 0)
- break;
- else
- {
- temp = printable_part (matches[l]);
- printed_len = print_filename (temp, matches[l]);
-
- if (j + 1 < limit)
- for (k = 0; k < max - printed_len; k++)
- putc (' ', rl_outstream);
- }
- l += count;
- }
- rl_crlf ();
- lines++;
- if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
- {
- lines = _rl_internal_pager (lines);
- if (lines < 0)
- return;
- }
- }
- }
- else
- {
- /* Print the sorted items, across alphabetically, like ls -x. */
- for (i = 1; matches[i]; i++)
- {
- temp = printable_part (matches[i]);
- printed_len = print_filename (temp, matches[i]);
- /* Have we reached the end of this line? */
- if (matches[i+1])
- {
- if (i && (limit > 1) && (i % limit) == 0)
- {
- rl_crlf ();
- lines++;
- if (_rl_page_completions && lines >= _rl_screenheight - 1)
- {
- lines = _rl_internal_pager (lines);
- if (lines < 0)
- return;
- }
- }
- else
- for (k = 0; k < max - printed_len; k++)
- putc (' ', rl_outstream);
- }
- }
- rl_crlf ();
- }
-}
-
-/* Display MATCHES, a list of matching filenames in argv format. This
- handles the simple case -- a single match -- first. If there is more
- than one match, we compute the number of strings in the list and the
- length of the longest string, which will be needed by the display
- function. If the application wants to handle displaying the list of
- matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the
- address of a function, and we just call it. If we're handling the
- display ourselves, we just call rl_display_match_list. We also check
- that the list of matches doesn't exceed the user-settable threshold,
- and ask the user if he wants to see the list if there are more matches
- than RL_COMPLETION_QUERY_ITEMS. */
-static void
-display_matches (matches)
- char **matches;
-{
- int len, max, i;
- char *temp;
-
- /* Move to the last visible line of a possibly-multiple-line command. */
- _rl_move_vert (_rl_vis_botlin);
-
- /* Handle simple case first. What if there is only one answer? */
- if (matches[1] == 0)
- {
- temp = printable_part (matches[0]);
- rl_crlf ();
- print_filename (temp, matches[0]);
- rl_crlf ();
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-
- return;
- }
-
- /* There is more than one answer. Find out how many there are,
- and find the maximum printed length of a single entry. */
- for (max = 0, i = 1; matches[i]; i++)
- {
- temp = printable_part (matches[i]);
- len = fnwidth (temp);
-
- if (len > max)
- max = len;
- }
-
- len = i - 1;
-
- /* If the caller has defined a display hook, then call that now. */
- if (rl_completion_display_matches_hook)
- {
- (*rl_completion_display_matches_hook) (matches, len, max);
- return;
- }
-
- /* If there are many items, then ask the user if she really wants to
- see them all. */
- if (rl_completion_query_items > 0 && len >= rl_completion_query_items)
- {
- rl_crlf ();
- fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
- fflush (rl_outstream);
- if (get_y_or_n (0) == 0)
- {
- rl_crlf ();
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-
- return;
- }
- }
-
- rl_display_match_list (matches, len, max);
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-}
-
-static char *
-make_quoted_replacement (match, mtype, qc)
- char *match;
- int mtype;
- char *qc; /* Pointer to quoting character, if any */
-{
- int should_quote, do_replace;
- char *replacement;
-
- /* If we are doing completion on quoted substrings, and any matches
- contain any of the completer_word_break_characters, then auto-
- matically prepend the substring with a quote character (just pick
- the first one from the list of such) if it does not already begin
- with a quote string. FIXME: Need to remove any such automatically
- inserted quote character when it no longer is necessary, such as
- if we change the string we are completing on and the new set of
- matches don't require a quoted substring. */
- replacement = match;
-
- should_quote = match && rl_completer_quote_characters &&
- rl_filename_completion_desired &&
- rl_filename_quoting_desired;
-
- if (should_quote)
- should_quote = should_quote && (!qc || !*qc ||
- (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc)));
-
- if (should_quote)
- {
- /* If there is a single match, see if we need to quote it.
- This also checks whether the common prefix of several
- matches needs to be quoted. */
- should_quote = rl_filename_quote_characters
- ? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
- : 0;
-
- do_replace = should_quote ? mtype : NO_MATCH;
- /* Quote the replacement, since we found an embedded
- word break character in a potential match. */
- if (do_replace != NO_MATCH && rl_filename_quoting_function)
- replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
- }
- return (replacement);
-}
-
-static void
-insert_match (match, start, mtype, qc)
- char *match;
- int start, mtype;
- char *qc;
-{
- char *replacement;
- char oqc;
-
- oqc = qc ? *qc : '\0';
- replacement = make_quoted_replacement (match, mtype, qc);
-
- /* Now insert the match. */
- if (replacement)
- {
- /* Don't double an opening quote character. */
- if (qc && *qc && start && rl_line_buffer[start - 1] == *qc &&
- replacement[0] == *qc)
- start--;
- /* If make_quoted_replacement changed the quoting character, remove
- the opening quote and insert the (fully-quoted) replacement. */
- else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc &&
- replacement[0] != oqc)
- start--;
- _rl_replace_text (replacement, start, rl_point - 1);
- if (replacement != match)
- free (replacement);
- }
-}
-
-/* Append any necessary closing quote and a separator character to the
- just-inserted match. If the user has specified that directories
- should be marked by a trailing `/', append one of those instead. The
- default trailing character is a space. Returns the number of characters
- appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS
- has them) and don't add a suffix for a symlink to a directory. A
- nontrivial match is one that actually adds to the word being completed.
- The variable rl_completion_mark_symlink_dirs controls this behavior
- (it's initially set to the what the user has chosen, indicated by the
- value of _rl_complete_mark_symlink_dirs, but may be modified by an
- application's completion function). */
-static int
-append_to_match (text, delimiter, quote_char, nontrivial_match)
- char *text;
- int delimiter, quote_char, nontrivial_match;
-{
- char temp_string[4], *filename;
- int temp_string_index, s;
- struct stat finfo;
-
- temp_string_index = 0;
- if (quote_char && rl_point && rl_completion_suppress_quote == 0 &&
- rl_line_buffer[rl_point - 1] != quote_char)
- temp_string[temp_string_index++] = quote_char;
-
- if (delimiter)
- temp_string[temp_string_index++] = delimiter;
- else if (rl_completion_suppress_append == 0 && rl_completion_append_character)
- temp_string[temp_string_index++] = rl_completion_append_character;
-
- temp_string[temp_string_index++] = '\0';
-
- if (rl_filename_completion_desired)
- {
- filename = tilde_expand (text);
- s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
- ? LSTAT (filename, &finfo)
- : stat (filename, &finfo);
- if (s == 0 && S_ISDIR (finfo.st_mode))
- {
- if (_rl_complete_mark_directories /* && rl_completion_suppress_append == 0 */)
- {
- /* This is clumsy. Avoid putting in a double slash if point
- is at the end of the line and the previous character is a
- slash. */
- if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/')
- ;
- else if (rl_line_buffer[rl_point] != '/')
- rl_insert_text ("/");
- }
- }
-#ifdef S_ISLNK
- /* Don't add anything if the filename is a symlink and resolves to a
- directory. */
- else if (s == 0 && S_ISLNK (finfo.st_mode) &&
- stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
- ;
-#endif
- else
- {
- if (rl_point == rl_end && temp_string_index)
- rl_insert_text (temp_string);
- }
- free (filename);
- }
- else
- {
- if (rl_point == rl_end && temp_string_index)
- rl_insert_text (temp_string);
- }
-
- return (temp_string_index);
-}
-
-static void
-insert_all_matches (matches, point, qc)
- char **matches;
- int point;
- char *qc;
-{
- int i;
- char *rp;
-
- rl_begin_undo_group ();
- /* remove any opening quote character; make_quoted_replacement will add
- it back. */
- if (qc && *qc && point && rl_line_buffer[point - 1] == *qc)
- point--;
- rl_delete_text (point, rl_point);
- rl_point = point;
-
- if (matches[1])
- {
- for (i = 1; matches[i]; i++)
- {
- rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc);
- rl_insert_text (rp);
- rl_insert_text (" ");
- if (rp != matches[i])
- free (rp);
- }
- }
- else
- {
- rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc);
- rl_insert_text (rp);
- rl_insert_text (" ");
- if (rp != matches[0])
- free (rp);
- }
- rl_end_undo_group ();
-}
-
-void
-_rl_free_match_list (matches)
- char **matches;
-{
- register int i;
-
- if (matches == 0)
- return;
-
- for (i = 0; matches[i]; i++)
- free (matches[i]);
- free (matches);
-}
-
-/* Complete the word at or before point.
- WHAT_TO_DO says what to do with the completion.
- `?' means list the possible completions.
- TAB means do standard completion.
- `*' means insert all of the possible completions.
- `!' means to do standard completion, and list all possible completions if
- there is more than one.
- `@' means to do standard completion, and list all possible completions if
- there is more than one and partial completion is not possible. */
-int
-rl_complete_internal (what_to_do)
- int what_to_do;
-{
- char **matches;
- rl_compentry_func_t *our_func;
- int start, end, delimiter, found_quote, i, nontrivial_lcd;
- char *text, *saved_line_buffer;
- char quote_char;
-
- RL_SETSTATE(RL_STATE_COMPLETING);
-
- set_completion_defaults (what_to_do);
-
- saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL;
- our_func = rl_completion_entry_function
- ? rl_completion_entry_function
- : rl_filename_completion_function;
- /* We now look backwards for the start of a filename/variable word. */
- end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- if (rl_point)
- /* This (possibly) changes rl_point. If it returns a non-zero char,
- we know we have an open quote. */
- quote_char = _rl_find_completion_word (&found_quote, &delimiter);
-
- start = rl_point;
- rl_point = end;
-
- text = rl_copy_text (start, end);
- matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
- /* nontrivial_lcd is set if the common prefix adds something to the word
- being completed. */
- nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
- free (text);
-
- if (matches == 0)
- {
- rl_ding ();
- FREE (saved_line_buffer);
- completion_changed_buffer = 0;
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return (0);
- }
-
- /* If we are matching filenames, the attempted completion function will
- have set rl_filename_completion_desired to a non-zero value. The basic
- rl_filename_completion_function does this. */
- i = rl_filename_completion_desired;
-
- if (postprocess_matches (&matches, i) == 0)
- {
- rl_ding ();
- FREE (saved_line_buffer);
- completion_changed_buffer = 0;
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return (0);
- }
-
- switch (what_to_do)
- {
- case TAB:
- case '!':
- case '@':
- /* Insert the first match with proper quoting. */
- if (*matches[0])
- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
-
- /* If there are more matches, ring the bell to indicate.
- If we are in vi mode, Posix.2 says to not ring the bell.
- If the `show-all-if-ambiguous' variable is set, display
- all the matches immediately. Otherwise, if this was the
- only match, and we are hacking files, check the file to
- see if it was a directory. If so, and the `mark-directories'
- variable is set, add a '/' to the name. If not, and we
- are at the end of the line, then add a space. */
- if (matches[1])
- {
- if (what_to_do == '!')
- {
- display_matches (matches);
- break;
- }
- else if (what_to_do == '@')
- {
- if (nontrivial_lcd == 0)
- display_matches (matches);
- break;
- }
- else if (rl_editing_mode != vi_mode)
- rl_ding (); /* There are other matches remaining. */
- }
- else
- append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
-
- break;
-
- case '*':
- insert_all_matches (matches, start, &quote_char);
- break;
-
- case '?':
- display_matches (matches);
- break;
-
- default:
- fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do);
- rl_ding ();
- FREE (saved_line_buffer);
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return 1;
- }
-
- _rl_free_match_list (matches);
-
- /* Check to see if the line has changed through all of this manipulation. */
- if (saved_line_buffer)
- {
- completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0;
- free (saved_line_buffer);
- }
-
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return 0;
-}
-
-/***************************************************************/
-/* */
-/* Application-callable completion match generator functions */
-/* */
-/***************************************************************/
-
-/* Return an array of (char *) which is a list of completions for TEXT.
- If there are no completions, return a NULL pointer.
- The first entry in the returned array is the substitution for TEXT.
- The remaining entries are the possible completions.
- The array is terminated with a NULL pointer.
-
- ENTRY_FUNCTION is a function of two args, and returns a (char *).
- The first argument is TEXT.
- The second is a state argument; it should be zero on the first call, and
- non-zero on subsequent calls. It returns a NULL pointer to the caller
- when there are no more matches.
- */
-char **
-rl_completion_matches (text, entry_function)
- const char *text;
- rl_compentry_func_t *entry_function;
-{
- /* Number of slots in match_list. */
- int match_list_size;
-
- /* The list of matches. */
- char **match_list;
-
- /* Number of matches actually found. */
- int matches;
-
- /* Temporary string binder. */
- char *string;
-
- matches = 0;
- match_list_size = 10;
- match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
- match_list[1] = (char *)NULL;
-
- while (string = (*entry_function) (text, matches))
- {
- if (matches + 1 == match_list_size)
- match_list = (char **)xrealloc
- (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
-
- match_list[++matches] = string;
- match_list[matches + 1] = (char *)NULL;
- }
-
- /* If there were any matches, then look through them finding out the
- lowest common denominator. That then becomes match_list[0]. */
- if (matches)
- compute_lcd_of_matches (match_list, matches, text);
- else /* There were no matches. */
- {
- free (match_list);
- match_list = (char **)NULL;
- }
- return (match_list);
-}
-
-/* A completion function for usernames.
- TEXT contains a partial username preceded by a random
- character (usually `~'). */
-char *
-rl_username_completion_function (text, state)
- const char *text;
- int state;
-{
-#if defined (__WIN32__) || defined (__OPENNT)
- return (char *)NULL;
-#else /* !__WIN32__ && !__OPENNT) */
- static char *username = (char *)NULL;
- static struct passwd *entry;
- static int namelen, first_char, first_char_loc;
- char *value;
-
- if (state == 0)
- {
- FREE (username);
-
- first_char = *text;
- first_char_loc = first_char == '~';
-
- username = savestring (&text[first_char_loc]);
- namelen = strlen (username);
- setpwent ();
- }
-
-#if defined (HAVE_GETPWENT)
- while (entry = getpwent ())
- {
- /* Null usernames should result in all users as possible completions. */
- if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
- break;
- }
-#endif
-
- if (entry == 0)
- {
-#if defined (HAVE_GETPWENT)
- endpwent ();
-#endif
- return ((char *)NULL);
- }
- else
- {
- value = (char *)xmalloc (2 + strlen (entry->pw_name));
-
- *value = *text;
-
- strcpy (value + first_char_loc, entry->pw_name);
-
- if (first_char == '~')
- rl_filename_completion_desired = 1;
-
- return (value);
- }
-#endif /* !__WIN32__ && !__OPENNT */
-}
-
-/* Okay, now we write the entry_function for filename completion. In the
- general case. Note that completion in the shell is a little different
- because of all the pathnames that must be followed when looking up the
- completion for a command. */
-char *
-rl_filename_completion_function (text, state)
- const char *text;
- int state;
-{
- static DIR *directory = (DIR *)NULL;
- static char *filename = (char *)NULL;
- static char *dirname = (char *)NULL;
- static char *users_dirname = (char *)NULL;
- static int filename_len;
- char *temp;
- int dirlen;
- struct dirent *entry;
-
- /* If we don't have any state, then do some initialization. */
- if (state == 0)
- {
- /* If we were interrupted before closing the directory or reading
- all of its contents, close it. */
- if (directory)
- {
- closedir (directory);
- directory = (DIR *)NULL;
- }
- FREE (dirname);
- FREE (filename);
- FREE (users_dirname);
-
- filename = savestring (text);
- if (*text == 0)
- text = ".";
- dirname = savestring (text);
-
- temp = strrchr (dirname, '/');
-
-#if defined (__MSDOS__)
- /* special hack for //X/... */
- if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/')
- temp = strrchr (dirname + 3, '/');
-#endif
-
- if (temp)
- {
- strcpy (filename, ++temp);
- *temp = '\0';
- }
-#if defined (__MSDOS__)
- /* searches from current directory on the drive */
- else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':')
- {
- strcpy (filename, dirname + 2);
- dirname[2] = '\0';
- }
-#endif
- else
- {
- dirname[0] = '.';
- dirname[1] = '\0';
- }
-
- /* We aren't done yet. We also support the "~user" syntax. */
-
- /* Save the version of the directory that the user typed. */
- users_dirname = savestring (dirname);
-
- if (*dirname == '~')
- {
- temp = tilde_expand (dirname);
- free (dirname);
- dirname = temp;
- }
-
- if (rl_directory_rewrite_hook)
- (*rl_directory_rewrite_hook) (&dirname);
-
- if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
- {
- free (users_dirname);
- users_dirname = savestring (dirname);
- }
-
- directory = opendir (dirname);
- filename_len = strlen (filename);
-
- rl_filename_completion_desired = 1;
- }
-
- /* At this point we should entertain the possibility of hacking wildcarded
- filenames, like /usr/man/man<WILD>/te<TAB>. If the directory name
- contains globbing characters, then build an array of directories, and
- then map over that list while completing. */
- /* *** UNIMPLEMENTED *** */
-
- /* Now that we have some state, we can read the directory. */
-
- entry = (struct dirent *)NULL;
- while (directory && (entry = readdir (directory)))
- {
- /* Special case for no filename. If the user has disabled the
- `match-hidden-files' variable, skip filenames beginning with `.'.
- All other entries except "." and ".." match. */
- if (filename_len == 0)
- {
- if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name))
- continue;
-
- if (entry->d_name[0] != '.' ||
- (entry->d_name[1] &&
- (entry->d_name[1] != '.' || entry->d_name[2])))
- break;
- }
- else
- {
- /* Otherwise, if these match up to the length of filename, then
- it is a match. */
- if (_rl_completion_case_fold)
- {
- if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) &&
- (((int)D_NAMLEN (entry)) >= filename_len) &&
- (_rl_strnicmp (filename, entry->d_name, filename_len) == 0))
- break;
- }
- else
- {
- if ((entry->d_name[0] == filename[0]) &&
- (((int)D_NAMLEN (entry)) >= filename_len) &&
- (strncmp (filename, entry->d_name, filename_len) == 0))
- break;
- }
- }
- }
-
- if (entry == 0)
- {
- if (directory)
- {
- closedir (directory);
- directory = (DIR *)NULL;
- }
- if (dirname)
- {
- free (dirname);
- dirname = (char *)NULL;
- }
- if (filename)
- {
- free (filename);
- filename = (char *)NULL;
- }
- if (users_dirname)
- {
- free (users_dirname);
- users_dirname = (char *)NULL;
- }
-
- return (char *)NULL;
- }
- else
- {
- /* dirname && (strcmp (dirname, ".") != 0) */
- if (dirname && (dirname[0] != '.' || dirname[1]))
- {
- if (rl_complete_with_tilde_expansion && *users_dirname == '~')
- {
- dirlen = strlen (dirname);
- temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry));
- strcpy (temp, dirname);
- /* Canonicalization cuts off any final slash present. We
- may need to add it back. */
- if (dirname[dirlen - 1] != '/')
- {
- temp[dirlen++] = '/';
- temp[dirlen] = '\0';
- }
- }
- else
- {
- dirlen = strlen (users_dirname);
- temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry));
- strcpy (temp, users_dirname);
- /* Make sure that temp has a trailing slash here. */
- if (users_dirname[dirlen - 1] != '/')
- temp[dirlen++] = '/';
- }
-
- strcpy (temp + dirlen, entry->d_name);
- }
- else
- temp = savestring (entry->d_name);
-
- return (temp);
- }
-}
-
-/* An initial implementation of a menu completion function a la tcsh. The
- first time (if the last readline command was not rl_menu_complete), we
- generate the list of matches. This code is very similar to the code in
- rl_complete_internal -- there should be a way to combine the two. Then,
- for each item in the list of matches, we insert the match in an undoable
- fashion, with the appropriate character appended (this happens on the
- second and subsequent consecutive calls to rl_menu_complete). When we
- hit the end of the match list, we restore the original unmatched text,
- ring the bell, and reset the counter to zero. */
-int
-rl_menu_complete (count, ignore)
- int count, ignore;
-{
- rl_compentry_func_t *our_func;
- int matching_filenames, found_quote;
-
- static char *orig_text;
- static char **matches = (char **)0;
- static int match_list_index = 0;
- static int match_list_size = 0;
- static int orig_start, orig_end;
- static char quote_char;
- static int delimiter;
-
- /* The first time through, we generate the list of matches and set things
- up to insert them. */
- if (rl_last_func != rl_menu_complete)
- {
- /* Clean up from previous call, if any. */
- FREE (orig_text);
- if (matches)
- _rl_free_match_list (matches);
-
- match_list_index = match_list_size = 0;
- matches = (char **)NULL;
-
- /* Only the completion entry function can change these. */
- set_completion_defaults ('%');
-
- our_func = rl_completion_entry_function
- ? rl_completion_entry_function
- : rl_filename_completion_function;
-
- /* We now look backwards for the start of a filename/variable word. */
- orig_end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- if (rl_point)
- /* This (possibly) changes rl_point. If it returns a non-zero char,
- we know we have an open quote. */
- quote_char = _rl_find_completion_word (&found_quote, &delimiter);
-
- orig_start = rl_point;
- rl_point = orig_end;
-
- orig_text = rl_copy_text (orig_start, orig_end);
- matches = gen_completion_matches (orig_text, orig_start, orig_end,
- our_func, found_quote, quote_char);
-
- /* If we are matching filenames, the attempted completion function will
- have set rl_filename_completion_desired to a non-zero value. The basic
- rl_filename_completion_function does this. */
- matching_filenames = rl_filename_completion_desired;
-
- if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
- {
- rl_ding ();
- FREE (matches);
- matches = (char **)0;
- FREE (orig_text);
- orig_text = (char *)0;
- completion_changed_buffer = 0;
- return (0);
- }
-
- for (match_list_size = 0; matches[match_list_size]; match_list_size++)
- ;
- /* matches[0] is lcd if match_list_size > 1, but the circular buffer
- code below should take care of it. */
- }
-
- /* Now we have the list of matches. Replace the text between
- rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
- matches[match_list_index], and add any necessary closing char. */
-
- if (matches == 0 || match_list_size == 0)
- {
- rl_ding ();
- FREE (matches);
- matches = (char **)0;
- completion_changed_buffer = 0;
- return (0);
- }
-
- match_list_index += count;
- if (match_list_index < 0)
- match_list_index += match_list_size;
- else
- match_list_index %= match_list_size;
-
- if (match_list_index == 0 && match_list_size > 1)
- {
- rl_ding ();
- insert_match (orig_text, orig_start, MULT_MATCH, &quote_char);
- }
- else
- {
- insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
- append_to_match (matches[match_list_index], delimiter, quote_char,
- strcmp (orig_text, matches[match_list_index]));
- }
-
- completion_changed_buffer = 1;
- return (0);
-}
diff --git a/lib/readline/complete.c~ b/lib/readline/complete.c~
deleted file mode 100644
index ad253b16..00000000
--- a/lib/readline/complete.c~
+++ /dev/null
@@ -1,2216 +0,0 @@
-/* complete.c -- filename completion 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 <sys/types.h>
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.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 */
-
-#include <stdio.h>
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#if defined (HAVE_PWD_H)
-#include <pwd.h>
-#endif
-
-#include "posixdir.h"
-#include "posixstat.h"
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "xmalloc.h"
-#include "rlprivate.h"
-
-#ifdef __STDC__
-typedef int QSFUNC (const void *, const void *);
-#else
-typedef int QSFUNC ();
-#endif
-
-#ifdef HAVE_LSTAT
-# define LSTAT lstat
-#else
-# define LSTAT stat
-#endif
-
-/* Unix version of a hidden file. Could be different on other systems. */
-#define HIDDEN_FILE(fname) ((fname)[0] == '.')
-
-/* Most systems don't declare getpwent in <pwd.h> if _POSIX_SOURCE is
- defined. */
-#if defined (HAVE_GETPWENT) && (!defined (HAVE_GETPW_DECLS) || defined (_POSIX_SOURCE))
-extern struct passwd *getpwent PARAMS((void));
-#endif /* HAVE_GETPWENT && (!HAVE_GETPW_DECLS || _POSIX_SOURCE) */
-
-/* If non-zero, then this is the address of a function to call when
- completing a word would normally display the list of possible matches.
- This function is called instead of actually doing the display.
- It takes three arguments: (char **matches, int num_matches, int max_length)
- where MATCHES is the array of strings that matched, NUM_MATCHES is the
- number of strings in that array, and MAX_LENGTH is the length of the
- longest string in that array. */
-rl_compdisp_func_t *rl_completion_display_matches_hook = (rl_compdisp_func_t *)NULL;
-
-#if defined (VISIBLE_STATS)
-# if !defined (X_OK)
-# define X_OK 1
-# endif
-static int stat_char PARAMS((char *));
-#endif
-
-static int path_isdir PARAMS((const char *));
-
-static char *rl_quote_filename PARAMS((char *, int, char *));
-
-static void set_completion_defaults PARAMS((int));
-static int get_y_or_n PARAMS((int));
-static int _rl_internal_pager PARAMS((int));
-static char *printable_part PARAMS((char *));
-static int fnwidth PARAMS((const char *));
-static int fnprint PARAMS((const char *));
-static int print_filename PARAMS((char *, char *));
-
-static char **gen_completion_matches PARAMS((char *, int, int, rl_compentry_func_t *, int, int));
-
-static char **remove_duplicate_matches PARAMS((char **));
-static void insert_match PARAMS((char *, int, int, char *));
-static int append_to_match PARAMS((char *, int, int, int));
-static void insert_all_matches PARAMS((char **, int, char *));
-static void display_matches PARAMS((char **));
-static int compute_lcd_of_matches PARAMS((char **, int, const char *));
-static int postprocess_matches PARAMS((char ***, int));
-
-static char *make_quoted_replacement PARAMS((char *, int, char *));
-
-/* **************************************************************** */
-/* */
-/* Completion matching, from readline's point of view. */
-/* */
-/* **************************************************************** */
-
-/* Variables known only to the readline library. */
-
-/* If non-zero, non-unique completions always show the list of matches. */
-int _rl_complete_show_all = 0;
-
-/* If non-zero, non-unique completions show the list of matches, unless it
- is not possible to do partial completion and modify the line. */
-int _rl_complete_show_unmodified = 0;
-
-/* If non-zero, completed directory names have a slash appended. */
-int _rl_complete_mark_directories = 1;
-
-/* If non-zero, the symlinked directory completion behavior introduced in
- readline-4.2a is disabled, and symlinks that point to directories have
- a slash appended (subject to the value of _rl_complete_mark_directories).
- This is user-settable via the mark-symlinked-directories variable. */
-int _rl_complete_mark_symlink_dirs = 0;
-
-/* If non-zero, completions are printed horizontally in alphabetical order,
- like `ls -x'. */
-int _rl_print_completions_horizontally;
-
-/* Non-zero means that case is not significant in filename completion. */
-#if defined (__MSDOS__) && !defined (__DJGPP__)
-int _rl_completion_case_fold = 1;
-#else
-int _rl_completion_case_fold;
-#endif
-
-/* If non-zero, don't match hidden files (filenames beginning with a `.' on
- Unix) when doing filename completion. */
-int _rl_match_hidden_files = 1;
-
-/* Global variables available to applications using readline. */
-
-#if defined (VISIBLE_STATS)
-/* Non-zero means add an additional character to each filename displayed
- during listing completion iff rl_filename_completion_desired which helps
- to indicate the type of file being listed. */
-int rl_visible_stats = 0;
-#endif /* VISIBLE_STATS */
-
-/* If non-zero, then this is the address of a function to call when
- completing on a directory name. The function is called with
- the address of a string (the current directory name) as an arg. */
-rl_icppfunc_t *rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
-
-rl_icppfunc_t *rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
-
-/* Non-zero means readline completion functions perform tilde expansion. */
-int rl_complete_with_tilde_expansion = 0;
-
-/* Pointer to the generator function for completion_matches ().
- NULL means to use rl_filename_completion_function (), the default filename
- completer. */
-rl_compentry_func_t *rl_completion_entry_function = (rl_compentry_func_t *)NULL;
-
-/* Pointer to alternative function to create matches.
- Function is called with TEXT, START, and END.
- START and END are indices in RL_LINE_BUFFER saying what the boundaries
- of TEXT are.
- If this function exists and returns NULL then call the value of
- rl_completion_entry_function to try to match, otherwise use the
- array of strings returned. */
-rl_completion_func_t *rl_attempted_completion_function = (rl_completion_func_t *)NULL;
-
-/* Non-zero means to suppress normal filename completion after the
- user-specified completion function has been called. */
-int rl_attempted_completion_over = 0;
-
-/* Set to a character indicating the type of completion being performed
- by rl_complete_internal, available for use by application completion
- functions. */
-int rl_completion_type = 0;
-
-/* Up to this many items will be displayed in response to a
- possible-completions call. After that, we ask the user if
- she is sure she wants to see them all. A negative value means
- don't ask. */
-int rl_completion_query_items = 100;
-
-int _rl_page_completions = 1;
-
-/* The basic list of characters that signal a break between words for the
- completer routine. The contents of this variable is what breaks words
- in the shell, i.e. " \t\n\"\\'`@$><=" */
-const char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; /* }) */
-
-/* List of basic quoting characters. */
-const char *rl_basic_quote_characters = "\"'";
-
-/* The list of characters that signal a break between words for
- rl_complete_internal. The default list is the contents of
- rl_basic_word_break_characters. */
-/*const*/ char *rl_completer_word_break_characters = (/*const*/ char *)NULL;
-
-/* Hook function to allow an application to set the completion word
- break characters before readline breaks up the line. Allows
- position-dependent word break characters. */
-rl_cpvfunc_t *rl_completion_word_break_hook = (rl_cpvfunc_t *)NULL;
-
-/* List of characters which can be used to quote a substring of the line.
- Completion occurs on the entire substring, and within the substring
- rl_completer_word_break_characters are treated as any other character,
- unless they also appear within this list. */
-const char *rl_completer_quote_characters = (const char *)NULL;
-
-/* List of characters that should be quoted in filenames by the completer. */
-const char *rl_filename_quote_characters = (const char *)NULL;
-
-/* List of characters that are word break characters, but should be left
- in TEXT when it is passed to the completion function. The shell uses
- this to help determine what kind of completing to do. */
-const char *rl_special_prefixes = (const char *)NULL;
-
-/* If non-zero, then disallow duplicates in the matches. */
-int rl_ignore_completion_duplicates = 1;
-
-/* Non-zero means that the results of the matches are to be treated
- as filenames. This is ALWAYS zero on entry, and can only be changed
- within a completion entry finder function. */
-int rl_filename_completion_desired = 0;
-
-/* Non-zero means that the results of the matches are to be quoted using
- double quotes (or an application-specific quoting mechanism) if the
- filename contains any characters in rl_filename_quote_chars. This is
- ALWAYS non-zero on entry, and can only be changed within a completion
- entry finder function. */
-int rl_filename_quoting_desired = 1;
-
-/* This function, if defined, is called by the completer when real
- filename completion is done, after all the matching names have been
- generated. It is passed a (char**) known as matches in the code below.
- It consists of a NULL-terminated array of pointers to potential
- matching strings. The 1st element (matches[0]) is the maximal
- substring that is common to all matches. This function can re-arrange
- the list of matches as required, but all elements of the array must be
- free()'d if they are deleted. The main intent of this function is
- to implement FIGNORE a la SunOS csh. */
-rl_compignore_func_t *rl_ignore_some_completions_function = (rl_compignore_func_t *)NULL;
-
-/* Set to a function to quote a filename in an application-specific fashion.
- Called with the text to quote, the type of match found (single or multiple)
- and a pointer to the quoting character to be used, which the function can
- reset if desired. */
-rl_quote_func_t *rl_filename_quoting_function = rl_quote_filename;
-
-/* Function to call to remove quoting characters from a filename. Called
- before completion is attempted, so the embedded quotes do not interfere
- with matching names in the file system. Readline doesn't do anything
- with this; it's set only by applications. */
-rl_dequote_func_t *rl_filename_dequoting_function = (rl_dequote_func_t *)NULL;
-
-/* Function to call to decide whether or not a word break character is
- quoted. If a character is quoted, it does not break words for the
- completer. */
-rl_linebuf_func_t *rl_char_is_quoted_p = (rl_linebuf_func_t *)NULL;
-
-/* If non-zero, the completion functions don't append anything except a
- possible closing quote. This is set to 0 by rl_complete_internal and
- may be changed by an application-specific completion function. */
-int rl_completion_suppress_append = 0;
-
-/* Character appended to completed words when at the end of the line. The
- default is a space. */
-int rl_completion_append_character = ' ';
-
-/* If non-zero, the completion functions don't append any closing quote.
- This is set to 0 by rl_complete_internal and may be changed by an
- application-specific completion function. */
-int rl_completion_suppress_quote = 0;
-
-/* Set to any quote character readline thinks it finds before any application
- completion function is called. */
-int rl_completion_quote_character;
-
-/* Set to a non-zero value if readline found quoting anywhere in the word to
- be completed; set before any application completion function is called. */
-int rl_completion_found_quote;
-
-/* If non-zero, a slash will be appended to completed filenames that are
- symbolic links to directory names, subject to the value of the
- mark-directories variable (which is user-settable). This exists so
- that application completion functions can override the user's preference
- (set via the mark-symlinked-directories variable) if appropriate.
- It's set to the value of _rl_complete_mark_symlink_dirs in
- rl_complete_internal before any application-specific completion
- function is called, so without that function doing anything, the user's
- preferences are honored. */
-int rl_completion_mark_symlink_dirs;
-
-/* If non-zero, inhibit completion (temporarily). */
-int rl_inhibit_completion;
-
-/* Variables local to this file. */
-
-/* Local variable states what happened during the last completion attempt. */
-static int completion_changed_buffer;
-
-/*************************************/
-/* */
-/* Bindable completion functions */
-/* */
-/*************************************/
-
-/* Complete the word at or before point. You have supplied the function
- that does the initial simple matching selection algorithm (see
- rl_completion_matches ()). The default is to do filename completion. */
-int
-rl_complete (ignore, invoking_key)
- int ignore, invoking_key;
-{
- if (rl_inhibit_completion)
- return (_rl_insert_char (ignore, invoking_key));
- else if (rl_last_func == rl_complete && !completion_changed_buffer)
- return (rl_complete_internal ('?'));
- else if (_rl_complete_show_all)
- return (rl_complete_internal ('!'));
- else if (_rl_complete_show_unmodified)
- return (rl_complete_internal ('@'));
- else
- return (rl_complete_internal (TAB));
-}
-
-/* List the possible completions. See description of rl_complete (). */
-int
-rl_possible_completions (ignore, invoking_key)
- int ignore, invoking_key;
-{
- return (rl_complete_internal ('?'));
-}
-
-int
-rl_insert_completions (ignore, invoking_key)
- int ignore, invoking_key;
-{
- return (rl_complete_internal ('*'));
-}
-
-/* Return the correct value to pass to rl_complete_internal performing
- the same tests as rl_complete. This allows consecutive calls to an
- application's completion function to list possible completions and for
- an application-specific completion function to honor the
- show-all-if-ambiguous readline variable. */
-int
-rl_completion_mode (cfunc)
- rl_command_func_t *cfunc;
-{
- if (rl_last_func == cfunc && !completion_changed_buffer)
- return '?';
- else if (_rl_complete_show_all)
- return '!';
- else if (_rl_complete_show_unmodified)
- return '@';
- else
- return TAB;
-}
-
-/************************************/
-/* */
-/* Completion utility functions */
-/* */
-/************************************/
-
-/* Set default values for readline word completion. These are the variables
- that application completion functions can change or inspect. */
-static void
-set_completion_defaults (what_to_do)
- int what_to_do;
-{
- /* Only the completion entry function can change these. */
- rl_filename_completion_desired = 0;
- rl_filename_quoting_desired = 1;
- rl_completion_type = what_to_do;
- rl_completion_suppress_append = rl_completion_suppress_quote = 0;
-
- /* The completion entry function may optionally change this. */
- rl_completion_mark_symlink_dirs = _rl_complete_mark_symlink_dirs;
-}
-
-/* The user must press "y" or "n". Non-zero return means "y" pressed. */
-static int
-get_y_or_n (for_pager)
- int for_pager;
-{
- int c;
-
- for (;;)
- {
- RL_SETSTATE(RL_STATE_MOREINPUT);
- c = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
- if (c == 'y' || c == 'Y' || c == ' ')
- return (1);
- if (c == 'n' || c == 'N' || c == RUBOUT)
- return (0);
- if (c == ABORT_CHAR)
- _rl_abort_internal ();
- if (for_pager && (c == NEWLINE || c == RETURN))
- return (2);
- if (for_pager && (c == 'q' || c == 'Q'))
- return (0);
- rl_ding ();
- }
-}
-
-static int
-_rl_internal_pager (lines)
- int lines;
-{
- int i;
-
- fprintf (rl_outstream, "--More--");
- fflush (rl_outstream);
- i = get_y_or_n (1);
- _rl_erase_entire_line ();
- if (i == 0)
- return -1;
- else if (i == 2)
- return (lines - 1);
- else
- return 0;
-}
-
-static int
-path_isdir (filename)
- const char *filename;
-{
- struct stat finfo;
-
- return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode));
-}
-
-#if defined (VISIBLE_STATS)
-/* Return the character which best describes FILENAME.
- `@' for symbolic links
- `/' for directories
- `*' for executables
- `=' for sockets
- `|' for FIFOs
- `%' for character special devices
- `#' for block special devices */
-static int
-stat_char (filename)
- char *filename;
-{
- struct stat finfo;
- int character, r;
-
-#if defined (HAVE_LSTAT) && defined (S_ISLNK)
- r = lstat (filename, &finfo);
-#else
- r = stat (filename, &finfo);
-#endif
-
- if (r == -1)
- return (0);
-
- character = 0;
- if (S_ISDIR (finfo.st_mode))
- character = '/';
-#if defined (S_ISCHR)
- else if (S_ISCHR (finfo.st_mode))
- character = '%';
-#endif /* S_ISCHR */
-#if defined (S_ISBLK)
- else if (S_ISBLK (finfo.st_mode))
- character = '#';
-#endif /* S_ISBLK */
-#if defined (S_ISLNK)
- else if (S_ISLNK (finfo.st_mode))
- character = '@';
-#endif /* S_ISLNK */
-#if defined (S_ISSOCK)
- else if (S_ISSOCK (finfo.st_mode))
- character = '=';
-#endif /* S_ISSOCK */
-#if defined (S_ISFIFO)
- else if (S_ISFIFO (finfo.st_mode))
- character = '|';
-#endif
- else if (S_ISREG (finfo.st_mode))
- {
- if (access (filename, X_OK) == 0)
- character = '*';
- }
- return (character);
-}
-#endif /* VISIBLE_STATS */
-
-/* Return the portion of PATHNAME that should be output when listing
- possible completions. If we are hacking filename completion, we
- are only interested in the basename, the portion following the
- final slash. Otherwise, we return what we were passed. Since
- printing empty strings is not very informative, if we're doing
- filename completion, and the basename is the empty string, we look
- for the previous slash and return the portion following that. If
- there's no previous slash, we just return what we were passed. */
-static char *
-printable_part (pathname)
- char *pathname;
-{
- char *temp, *x;
-
- if (rl_filename_completion_desired == 0) /* don't need to do anything */
- return (pathname);
-
- temp = strrchr (pathname, '/');
-#if defined (__MSDOS__)
- if (temp == 0 && ISALPHA ((unsigned char)pathname[0]) && pathname[1] == ':')
- temp = pathname + 1;
-#endif
-
- if (temp == 0 || *temp == '\0')
- return (pathname);
- /* If the basename is NULL, we might have a pathname like '/usr/src/'.
- Look for a previous slash and, if one is found, return the portion
- following that slash. If there's no previous slash, just return the
- pathname we were passed. */
- else if (temp[1] == '\0')
- {
- for (x = temp - 1; x > pathname; x--)
- if (*x == '/')
- break;
- return ((*x == '/') ? x + 1 : pathname);
- }
- else
- return ++temp;
-}
-
-/* Compute width of STRING when displayed on screen by print_filename */
-static int
-fnwidth (string)
- const char *string;
-{
- int width, pos;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps;
- int left, w;
- size_t clen;
- wchar_t wc;
-
- left = strlen (string) + 1;
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
-
- width = pos = 0;
- while (string[pos])
- {
- if (CTRL_CHAR (*string) || *string == RUBOUT)
- {
- width += 2;
- pos++;
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- clen = mbrtowc (&wc, string + pos, left - pos, &ps);
- if (MB_INVALIDCH (clen))
- {
- width++;
- pos++;
- memset (&ps, 0, sizeof (mbstate_t));
- }
- else if (MB_NULLWCH (clen))
- break;
- else
- {
- pos += clen;
- w = wcwidth (wc);
- width += (w >= 0) ? w : 1;
- }
-#else
- width++;
- pos++;
-#endif
- }
- }
-
- return width;
-}
-
-static int
-fnprint (to_print)
- const char *to_print;
-{
- int printed_len;
- const char *s;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps;
- const char *end;
- size_t tlen;
- int width, w;
- wchar_t wc;
-
- end = to_print + strlen (to_print) + 1;
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
-
- printed_len = 0;
- s = to_print;
- while (*s)
- {
- if (CTRL_CHAR (*s))
- {
- putc ('^', rl_outstream);
- putc (UNCTRL (*s), rl_outstream);
- printed_len += 2;
- s++;
-#if defined (HANDLE_MULTIBYTE)
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
- }
- else if (*s == RUBOUT)
- {
- putc ('^', rl_outstream);
- putc ('?', rl_outstream);
- printed_len += 2;
- s++;
-#if defined (HANDLE_MULTIBYTE)
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- tlen = mbrtowc (&wc, s, end - s, &ps);
- if (MB_INVALIDCH (tlen))
- {
- tlen = 1;
- width = 1;
- memset (&ps, 0, sizeof (mbstate_t));
- }
- else if (MB_NULLWCH (tlen))
- break;
- else
- {
- w = wcwidth (wc);
- width = (w >= 0) ? w : 1;
- }
- fwrite (s, 1, tlen, rl_outstream);
- s += tlen;
- printed_len += width;
-#else
- putc (*s, rl_outstream);
- s++;
- printed_len++;
-#endif
- }
- }
-
- return printed_len;
-}
-
-/* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and we
- are using it, check for and output a single character for `special'
- filenames. Return the number of characters we output. */
-
-static int
-print_filename (to_print, full_pathname)
- char *to_print, *full_pathname;
-{
- int printed_len, extension_char, slen, tlen;
- char *s, c, *new_full_pathname, *dn;
-
- extension_char = 0;
- printed_len = fnprint (to_print);
-
-#if defined (VISIBLE_STATS)
- if (rl_filename_completion_desired && (rl_visible_stats || _rl_complete_mark_directories))
-#else
- if (rl_filename_completion_desired && _rl_complete_mark_directories)
-#endif
- {
- /* If to_print != full_pathname, to_print is the basename of the
- path passed. In this case, we try to expand the directory
- name before checking for the stat character. */
- if (to_print != full_pathname)
- {
- /* Terminate the directory name. */
- c = to_print[-1];
- to_print[-1] = '\0';
-
- /* If setting the last slash in full_pathname to a NUL results in
- full_pathname being the empty string, we are trying to complete
- files in the root directory. If we pass a null string to the
- bash directory completion hook, for example, it will expand it
- to the current directory. We just want the `/'. */
- if (full_pathname == 0 || *full_pathname == 0)
- dn = "/";
- else if (full_pathname[0] != '/')
- dn = full_pathname;
- else if (full_pathname[1] == 0)
- dn = "//"; /* restore trailing slash to `//' */
- else if (full_pathname[1] == '/' && full_pathname[2] == 0)
- dn = "/"; /* don't turn /// into // */
- else
- dn = full_pathname;
- s = tilde_expand (dn);
- if (rl_directory_completion_hook)
- (*rl_directory_completion_hook) (&s);
-
- slen = strlen (s);
- tlen = strlen (to_print);
- new_full_pathname = (char *)xmalloc (slen + tlen + 2);
- strcpy (new_full_pathname, s);
- if (s[slen - 1] == '/')
- slen--;
- else
- new_full_pathname[slen] = '/';
- new_full_pathname[slen] = '/';
- strcpy (new_full_pathname + slen + 1, to_print);
-
-#if defined (VISIBLE_STATS)
- if (rl_visible_stats)
- extension_char = stat_char (new_full_pathname);
- else
-#endif
- if (path_isdir (new_full_pathname))
- extension_char = '/';
-
- free (new_full_pathname);
- to_print[-1] = c;
- }
- else
- {
- s = tilde_expand (full_pathname);
-#if defined (VISIBLE_STATS)
- if (rl_visible_stats)
- extension_char = stat_char (s);
- else
-#endif
- if (path_isdir (s))
- extension_char = '/';
- }
-
- free (s);
- if (extension_char)
- {
- putc (extension_char, rl_outstream);
- printed_len++;
- }
- }
-
- return printed_len;
-}
-
-static char *
-rl_quote_filename (s, rtype, qcp)
- char *s;
- int rtype;
- char *qcp;
-{
- char *r;
-
- r = (char *)xmalloc (strlen (s) + 2);
- *r = *rl_completer_quote_characters;
- strcpy (r + 1, s);
- if (qcp)
- *qcp = *rl_completer_quote_characters;
- return r;
-}
-
-/* Find the bounds of the current word for completion purposes, and leave
- rl_point set to the end of the word. This function skips quoted
- substrings (characters between matched pairs of characters in
- rl_completer_quote_characters). First we try to find an unclosed
- quoted substring on which to do matching. If one is not found, we use
- the word break characters to find the boundaries of the current word.
- We call an application-specific function to decide whether or not a
- particular word break character is quoted; if that function returns a
- non-zero result, the character does not break a word. This function
- returns the opening quote character if we found an unclosed quoted
- substring, '\0' otherwise. FP, if non-null, is set to a value saying
- which (shell-like) quote characters we found (single quote, double
- quote, or backslash) anywhere in the string. DP, if non-null, is set to
- the value of the delimiter character that caused a word break. */
-
-char
-_rl_find_completion_word (fp, dp)
- int *fp, *dp;
-{
- int scan, end, found_quote, delimiter, pass_next, isbrk;
- char quote_char, *brkchars;
-
- end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- brkchars = 0;
- if (rl_completion_word_break_hook)
- brkchars = (*rl_completion_word_break_hook) ();
- if (brkchars == 0)
- brkchars = rl_completer_word_break_characters;
-
- if (rl_completer_quote_characters)
- {
- /* We have a list of characters which can be used in pairs to
- quote substrings for the completer. Try to find the start
- of an unclosed quoted substring. */
- /* FOUND_QUOTE is set so we know what kind of quotes we found. */
- for (scan = pass_next = 0; scan < end; scan = MB_NEXTCHAR (rl_line_buffer, scan, 1, MB_FIND_ANY))
- {
- if (pass_next)
- {
- pass_next = 0;
- continue;
- }
-
- /* Shell-like semantics for single quotes -- don't allow backslash
- to quote anything in single quotes, especially not the closing
- quote. If you don't like this, take out the check on the value
- of quote_char. */
- if (quote_char != '\'' && rl_line_buffer[scan] == '\\')
- {
- pass_next = 1;
- found_quote |= RL_QF_BACKSLASH;
- continue;
- }
-
- if (quote_char != '\0')
- {
- /* Ignore everything until the matching close quote char. */
- if (rl_line_buffer[scan] == quote_char)
- {
- /* Found matching close. Abandon this substring. */
- quote_char = '\0';
- rl_point = end;
- }
- }
- else if (strchr (rl_completer_quote_characters, rl_line_buffer[scan]))
- {
- /* Found start of a quoted substring. */
- quote_char = rl_line_buffer[scan];
- rl_point = scan + 1;
- /* Shell-like quoting conventions. */
- if (quote_char == '\'')
- found_quote |= RL_QF_SINGLE_QUOTE;
- else if (quote_char == '"')
- found_quote |= RL_QF_DOUBLE_QUOTE;
- else
- found_quote |= RL_QF_OTHER_QUOTE;
- }
- }
- }
-
- if (rl_point == end && quote_char == '\0')
- {
- /* We didn't find an unclosed quoted substring upon which to do
- completion, so use the word break characters to find the
- substring on which to complete. */
- while (rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_ANY))
- {
- scan = rl_line_buffer[rl_point];
-
- if (strchr (brkchars, scan) == 0)
- continue;
-
- /* Call the application-specific function to tell us whether
- this word break character is quoted and should be skipped. */
- if (rl_char_is_quoted_p && found_quote &&
- (*rl_char_is_quoted_p) (rl_line_buffer, rl_point))
- continue;
-
- /* Convoluted code, but it avoids an n^2 algorithm with calls
- to char_is_quoted. */
- break;
- }
- }
-
- /* If we are at an unquoted word break, then advance past it. */
- scan = rl_line_buffer[rl_point];
-
- /* If there is an application-specific function to say whether or not
- a character is quoted and we found a quote character, let that
- function decide whether or not a character is a word break, even
- if it is found in rl_completer_word_break_characters. Don't bother
- if we're at the end of the line, though. */
- if (scan)
- {
- if (rl_char_is_quoted_p)
- isbrk = (found_quote == 0 ||
- (*rl_char_is_quoted_p) (rl_line_buffer, rl_point) == 0) &&
- strchr (brkchars, scan) != 0;
- else
- isbrk = strchr (brkchars, scan) != 0;
-
- if (isbrk)
- {
- /* If the character that caused the word break was a quoting
- character, then remember it as the delimiter. */
- if (rl_basic_quote_characters &&
- strchr (rl_basic_quote_characters, scan) &&
- (end - rl_point) > 1)
- delimiter = scan;
-
- /* If the character isn't needed to determine something special
- about what kind of completion to perform, then advance past it. */
- if (rl_special_prefixes == 0 || strchr (rl_special_prefixes, scan) == 0)
- rl_point++;
- }
- }
-
- if (fp)
- *fp = found_quote;
- if (dp)
- *dp = delimiter;
-
- return (quote_char);
-}
-
-static char **
-gen_completion_matches (text, start, end, our_func, found_quote, quote_char)
- char *text;
- int start, end;
- rl_compentry_func_t *our_func;
- int found_quote, quote_char;
-{
- char **matches;
-
- rl_completion_found_quote = found_quote;
- rl_completion_quote_character = quote_char;
-
- /* If the user wants to TRY to complete, but then wants to give
- up and use the default completion function, they set the
- variable rl_attempted_completion_function. */
- if (rl_attempted_completion_function)
- {
- matches = (*rl_attempted_completion_function) (text, start, end);
-
- if (matches || rl_attempted_completion_over)
- {
- rl_attempted_completion_over = 0;
- return (matches);
- }
- }
-
- /* XXX -- filename dequoting moved into rl_filename_completion_function */
-
- matches = rl_completion_matches (text, our_func);
- return matches;
-}
-
-/* Filter out duplicates in MATCHES. This frees up the strings in
- MATCHES. */
-static char **
-remove_duplicate_matches (matches)
- char **matches;
-{
- char *lowest_common;
- int i, j, newlen;
- char dead_slot;
- char **temp_array;
-
- /* Sort the items. */
- for (i = 0; matches[i]; i++)
- ;
-
- /* Sort the array without matches[0], since we need it to
- stay in place no matter what. */
- if (i)
- qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
-
- /* Remember the lowest common denominator for it may be unique. */
- lowest_common = savestring (matches[0]);
-
- for (i = newlen = 0; matches[i + 1]; i++)
- {
- if (strcmp (matches[i], matches[i + 1]) == 0)
- {
- free (matches[i]);
- matches[i] = (char *)&dead_slot;
- }
- else
- newlen++;
- }
-
- /* We have marked all the dead slots with (char *)&dead_slot.
- Copy all the non-dead entries into a new array. */
- temp_array = (char **)xmalloc ((3 + newlen) * sizeof (char *));
- for (i = j = 1; matches[i]; i++)
- {
- if (matches[i] != (char *)&dead_slot)
- temp_array[j++] = matches[i];
- }
- temp_array[j] = (char *)NULL;
-
- if (matches[0] != (char *)&dead_slot)
- free (matches[0]);
-
- /* Place the lowest common denominator back in [0]. */
- temp_array[0] = lowest_common;
-
- /* If there is one string left, and it is identical to the
- lowest common denominator, then the LCD is the string to
- insert. */
- if (j == 2 && strcmp (temp_array[0], temp_array[1]) == 0)
- {
- free (temp_array[1]);
- temp_array[1] = (char *)NULL;
- }
- return (temp_array);
-}
-
-/* Find the common prefix of the list of matches, and put it into
- matches[0]. */
-static int
-compute_lcd_of_matches (match_list, matches, text)
- char **match_list;
- int matches;
- const char *text;
-{
- register int i, c1, c2, si;
- int low; /* Count of max-matched characters. */
- char *dtext; /* dequoted TEXT, if needed */
-#if defined (HANDLE_MULTIBYTE)
- int v;
- mbstate_t ps1, ps2;
- wchar_t wc1, wc2;
-#endif
-
- /* If only one match, just use that. Otherwise, compare each
- member of the list with the next, finding out where they
- stop matching. */
- if (matches == 1)
- {
- match_list[0] = match_list[1];
- match_list[1] = (char *)NULL;
- return 1;
- }
-
- for (i = 1, low = 100000; i < matches; i++)
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- memset (&ps1, 0, sizeof (mbstate_t));
- memset (&ps2, 0, sizeof (mbstate_t));
- }
-#endif
- if (_rl_completion_case_fold)
- {
- for (si = 0;
- (c1 = _rl_to_lower(match_list[i][si])) &&
- (c2 = _rl_to_lower(match_list[i + 1][si]));
- si++)
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- v = mbrtowc (&wc1, match_list[i]+si, strlen (match_list[i]+si), &ps1);
- mbrtowc (&wc2, match_list[i+1]+si, strlen (match_list[i+1]+si), &ps2);
- wc1 = towlower (wc1);
- wc2 = towlower (wc2);
- if (wc1 != wc2)
- break;
- else if (v > 1)
- si += v - 1;
- }
- else
-#endif
- if (c1 != c2)
- break;
- }
- else
- {
- for (si = 0;
- (c1 = match_list[i][si]) &&
- (c2 = match_list[i + 1][si]);
- si++)
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- mbstate_t ps_back = ps1;
- if (!_rl_compare_chars (match_list[i], si, &ps1, match_list[i+1], si, &ps2))
- break;
- else if ((v = _rl_get_char_len (&match_list[i][si], &ps_back)) > 1)
- si += v - 1;
- }
- else
-#endif
- if (c1 != c2)
- break;
- }
-
- if (low > si)
- low = si;
- }
-
- /* If there were multiple matches, but none matched up to even the
- first character, and the user typed something, use that as the
- value of matches[0]. */
- if (low == 0 && text && *text)
- {
- match_list[0] = (char *)xmalloc (strlen (text) + 1);
- strcpy (match_list[0], text);
- }
- else
- {
- match_list[0] = (char *)xmalloc (low + 1);
-
- /* XXX - this might need changes in the presence of multibyte chars */
-
- /* If we are ignoring case, try to preserve the case of the string
- the user typed in the face of multiple matches differing in case. */
- if (_rl_completion_case_fold)
- {
- /* We're making an assumption here:
- IF we're completing filenames AND
- the application has defined a filename dequoting function AND
- we found a quote character AND
- the application has requested filename quoting
- THEN
- we assume that TEXT was dequoted before checking against
- the file system and needs to be dequoted here before we
- check against the list of matches
- FI */
- dtext = (char *)NULL;
- if (rl_filename_completion_desired &&
- rl_filename_dequoting_function &&
- rl_completion_found_quote &&
- rl_filename_quoting_desired)
- {
- dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
- text = dtext;
- }
-
- /* sort the list to get consistent answers. */
- qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
-
- si = strlen (text);
- if (si <= low)
- {
- for (i = 1; i <= matches; i++)
- if (strncmp (match_list[i], text, si) == 0)
- {
- strncpy (match_list[0], match_list[i], low);
- break;
- }
- /* no casematch, use first entry */
- if (i > matches)
- strncpy (match_list[0], match_list[1], low);
- }
- else
- /* otherwise, just use the text the user typed. */
- strncpy (match_list[0], text, low);
-
- FREE (dtext);
- }
- else
- strncpy (match_list[0], match_list[1], low);
-
- match_list[0][low] = '\0';
- }
-
- return matches;
-}
-
-static int
-postprocess_matches (matchesp, matching_filenames)
- char ***matchesp;
- int matching_filenames;
-{
- char *t, **matches, **temp_matches;
- int nmatch, i;
-
- matches = *matchesp;
-
- if (matches == 0)
- return 0;
-
- /* It seems to me that in all the cases we handle we would like
- to ignore duplicate possiblilities. Scan for the text to
- insert being identical to the other completions. */
- if (rl_ignore_completion_duplicates)
- {
- temp_matches = remove_duplicate_matches (matches);
- free (matches);
- matches = temp_matches;
- }
-
- /* If we are matching filenames, then here is our chance to
- do clever processing by re-examining the list. Call the
- ignore function with the array as a parameter. It can
- munge the array, deleting matches as it desires. */
- if (rl_ignore_some_completions_function && matching_filenames)
- {
- for (nmatch = 1; matches[nmatch]; nmatch++)
- ;
- (void)(*rl_ignore_some_completions_function) (matches);
- if (matches == 0 || matches[0] == 0)
- {
- FREE (matches);
- *matchesp = (char **)0;
- return 0;
- }
- else
- {
- /* If we removed some matches, recompute the common prefix. */
- for (i = 1; matches[i]; i++)
- ;
- if (i > 1 && i < nmatch)
- {
- t = matches[0];
- compute_lcd_of_matches (matches, i - 1, t);
- FREE (t);
- }
- }
- }
-
- *matchesp = matches;
- return (1);
-}
-
-/* A convenience function for displaying a list of strings in
- columnar format on readline's output stream. MATCHES is the list
- of strings, in argv format, LEN is the number of strings in MATCHES,
- and MAX is the length of the longest string in MATCHES. */
-void
-rl_display_match_list (matches, len, max)
- char **matches;
- int len, max;
-{
- int count, limit, printed_len, lines;
- int i, j, k, l;
- char *temp;
-
- /* How many items of MAX length can we fit in the screen window? */
- max += 2;
- limit = _rl_screenwidth / max;
- if (limit != 1 && (limit * max == _rl_screenwidth))
- limit--;
-
- /* Avoid a possible floating exception. If max > _rl_screenwidth,
- limit will be 0 and a divide-by-zero fault will result. */
- if (limit == 0)
- limit = 1;
-
- /* How many iterations of the printing loop? */
- count = (len + (limit - 1)) / limit;
-
- /* Watch out for special case. If LEN is less than LIMIT, then
- just do the inner printing loop.
- 0 < len <= limit implies count = 1. */
-
- /* Sort the items if they are not already sorted. */
- if (rl_ignore_completion_duplicates == 0)
- qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
-
- rl_crlf ();
-
- lines = 0;
- if (_rl_print_completions_horizontally == 0)
- {
- /* Print the sorted items, up-and-down alphabetically, like ls. */
- for (i = 1; i <= count; i++)
- {
- for (j = 0, l = i; j < limit; j++)
- {
- if (l > len || matches[l] == 0)
- break;
- else
- {
- temp = printable_part (matches[l]);
- printed_len = print_filename (temp, matches[l]);
-
- if (j + 1 < limit)
- for (k = 0; k < max - printed_len; k++)
- putc (' ', rl_outstream);
- }
- l += count;
- }
- rl_crlf ();
- lines++;
- if (_rl_page_completions && lines >= (_rl_screenheight - 1) && i < count)
- {
- lines = _rl_internal_pager (lines);
- if (lines < 0)
- return;
- }
- }
- }
- else
- {
- /* Print the sorted items, across alphabetically, like ls -x. */
- for (i = 1; matches[i]; i++)
- {
- temp = printable_part (matches[i]);
- printed_len = print_filename (temp, matches[i]);
- /* Have we reached the end of this line? */
- if (matches[i+1])
- {
- if (i && (limit > 1) && (i % limit) == 0)
- {
- rl_crlf ();
- lines++;
- if (_rl_page_completions && lines >= _rl_screenheight - 1)
- {
- lines = _rl_internal_pager (lines);
- if (lines < 0)
- return;
- }
- }
- else
- for (k = 0; k < max - printed_len; k++)
- putc (' ', rl_outstream);
- }
- }
- rl_crlf ();
- }
-}
-
-/* Display MATCHES, a list of matching filenames in argv format. This
- handles the simple case -- a single match -- first. If there is more
- than one match, we compute the number of strings in the list and the
- length of the longest string, which will be needed by the display
- function. If the application wants to handle displaying the list of
- matches itself, it sets RL_COMPLETION_DISPLAY_MATCHES_HOOK to the
- address of a function, and we just call it. If we're handling the
- display ourselves, we just call rl_display_match_list. We also check
- that the list of matches doesn't exceed the user-settable threshold,
- and ask the user if he wants to see the list if there are more matches
- than RL_COMPLETION_QUERY_ITEMS. */
-static void
-display_matches (matches)
- char **matches;
-{
- int len, max, i;
- char *temp;
-
- /* Move to the last visible line of a possibly-multiple-line command. */
- _rl_move_vert (_rl_vis_botlin);
-
- /* Handle simple case first. What if there is only one answer? */
- if (matches[1] == 0)
- {
- temp = printable_part (matches[0]);
- rl_crlf ();
- print_filename (temp, matches[0]);
- rl_crlf ();
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-
- return;
- }
-
- /* There is more than one answer. Find out how many there are,
- and find the maximum printed length of a single entry. */
- for (max = 0, i = 1; matches[i]; i++)
- {
- temp = printable_part (matches[i]);
- len = fnwidth (temp);
-
- if (len > max)
- max = len;
- }
-
- len = i - 1;
-
- /* If the caller has defined a display hook, then call that now. */
- if (rl_completion_display_matches_hook)
- {
- (*rl_completion_display_matches_hook) (matches, len, max);
- return;
- }
-
- /* If there are many items, then ask the user if she really wants to
- see them all. */
- if (rl_completion_query_items > 0 && len >= rl_completion_query_items)
- {
- rl_crlf ();
- fprintf (rl_outstream, "Display all %d possibilities? (y or n)", len);
- fflush (rl_outstream);
- if (get_y_or_n (0) == 0)
- {
- rl_crlf ();
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-
- return;
- }
- }
-
- rl_display_match_list (matches, len, max);
-
- rl_forced_update_display ();
- rl_display_fixed = 1;
-}
-
-static char *
-make_quoted_replacement (match, mtype, qc)
- char *match;
- int mtype;
- char *qc; /* Pointer to quoting character, if any */
-{
- int should_quote, do_replace;
- char *replacement;
-
- /* If we are doing completion on quoted substrings, and any matches
- contain any of the completer_word_break_characters, then auto-
- matically prepend the substring with a quote character (just pick
- the first one from the list of such) if it does not already begin
- with a quote string. FIXME: Need to remove any such automatically
- inserted quote character when it no longer is necessary, such as
- if we change the string we are completing on and the new set of
- matches don't require a quoted substring. */
- replacement = match;
-
- should_quote = match && rl_completer_quote_characters &&
- rl_filename_completion_desired &&
- rl_filename_quoting_desired;
-
- if (should_quote)
- should_quote = should_quote && (!qc || !*qc ||
- (rl_completer_quote_characters && strchr (rl_completer_quote_characters, *qc)));
-
- if (should_quote)
- {
- /* If there is a single match, see if we need to quote it.
- This also checks whether the common prefix of several
- matches needs to be quoted. */
- should_quote = rl_filename_quote_characters
- ? (_rl_strpbrk (match, rl_filename_quote_characters) != 0)
- : 0;
-
- do_replace = should_quote ? mtype : NO_MATCH;
- /* Quote the replacement, since we found an embedded
- word break character in a potential match. */
- if (do_replace != NO_MATCH && rl_filename_quoting_function)
- replacement = (*rl_filename_quoting_function) (match, do_replace, qc);
- }
- return (replacement);
-}
-
-static void
-insert_match (match, start, mtype, qc)
- char *match;
- int start, mtype;
- char *qc;
-{
- char *replacement;
- char oqc;
-
- oqc = qc ? *qc : '\0';
- replacement = make_quoted_replacement (match, mtype, qc);
-
- /* Now insert the match. */
- if (replacement)
- {
- /* Don't double an opening quote character. */
- if (qc && *qc && start && rl_line_buffer[start - 1] == *qc &&
- replacement[0] == *qc)
- start--;
- /* If make_quoted_replacement changed the quoting character, remove
- the opening quote and insert the (fully-quoted) replacement. */
- else if (qc && (*qc != oqc) && start && rl_line_buffer[start - 1] == oqc &&
- replacement[0] != oqc)
- start--;
- _rl_replace_text (replacement, start, rl_point - 1);
- if (replacement != match)
- free (replacement);
- }
-}
-
-/* Append any necessary closing quote and a separator character to the
- just-inserted match. If the user has specified that directories
- should be marked by a trailing `/', append one of those instead. The
- default trailing character is a space. Returns the number of characters
- appended. If NONTRIVIAL_MATCH is set, we test for a symlink (if the OS
- has them) and don't add a suffix for a symlink to a directory. A
- nontrivial match is one that actually adds to the word being completed.
- The variable rl_completion_mark_symlink_dirs controls this behavior
- (it's initially set to the what the user has chosen, indicated by the
- value of _rl_complete_mark_symlink_dirs, but may be modified by an
- application's completion function). */
-static int
-append_to_match (text, delimiter, quote_char, nontrivial_match)
- char *text;
- int delimiter, quote_char, nontrivial_match;
-{
- char temp_string[4], *filename;
- int temp_string_index, s;
- struct stat finfo;
-
- temp_string_index = 0;
- if (quote_char && rl_point && rl_completion_suppress_quote == 0 &&
- rl_line_buffer[rl_point - 1] != quote_char)
- temp_string[temp_string_index++] = quote_char;
-
- if (delimiter)
- temp_string[temp_string_index++] = delimiter;
- else if (rl_completion_suppress_append == 0 && rl_completion_append_character)
- temp_string[temp_string_index++] = rl_completion_append_character;
-
- temp_string[temp_string_index++] = '\0';
-
- if (rl_filename_completion_desired)
- {
- filename = tilde_expand (text);
- s = (nontrivial_match && rl_completion_mark_symlink_dirs == 0)
- ? LSTAT (filename, &finfo)
- : stat (filename, &finfo);
- if (s == 0 && S_ISDIR (finfo.st_mode))
- {
- if (_rl_complete_mark_directories /* && rl_completion_suppress_append == 0 */)
- {
- /* This is clumsy. Avoid putting in a double slash if point
- is at the end of the line and the previous character is a
- slash. */
- if (rl_point && rl_line_buffer[rl_point] == '\0' && rl_line_buffer[rl_point - 1] == '/')
- ;
- else if (rl_line_buffer[rl_point] != '/')
- rl_insert_text ("/");
- }
- }
-#ifdef S_ISLNK
- /* Don't add anything if the filename is a symlink and resolves to a
- directory. */
- else if (s == 0 && S_ISLNK (finfo.st_mode) &&
- stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode))
- ;
-#endif
- else
- {
- if (rl_point == rl_end && temp_string_index)
- rl_insert_text (temp_string);
- }
- free (filename);
- }
- else
- {
- if (rl_point == rl_end && temp_string_index)
- rl_insert_text (temp_string);
- }
-
- return (temp_string_index);
-}
-
-static void
-insert_all_matches (matches, point, qc)
- char **matches;
- int point;
- char *qc;
-{
- int i;
- char *rp;
-
- rl_begin_undo_group ();
- /* remove any opening quote character; make_quoted_replacement will add
- it back. */
- if (qc && *qc && point && rl_line_buffer[point - 1] == *qc)
- point--;
- rl_delete_text (point, rl_point);
- rl_point = point;
-
- if (matches[1])
- {
- for (i = 1; matches[i]; i++)
- {
- rp = make_quoted_replacement (matches[i], SINGLE_MATCH, qc);
- rl_insert_text (rp);
- rl_insert_text (" ");
- if (rp != matches[i])
- free (rp);
- }
- }
- else
- {
- rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc);
- rl_insert_text (rp);
- rl_insert_text (" ");
- if (rp != matches[0])
- free (rp);
- }
- rl_end_undo_group ();
-}
-
-void
-_rl_free_match_list (matches)
- char **matches;
-{
- register int i;
-
- if (matches == 0)
- return;
-
- for (i = 0; matches[i]; i++)
- free (matches[i]);
- free (matches);
-}
-
-/* Complete the word at or before point.
- WHAT_TO_DO says what to do with the completion.
- `?' means list the possible completions.
- TAB means do standard completion.
- `*' means insert all of the possible completions.
- `!' means to do standard completion, and list all possible completions if
- there is more than one.
- `@' means to do standard completion, and list all possible completions if
- there is more than one and partial completion is not possible. */
-int
-rl_complete_internal (what_to_do)
- int what_to_do;
-{
- char **matches;
- rl_compentry_func_t *our_func;
- int start, end, delimiter, found_quote, i, nontrivial_lcd;
- char *text, *saved_line_buffer;
- char quote_char;
-
- RL_SETSTATE(RL_STATE_COMPLETING);
-
- set_completion_defaults (what_to_do);
-
- saved_line_buffer = rl_line_buffer ? savestring (rl_line_buffer) : (char *)NULL;
- our_func = rl_completion_entry_function
- ? rl_completion_entry_function
- : rl_filename_completion_function;
- /* We now look backwards for the start of a filename/variable word. */
- end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- if (rl_point)
- /* This (possibly) changes rl_point. If it returns a non-zero char,
- we know we have an open quote. */
- quote_char = _rl_find_completion_word (&found_quote, &delimiter);
-
- start = rl_point;
- rl_point = end;
-
- text = rl_copy_text (start, end);
- matches = gen_completion_matches (text, start, end, our_func, found_quote, quote_char);
- /* nontrivial_lcd is set if the common prefix adds something to the word
- being completed. */
- nontrivial_lcd = matches && strcmp (text, matches[0]) != 0;
- free (text);
-
- if (matches == 0)
- {
- rl_ding ();
- FREE (saved_line_buffer);
- completion_changed_buffer = 0;
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return (0);
- }
-
- /* If we are matching filenames, the attempted completion function will
- have set rl_filename_completion_desired to a non-zero value. The basic
- rl_filename_completion_function does this. */
- i = rl_filename_completion_desired;
-
- if (postprocess_matches (&matches, i) == 0)
- {
- rl_ding ();
- FREE (saved_line_buffer);
- completion_changed_buffer = 0;
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return (0);
- }
-
- switch (what_to_do)
- {
- case TAB:
- case '!':
- case '@':
- /* Insert the first match with proper quoting. */
- if (*matches[0])
- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, &quote_char);
-
- /* If there are more matches, ring the bell to indicate.
- If we are in vi mode, Posix.2 says to not ring the bell.
- If the `show-all-if-ambiguous' variable is set, display
- all the matches immediately. Otherwise, if this was the
- only match, and we are hacking files, check the file to
- see if it was a directory. If so, and the `mark-directories'
- variable is set, add a '/' to the name. If not, and we
- are at the end of the line, then add a space. */
- if (matches[1])
- {
- if (what_to_do == '!')
- {
- display_matches (matches);
- break;
- }
- else if (what_to_do == '@')
- {
- if (nontrivial_lcd == 0)
- display_matches (matches);
- break;
- }
- else if (rl_editing_mode != vi_mode)
- rl_ding (); /* There are other matches remaining. */
- }
- else
- append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
-
- break;
-
- case '*':
- insert_all_matches (matches, start, &quote_char);
- break;
-
- case '?':
- display_matches (matches);
- break;
-
- default:
- fprintf (stderr, "\r\nreadline: bad value %d for what_to_do in rl_complete\n", what_to_do);
- rl_ding ();
- FREE (saved_line_buffer);
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return 1;
- }
-
- _rl_free_match_list (matches);
-
- /* Check to see if the line has changed through all of this manipulation. */
- if (saved_line_buffer)
- {
- completion_changed_buffer = strcmp (rl_line_buffer, saved_line_buffer) != 0;
- free (saved_line_buffer);
- }
-
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return 0;
-}
-
-/***************************************************************/
-/* */
-/* Application-callable completion match generator functions */
-/* */
-/***************************************************************/
-
-/* Return an array of (char *) which is a list of completions for TEXT.
- If there are no completions, return a NULL pointer.
- The first entry in the returned array is the substitution for TEXT.
- The remaining entries are the possible completions.
- The array is terminated with a NULL pointer.
-
- ENTRY_FUNCTION is a function of two args, and returns a (char *).
- The first argument is TEXT.
- The second is a state argument; it should be zero on the first call, and
- non-zero on subsequent calls. It returns a NULL pointer to the caller
- when there are no more matches.
- */
-char **
-rl_completion_matches (text, entry_function)
- const char *text;
- rl_compentry_func_t *entry_function;
-{
- /* Number of slots in match_list. */
- int match_list_size;
-
- /* The list of matches. */
- char **match_list;
-
- /* Number of matches actually found. */
- int matches;
-
- /* Temporary string binder. */
- char *string;
-
- matches = 0;
- match_list_size = 10;
- match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *));
- match_list[1] = (char *)NULL;
-
- while (string = (*entry_function) (text, matches))
- {
- if (matches + 1 == match_list_size)
- match_list = (char **)xrealloc
- (match_list, ((match_list_size += 10) + 1) * sizeof (char *));
-
- match_list[++matches] = string;
- match_list[matches + 1] = (char *)NULL;
- }
-
- /* If there were any matches, then look through them finding out the
- lowest common denominator. That then becomes match_list[0]. */
- if (matches)
- compute_lcd_of_matches (match_list, matches, text);
- else /* There were no matches. */
- {
- free (match_list);
- match_list = (char **)NULL;
- }
- return (match_list);
-}
-
-/* A completion function for usernames.
- TEXT contains a partial username preceded by a random
- character (usually `~'). */
-char *
-rl_username_completion_function (text, state)
- const char *text;
- int state;
-{
-#if defined (__WIN32__) || defined (__OPENNT)
- return (char *)NULL;
-#else /* !__WIN32__ && !__OPENNT) */
- static char *username = (char *)NULL;
- static struct passwd *entry;
- static int namelen, first_char, first_char_loc;
- char *value;
-
- if (state == 0)
- {
- FREE (username);
-
- first_char = *text;
- first_char_loc = first_char == '~';
-
- username = savestring (&text[first_char_loc]);
- namelen = strlen (username);
- setpwent ();
- }
-
-#if defined (HAVE_GETPWENT)
- while (entry = getpwent ())
- {
- /* Null usernames should result in all users as possible completions. */
- if (namelen == 0 || (STREQN (username, entry->pw_name, namelen)))
- break;
- }
-#endif
-
- if (entry == 0)
- {
-#if defined (HAVE_GETPWENT)
- endpwent ();
-#endif
- return ((char *)NULL);
- }
- else
- {
- value = (char *)xmalloc (2 + strlen (entry->pw_name));
-
- *value = *text;
-
- strcpy (value + first_char_loc, entry->pw_name);
-
- if (first_char == '~')
- rl_filename_completion_desired = 1;
-
- return (value);
- }
-#endif /* !__WIN32__ && !__OPENNT */
-}
-
-/* Okay, now we write the entry_function for filename completion. In the
- general case. Note that completion in the shell is a little different
- because of all the pathnames that must be followed when looking up the
- completion for a command. */
-char *
-rl_filename_completion_function (text, state)
- const char *text;
- int state;
-{
- static DIR *directory = (DIR *)NULL;
- static char *filename = (char *)NULL;
- static char *dirname = (char *)NULL;
- static char *users_dirname = (char *)NULL;
- static int filename_len;
- char *temp;
- int dirlen;
- struct dirent *entry;
-
- /* If we don't have any state, then do some initialization. */
- if (state == 0)
- {
- /* If we were interrupted before closing the directory or reading
- all of its contents, close it. */
- if (directory)
- {
- closedir (directory);
- directory = (DIR *)NULL;
- }
- FREE (dirname);
- FREE (filename);
- FREE (users_dirname);
-
- filename = savestring (text);
- if (*text == 0)
- text = ".";
- dirname = savestring (text);
-
- temp = strrchr (dirname, '/');
-
-#if defined (__MSDOS__)
- /* special hack for //X/... */
- if (dirname[0] == '/' && dirname[1] == '/' && ISALPHA ((unsigned char)dirname[2]) && dirname[3] == '/')
- temp = strrchr (dirname + 3, '/');
-#endif
-
- if (temp)
- {
- strcpy (filename, ++temp);
- *temp = '\0';
- }
-#if defined (__MSDOS__)
- /* searches from current directory on the drive */
- else if (ISALPHA ((unsigned char)dirname[0]) && dirname[1] == ':')
- {
- strcpy (filename, dirname + 2);
- dirname[2] = '\0';
- }
-#endif
- else
- {
- dirname[0] = '.';
- dirname[1] = '\0';
- }
-
- /* We aren't done yet. We also support the "~user" syntax. */
-
- /* Save the version of the directory that the user typed. */
- users_dirname = savestring (dirname);
-
- if (*dirname == '~')
- {
- temp = tilde_expand (dirname);
- free (dirname);
- dirname = temp;
- }
-
- if (rl_directory_rewrite_hook)
- (*rl_directory_rewrite_hook) (&dirname);
-
- /* The directory completion hook should perform any necessary
- dequoting. */
- if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
- {
- free (users_dirname);
- users_dirname = savestring (dirname);
- }
- else if (rl_completion_found_quote && rl_filename_dequoting_function)
- {
- /* delete single and double quotes */
- temp = (*rl_filename_dequoting_function) (users_dirname, rl_completion_quote_character);
- free (users_dirname);
- users_dirname = temp;
- }
- directory = opendir (dirname);
-
- /* Now dequote a non-null filename. */
- if (filename && *filename && rl_completion_found_quote && rl_filename_dequoting_function)
- {
- /* delete single and double quotes */
- temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character);
- free (filename);
- filename = temp;
- }
- filename_len = strlen (filename);
-
- rl_filename_completion_desired = 1;
- }
-
- /* At this point we should entertain the possibility of hacking wildcarded
- filenames, like /usr/man/man<WILD>/te<TAB>. If the directory name
- contains globbing characters, then build an array of directories, and
- then map over that list while completing. */
- /* *** UNIMPLEMENTED *** */
-
- /* Now that we have some state, we can read the directory. */
-
- entry = (struct dirent *)NULL;
- while (directory && (entry = readdir (directory)))
- {
- /* Special case for no filename. If the user has disabled the
- `match-hidden-files' variable, skip filenames beginning with `.'.
- All other entries except "." and ".." match. */
- if (filename_len == 0)
- {
- if (_rl_match_hidden_files == 0 && HIDDEN_FILE (entry->d_name))
- continue;
-
- if (entry->d_name[0] != '.' ||
- (entry->d_name[1] &&
- (entry->d_name[1] != '.' || entry->d_name[2])))
- break;
- }
- else
- {
- /* Otherwise, if these match up to the length of filename, then
- it is a match. */
- if (_rl_completion_case_fold)
- {
- if ((_rl_to_lower (entry->d_name[0]) == _rl_to_lower (filename[0])) &&
- (((int)D_NAMLEN (entry)) >= filename_len) &&
- (_rl_strnicmp (filename, entry->d_name, filename_len) == 0))
- break;
- }
- else
- {
- if ((entry->d_name[0] == filename[0]) &&
- (((int)D_NAMLEN (entry)) >= filename_len) &&
- (strncmp (filename, entry->d_name, filename_len) == 0))
- break;
- }
- }
- }
-
- if (entry == 0)
- {
- if (directory)
- {
- closedir (directory);
- directory = (DIR *)NULL;
- }
- if (dirname)
- {
- free (dirname);
- dirname = (char *)NULL;
- }
- if (filename)
- {
- free (filename);
- filename = (char *)NULL;
- }
- if (users_dirname)
- {
- free (users_dirname);
- users_dirname = (char *)NULL;
- }
-
- return (char *)NULL;
- }
- else
- {
- /* dirname && (strcmp (dirname, ".") != 0) */
- if (dirname && (dirname[0] != '.' || dirname[1]))
- {
- if (rl_complete_with_tilde_expansion && *users_dirname == '~')
- {
- dirlen = strlen (dirname);
- temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry));
- strcpy (temp, dirname);
- /* Canonicalization cuts off any final slash present. We
- may need to add it back. */
- if (dirname[dirlen - 1] != '/')
- {
- temp[dirlen++] = '/';
- temp[dirlen] = '\0';
- }
- }
- else
- {
- dirlen = strlen (users_dirname);
- temp = (char *)xmalloc (2 + dirlen + D_NAMLEN (entry));
- strcpy (temp, users_dirname);
- /* Make sure that temp has a trailing slash here. */
- if (users_dirname[dirlen - 1] != '/')
- temp[dirlen++] = '/';
- }
-
- strcpy (temp + dirlen, entry->d_name);
- }
- else
- temp = savestring (entry->d_name);
-
- return (temp);
- }
-}
-
-/* An initial implementation of a menu completion function a la tcsh. The
- first time (if the last readline command was not rl_menu_complete), we
- generate the list of matches. This code is very similar to the code in
- rl_complete_internal -- there should be a way to combine the two. Then,
- for each item in the list of matches, we insert the match in an undoable
- fashion, with the appropriate character appended (this happens on the
- second and subsequent consecutive calls to rl_menu_complete). When we
- hit the end of the match list, we restore the original unmatched text,
- ring the bell, and reset the counter to zero. */
-int
-rl_menu_complete (count, ignore)
- int count, ignore;
-{
- rl_compentry_func_t *our_func;
- int matching_filenames, found_quote;
-
- static char *orig_text;
- static char **matches = (char **)0;
- static int match_list_index = 0;
- static int match_list_size = 0;
- static int orig_start, orig_end;
- static char quote_char;
- static int delimiter;
-
- /* The first time through, we generate the list of matches and set things
- up to insert them. */
- if (rl_last_func != rl_menu_complete)
- {
- /* Clean up from previous call, if any. */
- FREE (orig_text);
- if (matches)
- _rl_free_match_list (matches);
-
- match_list_index = match_list_size = 0;
- matches = (char **)NULL;
-
- /* Only the completion entry function can change these. */
- set_completion_defaults ('%');
-
- our_func = rl_completion_entry_function
- ? rl_completion_entry_function
- : rl_filename_completion_function;
-
- /* We now look backwards for the start of a filename/variable word. */
- orig_end = rl_point;
- found_quote = delimiter = 0;
- quote_char = '\0';
-
- if (rl_point)
- /* This (possibly) changes rl_point. If it returns a non-zero char,
- we know we have an open quote. */
- quote_char = _rl_find_completion_word (&found_quote, &delimiter);
-
- orig_start = rl_point;
- rl_point = orig_end;
-
- orig_text = rl_copy_text (orig_start, orig_end);
- matches = gen_completion_matches (orig_text, orig_start, orig_end,
- our_func, found_quote, quote_char);
-
- /* If we are matching filenames, the attempted completion function will
- have set rl_filename_completion_desired to a non-zero value. The basic
- rl_filename_completion_function does this. */
- matching_filenames = rl_filename_completion_desired;
-
- if (matches == 0 || postprocess_matches (&matches, matching_filenames) == 0)
- {
- rl_ding ();
- FREE (matches);
- matches = (char **)0;
- FREE (orig_text);
- orig_text = (char *)0;
- completion_changed_buffer = 0;
- return (0);
- }
-
- for (match_list_size = 0; matches[match_list_size]; match_list_size++)
- ;
- /* matches[0] is lcd if match_list_size > 1, but the circular buffer
- code below should take care of it. */
- }
-
- /* Now we have the list of matches. Replace the text between
- rl_line_buffer[orig_start] and rl_line_buffer[rl_point] with
- matches[match_list_index], and add any necessary closing char. */
-
- if (matches == 0 || match_list_size == 0)
- {
- rl_ding ();
- FREE (matches);
- matches = (char **)0;
- completion_changed_buffer = 0;
- return (0);
- }
-
- match_list_index += count;
- if (match_list_index < 0)
- match_list_index += match_list_size;
- else
- match_list_index %= match_list_size;
-
- if (match_list_index == 0 && match_list_size > 1)
- {
- rl_ding ();
- insert_match (orig_text, orig_start, MULT_MATCH, &quote_char);
- }
- else
- {
- insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, &quote_char);
- append_to_match (matches[match_list_index], delimiter, quote_char,
- strcmp (orig_text, matches[match_list_index]));
- }
-
- completion_changed_buffer = 1;
- return (0);
-}
diff --git a/lib/readline/display.c.save b/lib/readline/display.c.save
deleted file mode 100644
index 34005739..00000000
--- a/lib/readline/display.c.save
+++ /dev/null
@@ -1,2396 +0,0 @@
-/* display.c -- readline redisplay facility. */
-
-/* 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 <sys/types.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#include "posixstat.h"
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-/* Termcap library stuff. */
-#include "tcap.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#include "rlprivate.h"
-#include "xmalloc.h"
-
-#if !defined (strchr) && !defined (__STDC__)
-extern char *strchr (), *strrchr ();
-#endif /* !strchr && !__STDC__ */
-
-#if defined (HACK_TERMCAP_MOTION)
-extern char *_rl_term_forward_char;
-#endif
-
-static void update_line PARAMS((char *, char *, int, int, int, int));
-static void space_to_eol PARAMS((int));
-static void delete_chars PARAMS((int));
-static void insert_some_chars PARAMS((char *, int, int));
-static void cr PARAMS((void));
-
-#if defined (HANDLE_MULTIBYTE)
-static int _rl_col_width PARAMS((const char *, int, int));
-static int *_rl_wrapped_line;
-#else
-# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s))
-#endif
-
-static int *inv_lbreaks, *vis_lbreaks;
-static int inv_lbsize, vis_lbsize;
-
-/* Heuristic used to decide whether it is faster to move from CUR to NEW
- by backing up or outputting a carriage return and moving forward. */
-#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
-
-/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
- buffer index in others. This macro is used when deciding whether the
- current cursor position is in the middle of a prompt string containing
- invisible characters. */
-#define PROMPT_ENDING_INDEX \
- ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
-
-
-/* **************************************************************** */
-/* */
-/* Display stuff */
-/* */
-/* **************************************************************** */
-
-/* This is the stuff that is hard for me. I never seem to write good
- display routines in C. Let's see how I do this time. */
-
-/* (PWP) Well... Good for a simple line updater, but totally ignores
- the problems of input lines longer than the screen width.
-
- update_line and the code that calls it makes a multiple line,
- automatically wrapping line update. Careful attention needs
- to be paid to the vertical position variables. */
-
-/* Keep two buffers; one which reflects the current contents of the
- screen, and the other to draw what we think the new contents should
- be. Then compare the buffers, and make whatever changes to the
- screen itself that we should. Finally, make the buffer that we
- just drew into be the one which reflects the current contents of the
- screen, and place the cursor where it belongs.
-
- Commands that want to can fix the display themselves, and then let
- this function know that the display has been fixed by setting the
- RL_DISPLAY_FIXED variable. This is good for efficiency. */
-
-/* Application-specific redisplay function. */
-rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
-
-/* Global variables declared here. */
-/* What YOU turn on when you have handled all redisplay yourself. */
-int rl_display_fixed = 0;
-
-int _rl_suppress_redisplay = 0;
-int _rl_want_redisplay = 0;
-
-/* The stuff that gets printed out before the actual text of the line.
- This is usually pointing to rl_prompt. */
-char *rl_display_prompt = (char *)NULL;
-
-/* Pseudo-global variables declared here. */
-
-/* The visible cursor position. If you print some text, adjust this. */
-/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
- supporting multibyte characters, and an absolute cursor position when
- in such a locale. This is an artifact of the donated multibyte support.
- Care must be taken when modifying its value. */
-int _rl_last_c_pos = 0;
-int _rl_last_v_pos = 0;
-
-static int cpos_adjusted;
-
-/* Number of lines currently on screen minus 1. */
-int _rl_vis_botlin = 0;
-
-/* Variables used only in this file. */
-/* The last left edge of text that was displayed. This is used when
- doing horizontal scrolling. It shifts in thirds of a screenwidth. */
-static int last_lmargin;
-
-/* The line display buffers. One is the line currently displayed on
- the screen. The other is the line about to be displayed. */
-static char *visible_line = (char *)NULL;
-static char *invisible_line = (char *)NULL;
-
-/* A buffer for `modeline' messages. */
-static char msg_buf[128];
-
-/* Non-zero forces the redisplay even if we thought it was unnecessary. */
-static int forced_display;
-
-/* Default and initial buffer size. Can grow. */
-static int line_size = 1024;
-
-/* Variables to keep track of the expanded prompt string, which may
- include invisible characters. */
-
-static char *local_prompt, *local_prompt_prefix;
-static int prompt_visible_length, prompt_prefix_length;
-
-/* The number of invisible characters in the line currently being
- displayed on the screen. */
-static int visible_wrap_offset;
-
-/* The number of invisible characters in the prompt string. Static so it
- can be shared between rl_redisplay and update_line */
-static int wrap_offset;
-
-/* The index of the last invisible character in the prompt string. */
-static int prompt_last_invisible;
-
-/* The length (buffer offset) of the first line of the last (possibly
- multi-line) buffer displayed on the screen. */
-static int visible_first_line_len;
-
-/* Number of invisible characters on the first physical line of the prompt.
- Only valid when the number of physical characters in the prompt exceeds
- (or is equal to) _rl_screenwidth. */
-static int prompt_invis_chars_first_line;
-
-static int prompt_last_screen_line;
-
-static int prompt_physical_chars;
-
-/* Variables to save and restore prompt and display information. */
-
-/* These are getting numerous enough that it's time to create a struct. */
-
-static char *saved_local_prompt;
-static char *saved_local_prefix;
-static int saved_last_invisible;
-static int saved_visible_length;
-static int saved_prefix_length;
-static int saved_invis_chars_first_line;
-static int saved_physical_chars;
-
-/* Expand the prompt string S and return the number of visible
- characters in *LP, if LP is not null. This is currently more-or-less
- a placeholder for expansion. LIP, if non-null is a place to store the
- index of the last invisible character in the returned string. NIFLP,
- if non-zero, is a place to store the number of invisible characters in
- the first prompt line. The previous are used as byte counts -- indexes
- into a character buffer. */
-
-/* Current implementation:
- \001 (^A) start non-visible characters
- \002 (^B) end non-visible characters
- all characters except \001 and \002 (following a \001) are copied to
- the returned string; all characters except those between \001 and
- \002 are assumed to be `visible'. */
-
-static char *
-expand_prompt (pmt, lp, lip, niflp, vlp)
- char *pmt;
- int *lp, *lip, *niflp, *vlp;
-{
- char *r, *ret, *p, *igstart;
- int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
-
- /* Short-circuit if we can. */
- if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
- {
- r = savestring (pmt);
- if (lp)
- *lp = strlen (r);
- if (lip)
- *lip = 0;
- if (niflp)
- *niflp = 0;
- if (vlp)
- *vlp = lp ? *lp : strlen (r);
- return r;
- }
-
- l = strlen (pmt);
- r = ret = (char *)xmalloc (l + 1);
-
- 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 (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
- {
- ignoring = 1;
- igstart = p;
- continue;
- }
- else if (ignoring && *p == RL_PROMPT_END_IGNORE)
- {
- ignoring = 0;
- if (p != (igstart + 1))
- last = r - ret - 1;
- continue;
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- pind = p - pmt;
- ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
- l = ind - pind;
- while (l--)
- *r++ = *p++;
- if (!ignoring)
- {
- rl += ind - pind;
- physchars += _rl_col_width (pmt, pind, ind);
- }
- else
- ninvis += ind - pind;
- p--; /* compensate for later increment */
- }
- else
-#endif
- {
- *r++ = *p;
- if (!ignoring)
- {
- rl++; /* visible length byte counter */
- physchars++;
- }
- else
- ninvis++; /* invisible chars byte counter */
- }
-
- if (invflset == 0 && rl >= _rl_screenwidth)
- {
- invfl = ninvis;
- invflset = 1;
- }
- }
- }
-
- if (rl < _rl_screenwidth)
- invfl = ninvis;
-
- *r = '\0';
- if (lp)
- *lp = rl;
- if (lip)
- *lip = last;
- if (niflp)
- *niflp = invfl;
- if (vlp)
- *vlp = physchars;
- return ret;
-}
-
-/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
- PMT and return the rest of PMT. */
-char *
-_rl_strip_prompt (pmt)
- char *pmt;
-{
- char *ret;
-
- ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
- return ret;
-}
-
-/*
- * Expand the prompt string into the various display components, if
- * necessary.
- *
- * local_prompt = expanded last line of string in rl_display_prompt
- * (portion after the final newline)
- * local_prompt_prefix = portion before last newline of rl_display_prompt,
- * expanded via expand_prompt
- * prompt_visible_length = number of visible characters in local_prompt
- * prompt_prefix_length = number of visible characters in local_prompt_prefix
- *
- * This function is called once per call to readline(). It may also be
- * called arbitrarily to expand the primary prompt.
- *
- * The return value is the number of visible characters on the last line
- * of the (possibly multi-line) prompt.
- */
-int
-rl_expand_prompt (prompt)
- char *prompt;
-{
- char *p, *t;
- int c;
-
- /* Clear out any saved values. */
- FREE (local_prompt);
- FREE (local_prompt_prefix);
-
- local_prompt = local_prompt_prefix = (char *)0;
- prompt_last_invisible = prompt_invis_chars_first_line = 0;
- prompt_visible_length = prompt_physical_chars = 0;
-
- if (prompt == 0 || *prompt == 0)
- return (0);
-
- p = strrchr (prompt, '\n');
- if (!p)
- {
- /* The prompt is only one logical line, though it might wrap. */
- local_prompt = expand_prompt (prompt, &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
- local_prompt_prefix = (char *)0;
- return (prompt_visible_length);
- }
- else
- {
- /* The prompt spans multiple lines. */
- t = ++p;
- local_prompt = expand_prompt (p, &prompt_visible_length,
- &prompt_last_invisible,
- (int *)NULL,
- &prompt_physical_chars);
- c = *t; *t = '\0';
- /* The portion of the prompt string up to and including the
- final newline is now null-terminated. */
- local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
- (int *)NULL,
- &prompt_invis_chars_first_line,
- (int *)NULL);
- *t = c;
- return (prompt_prefix_length);
- }
-}
-
-/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
- arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
- and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
- increased. If the lines have already been allocated, this ensures that
- they can hold at least MINSIZE characters. */
-static void
-init_line_structures (minsize)
- int minsize;
-{
- register int n;
-
- if (invisible_line == 0) /* initialize it */
- {
- if (line_size < minsize)
- line_size = minsize;
- visible_line = (char *)xmalloc (line_size);
- invisible_line = (char *)xmalloc (line_size);
- }
- else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
- {
- line_size *= 2;
- if (line_size < minsize)
- line_size = minsize;
- visible_line = (char *)xrealloc (visible_line, line_size);
- invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
-
- for (n = minsize; n < line_size; n++)
- {
- visible_line[n] = 0;
- invisible_line[n] = 1;
- }
-
- if (vis_lbreaks == 0)
- {
- /* should be enough. */
- inv_lbsize = vis_lbsize = 256;
- inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
- vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
-#if defined (HANDLE_MULTIBYTE)
- _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
-#endif
- inv_lbreaks[0] = vis_lbreaks[0] = 0;
- }
-}
-
-/* Basic redisplay algorithm. */
-void
-rl_redisplay ()
-{
- register int in, out, c, linenum, cursor_linenum;
- register char *line;
- int c_pos, inv_botlin, lb_botlin, lb_linenum, o_cpos;
- int newlines, lpos, temp, modmark, n0, num;
- char *prompt_this_line;
-#if defined (HANDLE_MULTIBYTE)
- wchar_t wc;
- size_t wc_bytes;
- int wc_width;
- mbstate_t ps;
- int _rl_wrapped_multicolumn = 0;
-#endif
-
- if (!readline_echoing_p)
- return;
-
- if (!rl_display_prompt)
- rl_display_prompt = "";
-
- if (invisible_line == 0 || vis_lbreaks == 0)
- {
- init_line_structures (0);
- rl_on_new_line ();
- }
-
- /* Draw the line into the buffer. */
- c_pos = -1;
-
- line = invisible_line;
- out = inv_botlin = 0;
-
- /* Mark the line as modified or not. We only do this for history
- lines. */
- modmark = 0;
- if (_rl_mark_modified_lines && current_history () && rl_undo_list)
- {
- line[out++] = '*';
- line[out] = '\0';
- modmark = 1;
- }
-
- /* If someone thought that the redisplay was handled, but the currently
- visible line has a different modification state than the one about
- to become visible, then correct the caller's misconception. */
- if (visible_line[0] != invisible_line[0])
- rl_display_fixed = 0;
-
- /* If the prompt to be displayed is the `primary' readline prompt (the
- one passed to readline()), use the values we have already expanded.
- If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
- number of non-visible characters in the prompt string. */
- if (rl_display_prompt == rl_prompt || local_prompt)
- {
- int local_len = local_prompt ? strlen (local_prompt) : 0;
- if (local_prompt_prefix && forced_display)
- _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
-
- if (local_len > 0)
- {
- temp = local_len + out + 2;
- if (temp >= line_size)
- {
- line_size = (temp + 1024) - (temp % 1024);
- visible_line = (char *)xrealloc (visible_line, line_size);
- line = invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
- strncpy (line + out, local_prompt, local_len);
- out += local_len;
- }
- line[out] = '\0';
- wrap_offset = local_len - prompt_visible_length;
- }
- else
- {
- int pmtlen;
- prompt_this_line = strrchr (rl_display_prompt, '\n');
- if (!prompt_this_line)
- prompt_this_line = rl_display_prompt;
- else
- {
- prompt_this_line++;
- pmtlen = prompt_this_line - rl_display_prompt; /* temp var */
- if (forced_display)
- {
- _rl_output_some_chars (rl_display_prompt, pmtlen);
- /* Make sure we are at column zero even after a newline,
- regardless of the state of terminal output processing. */
- if (pmtlen < 2 || prompt_this_line[-2] != '\r')
- cr ();
- }
- }
-
- prompt_physical_chars = pmtlen = strlen (prompt_this_line);
- temp = pmtlen + out + 2;
- if (temp >= line_size)
- {
- line_size = (temp + 1024) - (temp % 1024);
- visible_line = (char *)xrealloc (visible_line, line_size);
- line = invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
- strncpy (line + out, prompt_this_line, pmtlen);
- out += pmtlen;
- line[out] = '\0';
- wrap_offset = prompt_invis_chars_first_line = 0;
- }
-
-#define CHECK_INV_LBREAKS() \
- do { \
- if (newlines >= (inv_lbsize - 2)) \
- { \
- inv_lbsize *= 2; \
- inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
- } \
- } while (0)
-
-#if defined (HANDLE_MULTIBYTE)
-#define CHECK_LPOS() \
- do { \
- lpos++; \
- if (lpos >= _rl_screenwidth) \
- { \
- if (newlines >= (inv_lbsize - 2)) \
- { \
- inv_lbsize *= 2; \
- inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
- _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
- } \
- inv_lbreaks[++newlines] = out; \
- _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
- lpos = 0; \
- } \
- } while (0)
-#else
-#define CHECK_LPOS() \
- do { \
- lpos++; \
- if (lpos >= _rl_screenwidth) \
- { \
- if (newlines >= (inv_lbsize - 2)) \
- { \
- inv_lbsize *= 2; \
- inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
- } \
- inv_lbreaks[++newlines] = out; \
- lpos = 0; \
- } \
- } while (0)
-#endif
-
- /* inv_lbreaks[i] is where line i starts in the buffer. */
- inv_lbreaks[newlines = 0] = 0;
-#if 0
- lpos = out - wrap_offset;
-#else
- lpos = prompt_physical_chars + modmark;
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
- memset (_rl_wrapped_line, 0, vis_lbsize);
- num = 0;
-#endif
-
- /* prompt_invis_chars_first_line is the number of invisible characters in
- the first physical line of the prompt.
- wrap_offset - prompt_invis_chars_first_line is the number of invis
- chars on the second line. */
-
- /* what if lpos is already >= _rl_screenwidth before we start drawing the
- contents of the command line? */
- while (lpos >= _rl_screenwidth)
- {
- /* fix from Darin Johnson <darin@acuson.com> for prompt string with
- invisible characters that is longer than the screen width. The
- prompt_invis_chars_first_line variable could be made into an array
- saying how many invisible characters there are per line, but that's
- probably too much work for the benefit gained. How many people have
- prompts that exceed two physical lines?
- Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
-#if defined (HANDLE_MULTIBYTE)
- n0 = num;
- temp = local_prompt ? strlen (local_prompt) : 0;
- while (num < temp)
- {
- if (_rl_col_width (local_prompt, n0, num) > _rl_screenwidth)
- {
- num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
- break;
- }
- num++;
- }
- temp = num +
-#else
- temp = ((newlines + 1) * _rl_screenwidth) +
-#endif /* !HANDLE_MULTIBYTE */
- ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
- : ((newlines == 1) ? wrap_offset : 0))
- : ((newlines == 0) ? wrap_offset :0));
-
- inv_lbreaks[++newlines] = temp;
-#if defined (HANDLE_MULTIBYTE)
- lpos -= _rl_col_width (local_prompt, n0, num);
-#else
- lpos -= _rl_screenwidth;
-#endif
- }
-
- prompt_last_screen_line = newlines;
-
- /* Draw the rest of the line (after the prompt) into invisible_line, keeping
- track of where the cursor is (c_pos), the number of the line containing
- the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
- It maintains an array of line breaks for display (inv_lbreaks).
- This handles expanding tabs for display and displaying meta characters. */
- lb_linenum = 0;
-#if defined (HANDLE_MULTIBYTE)
- in = 0;
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- memset (&ps, 0, sizeof (mbstate_t));
- wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
- }
- else
- wc_bytes = 1;
- while (in < rl_end)
-#else
- for (in = 0; in < rl_end; in++)
-#endif
- {
- c = (unsigned char)rl_line_buffer[in];
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- if (MB_INVALIDCH (wc_bytes))
- {
- /* Byte sequence is invalid or shortened. Assume that the
- first byte represents a character. */
- wc_bytes = 1;
- /* Assume that a character occupies a single column. */
- wc_width = 1;
- memset (&ps, 0, sizeof (mbstate_t));
- }
- else if (MB_NULLWCH (wc_bytes))
- break; /* Found '\0' */
- else
- {
- temp = wcwidth (wc);
- wc_width = (temp >= 0) ? temp : 1;
- }
- }
-#endif
-
- if (out + 8 >= line_size) /* XXX - 8 for \t */
- {
- line_size *= 2;
- visible_line = (char *)xrealloc (visible_line, line_size);
- invisible_line = (char *)xrealloc (invisible_line, line_size);
- line = invisible_line;
- }
-
- if (in == rl_point)
- {
- c_pos = out;
- lb_linenum = newlines;
- }
-
-#if defined (HANDLE_MULTIBYTE)
- if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
-#else
- if (META_CHAR (c))
-#endif
- {
- if (_rl_output_meta_chars == 0)
- {
- sprintf (line + out, "\\%o", c);
-
- if (lpos + 4 >= _rl_screenwidth)
- {
- temp = _rl_screenwidth - lpos;
- CHECK_INV_LBREAKS ();
- inv_lbreaks[++newlines] = out + temp;
- lpos = 4 - temp;
- }
- else
- lpos += 4;
-
- out += 4;
- }
- else
- {
- line[out++] = c;
- CHECK_LPOS();
- }
- }
-#if defined (DISPLAY_TABS)
- else if (c == '\t')
- {
- register int newout;
-
-#if 0
- newout = (out | (int)7) + 1;
-#else
- newout = out + 8 - lpos % 8;
-#endif
- temp = newout - out;
- if (lpos + temp >= _rl_screenwidth)
- {
- register int temp2;
- temp2 = _rl_screenwidth - lpos;
- CHECK_INV_LBREAKS ();
- inv_lbreaks[++newlines] = out + temp2;
- lpos = temp - temp2;
- while (out < newout)
- line[out++] = ' ';
- }
- else
- {
- while (out < newout)
- line[out++] = ' ';
- lpos += temp;
- }
- }
-#endif
- else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
- {
- line[out++] = '\0'; /* XXX - sentinel */
- CHECK_INV_LBREAKS ();
- inv_lbreaks[++newlines] = out;
- lpos = 0;
- }
- else if (CTRL_CHAR (c) || c == RUBOUT)
- {
- line[out++] = '^';
- CHECK_LPOS();
- line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
- CHECK_LPOS();
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- register int i;
-
- _rl_wrapped_multicolumn = 0;
-
- if (_rl_screenwidth < lpos + wc_width)
- for (i = lpos; i < _rl_screenwidth; i++)
- {
- /* The space will be removed in update_line() */
- line[out++] = ' ';
- _rl_wrapped_multicolumn++;
- CHECK_LPOS();
- }
- if (in == rl_point)
- {
- c_pos = out;
- lb_linenum = newlines;
- }
- for (i = in; i < in+wc_bytes; i++)
- line[out++] = rl_line_buffer[i];
- for (i = 0; i < wc_width; i++)
- CHECK_LPOS();
- }
- else
- {
- line[out++] = c;
- CHECK_LPOS();
- }
-#else
- line[out++] = c;
- CHECK_LPOS();
-#endif
- }
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- in += wc_bytes;
- wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
- }
- else
- in++;
-#endif
-
- }
- line[out] = '\0';
- if (c_pos < 0)
- {
- c_pos = out;
- lb_linenum = newlines;
- }
-
- inv_botlin = lb_botlin = newlines;
- CHECK_INV_LBREAKS ();
- inv_lbreaks[newlines+1] = out;
- cursor_linenum = lb_linenum;
-
- /* C_POS == position in buffer where cursor should be placed.
- CURSOR_LINENUM == line number where the cursor should be placed. */
-
- /* PWP: now is when things get a bit hairy. The visible and invisible
- line buffers are really multiple lines, which would wrap every
- (screenwidth - 1) characters. Go through each in turn, finding
- the changed region and updating it. The line order is top to bottom. */
-
- /* If we can move the cursor up and down, then use multiple lines,
- otherwise, let long lines display in a single terminal line, and
- horizontally scroll it. */
-
- if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
- {
- int nleft, pos, changed_screen_line, tx;
-
- if (!rl_display_fixed || forced_display)
- {
- forced_display = 0;
-
- /* If we have more than a screenful of material to display, then
- only display a screenful. We should display the last screen,
- not the first. */
- if (out >= _rl_screenchars)
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
- else
- out = _rl_screenchars - 1;
- }
-
- /* The first line is at character position 0 in the buffer. The
- second and subsequent lines start at inv_lbreaks[N], offset by
- OFFSET (which has already been calculated above). */
-
-#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
-#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
-#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
-#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
-#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
-#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
-
- /* For each line in the buffer, do the updating display. */
- for (linenum = 0; linenum <= inv_botlin; linenum++)
- {
- o_cpos = _rl_last_c_pos;
- cpos_adjusted = 0;
- update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
- VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
-
- /* update_line potentially changes _rl_last_c_pos, but doesn't
- take invisible characters into account, since _rl_last_c_pos
- is an absolute cursor position in a multibyte locale. See
- if compensating here is the right thing, or if we have to
- change update_line itself. There is one case in which
- update_line adjusts _rl_last_c_pos itself (so it can pass
- _rl_move_cursor_relative accurate values); it communicates
- this back by setting cpos_adjusted */
- if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
- cpos_adjusted == 0 &&
- _rl_last_c_pos != o_cpos &&
- _rl_last_c_pos > wrap_offset &&
- o_cpos < prompt_last_invisible)
- _rl_last_c_pos -= wrap_offset;
-
- /* If this is the line with the prompt, we might need to
- compensate for invisible characters in the new line. Do
- this only if there is not more than one new line (which
- implies that we completely overwrite the old visible line)
- and the new line is shorter than the old. Make sure we are
- at the end of the new line before clearing. */
- if (linenum == 0 &&
- inv_botlin == 0 && _rl_last_c_pos == out &&
- (wrap_offset > visible_wrap_offset) &&
- (_rl_last_c_pos < visible_first_line_len))
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- nleft = _rl_screenwidth - _rl_last_c_pos;
- else
- nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
- if (nleft)
- _rl_clear_to_eol (nleft);
- }
-
- /* Since the new first line is now visible, save its length. */
- if (linenum == 0)
- visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
- }
-
- /* We may have deleted some lines. If so, clear the left over
- blank ones at the bottom out. */
- if (_rl_vis_botlin > inv_botlin)
- {
- char *tt;
- for (; linenum <= _rl_vis_botlin; linenum++)
- {
- tt = VIS_CHARS (linenum);
- _rl_move_vert (linenum);
- _rl_move_cursor_relative (0, tt);
- _rl_clear_to_eol
- ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
- }
- }
- _rl_vis_botlin = inv_botlin;
-
- /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
- different screen line during this redisplay. */
- changed_screen_line = _rl_last_v_pos != cursor_linenum;
- if (changed_screen_line)
- {
- _rl_move_vert (cursor_linenum);
- /* If we moved up to the line with the prompt using _rl_term_up,
- the physical cursor position on the screen stays the same,
- but the buffer position needs to be adjusted to account
- for invisible characters. */
- if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
- _rl_last_c_pos += wrap_offset;
- }
-
- /* We have to reprint the prompt if it contains invisible
- characters, since it's not generally OK to just reprint
- the characters from the current cursor position. But we
- only need to reprint it if the cursor is before the last
- invisible character in the prompt string. */
- nleft = prompt_visible_length + wrap_offset;
- if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
-#if 0
- _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
-#else
- _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
-#endif
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- if (_rl_term_cr)
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_output_some_chars (local_prompt, nleft);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset;
- else
- _rl_last_c_pos = nleft;
- }
-
- /* Where on that line? And where does that line start
- in the buffer? */
- pos = inv_lbreaks[cursor_linenum];
- /* nleft == number of characters in the line buffer between the
- start of the line and the cursor position. */
- nleft = c_pos - pos;
-
- /* NLEFT is now a number of characters in a buffer. When in a
- multibyte locale, however, _rl_last_c_pos is an absolute cursor
- position that doesn't take invisible characters in the prompt
- into account. We use a fudge factor to compensate. */
-
- /* Since _rl_backspace() doesn't know about invisible characters in the
- prompt, and there's no good way to tell it, we compensate for
- those characters here and call _rl_backspace() directly. */
- if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset;
- else
- tx = nleft;
- if (_rl_last_c_pos > tx)
- {
- _rl_backspace (_rl_last_c_pos - tx); /* XXX */
- _rl_last_c_pos = tx;
- }
- }
-
- /* We need to note that in a multibyte locale we are dealing with
- _rl_last_c_pos as an absolute cursor position, but moving to a
- point specified by a buffer position (NLEFT) that doesn't take
- invisible characters into account. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- _rl_move_cursor_relative (nleft, &invisible_line[pos]);
- else if (nleft != _rl_last_c_pos)
- _rl_move_cursor_relative (nleft, &invisible_line[pos]);
- }
- }
- else /* Do horizontal scrolling. */
- {
-#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
- int lmargin, ndisp, nleft, phys_c_pos, t;
-
- /* Always at top line. */
- _rl_last_v_pos = 0;
-
- /* Compute where in the buffer the displayed line should start. This
- will be LMARGIN. */
-
- /* The number of characters that will be displayed before the cursor. */
- ndisp = c_pos - wrap_offset;
- nleft = prompt_visible_length + wrap_offset;
- /* Where the new cursor position will be on the screen. This can be
- longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
- phys_c_pos = c_pos - (last_lmargin ? last_lmargin : wrap_offset);
- t = _rl_screenwidth / 3;
-
- /* If the number of characters had already exceeded the screenwidth,
- last_lmargin will be > 0. */
-
- /* If the number of characters to be displayed is more than the screen
- width, compute the starting offset so that the cursor is about
- two-thirds of the way across the screen. */
- if (phys_c_pos > _rl_screenwidth - 2)
- {
- lmargin = c_pos - (2 * t);
- if (lmargin < 0)
- lmargin = 0;
- /* If the left margin would be in the middle of a prompt with
- invisible characters, don't display the prompt at all. */
- if (wrap_offset && lmargin > 0 && lmargin < nleft)
- lmargin = nleft;
- }
- else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
- lmargin = 0;
- else if (phys_c_pos < 1)
- {
- /* If we are moving back towards the beginning of the line and
- the last margin is no longer correct, compute a new one. */
- lmargin = ((c_pos - 1) / t) * t; /* XXX */
- if (wrap_offset && lmargin > 0 && lmargin < nleft)
- lmargin = nleft;
- }
- else
- lmargin = last_lmargin;
-
- /* If the first character on the screen isn't the first character
- in the display line, indicate this with a special character. */
- if (lmargin > 0)
- line[lmargin] = '<';
-
- /* If SCREENWIDTH characters starting at LMARGIN do not encompass
- the whole line, indicate that with a special character at the
- right edge of the screen. If LMARGIN is 0, we need to take the
- wrap offset into account. */
- t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
- if (t < out)
- line[t - 1] = '>';
-
- if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
- {
- forced_display = 0;
- update_line (&visible_line[last_lmargin],
- &invisible_line[lmargin],
- 0,
- _rl_screenwidth + visible_wrap_offset,
- _rl_screenwidth + (lmargin ? 0 : wrap_offset),
- 0);
-
- /* If the visible new line is shorter than the old, but the number
- of invisible characters is greater, and we are at the end of
- the new line, we need to clear to eol. */
- t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
- if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
- (_rl_last_c_pos == out) &&
- t < visible_first_line_len)
- {
- nleft = _rl_screenwidth - t;
- _rl_clear_to_eol (nleft);
- }
- visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
- if (visible_first_line_len > _rl_screenwidth)
- visible_first_line_len = _rl_screenwidth;
-
- _rl_move_cursor_relative (c_pos - lmargin, &invisible_line[lmargin]);
- last_lmargin = lmargin;
- }
- }
- fflush (rl_outstream);
-
- /* Swap visible and non-visible lines. */
- {
- char *vtemp = visible_line;
- int *itemp = vis_lbreaks, ntemp = vis_lbsize;
-
- visible_line = invisible_line;
- invisible_line = vtemp;
-
- vis_lbreaks = inv_lbreaks;
- inv_lbreaks = itemp;
-
- vis_lbsize = inv_lbsize;
- inv_lbsize = ntemp;
-
- rl_display_fixed = 0;
- /* If we are displaying on a single line, and last_lmargin is > 0, we
- are not displaying any invisible characters, so set visible_wrap_offset
- to 0. */
- if (_rl_horizontal_scroll_mode && last_lmargin)
- visible_wrap_offset = 0;
- else
- visible_wrap_offset = wrap_offset;
- }
-}
-
-/* PWP: update_line() is based on finding the middle difference of each
- line on the screen; vis:
-
- /old first difference
- /beginning of line | /old last same /old EOL
- v v v v
-old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
-new: eddie> Oh, my little buggy says to me, as lurgid as
- ^ ^ ^ ^
- \beginning of line | \new last same \new end of line
- \new first difference
-
- All are character pointers for the sake of speed. Special cases for
- no differences, as well as for end of line additions must be handled.
-
- Could be made even smarter, but this works well enough */
-static void
-update_line (old, new, current_line, omax, nmax, inv_botlin)
- register char *old, *new;
- int current_line, omax, nmax, inv_botlin;
-{
- register char *ofd, *ols, *oe, *nfd, *nls, *ne;
- int temp, lendiff, wsatend, od, nd;
- int current_invis_chars;
- int col_lendiff, col_temp;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps_new, ps_old;
- int new_offset, old_offset;
-#endif
-
- /* If we're at the right edge of a terminal that supports xn, we're
- ready to wrap around, so do so. This fixes problems with knowing
- the exact cursor position and cut-and-paste with certain terminal
- emulators. In this calculation, TEMP is the physical screen
- position of the cursor. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- temp = _rl_last_c_pos;
- else
- temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
- if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
- && _rl_last_v_pos == current_line - 1)
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- wchar_t wc;
- mbstate_t ps;
- int tempwidth, bytes;
- size_t ret;
-
- /* This fixes only double-column characters, but if the wrapped
- character comsumes more than three columns, spaces will be
- inserted in the string buffer. */
- if (_rl_wrapped_line[current_line] > 0)
- _rl_clear_to_eol (_rl_wrapped_line[current_line]);
-
- memset (&ps, 0, sizeof (mbstate_t));
- ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
- if (MB_INVALIDCH (ret))
- {
- tempwidth = 1;
- ret = 1;
- }
- else if (MB_NULLWCH (ret))
- tempwidth = 0;
- else
- tempwidth = wcwidth (wc);
-
- if (tempwidth > 0)
- {
- int count;
- bytes = ret;
- for (count = 0; count < bytes; count++)
- putc (new[count], rl_outstream);
- _rl_last_c_pos = tempwidth;
- _rl_last_v_pos++;
- memset (&ps, 0, sizeof (mbstate_t));
- ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
- if (ret != 0 && bytes != 0)
- {
- if (MB_INVALIDCH (ret))
- memmove (old+bytes, old+1, strlen (old+1));
- else
- memmove (old+bytes, old+ret, strlen (old+ret));
- memcpy (old, new, bytes);
- }
- }
- else
- {
- putc (' ', rl_outstream);
- _rl_last_c_pos = 1;
- _rl_last_v_pos++;
- if (old[0] && new[0])
- old[0] = new[0];
- }
- }
- else
-#endif
- {
- if (new[0])
- putc (new[0], rl_outstream);
- else
- putc (' ', rl_outstream);
- _rl_last_c_pos = 1;
- _rl_last_v_pos++;
- if (old[0] && new[0])
- old[0] = new[0];
- }
- }
-
-
- /* Find first difference. */
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- /* See if the old line is a subset of the new line, so that the
- only change is adding characters. */
- temp = (omax < nmax) ? omax : nmax;
- if (memcmp (old, new, temp) == 0)
- {
- ofd = old + temp;
- nfd = new + temp;
- }
- else
- {
- memset (&ps_new, 0, sizeof(mbstate_t));
- memset (&ps_old, 0, sizeof(mbstate_t));
-
- if (omax == nmax && STREQN (new, old, omax))
- {
- ofd = old + omax;
- nfd = new + nmax;
- }
- else
- {
- new_offset = old_offset = 0;
- for (ofd = old, nfd = new;
- (ofd - old < omax) && *ofd &&
- _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
- {
- old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
- new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
- ofd = old + old_offset;
- nfd = new + new_offset;
- }
- }
- }
- }
- else
-#endif
- for (ofd = old, nfd = new;
- (ofd - old < omax) && *ofd && (*ofd == *nfd);
- ofd++, nfd++)
- ;
-
- /* Move to the end of the screen line. ND and OD are used to keep track
- of the distance between ne and new and oe and old, respectively, to
- move a subtraction out of each loop. */
- for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
- for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
-
- /* If no difference, continue to next line. */
- if (ofd == oe && nfd == ne)
- return;
-
- wsatend = 1; /* flag for trailing whitespace */
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
- nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
- while ((ols > ofd) && (nls > nfd))
- {
- memset (&ps_old, 0, sizeof (mbstate_t));
- memset (&ps_new, 0, sizeof (mbstate_t));
-
-#if 0
- /* On advice from jir@yamato.ibm.com */
- _rl_adjust_point (old, ols - old, &ps_old);
- _rl_adjust_point (new, nls - new, &ps_new);
-#endif
-
- if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
- break;
-
- if (*ols == ' ')
- wsatend = 0;
-
- ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
- nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
- }
- }
- else
- {
-#endif /* HANDLE_MULTIBYTE */
- ols = oe - 1; /* find last same */
- nls = ne - 1;
- while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
- {
- if (*ols != ' ')
- wsatend = 0;
- ols--;
- nls--;
- }
-#if defined (HANDLE_MULTIBYTE)
- }
-#endif
-
- if (wsatend)
- {
- ols = oe;
- nls = ne;
- }
-#if defined (HANDLE_MULTIBYTE)
- /* This may not work for stateful encoding, but who cares? To handle
- stateful encoding properly, we have to scan each string from the
- beginning and compare. */
- else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
-#else
- else if (*ols != *nls)
-#endif
- {
- if (*ols) /* don't step past the NUL */
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
- else
- ols++;
- }
- if (*nls)
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
- else
- nls++;
- }
- }
-
- /* count of invisible characters in the current invisible line. */
- current_invis_chars = W_OFFSET (current_line, wrap_offset);
- if (_rl_last_v_pos != current_line)
- {
- _rl_move_vert (current_line);
- if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
- _rl_last_c_pos += visible_wrap_offset;
- }
-
- /* If this is the first line and there are invisible characters in the
- prompt string, and the prompt string has not changed, and the current
- cursor position is before the last invisible character in the prompt,
- and the index of the character to move to is past the end of the prompt
- string, then redraw the entire prompt string. We can only do this
- reliably if the terminal supports a `cr' capability.
-
- This is not an efficiency hack -- there is a problem with redrawing
- portions of the prompt string if they contain terminal escape
- sequences (like drawing the `unbold' sequence without a corresponding
- `bold') that manifests itself on certain terminals. */
-
- lendiff = local_prompt ? strlen (local_prompt) : 0;
- od = ofd - old; /* index of first difference in visible line */
- if (current_line == 0 && !_rl_horizontal_scroll_mode &&
- _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
- od >= lendiff && _rl_last_c_pos <= PROMPT_ENDING_INDEX)
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_output_some_chars (local_prompt, lendiff);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- /* We take wrap_offset into account here so we can pass correct
- information to _rl_move_cursor_relative. */
- _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset;
- cpos_adjusted = 1;
- }
- else
- _rl_last_c_pos = lendiff;
- }
-
- _rl_move_cursor_relative (od, old);
-
- /* if (len (new) > len (old))
- lendiff == difference in buffer
- col_lendiff == difference on screen
- When not using multibyte characters, these are equal */
- lendiff = (nls - nfd) - (ols - ofd);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
- else
- col_lendiff = lendiff;
-
- /* If we are changing the number of invisible characters in a line, and
- the spot of first difference is before the end of the invisible chars,
- lendiff needs to be adjusted. */
- if (current_line == 0 && !_rl_horizontal_scroll_mode &&
- current_invis_chars != visible_wrap_offset)
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- lendiff += visible_wrap_offset - current_invis_chars;
- col_lendiff += visible_wrap_offset - current_invis_chars;
- }
- else
- {
- lendiff += visible_wrap_offset - current_invis_chars;
- col_lendiff = lendiff;
- }
- }
-
- /* Insert (diff (len (old), len (new)) ch. */
- temp = ne - nfd;
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- col_temp = _rl_col_width (new, nfd - new, ne - new);
- else
- col_temp = temp;
-
- if (col_lendiff > 0) /* XXX - was lendiff */
- {
- /* Non-zero if we're increasing the number of lines. */
- int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
- /* Sometimes it is cheaper to print the characters rather than
- use the terminal's capabilities. If we're growing the number
- of lines, make sure we actually cause the new line to wrap
- around on auto-wrapping terminals. */
- if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
- {
- /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
- _rl_horizontal_scroll_mode == 1, inserting the characters with
- _rl_term_IC or _rl_term_ic will screw up the screen because of the
- invisible characters. We need to just draw them. */
- if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
- lendiff <= prompt_visible_length || !current_invis_chars))
- {
- insert_some_chars (nfd, lendiff, col_lendiff);
- _rl_last_c_pos += col_lendiff;
- }
- else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
- {
- /* At the end of a line the characters do not have to
- be "inserted". They can just be placed on the screen. */
- /* However, this screws up the rest of this block, which
- assumes you've done the insert because you can. */
- _rl_output_some_chars (nfd, lendiff);
- _rl_last_c_pos += col_lendiff;
- }
- else
- {
- /* We have horizontal scrolling and we are not inserting at
- the end. We have invisible characters in this line. This
- is a dumb update. */
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += col_temp;
- return;
- }
- /* Copy (new) chars to screen from first diff to last match. */
- temp = nls - nfd;
- if ((temp - lendiff) > 0)
- {
- _rl_output_some_chars (nfd + lendiff, temp - lendiff);
-#if 1
- /* XXX -- this bears closer inspection. Fixes a redisplay bug
- reported against bash-3.0-alpha by Andreas Schwab involving
- multibyte characters and prompt strings with invisible
- characters, but was previously disabled. */
- _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
-#else
- _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
-#endif
- }
- }
- else
- {
- /* cannot insert chars, write to EOL */
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += col_temp;
- /* If we're in a multibyte locale and were before the last invisible
- char in the current line (which implies we just output some invisible
- characters) we need to adjust _rl_last_c_pos, since it represents
- a physical character position. */
- }
- }
- else /* Delete characters from line. */
- {
- /* If possible and inexpensive to use terminal deletion, then do so. */
- if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
- {
- /* If all we're doing is erasing the invisible characters in the
- prompt string, don't bother. It screws up the assumptions
- about what's on the screen. */
- if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
- -lendiff == visible_wrap_offset)
- col_lendiff = 0;
-
- if (col_lendiff)
- delete_chars (-col_lendiff); /* delete (diff) characters */
-
- /* Copy (new) chars to screen from first diff to last match */
- temp = nls - nfd;
- if (temp > 0)
- {
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
- }
- }
- /* Otherwise, print over the existing material. */
- else
- {
- if (temp > 0)
- {
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += col_temp; /* XXX */
- }
- lendiff = (oe - old) - (ne - new);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
- else
- col_lendiff = lendiff;
-
- if (col_lendiff)
- {
- if (_rl_term_autowrap && current_line < inv_botlin)
- space_to_eol (col_lendiff);
- else
- _rl_clear_to_eol (col_lendiff);
- }
- }
- }
-}
-
-/* Tell the update routines that we have moved onto a new (empty) line. */
-int
-rl_on_new_line ()
-{
- if (visible_line)
- visible_line[0] = '\0';
-
- _rl_last_c_pos = _rl_last_v_pos = 0;
- _rl_vis_botlin = last_lmargin = 0;
- if (vis_lbreaks)
- vis_lbreaks[0] = vis_lbreaks[1] = 0;
- visible_wrap_offset = 0;
- return 0;
-}
-
-/* Tell the update routines that we have moved onto a new line with the
- prompt already displayed. Code originally from the version of readline
- distributed with CLISP. rl_expand_prompt must have already been called
- (explicitly or implicitly). This still doesn't work exactly right. */
-int
-rl_on_new_line_with_prompt ()
-{
- int prompt_size, i, l, real_screenwidth, newlines;
- char *prompt_last_line, *lprompt;
-
- /* Initialize visible_line and invisible_line to ensure that they can hold
- the already-displayed prompt. */
- prompt_size = strlen (rl_prompt) + 1;
- init_line_structures (prompt_size);
-
- /* Make sure the line structures hold the already-displayed prompt for
- redisplay. */
- lprompt = local_prompt ? local_prompt : rl_prompt;
- strcpy (visible_line, lprompt);
- strcpy (invisible_line, lprompt);
-
- /* If the prompt contains newlines, take the last tail. */
- prompt_last_line = strrchr (rl_prompt, '\n');
- if (!prompt_last_line)
- prompt_last_line = rl_prompt;
-
- l = strlen (prompt_last_line);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); /* XXX */
- else
- _rl_last_c_pos = l;
-
- /* Dissect prompt_last_line into screen lines. Note that here we have
- to use the real screenwidth. Readline's notion of screenwidth might be
- one less, see terminal.c. */
- real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
- _rl_last_v_pos = l / real_screenwidth;
- /* If the prompt length is a multiple of real_screenwidth, we don't know
- whether the cursor is at the end of the last line, or already at the
- beginning of the next line. Output a newline just to be safe. */
- if (l > 0 && (l % real_screenwidth) == 0)
- _rl_output_some_chars ("\n", 1);
- last_lmargin = 0;
-
- newlines = 0; i = 0;
- while (i <= l)
- {
- _rl_vis_botlin = newlines;
- vis_lbreaks[newlines++] = i;
- i += real_screenwidth;
- }
- vis_lbreaks[newlines] = l;
- visible_wrap_offset = 0;
-
- rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
-
- return 0;
-}
-
-/* Actually update the display, period. */
-int
-rl_forced_update_display ()
-{
- register char *temp;
-
- if (visible_line)
- {
- temp = visible_line;
- while (*temp)
- *temp++ = '\0';
- }
- rl_on_new_line ();
- forced_display++;
- (*rl_redisplay_function) ();
- return 0;
-}
-
-/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
- (Well, when we don't have multibyte characters, _rl_last_c_pos is a
- buffer index.)
- DATA is the contents of the screen line of interest; i.e., where
- the movement is being done. */
-void
-_rl_move_cursor_relative (new, data)
- int new;
- const char *data;
-{
- register int i;
- int woff; /* number of invisible chars on current line */
- int cpos, dpos; /* current and desired cursor positions */
-
- woff = W_OFFSET (_rl_last_v_pos, wrap_offset);
- cpos = _rl_last_c_pos;
-#if defined (HANDLE_MULTIBYTE)
- /* If we have multibyte characters, NEW is indexed by the buffer point in
- a multibyte string, but _rl_last_c_pos is the display position. In
- this case, NEW's display position is not obvious and must be
- calculated. We need to account for invisible characters in this line,
- as long as we are past them and they are counted by _rl_col_width. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- dpos = _rl_col_width (data, 0, new);
- if (dpos > woff)
- dpos -= woff;
- }
- else
-#endif
- dpos = new;
-
- /* If we don't have to do anything, then return. */
- if (cpos == dpos)
- return;
-
- /* It may be faster to output a CR, and then move forwards instead
- of moving backwards. */
- /* i == current physical cursor position. */
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- i = _rl_last_c_pos;
- else
-#endif
- i = _rl_last_c_pos - woff;
- if (new == 0 || CR_FASTER (new, _rl_last_c_pos) ||
- (_rl_term_autowrap && i == _rl_screenwidth))
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif /* !__MSDOS__ */
- cpos = _rl_last_c_pos = 0;
- }
-
- if (cpos < dpos)
- {
- /* Move the cursor forward. We do it by printing the command
- to move the cursor forward if there is one, else print that
- portion of the output buffer again. Which is cheaper? */
-
- /* The above comment is left here for posterity. It is faster
- to print one character (non-control) than to print a control
- sequence telling the terminal to move forward one character.
- That kind of control is for people who don't know what the
- data is underneath the cursor. */
-#if defined (HACK_TERMCAP_MOTION)
- if (_rl_term_forward_char)
- {
- for (i = cpos; i < dpos; i++)
- tputs (_rl_term_forward_char, 1, _rl_output_character_function);
- }
- else
-#endif /* HACK_TERMCAP_MOTION */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- tputs (_rl_term_cr, 1, _rl_output_character_function);
- for (i = 0; i < new; i++)
- putc (data[i], rl_outstream);
- }
- else
- for (i = cpos; i < new; i++)
- putc (data[i], rl_outstream);
- }
-
-#if defined (HANDLE_MULTIBYTE)
- /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
- The byte length of the string is probably bigger than the column width
- of the string, which means that if NEW == _rl_last_c_pos, then NEW's
- display point is less than _rl_last_c_pos. */
-#endif
- else if (cpos > dpos)
- _rl_backspace (cpos - dpos);
-
- _rl_last_c_pos = dpos;
-}
-
-/* PWP: move the cursor up or down. */
-void
-_rl_move_vert (to)
- int to;
-{
- register int delta, i;
-
- if (_rl_last_v_pos == to || to > _rl_screenheight)
- return;
-
- if ((delta = to - _rl_last_v_pos) > 0)
- {
- for (i = 0; i < delta; i++)
- putc ('\n', rl_outstream);
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_last_c_pos = 0;
- }
- else
- { /* delta < 0 */
- if (_rl_term_up && *_rl_term_up)
- for (i = 0; i < -delta; i++)
- tputs (_rl_term_up, 1, _rl_output_character_function);
- }
-
- _rl_last_v_pos = to; /* Now TO is here */
-}
-
-/* Physically print C on rl_outstream. This is for functions which know
- how to optimize the display. Return the number of characters output. */
-int
-rl_show_char (c)
- int c;
-{
- int n = 1;
- if (META_CHAR (c) && (_rl_output_meta_chars == 0))
- {
- fprintf (rl_outstream, "M-");
- n += 2;
- c = UNMETA (c);
- }
-
-#if defined (DISPLAY_TABS)
- if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
-#else
- if (CTRL_CHAR (c) || c == RUBOUT)
-#endif /* !DISPLAY_TABS */
- {
- fprintf (rl_outstream, "C-");
- n += 2;
- c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
- }
-
- putc (c, rl_outstream);
- fflush (rl_outstream);
- return n;
-}
-
-int
-rl_character_len (c, pos)
- register int c, pos;
-{
- unsigned char uc;
-
- uc = (unsigned char)c;
-
- if (META_CHAR (uc))
- return ((_rl_output_meta_chars == 0) ? 4 : 1);
-
- if (uc == '\t')
- {
-#if defined (DISPLAY_TABS)
- return (((pos | 7) + 1) - pos);
-#else
- return (2);
-#endif /* !DISPLAY_TABS */
- }
-
- if (CTRL_CHAR (c) || c == RUBOUT)
- return (2);
-
- return ((ISPRINT (uc)) ? 1 : 2);
-}
-/* How to print things in the "echo-area". The prompt is treated as a
- mini-modeline. */
-static int msg_saved_prompt = 0;
-
-#if defined (USE_VARARGS)
-int
-#if defined (PREFER_STDARG)
-rl_message (const char *format, ...)
-#else
-rl_message (va_alist)
- va_dcl
-#endif
-{
- va_list args;
-#if defined (PREFER_VARARGS)
- char *format;
-#endif
-
-#if defined (PREFER_STDARG)
- va_start (args, format);
-#else
- va_start (args);
- format = va_arg (args, char *);
-#endif
-
-#if defined (HAVE_VSNPRINTF)
- vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
-#else
- vsprintf (msg_buf, format, args);
- msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
-#endif
- va_end (args);
-
- if (saved_local_prompt == 0)
- {
- rl_save_prompt ();
- msg_saved_prompt = 1;
- }
- rl_display_prompt = msg_buf;
- local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
- local_prompt_prefix = (char *)NULL;
- (*rl_redisplay_function) ();
-
- return 0;
-}
-#else /* !USE_VARARGS */
-int
-rl_message (format, arg1, arg2)
- char *format;
-{
- sprintf (msg_buf, format, arg1, arg2);
- msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
-
- rl_display_prompt = msg_buf;
- if (saved_local_prompt == 0)
- {
- rl_save_prompt ();
- msg_saved_prompt = 1;
- }
- local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
- local_prompt_prefix = (char *)NULL;
- (*rl_redisplay_function) ();
-
- return 0;
-}
-#endif /* !USE_VARARGS */
-
-/* How to clear things from the "echo-area". */
-int
-rl_clear_message ()
-{
- rl_display_prompt = rl_prompt;
- if (msg_saved_prompt)
- {
- rl_restore_prompt ();
- msg_saved_prompt = 0;
- }
- (*rl_redisplay_function) ();
- return 0;
-}
-
-int
-rl_reset_line_state ()
-{
- rl_on_new_line ();
-
- rl_display_prompt = rl_prompt ? rl_prompt : "";
- forced_display = 1;
- return 0;
-}
-
-void
-rl_save_prompt ()
-{
- saved_local_prompt = local_prompt;
- saved_local_prefix = local_prompt_prefix;
- saved_prefix_length = prompt_prefix_length;
- saved_last_invisible = prompt_last_invisible;
- saved_visible_length = prompt_visible_length;
- saved_invis_chars_first_line = prompt_invis_chars_first_line;
- saved_physical_chars = prompt_physical_chars;
-
- local_prompt = local_prompt_prefix = (char *)0;
- prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
- prompt_invis_chars_first_line = prompt_physical_chars = 0;
-}
-
-void
-rl_restore_prompt ()
-{
- FREE (local_prompt);
- FREE (local_prompt_prefix);
-
- local_prompt = saved_local_prompt;
- local_prompt_prefix = saved_local_prefix;
- prompt_prefix_length = saved_prefix_length;
- prompt_last_invisible = saved_last_invisible;
- prompt_visible_length = saved_visible_length;
- prompt_invis_chars_first_line = saved_invis_chars_first_line;
- prompt_physical_chars = saved_physical_chars;
-
- /* can test saved_local_prompt to see if prompt info has been saved. */
- saved_local_prompt = saved_local_prefix = (char *)0;
- saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
- saved_invis_chars_first_line = saved_physical_chars = 0;
-}
-
-char *
-_rl_make_prompt_for_search (pchar)
- int pchar;
-{
- int len;
- char *pmt, *p;
-
- rl_save_prompt ();
-
- /* We've saved the prompt, and can do anything with the various prompt
- strings we need before they're restored. We want the unexpanded
- portion of the prompt string after any final newline. */
- p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
- if (p == 0)
- {
- len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
- pmt = (char *)xmalloc (len + 2);
- if (len)
- strcpy (pmt, rl_prompt);
- pmt[len] = pchar;
- pmt[len+1] = '\0';
- }
- else
- {
- p++;
- len = strlen (p);
- pmt = (char *)xmalloc (len + 2);
- if (len)
- strcpy (pmt, p);
- pmt[len] = pchar;
- pmt[len+1] = '\0';
- }
-
- /* will be overwritten by expand_prompt, called from rl_message */
- prompt_physical_chars = saved_physical_chars + 1;
- return pmt;
-}
-
-/* Quick redisplay hack when erasing characters at the end of the line. */
-void
-_rl_erase_at_end_of_line (l)
- int l;
-{
- register int i;
-
- _rl_backspace (l);
- for (i = 0; i < l; i++)
- putc (' ', rl_outstream);
- _rl_backspace (l);
- for (i = 0; i < l; i++)
- visible_line[--_rl_last_c_pos] = '\0';
- rl_display_fixed++;
-}
-
-/* Clear to the end of the line. COUNT is the minimum
- number of character spaces to clear, */
-void
-_rl_clear_to_eol (count)
- int count;
-{
- if (_rl_term_clreol)
- tputs (_rl_term_clreol, 1, _rl_output_character_function);
- else if (count)
- space_to_eol (count);
-}
-
-/* Clear to the end of the line using spaces. COUNT is the minimum
- number of character spaces to clear, */
-static void
-space_to_eol (count)
- int count;
-{
- register int i;
-
- for (i = 0; i < count; i++)
- putc (' ', rl_outstream);
-
- _rl_last_c_pos += count;
-}
-
-void
-_rl_clear_screen ()
-{
- if (_rl_term_clrpag)
- tputs (_rl_term_clrpag, 1, _rl_output_character_function);
- else
- rl_crlf ();
-}
-
-/* Insert COUNT characters from STRING to the output stream at column COL. */
-static void
-insert_some_chars (string, count, col)
- char *string;
- int count, col;
-{
-#if defined (__MSDOS__) || defined (__MINGW32__)
- _rl_output_some_chars (string, count);
-#else
- /* DEBUGGING */
- if (MB_CUR_MAX == 1 || rl_byte_oriented)
- if (count != col)
- fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
-
- /* If IC is defined, then we do not have to "enter" insert mode. */
- if (_rl_term_IC)
- {
- char *buffer;
-
- buffer = tgoto (_rl_term_IC, 0, col);
- tputs (buffer, 1, _rl_output_character_function);
- _rl_output_some_chars (string, count);
- }
- else
- {
- register int i;
-
- /* If we have to turn on insert-mode, then do so. */
- if (_rl_term_im && *_rl_term_im)
- tputs (_rl_term_im, 1, _rl_output_character_function);
-
- /* If there is a special command for inserting characters, then
- use that first to open up the space. */
- if (_rl_term_ic && *_rl_term_ic)
- {
- for (i = col; i--; )
- tputs (_rl_term_ic, 1, _rl_output_character_function);
- }
-
- /* Print the text. */
- _rl_output_some_chars (string, count);
-
- /* If there is a string to turn off insert mode, we had best use
- it now. */
- if (_rl_term_ei && *_rl_term_ei)
- tputs (_rl_term_ei, 1, _rl_output_character_function);
- }
-#endif /* __MSDOS__ || __MINGW32__ */
-}
-
-/* Delete COUNT characters from the display line. */
-static void
-delete_chars (count)
- int count;
-{
- if (count > _rl_screenwidth) /* XXX */
- return;
-
-#if !defined (__MSDOS__) && !defined (__MINGW32__)
- if (_rl_term_DC && *_rl_term_DC)
- {
- char *buffer;
- buffer = tgoto (_rl_term_DC, count, count);
- tputs (buffer, count, _rl_output_character_function);
- }
- else
- {
- if (_rl_term_dc && *_rl_term_dc)
- while (count--)
- tputs (_rl_term_dc, 1, _rl_output_character_function);
- }
-#endif /* !__MSDOS__ && !__MINGW32__ */
-}
-
-void
-_rl_update_final ()
-{
- int full_lines;
-
- full_lines = 0;
- /* If the cursor is the only thing on an otherwise-blank last line,
- compensate so we don't print an extra CRLF. */
- if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
- visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
- {
- _rl_vis_botlin--;
- full_lines = 1;
- }
- _rl_move_vert (_rl_vis_botlin);
- /* If we've wrapped lines, remove the final xterm line-wrap flag. */
- if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
- {
- char *last_line;
-
- last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
- _rl_move_cursor_relative (_rl_screenwidth - 1, last_line);
- _rl_clear_to_eol (0);
- putc (last_line[_rl_screenwidth - 1], rl_outstream);
- }
- _rl_vis_botlin = 0;
- rl_crlf ();
- fflush (rl_outstream);
- rl_display_fixed++;
-}
-
-/* Move to the start of the current line. */
-static void
-cr ()
-{
- if (_rl_term_cr)
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_last_c_pos = 0;
- }
-}
-
-/* Redraw the last line of a multi-line prompt that may possibly contain
- terminal escape sequences. Called with the cursor at column 0 of the
- line to draw the prompt on. */
-static void
-redraw_prompt (t)
- char *t;
-{
- char *oldp;
-
- oldp = rl_display_prompt;
- rl_save_prompt ();
-
- rl_display_prompt = t;
- local_prompt = expand_prompt (t, &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
- local_prompt_prefix = (char *)NULL;
-
- rl_forced_update_display ();
-
- rl_display_prompt = oldp;
- rl_restore_prompt();
-}
-
-/* Redisplay the current line after a SIGWINCH is received. */
-void
-_rl_redisplay_after_sigwinch ()
-{
- char *t;
-
- /* Clear the current line and put the cursor at column 0. Make sure
- the right thing happens if we have wrapped to a new screen line. */
- if (_rl_term_cr)
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_last_c_pos = 0;
-#if defined (__MSDOS__)
- space_to_eol (_rl_screenwidth);
- putc ('\r', rl_outstream);
-#else
- if (_rl_term_clreol)
- tputs (_rl_term_clreol, 1, _rl_output_character_function);
- else
- {
- space_to_eol (_rl_screenwidth);
- tputs (_rl_term_cr, 1, _rl_output_character_function);
- }
-#endif
- if (_rl_last_v_pos > 0)
- _rl_move_vert (0);
- }
- else
- rl_crlf ();
-
- /* Redraw only the last line of a multi-line prompt. */
- t = strrchr (rl_display_prompt, '\n');
- if (t)
- redraw_prompt (++t);
- else
- rl_forced_update_display ();
-}
-
-void
-_rl_clean_up_for_exit ()
-{
- if (readline_echoing_p)
- {
- _rl_move_vert (_rl_vis_botlin);
- _rl_vis_botlin = 0;
- fflush (rl_outstream);
- rl_restart_output (1, 0);
- }
-}
-
-void
-_rl_erase_entire_line ()
-{
- cr ();
- _rl_clear_to_eol (0);
- cr ();
- fflush (rl_outstream);
-}
-
-/* return the `current display line' of the cursor -- the number of lines to
- move up to get to the first screen line of the current readline line. */
-int
-_rl_current_display_line ()
-{
- int ret, nleft;
-
- /* Find out whether or not there might be invisible characters in the
- editing buffer. */
- if (rl_display_prompt == rl_prompt)
- nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
- else
- nleft = _rl_last_c_pos - _rl_screenwidth;
-
- if (nleft > 0)
- ret = 1 + nleft / _rl_screenwidth;
- else
- ret = 0;
-
- return ret;
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* Calculate the number of screen columns occupied by STR from START to END.
- In the case of multibyte characters with stateful encoding, we have to
- scan from the beginning of the string to take the state into account. */
-static int
-_rl_col_width (str, start, end)
- const char *str;
- int start, end;
-{
- wchar_t wc;
- mbstate_t ps = {0};
- int tmp, point, width, max;
-
- if (end <= start)
- return 0;
-
- point = 0;
- max = end;
-
- while (point < start)
- {
- tmp = mbrlen (str + point, max, &ps);
- if (MB_INVALIDCH ((size_t)tmp))
- {
- /* In this case, the bytes are invalid or too short to compose a
- multibyte character, so we assume that the first byte represents
- a single character. */
- point++;
- max--;
-
- /* 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 (MB_NULLWCH (tmp))
- break; /* Found '\0' */
- else
- {
- point += tmp;
- max -= tmp;
- }
- }
-
- /* If START is not a byte that starts a character, then POINT will be
- greater than START. In this case, assume that (POINT - START) gives
- a byte count that is the number of columns of difference. */
- width = point - start;
-
- while (point < end)
- {
- tmp = mbrtowc (&wc, str + point, max, &ps);
- if (MB_INVALIDCH ((size_t)tmp))
- {
- /* In this case, the bytes are invalid or too short to compose a
- multibyte character, so we assume that the first byte represents
- a single character. */
- point++;
- max--;
-
- /* and assume that the byte occupies a single column. */
- width++;
-
- /* 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 (MB_NULLWCH (tmp))
- break; /* Found '\0' */
- else
- {
- point += tmp;
- max -= tmp;
- tmp = wcwidth(wc);
- width += (tmp >= 0) ? tmp : 1;
- }
- }
-
- width += point - end;
-
- return width;
-}
-#endif /* HANDLE_MULTIBYTE */
diff --git a/lib/readline/display.c~ b/lib/readline/display.c~
deleted file mode 100644
index 253cf65f..00000000
--- a/lib/readline/display.c~
+++ /dev/null
@@ -1,2439 +0,0 @@
-/* display.c -- readline redisplay facility. */
-
-/* Copyright (C) 1987-2006 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>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-
-#include "posixstat.h"
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-/* Termcap library stuff. */
-#include "tcap.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#include "rlprivate.h"
-#include "xmalloc.h"
-
-#if !defined (strchr) && !defined (__STDC__)
-extern char *strchr (), *strrchr ();
-#endif /* !strchr && !__STDC__ */
-
-static void update_line PARAMS((char *, char *, int, int, int, int));
-static void space_to_eol PARAMS((int));
-static void delete_chars PARAMS((int));
-static void insert_some_chars PARAMS((char *, int, int));
-static void cr PARAMS((void));
-
-#if defined (HANDLE_MULTIBYTE)
-static int _rl_col_width PARAMS((const char *, int, int));
-static int *_rl_wrapped_line;
-#else
-# define _rl_col_width(l, s, e) (((e) <= (s)) ? 0 : (e) - (s))
-#endif
-
-static int *inv_lbreaks, *vis_lbreaks;
-static int inv_lbsize, vis_lbsize;
-
-/* Heuristic used to decide whether it is faster to move from CUR to NEW
- by backing up or outputting a carriage return and moving forward. CUR
- and NEW are either both buffer positions or absolute screen positions. */
-#define CR_FASTER(new, cur) (((new) + 1) < ((cur) - (new)))
-
-/* _rl_last_c_pos is an absolute cursor position in multibyte locales and a
- buffer index in others. This macro is used when deciding whether the
- current cursor position is in the middle of a prompt string containing
- invisible characters. */
-#define PROMPT_ENDING_INDEX \
- ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) ? prompt_physical_chars : prompt_last_invisible+1)
-
-
-/* **************************************************************** */
-/* */
-/* Display stuff */
-/* */
-/* **************************************************************** */
-
-/* This is the stuff that is hard for me. I never seem to write good
- display routines in C. Let's see how I do this time. */
-
-/* (PWP) Well... Good for a simple line updater, but totally ignores
- the problems of input lines longer than the screen width.
-
- update_line and the code that calls it makes a multiple line,
- automatically wrapping line update. Careful attention needs
- to be paid to the vertical position variables. */
-
-/* Keep two buffers; one which reflects the current contents of the
- screen, and the other to draw what we think the new contents should
- be. Then compare the buffers, and make whatever changes to the
- screen itself that we should. Finally, make the buffer that we
- just drew into be the one which reflects the current contents of the
- screen, and place the cursor where it belongs.
-
- Commands that want to can fix the display themselves, and then let
- this function know that the display has been fixed by setting the
- RL_DISPLAY_FIXED variable. This is good for efficiency. */
-
-/* Application-specific redisplay function. */
-rl_voidfunc_t *rl_redisplay_function = rl_redisplay;
-
-/* Global variables declared here. */
-/* What YOU turn on when you have handled all redisplay yourself. */
-int rl_display_fixed = 0;
-
-int _rl_suppress_redisplay = 0;
-int _rl_want_redisplay = 0;
-
-/* The stuff that gets printed out before the actual text of the line.
- This is usually pointing to rl_prompt. */
-char *rl_display_prompt = (char *)NULL;
-
-/* Pseudo-global variables declared here. */
-
-/* The visible cursor position. If you print some text, adjust this. */
-/* NOTE: _rl_last_c_pos is used as a buffer index when not in a locale
- supporting multibyte characters, and an absolute cursor position when
- in such a locale. This is an artifact of the donated multibyte support.
- Care must be taken when modifying its value. */
-int _rl_last_c_pos = 0;
-int _rl_last_v_pos = 0;
-
-static int cpos_adjusted;
-static int cpos_buffer_position;
-
-/* Number of lines currently on screen minus 1. */
-int _rl_vis_botlin = 0;
-
-/* Variables used only in this file. */
-/* The last left edge of text that was displayed. This is used when
- doing horizontal scrolling. It shifts in thirds of a screenwidth. */
-static int last_lmargin;
-
-/* The line display buffers. One is the line currently displayed on
- the screen. The other is the line about to be displayed. */
-static char *visible_line = (char *)NULL;
-static char *invisible_line = (char *)NULL;
-
-/* A buffer for `modeline' messages. */
-static char msg_buf[128];
-
-/* Non-zero forces the redisplay even if we thought it was unnecessary. */
-static int forced_display;
-
-/* Default and initial buffer size. Can grow. */
-static int line_size = 1024;
-
-/* Variables to keep track of the expanded prompt string, which may
- include invisible characters. */
-
-static char *local_prompt, *local_prompt_prefix;
-static int local_prompt_len;
-static int prompt_visible_length, prompt_prefix_length;
-
-/* The number of invisible characters in the line currently being
- displayed on the screen. */
-static int visible_wrap_offset;
-
-/* The number of invisible characters in the prompt string. Static so it
- can be shared between rl_redisplay and update_line */
-static int wrap_offset;
-
-/* The index of the last invisible character in the prompt string. */
-static int prompt_last_invisible;
-
-/* The length (buffer offset) of the first line of the last (possibly
- multi-line) buffer displayed on the screen. */
-static int visible_first_line_len;
-
-/* Number of invisible characters on the first physical line of the prompt.
- Only valid when the number of physical characters in the prompt exceeds
- (or is equal to) _rl_screenwidth. */
-static int prompt_invis_chars_first_line;
-
-static int prompt_last_screen_line;
-
-static int prompt_physical_chars;
-
-/* Variables to save and restore prompt and display information. */
-
-/* These are getting numerous enough that it's time to create a struct. */
-
-static char *saved_local_prompt;
-static char *saved_local_prefix;
-static int saved_last_invisible;
-static int saved_visible_length;
-static int saved_prefix_length;
-static int saved_local_length;
-static int saved_invis_chars_first_line;
-static int saved_physical_chars;
-
-/* Expand the prompt string S and return the number of visible
- characters in *LP, if LP is not null. This is currently more-or-less
- a placeholder for expansion. LIP, if non-null is a place to store the
- index of the last invisible character in the returned string. NIFLP,
- if non-zero, is a place to store the number of invisible characters in
- the first prompt line. The previous are used as byte counts -- indexes
- into a character buffer. */
-
-/* Current implementation:
- \001 (^A) start non-visible characters
- \002 (^B) end non-visible characters
- all characters except \001 and \002 (following a \001) are copied to
- the returned string; all characters except those between \001 and
- \002 are assumed to be `visible'. */
-
-static char *
-expand_prompt (pmt, lp, lip, niflp, vlp)
- char *pmt;
- int *lp, *lip, *niflp, *vlp;
-{
- char *r, *ret, *p, *igstart;
- int l, rl, last, ignoring, ninvis, invfl, invflset, ind, pind, physchars;
-
- /* Short-circuit if we can. */
- if ((MB_CUR_MAX <= 1 || rl_byte_oriented) && strchr (pmt, RL_PROMPT_START_IGNORE) == 0)
- {
- r = savestring (pmt);
- if (lp)
- *lp = strlen (r);
- if (lip)
- *lip = 0;
- if (niflp)
- *niflp = 0;
- if (vlp)
- *vlp = lp ? *lp : strlen (r);
- return r;
- }
-
- l = strlen (pmt);
- r = ret = (char *)xmalloc (l + 1);
-
- 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 (ignoring == 0 && *p == RL_PROMPT_START_IGNORE) /* XXX - check ignoring? */
- {
- ignoring = 1;
- igstart = p;
- continue;
- }
- else if (ignoring && *p == RL_PROMPT_END_IGNORE)
- {
- ignoring = 0;
- if (p != (igstart + 1))
- last = r - ret - 1;
- continue;
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- pind = p - pmt;
- ind = _rl_find_next_mbchar (pmt, pind, 1, MB_FIND_NONZERO);
- l = ind - pind;
- while (l--)
- *r++ = *p++;
- if (!ignoring)
- {
- rl += ind - pind;
- physchars += _rl_col_width (pmt, pind, ind);
- }
- else
- ninvis += ind - pind;
- p--; /* compensate for later increment */
- }
- else
-#endif
- {
- *r++ = *p;
- if (!ignoring)
- {
- rl++; /* visible length byte counter */
- physchars++;
- }
- else
- ninvis++; /* invisible chars byte counter */
- }
-
- if (invflset == 0 && rl >= _rl_screenwidth)
- {
- invfl = ninvis;
- invflset = 1;
- }
- }
- }
-
- if (rl < _rl_screenwidth)
- invfl = ninvis;
-
- *r = '\0';
- if (lp)
- *lp = rl;
- if (lip)
- *lip = last;
- if (niflp)
- *niflp = invfl;
- if (vlp)
- *vlp = physchars;
- return ret;
-}
-
-/* Just strip out RL_PROMPT_START_IGNORE and RL_PROMPT_END_IGNORE from
- PMT and return the rest of PMT. */
-char *
-_rl_strip_prompt (pmt)
- char *pmt;
-{
- char *ret;
-
- ret = expand_prompt (pmt, (int *)NULL, (int *)NULL, (int *)NULL, (int *)NULL);
- return ret;
-}
-
-/*
- * Expand the prompt string into the various display components, if
- * necessary.
- *
- * local_prompt = expanded last line of string in rl_display_prompt
- * (portion after the final newline)
- * local_prompt_prefix = portion before last newline of rl_display_prompt,
- * expanded via expand_prompt
- * prompt_visible_length = number of visible characters in local_prompt
- * prompt_prefix_length = number of visible characters in local_prompt_prefix
- *
- * This function is called once per call to readline(). It may also be
- * called arbitrarily to expand the primary prompt.
- *
- * The return value is the number of visible characters on the last line
- * of the (possibly multi-line) prompt.
- */
-int
-rl_expand_prompt (prompt)
- char *prompt;
-{
- char *p, *t;
- int c;
-
- /* Clear out any saved values. */
- FREE (local_prompt);
- FREE (local_prompt_prefix);
-
- local_prompt = local_prompt_prefix = (char *)0;
- local_prompt_len = 0;
- prompt_last_invisible = prompt_invis_chars_first_line = 0;
- prompt_visible_length = prompt_physical_chars = 0;
-
- if (prompt == 0 || *prompt == 0)
- return (0);
-
- p = strrchr (prompt, '\n');
- if (!p)
- {
- /* The prompt is only one logical line, though it might wrap. */
- local_prompt = expand_prompt (prompt, &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
- local_prompt_prefix = (char *)0;
- local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
- return (prompt_visible_length);
- }
- else
- {
- /* The prompt spans multiple lines. */
- t = ++p;
- local_prompt = expand_prompt (p, &prompt_visible_length,
- &prompt_last_invisible,
- (int *)NULL,
- &prompt_physical_chars);
- c = *t; *t = '\0';
- /* The portion of the prompt string up to and including the
- final newline is now null-terminated. */
- local_prompt_prefix = expand_prompt (prompt, &prompt_prefix_length,
- (int *)NULL,
- &prompt_invis_chars_first_line,
- (int *)NULL);
- *t = c;
- local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
- return (prompt_prefix_length);
- }
-}
-
-/* Initialize the VISIBLE_LINE and INVISIBLE_LINE arrays, and their associated
- arrays of line break markers. MINSIZE is the minimum size of VISIBLE_LINE
- and INVISIBLE_LINE; if it is greater than LINE_SIZE, LINE_SIZE is
- increased. If the lines have already been allocated, this ensures that
- they can hold at least MINSIZE characters. */
-static void
-init_line_structures (minsize)
- int minsize;
-{
- register int n;
-
- if (invisible_line == 0) /* initialize it */
- {
- if (line_size < minsize)
- line_size = minsize;
- visible_line = (char *)xmalloc (line_size);
- invisible_line = (char *)xmalloc (line_size);
- }
- else if (line_size < minsize) /* ensure it can hold MINSIZE chars */
- {
- line_size *= 2;
- if (line_size < minsize)
- line_size = minsize;
- visible_line = (char *)xrealloc (visible_line, line_size);
- invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
-
- for (n = minsize; n < line_size; n++)
- {
- visible_line[n] = 0;
- invisible_line[n] = 1;
- }
-
- if (vis_lbreaks == 0)
- {
- /* should be enough. */
- inv_lbsize = vis_lbsize = 256;
- inv_lbreaks = (int *)xmalloc (inv_lbsize * sizeof (int));
- vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
-#if defined (HANDLE_MULTIBYTE)
- _rl_wrapped_line = (int *)xmalloc (vis_lbsize * sizeof (int));
-#endif
- inv_lbreaks[0] = vis_lbreaks[0] = 0;
- }
-}
-
-/* Basic redisplay algorithm. */
-void
-rl_redisplay ()
-{
- register int in, out, c, linenum, cursor_linenum;
- register char *line;
- int inv_botlin, lb_botlin, lb_linenum, o_cpos;
- int newlines, lpos, temp, modmark, n0, num;
- char *prompt_this_line;
-#if defined (HANDLE_MULTIBYTE)
- wchar_t wc;
- size_t wc_bytes;
- int wc_width;
- mbstate_t ps;
- int _rl_wrapped_multicolumn = 0;
-#endif
-
- if (!readline_echoing_p)
- return;
-
- if (!rl_display_prompt)
- rl_display_prompt = "";
-
- if (invisible_line == 0 || vis_lbreaks == 0)
- {
- init_line_structures (0);
- rl_on_new_line ();
- }
-
- /* Draw the line into the buffer. */
- cpos_buffer_position = -1;
-
- line = invisible_line;
- out = inv_botlin = 0;
-
- /* Mark the line as modified or not. We only do this for history
- lines. */
- modmark = 0;
- if (_rl_mark_modified_lines && current_history () && rl_undo_list)
- {
- line[out++] = '*';
- line[out] = '\0';
- modmark = 1;
- }
-
- /* If someone thought that the redisplay was handled, but the currently
- visible line has a different modification state than the one about
- to become visible, then correct the caller's misconception. */
- if (visible_line[0] != invisible_line[0])
- rl_display_fixed = 0;
-
- /* If the prompt to be displayed is the `primary' readline prompt (the
- one passed to readline()), use the values we have already expanded.
- If not, use what's already in rl_display_prompt. WRAP_OFFSET is the
- number of non-visible characters in the prompt string. */
- if (rl_display_prompt == rl_prompt || local_prompt)
- {
- if (local_prompt_prefix && forced_display)
- _rl_output_some_chars (local_prompt_prefix, strlen (local_prompt_prefix));
-
- if (local_prompt_len > 0)
- {
- temp = local_prompt_len + out + 2;
- if (temp >= line_size)
- {
- line_size = (temp + 1024) - (temp % 1024);
- visible_line = (char *)xrealloc (visible_line, line_size);
- line = invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
- strncpy (line + out, local_prompt, local_prompt_len);
- out += local_prompt_len;
- }
- line[out] = '\0';
- wrap_offset = local_prompt_len - prompt_visible_length;
- }
- else
- {
- int pmtlen;
- prompt_this_line = strrchr (rl_display_prompt, '\n');
- if (!prompt_this_line)
- prompt_this_line = rl_display_prompt;
- else
- {
- prompt_this_line++;
- pmtlen = prompt_this_line - rl_display_prompt; /* temp var */
- if (forced_display)
- {
- _rl_output_some_chars (rl_display_prompt, pmtlen);
- /* Make sure we are at column zero even after a newline,
- regardless of the state of terminal output processing. */
- if (pmtlen < 2 || prompt_this_line[-2] != '\r')
- cr ();
- }
- }
-
- prompt_physical_chars = pmtlen = strlen (prompt_this_line);
- temp = pmtlen + out + 2;
- if (temp >= line_size)
- {
- line_size = (temp + 1024) - (temp % 1024);
- visible_line = (char *)xrealloc (visible_line, line_size);
- line = invisible_line = (char *)xrealloc (invisible_line, line_size);
- }
- strncpy (line + out, prompt_this_line, pmtlen);
- out += pmtlen;
- line[out] = '\0';
- wrap_offset = prompt_invis_chars_first_line = 0;
- }
-
-#define CHECK_INV_LBREAKS() \
- do { \
- if (newlines >= (inv_lbsize - 2)) \
- { \
- inv_lbsize *= 2; \
- inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
- } \
- } while (0)
-
-#if defined (HANDLE_MULTIBYTE)
-#define CHECK_LPOS() \
- do { \
- lpos++; \
- if (lpos >= _rl_screenwidth) \
- { \
- if (newlines >= (inv_lbsize - 2)) \
- { \
- inv_lbsize *= 2; \
- inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
- _rl_wrapped_line = (int *)xrealloc (_rl_wrapped_line, inv_lbsize * sizeof (int)); \
- } \
- inv_lbreaks[++newlines] = out; \
- _rl_wrapped_line[newlines] = _rl_wrapped_multicolumn; \
- lpos = 0; \
- } \
- } while (0)
-#else
-#define CHECK_LPOS() \
- do { \
- lpos++; \
- if (lpos >= _rl_screenwidth) \
- { \
- if (newlines >= (inv_lbsize - 2)) \
- { \
- inv_lbsize *= 2; \
- inv_lbreaks = (int *)xrealloc (inv_lbreaks, inv_lbsize * sizeof (int)); \
- } \
- inv_lbreaks[++newlines] = out; \
- lpos = 0; \
- } \
- } while (0)
-#endif
-
- /* inv_lbreaks[i] is where line i starts in the buffer. */
- inv_lbreaks[newlines = 0] = 0;
-#if 0
- lpos = out - wrap_offset;
-#else
- lpos = prompt_physical_chars + modmark;
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
- memset (_rl_wrapped_line, 0, vis_lbsize);
- num = 0;
-#endif
-
- /* prompt_invis_chars_first_line is the number of invisible characters in
- the first physical line of the prompt.
- wrap_offset - prompt_invis_chars_first_line is the number of invis
- chars on the second line. */
-
- /* what if lpos is already >= _rl_screenwidth before we start drawing the
- contents of the command line? */
- while (lpos >= _rl_screenwidth)
- {
- /* fix from Darin Johnson <darin@acuson.com> for prompt string with
- invisible characters that is longer than the screen width. The
- prompt_invis_chars_first_line variable could be made into an array
- saying how many invisible characters there are per line, but that's
- probably too much work for the benefit gained. How many people have
- prompts that exceed two physical lines?
- Additional logic fix from Edward Catmur <ed@catmur.co.uk> */
-#if defined (HANDLE_MULTIBYTE)
- n0 = num;
- temp = local_prompt_len;
- while (num < temp)
- {
- if (_rl_col_width (local_prompt, n0, num) > _rl_screenwidth)
- {
- num = _rl_find_prev_mbchar (local_prompt, num, MB_FIND_ANY);
- break;
- }
- num++;
- }
- temp = num +
-#else
- temp = ((newlines + 1) * _rl_screenwidth) +
-#endif /* !HANDLE_MULTIBYTE */
- ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
- : ((newlines == 1) ? wrap_offset : 0))
- : ((newlines == 0) ? wrap_offset :0));
-
- inv_lbreaks[++newlines] = temp;
-#if defined (HANDLE_MULTIBYTE)
- lpos -= _rl_col_width (local_prompt, n0, num);
-#else
- lpos -= _rl_screenwidth;
-#endif
- }
-
- prompt_last_screen_line = newlines;
-
- /* Draw the rest of the line (after the prompt) into invisible_line, keeping
- track of where the cursor is (cpos_buffer_position), the number of the line containing
- the cursor (lb_linenum), the last line number (lb_botlin and inv_botlin).
- It maintains an array of line breaks for display (inv_lbreaks).
- This handles expanding tabs for display and displaying meta characters. */
- lb_linenum = 0;
-#if defined (HANDLE_MULTIBYTE)
- in = 0;
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- memset (&ps, 0, sizeof (mbstate_t));
- wc_bytes = mbrtowc (&wc, rl_line_buffer, rl_end, &ps);
- }
- else
- wc_bytes = 1;
- while (in < rl_end)
-#else
- for (in = 0; in < rl_end; in++)
-#endif
- {
- c = (unsigned char)rl_line_buffer[in];
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- if (MB_INVALIDCH (wc_bytes))
- {
- /* Byte sequence is invalid or shortened. Assume that the
- first byte represents a character. */
- wc_bytes = 1;
- /* Assume that a character occupies a single column. */
- wc_width = 1;
- memset (&ps, 0, sizeof (mbstate_t));
- }
- else if (MB_NULLWCH (wc_bytes))
- break; /* Found '\0' */
- else
- {
- temp = wcwidth (wc);
- wc_width = (temp >= 0) ? temp : 1;
- }
- }
-#endif
-
- if (out + 8 >= line_size) /* XXX - 8 for \t */
- {
- line_size *= 2;
- visible_line = (char *)xrealloc (visible_line, line_size);
- invisible_line = (char *)xrealloc (invisible_line, line_size);
- line = invisible_line;
- }
-
- if (in == rl_point)
- {
- cpos_buffer_position = out;
- lb_linenum = newlines;
- }
-
-#if defined (HANDLE_MULTIBYTE)
- if (META_CHAR (c) && _rl_output_meta_chars == 0) /* XXX - clean up */
-#else
- if (META_CHAR (c))
-#endif
- {
- if (_rl_output_meta_chars == 0)
- {
- sprintf (line + out, "\\%o", c);
-
- if (lpos + 4 >= _rl_screenwidth)
- {
- temp = _rl_screenwidth - lpos;
- CHECK_INV_LBREAKS ();
- inv_lbreaks[++newlines] = out + temp;
- lpos = 4 - temp;
- }
- else
- lpos += 4;
-
- out += 4;
- }
- else
- {
- line[out++] = c;
- CHECK_LPOS();
- }
- }
-#if defined (DISPLAY_TABS)
- else if (c == '\t')
- {
- register int newout;
-
-#if 0
- newout = (out | (int)7) + 1;
-#else
- newout = out + 8 - lpos % 8;
-#endif
- temp = newout - out;
- if (lpos + temp >= _rl_screenwidth)
- {
- register int temp2;
- temp2 = _rl_screenwidth - lpos;
- CHECK_INV_LBREAKS ();
- inv_lbreaks[++newlines] = out + temp2;
- lpos = temp - temp2;
- while (out < newout)
- line[out++] = ' ';
- }
- else
- {
- while (out < newout)
- line[out++] = ' ';
- lpos += temp;
- }
- }
-#endif
- else if (c == '\n' && _rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
- {
- line[out++] = '\0'; /* XXX - sentinel */
- CHECK_INV_LBREAKS ();
- inv_lbreaks[++newlines] = out;
- lpos = 0;
- }
- else if (CTRL_CHAR (c) || c == RUBOUT)
- {
- line[out++] = '^';
- CHECK_LPOS();
- line[out++] = CTRL_CHAR (c) ? UNCTRL (c) : '?';
- CHECK_LPOS();
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- register int i;
-
- _rl_wrapped_multicolumn = 0;
-
- if (_rl_screenwidth < lpos + wc_width)
- for (i = lpos; i < _rl_screenwidth; i++)
- {
- /* The space will be removed in update_line() */
- line[out++] = ' ';
- _rl_wrapped_multicolumn++;
- CHECK_LPOS();
- }
- if (in == rl_point)
- {
- cpos_buffer_position = out;
- lb_linenum = newlines;
- }
- for (i = in; i < in+wc_bytes; i++)
- line[out++] = rl_line_buffer[i];
- for (i = 0; i < wc_width; i++)
- CHECK_LPOS();
- }
- else
- {
- line[out++] = c;
- CHECK_LPOS();
- }
-#else
- line[out++] = c;
- CHECK_LPOS();
-#endif
- }
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- in += wc_bytes;
- wc_bytes = mbrtowc (&wc, rl_line_buffer + in, rl_end - in, &ps);
- }
- else
- in++;
-#endif
-
- }
- line[out] = '\0';
- if (cpos_buffer_position < 0)
- {
- cpos_buffer_position = out;
- lb_linenum = newlines;
- }
-
- inv_botlin = lb_botlin = newlines;
- CHECK_INV_LBREAKS ();
- inv_lbreaks[newlines+1] = out;
- cursor_linenum = lb_linenum;
-
- /* CPOS_BUFFER_POSITION == position in buffer where cursor should be placed.
- CURSOR_LINENUM == line number where the cursor should be placed. */
-
- /* PWP: now is when things get a bit hairy. The visible and invisible
- line buffers are really multiple lines, which would wrap every
- (screenwidth - 1) characters. Go through each in turn, finding
- the changed region and updating it. The line order is top to bottom. */
-
- /* If we can move the cursor up and down, then use multiple lines,
- otherwise, let long lines display in a single terminal line, and
- horizontally scroll it. */
-
- if (_rl_horizontal_scroll_mode == 0 && _rl_term_up && *_rl_term_up)
- {
- int nleft, pos, changed_screen_line, tx;
-
- if (!rl_display_fixed || forced_display)
- {
- forced_display = 0;
-
- /* If we have more than a screenful of material to display, then
- only display a screenful. We should display the last screen,
- not the first. */
- if (out >= _rl_screenchars)
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- out = _rl_find_prev_mbchar (line, _rl_screenchars, MB_FIND_ANY);
- else
- out = _rl_screenchars - 1;
- }
-
- /* The first line is at character position 0 in the buffer. The
- second and subsequent lines start at inv_lbreaks[N], offset by
- OFFSET (which has already been calculated above). */
-
-#define W_OFFSET(line, offset) ((line) == 0 ? offset : 0)
-#define VIS_LLEN(l) ((l) > _rl_vis_botlin ? 0 : (vis_lbreaks[l+1] - vis_lbreaks[l]))
-#define INV_LLEN(l) (inv_lbreaks[l+1] - inv_lbreaks[l])
-#define VIS_CHARS(line) (visible_line + vis_lbreaks[line])
-#define VIS_LINE(line) ((line) > _rl_vis_botlin) ? "" : VIS_CHARS(line)
-#define INV_LINE(line) (invisible_line + inv_lbreaks[line])
-
- /* For each line in the buffer, do the updating display. */
- for (linenum = 0; linenum <= inv_botlin; linenum++)
- {
- /* This can lead us astray if we execute a program that changes
- the locale from a non-multibyte to a multibyte one. */
- o_cpos = _rl_last_c_pos;
- cpos_adjusted = 0;
- update_line (VIS_LINE(linenum), INV_LINE(linenum), linenum,
- VIS_LLEN(linenum), INV_LLEN(linenum), inv_botlin);
-
- /* update_line potentially changes _rl_last_c_pos, but doesn't
- take invisible characters into account, since _rl_last_c_pos
- is an absolute cursor position in a multibyte locale. See
- if compensating here is the right thing, or if we have to
- change update_line itself. There is one case in which
- update_line adjusts _rl_last_c_pos itself (so it can pass
- _rl_move_cursor_relative accurate values); it communicates
- this back by setting cpos_adjusted. If we assume that
- _rl_last_c_pos is correct (an absolute cursor position) each
- time update_line is called, then we can assume in our
- calculations that o_cpos does not need to be adjusted by
- wrap_offset. */
- if (linenum == 0 && (MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
- cpos_adjusted == 0 &&
- _rl_last_c_pos != o_cpos &&
- _rl_last_c_pos > wrap_offset &&
- o_cpos < prompt_last_invisible)
- _rl_last_c_pos -= wrap_offset;
-
- /* If this is the line with the prompt, we might need to
- compensate for invisible characters in the new line. Do
- this only if there is not more than one new line (which
- implies that we completely overwrite the old visible line)
- and the new line is shorter than the old. Make sure we are
- at the end of the new line before clearing. */
- if (linenum == 0 &&
- inv_botlin == 0 && _rl_last_c_pos == out &&
- (wrap_offset > visible_wrap_offset) &&
- (_rl_last_c_pos < visible_first_line_len))
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- nleft = _rl_screenwidth - _rl_last_c_pos;
- else
- nleft = _rl_screenwidth + wrap_offset - _rl_last_c_pos;
- if (nleft)
- _rl_clear_to_eol (nleft);
- }
-
- /* Since the new first line is now visible, save its length. */
- if (linenum == 0)
- visible_first_line_len = (inv_botlin > 0) ? inv_lbreaks[1] : out - wrap_offset;
- }
-
- /* We may have deleted some lines. If so, clear the left over
- blank ones at the bottom out. */
- if (_rl_vis_botlin > inv_botlin)
- {
- char *tt;
- for (; linenum <= _rl_vis_botlin; linenum++)
- {
- tt = VIS_CHARS (linenum);
- _rl_move_vert (linenum);
- _rl_move_cursor_relative (0, tt);
- _rl_clear_to_eol
- ((linenum == _rl_vis_botlin) ? strlen (tt) : _rl_screenwidth);
- }
- }
- _rl_vis_botlin = inv_botlin;
-
- /* CHANGED_SCREEN_LINE is set to 1 if we have moved to a
- different screen line during this redisplay. */
- changed_screen_line = _rl_last_v_pos != cursor_linenum;
- if (changed_screen_line)
- {
- _rl_move_vert (cursor_linenum);
- /* If we moved up to the line with the prompt using _rl_term_up,
- the physical cursor position on the screen stays the same,
- but the buffer position needs to be adjusted to account
- for invisible characters. */
- if ((MB_CUR_MAX == 1 || rl_byte_oriented) && cursor_linenum == 0 && wrap_offset)
- _rl_last_c_pos += wrap_offset;
- }
-
- /* We have to reprint the prompt if it contains invisible
- characters, since it's not generally OK to just reprint
- the characters from the current cursor position. But we
- only need to reprint it if the cursor is before the last
- invisible character in the prompt string. */
- nleft = prompt_visible_length + wrap_offset;
- if (cursor_linenum == 0 && wrap_offset > 0 && _rl_last_c_pos > 0 &&
-#if 0
- _rl_last_c_pos <= PROMPT_ENDING_INDEX && local_prompt)
-#else
- _rl_last_c_pos < PROMPT_ENDING_INDEX && local_prompt)
-#endif
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- if (_rl_term_cr)
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_output_some_chars (local_prompt, nleft);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- _rl_last_c_pos = _rl_col_width (local_prompt, 0, nleft) - wrap_offset;
- else
- _rl_last_c_pos = nleft;
- }
-
- /* Where on that line? And where does that line start
- in the buffer? */
- pos = inv_lbreaks[cursor_linenum];
- /* nleft == number of characters in the line buffer between the
- start of the line and the desired cursor position. */
- nleft = cpos_buffer_position - pos;
-
- /* NLEFT is now a number of characters in a buffer. When in a
- multibyte locale, however, _rl_last_c_pos is an absolute cursor
- position that doesn't take invisible characters in the prompt
- into account. We use a fudge factor to compensate. */
-
- /* Since _rl_backspace() doesn't know about invisible characters in the
- prompt, and there's no good way to tell it, we compensate for
- those characters here and call _rl_backspace() directly. */
- if (wrap_offset && cursor_linenum == 0 && nleft < _rl_last_c_pos)
- {
- /* TX == new physical cursor position in multibyte locale. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- tx = _rl_col_width (&visible_line[pos], 0, nleft) - visible_wrap_offset;
- else
- tx = nleft;
- if (_rl_last_c_pos > tx)
- {
- _rl_backspace (_rl_last_c_pos - tx); /* XXX */
- _rl_last_c_pos = tx;
- }
- }
-
- /* We need to note that in a multibyte locale we are dealing with
- _rl_last_c_pos as an absolute cursor position, but moving to a
- point specified by a buffer position (NLEFT) that doesn't take
- invisible characters into account. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- _rl_move_cursor_relative (nleft, &invisible_line[pos]);
- else if (nleft != _rl_last_c_pos)
- _rl_move_cursor_relative (nleft, &invisible_line[pos]);
- }
- }
- else /* Do horizontal scrolling. */
- {
-#define M_OFFSET(margin, offset) ((margin) == 0 ? offset : 0)
- int lmargin, ndisp, nleft, phys_c_pos, t;
-
- /* Always at top line. */
- _rl_last_v_pos = 0;
-
- /* Compute where in the buffer the displayed line should start. This
- will be LMARGIN. */
-
- /* The number of characters that will be displayed before the cursor. */
- ndisp = cpos_buffer_position - wrap_offset;
- nleft = prompt_visible_length + wrap_offset;
- /* Where the new cursor position will be on the screen. This can be
- longer than SCREENWIDTH; if it is, lmargin will be adjusted. */
- phys_c_pos = cpos_buffer_position - (last_lmargin ? last_lmargin : wrap_offset);
- t = _rl_screenwidth / 3;
-
- /* If the number of characters had already exceeded the screenwidth,
- last_lmargin will be > 0. */
-
- /* If the number of characters to be displayed is more than the screen
- width, compute the starting offset so that the cursor is about
- two-thirds of the way across the screen. */
- if (phys_c_pos > _rl_screenwidth - 2)
- {
- lmargin = cpos_buffer_position - (2 * t);
- if (lmargin < 0)
- lmargin = 0;
- /* If the left margin would be in the middle of a prompt with
- invisible characters, don't display the prompt at all. */
- if (wrap_offset && lmargin > 0 && lmargin < nleft)
- lmargin = nleft;
- }
- else if (ndisp < _rl_screenwidth - 2) /* XXX - was -1 */
- lmargin = 0;
- else if (phys_c_pos < 1)
- {
- /* If we are moving back towards the beginning of the line and
- the last margin is no longer correct, compute a new one. */
- lmargin = ((cpos_buffer_position - 1) / t) * t; /* XXX */
- if (wrap_offset && lmargin > 0 && lmargin < nleft)
- lmargin = nleft;
- }
- else
- lmargin = last_lmargin;
-
- /* If the first character on the screen isn't the first character
- in the display line, indicate this with a special character. */
- if (lmargin > 0)
- line[lmargin] = '<';
-
- /* If SCREENWIDTH characters starting at LMARGIN do not encompass
- the whole line, indicate that with a special character at the
- right edge of the screen. If LMARGIN is 0, we need to take the
- wrap offset into account. */
- t = lmargin + M_OFFSET (lmargin, wrap_offset) + _rl_screenwidth;
- if (t < out)
- line[t - 1] = '>';
-
- if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
- {
- forced_display = 0;
- update_line (&visible_line[last_lmargin],
- &invisible_line[lmargin],
- 0,
- _rl_screenwidth + visible_wrap_offset,
- _rl_screenwidth + (lmargin ? 0 : wrap_offset),
- 0);
-
- /* If the visible new line is shorter than the old, but the number
- of invisible characters is greater, and we are at the end of
- the new line, we need to clear to eol. */
- t = _rl_last_c_pos - M_OFFSET (lmargin, wrap_offset);
- if ((M_OFFSET (lmargin, wrap_offset) > visible_wrap_offset) &&
- (_rl_last_c_pos == out) &&
- t < visible_first_line_len)
- {
- nleft = _rl_screenwidth - t;
- _rl_clear_to_eol (nleft);
- }
- visible_first_line_len = out - lmargin - M_OFFSET (lmargin, wrap_offset);
- if (visible_first_line_len > _rl_screenwidth)
- visible_first_line_len = _rl_screenwidth;
-
- _rl_move_cursor_relative (cpos_buffer_position - lmargin, &invisible_line[lmargin]);
- last_lmargin = lmargin;
- }
- }
- fflush (rl_outstream);
-
- /* Swap visible and non-visible lines. */
- {
- char *vtemp = visible_line;
- int *itemp = vis_lbreaks, ntemp = vis_lbsize;
-
- visible_line = invisible_line;
- invisible_line = vtemp;
-
- vis_lbreaks = inv_lbreaks;
- inv_lbreaks = itemp;
-
- vis_lbsize = inv_lbsize;
- inv_lbsize = ntemp;
-
- rl_display_fixed = 0;
- /* If we are displaying on a single line, and last_lmargin is > 0, we
- are not displaying any invisible characters, so set visible_wrap_offset
- to 0. */
- if (_rl_horizontal_scroll_mode && last_lmargin)
- visible_wrap_offset = 0;
- else
- visible_wrap_offset = wrap_offset;
- }
-}
-
-/* PWP: update_line() is based on finding the middle difference of each
- line on the screen; vis:
-
- /old first difference
- /beginning of line | /old last same /old EOL
- v v v v
-old: eddie> Oh, my little gruntle-buggy is to me, as lurgid as
-new: eddie> Oh, my little buggy says to me, as lurgid as
- ^ ^ ^ ^
- \beginning of line | \new last same \new end of line
- \new first difference
-
- All are character pointers for the sake of speed. Special cases for
- no differences, as well as for end of line additions must be handled.
-
- Could be made even smarter, but this works well enough */
-static void
-update_line (old, new, current_line, omax, nmax, inv_botlin)
- register char *old, *new;
- int current_line, omax, nmax, inv_botlin;
-{
- register char *ofd, *ols, *oe, *nfd, *nls, *ne;
- int temp, lendiff, wsatend, od, nd;
- int current_invis_chars;
- int col_lendiff, col_temp;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps_new, ps_old;
- int new_offset, old_offset;
-#endif
-
- /* If we're at the right edge of a terminal that supports xn, we're
- ready to wrap around, so do so. This fixes problems with knowing
- the exact cursor position and cut-and-paste with certain terminal
- emulators. In this calculation, TEMP is the physical screen
- position of the cursor. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- temp = _rl_last_c_pos;
- else
- temp = _rl_last_c_pos - W_OFFSET(_rl_last_v_pos, visible_wrap_offset);
- if (temp == _rl_screenwidth && _rl_term_autowrap && !_rl_horizontal_scroll_mode
- && _rl_last_v_pos == current_line - 1)
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- wchar_t wc;
- mbstate_t ps;
- int tempwidth, bytes;
- size_t ret;
-
- /* This fixes only double-column characters, but if the wrapped
- character comsumes more than three columns, spaces will be
- inserted in the string buffer. */
- if (_rl_wrapped_line[current_line] > 0)
- _rl_clear_to_eol (_rl_wrapped_line[current_line]);
-
- memset (&ps, 0, sizeof (mbstate_t));
- ret = mbrtowc (&wc, new, MB_CUR_MAX, &ps);
- if (MB_INVALIDCH (ret))
- {
- tempwidth = 1;
- ret = 1;
- }
- else if (MB_NULLWCH (ret))
- tempwidth = 0;
- else
- tempwidth = wcwidth (wc);
-
- if (tempwidth > 0)
- {
- int count;
- bytes = ret;
- for (count = 0; count < bytes; count++)
- putc (new[count], rl_outstream);
- _rl_last_c_pos = tempwidth;
- _rl_last_v_pos++;
- memset (&ps, 0, sizeof (mbstate_t));
- ret = mbrtowc (&wc, old, MB_CUR_MAX, &ps);
- if (ret != 0 && bytes != 0)
- {
- if (MB_INVALIDCH (ret))
- memmove (old+bytes, old+1, strlen (old+1));
- else
- memmove (old+bytes, old+ret, strlen (old+ret));
- memcpy (old, new, bytes);
- }
- }
- else
- {
- putc (' ', rl_outstream);
- _rl_last_c_pos = 1;
- _rl_last_v_pos++;
- if (old[0] && new[0])
- old[0] = new[0];
- }
- }
- else
-#endif
- {
- if (new[0])
- putc (new[0], rl_outstream);
- else
- putc (' ', rl_outstream);
- _rl_last_c_pos = 1;
- _rl_last_v_pos++;
- if (old[0] && new[0])
- old[0] = new[0];
- }
- }
-
-
- /* Find first difference. */
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- /* See if the old line is a subset of the new line, so that the
- only change is adding characters. */
- temp = (omax < nmax) ? omax : nmax;
- if (memcmp (old, new, temp) == 0)
- {
- ofd = old + temp;
- nfd = new + temp;
- }
- else
- {
- memset (&ps_new, 0, sizeof(mbstate_t));
- memset (&ps_old, 0, sizeof(mbstate_t));
-
- if (omax == nmax && STREQN (new, old, omax))
- {
- ofd = old + omax;
- nfd = new + nmax;
- }
- else
- {
- new_offset = old_offset = 0;
- for (ofd = old, nfd = new;
- (ofd - old < omax) && *ofd &&
- _rl_compare_chars(old, old_offset, &ps_old, new, new_offset, &ps_new); )
- {
- old_offset = _rl_find_next_mbchar (old, old_offset, 1, MB_FIND_ANY);
- new_offset = _rl_find_next_mbchar (new, new_offset, 1, MB_FIND_ANY);
- ofd = old + old_offset;
- nfd = new + new_offset;
- }
- }
- }
- }
- else
-#endif
- for (ofd = old, nfd = new;
- (ofd - old < omax) && *ofd && (*ofd == *nfd);
- ofd++, nfd++)
- ;
-
- /* Move to the end of the screen line. ND and OD are used to keep track
- of the distance between ne and new and oe and old, respectively, to
- move a subtraction out of each loop. */
- for (od = ofd - old, oe = ofd; od < omax && *oe; oe++, od++);
- for (nd = nfd - new, ne = nfd; nd < nmax && *ne; ne++, nd++);
-
- /* If no difference, continue to next line. */
- if (ofd == oe && nfd == ne)
- return;
-
- wsatend = 1; /* flag for trailing whitespace */
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- ols = old + _rl_find_prev_mbchar (old, oe - old, MB_FIND_ANY);
- nls = new + _rl_find_prev_mbchar (new, ne - new, MB_FIND_ANY);
- while ((ols > ofd) && (nls > nfd))
- {
- memset (&ps_old, 0, sizeof (mbstate_t));
- memset (&ps_new, 0, sizeof (mbstate_t));
-
-#if 0
- /* On advice from jir@yamato.ibm.com */
- _rl_adjust_point (old, ols - old, &ps_old);
- _rl_adjust_point (new, nls - new, &ps_new);
-#endif
-
- if (_rl_compare_chars (old, ols - old, &ps_old, new, nls - new, &ps_new) == 0)
- break;
-
- if (*ols == ' ')
- wsatend = 0;
-
- ols = old + _rl_find_prev_mbchar (old, ols - old, MB_FIND_ANY);
- nls = new + _rl_find_prev_mbchar (new, nls - new, MB_FIND_ANY);
- }
- }
- else
- {
-#endif /* HANDLE_MULTIBYTE */
- ols = oe - 1; /* find last same */
- nls = ne - 1;
- while ((ols > ofd) && (nls > nfd) && (*ols == *nls))
- {
- if (*ols != ' ')
- wsatend = 0;
- ols--;
- nls--;
- }
-#if defined (HANDLE_MULTIBYTE)
- }
-#endif
-
- if (wsatend)
- {
- ols = oe;
- nls = ne;
- }
-#if defined (HANDLE_MULTIBYTE)
- /* This may not work for stateful encoding, but who cares? To handle
- stateful encoding properly, we have to scan each string from the
- beginning and compare. */
- else if (_rl_compare_chars (ols, 0, NULL, nls, 0, NULL) == 0)
-#else
- else if (*ols != *nls)
-#endif
- {
- if (*ols) /* don't step past the NUL */
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- ols = old + _rl_find_next_mbchar (old, ols - old, 1, MB_FIND_ANY);
- else
- ols++;
- }
- if (*nls)
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- nls = new + _rl_find_next_mbchar (new, nls - new, 1, MB_FIND_ANY);
- else
- nls++;
- }
- }
-
- /* count of invisible characters in the current invisible line. */
- current_invis_chars = W_OFFSET (current_line, wrap_offset);
- if (_rl_last_v_pos != current_line)
- {
- _rl_move_vert (current_line);
- if ((MB_CUR_MAX == 1 || rl_byte_oriented) && current_line == 0 && visible_wrap_offset)
- _rl_last_c_pos += visible_wrap_offset;
- }
-
- /* If this is the first line and there are invisible characters in the
- prompt string, and the prompt string has not changed, and the current
- cursor position is before the last invisible character in the prompt,
- and the index of the character to move to is past the end of the prompt
- string, then redraw the entire prompt string. We can only do this
- reliably if the terminal supports a `cr' capability.
-
- This is not an efficiency hack -- there is a problem with redrawing
- portions of the prompt string if they contain terminal escape
- sequences (like drawing the `unbold' sequence without a corresponding
- `bold') that manifests itself on certain terminals. */
-
- lendiff = local_prompt_len;
- od = ofd - old; /* index of first difference in visible line */
- if (current_line == 0 && !_rl_horizontal_scroll_mode &&
- _rl_term_cr && lendiff > prompt_visible_length && _rl_last_c_pos > 0 &&
- od >= lendiff && _rl_last_c_pos < PROMPT_ENDING_INDEX)
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_output_some_chars (local_prompt, lendiff);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- /* We take wrap_offset into account here so we can pass correct
- information to _rl_move_cursor_relative. */
- _rl_last_c_pos = _rl_col_width (local_prompt, 0, lendiff) - wrap_offset;
- cpos_adjusted = 1;
- }
- else
- _rl_last_c_pos = lendiff;
- }
-
- /* When this function returns, _rl_last_c_pos is correct, and an absolute
- cursor postion in multibyte mode, but a buffer index when not in a
- multibyte locale. */
- _rl_move_cursor_relative (od, old);
-#if 1
-#if defined (HANDLE_MULTIBYTE)
- /* We need to indicate that the cursor position is correct in the presence of
- invisible characters in the prompt string. Let's see if setting this when
- we make sure we're at the end of the drawn prompt string works. */
- if (current_line == 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0 && _rl_last_c_pos == prompt_physical_chars)
- cpos_adjusted = 1;
-#endif
-#endif
-
- /* if (len (new) > len (old))
- lendiff == difference in buffer
- col_lendiff == difference on screen
- When not using multibyte characters, these are equal */
- lendiff = (nls - nfd) - (ols - ofd);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- col_lendiff = _rl_col_width (new, nfd - new, nls - new) - _rl_col_width (old, ofd - old, ols - old);
- else
- col_lendiff = lendiff;
-
- /* If we are changing the number of invisible characters in a line, and
- the spot of first difference is before the end of the invisible chars,
- lendiff needs to be adjusted. */
- if (current_line == 0 && !_rl_horizontal_scroll_mode &&
- current_invis_chars != visible_wrap_offset)
- {
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- lendiff += visible_wrap_offset - current_invis_chars;
- col_lendiff += visible_wrap_offset - current_invis_chars;
- }
- else
- {
- lendiff += visible_wrap_offset - current_invis_chars;
- col_lendiff = lendiff;
- }
- }
-
- /* Insert (diff (len (old), len (new)) ch. */
- temp = ne - nfd;
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- col_temp = _rl_col_width (new, nfd - new, ne - new);
- else
- col_temp = temp;
-
- if (col_lendiff > 0) /* XXX - was lendiff */
- {
- /* Non-zero if we're increasing the number of lines. */
- int gl = current_line >= _rl_vis_botlin && inv_botlin > _rl_vis_botlin;
- /* Sometimes it is cheaper to print the characters rather than
- use the terminal's capabilities. If we're growing the number
- of lines, make sure we actually cause the new line to wrap
- around on auto-wrapping terminals. */
- if (_rl_terminal_can_insert && ((2 * col_temp) >= col_lendiff || _rl_term_IC) && (!_rl_term_autowrap || !gl))
- {
- /* If lendiff > prompt_visible_length and _rl_last_c_pos == 0 and
- _rl_horizontal_scroll_mode == 1, inserting the characters with
- _rl_term_IC or _rl_term_ic will screw up the screen because of the
- invisible characters. We need to just draw them. */
- if (*ols && (!_rl_horizontal_scroll_mode || _rl_last_c_pos > 0 ||
- lendiff <= prompt_visible_length || !current_invis_chars))
- {
- insert_some_chars (nfd, lendiff, col_lendiff);
- _rl_last_c_pos += col_lendiff;
- }
- else if ((MB_CUR_MAX == 1 || rl_byte_oriented != 0) && *ols == 0 && lendiff > 0)
- {
- /* At the end of a line the characters do not have to
- be "inserted". They can just be placed on the screen. */
- /* However, this screws up the rest of this block, which
- assumes you've done the insert because you can. */
- _rl_output_some_chars (nfd, lendiff);
- _rl_last_c_pos += col_lendiff;
- }
- else
- {
- /* We have horizontal scrolling and we are not inserting at
- the end. We have invisible characters in this line. This
- is a dumb update. */
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += col_temp;
- return;
- }
- /* Copy (new) chars to screen from first diff to last match. */
- temp = nls - nfd;
- if ((temp - lendiff) > 0)
- {
- _rl_output_some_chars (nfd + lendiff, temp - lendiff);
-#if 1
- /* XXX -- this bears closer inspection. Fixes a redisplay bug
- reported against bash-3.0-alpha by Andreas Schwab involving
- multibyte characters and prompt strings with invisible
- characters, but was previously disabled. */
- _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-col_lendiff);
-#else
- _rl_last_c_pos += _rl_col_width (nfd+lendiff, 0, temp-lendiff);
-#endif
- }
- }
- else
- {
- /* cannot insert chars, write to EOL */
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += col_temp;
- /* If we're in a multibyte locale and were before the last invisible
- char in the current line (which implies we just output some invisible
- characters) we need to adjust _rl_last_c_pos, since it represents
- a physical character position. */
- }
- }
- else /* Delete characters from line. */
- {
- /* If possible and inexpensive to use terminal deletion, then do so. */
- if (_rl_term_dc && (2 * col_temp) >= -col_lendiff)
- {
- /* If all we're doing is erasing the invisible characters in the
- prompt string, don't bother. It screws up the assumptions
- about what's on the screen. */
- if (_rl_horizontal_scroll_mode && _rl_last_c_pos == 0 &&
- -lendiff == visible_wrap_offset)
- col_lendiff = 0;
-
- if (col_lendiff)
- delete_chars (-col_lendiff); /* delete (diff) characters */
-
- /* Copy (new) chars to screen from first diff to last match */
- temp = nls - nfd;
- if (temp > 0)
- {
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += _rl_col_width (nfd, 0, temp);;
- }
- }
- /* Otherwise, print over the existing material. */
- else
- {
- if (temp > 0)
- {
- _rl_output_some_chars (nfd, temp);
- _rl_last_c_pos += col_temp; /* XXX */
- }
- lendiff = (oe - old) - (ne - new);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- col_lendiff = _rl_col_width (old, 0, oe - old) - _rl_col_width (new, 0, ne - new);
- else
- col_lendiff = lendiff;
-
- if (col_lendiff)
- {
- if (_rl_term_autowrap && current_line < inv_botlin)
- space_to_eol (col_lendiff);
- else
- _rl_clear_to_eol (col_lendiff);
- }
- }
- }
-}
-
-/* Tell the update routines that we have moved onto a new (empty) line. */
-int
-rl_on_new_line ()
-{
- if (visible_line)
- visible_line[0] = '\0';
-
- _rl_last_c_pos = _rl_last_v_pos = 0;
- _rl_vis_botlin = last_lmargin = 0;
- if (vis_lbreaks)
- vis_lbreaks[0] = vis_lbreaks[1] = 0;
- visible_wrap_offset = 0;
- return 0;
-}
-
-/* Tell the update routines that we have moved onto a new line with the
- prompt already displayed. Code originally from the version of readline
- distributed with CLISP. rl_expand_prompt must have already been called
- (explicitly or implicitly). This still doesn't work exactly right. */
-int
-rl_on_new_line_with_prompt ()
-{
- int prompt_size, i, l, real_screenwidth, newlines;
- char *prompt_last_line, *lprompt;
-
- /* Initialize visible_line and invisible_line to ensure that they can hold
- the already-displayed prompt. */
- prompt_size = strlen (rl_prompt) + 1;
- init_line_structures (prompt_size);
-
- /* Make sure the line structures hold the already-displayed prompt for
- redisplay. */
- lprompt = local_prompt ? local_prompt : rl_prompt;
- strcpy (visible_line, lprompt);
- strcpy (invisible_line, lprompt);
-
- /* If the prompt contains newlines, take the last tail. */
- prompt_last_line = strrchr (rl_prompt, '\n');
- if (!prompt_last_line)
- prompt_last_line = rl_prompt;
-
- l = strlen (prompt_last_line);
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- _rl_last_c_pos = _rl_col_width (prompt_last_line, 0, l); /* XXX */
- else
- _rl_last_c_pos = l;
-
- /* Dissect prompt_last_line into screen lines. Note that here we have
- to use the real screenwidth. Readline's notion of screenwidth might be
- one less, see terminal.c. */
- real_screenwidth = _rl_screenwidth + (_rl_term_autowrap ? 0 : 1);
- _rl_last_v_pos = l / real_screenwidth;
- /* If the prompt length is a multiple of real_screenwidth, we don't know
- whether the cursor is at the end of the last line, or already at the
- beginning of the next line. Output a newline just to be safe. */
- if (l > 0 && (l % real_screenwidth) == 0)
- _rl_output_some_chars ("\n", 1);
- last_lmargin = 0;
-
- newlines = 0; i = 0;
- while (i <= l)
- {
- _rl_vis_botlin = newlines;
- vis_lbreaks[newlines++] = i;
- i += real_screenwidth;
- }
- vis_lbreaks[newlines] = l;
- visible_wrap_offset = 0;
-
- rl_display_prompt = rl_prompt; /* XXX - make sure it's set */
-
- return 0;
-}
-
-/* Actually update the display, period. */
-int
-rl_forced_update_display ()
-{
- register char *temp;
-
- if (visible_line)
- {
- temp = visible_line;
- while (*temp)
- *temp++ = '\0';
- }
- rl_on_new_line ();
- forced_display++;
- (*rl_redisplay_function) ();
- return 0;
-}
-
-/* Move the cursor from _rl_last_c_pos to NEW, which are buffer indices.
- (Well, when we don't have multibyte characters, _rl_last_c_pos is a
- buffer index.)
- DATA is the contents of the screen line of interest; i.e., where
- the movement is being done. */
-void
-_rl_move_cursor_relative (new, data)
- int new;
- const char *data;
-{
- register int i;
- int woff; /* number of invisible chars on current line */
- int cpos, dpos; /* current and desired cursor positions */
-
- woff = W_OFFSET (_rl_last_v_pos, wrap_offset);
- cpos = _rl_last_c_pos;
-#if defined (HANDLE_MULTIBYTE)
- /* If we have multibyte characters, NEW is indexed by the buffer point in
- a multibyte string, but _rl_last_c_pos is the display position. In
- this case, NEW's display position is not obvious and must be
- calculated. We need to account for invisible characters in this line,
- as long as we are past them and they are counted by _rl_col_width. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- dpos = _rl_col_width (data, 0, new);
- if (dpos > prompt_last_invisible) /* XXX - don't use woff here */
- {
- dpos -= woff;
- /* Since this will be assigned to _rl_last_c_pos at the end (more
- precisely, _rl_last_c_pos == dpos when this function returns),
- let the caller know. */
- cpos_adjusted = 1;
- }
- }
- else
-#endif
- dpos = new;
-
- /* If we don't have to do anything, then return. */
- if (cpos == dpos)
- return;
-
- /* It may be faster to output a CR, and then move forwards instead
- of moving backwards. */
- /* i == current physical cursor position. */
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- i = _rl_last_c_pos;
- else
-#endif
- i = _rl_last_c_pos - woff;
- if (dpos == 0 || CR_FASTER (dpos, _rl_last_c_pos) ||
- (_rl_term_autowrap && i == _rl_screenwidth))
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif /* !__MSDOS__ */
- cpos = _rl_last_c_pos = 0;
- }
-
- if (cpos < dpos)
- {
- /* Move the cursor forward. We do it by printing the command
- to move the cursor forward if there is one, else print that
- portion of the output buffer again. Which is cheaper? */
-
- /* The above comment is left here for posterity. It is faster
- to print one character (non-control) than to print a control
- sequence telling the terminal to move forward one character.
- That kind of control is for people who don't know what the
- data is underneath the cursor. */
-
- /* However, we need a handle on where the current display position is
- in the buffer for the immediately preceding comment to be true.
- In multibyte locales, we don't currently have that info available.
- Without it, we don't know where the data we have to display begins
- in the buffer and we have to go back to the beginning of the screen
- line. In this case, we can use the terminal sequence to move forward
- if it's available. */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- if (_rl_term_forward_char)
- {
- for (i = cpos; i < dpos; i++)
- tputs (_rl_term_forward_char, 1, _rl_output_character_function);
- }
- else
- {
- tputs (_rl_term_cr, 1, _rl_output_character_function);
- for (i = 0; i < new; i++)
- putc (data[i], rl_outstream);
- }
- }
- else
- for (i = cpos; i < new; i++)
- putc (data[i], rl_outstream);
- }
-
-#if defined (HANDLE_MULTIBYTE)
- /* NEW points to the buffer point, but _rl_last_c_pos is the display point.
- The byte length of the string is probably bigger than the column width
- of the string, which means that if NEW == _rl_last_c_pos, then NEW's
- display point is less than _rl_last_c_pos. */
-#endif
- else if (cpos > dpos)
- _rl_backspace (cpos - dpos);
-
- _rl_last_c_pos = dpos;
-}
-
-/* PWP: move the cursor up or down. */
-void
-_rl_move_vert (to)
- int to;
-{
- register int delta, i;
-
- if (_rl_last_v_pos == to || to > _rl_screenheight)
- return;
-
- if ((delta = to - _rl_last_v_pos) > 0)
- {
- for (i = 0; i < delta; i++)
- putc ('\n', rl_outstream);
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_last_c_pos = 0;
- }
- else
- { /* delta < 0 */
- if (_rl_term_up && *_rl_term_up)
- for (i = 0; i < -delta; i++)
- tputs (_rl_term_up, 1, _rl_output_character_function);
- }
-
- _rl_last_v_pos = to; /* Now TO is here */
-}
-
-/* Physically print C on rl_outstream. This is for functions which know
- how to optimize the display. Return the number of characters output. */
-int
-rl_show_char (c)
- int c;
-{
- int n = 1;
- if (META_CHAR (c) && (_rl_output_meta_chars == 0))
- {
- fprintf (rl_outstream, "M-");
- n += 2;
- c = UNMETA (c);
- }
-
-#if defined (DISPLAY_TABS)
- if ((CTRL_CHAR (c) && c != '\t') || c == RUBOUT)
-#else
- if (CTRL_CHAR (c) || c == RUBOUT)
-#endif /* !DISPLAY_TABS */
- {
- fprintf (rl_outstream, "C-");
- n += 2;
- c = CTRL_CHAR (c) ? UNCTRL (c) : '?';
- }
-
- putc (c, rl_outstream);
- fflush (rl_outstream);
- return n;
-}
-
-int
-rl_character_len (c, pos)
- register int c, pos;
-{
- unsigned char uc;
-
- uc = (unsigned char)c;
-
- if (META_CHAR (uc))
- return ((_rl_output_meta_chars == 0) ? 4 : 1);
-
- if (uc == '\t')
- {
-#if defined (DISPLAY_TABS)
- return (((pos | 7) + 1) - pos);
-#else
- return (2);
-#endif /* !DISPLAY_TABS */
- }
-
- if (CTRL_CHAR (c) || c == RUBOUT)
- return (2);
-
- return ((ISPRINT (uc)) ? 1 : 2);
-}
-/* How to print things in the "echo-area". The prompt is treated as a
- mini-modeline. */
-static int msg_saved_prompt = 0;
-
-#if defined (USE_VARARGS)
-int
-#if defined (PREFER_STDARG)
-rl_message (const char *format, ...)
-#else
-rl_message (va_alist)
- va_dcl
-#endif
-{
- va_list args;
-#if defined (PREFER_VARARGS)
- char *format;
-#endif
-
-#if defined (PREFER_STDARG)
- va_start (args, format);
-#else
- va_start (args);
- format = va_arg (args, char *);
-#endif
-
-#if defined (HAVE_VSNPRINTF)
- vsnprintf (msg_buf, sizeof (msg_buf) - 1, format, args);
-#else
- vsprintf (msg_buf, format, args);
- msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
-#endif
- va_end (args);
-
- if (saved_local_prompt == 0)
- {
- rl_save_prompt ();
- msg_saved_prompt = 1;
- }
- rl_display_prompt = msg_buf;
- local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
- local_prompt_prefix = (char *)NULL;
- local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
- (*rl_redisplay_function) ();
-
- return 0;
-}
-#else /* !USE_VARARGS */
-int
-rl_message (format, arg1, arg2)
- char *format;
-{
- sprintf (msg_buf, format, arg1, arg2);
- msg_buf[sizeof(msg_buf) - 1] = '\0'; /* overflow? */
-
- rl_display_prompt = msg_buf;
- if (saved_local_prompt == 0)
- {
- rl_save_prompt ();
- msg_saved_prompt = 1;
- }
- local_prompt = expand_prompt (msg_buf, &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
- local_prompt_prefix = (char *)NULL;
- local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
- (*rl_redisplay_function) ();
-
- return 0;
-}
-#endif /* !USE_VARARGS */
-
-/* How to clear things from the "echo-area". */
-int
-rl_clear_message ()
-{
- rl_display_prompt = rl_prompt;
- if (msg_saved_prompt)
- {
- rl_restore_prompt ();
- msg_saved_prompt = 0;
- }
- (*rl_redisplay_function) ();
- return 0;
-}
-
-int
-rl_reset_line_state ()
-{
- rl_on_new_line ();
-
- rl_display_prompt = rl_prompt ? rl_prompt : "";
- forced_display = 1;
- return 0;
-}
-
-void
-rl_save_prompt ()
-{
- saved_local_prompt = local_prompt;
- saved_local_prefix = local_prompt_prefix;
- saved_prefix_length = prompt_prefix_length;
- saved_local_length = local_prompt_len;
- saved_last_invisible = prompt_last_invisible;
- saved_visible_length = prompt_visible_length;
- saved_invis_chars_first_line = prompt_invis_chars_first_line;
- saved_physical_chars = prompt_physical_chars;
-
- local_prompt = local_prompt_prefix = (char *)0;
- local_prompt_len = 0;
- prompt_last_invisible = prompt_visible_length = prompt_prefix_length = 0;
- prompt_invis_chars_first_line = prompt_physical_chars = 0;
-}
-
-void
-rl_restore_prompt ()
-{
- FREE (local_prompt);
- FREE (local_prompt_prefix);
-
- local_prompt = saved_local_prompt;
- local_prompt_prefix = saved_local_prefix;
- local_prompt_len = saved_local_length;
- prompt_prefix_length = saved_prefix_length;
- prompt_last_invisible = saved_last_invisible;
- prompt_visible_length = saved_visible_length;
- prompt_invis_chars_first_line = saved_invis_chars_first_line;
- prompt_physical_chars = saved_physical_chars;
-
- /* can test saved_local_prompt to see if prompt info has been saved. */
- saved_local_prompt = saved_local_prefix = (char *)0;
- saved_local_length = 0;
- saved_last_invisible = saved_visible_length = saved_prefix_length = 0;
- saved_invis_chars_first_line = saved_physical_chars = 0;
-}
-
-char *
-_rl_make_prompt_for_search (pchar)
- int pchar;
-{
- int len;
- char *pmt, *p;
-
- rl_save_prompt ();
-
- /* We've saved the prompt, and can do anything with the various prompt
- strings we need before they're restored. We want the unexpanded
- portion of the prompt string after any final newline. */
- p = rl_prompt ? strrchr (rl_prompt, '\n') : 0;
- if (p == 0)
- {
- len = (rl_prompt && *rl_prompt) ? strlen (rl_prompt) : 0;
- pmt = (char *)xmalloc (len + 2);
- if (len)
- strcpy (pmt, rl_prompt);
- pmt[len] = pchar;
- pmt[len+1] = '\0';
- }
- else
- {
- p++;
- len = strlen (p);
- pmt = (char *)xmalloc (len + 2);
- if (len)
- strcpy (pmt, p);
- pmt[len] = pchar;
- pmt[len+1] = '\0';
- }
-
- /* will be overwritten by expand_prompt, called from rl_message */
- prompt_physical_chars = saved_physical_chars + 1;
- return pmt;
-}
-
-/* Quick redisplay hack when erasing characters at the end of the line. */
-void
-_rl_erase_at_end_of_line (l)
- int l;
-{
- register int i;
-
- _rl_backspace (l);
- for (i = 0; i < l; i++)
- putc (' ', rl_outstream);
- _rl_backspace (l);
- for (i = 0; i < l; i++)
- visible_line[--_rl_last_c_pos] = '\0';
- rl_display_fixed++;
-}
-
-/* Clear to the end of the line. COUNT is the minimum
- number of character spaces to clear, */
-void
-_rl_clear_to_eol (count)
- int count;
-{
- if (_rl_term_clreol)
- tputs (_rl_term_clreol, 1, _rl_output_character_function);
- else if (count)
- space_to_eol (count);
-}
-
-/* Clear to the end of the line using spaces. COUNT is the minimum
- number of character spaces to clear, */
-static void
-space_to_eol (count)
- int count;
-{
- register int i;
-
- for (i = 0; i < count; i++)
- putc (' ', rl_outstream);
-
- _rl_last_c_pos += count;
-}
-
-void
-_rl_clear_screen ()
-{
- if (_rl_term_clrpag)
- tputs (_rl_term_clrpag, 1, _rl_output_character_function);
- else
- rl_crlf ();
-}
-
-/* Insert COUNT characters from STRING to the output stream at column COL. */
-static void
-insert_some_chars (string, count, col)
- char *string;
- int count, col;
-{
-#if defined (__MSDOS__) || defined (__MINGW32__)
- _rl_output_some_chars (string, count);
-#else
- /* DEBUGGING */
- if (MB_CUR_MAX == 1 || rl_byte_oriented)
- if (count != col)
- fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
-
- /* If IC is defined, then we do not have to "enter" insert mode. */
- if (_rl_term_IC)
- {
- char *buffer;
-
- buffer = tgoto (_rl_term_IC, 0, col);
- tputs (buffer, 1, _rl_output_character_function);
- _rl_output_some_chars (string, count);
- }
- else
- {
- register int i;
-
- /* If we have to turn on insert-mode, then do so. */
- if (_rl_term_im && *_rl_term_im)
- tputs (_rl_term_im, 1, _rl_output_character_function);
-
- /* If there is a special command for inserting characters, then
- use that first to open up the space. */
- if (_rl_term_ic && *_rl_term_ic)
- {
- for (i = col; i--; )
- tputs (_rl_term_ic, 1, _rl_output_character_function);
- }
-
- /* Print the text. */
- _rl_output_some_chars (string, count);
-
- /* If there is a string to turn off insert mode, we had best use
- it now. */
- if (_rl_term_ei && *_rl_term_ei)
- tputs (_rl_term_ei, 1, _rl_output_character_function);
- }
-#endif /* __MSDOS__ || __MINGW32__ */
-}
-
-/* Delete COUNT characters from the display line. */
-static void
-delete_chars (count)
- int count;
-{
- if (count > _rl_screenwidth) /* XXX */
- return;
-
-#if !defined (__MSDOS__) && !defined (__MINGW32__)
- if (_rl_term_DC && *_rl_term_DC)
- {
- char *buffer;
- buffer = tgoto (_rl_term_DC, count, count);
- tputs (buffer, count, _rl_output_character_function);
- }
- else
- {
- if (_rl_term_dc && *_rl_term_dc)
- while (count--)
- tputs (_rl_term_dc, 1, _rl_output_character_function);
- }
-#endif /* !__MSDOS__ && !__MINGW32__ */
-}
-
-void
-_rl_update_final ()
-{
- int full_lines;
-
- full_lines = 0;
- /* If the cursor is the only thing on an otherwise-blank last line,
- compensate so we don't print an extra CRLF. */
- if (_rl_vis_botlin && _rl_last_c_pos == 0 &&
- visible_line[vis_lbreaks[_rl_vis_botlin]] == 0)
- {
- _rl_vis_botlin--;
- full_lines = 1;
- }
- _rl_move_vert (_rl_vis_botlin);
- /* If we've wrapped lines, remove the final xterm line-wrap flag. */
- if (full_lines && _rl_term_autowrap && (VIS_LLEN(_rl_vis_botlin) == _rl_screenwidth))
- {
- char *last_line;
-
- last_line = &visible_line[vis_lbreaks[_rl_vis_botlin]];
- cpos_buffer_position = -1; /* don't know where we are in buffer */
- _rl_move_cursor_relative (_rl_screenwidth - 1, last_line); /* XXX */
- _rl_clear_to_eol (0);
- putc (last_line[_rl_screenwidth - 1], rl_outstream);
- }
- _rl_vis_botlin = 0;
- rl_crlf ();
- fflush (rl_outstream);
- rl_display_fixed++;
-}
-
-/* Move to the start of the current line. */
-static void
-cr ()
-{
- if (_rl_term_cr)
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_last_c_pos = 0;
- }
-}
-
-/* Redraw the last line of a multi-line prompt that may possibly contain
- terminal escape sequences. Called with the cursor at column 0 of the
- line to draw the prompt on. */
-static void
-redraw_prompt (t)
- char *t;
-{
- char *oldp;
-
- oldp = rl_display_prompt;
- rl_save_prompt ();
-
- rl_display_prompt = t;
- local_prompt = expand_prompt (t, &prompt_visible_length,
- &prompt_last_invisible,
- &prompt_invis_chars_first_line,
- &prompt_physical_chars);
- local_prompt_prefix = (char *)NULL;
- local_prompt_len = local_prompt ? strlen (local_prompt) : 0;
-
- rl_forced_update_display ();
-
- rl_display_prompt = oldp;
- rl_restore_prompt();
-}
-
-/* Redisplay the current line after a SIGWINCH is received. */
-void
-_rl_redisplay_after_sigwinch ()
-{
- char *t;
-
- /* Clear the current line and put the cursor at column 0. Make sure
- the right thing happens if we have wrapped to a new screen line. */
- if (_rl_term_cr)
- {
-#if defined (__MSDOS__)
- putc ('\r', rl_outstream);
-#else
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif
- _rl_last_c_pos = 0;
-#if defined (__MSDOS__)
- space_to_eol (_rl_screenwidth);
- putc ('\r', rl_outstream);
-#else
- if (_rl_term_clreol)
- tputs (_rl_term_clreol, 1, _rl_output_character_function);
- else
- {
- space_to_eol (_rl_screenwidth);
- tputs (_rl_term_cr, 1, _rl_output_character_function);
- }
-#endif
- if (_rl_last_v_pos > 0)
- _rl_move_vert (0);
- }
- else
- rl_crlf ();
-
- /* Redraw only the last line of a multi-line prompt. */
- t = strrchr (rl_display_prompt, '\n');
- if (t)
- redraw_prompt (++t);
- else
- rl_forced_update_display ();
-}
-
-void
-_rl_clean_up_for_exit ()
-{
- if (readline_echoing_p)
- {
- _rl_move_vert (_rl_vis_botlin);
- _rl_vis_botlin = 0;
- fflush (rl_outstream);
- rl_restart_output (1, 0);
- }
-}
-
-void
-_rl_erase_entire_line ()
-{
- cr ();
- _rl_clear_to_eol (0);
- cr ();
- fflush (rl_outstream);
-}
-
-/* return the `current display line' of the cursor -- the number of lines to
- move up to get to the first screen line of the current readline line. */
-int
-_rl_current_display_line ()
-{
- int ret, nleft;
-
- /* Find out whether or not there might be invisible characters in the
- editing buffer. */
- if (rl_display_prompt == rl_prompt)
- nleft = _rl_last_c_pos - _rl_screenwidth - rl_visible_prompt_length;
- else
- nleft = _rl_last_c_pos - _rl_screenwidth;
-
- if (nleft > 0)
- ret = 1 + nleft / _rl_screenwidth;
- else
- ret = 0;
-
- return ret;
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* Calculate the number of screen columns occupied by STR from START to END.
- In the case of multibyte characters with stateful encoding, we have to
- scan from the beginning of the string to take the state into account. */
-static int
-_rl_col_width (str, start, end)
- const char *str;
- int start, end;
-{
- wchar_t wc;
- mbstate_t ps = {0};
- int tmp, point, width, max;
-
- if (end <= start)
- return 0;
-
- point = 0;
- max = end;
-
- while (point < start)
- {
- tmp = mbrlen (str + point, max, &ps);
- if (MB_INVALIDCH ((size_t)tmp))
- {
- /* In this case, the bytes are invalid or too short to compose a
- multibyte character, so we assume that the first byte represents
- a single character. */
- point++;
- max--;
-
- /* 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 (MB_NULLWCH (tmp))
- break; /* Found '\0' */
- else
- {
- point += tmp;
- max -= tmp;
- }
- }
-
- /* If START is not a byte that starts a character, then POINT will be
- greater than START. In this case, assume that (POINT - START) gives
- a byte count that is the number of columns of difference. */
- width = point - start;
-
- while (point < end)
- {
- tmp = mbrtowc (&wc, str + point, max, &ps);
- if (MB_INVALIDCH ((size_t)tmp))
- {
- /* In this case, the bytes are invalid or too short to compose a
- multibyte character, so we assume that the first byte represents
- a single character. */
- point++;
- max--;
-
- /* and assume that the byte occupies a single column. */
- width++;
-
- /* 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 (MB_NULLWCH (tmp))
- break; /* Found '\0' */
- else
- {
- point += tmp;
- max -= tmp;
- tmp = wcwidth(wc);
- width += (tmp >= 0) ? tmp : 1;
- }
- }
-
- width += point - end;
-
- return width;
-}
-#endif /* HANDLE_MULTIBYTE */
diff --git a/lib/readline/doc/Makefile.old b/lib/readline/doc/Makefile.old
deleted file mode 100644
index 58d4dd76..00000000
--- a/lib/readline/doc/Makefile.old
+++ /dev/null
@@ -1,76 +0,0 @@
-# This makefile for Readline library documentation is in -*- text -*- mode.
-# Emacs likes it that way.
-RM = rm -f
-
-MAKEINFO = makeinfo
-TEXI2DVI = texi2dvi
-TEXI2HTML = texi2html
-QUIETPS = #set this to -q to shut up dvips
-DVIPS = dvips -D 300 $(QUIETPS) -o $@ # tricky
-
-INSTALL_DATA = cp
-infodir = /usr/local/info
-
-RLSRC = rlman.texinfo rluser.texinfo rltech.texinfo
-HISTSRC = hist.texinfo hsuser.texinfo hstech.texinfo
-
-DVIOBJ = readline.dvi history.dvi
-INFOOBJ = readline.info history.info
-PSOBJ = readline.ps history.ps
-HTMLOBJ = readline.html history.html
-
-all: info dvi html ps
-nodvi: info html
-
-readline.dvi: $(RLSRC)
- $(TEXI2DVI) rlman.texinfo
- mv rlman.dvi readline.dvi
-
-readline.info: $(RLSRC)
- $(MAKEINFO) --no-split -o $@ rlman.texinfo
-
-history.dvi: ${HISTSRC}
- $(TEXI2DVI) hist.texinfo
- mv hist.dvi history.dvi
-
-history.info: ${HISTSRC}
- $(MAKEINFO) --no-split -o $@ hist.texinfo
-
-readline.ps: readline.dvi
- $(RM) $@
- $(DVIPS) readline.dvi
-
-history.ps: history.dvi
- $(RM) $@
- $(DVIPS) history.dvi
-
-readline.html: ${RLSRC}
- $(TEXI2HTML) rlman.texinfo
- sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman.html > readline.html
- sed -e 's:rlman.html:readline.html:' -e 's:rlman_toc.html:readline_toc.html:' rlman_toc.html > readline_toc.html
- $(RM) rlman.html rlman_toc.html
-
-history.html: ${HISTSRC}
- $(TEXI2HTML) hist.texinfo
- sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist.html > history.html
- sed -e 's:hist.html:history.html:' -e 's:hist_toc.html:history_toc.html:' hist_toc.html > history_toc.html
- $(RM) hist.html hist_toc.html
-
-info: $(INFOOBJ)
-dvi: $(DVIOBJ)
-ps: $(PSOBJ)
-html: $(HTMLOBJ)
-
-clean:
- $(RM) *.aux *.cp *.fn *.ky *.log *.pg *.toc *.tp *.vr *.cps *.pgs \
- *.fns *.kys *.tps *.vrs *.o core
-
-distclean: clean
-mostlyclean: clean
-
-maintainer-clean: clean
- $(RM) *.dvi *.info *.info-* *.ps *.html
-
-install: info
- ${INSTALL_DATA} readline.info $(infodir)/readline.info
- ${INSTALL_DATA} history.info $(infodir)/history.info
diff --git a/lib/readline/doc/rltech.texi~ b/lib/readline/doc/rltech.texi~
deleted file mode 100644
index 8fcfaeb5..00000000
--- a/lib/readline/doc/rltech.texi~
+++ /dev/null
@@ -1,2287 +0,0 @@
-@comment %**start of header (This is for running Texinfo on a region.)
-@setfilename rltech.info
-@comment %**end of header (This is for running Texinfo on a region.)
-@setchapternewpage odd
-
-@ifinfo
-This document describes the GNU Readline Library, a utility for aiding
-in the consistency of user interface across discrete programs that need
-to provide a command line interface.
-
-Copyright (C) 1988-2005 Free Software Foundation, Inc.
-
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-pare preserved on all copies.
-
-@ignore
-Permission is granted to process this file through TeX and print the
-results, provided the printed document carries copying permission
-notice identical to this one except for the removal of this paragraph
-(this paragraph not being relevant to the printed manual).
-@end ignore
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the entire
-resulting derived work is distributed under the terms of a permission
-notice identical to this one.
-
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions,
-except that this permission notice may be stated in a translation approved
-by the Foundation.
-@end ifinfo
-
-@node Programming with GNU Readline
-@chapter Programming with GNU Readline
-
-This chapter describes the interface between the @sc{gnu} Readline Library and
-other programs. If you are a programmer, and you wish to include the
-features found in @sc{gnu} Readline
-such as completion, line editing, and interactive history manipulation
-in your own programs, this section is for you.
-
-@menu
-* Basic Behavior:: Using the default behavior of Readline.
-* Custom Functions:: Adding your own functions to Readline.
-* Readline Variables:: Variables accessible to custom
- functions.
-* Readline Convenience Functions:: Functions which Readline supplies to
- aid in writing your own custom
- functions.
-* Readline Signal Handling:: How Readline behaves when it receives signals.
-* Custom Completers:: Supplanting or supplementing Readline's
- completion functions.
-@end menu
-
-@node Basic Behavior
-@section Basic Behavior
-
-Many programs provide a command line interface, such as @code{mail},
-@code{ftp}, and @code{sh}. For such programs, the default behaviour of
-Readline is sufficient. This section describes how to use Readline in
-the simplest way possible, perhaps to replace calls in your code to
-@code{gets()} or @code{fgets()}.
-
-@findex readline
-@cindex readline, function
-
-The function @code{readline()} prints a prompt @var{prompt}
-and then reads and returns a single line of text from the user.
-If @var{prompt} is @code{NULL} or the empty string, no prompt is displayed.
-The line @code{readline} returns is allocated with @code{malloc()};
-the caller should @code{free()} the line when it has finished with it.
-The declaration for @code{readline} in ANSI C is
-
-@example
-@code{char *readline (const char *@var{prompt});}
-@end example
-
-@noindent
-So, one might say
-@example
-@code{char *line = readline ("Enter a line: ");}
-@end example
-@noindent
-in order to read a line of text from the user.
-The line returned has the final newline removed, so only the
-text remains.
-
-If @code{readline} encounters an @code{EOF} while reading the line, and the
-line is empty at that point, then @code{(char *)NULL} is returned.
-Otherwise, the line is ended just as if a newline had been typed.
-
-If you want the user to be able to get at the line later, (with
-@key{C-p} for example), you must call @code{add_history()} to save the
-line away in a @dfn{history} list of such lines.
-
-@example
-@code{add_history (line)};
-@end example
-
-@noindent
-For full details on the GNU History Library, see the associated manual.
-
-It is preferable to avoid saving empty lines on the history list, since
-users rarely have a burning need to reuse a blank line. Here is
-a function which usefully replaces the standard @code{gets()} library
-function, and has the advantage of no static buffer to overflow:
-
-@example
-/* A static variable for holding the line. */
-static char *line_read = (char *)NULL;
-
-/* Read a string, and return a pointer to it.
- Returns NULL on EOF. */
-char *
-rl_gets ()
-@{
- /* If the buffer has already been allocated,
- return the memory to the free pool. */
- if (line_read)
- @{
- free (line_read);
- line_read = (char *)NULL;
- @}
-
- /* Get a line from the user. */
- line_read = readline ("");
-
- /* If the line has any text in it,
- save it on the history. */
- if (line_read && *line_read)
- add_history (line_read);
-
- return (line_read);
-@}
-@end example
-
-This function gives the user the default behaviour of @key{TAB}
-completion: completion on file names. If you do not want Readline to
-complete on filenames, you can change the binding of the @key{TAB} key
-with @code{rl_bind_key()}.
-
-@example
-@code{int rl_bind_key (int @var{key}, rl_command_func_t *@var{function});}
-@end example
-
-@code{rl_bind_key()} takes two arguments: @var{key} is the character that
-you want to bind, and @var{function} is the address of the function to
-call when @var{key} is pressed. Binding @key{TAB} to @code{rl_insert()}
-makes @key{TAB} insert itself.
-@code{rl_bind_key()} returns non-zero if @var{key} is not a valid
-ASCII character code (between 0 and 255).
-
-Thus, to disable the default @key{TAB} behavior, the following suffices:
-@example
-@code{rl_bind_key ('\t', rl_insert);}
-@end example
-
-This code should be executed once at the start of your program; you
-might write a function called @code{initialize_readline()} which
-performs this and other desired initializations, such as installing
-custom completers (@pxref{Custom Completers}).
-
-@node Custom Functions
-@section Custom Functions
-
-Readline provides many functions for manipulating the text of
-the line, but it isn't possible to anticipate the needs of all
-programs. This section describes the various functions and variables
-defined within the Readline library which allow a user program to add
-customized functionality to Readline.
-
-Before declaring any functions that customize Readline's behavior, or
-using any functionality Readline provides in other code, an
-application writer should include the file @code{<readline/readline.h>}
-in any file that uses Readline's features. Since some of the definitions
-in @code{readline.h} use the @code{stdio} library, the file
-@code{<stdio.h>} should be included before @code{readline.h}.
-
-@code{readline.h} defines a C preprocessor variable that should
-be treated as an integer, @code{RL_READLINE_VERSION}, which may
-be used to conditionally compile application code depending on
-the installed Readline version. The value is a hexadecimal
-encoding of the major and minor version numbers of the library,
-of the form 0x@var{MMmm}. @var{MM} is the two-digit major
-version number; @var{mm} is the two-digit minor version number.
-For Readline 4.2, for example, the value of
-@code{RL_READLINE_VERSION} would be @code{0x0402}.
-
-@menu
-* Readline Typedefs:: C declarations to make code readable.
-* Function Writing:: Variables and calling conventions.
-@end menu
-
-@node Readline Typedefs
-@subsection Readline Typedefs
-
-For readabilty, we declare a number of new object types, all pointers
-to functions.
-
-The reason for declaring these new types is to make it easier to write
-code describing pointers to C functions with appropriately prototyped
-arguments and return values.
-
-For instance, say we want to declare a variable @var{func} as a pointer
-to a function which takes two @code{int} arguments and returns an
-@code{int} (this is the type of all of the Readline bindable functions).
-Instead of the classic C declaration
-
-@code{int (*func)();}
-
-@noindent
-or the ANSI-C style declaration
-
-@code{int (*func)(int, int);}
-
-@noindent
-we may write
-
-@code{rl_command_func_t *func;}
-
-The full list of function pointer types available is
-
-@table @code
-@item typedef int rl_command_func_t (int, int);
-
-@item typedef char *rl_compentry_func_t (const char *, int);
-
-@item typedef char **rl_completion_func_t (const char *, int, int);
-
-@item typedef char *rl_quote_func_t (char *, int, char *);
-
-@item typedef char *rl_dequote_func_t (char *, int);
-
-@item typedef int rl_compignore_func_t (char **);
-
-@item typedef void rl_compdisp_func_t (char **, int, int);
-
-@item typedef int rl_hook_func_t (void);
-
-@item typedef int rl_getc_func_t (FILE *);
-
-@item typedef int rl_linebuf_func_t (char *, int);
-
-@item typedef int rl_intfunc_t (int);
-@item #define rl_ivoidfunc_t rl_hook_func_t
-@item typedef int rl_icpfunc_t (char *);
-@item typedef int rl_icppfunc_t (char **);
-
-@item typedef void rl_voidfunc_t (void);
-@item typedef void rl_vintfunc_t (int);
-@item typedef void rl_vcpfunc_t (char *);
-@item typedef void rl_vcppfunc_t (char **);
-
-@end table
-
-@node Function Writing
-@subsection Writing a New Function
-
-In order to write new functions for Readline, you need to know the
-calling conventions for keyboard-invoked functions, and the names of the
-variables that describe the current state of the line read so far.
-
-The calling sequence for a command @code{foo} looks like
-
-@example
-@code{int foo (int count, int key)}
-@end example
-
-@noindent
-where @var{count} is the numeric argument (or 1 if defaulted) and
-@var{key} is the key that invoked this function.
-
-It is completely up to the function as to what should be done with the
-numeric argument. Some functions use it as a repeat count, some
-as a flag, and others to choose alternate behavior (refreshing the current
-line as opposed to refreshing the screen, for example). Some choose to
-ignore it. In general, if a
-function uses the numeric argument as a repeat count, it should be able
-to do something useful with both negative and positive arguments.
-At the very least, it should be aware that it can be passed a
-negative argument.
-
-A command function should return 0 if its action completes successfully,
-and a non-zero value if some error occurs.
-This is the convention obeyed by all of the builtin Readline bindable
-command functions.
-
-@node Readline Variables
-@section Readline Variables
-
-These variables are available to function writers.
-
-@deftypevar {char *} rl_line_buffer
-This is the line gathered so far. You are welcome to modify the
-contents of the line, but see @ref{Allowing Undoing}. The
-function @code{rl_extend_line_buffer} is available to increase
-the memory allocated to @code{rl_line_buffer}.
-@end deftypevar
-
-@deftypevar int rl_point
-The offset of the current cursor position in @code{rl_line_buffer}
-(the @emph{point}).
-@end deftypevar
-
-@deftypevar int rl_end
-The number of characters present in @code{rl_line_buffer}. When
-@code{rl_point} is at the end of the line, @code{rl_point} and
-@code{rl_end} are equal.
-@end deftypevar
-
-@deftypevar int rl_mark
-The @var{mark} (saved position) in the current line. If set, the mark
-and point define a @emph{region}.
-@end deftypevar
-
-@deftypevar int rl_done
-Setting this to a non-zero value causes Readline to return the current
-line immediately.
-@end deftypevar
-
-@deftypevar int rl_num_chars_to_read
-Setting this to a positive value before calling @code{readline()} causes
-Readline to return after accepting that many characters, rather
-than reading up to a character bound to @code{accept-line}.
-@end deftypevar
-
-@deftypevar int rl_pending_input
-Setting this to a value makes it the next keystroke read. This is a
-way to stuff a single character into the input stream.
-@end deftypevar
-
-@deftypevar int rl_dispatching
-Set to a non-zero value if a function is being called from a key binding;
-zero otherwise. Application functions can test this to discover whether
-they were called directly or by Readline's dispatching mechanism.
-@end deftypevar
-
-@deftypevar int rl_erase_empty_line
-Setting this to a non-zero value causes Readline to completely erase
-the current line, including any prompt, any time a newline is typed as
-the only character on an otherwise-empty line. The cursor is moved to
-the beginning of the newly-blank line.
-@end deftypevar
-
-@deftypevar {char *} rl_prompt
-The prompt Readline uses. This is set from the argument to
-@code{readline()}, and should not be assigned to directly.
-The @code{rl_set_prompt()} function (@pxref{Redisplay}) may
-be used to modify the prompt string after calling @code{readline()}.
-@end deftypevar
-
-@deftypevar int rl_already_prompted
-If an application wishes to display the prompt itself, rather than have
-Readline do it the first time @code{readline()} is called, it should set
-this variable to a non-zero value after displaying the prompt.
-The prompt must also be passed as the argument to @code{readline()} so
-the redisplay functions can update the display properly.
-The calling application is responsible for managing the value; Readline
-never sets it.
-@end deftypevar
-
-@deftypevar {const char *} rl_library_version
-The version number of this revision of the library.
-@end deftypevar
-
-@deftypevar int rl_readline_version
-An integer encoding the current version of the library. The encoding is
-of the form 0x@var{MMmm}, where @var{MM} is the two-digit major version
-number, and @var{mm} is the two-digit minor version number.
-For example, for Readline-4.2, @code{rl_readline_version} would have the
-value 0x0402.
-@end deftypevar
-
-@deftypevar {int} rl_gnu_readline_p
-Always set to 1, denoting that this is @sc{gnu} readline rather than some
-emulation.
-@end deftypevar
-
-@deftypevar {const char *} rl_terminal_name
-The terminal type, used for initialization. If not set by the application,
-Readline sets this to the value of the @env{TERM} environment variable
-the first time it is called.
-@end deftypevar
-
-@deftypevar {const char *} rl_readline_name
-This variable is set to a unique name by each application using Readline.
-The value allows conditional parsing of the inputrc file
-(@pxref{Conditional Init Constructs}).
-@end deftypevar
-
-@deftypevar {FILE *} rl_instream
-The stdio stream from which Readline reads input.
-If @code{NULL}, Readline defaults to @var{stdin}.
-@end deftypevar
-
-@deftypevar {FILE *} rl_outstream
-The stdio stream to which Readline performs output.
-If @code{NULL}, Readline defaults to @var{stdout}.
-@end deftypevar
-
-@deftypevar int rl_prefer_env_winsize
-If non-zero, Readline gives values found in the @env{LINES} and
-@env{COLUMNS} environment variables greater precedence than values fetched
-from the kernel when computing the screen dimensions.
-@end deftypevar
-
-@deftypevar {rl_command_func_t *} rl_last_func
-The address of the last command function Readline executed. May be used to
-test whether or not a function is being executed twice in succession, for
-example.
-@end deftypevar
-
-@deftypevar {rl_hook_func_t *} rl_startup_hook
-If non-zero, this is the address of a function to call just
-before @code{readline} prints the first prompt.
-@end deftypevar
-
-@deftypevar {rl_hook_func_t *} rl_pre_input_hook
-If non-zero, this is the address of a function to call after
-the first prompt has been printed and just before @code{readline}
-starts reading input characters.
-@end deftypevar
-
-@deftypevar {rl_hook_func_t *} rl_event_hook
-If non-zero, this is the address of a function to call periodically
-when Readline is waiting for terminal input.
-By default, this will be called at most ten times a second if there
-is no keyboard input.
-@end deftypevar
-
-@deftypevar {rl_getc_func_t *} rl_getc_function
-If non-zero, Readline will call indirectly through this pointer
-to get a character from the input stream. By default, it is set to
-@code{rl_getc}, the default Readline character input function
-(@pxref{Character Input}).
-@end deftypevar
-
-@deftypevar {rl_voidfunc_t *} rl_redisplay_function
-If non-zero, Readline will call indirectly through this pointer
-to update the display with the current contents of the editing buffer.
-By default, it is set to @code{rl_redisplay}, the default Readline
-redisplay function (@pxref{Redisplay}).
-@end deftypevar
-
-@deftypevar {rl_vintfunc_t *} rl_prep_term_function
-If non-zero, Readline will call indirectly through this pointer
-to initialize the terminal. The function takes a single argument, an
-@code{int} flag that says whether or not to use eight-bit characters.
-By default, this is set to @code{rl_prep_terminal}
-(@pxref{Terminal Management}).
-@end deftypevar
-
-@deftypevar {rl_voidfunc_t *} rl_deprep_term_function
-If non-zero, Readline will call indirectly through this pointer
-to reset the terminal. This function should undo the effects of
-@code{rl_prep_term_function}.
-By default, this is set to @code{rl_deprep_terminal}
-(@pxref{Terminal Management}).
-@end deftypevar
-
-@deftypevar {Keymap} rl_executing_keymap
-This variable is set to the keymap (@pxref{Keymaps}) in which the
-currently executing readline function was found.
-@end deftypevar
-
-@deftypevar {Keymap} rl_binding_keymap
-This variable is set to the keymap (@pxref{Keymaps}) in which the
-last key binding occurred.
-@end deftypevar
-
-@deftypevar {char *} rl_executing_macro
-This variable is set to the text of any currently-executing macro.
-@end deftypevar
-
-@deftypevar {int} rl_readline_state
-A variable with bit values that encapsulate the current Readline state.
-A bit is set with the @code{RL_SETSTATE} macro, and unset with the
-@code{RL_UNSETSTATE} macro. Use the @code{RL_ISSTATE} macro to test
-whether a particular state bit is set. Current state bits include:
-
-@table @code
-@item RL_STATE_NONE
-Readline has not yet been called, nor has it begun to intialize.
-@item RL_STATE_INITIALIZING
-Readline is initializing its internal data structures.
-@item RL_STATE_INITIALIZED
-Readline has completed its initialization.
-@item RL_STATE_TERMPREPPED
-Readline has modified the terminal modes to do its own input and redisplay.
-@item RL_STATE_READCMD
-Readline is reading a command from the keyboard.
-@item RL_STATE_METANEXT
-Readline is reading more input after reading the meta-prefix character.
-@item RL_STATE_DISPATCHING
-Readline is dispatching to a command.
-@item RL_STATE_MOREINPUT
-Readline is reading more input while executing an editing command.
-@item RL_STATE_ISEARCH
-Readline is performing an incremental history search.
-@item RL_STATE_NSEARCH
-Readline is performing a non-incremental history search.
-@item RL_STATE_SEARCH
-Readline is searching backward or forward through the history for a string.
-@item RL_STATE_NUMERICARG
-Readline is reading a numeric argument.
-@item RL_STATE_MACROINPUT
-Readline is currently getting its input from a previously-defined keyboard
-macro.
-@item RL_STATE_MACRODEF
-Readline is currently reading characters defining a keyboard macro.
-@item RL_STATE_OVERWRITE
-Readline is in overwrite mode.
-@item RL_STATE_COMPLETING
-Readline is performing word completion.
-@item RL_STATE_SIGHANDLER
-Readline is currently executing the readline signal handler.
-@item RL_STATE_UNDOING
-Readline is performing an undo.
-@item RL_STATE_DONE
-Readline has read a key sequence bound to @code{accept-line}
-and is about to return the line to the caller.
-@end table
-
-@end deftypevar
-
-@deftypevar {int} rl_explicit_arg
-Set to a non-zero value if an explicit numeric argument was specified by
-the user. Only valid in a bindable command function.
-@end deftypevar
-
-@deftypevar {int} rl_numeric_arg
-Set to the value of any numeric argument explicitly specified by the user
-before executing the current Readline function. Only valid in a bindable
-command function.
-@end deftypevar
-
-@deftypevar {int} rl_editing_mode
-Set to a value denoting Readline's current editing mode. A value of
-@var{1} means Readline is currently in emacs mode; @var{0}
-means that vi mode is active.
-@end deftypevar
-
-
-@node Readline Convenience Functions
-@section Readline Convenience Functions
-
-@menu
-* Function Naming:: How to give a function you write a name.
-* Keymaps:: Making keymaps.
-* Binding Keys:: Changing Keymaps.
-* Associating Function Names and Bindings:: Translate function names to
- key sequences.
-* Allowing Undoing:: How to make your functions undoable.
-* Redisplay:: Functions to control line display.
-* Modifying Text:: Functions to modify @code{rl_line_buffer}.
-* Character Input:: Functions to read keyboard input.
-* Terminal Management:: Functions to manage terminal settings.
-* Utility Functions:: Generally useful functions and hooks.
-* Miscellaneous Functions:: Functions that don't fall into any category.
-* Alternate Interface:: Using Readline in a `callback' fashion.
-* A Readline Example:: An example Readline function.
-@end menu
-
-@node Function Naming
-@subsection Naming a Function
-
-The user can dynamically change the bindings of keys while using
-Readline. This is done by representing the function with a descriptive
-name. The user is able to type the descriptive name when referring to
-the function. Thus, in an init file, one might find
-
-@example
-Meta-Rubout: backward-kill-word
-@end example
-
-This binds the keystroke @key{Meta-Rubout} to the function
-@emph{descriptively} named @code{backward-kill-word}. You, as the
-programmer, should bind the functions you write to descriptive names as
-well. Readline provides a function for doing that:
-
-@deftypefun int rl_add_defun (const char *name, rl_command_func_t *function, int key)
-Add @var{name} to the list of named functions. Make @var{function} be
-the function that gets called. If @var{key} is not -1, then bind it to
-@var{function} using @code{rl_bind_key()}.
-@end deftypefun
-
-Using this function alone is sufficient for most applications.
-It is the recommended way to add a few functions to the default
-functions that Readline has built in.
-If you need to do something other than adding a function to Readline,
-you may need to use the underlying functions described below.
-
-@node Keymaps
-@subsection Selecting a Keymap
-
-Key bindings take place on a @dfn{keymap}. The keymap is the
-association between the keys that the user types and the functions that
-get run. You can make your own keymaps, copy existing keymaps, and tell
-Readline which keymap to use.
-
-@deftypefun Keymap rl_make_bare_keymap (void)
-Returns a new, empty keymap. The space for the keymap is allocated with
-@code{malloc()}; the caller should free it by calling
-@code{rl_discard_keymap()} when done.
-@end deftypefun
-
-@deftypefun Keymap rl_copy_keymap (Keymap map)
-Return a new keymap which is a copy of @var{map}.
-@end deftypefun
-
-@deftypefun Keymap rl_make_keymap (void)
-Return a new keymap with the printing characters bound to rl_insert,
-the lowercase Meta characters bound to run their equivalents, and
-the Meta digits bound to produce numeric arguments.
-@end deftypefun
-
-@deftypefun void rl_discard_keymap (Keymap keymap)
-Free the storage associated with @var{keymap}.
-@end deftypefun
-
-Readline has several internal keymaps. These functions allow you to
-change which keymap is active.
-
-@deftypefun Keymap rl_get_keymap (void)
-Returns the currently active keymap.
-@end deftypefun
-
-@deftypefun void rl_set_keymap (Keymap keymap)
-Makes @var{keymap} the currently active keymap.
-@end deftypefun
-
-@deftypefun Keymap rl_get_keymap_by_name (const char *name)
-Return the keymap matching @var{name}. @var{name} is one which would
-be supplied in a @code{set keymap} inputrc line (@pxref{Readline Init File}).
-@end deftypefun
-
-@deftypefun {char *} rl_get_keymap_name (Keymap keymap)
-Return the name matching @var{keymap}. @var{name} is one which would
-be supplied in a @code{set keymap} inputrc line (@pxref{Readline Init File}).
-@end deftypefun
-
-@node Binding Keys
-@subsection Binding Keys
-
-Key sequences are associate with functions through the keymap.
-Readline has several internal keymaps: @code{emacs_standard_keymap},
-@code{emacs_meta_keymap}, @code{emacs_ctlx_keymap},
-@code{vi_movement_keymap}, and @code{vi_insertion_keymap}.
-@code{emacs_standard_keymap} is the default, and the examples in
-this manual assume that.
-
-Since @code{readline()} installs a set of default key bindings the first
-time it is called, there is always the danger that a custom binding
-installed before the first call to @code{readline()} will be overridden.
-An alternate mechanism is to install custom key bindings in an
-initialization function assigned to the @code{rl_startup_hook} variable
-(@pxref{Readline Variables}).
-
-These functions manage key bindings.
-
-@deftypefun int rl_bind_key (int key, rl_command_func_t *function)
-Binds @var{key} to @var{function} in the currently active keymap.
-Returns non-zero in the case of an invalid @var{key}.
-@end deftypefun
-
-@deftypefun int rl_bind_key_in_map (int key, rl_command_func_t *function, Keymap map)
-Bind @var{key} to @var{function} in @var{map}.
-Returns non-zero in the case of an invalid @var{key}.
-@end deftypefun
-
-@deftypefun int rl_bind_key_if_unbound (int key, rl_command_func_t *function)
-Binds @var{key} to @var{function} if it is not already bound in the
-currently active keymap.
-Returns non-zero in the case of an invalid @var{key} or if @var{key} is
-already bound.
-@end deftypefun
-
-@deftypefun int rl_bind_key_if_unbound_in_map (int key, rl_command_func_t *function, Keymap map)
-Binds @var{key} to @var{function} if it is not already bound in @var{map}.
-Returns non-zero in the case of an invalid @var{key} or if @var{key} is
-already bound.
-@end deftypefun
-
-@deftypefun int rl_unbind_key (int key)
-Bind @var{key} to the null function in the currently active keymap.
-Returns non-zero in case of error.
-@end deftypefun
-
-@deftypefun int rl_unbind_key_in_map (int key, Keymap map)
-Bind @var{key} to the null function in @var{map}.
-Returns non-zero in case of error.
-@end deftypefun
-
-@deftypefun int rl_unbind_function_in_map (rl_command_func_t *function, Keymap map)
-Unbind all keys that execute @var{function} in @var{map}.
-@end deftypefun
-
-@deftypefun int rl_unbind_command_in_map (const char *command, Keymap map)
-Unbind all keys that are bound to @var{command} in @var{map}.
-@end deftypefun
-
-@deftypefun int rl_bind_keyseq (const char *keyseq, rl_command_func_t *function)
-Bind the key sequence represented by the string @var{keyseq} to the function
-@var{function}, beginning in the current keymap.
-This makes new keymaps as necessary.
-The return value is non-zero if @var{keyseq} is invalid.
-@end deftypefun
-
-@deftypefun int rl_bind_keyseq_in_map (const char *keyseq, rl_command_func_t *function, Keymap map)
-Bind the key sequence represented by the string @var{keyseq} to the function
-@var{function}. This makes new keymaps as necessary.
-Initial bindings are performed in @var{map}.
-The return value is non-zero if @var{keyseq} is invalid.
-@end deftypefun
-
-@deftypefun int rl_set_key (const char *keyseq, rl_command_func_t *function, Keymap map)
-Equivalent to @code{rl_bind_keyseq_in_map}.
-@end deftypefun
-
-@deftypefun int rl_bind_keyseq_if_unbound (const char *keyseq, rl_command_func_t *function)
-Binds @var{keyseq} to @var{function} if it is not already bound in the
-currently active keymap.
-Returns non-zero in the case of an invalid @var{keyseq} or if @var{keyseq} is
-already bound.
-@end deftypefun
-
-@deftypefun int rl_bind_keyseq_if_unbound_in_map (const char *keyseq, rl_command_func_t *function, Keymap map)
-Binds @var{keyseq} to @var{function} if it is not already bound in @var{map}.
-Returns non-zero in the case of an invalid @var{keyseq} or if @var{keyseq} is
-already bound.
-@end deftypefun
-
-@deftypefun int rl_generic_bind (int type, const char *keyseq, char *data, Keymap map)
-Bind the key sequence represented by the string @var{keyseq} to the arbitrary
-pointer @var{data}. @var{type} says what kind of data is pointed to by
-@var{data}; this can be a function (@code{ISFUNC}), a macro
-(@code{ISMACR}), or a keymap (@code{ISKMAP}). This makes new keymaps as
-necessary. The initial keymap in which to do bindings is @var{map}.
-@end deftypefun
-
-@deftypefun int rl_parse_and_bind (char *line)
-Parse @var{line} as if it had been read from the @code{inputrc} file and
-perform any key bindings and variable assignments found
-(@pxref{Readline Init File}).
-@end deftypefun
-
-@deftypefun int rl_read_init_file (const char *filename)
-Read keybindings and variable assignments from @var{filename}
-(@pxref{Readline Init File}).
-@end deftypefun
-
-@node Associating Function Names and Bindings
-@subsection Associating Function Names and Bindings
-
-These functions allow you to find out what keys invoke named functions
-and the functions invoked by a particular key sequence. You may also
-associate a new function name with an arbitrary function.
-
-@deftypefun {rl_command_func_t *} rl_named_function (const char *name)
-Return the function with name @var{name}.
-@end deftypefun
-
-@deftypefun {rl_command_func_t *} rl_function_of_keyseq (const char *keyseq, Keymap map, int *type)
-Return the function invoked by @var{keyseq} in keymap @var{map}.
-If @var{map} is @code{NULL}, the current keymap is used. If @var{type} is
-not @code{NULL}, the type of the object is returned in the @code{int} variable
-it points to (one of @code{ISFUNC}, @code{ISKMAP}, or @code{ISMACR}).
-@end deftypefun
-
-@deftypefun {char **} rl_invoking_keyseqs (rl_command_func_t *function)
-Return an array of strings representing the key sequences used to
-invoke @var{function} in the current keymap.
-@end deftypefun
-
-@deftypefun {char **} rl_invoking_keyseqs_in_map (rl_command_func_t *function, Keymap map)
-Return an array of strings representing the key sequences used to
-invoke @var{function} in the keymap @var{map}.
-@end deftypefun
-
-@deftypefun void rl_function_dumper (int readable)
-Print the readline function names and the key sequences currently
-bound to them to @code{rl_outstream}. If @var{readable} is non-zero,
-the list is formatted in such a way that it can be made part of an
-@code{inputrc} file and re-read.
-@end deftypefun
-
-@deftypefun void rl_list_funmap_names (void)
-Print the names of all bindable Readline functions to @code{rl_outstream}.
-@end deftypefun
-
-@deftypefun {const char **} rl_funmap_names (void)
-Return a NULL terminated array of known function names. The array is
-sorted. The array itself is allocated, but not the strings inside. You
-should @code{free()} the array when you are done, but not the pointers.
-@end deftypefun
-
-@deftypefun int rl_add_funmap_entry (const char *name, rl_command_func_t *function)
-Add @var{name} to the list of bindable Readline command names, and make
-@var{function} the function to be called when @var{name} is invoked.
-@end deftypefun
-
-@node Allowing Undoing
-@subsection Allowing Undoing
-
-Supporting the undo command is a painless thing, and makes your
-functions much more useful. It is certainly easy to try
-something if you know you can undo it.
-
-If your function simply inserts text once, or deletes text once, and
-uses @code{rl_insert_text()} or @code{rl_delete_text()} to do it, then
-undoing is already done for you automatically.
-
-If you do multiple insertions or multiple deletions, or any combination
-of these operations, you should group them together into one operation.
-This is done with @code{rl_begin_undo_group()} and
-@code{rl_end_undo_group()}.
-
-The types of events that can be undone are:
-
-@smallexample
-enum undo_code @{ UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END @};
-@end smallexample
-
-Notice that @code{UNDO_DELETE} means to insert some text, and
-@code{UNDO_INSERT} means to delete some text. That is, the undo code
-tells what to undo, not how to undo it. @code{UNDO_BEGIN} and
-@code{UNDO_END} are tags added by @code{rl_begin_undo_group()} and
-@code{rl_end_undo_group()}.
-
-@deftypefun int rl_begin_undo_group (void)
-Begins saving undo information in a group construct. The undo
-information usually comes from calls to @code{rl_insert_text()} and
-@code{rl_delete_text()}, but could be the result of calls to
-@code{rl_add_undo()}.
-@end deftypefun
-
-@deftypefun int rl_end_undo_group (void)
-Closes the current undo group started with @code{rl_begin_undo_group
-()}. There should be one call to @code{rl_end_undo_group()}
-for each call to @code{rl_begin_undo_group()}.
-@end deftypefun
-
-@deftypefun void rl_add_undo (enum undo_code what, int start, int end, char *text)
-Remember how to undo an event (according to @var{what}). The affected
-text runs from @var{start} to @var{end}, and encompasses @var{text}.
-@end deftypefun
-
-@deftypefun void rl_free_undo_list (void)
-Free the existing undo list.
-@end deftypefun
-
-@deftypefun int rl_do_undo (void)
-Undo the first thing on the undo list. Returns @code{0} if there was
-nothing to undo, non-zero if something was undone.
-@end deftypefun
-
-Finally, if you neither insert nor delete text, but directly modify the
-existing text (e.g., change its case), call @code{rl_modifying()}
-once, just before you modify the text. You must supply the indices of
-the text range that you are going to modify.
-
-@deftypefun int rl_modifying (int start, int end)
-Tell Readline to save the text between @var{start} and @var{end} as a
-single undo unit. It is assumed that you will subsequently modify
-that text.
-@end deftypefun
-
-@node Redisplay
-@subsection Redisplay
-
-@deftypefun void rl_redisplay (void)
-Change what's displayed on the screen to reflect the current contents
-of @code{rl_line_buffer}.
-@end deftypefun
-
-@deftypefun int rl_forced_update_display (void)
-Force the line to be updated and redisplayed, whether or not
-Readline thinks the screen display is correct.
-@end deftypefun
-
-@deftypefun int rl_on_new_line (void)
-Tell the update functions that we have moved onto a new (empty) line,
-usually after ouputting a newline.
-@end deftypefun
-
-@deftypefun int rl_on_new_line_with_prompt (void)
-Tell the update functions that we have moved onto a new line, with
-@var{rl_prompt} already displayed.
-This could be used by applications that want to output the prompt string
-themselves, but still need Readline to know the prompt string length for
-redisplay.
-It should be used after setting @var{rl_already_prompted}.
-@end deftypefun
-
-@deftypefun int rl_reset_line_state (void)
-Reset the display state to a clean state and redisplay the current line
-starting on a new line.
-@end deftypefun
-
-@deftypefun int rl_crlf (void)
-Move the cursor to the start of the next screen line.
-@end deftypefun
-
-@deftypefun int rl_show_char (int c)
-Display character @var{c} on @code{rl_outstream}.
-If Readline has not been set to display meta characters directly, this
-will convert meta characters to a meta-prefixed key sequence.
-This is intended for use by applications which wish to do their own
-redisplay.
-@end deftypefun
-
-@deftypefun int rl_message (const char *, @dots{})
-The arguments are a format string as would be supplied to @code{printf},
-possibly containing conversion specifications such as @samp{%d}, and
-any additional arguments necessary to satisfy the conversion specifications.
-The resulting string is displayed in the @dfn{echo area}. The echo area
-is also used to display numeric arguments and search strings.
-You should call @code{rl_save_prompt} to save the prompt information
-before calling this function.
-@end deftypefun
-
-@deftypefun int rl_clear_message (void)
-Clear the message in the echo area. If the prompt was saved with a call to
-@code{rl_save_prompt} before the last call to @code{rl_message},
-call @code{rl_restore_prompt} before calling this function.
-@end deftypefun
-
-@deftypefun void rl_save_prompt (void)
-Save the local Readline prompt display state in preparation for
-displaying a new message in the message area with @code{rl_message()}.
-@end deftypefun
-
-@deftypefun void rl_restore_prompt (void)
-Restore the local Readline prompt display state saved by the most
-recent call to @code{rl_save_prompt}.
-if @code{rl_save_prompt} was called to save the prompt before a call
-to @code{rl_message}, this function should be called before the
-corresponding call to @code{rl_clear_message}.
-@end deftypefun
-
-@deftypefun int rl_expand_prompt (char *prompt)
-Expand any special character sequences in @var{prompt} and set up the
-local Readline prompt redisplay variables.
-This function is called by @code{readline()}. It may also be called to
-expand the primary prompt if the @code{rl_on_new_line_with_prompt()}
-function or @code{rl_already_prompted} variable is used.
-It returns the number of visible characters on the last line of the
-(possibly multi-line) prompt.
-Applications may indicate that the prompt contains characters that take
-up no physical screen space when displayed by bracketing a sequence of
-such characters with the special markers @code{RL_PROMPT_START_IGNORE}
-and @code{RL_PROMPT_END_IGNORE} (declared in @file{readline.h}. This may
-be used to embed terminal-specific escape sequences in prompts.
-@end deftypefun
-
-@deftypefun int rl_set_prompt (const char *prompt)
-Make Readline use @var{prompt} for subsequent redisplay. This calls
-@code{rl_expand_prompt()} to expand the prompt and sets @code{rl_prompt}
-to the result.
-@end deftypefun
-
-@node Modifying Text
-@subsection Modifying Text
-
-@deftypefun int rl_insert_text (const char *text)
-Insert @var{text} into the line at the current cursor position.
-Returns the number of characters inserted.
-@end deftypefun
-
-@deftypefun int rl_delete_text (int start, int end)
-Delete the text between @var{start} and @var{end} in the current line.
-Returns the number of characters deleted.
-@end deftypefun
-
-@deftypefun {char *} rl_copy_text (int start, int end)
-Return a copy of the text between @var{start} and @var{end} in
-the current line.
-@end deftypefun
-
-@deftypefun int rl_kill_text (int start, int end)
-Copy the text between @var{start} and @var{end} in the current line
-to the kill ring, appending or prepending to the last kill if the
-last command was a kill command. The text is deleted.
-If @var{start} is less than @var{end},
-the text is appended, otherwise prepended. If the last command was
-not a kill, a new kill ring slot is used.
-@end deftypefun
-
-@deftypefun int rl_push_macro_input (char *macro)
-Cause @var{macro} to be inserted into the line, as if it had been invoked
-by a key bound to a macro. Not especially useful; use
-@code{rl_insert_text()} instead.
-@end deftypefun
-
-@node Character Input
-@subsection Character Input
-
-@deftypefun int rl_read_key (void)
-Return the next character available from Readline's current input stream.
-This handles input inserted into
-the input stream via @var{rl_pending_input} (@pxref{Readline Variables})
-and @code{rl_stuff_char()}, macros, and characters read from the keyboard.
-While waiting for input, this function will call any function assigned to
-the @code{rl_event_hook} variable.
-@end deftypefun
-
-@deftypefun int rl_getc (FILE *stream)
-Return the next character available from @var{stream}, which is assumed to
-be the keyboard.
-@end deftypefun
-
-@deftypefun int rl_stuff_char (int c)
-Insert @var{c} into the Readline input stream. It will be "read"
-before Readline attempts to read characters from the terminal with
-@code{rl_read_key()}. Up to 512 characters may be pushed back.
-@code{rl_stuff_char} returns 1 if the character was successfully inserted;
-0 otherwise.
-@end deftypefun
-
-@deftypefun int rl_execute_next (int c)
-Make @var{c} be the next command to be executed when @code{rl_read_key()}
-is called. This sets @var{rl_pending_input}.
-@end deftypefun
-
-@deftypefun int rl_clear_pending_input (void)
-Unset @var{rl_pending_input}, effectively negating the effect of any
-previous call to @code{rl_execute_next()}. This works only if the
-pending input has not already been read with @code{rl_read_key()}.
-@end deftypefun
-
-@deftypefun int rl_set_keyboard_input_timeout (int u)
-While waiting for keyboard input in @code{rl_read_key()}, Readline will
-wait for @var{u} microseconds for input before calling any function
-assigned to @code{rl_event_hook}. @var{u} must be greater than or equal
-to zero (a zero-length timeout is equivalent to a poll).
-The default waiting period is one-tenth of a second.
-Returns the old timeout value.
-@end deftypefun
-
-@node Terminal Management
-@subsection Terminal Management
-
-@deftypefun void rl_prep_terminal (int meta_flag)
-Modify the terminal settings for Readline's use, so @code{readline()}
-can read a single character at a time from the keyboard.
-The @var{meta_flag} argument should be non-zero if Readline should
-read eight-bit input.
-@end deftypefun
-
-@deftypefun void rl_deprep_terminal (void)
-Undo the effects of @code{rl_prep_terminal()}, leaving the terminal in
-the state in which it was before the most recent call to
-@code{rl_prep_terminal()}.
-@end deftypefun
-
-@deftypefun void rl_tty_set_default_bindings (Keymap kmap)
-Read the operating system's terminal editing characters (as would be
-displayed by @code{stty}) to their Readline equivalents.
-The bindings are performed in @var{kmap}.
-@end deftypefun
-
-@deftypefun void rl_tty_unset_default_bindings (Keymap kmap)
-Reset the bindings manipulated by @code{rl_tty_set_default_bindings} so
-that the terminal editing characters are bound to @code{rl_insert}.
-The bindings are performed in @var{kmap}.
-@end deftypefun
-
-@deftypefun int rl_reset_terminal (const char *terminal_name)
-Reinitialize Readline's idea of the terminal settings using
-@var{terminal_name} as the terminal type (e.g., @code{vt100}).
-If @var{terminal_name} is @code{NULL}, the value of the @code{TERM}
-environment variable is used.
-@end deftypefun
-
-@node Utility Functions
-@subsection Utility Functions
-
-@deftypefun void rl_replace_line (const char *text, int clear_undo)
-Replace the contents of @code{rl_line_buffer} with @var{text}.
-The point and mark are preserved, if possible.
-If @var{clear_undo} is non-zero, the undo list associated with the
-current line is cleared.
-@end deftypefun
-
-@deftypefun int rl_extend_line_buffer (int len)
-Ensure that @code{rl_line_buffer} has enough space to hold @var{len}
-characters, possibly reallocating it if necessary.
-@end deftypefun
-
-@deftypefun int rl_initialize (void)
-Initialize or re-initialize Readline's internal state.
-It's not strictly necessary to call this; @code{readline()} calls it before
-reading any input.
-@end deftypefun
-
-@deftypefun int rl_ding (void)
-Ring the terminal bell, obeying the setting of @code{bell-style}.
-@end deftypefun
-
-@deftypefun int rl_alphabetic (int c)
-Return 1 if @var{c} is an alphabetic character.
-@end deftypefun
-
-@deftypefun void rl_display_match_list (char **matches, int len, int max)
-A convenience function for displaying a list of strings in
-columnar format on Readline's output stream. @code{matches} is the list
-of strings, in argv format, such as a list of completion matches.
-@code{len} is the number of strings in @code{matches}, and @code{max}
-is the length of the longest string in @code{matches}. This function uses
-the setting of @code{print-completions-horizontally} to select how the
-matches are displayed (@pxref{Readline Init File Syntax}).
-@end deftypefun
-
-The following are implemented as macros, defined in @code{chardefs.h}.
-Applications should refrain from using them.
-
-@deftypefun int _rl_uppercase_p (int c)
-Return 1 if @var{c} is an uppercase alphabetic character.
-@end deftypefun
-
-@deftypefun int _rl_lowercase_p (int c)
-Return 1 if @var{c} is a lowercase alphabetic character.
-@end deftypefun
-
-@deftypefun int _rl_digit_p (int c)
-Return 1 if @var{c} is a numeric character.
-@end deftypefun
-
-@deftypefun int _rl_to_upper (int c)
-If @var{c} is a lowercase alphabetic character, return the corresponding
-uppercase character.
-@end deftypefun
-
-@deftypefun int _rl_to_lower (int c)
-If @var{c} is an uppercase alphabetic character, return the corresponding
-lowercase character.
-@end deftypefun
-
-@deftypefun int _rl_digit_value (int c)
-If @var{c} is a number, return the value it represents.
-@end deftypefun
-
-@node Miscellaneous Functions
-@subsection Miscellaneous Functions
-
-@deftypefun int rl_macro_bind (const char *keyseq, const char *macro, Keymap map)
-Bind the key sequence @var{keyseq} to invoke the macro @var{macro}.
-The binding is performed in @var{map}. When @var{keyseq} is invoked, the
-@var{macro} will be inserted into the line. This function is deprecated;
-use @code{rl_generic_bind()} instead.
-@end deftypefun
-
-@deftypefun void rl_macro_dumper (int readable)
-Print the key sequences bound to macros and their values, using
-the current keymap, to @code{rl_outstream}.
-If @var{readable} is non-zero, the list is formatted in such a way
-that it can be made part of an @code{inputrc} file and re-read.
-@end deftypefun
-
-@deftypefun int rl_variable_bind (const char *variable, const char *value)
-Make the Readline variable @var{variable} have @var{value}.
-This behaves as if the readline command
-@samp{set @var{variable} @var{value}} had been executed in an @code{inputrc}
-file (@pxref{Readline Init File Syntax}).
-@end deftypefun
-
-@deftypefun {char *} rl_variable_value (const char *variable)
-Return a string representing the value of the Readline variable @var{variable}.
-For boolean variables, this string is either @samp{on} or @samp{off}.
-@end deftypefun
-
-@deftypefun void rl_variable_dumper (int readable)
-Print the readline variable names and their current values
-to @code{rl_outstream}.
-If @var{readable} is non-zero, the list is formatted in such a way
-that it can be made part of an @code{inputrc} file and re-read.
-@end deftypefun
-
-@deftypefun int rl_set_paren_blink_timeout (int u)
-Set the time interval (in microseconds) that Readline waits when showing
-a balancing character when @code{blink-matching-paren} has been enabled.
-@end deftypefun
-
-@deftypefun {char *} rl_get_termcap (const char *cap)
-Retrieve the string value of the termcap capability @var{cap}.
-Readline fetches the termcap entry for the current terminal name and
-uses those capabilities to move around the screen line and perform other
-terminal-specific operations, like erasing a line. Readline does not
-use all of a terminal's capabilities, and this function will return
-values for only those capabilities Readline uses.
-@end deftypefun
-
-@node Alternate Interface
-@subsection Alternate Interface
-
-An alternate interface is available to plain @code{readline()}. Some
-applications need to interleave keyboard I/O with file, device, or
-window system I/O, typically by using a main loop to @code{select()}
-on various file descriptors. To accomodate this need, readline can
-also be invoked as a `callback' function from an event loop. There
-are functions available to make this easy.
-
-@deftypefun void rl_callback_handler_install (const char *prompt, rl_vcpfunc_t *lhandler)
-Set up the terminal for readline I/O and display the initial
-expanded value of @var{prompt}. Save the value of @var{lhandler} to
-use as a function to call when a complete line of input has been entered.
-The function takes the text of the line as an argument.
-@end deftypefun
-
-@deftypefun void rl_callback_read_char (void)
-Whenever an application determines that keyboard input is available, it
-should call @code{rl_callback_read_char()}, which will read the next
-character from the current input source.
-If that character completes the line, @code{rl_callback_read_char} will
-invoke the @var{lhandler} function saved by @code{rl_callback_handler_install}
-to process the line.
-Before calling the @var{lhandler} function, the terminal settings are
-reset to the values they had before calling
-@code{rl_callback_handler_install}.
-If the @var{lhandler} function returns,
-the terminal settings are modified for Readline's use again.
-@code{EOF} is indicated by calling @var{lhandler} with a
-@code{NULL} line.
-@end deftypefun
-
-@deftypefun void rl_callback_handler_remove (void)
-Restore the terminal to its initial state and remove the line handler.
-This may be called from within a callback as well as independently.
-If the @var{lhandler} installed by @code{rl_callback_handler_install}
-does not exit the program, either this function or the function referred
-to by the value of @code{rl_deprep_term_function} should be called before
-the program exits to reset the terminal settings.
-@end deftypefun
-
-@node A Readline Example
-@subsection A Readline Example
-
-Here is a function which changes lowercase characters to their uppercase
-equivalents, and uppercase characters to lowercase. If
-this function was bound to @samp{M-c}, then typing @samp{M-c} would
-change the case of the character under point. Typing @samp{M-1 0 M-c}
-would change the case of the following 10 characters, leaving the cursor on
-the last character changed.
-
-@example
-/* Invert the case of the COUNT following characters. */
-int
-invert_case_line (count, key)
- int count, key;
-@{
- register int start, end, i;
-
- start = rl_point;
-
- if (rl_point >= rl_end)
- return (0);
-
- if (count < 0)
- @{
- direction = -1;
- count = -count;
- @}
- else
- direction = 1;
-
- /* Find the end of the range to modify. */
- end = start + (count * direction);
-
- /* Force it to be within range. */
- if (end > rl_end)
- end = rl_end;
- else if (end < 0)
- end = 0;
-
- if (start == end)
- return (0);
-
- if (start > end)
- @{
- int temp = start;
- start = end;
- end = temp;
- @}
-
- /* Tell readline that we are modifying the line,
- so it will save the undo information. */
- rl_modifying (start, end);
-
- for (i = start; i != end; i++)
- @{
- if (_rl_uppercase_p (rl_line_buffer[i]))
- rl_line_buffer[i] = _rl_to_lower (rl_line_buffer[i]);
- else if (_rl_lowercase_p (rl_line_buffer[i]))
- rl_line_buffer[i] = _rl_to_upper (rl_line_buffer[i]);
- @}
- /* Move point to on top of the last character changed. */
- rl_point = (direction == 1) ? end - 1 : start;
- return (0);
-@}
-@end example
-
-@node Readline Signal Handling
-@section Readline Signal Handling
-
-Signals are asynchronous events sent to a process by the Unix kernel,
-sometimes on behalf of another process. They are intended to indicate
-exceptional events, like a user pressing the interrupt key on his terminal,
-or a network connection being broken. There is a class of signals that can
-be sent to the process currently reading input from the keyboard. Since
-Readline changes the terminal attributes when it is called, it needs to
-perform special processing when such a signal is received in order to
-restore the terminal to a sane state, or provide application writers with
-functions to do so manually.
-
-Readline contains an internal signal handler that is installed for a
-number of signals (@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM},
-@code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN}, and @code{SIGTTOU}).
-When one of these signals is received, the signal handler
-will reset the terminal attributes to those that were in effect before
-@code{readline()} was called, reset the signal handling to what it was
-before @code{readline()} was called, and resend the signal to the calling
-application.
-If and when the calling application's signal handler returns, Readline
-will reinitialize the terminal and continue to accept input.
-When a @code{SIGINT} is received, the Readline signal handler performs
-some additional work, which will cause any partially-entered line to be
-aborted (see the description of @code{rl_free_line_state()} below).
-
-There is an additional Readline signal handler, for @code{SIGWINCH}, which
-the kernel sends to a process whenever the terminal's size changes (for
-example, if a user resizes an @code{xterm}). The Readline @code{SIGWINCH}
-handler updates Readline's internal screen size information, and then calls
-any @code{SIGWINCH} signal handler the calling application has installed.
-Readline calls the application's @code{SIGWINCH} signal handler without
-resetting the terminal to its original state. If the application's signal
-handler does more than update its idea of the terminal size and return (for
-example, a @code{longjmp} back to a main processing loop), it @emph{must}
-call @code{rl_cleanup_after_signal()} (described below), to restore the
-terminal state.
-
-Readline provides two variables that allow application writers to
-control whether or not it will catch certain signals and act on them
-when they are received. It is important that applications change the
-values of these variables only when calling @code{readline()}, not in
-a signal handler, so Readline's internal signal state is not corrupted.
-
-@deftypevar int rl_catch_signals
-If this variable is non-zero, Readline will install signal handlers for
-@code{SIGINT}, @code{SIGQUIT}, @code{SIGTERM}, @code{SIGALRM},
-@code{SIGTSTP}, @code{SIGTTIN}, and @code{SIGTTOU}.
-
-The default value of @code{rl_catch_signals} is 1.
-@end deftypevar
-
-@deftypevar int rl_catch_sigwinch
-If this variable is non-zero, Readline will install a signal handler for
-@code{SIGWINCH}.
-
-The default value of @code{rl_catch_sigwinch} is 1.
-@end deftypevar
-
-If an application does not wish to have Readline catch any signals, or
-to handle signals other than those Readline catches (@code{SIGHUP},
-for example),
-Readline provides convenience functions to do the necessary terminal
-and internal state cleanup upon receipt of a signal.
-
-@deftypefun void rl_cleanup_after_signal (void)
-This function will reset the state of the terminal to what it was before
-@code{readline()} was called, and remove the Readline signal handlers for
-all signals, depending on the values of @code{rl_catch_signals} and
-@code{rl_catch_sigwinch}.
-@end deftypefun
-
-@deftypefun void rl_free_line_state (void)
-This will free any partial state associated with the current input line
-(undo information, any partial history entry, any partially-entered
-keyboard macro, and any partially-entered numeric argument). This
-should be called before @code{rl_cleanup_after_signal()}. The
-Readline signal handler for @code{SIGINT} calls this to abort the
-current input line.
-@end deftypefun
-
-@deftypefun void rl_reset_after_signal (void)
-This will reinitialize the terminal and reinstall any Readline signal
-handlers, depending on the values of @code{rl_catch_signals} and
-@code{rl_catch_sigwinch}.
-@end deftypefun
-
-If an application does not wish Readline to catch @code{SIGWINCH}, it may
-call @code{rl_resize_terminal()} or @code{rl_set_screen_size()} to force
-Readline to update its idea of the terminal size when a @code{SIGWINCH}
-is received.
-
-@deftypefun void rl_resize_terminal (void)
-Update Readline's internal screen size by reading values from the kernel.
-@end deftypefun
-
-@deftypefun void rl_set_screen_size (int rows, int cols)
-Set Readline's idea of the terminal size to @var{rows} rows and
-@var{cols} columns. If either @var{rows} or @var{columns} is less than
-or equal to 0, Readline's idea of that terminal dimension is unchanged.
-@end deftypefun
-
-If an application does not want to install a @code{SIGWINCH} handler, but
-is still interested in the screen dimensions, Readline's idea of the screen
-size may be queried.
-
-@deftypefun void rl_get_screen_size (int *rows, int *cols)
-Return Readline's idea of the terminal's size in the
-variables pointed to by the arguments.
-@end deftypefun
-
-@deftypefun void rl_reset_screen_size (void)
-Cause Readline to reobtain the screen size and recalculate its dimensions.
-@end deftypefun
-
-The following functions install and remove Readline's signal handlers.
-
-@deftypefun int rl_set_signals (void)
-Install Readline's signal handler for @code{SIGINT}, @code{SIGQUIT},
-@code{SIGTERM}, @code{SIGALRM}, @code{SIGTSTP}, @code{SIGTTIN},
-@code{SIGTTOU}, and @code{SIGWINCH}, depending on the values of
-@code{rl_catch_signals} and @code{rl_catch_sigwinch}.
-@end deftypefun
-
-@deftypefun int rl_clear_signals (void)
-Remove all of the Readline signal handlers installed by
-@code{rl_set_signals()}.
-@end deftypefun
-
-@node Custom Completers
-@section Custom Completers
-@cindex application-specific completion functions
-
-Typically, a program that reads commands from the user has a way of
-disambiguating commands and data. If your program is one of these, then
-it can provide completion for commands, data, or both.
-The following sections describe how your program and Readline
-cooperate to provide this service.
-
-@menu
-* How Completing Works:: The logic used to do completion.
-* Completion Functions:: Functions provided by Readline.
-* Completion Variables:: Variables which control completion.
-* A Short Completion Example:: An example of writing completer subroutines.
-@end menu
-
-@node How Completing Works
-@subsection How Completing Works
-
-In order to complete some text, the full list of possible completions
-must be available. That is, it is not possible to accurately
-expand a partial word without knowing all of the possible words
-which make sense in that context. The Readline library provides
-the user interface to completion, and two of the most common
-completion functions: filename and username. For completing other types
-of text, you must write your own completion function. This section
-describes exactly what such functions must do, and provides an example.
-
-There are three major functions used to perform completion:
-
-@enumerate
-@item
-The user-interface function @code{rl_complete()}. This function is
-called with the same arguments as other bindable Readline functions:
-@var{count} and @var{invoking_key}.
-It isolates the word to be completed and calls
-@code{rl_completion_matches()} to generate a list of possible completions.
-It then either lists the possible completions, inserts the possible
-completions, or actually performs the
-completion, depending on which behavior is desired.
-
-@item
-The internal function @code{rl_completion_matches()} uses an
-application-supplied @dfn{generator} function to generate the list of
-possible matches, and then returns the array of these matches.
-The caller should place the address of its generator function in
-@code{rl_completion_entry_function}.
-
-@item
-The generator function is called repeatedly from
-@code{rl_completion_matches()}, returning a string each time. The
-arguments to the generator function are @var{text} and @var{state}.
-@var{text} is the partial word to be completed. @var{state} is zero the
-first time the function is called, allowing the generator to perform
-any necessary initialization, and a positive non-zero integer for
-each subsequent call. The generator function returns
-@code{(char *)NULL} to inform @code{rl_completion_matches()} that there are
-no more possibilities left. Usually the generator function computes the
-list of possible completions when @var{state} is zero, and returns them
-one at a time on subsequent calls. Each string the generator function
-returns as a match must be allocated with @code{malloc()}; Readline
-frees the strings when it has finished with them.
-Such a generator function is referred to as an
-@dfn{application-specific completion function}.
-
-@end enumerate
-
-@deftypefun int rl_complete (int ignore, int invoking_key)
-Complete the word at or before point. You have supplied the function
-that does the initial simple matching selection algorithm (see
-@code{rl_completion_matches()}). The default is to do filename completion.
-@end deftypefun
-
-@deftypevar {rl_compentry_func_t *} rl_completion_entry_function
-This is a pointer to the generator function for
-@code{rl_completion_matches()}.
-If the value of @code{rl_completion_entry_function} is
-@code{NULL} then the default filename generator
-function, @code{rl_filename_completion_function()}, is used.
-An @dfn{application-specific completion function} is a function whose
-address is assigned to @code{rl_completion_entry_function} and whose
-return values are used to generate possible completions.
-@end deftypevar
-
-@node Completion Functions
-@subsection Completion Functions
-
-Here is the complete list of callable completion functions present in
-Readline.
-
-@deftypefun int rl_complete_internal (int what_to_do)
-Complete the word at or before point. @var{what_to_do} says what to do
-with the completion. A value of @samp{?} means list the possible
-completions. @samp{TAB} means do standard completion. @samp{*} means
-insert all of the possible completions. @samp{!} means to display
-all of the possible completions, if there is more than one, as well as
-performing partial completion. @samp{@@} is similar to @samp{!}, but
-possible completions are not listed if the possible completions share
-a common prefix.
-@end deftypefun
-
-@deftypefun int rl_complete (int ignore, int invoking_key)
-Complete the word at or before point. You have supplied the function
-that does the initial simple matching selection algorithm (see
-@code{rl_completion_matches()} and @code{rl_completion_entry_function}).
-The default is to do filename
-completion. This calls @code{rl_complete_internal()} with an
-argument depending on @var{invoking_key}.
-@end deftypefun
-
-@deftypefun int rl_possible_completions (int count, int invoking_key)
-List the possible completions. See description of @code{rl_complete
-()}. This calls @code{rl_complete_internal()} with an argument of
-@samp{?}.
-@end deftypefun
-
-@deftypefun int rl_insert_completions (int count, int invoking_key)
-Insert the list of possible completions into the line, deleting the
-partially-completed word. See description of @code{rl_complete()}.
-This calls @code{rl_complete_internal()} with an argument of @samp{*}.
-@end deftypefun
-
-@deftypefun int rl_completion_mode (rl_command_func_t *cfunc)
-Returns the apppriate value to pass to @code{rl_complete_internal()}
-depending on whether @var{cfunc} was called twice in succession and
-the values of the @code{show-all-if-ambiguous} and
-@code{show-all-if-unmodified} variables.
-Application-specific completion functions may use this function to present
-the same interface as @code{rl_complete()}.
-@end deftypefun
-
-@deftypefun {char **} rl_completion_matches (const char *text, rl_compentry_func_t *entry_func)
-Returns an array of strings which is a list of completions for
-@var{text}. If there are no completions, returns @code{NULL}.
-The first entry in the returned array is the substitution for @var{text}.
-The remaining entries are the possible completions. The array is
-terminated with a @code{NULL} pointer.
-
-@var{entry_func} is a function of two args, and returns a
-@code{char *}. The first argument is @var{text}. The second is a
-state argument; it is zero on the first call, and non-zero on subsequent
-calls. @var{entry_func} returns a @code{NULL} pointer to the caller
-when there are no more matches.
-@end deftypefun
-
-@deftypefun {char *} rl_filename_completion_function (const char *text, int state)
-A generator function for filename completion in the general case.
-@var{text} is a partial filename.
-The Bash source is a useful reference for writing application-specific
-completion functions (the Bash completion functions call this and other
-Readline functions).
-@end deftypefun
-
-@deftypefun {char *} rl_username_completion_function (const char *text, int state)
-A completion generator for usernames. @var{text} contains a partial
-username preceded by a random character (usually @samp{~}). As with all
-completion generators, @var{state} is zero on the first call and non-zero
-for subsequent calls.
-@end deftypefun
-
-@node Completion Variables
-@subsection Completion Variables
-
-@deftypevar {rl_compentry_func_t *} rl_completion_entry_function
-A pointer to the generator function for @code{rl_completion_matches()}.
-@code{NULL} means to use @code{rl_filename_completion_function()},
-the default filename completer.
-@end deftypevar
-
-@deftypevar {rl_completion_func_t *} rl_attempted_completion_function
-A pointer to an alternative function to create matches.
-The function is called with @var{text}, @var{start}, and @var{end}.
-@var{start} and @var{end} are indices in @code{rl_line_buffer} defining
-the boundaries of @var{text}, which is a character string.
-If this function exists and returns @code{NULL}, or if this variable is
-set to @code{NULL}, then @code{rl_complete()} will call the value of
-@code{rl_completion_entry_function} to generate matches, otherwise the
-array of strings returned will be used.
-If this function sets the @code{rl_attempted_completion_over}
-variable to a non-zero value, Readline will not perform its default
-completion even if this function returns no matches.
-@end deftypevar
-
-@deftypevar {rl_quote_func_t *} rl_filename_quoting_function
-A pointer to a function that will quote a filename in an
-application-specific fashion. This is called if filename completion is being
-attempted and one of the characters in @code{rl_filename_quote_characters}
-appears in a completed filename. The function is called with
-@var{text}, @var{match_type}, and @var{quote_pointer}. The @var{text}
-is the filename to be quoted. The @var{match_type} is either
-@code{SINGLE_MATCH}, if there is only one completion match, or
-@code{MULT_MATCH}. Some functions use this to decide whether or not to
-insert a closing quote character. The @var{quote_pointer} is a pointer
-to any opening quote character the user typed. Some functions choose
-to reset this character.
-@end deftypevar
-
-@deftypevar {rl_dequote_func_t *} rl_filename_dequoting_function
-A pointer to a function that will remove application-specific quoting
-characters from a filename before completion is attempted, so those
-characters do not interfere with matching the text against names in
-the filesystem. It is called with @var{text}, the text of the word
-to be dequoted, and @var{quote_char}, which is the quoting character
-that delimits the filename (usually @samp{'} or @samp{"}). If
-@var{quote_char} is zero, the filename was not in an embedded string.
-@end deftypevar
-
-@deftypevar {rl_linebuf_func_t *} rl_char_is_quoted_p
-A pointer to a function to call that determines whether or not a specific
-character in the line buffer is quoted, according to whatever quoting
-mechanism the program calling Readline uses. The function is called with
-two arguments: @var{text}, the text of the line, and @var{index}, the
-index of the character in the line. It is used to decide whether a
-character found in @code{rl_completer_word_break_characters} should be
-used to break words for the completer.
-@end deftypevar
-
-@deftypevar {rl_compignore_func_t *} rl_ignore_some_completions_function
-This function, if defined, is called by the completer when real filename
-completion is done, after all the matching names have been generated.
-It is passed a @code{NULL} terminated array of matches.
-The first element (@code{matches[0]}) is the
-maximal substring common to all matches. This function can
-re-arrange the list of matches as required, but each element deleted
-from the array must be freed.
-@end deftypevar
-
-@deftypevar {rl_icppfunc_t *} rl_directory_completion_hook
-This function, if defined, is allowed to modify the directory portion
-of filenames Readline completes. It is called with the address of a
-string (the current directory name) as an argument, and may modify that string.
-If the string is replaced with a new string, the old value should be freed.
-Any modified directory name should have a trailing slash.
-The modified value will be displayed as part of the completion, replacing
-the directory portion of the pathname the user typed.
-It returns an integer that should be non-zero if the function modifies
-its directory argument.
-It could be used to expand symbolic links or shell variables in pathnames.
-@end deftypevar
-
-@deftypevar {rl_compdisp_func_t *} rl_completion_display_matches_hook
-If non-zero, then this is the address of a function to call when
-completing a word would normally display the list of possible matches.
-This function is called in lieu of Readline displaying the list.
-It takes three arguments:
-(@code{char **}@var{matches}, @code{int} @var{num_matches}, @code{int} @var{max_length})
-where @var{matches} is the array of matching strings,
-@var{num_matches} is the number of strings in that array, and
-@var{max_length} is the length of the longest string in that array.
-Readline provides a convenience function, @code{rl_display_match_list},
-that takes care of doing the display to Readline's output stream. That
-function may be called from this hook.
-@end deftypevar
-
-@deftypevar {const char *} rl_basic_word_break_characters
-The basic list of characters that signal a break between words for the
-completer routine. The default value of this variable is the characters
-which break words for completion in Bash:
-@code{" \t\n\"\\'`@@$><=;|&@{("}.
-@end deftypevar
-
-@deftypevar {const char *} rl_basic_quote_characters
-A list of quote characters which can cause a word break.
-@end deftypevar
-
-@deftypevar {const char *} rl_completer_word_break_characters
-The list of characters that signal a break between words for
-@code{rl_complete_internal()}. The default list is the value of
-@code{rl_basic_word_break_characters}.
-@end deftypevar
-
-@deftypevar {rl_cpvfunc_t *} rl_completion_word_break_hook
-If non-zero, this is the address of a function to call when Readline is
-deciding where to separate words for word completion. It should return
-a character string like @code{rl_completer_word_break_characters} to be
-used to perform the current completion. The function may choose to set
-@code{rl_completer_word_break_characters} itself. If the function
-returns @code{NULL}, @code{rl_completer_word_break_characters} is used.
-@end deftypevar
-
-@deftypevar {const char *} rl_completer_quote_characters
-A list of characters which can be used to quote a substring of the line.
-Completion occurs on the entire substring, and within the substring
-@code{rl_completer_word_break_characters} are treated as any other character,
-unless they also appear within this list.
-@end deftypevar
-
-@deftypevar {const char *} rl_filename_quote_characters
-A list of characters that cause a filename to be quoted by the completer
-when they appear in a completed filename. The default is the null string.
-@end deftypevar
-
-@deftypevar {const char *} rl_special_prefixes
-The list of characters that are word break characters, but should be
-left in @var{text} when it is passed to the completion function.
-Programs can use this to help determine what kind of completing to do.
-For instance, Bash sets this variable to "$@@" so that it can complete
-shell variables and hostnames.
-@end deftypevar
-
-@deftypevar int rl_completion_query_items
-Up to this many items will be displayed in response to a
-possible-completions call. After that, readline asks the user if she is sure
-she wants to see them all. The default value is 100. A negative value
-indicates that Readline should never ask the user.
-@end deftypevar
-
-@deftypevar {int} rl_completion_append_character
-When a single completion alternative matches at the end of the command
-line, this character is appended to the inserted completion text. The
-default is a space character (@samp{ }). Setting this to the null
-character (@samp{\0}) prevents anything being appended automatically.
-This can be changed in application-specific completion functions to
-provide the ``most sensible word separator character'' according to
-an application-specific command line syntax specification.
-@end deftypevar
-
-@deftypevar int rl_completion_suppress_append
-If non-zero, @var{rl_completion_append_character} is not appended to
-matches at the end of the command line, as described above.
-It is set to 0 before any application-specific completion function
-is called, and may only be changed within such a function.
-@end deftypevar
-
-@deftypevar int rl_completion_quote_character
-When Readline is completing quoted text, as delimited by one of the
-characters in @var{rl_completer_quote_characters}, it sets this variable
-to the quoting character found.
-This is set before any application-specific completion function is called.
-@end deftypevar
-
-@deftypevar int rl_completion_suppress_quote
-If non-zero, Readline does not append a matching quote character when
-performing completion on a quoted string.
-It is set to 0 before any application-specific completion function
-is called, and may only be changed within such a function.
-@end deftypevar
-
-@deftypevar int rl_completion_found_quote
-When Readline is completing quoted text, it sets this variable
-to a non-zero value if the word being completed contains or is delimited
-by any quoting characters, including backslashes.
-This is set before any application-specific completion function is called.
-@end deftypevar
-
-@deftypevar int rl_completion_mark_symlink_dirs
-If non-zero, a slash will be appended to completed filenames that are
-symbolic links to directory names, subject to the value of the
-user-settable @var{mark-directories} variable.
-This variable exists so that application-specific completion functions
-can override the user's global preference (set via the
-@var{mark-symlinked-directories} Readline variable) if appropriate.
-This variable is set to the user's preference before any
-application-specific completion function is called, so unless that
-function modifies the value, the user's preferences are honored.
-@end deftypevar
-
-@deftypevar int rl_ignore_completion_duplicates
-If non-zero, then duplicates in the matches are removed.
-The default is 1.
-@end deftypevar
-
-@deftypevar int rl_filename_completion_desired
-Non-zero means that the results of the matches are to be treated as
-filenames. This is @emph{always} zero when completion is attempted,
-and can only be changed
-within an application-specific completion function. If it is set to a
-non-zero value by such a function, directory names have a slash appended
-and Readline attempts to quote completed filenames if they contain any
-characters in @code{rl_filename_quote_characters} and
-@code{rl_filename_quoting_desired} is set to a non-zero value.
-@end deftypevar
-
-@deftypevar int rl_filename_quoting_desired
-Non-zero means that the results of the matches are to be quoted using
-double quotes (or an application-specific quoting mechanism) if the
-completed filename contains any characters in
-@code{rl_filename_quote_chars}. This is @emph{always} non-zero
-when completion is attempted, and can only be changed within an
-application-specific completion function.
-The quoting is effected via a call to the function pointed to
-by @code{rl_filename_quoting_function}.
-@end deftypevar
-
-@deftypevar int rl_attempted_completion_over
-If an application-specific completion function assigned to
-@code{rl_attempted_completion_function} sets this variable to a non-zero
-value, Readline will not perform its default filename completion even
-if the application's completion function returns no matches.
-It should be set only by an application's completion function.
-@end deftypevar
-
-@deftypevar int rl_completion_type
-Set to a character describing the type of completion Readline is currently
-attempting; see the description of @code{rl_complete_internal()}
-(@pxref{Completion Functions}) for the list of characters.
-This is set to the appropriate value before any application-specific
-completion function is called, allowing such functions to present
-the same interface as @code{rl_complete()}.
-@end deftypevar
-
-@deftypevar int rl_inhibit_completion
-If this variable is non-zero, completion is inhibited. The completion
-character will be inserted as any other bound to @code{self-insert}.
-@end deftypevar
-
-@node A Short Completion Example
-@subsection A Short Completion Example
-
-Here is a small application demonstrating the use of the GNU Readline
-library. It is called @code{fileman}, and the source code resides in
-@file{examples/fileman.c}. This sample application provides
-completion of command names, line editing features, and access to the
-history list.
-
-@page
-@smallexample
-/* fileman.c -- A tiny application which demonstrates how to use the
- GNU Readline library. This application interactively allows users
- to manipulate files and their modes. */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <sys/errno.h>
-
-#include <readline/readline.h>
-#include <readline/history.h>
-
-extern char *xmalloc ();
-
-/* The names of functions that actually do the manipulation. */
-int com_list __P((char *));
-int com_view __P((char *));
-int com_rename __P((char *));
-int com_stat __P((char *));
-int com_pwd __P((char *));
-int com_delete __P((char *));
-int com_help __P((char *));
-int com_cd __P((char *));
-int com_quit __P((char *));
-
-/* A structure which contains information on the commands this program
- can understand. */
-
-typedef struct @{
- char *name; /* User printable name of the function. */
- rl_icpfunc_t *func; /* Function to call to do the job. */
- char *doc; /* Documentation for this function. */
-@} COMMAND;
-
-COMMAND commands[] = @{
- @{ "cd", com_cd, "Change to directory DIR" @},
- @{ "delete", com_delete, "Delete FILE" @},
- @{ "help", com_help, "Display this text" @},
- @{ "?", com_help, "Synonym for `help'" @},
- @{ "list", com_list, "List files in DIR" @},
- @{ "ls", com_list, "Synonym for `list'" @},
- @{ "pwd", com_pwd, "Print the current working directory" @},
- @{ "quit", com_quit, "Quit using Fileman" @},
- @{ "rename", com_rename, "Rename FILE to NEWNAME" @},
- @{ "stat", com_stat, "Print out statistics on FILE" @},
- @{ "view", com_view, "View the contents of FILE" @},
- @{ (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL @}
-@};
-
-/* Forward declarations. */
-char *stripwhite ();
-COMMAND *find_command ();
-
-/* The name of this program, as taken from argv[0]. */
-char *progname;
-
-/* When non-zero, this means the user is done using this program. */
-int done;
-
-char *
-dupstr (s)
- int s;
-@{
- char *r;
-
- r = xmalloc (strlen (s) + 1);
- strcpy (r, s);
- return (r);
-@}
-
-main (argc, argv)
- int argc;
- char **argv;
-@{
- char *line, *s;
-
- progname = argv[0];
-
- initialize_readline (); /* Bind our completer. */
-
- /* Loop reading and executing lines until the user quits. */
- for ( ; done == 0; )
- @{
- line = readline ("FileMan: ");
-
- if (!line)
- break;
-
- /* Remove leading and trailing whitespace from the line.
- Then, if there is anything left, add it to the history list
- and execute it. */
- s = stripwhite (line);
-
- if (*s)
- @{
- add_history (s);
- execute_line (s);
- @}
-
- free (line);
- @}
- exit (0);
-@}
-
-/* Execute a command line. */
-int
-execute_line (line)
- char *line;
-@{
- register int i;
- COMMAND *command;
- char *word;
-
- /* Isolate the command word. */
- i = 0;
- while (line[i] && whitespace (line[i]))
- i++;
- word = line + i;
-
- while (line[i] && !whitespace (line[i]))
- i++;
-
- if (line[i])
- line[i++] = '\0';
-
- command = find_command (word);
-
- if (!command)
- @{
- fprintf (stderr, "%s: No such command for FileMan.\n", word);
- return (-1);
- @}
-
- /* Get argument to command, if any. */
- while (whitespace (line[i]))
- i++;
-
- word = line + i;
-
- /* Call the function. */
- return ((*(command->func)) (word));
-@}
-
-/* Look up NAME as the name of a command, and return a pointer to that
- command. Return a NULL pointer if NAME isn't a command name. */
-COMMAND *
-find_command (name)
- char *name;
-@{
- register int i;
-
- for (i = 0; commands[i].name; i++)
- if (strcmp (name, commands[i].name) == 0)
- return (&commands[i]);
-
- return ((COMMAND *)NULL);
-@}
-
-/* Strip whitespace from the start and end of STRING. Return a pointer
- into STRING. */
-char *
-stripwhite (string)
- char *string;
-@{
- register char *s, *t;
-
- for (s = string; whitespace (*s); s++)
- ;
-
- if (*s == 0)
- return (s);
-
- t = s + strlen (s) - 1;
- while (t > s && whitespace (*t))
- t--;
- *++t = '\0';
-
- return s;
-@}
-
-/* **************************************************************** */
-/* */
-/* Interface to Readline Completion */
-/* */
-/* **************************************************************** */
-
-char *command_generator __P((const char *, int));
-char **fileman_completion __P((const char *, int, int));
-
-/* Tell the GNU Readline library how to complete. We want to try to
- complete on command names if this is the first word in the line, or
- on filenames if not. */
-initialize_readline ()
-@{
- /* Allow conditional parsing of the ~/.inputrc file. */
- rl_readline_name = "FileMan";
-
- /* Tell the completer that we want a crack first. */
- rl_attempted_completion_function = fileman_completion;
-@}
-
-/* Attempt to complete on the contents of TEXT. START and END
- bound the region of rl_line_buffer that contains the word to
- complete. TEXT is the word to complete. We can use the entire
- contents of rl_line_buffer in case we want to do some simple
- parsing. Returnthe array of matches, or NULL if there aren't any. */
-char **
-fileman_completion (text, start, end)
- const char *text;
- int start, end;
-@{
- char **matches;
-
- matches = (char **)NULL;
-
- /* If this word is at the start of the line, then it is a command
- to complete. Otherwise it is the name of a file in the current
- directory. */
- if (start == 0)
- matches = rl_completion_matches (text, command_generator);
-
- return (matches);
-@}
-
-/* Generator function for command completion. STATE lets us
- know whether to start from scratch; without any state
- (i.e. STATE == 0), then we start at the top of the list. */
-char *
-command_generator (text, state)
- const char *text;
- int state;
-@{
- static int list_index, len;
- char *name;
-
- /* If this is a new word to complete, initialize now. This
- includes saving the length of TEXT for efficiency, and
- initializing the index variable to 0. */
- if (!state)
- @{
- list_index = 0;
- len = strlen (text);
- @}
-
- /* Return the next name which partially matches from the
- command list. */
- while (name = commands[list_index].name)
- @{
- list_index++;
-
- if (strncmp (name, text, len) == 0)
- return (dupstr(name));
- @}
-
- /* If no names matched, then return NULL. */
- return ((char *)NULL);
-@}
-
-/* **************************************************************** */
-/* */
-/* FileMan Commands */
-/* */
-/* **************************************************************** */
-
-/* String to pass to system (). This is for the LIST, VIEW and RENAME
- commands. */
-static char syscom[1024];
-
-/* List the file(s) named in arg. */
-com_list (arg)
- char *arg;
-@{
- if (!arg)
- arg = "";
-
- sprintf (syscom, "ls -FClg %s", arg);
- return (system (syscom));
-@}
-
-com_view (arg)
- char *arg;
-@{
- if (!valid_argument ("view", arg))
- return 1;
-
- sprintf (syscom, "more %s", arg);
- return (system (syscom));
-@}
-
-com_rename (arg)
- char *arg;
-@{
- too_dangerous ("rename");
- return (1);
-@}
-
-com_stat (arg)
- char *arg;
-@{
- struct stat finfo;
-
- if (!valid_argument ("stat", arg))
- return (1);
-
- if (stat (arg, &finfo) == -1)
- @{
- perror (arg);
- return (1);
- @}
-
- printf ("Statistics for `%s':\n", arg);
-
- printf ("%s has %d link%s, and is %d byte%s in length.\n", arg,
- finfo.st_nlink,
- (finfo.st_nlink == 1) ? "" : "s",
- finfo.st_size,
- (finfo.st_size == 1) ? "" : "s");
- printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime));
- printf (" Last access at: %s", ctime (&finfo.st_atime));
- printf (" Last modified at: %s", ctime (&finfo.st_mtime));
- return (0);
-@}
-
-com_delete (arg)
- char *arg;
-@{
- too_dangerous ("delete");
- return (1);
-@}
-
-/* Print out help for ARG, or for all of the commands if ARG is
- not present. */
-com_help (arg)
- char *arg;
-@{
- register int i;
- int printed = 0;
-
- for (i = 0; commands[i].name; i++)
- @{
- if (!*arg || (strcmp (arg, commands[i].name) == 0))
- @{
- printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc);
- printed++;
- @}
- @}
-
- if (!printed)
- @{
- printf ("No commands match `%s'. Possibilties are:\n", arg);
-
- for (i = 0; commands[i].name; i++)
- @{
- /* Print in six columns. */
- if (printed == 6)
- @{
- printed = 0;
- printf ("\n");
- @}
-
- printf ("%s\t", commands[i].name);
- printed++;
- @}
-
- if (printed)
- printf ("\n");
- @}
- return (0);
-@}
-
-/* Change to the directory ARG. */
-com_cd (arg)
- char *arg;
-@{
- if (chdir (arg) == -1)
- @{
- perror (arg);
- return 1;
- @}
-
- com_pwd ("");
- return (0);
-@}
-
-/* Print out the current working directory. */
-com_pwd (ignore)
- char *ignore;
-@{
- char dir[1024], *s;
-
- s = getcwd (dir, sizeof(dir) - 1);
- if (s == 0)
- @{
- printf ("Error getting pwd: %s\n", dir);
- return 1;
- @}
-
- printf ("Current directory is %s\n", dir);
- return 0;
-@}
-
-/* The user wishes to quit using this program. Just set DONE
- non-zero. */
-com_quit (arg)
- char *arg;
-@{
- done = 1;
- return (0);
-@}
-
-/* Function which tells you that you can't do this. */
-too_dangerous (caller)
- char *caller;
-@{
- fprintf (stderr,
- "%s: Too dangerous for me to distribute.\n",
- caller);
- fprintf (stderr, "Write it yourself.\n");
-@}
-
-/* Return non-zero if ARG is a valid argument for CALLER,
- else print an error message and return zero. */
-int
-valid_argument (caller, arg)
- char *caller, *arg;
-@{
- if (!arg || !*arg)
- @{
- fprintf (stderr, "%s: Argument required.\n", caller);
- return (0);
- @}
-
- return (1);
-@}
-@end smallexample
diff --git a/lib/readline/doc/version.texi~ b/lib/readline/doc/version.texi~
deleted file mode 100644
index 8ce3bafd..00000000
--- a/lib/readline/doc/version.texi~
+++ /dev/null
@@ -1,10 +0,0 @@
-@ignore
-Copyright (C) 1988-2005 Free Software Foundation, Inc.
-@end ignore
-
-@set EDITION 5.1
-@set VERSION 5.1
-@set UPDATED 11 November 2005
-@set UPDATED-MONTH November 2005
-
-@set LASTCHANGE Fri Nov 11 19:50:51 EST 2005
diff --git a/lib/readline/histexpand.c~ b/lib/readline/histexpand.c~
deleted file mode 100644
index dd987262..00000000
--- a/lib/readline/histexpand.c~
+++ /dev/null
@@ -1,1593 +0,0 @@
-/* histexpand.c -- history expansion. */
-
-/* Copyright (C) 1989-2004 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- 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 <stdio.h>
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_UNISTD_H)
-# ifndef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include "rlmbutil.h"
-
-#include "history.h"
-#include "histlib.h"
-
-#include "rlshell.h"
-#include "xmalloc.h"
-
-#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>"
-#define HISTORY_QUOTE_CHARACTERS "\"'`"
-
-#define slashify_in_quotes "\\`\"$"
-
-typedef int _hist_search_func_t PARAMS((const char *, int));
-
-static char error_pointer;
-
-static char *subst_lhs;
-static char *subst_rhs;
-static int subst_lhs_len;
-static int subst_rhs_len;
-
-static char *get_history_word_specifier PARAMS((char *, char *, int *));
-static char *history_find_word PARAMS((char *, int));
-static int history_tokenize_word PARAMS((const char *, int));
-static char *history_substring PARAMS((const char *, int, int));
-
-static char *quote_breaks PARAMS((char *));
-
-/* Variables exported by this file. */
-/* The character that represents the start of a history expansion
- request. This is usually `!'. */
-char history_expansion_char = '!';
-
-/* The character that invokes word substitution if found at the start of
- a line. This is usually `^'. */
-char history_subst_char = '^';
-
-/* During tokenization, if this character is seen as the first character
- of a word, then it, and all subsequent characters upto a newline are
- ignored. For a Bourne shell, this should be '#'. Bash special cases
- the interactive comment character to not be a comment delimiter. */
-char history_comment_char = '\0';
-
-/* The list of characters which inhibit the expansion of text if found
- immediately following history_expansion_char. */
-char *history_no_expand_chars = " \t\n\r=";
-
-/* If set to a non-zero value, single quotes inhibit history expansion.
- The default is 0. */
-int history_quotes_inhibit_expansion = 0;
-
-/* Used to split words by history_tokenize_internal. */
-char *history_word_delimiters = HISTORY_WORD_DELIMITERS;
-
-/* If set, this points to a function that is called to verify that a
- particular history expansion should be performed. */
-rl_linebuf_func_t *history_inhibit_expansion_function;
-
-/* **************************************************************** */
-/* */
-/* History Expansion */
-/* */
-/* **************************************************************** */
-
-/* Hairy history expansion on text, not tokens. This is of general
- use, and thus belongs in this library. */
-
-/* The last string searched for by a !?string? search. */
-static char *search_string;
-
-/* The last string matched by a !?string? search. */
-static char *search_match;
-
-/* Return the event specified at TEXT + OFFSET modifying OFFSET to
- point to after the event specifier. Just a pointer to the history
- line is returned; NULL is returned in the event of a bad specifier.
- You pass STRING with *INDEX equal to the history_expansion_char that
- begins this specification.
- DELIMITING_QUOTE is a character that is allowed to end the string
- specification for what to search for in addition to the normal
- characters `:', ` ', `\t', `\n', and sometimes `?'.
- So you might call this function like:
- line = get_history_event ("!echo:p", &index, 0); */
-char *
-get_history_event (string, caller_index, delimiting_quote)
- const char *string;
- int *caller_index;
- int delimiting_quote;
-{
- register int i;
- register char c;
- HIST_ENTRY *entry;
- int which, sign, local_index, substring_okay;
- _hist_search_func_t *search_func;
- char *temp;
-
- /* The event can be specified in a number of ways.
-
- !! the previous command
- !n command line N
- !-n current command-line minus N
- !str the most recent command starting with STR
- !?str[?]
- the most recent command containing STR
-
- All values N are determined via HISTORY_BASE. */
-
- i = *caller_index;
-
- if (string[i] != history_expansion_char)
- return ((char *)NULL);
-
- /* Move on to the specification. */
- i++;
-
- sign = 1;
- substring_okay = 0;
-
-#define RETURN_ENTRY(e, w) \
- return ((e = history_get (w)) ? e->line : (char *)NULL)
-
- /* Handle !! case. */
- if (string[i] == history_expansion_char)
- {
- i++;
- which = history_base + (history_length - 1);
- *caller_index = i;
- RETURN_ENTRY (entry, which);
- }
-
- /* Hack case of numeric line specification. */
- if (string[i] == '-')
- {
- sign = -1;
- i++;
- }
-
- if (_rl_digit_p (string[i]))
- {
- /* Get the extent of the digits and compute the value. */
- for (which = 0; _rl_digit_p (string[i]); i++)
- which = (which * 10) + _rl_digit_value (string[i]);
-
- *caller_index = i;
-
- if (sign < 0)
- which = (history_length + history_base) - which;
-
- RETURN_ENTRY (entry, which);
- }
-
- /* This must be something to search for. If the spec begins with
- a '?', then the string may be anywhere on the line. Otherwise,
- the string must be found at the start of a line. */
- if (string[i] == '?')
- {
- substring_okay++;
- i++;
- }
-
- /* Only a closing `?' or a newline delimit a substring search string. */
- for (local_index = i; c = string[i]; i++)
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- int v;
- mbstate_t ps;
-
- memset (&ps, 0, sizeof (mbstate_t));
- /* These produce warnings because we're passing a const string to a
- function that takes a non-const string. */
- _rl_adjust_point ((char *)string, i, &ps);
- if ((v = _rl_get_char_len ((char *)string + i, &ps)) > 1)
- {
- i += v - 1;
- continue;
- }
- }
-
-#endif /* HANDLE_MULTIBYTE */
- if ((!substring_okay && (whitespace (c) || c == ':' ||
- (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) ||
- string[i] == delimiting_quote)) ||
- string[i] == '\n' ||
- (substring_okay && string[i] == '?'))
- break;
- }
-
- which = i - local_index;
- temp = (char *)xmalloc (1 + which);
- if (which)
- strncpy (temp, string + local_index, which);
- temp[which] = '\0';
-
- if (substring_okay && string[i] == '?')
- i++;
-
- *caller_index = i;
-
-#define FAIL_SEARCH() \
- do { \
- history_offset = history_length; free (temp) ; return (char *)NULL; \
- } while (0)
-
- /* If there is no search string, try to use the previous search string,
- if one exists. If not, fail immediately. */
- if (*temp == '\0' && substring_okay)
- {
- if (search_string)
- {
- free (temp);
- temp = savestring (search_string);
- }
- else
- FAIL_SEARCH ();
- }
-
- search_func = substring_okay ? history_search : history_search_prefix;
- while (1)
- {
- local_index = (*search_func) (temp, -1);
-
- if (local_index < 0)
- FAIL_SEARCH ();
-
- if (local_index == 0 || substring_okay)
- {
- entry = current_history ();
- history_offset = history_length;
-
- /* If this was a substring search, then remember the
- string that we matched for word substitution. */
- if (substring_okay)
- {
- FREE (search_string);
- search_string = temp;
-
- FREE (search_match);
- search_match = history_find_word (entry->line, local_index);
- }
- else
- free (temp);
-
- return (entry->line);
- }
-
- if (history_offset)
- history_offset--;
- else
- FAIL_SEARCH ();
- }
-#undef FAIL_SEARCH
-#undef RETURN_ENTRY
-}
-
-/* Function for extracting single-quoted strings. Used for inhibiting
- history expansion within single quotes. */
-
-/* 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
- to the closing single quote. */
-static void
-hist_string_extract_single_quoted (string, sindex)
- char *string;
- int *sindex;
-{
- register int i;
-
- for (i = *sindex; string[i] && string[i] != '\''; i++)
- ;
-
- *sindex = i;
-}
-
-static char *
-quote_breaks (s)
- char *s;
-{
- register char *p, *r;
- char *ret;
- int len = 3;
-
- for (p = s; p && *p; p++, len++)
- {
- if (*p == '\'')
- len += 3;
- else if (whitespace (*p) || *p == '\n')
- len += 2;
- }
-
- r = ret = (char *)xmalloc (len);
- *r++ = '\'';
- for (p = s; p && *p; )
- {
- if (*p == '\'')
- {
- *r++ = '\'';
- *r++ = '\\';
- *r++ = '\'';
- *r++ = '\'';
- p++;
- }
- else if (whitespace (*p) || *p == '\n')
- {
- *r++ = '\'';
- *r++ = *p++;
- *r++ = '\'';
- }
- else
- *r++ = *p++;
- }
- *r++ = '\'';
- *r = '\0';
- return ret;
-}
-
-static char *
-hist_error(s, start, current, errtype)
- char *s;
- int start, current, errtype;
-{
- char *temp;
- const char *emsg;
- int ll, elen;
-
- ll = current - start;
-
- switch (errtype)
- {
- case EVENT_NOT_FOUND:
- emsg = "event not found";
- elen = 15;
- break;
- case BAD_WORD_SPEC:
- emsg = "bad word specifier";
- elen = 18;
- break;
- case SUBST_FAILED:
- emsg = "substitution failed";
- elen = 19;
- break;
- case BAD_MODIFIER:
- emsg = "unrecognized history modifier";
- elen = 29;
- break;
- case NO_PREV_SUBST:
- emsg = "no previous substitution";
- elen = 24;
- break;
- default:
- emsg = "unknown expansion error";
- elen = 23;
- break;
- }
-
- temp = (char *)xmalloc (ll + elen + 3);
- strncpy (temp, s + start, ll);
- temp[ll] = ':';
- temp[ll + 1] = ' ';
- strcpy (temp + ll + 2, emsg);
- return (temp);
-}
-
-/* Get a history substitution string from STR starting at *IPTR
- and return it. The length is returned in LENPTR.
-
- A backslash can quote the delimiter. If the string is the
- empty string, the previous pattern is used. If there is
- no previous pattern for the lhs, the last history search
- string is used.
-
- If IS_RHS is 1, we ignore empty strings and set the pattern
- to "" anyway. subst_lhs is not changed if the lhs is empty;
- subst_rhs is allowed to be set to the empty string. */
-
-static char *
-get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr)
- char *str;
- int *iptr, delimiter, is_rhs, *lenptr;
-{
- register int si, i, j, k;
- char *s;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps;
-#endif
-
- s = (char *)NULL;
- i = *iptr;
-
-#if defined (HANDLE_MULTIBYTE)
- memset (&ps, 0, sizeof (mbstate_t));
- _rl_adjust_point (str, i, &ps);
-#endif
-
- for (si = i; str[si] && str[si] != delimiter; si++)
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- int v;
- if ((v = _rl_get_char_len (str + si, &ps)) > 1)
- si += v - 1;
- else if (str[si] == '\\' && str[si + 1] == delimiter)
- si++;
- }
- else
-#endif /* HANDLE_MULTIBYTE */
- if (str[si] == '\\' && str[si + 1] == delimiter)
- si++;
-
- if (si > i || is_rhs)
- {
- s = (char *)xmalloc (si - i + 1);
- for (j = 0, k = i; k < si; j++, k++)
- {
- /* Remove a backslash quoting the search string delimiter. */
- if (str[k] == '\\' && str[k + 1] == delimiter)
- k++;
- s[j] = str[k];
- }
- s[j] = '\0';
- if (lenptr)
- *lenptr = j;
- }
-
- i = si;
- if (str[i])
- i++;
- *iptr = i;
-
- return s;
-}
-
-static void
-postproc_subst_rhs ()
-{
- char *new;
- int i, j, new_size;
-
- new = (char *)xmalloc (new_size = subst_rhs_len + subst_lhs_len);
- for (i = j = 0; i < subst_rhs_len; i++)
- {
- if (subst_rhs[i] == '&')
- {
- if (j + subst_lhs_len >= new_size)
- new = (char *)xrealloc (new, (new_size = new_size * 2 + subst_lhs_len));
- strcpy (new + j, subst_lhs);
- j += subst_lhs_len;
- }
- else
- {
- /* a single backslash protects the `&' from lhs interpolation */
- if (subst_rhs[i] == '\\' && subst_rhs[i + 1] == '&')
- i++;
- if (j >= new_size)
- new = (char *)xrealloc (new, new_size *= 2);
- new[j++] = subst_rhs[i];
- }
- }
- new[j] = '\0';
- free (subst_rhs);
- subst_rhs = new;
- subst_rhs_len = j;
-}
-
-/* Expand the bulk of a history specifier starting at STRING[START].
- Returns 0 if everything is OK, -1 if an error occurred, and 1
- if the `p' modifier was supplied and the caller should just print
- the returned string. Returns the new index into string in
- *END_INDEX_PTR, and the expanded specifier in *RET_STRING. */
-static int
-history_expand_internal (string, start, end_index_ptr, ret_string, current_line)
- char *string;
- int start, *end_index_ptr;
- char **ret_string;
- char *current_line; /* for !# */
-{
- int i, n, starting_index;
- int substitute_globally, subst_bywords, want_quotes, print_only;
- char *event, *temp, *result, *tstr, *t, c, *word_spec;
- int result_len;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps;
-
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
-
- result = (char *)xmalloc (result_len = 128);
-
- i = start;
-
- /* If it is followed by something that starts a word specifier,
- then !! is implied as the event specifier. */
-
- if (member (string[i + 1], ":$*%^"))
- {
- char fake_s[3];
- int fake_i = 0;
- i++;
- fake_s[0] = fake_s[1] = history_expansion_char;
- fake_s[2] = '\0';
- event = get_history_event (fake_s, &fake_i, 0);
- }
- else if (string[i + 1] == '#')
- {
- i += 2;
- event = current_line;
- }
- else
- {
- int quoted_search_delimiter = 0;
-
- /* If the character before this `!' is a double or single
- quote, then this expansion takes place inside of the
- quoted string. If we have to search for some text ("!foo"),
- allow the delimiter to end the search string. */
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- int c, l;
- l = _rl_find_prev_mbchar (string, i, MB_FIND_ANY);
- c = string[l];
- /* XXX - original patch had i - 1 ??? If i == 0 it would fail. */
- if (i && (c == '\'' || c == '"'))
- quoted_search_delimiter = c;
- }
- else
-#endif /* HANDLE_MULTIBYTE */
- if (i && (string[i - 1] == '\'' || string[i - 1] == '"'))
- quoted_search_delimiter = string[i - 1];
-
- event = get_history_event (string, &i, quoted_search_delimiter);
- }
-
- if (event == 0)
- {
- *ret_string = hist_error (string, start, i, EVENT_NOT_FOUND);
- free (result);
- return (-1);
- }
-
- /* If a word specifier is found, then do what that requires. */
- starting_index = i;
- word_spec = get_history_word_specifier (string, event, &i);
-
- /* There is no such thing as a `malformed word specifier'. However,
- it is possible for a specifier that has no match. In that case,
- we complain. */
- if (word_spec == (char *)&error_pointer)
- {
- *ret_string = hist_error (string, starting_index, i, BAD_WORD_SPEC);
- free (result);
- return (-1);
- }
-
- /* If no word specifier, than the thing of interest was the event. */
- temp = word_spec ? savestring (word_spec) : savestring (event);
- FREE (word_spec);
-
- /* Perhaps there are other modifiers involved. Do what they say. */
- want_quotes = substitute_globally = subst_bywords = print_only = 0;
- starting_index = i;
-
- while (string[i] == ':')
- {
- c = string[i + 1];
-
- if (c == 'g' || c == 'a')
- {
- substitute_globally = 1;
- i++;
- c = string[i + 1];
- }
- else if (c == 'G')
- {
- subst_bywords = 1;
- i++;
- c = string[i + 1];
- }
-
- switch (c)
- {
- default:
- *ret_string = hist_error (string, i+1, i+2, BAD_MODIFIER);
- free (result);
- free (temp);
- return -1;
-
- case 'q':
- want_quotes = 'q';
- break;
-
- case 'x':
- want_quotes = 'x';
- break;
-
- /* :p means make this the last executed line. So we
- return an error state after adding this line to the
- history. */
- case 'p':
- print_only++;
- break;
-
- /* :t discards all but the last part of the pathname. */
- case 't':
- tstr = strrchr (temp, '/');
- if (tstr)
- {
- tstr++;
- t = savestring (tstr);
- free (temp);
- temp = t;
- }
- break;
-
- /* :h discards the last part of a pathname. */
- case 'h':
- tstr = strrchr (temp, '/');
- if (tstr)
- *tstr = '\0';
- break;
-
- /* :r discards the suffix. */
- case 'r':
- tstr = strrchr (temp, '.');
- if (tstr)
- *tstr = '\0';
- break;
-
- /* :e discards everything but the suffix. */
- case 'e':
- tstr = strrchr (temp, '.');
- if (tstr)
- {
- t = savestring (tstr);
- free (temp);
- temp = t;
- }
- break;
-
- /* :s/this/that substitutes `that' for the first
- occurrence of `this'. :gs/this/that substitutes `that'
- for each occurrence of `this'. :& repeats the last
- substitution. :g& repeats the last substitution
- globally. */
-
- case '&':
- case 's':
- {
- char *new_event;
- int delimiter, failed, si, l_temp, ws, we;
-
- if (c == 's')
- {
- if (i + 2 < (int)strlen (string))
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- _rl_adjust_point (string, i + 2, &ps);
- if (_rl_get_char_len (string + i + 2, &ps) > 1)
- delimiter = 0;
- else
- delimiter = string[i + 2];
- }
- else
-#endif /* HANDLE_MULTIBYTE */
- delimiter = string[i + 2];
- }
- else
- break; /* no search delimiter */
-
- i += 3;
-
- t = get_subst_pattern (string, &i, delimiter, 0, &subst_lhs_len);
- /* An empty substitution lhs with no previous substitution
- uses the last search string as the lhs. */
- if (t)
- {
- FREE (subst_lhs);
- subst_lhs = t;
- }
- else if (!subst_lhs)
- {
- if (search_string && *search_string)
- {
- subst_lhs = savestring (search_string);
- subst_lhs_len = strlen (subst_lhs);
- }
- else
- {
- subst_lhs = (char *) NULL;
- subst_lhs_len = 0;
- }
- }
-
- FREE (subst_rhs);
- subst_rhs = get_subst_pattern (string, &i, delimiter, 1, &subst_rhs_len);
-
- /* If `&' appears in the rhs, it's supposed to be replaced
- with the lhs. */
- if (member ('&', subst_rhs))
- postproc_subst_rhs ();
- }
- else
- i += 2;
-
- /* If there is no lhs, the substitution can't succeed. */
- if (subst_lhs_len == 0)
- {
- *ret_string = hist_error (string, starting_index, i, NO_PREV_SUBST);
- free (result);
- free (temp);
- return -1;
- }
-
- l_temp = strlen (temp);
- /* Ignore impossible cases. */
- if (subst_lhs_len > l_temp)
- {
- *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
- free (result);
- free (temp);
- return (-1);
- }
-
- /* Find the first occurrence of THIS in TEMP. */
- /* Substitute SUBST_RHS for SUBST_LHS in TEMP. There are three
- cases to consider:
-
- 1. substitute_globally == subst_bywords == 0
- 2. substitute_globally == 1 && subst_bywords == 0
- 3. substitute_globally == 0 && subst_bywords == 1
-
- In the first case, we substitute for the first occurrence only.
- In the second case, we substitute for every occurrence.
- In the third case, we tokenize into words and substitute the
- first occurrence of each word. */
-
- si = we = 0;
- for (failed = 1; (si + subst_lhs_len) <= l_temp; si++)
- {
- /* First skip whitespace and find word boundaries if
- we're past the end of the word boundary we found
- the last time. */
- if (subst_bywords && si > we)
- {
- for (; temp[si] && whitespace (temp[si]); si++)
- ;
- ws = si;
- we = history_tokenize_word (temp, si);
- }
-
- if (STREQN (temp+si, subst_lhs, subst_lhs_len))
- {
- int len = subst_rhs_len - subst_lhs_len + l_temp;
- new_event = (char *)xmalloc (1 + len);
- strncpy (new_event, temp, si);
- strncpy (new_event + si, subst_rhs, subst_rhs_len);
- strncpy (new_event + si + subst_rhs_len,
- temp + si + subst_lhs_len,
- l_temp - (si + subst_lhs_len));
- new_event[len] = '\0';
- free (temp);
- temp = new_event;
-
- failed = 0;
-
- if (substitute_globally)
- {
- /* Reported to fix a bug that causes it to skip every
- other match when matching a single character. Was
- si += subst_rhs_len previously. */
- si += subst_rhs_len - 1;
- l_temp = strlen (temp);
- substitute_globally++;
- continue;
- }
- else if (subst_bywords)
- {
- si = we;
- l_temp = strlen (temp);
- continue;
- }
- else
- break;
- }
- }
-
- if (substitute_globally > 1)
- {
- substitute_globally = 0;
- continue; /* don't want to increment i */
- }
-
- if (failed == 0)
- continue; /* don't want to increment i */
-
- *ret_string = hist_error (string, starting_index, i, SUBST_FAILED);
- free (result);
- free (temp);
- return (-1);
- }
- }
- i += 2;
- }
- /* Done with modfiers. */
- /* Believe it or not, we have to back the pointer up by one. */
- --i;
-
- if (want_quotes)
- {
- char *x;
-
- if (want_quotes == 'q')
- x = sh_single_quote (temp);
- else if (want_quotes == 'x')
- x = quote_breaks (temp);
- else
- x = savestring (temp);
-
- free (temp);
- temp = x;
- }
-
- n = strlen (temp);
- if (n >= result_len)
- result = (char *)xrealloc (result, n + 2);
- strcpy (result, temp);
- free (temp);
-
- *end_index_ptr = i;
- *ret_string = result;
- return (print_only);
-}
-
-/* Expand the string STRING, placing the result into OUTPUT, a pointer
- to a string. Returns:
-
- -1) If there was an error in expansion.
- 0) If no expansions took place (or, if the only change in
- the text was the de-slashifying of the history expansion
- character)
- 1) If expansions did take place
- 2) If the `p' modifier was given and the caller should print the result
-
- If an error ocurred in expansion, then OUTPUT contains a descriptive
- error message. */
-
-#define ADD_STRING(s) \
- do \
- { \
- int sl = strlen (s); \
- j += sl; \
- if (j >= result_len) \
- { \
- while (j >= result_len) \
- result_len += 128; \
- result = (char *)xrealloc (result, result_len); \
- } \
- strcpy (result + j - sl, s); \
- } \
- while (0)
-
-#define ADD_CHAR(c) \
- do \
- { \
- if (j >= result_len - 1) \
- result = (char *)xrealloc (result, result_len += 64); \
- result[j++] = c; \
- result[j] = '\0'; \
- } \
- while (0)
-
-int
-history_expand (hstring, output)
- char *hstring;
- char **output;
-{
- register int j;
- int i, r, l, passc, cc, modified, eindex, only_printing, dquote;
- char *string;
-
- /* The output string, and its length. */
- int result_len;
- char *result;
-
-#if defined (HANDLE_MULTIBYTE)
- char mb[MB_LEN_MAX];
- mbstate_t ps;
-#endif
-
- /* Used when adding the string. */
- char *temp;
-
- if (output == 0)
- return 0;
-
- /* Setting the history expansion character to 0 inhibits all
- history expansion. */
- if (history_expansion_char == 0)
- {
- *output = savestring (hstring);
- return (0);
- }
-
- /* Prepare the buffer for printing error messages. */
- result = (char *)xmalloc (result_len = 256);
- result[0] = '\0';
-
- only_printing = modified = 0;
- l = strlen (hstring);
-
- /* Grovel the string. Only backslash and single quotes can quote the
- history escape character. We also handle arg specifiers. */
-
- /* Before we grovel forever, see if the history_expansion_char appears
- anywhere within the text. */
-
- /* The quick substitution character is a history expansion all right. That
- is to say, "^this^that^" is equivalent to "!!:s^this^that^", and in fact,
- that is the substitution that we do. */
- if (hstring[0] == history_subst_char)
- {
- string = (char *)xmalloc (l + 5);
-
- string[0] = string[1] = history_expansion_char;
- string[2] = ':';
- string[3] = 's';
- strcpy (string + 4, hstring);
- l += 4;
- }
- else
- {
-#if defined (HANDLE_MULTIBYTE)
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
-
- string = hstring;
- /* If not quick substitution, still maybe have to do expansion. */
-
- /* `!' followed by one of the characters in history_no_expand_chars
- is NOT an expansion. */
- for (i = dquote = 0; string[i]; i++)
- {
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- int v;
- v = _rl_get_char_len (string + i, &ps);
- if (v > 1)
- {
- i += v - 1;
- continue;
- }
- }
-#endif /* HANDLE_MULTIBYTE */
-
- cc = string[i + 1];
- /* The history_comment_char, if set, appearing at the beginning
- of a word signifies that the rest of the line should not have
- history expansion performed on it.
- Skip the rest of the line and break out of the loop. */
- if (history_comment_char && string[i] == history_comment_char &&
- (i == 0 || member (string[i - 1], history_word_delimiters)))
- {
- while (string[i])
- i++;
- break;
- }
- else if (string[i] == history_expansion_char)
- {
- if (!cc || member (cc, history_no_expand_chars))
- continue;
- /* If the calling application has set
- history_inhibit_expansion_function to a function that checks
- for special cases that should not be history expanded,
- call the function and skip the expansion if it returns a
- non-zero value. */
- else if (history_inhibit_expansion_function &&
- (*history_inhibit_expansion_function) (string, i))
- continue;
- else
- break;
- }
- /* Shell-like quoting: allow backslashes to quote double quotes
- inside a double-quoted string. */
- else if (dquote && string[i] == '\\' && cc == '"')
- i++;
- /* More shell-like quoting: if we're paying attention to single
- quotes and letting them quote the history expansion character,
- then we need to pay attention to double quotes, because single
- quotes are not special inside double-quoted strings. */
- else if (history_quotes_inhibit_expansion && string[i] == '"')
- {
- dquote = 1 - dquote;
- }
- else if (dquote == 0 && history_quotes_inhibit_expansion && string[i] == '\'')
- {
- /* If this is bash, single quotes inhibit history expansion. */
- i++;
- hist_string_extract_single_quoted (string, &i);
- }
- else if (history_quotes_inhibit_expansion && string[i] == '\\')
- {
- /* If this is bash, allow backslashes to quote single
- quotes and the history expansion character. */
- if (cc == '\'' || cc == history_expansion_char)
- i++;
- }
-
- }
-
- if (string[i] != history_expansion_char)
- {
- free (result);
- *output = savestring (string);
- return (0);
- }
- }
-
- /* Extract and perform the substitution. */
- for (passc = dquote = i = j = 0; i < l; i++)
- {
- int tchar = string[i];
-
- if (passc)
- {
- passc = 0;
- ADD_CHAR (tchar);
- continue;
- }
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- int k, c;
-
- c = tchar;
- memset (mb, 0, sizeof (mb));
- for (k = 0; k < MB_LEN_MAX; k++)
- {
- mb[k] = (char)c;
- memset (&ps, 0, sizeof (mbstate_t));
- if (_rl_get_char_len (mb, &ps) == -2)
- c = string[++i];
- else
- break;
- }
- if (strlen (mb) > 1)
- {
- ADD_STRING (mb);
- break;
- }
- }
-#endif /* HANDLE_MULTIBYTE */
-
- if (tchar == history_expansion_char)
- tchar = -3;
- else if (tchar == history_comment_char)
- tchar = -2;
-
- switch (tchar)
- {
- default:
- ADD_CHAR (string[i]);
- break;
-
- case '\\':
- passc++;
- ADD_CHAR (tchar);
- break;
-
- case '"':
- dquote = 1 - dquote;
- ADD_CHAR (tchar);
- break;
-
- case '\'':
- {
- /* If history_quotes_inhibit_expansion is set, single quotes
- inhibit history expansion. */
- if (dquote == 0 && history_quotes_inhibit_expansion)
- {
- int quote, slen;
-
- quote = i++;
- hist_string_extract_single_quoted (string, &i);
-
- slen = i - quote + 2;
- temp = (char *)xmalloc (slen);
- strncpy (temp, string + quote, slen);
- temp[slen - 1] = '\0';
- ADD_STRING (temp);
- free (temp);
- }
- else
- ADD_CHAR (string[i]);
- break;
- }
-
- case -2: /* history_comment_char */
- if (i == 0 || member (string[i - 1], history_word_delimiters))
- {
- temp = (char *)xmalloc (l - i + 1);
- strcpy (temp, string + i);
- ADD_STRING (temp);
- free (temp);
- i = l;
- }
- else
- ADD_CHAR (string[i]);
- break;
-
- case -3: /* history_expansion_char */
- cc = string[i + 1];
-
- /* If the history_expansion_char is followed by one of the
- characters in history_no_expand_chars, then it is not a
- candidate for expansion of any kind. */
- if (member (cc, history_no_expand_chars))
- {
- ADD_CHAR (string[i]);
- break;
- }
-
-#if defined (NO_BANG_HASH_MODIFIERS)
- /* There is something that is listed as a `word specifier' in csh
- documentation which means `the expanded text to this point'.
- That is not a word specifier, it is an event specifier. If we
- don't want to allow modifiers with `!#', just stick the current
- output line in again. */
- if (cc == '#')
- {
- if (result)
- {
- temp = (char *)xmalloc (1 + strlen (result));
- strcpy (temp, result);
- ADD_STRING (temp);
- free (temp);
- }
- i++;
- break;
- }
-#endif
-
- r = history_expand_internal (string, i, &eindex, &temp, result);
- if (r < 0)
- {
- *output = temp;
- free (result);
- if (string != hstring)
- free (string);
- return -1;
- }
- else
- {
- if (temp)
- {
- modified++;
- if (*temp)
- ADD_STRING (temp);
- free (temp);
- }
- only_printing = r == 1;
- i = eindex;
- }
- break;
- }
- }
-
- *output = result;
- if (string != hstring)
- free (string);
-
- if (only_printing)
- {
-#if 0
- add_history (result);
-#endif
- return (2);
- }
-
- return (modified != 0);
-}
-
-/* Return a consed string which is the word specified in SPEC, and found
- in FROM. NULL is returned if there is no spec. The address of
- ERROR_POINTER is returned if the word specified cannot be found.
- CALLER_INDEX is the offset in SPEC to start looking; it is updated
- to point to just after the last character parsed. */
-static char *
-get_history_word_specifier (spec, from, caller_index)
- char *spec, *from;
- int *caller_index;
-{
- register int i = *caller_index;
- int first, last;
- int expecting_word_spec = 0;
- char *result;
-
- /* The range of words to return doesn't exist yet. */
- first = last = 0;
- result = (char *)NULL;
-
- /* If we found a colon, then this *must* be a word specification. If
- it isn't, then it is an error. */
- if (spec[i] == ':')
- {
- i++;
- expecting_word_spec++;
- }
-
- /* Handle special cases first. */
-
- /* `%' is the word last searched for. */
- if (spec[i] == '%')
- {
- *caller_index = i + 1;
- return (search_match ? savestring (search_match) : savestring (""));
- }
-
- /* `*' matches all of the arguments, but not the command. */
- if (spec[i] == '*')
- {
- *caller_index = i + 1;
- result = history_arg_extract (1, '$', from);
- return (result ? result : savestring (""));
- }
-
- /* `$' is last arg. */
- if (spec[i] == '$')
- {
- *caller_index = i + 1;
- return (history_arg_extract ('$', '$', from));
- }
-
- /* Try to get FIRST and LAST figured out. */
-
- if (spec[i] == '-')
- first = 0;
- else if (spec[i] == '^')
- {
- first = 1;
- i++;
- }
- else if (_rl_digit_p (spec[i]) && expecting_word_spec)
- {
- for (first = 0; _rl_digit_p (spec[i]); i++)
- first = (first * 10) + _rl_digit_value (spec[i]);
- }
- else
- return ((char *)NULL); /* no valid `first' for word specifier */
-
- if (spec[i] == '^' || spec[i] == '*')
- {
- last = (spec[i] == '^') ? 1 : '$'; /* x* abbreviates x-$ */
- i++;
- }
- else if (spec[i] != '-')
- last = first;
- else
- {
- i++;
-
- if (_rl_digit_p (spec[i]))
- {
- for (last = 0; _rl_digit_p (spec[i]); i++)
- last = (last * 10) + _rl_digit_value (spec[i]);
- }
- else if (spec[i] == '$')
- {
- i++;
- last = '$';
- }
-#if 0
- else if (!spec[i] || spec[i] == ':')
- /* check against `:' because there could be a modifier separator */
-#else
- else
- /* csh seems to allow anything to terminate the word spec here,
- leaving it as an abbreviation. */
-#endif
- last = -1; /* x- abbreviates x-$ omitting word `$' */
- }
-
- *caller_index = i;
-
- if (last >= first || last == '$' || last < 0)
- result = history_arg_extract (first, last, from);
-
- return (result ? result : (char *)&error_pointer);
-}
-
-/* Extract the args specified, starting at FIRST, and ending at LAST.
- The args are taken from STRING. If either FIRST or LAST is < 0,
- then make that arg count from the right (subtract from the number of
- tokens, so that FIRST = -1 means the next to last token on the line).
- If LAST is `$' the last arg from STRING is used. */
-char *
-history_arg_extract (first, last, string)
- int first, last;
- const char *string;
-{
- register int i, len;
- char *result;
- int size, offset;
- char **list;
-
- /* XXX - think about making history_tokenize return a struct array,
- each struct in array being a string and a length to avoid the
- calls to strlen below. */
- if ((list = history_tokenize (string)) == NULL)
- return ((char *)NULL);
-
- for (len = 0; list[len]; len++)
- ;
-
- if (last < 0)
- last = len + last - 1;
-
- if (first < 0)
- first = len + first - 1;
-
- if (last == '$')
- last = len - 1;
-
- if (first == '$')
- first = len - 1;
-
- last++;
-
- if (first >= len || last > len || first < 0 || last < 0 || first > last)
- result = ((char *)NULL);
- else
- {
- for (size = 0, i = first; i < last; i++)
- size += strlen (list[i]) + 1;
- result = (char *)xmalloc (size + 1);
- result[0] = '\0';
-
- for (i = first, offset = 0; i < last; i++)
- {
- strcpy (result + offset, list[i]);
- offset += strlen (list[i]);
- if (i + 1 < last)
- {
- result[offset++] = ' ';
- result[offset] = 0;
- }
- }
- }
-
- for (i = 0; i < len; i++)
- free (list[i]);
- free (list);
-
- return (result);
-}
-
-static int
-history_tokenize_word (string, ind)
- const char *string;
- int ind;
-{
- register int i;
- int delimiter;
-
- i = ind;
- delimiter = 0;
-
- if (member (string[i], "()\n"))
- {
- i++;
- return i;
- }
-
- if (member (string[i], "<>;&|$"))
- {
- int peek = string[i + 1];
-
- if (peek == string[i] && peek != '$')
- {
- if (peek == '<' && string[i + 2] == '-')
- i++;
- else if (peek == '<' && string[i + 2] == '<')
- i++;
- i += 2;
- return i;
- }
- else
- {
- if ((peek == '&' && (string[i] == '>' || string[i] == '<')) ||
- (peek == '>' && string[i] == '&') ||
- (peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */
- (peek == '(' && string[i] == '$')) /* ) */
- {
- i += 2;
- return i;
- }
- }
-
- if (string[i] != '$')
- {
- i++;
- return i;
- }
- }
-
- /* Get word from string + i; */
-
- if (member (string[i], HISTORY_QUOTE_CHARACTERS))
- delimiter = string[i++];
-
- for (; string[i]; i++)
- {
- if (string[i] == '\\' && string[i + 1] == '\n')
- {
- i++;
- continue;
- }
-
- if (string[i] == '\\' && delimiter != '\'' &&
- (delimiter != '"' || member (string[i], slashify_in_quotes)))
- {
- i++;
- continue;
- }
-
- if (delimiter && string[i] == delimiter)
- {
- delimiter = 0;
- continue;
- }
-
- if (!delimiter && (member (string[i], history_word_delimiters)))
- break;
-
- if (!delimiter && member (string[i], HISTORY_QUOTE_CHARACTERS))
- delimiter = string[i];
- }
-
- return i;
-}
-
-static char *
-history_substring (string, start, end)
- const char *string;
- int start, end;
-{
- register int len;
- register char *result;
-
- len = end - start;
- result = (char *)xmalloc (len + 1);
- strncpy (result, string + start, len);
- result[len] = '\0';
- return result;
-}
-
-/* Parse STRING into tokens and return an array of strings. If WIND is
- not -1 and INDP is not null, we also want the word surrounding index
- WIND. The position in the returned array of strings is returned in
- *INDP. */
-static char **
-history_tokenize_internal (string, wind, indp)
- const char *string;
- int wind, *indp;
-{
- char **result;
- register int i, start, result_index, size;
-
- /* If we're searching for a string that's not part of a word (e.g., " "),
- make sure we set *INDP to a reasonable value. */
- if (indp && wind != -1)
- *indp = -1;
-
- /* Get a token, and stuff it into RESULT. The tokens are split
- exactly where the shell would split them. */
- for (i = result_index = size = 0, result = (char **)NULL; string[i]; )
- {
- /* Skip leading whitespace. */
- for (; string[i] && whitespace (string[i]); i++)
- ;
- if (string[i] == 0 || string[i] == history_comment_char)
- return (result);
-
- start = i;
-
- i = history_tokenize_word (string, start);
-
- /* If we have a non-whitespace delimiter character (which would not be
- skipped by the loop above), use it and any adjacent delimiters to
- make a separate field. Any adjacent white space will be skipped the
- next time through the loop. */
- if (i == start && history_word_delimiters)
- {
- i++;
- while (string[i] && member (string[i], history_word_delimiters))
- i++;
- }
-
- /* If we are looking for the word in which the character at a
- particular index falls, remember it. */
- if (indp && wind != -1 && wind >= start && wind < i)
- *indp = result_index;
-
- if (result_index + 2 >= size)
- result = (char **)xrealloc (result, ((size += 10) * sizeof (char *)));
-
- result[result_index++] = history_substring (string, start, i);
- result[result_index] = (char *)NULL;
- }
-
- return (result);
-}
-
-/* Return an array of tokens, much as the shell might. The tokens are
- parsed out of STRING. */
-char **
-history_tokenize (string)
- const char *string;
-{
- return (history_tokenize_internal (string, -1, (int *)NULL));
-}
-
-/* Find and return the word which contains the character at index IND
- in the history line LINE. Used to save the word matched by the
- last history !?string? search. */
-static char *
-history_find_word (line, ind)
- char *line;
- int ind;
-{
- char **words, *s;
- int i, wind;
-
- words = history_tokenize_internal (line, ind, &wind);
- if (wind == -1 || words == 0)
- return ((char *)NULL);
- s = words[wind];
- for (i = 0; i < wind; i++)
- free (words[i]);
- for (i = wind + 1; words[i]; i++)
- free (words[i]);
- free (words);
- return s;
-}
diff --git a/lib/readline/histfile.c~ b/lib/readline/histfile.c~
deleted file mode 100644
index 717bbee6..00000000
--- a/lib/readline/histfile.c~
+++ /dev/null
@@ -1,542 +0,0 @@
-/* histfile.c - functions to manipulate the history file. */
-
-/* Copyright (C) 1989-2003 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- 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. */
-
-/* The goal is to make the implementation transparent, so that you
- don't have to know what data types are used, just what functions
- you can call. I think I have done that. */
-
-#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>
-#if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-#include "posixstat.h"
-#include <fcntl.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
-
-#if defined (__EMX__) || defined (__CYGWIN__)
-# undef HAVE_MMAP
-#endif
-
-#ifdef HISTORY_USE_MMAP
-# include <sys/mman.h>
-
-# ifdef MAP_FILE
-# define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
-# define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
-# else
-# define MAP_RFLAGS MAP_PRIVATE
-# define MAP_WFLAGS MAP_SHARED
-# endif
-
-# ifndef MAP_FAILED
-# define MAP_FAILED ((void *)-1)
-# endif
-
-#endif /* HISTORY_USE_MMAP */
-
-/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
- on win 95/98/nt), we want to open files with O_BINARY mode so that there
- is no \n -> \r\n conversion performed. On other systems, we don't want to
- mess around with O_BINARY at all, so we ensure that it's defined to 0. */
-#if defined (__EMX__) || defined (__CYGWIN__)
-# ifndef O_BINARY
-# define O_BINARY 0
-# endif
-#else /* !__EMX__ && !__CYGWIN__ */
-# undef O_BINARY
-# define O_BINARY 0
-#endif /* !__EMX__ && !__CYGWIN__ */
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#include "history.h"
-#include "histlib.h"
-
-#include "rlshell.h"
-#include "xmalloc.h"
-
-/* If non-zero, we write timestamps to the history file in history_do_write() */
-int history_write_timestamps = 0;
-
-/* Does S look like the beginning of a history timestamp entry? Placeholder
- for more extensive tests. */
-#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char)
-
-/* Return the string that should be used in the place of this
- filename. This only matters when you don't specify the
- filename to read_history (), or write_history (). */
-static char *
-history_filename (filename)
- const char *filename;
-{
- char *return_val;
- const char *home;
- int home_len;
-
- return_val = filename ? savestring (filename) : (char *)NULL;
-
- if (return_val)
- return (return_val);
-
- home = sh_get_env_value ("HOME");
-
- if (home == 0)
- {
- home = ".";
- home_len = 1;
- }
- else
- home_len = strlen (home);
-
- return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
- strcpy (return_val, home);
- return_val[home_len] = '/';
-#if defined (__MSDOS__)
- strcpy (return_val + home_len + 1, "_history");
-#else
- strcpy (return_val + home_len + 1, ".history");
-#endif
-
- return (return_val);
-}
-
-/* Add the contents of FILENAME to the history list, a line at a time.
- If FILENAME is NULL, then read from ~/.history. Returns 0 if
- successful, or errno if not. */
-int
-read_history (filename)
- const char *filename;
-{
- return (read_history_range (filename, 0, -1));
-}
-
-/* Read a range of lines from FILENAME, adding them to the history list.
- Start reading at the FROM'th line and end at the TO'th. If FROM
- is zero, start at the beginning. If TO is less than FROM, read
- until the end of the file. If FILENAME is NULL, then read from
- ~/.history. Returns 0 if successful, or errno if not. */
-int
-read_history_range (filename, from, to)
- const char *filename;
- int from, to;
-{
- register char *line_start, *line_end, *p;
- char *input, *buffer, *bufend, *last_ts;
- int file, current_line, chars_read;
- struct stat finfo;
- size_t file_size;
-#if defined (EFBIG)
- int overflow_errno = EFBIG;
-#elif defined (EOVERFLOW)
- int overflow_errno = EOVERFLOW;
-#else
- int overflow_errno = EIO;
-#endif
-
- buffer = last_ts = (char *)NULL;
- input = history_filename (filename);
- file = open (input, O_RDONLY|O_BINARY, 0666);
-
- if ((file < 0) || (fstat (file, &finfo) == -1))
- goto error_and_exit;
-
- 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)
- {
- errno = overflow_errno;
- goto error_and_exit;
- }
-
-#ifdef HISTORY_USE_MMAP
- /* We map read/write and private so we can change newlines to NULs without
- affecting the underlying object. */
- buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
- if ((void *)buffer == MAP_FAILED)
- {
- errno = overflow_errno;
- goto error_and_exit;
- }
- chars_read = file_size;
-#else
- buffer = (char *)malloc (file_size + 1);
- if (buffer == 0)
- {
- errno = overflow_errno;
- goto error_and_exit;
- }
-
- chars_read = read (file, buffer, file_size);
-#endif
- if (chars_read < 0)
- {
- error_and_exit:
- if (errno != 0)
- chars_read = errno;
- else
- chars_read = EIO;
- if (file >= 0)
- close (file);
-
- FREE (input);
-#ifndef HISTORY_USE_MMAP
- FREE (buffer);
-#endif
-
- return (chars_read);
- }
-
- close (file);
-
- /* Set TO to larger than end of file if negative. */
- if (to < 0)
- to = chars_read;
-
- /* Start at beginning of file, work to end. */
- bufend = buffer + chars_read;
- current_line = 0;
-
- /* Skip lines until we are at FROM. */
- for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
- if (*line_end == '\n')
- {
- p = line_end + 1;
- /* If we see something we think is a timestamp, continue with this
- line. We should check more extensively here... */
- if (HIST_TIMESTAMP_START(p) == 0)
- current_line++;
- line_start = p;
- }
-
- /* If there are lines left to gobble, then gobble them now. */
- for (line_end = line_start; line_end < bufend; line_end++)
- if (*line_end == '\n')
- {
- *line_end = '\0';
-
- if (*line_start)
- {
- if (HIST_TIMESTAMP_START(line_start) == 0)
- {
- add_history (line_start);
- if (last_ts)
- {
- add_history_time (last_ts);
- last_ts = NULL;
- }
- }
- else
- {
- last_ts = line_start;
- current_line--;
- }
- }
-
- current_line++;
-
- if (current_line >= to)
- break;
-
- line_start = line_end + 1;
- }
-
- FREE (input);
-#ifndef HISTORY_USE_MMAP
- FREE (buffer);
-#else
- munmap (buffer, file_size);
-#endif
-
- return (0);
-}
-
-/* Truncate the history file FNAME, leaving only LINES trailing lines.
- If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
- on failure. */
-int
-history_truncate_file (fname, lines)
- const char *fname;
- int lines;
-{
- char *buffer, *filename, *bp, *bp1; /* bp1 == bp+1 */
- int file, chars_read, rv;
- struct stat finfo;
- size_t file_size;
-
- buffer = (char *)NULL;
- filename = history_filename (fname);
- file = open (filename, O_RDONLY|O_BINARY, 0666);
- rv = 0;
-
- /* Don't try to truncate non-regular files. */
- if (file == -1 || fstat (file, &finfo) == -1)
- {
- rv = errno;
- if (file != -1)
- close (file);
- goto truncate_exit;
- }
-
- if (S_ISREG (finfo.st_mode) == 0)
- {
- close (file);
-#ifdef EFTYPE
- rv = EFTYPE;
-#else
- rv = EINVAL;
-#endif
- goto truncate_exit;
- }
-
- 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)
- {
- close (file);
-#if defined (EFBIG)
- rv = errno = EFBIG;
-#elif defined (EOVERFLOW)
- rv = errno = EOVERFLOW;
-#else
- rv = errno = EINVAL;
-#endif
- goto truncate_exit;
- }
-
- buffer = (char *)malloc (file_size + 1);
- if (buffer == 0)
- {
- close (file);
- goto truncate_exit;
- }
-
- chars_read = read (file, buffer, file_size);
- close (file);
-
- if (chars_read <= 0)
- {
- rv = (chars_read < 0) ? errno : 0;
- goto truncate_exit;
- }
-
- /* Count backwards from the end of buffer until we have passed
- LINES lines. bp1 is set funny initially. But since bp[1] can't
- be a comment character (since it's off the end) and *bp can't be
- both a newline and the history comment character, it should be OK. */
- for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
- {
- if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
- lines--;
- bp1 = bp;
- }
-
- /* If this is the first line, then the file contains exactly the
- number of lines we want to truncate to, so we don't need to do
- anything. It's the first line if we don't find a newline between
- the current value of i and 0. Otherwise, write from the start of
- this line until the end of the buffer. */
- for ( ; bp > buffer; bp--)
- {
- if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
- {
- bp++;
- break;
- }
- bp1 = bp;
- }
-
- /* Write only if there are more lines in the file than we want to
- truncate to. */
- if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
- {
- write (file, bp, chars_read - (bp - buffer));
-
-#if defined (__BEOS__)
- /* BeOS ignores O_TRUNC. */
- ftruncate (file, chars_read - (bp - buffer));
-#endif
-
- close (file);
- }
-
- truncate_exit:
-
- FREE (buffer);
-
- free (filename);
- return rv;
-}
-
-/* Workhorse function for writing history. Writes NELEMENT entries
- from the history list to FILENAME. OVERWRITE is non-zero if you
- wish to replace FILENAME with the entries. */
-static int
-history_do_write (filename, nelements, overwrite)
- const char *filename;
- int nelements, overwrite;
-{
- register int i;
- char *output;
- int file, mode, rv;
-#ifdef HISTORY_USE_MMAP
- size_t cursize;
-
- mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
-#else
- mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
-#endif
- output = history_filename (filename);
- rv = 0;
-
- if ((file = open (output, mode, 0600)) == -1)
- {
- FREE (output);
- return (errno);
- }
-
-#ifdef HISTORY_USE_MMAP
- cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
-#endif
-
- if (nelements > history_length)
- nelements = history_length;
-
- /* Build a buffer of all the lines to write, and write them in one syscall.
- Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
- {
- HIST_ENTRY **the_history; /* local */
- register int j;
- int buffer_size;
- char *buffer;
-
- the_history = history_list ();
- /* Calculate the total number of bytes to write. */
- for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
-#if 0
- buffer_size += 2 + HISTENT_BYTES (the_history[i]);
-#else
- {
- if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
- buffer_size += strlen (the_history[i]->timestamp) + 1;
- buffer_size += strlen (the_history[i]->line) + 1;
- }
-#endif
-
- /* Allocate the buffer, and fill it. */
-#ifdef HISTORY_USE_MMAP
- if (ftruncate (file, buffer_size+cursize) == -1)
- goto mmap_error;
- buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
- if ((void *)buffer == MAP_FAILED)
- {
-mmap_error:
- rv = errno;
- FREE (output);
- close (file);
- return rv;
- }
-#else
- buffer = (char *)malloc (buffer_size);
- if (buffer == 0)
- {
- rv = errno;
- FREE (output);
- close (file);
- return rv;
- }
-#endif
-
- for (j = 0, i = history_length - nelements; i < history_length; i++)
- {
- if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
- {
- strcpy (buffer + j, the_history[i]->timestamp);
- j += strlen (the_history[i]->timestamp);
- buffer[j++] = '\n';
- }
- strcpy (buffer + j, the_history[i]->line);
- j += strlen (the_history[i]->line);
- buffer[j++] = '\n';
- }
-
-#ifdef HISTORY_USE_MMAP
- if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
- rv = errno;
-#else
- if (write (file, buffer, buffer_size) < 0)
- rv = errno;
- free (buffer);
-#endif
- }
-
- close (file);
-
- FREE (output);
-
- return (rv);
-}
-
-/* Append NELEMENT entries to FILENAME. The entries appended are from
- the end of the list minus NELEMENTs up to the end of the list. */
-int
-append_history (nelements, filename)
- int nelements;
- const char *filename;
-{
- return (history_do_write (filename, nelements, HISTORY_APPEND));
-}
-
-/* Overwrite FILENAME with the current history. If FILENAME is NULL,
- then write the history list to ~/.history. Values returned
- are as in read_history ().*/
-int
-write_history (filename)
- const char *filename;
-{
- return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
-}
diff --git a/lib/readline/history.c~ b/lib/readline/history.c~
deleted file mode 100644
index e18b410a..00000000
--- a/lib/readline/history.c~
+++ /dev/null
@@ -1,486 +0,0 @@
-/* history.c -- standalone history library */
-
-/* Copyright (C) 1989-2005 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (the Library), a set of
- routines for managing the text of previously typed lines.
-
- 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. */
-
-/* The goal is to make the implementation transparent, so that you
- don't have to know what data types are used, just what functions
- you can call. I think I have done that. */
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include "history.h"
-#include "histlib.h"
-
-#include "xmalloc.h"
-
-/* The number of slots to increase the_history by. */
-#define DEFAULT_HISTORY_GROW_SIZE 50
-
-static char *hist_inittime PARAMS((void));
-
-/* **************************************************************** */
-/* */
-/* History Functions */
-/* */
-/* **************************************************************** */
-
-/* An array of HIST_ENTRY. This is where we store the history. */
-static HIST_ENTRY **the_history = (HIST_ENTRY **)NULL;
-
-/* Non-zero means that we have enforced a limit on the amount of
- history that we save. */
-static int history_stifled;
-
-/* The current number of slots allocated to the input_history. */
-static int history_size;
-
-/* If HISTORY_STIFLED is non-zero, then this is the maximum number of
- entries to remember. */
-int history_max_entries;
-int max_input_history; /* backwards compatibility */
-
-/* The current location of the interactive history pointer. Just makes
- life easier for outside callers. */
-int history_offset;
-
-/* The number of strings currently stored in the history list. */
-int history_length;
-
-/* The logical `base' of the history array. It defaults to 1. */
-int history_base = 1;
-
-/* Return the current HISTORY_STATE of the history. */
-HISTORY_STATE *
-history_get_history_state ()
-{
- HISTORY_STATE *state;
-
- state = (HISTORY_STATE *)xmalloc (sizeof (HISTORY_STATE));
- state->entries = the_history;
- state->offset = history_offset;
- state->length = history_length;
- state->size = history_size;
- state->flags = 0;
- if (history_stifled)
- state->flags |= HS_STIFLED;
-
- return (state);
-}
-
-/* Set the state of the current history array to STATE. */
-void
-history_set_history_state (state)
- HISTORY_STATE *state;
-{
- the_history = state->entries;
- history_offset = state->offset;
- history_length = state->length;
- history_size = state->size;
- if (state->flags & HS_STIFLED)
- history_stifled = 1;
-}
-
-/* Begin a session in which the history functions might be used. This
- initializes interactive variables. */
-void
-using_history ()
-{
- history_offset = history_length;
-}
-
-/* Return the number of bytes that the primary history entries are using.
- This just adds up the lengths of the_history->lines and the associated
- timestamps. */
-int
-history_total_bytes ()
-{
- register int i, result;
-
- for (i = result = 0; the_history && the_history[i]; i++)
- result += HISTENT_BYTES (the_history[i]);
-
- return (result);
-}
-
-/* Returns the magic number which says what history element we are
- looking at now. In this implementation, it returns history_offset. */
-int
-where_history ()
-{
- return (history_offset);
-}
-
-/* Make the current history item be the one at POS, an absolute index.
- Returns zero if POS is out of range, else non-zero. */
-int
-history_set_pos (pos)
- int pos;
-{
- if (pos > history_length || pos < 0 || !the_history)
- return (0);
- history_offset = pos;
- return (1);
-}
-
-/* Return the current history array. The caller has to be carefull, since this
- is the actual array of data, and could be bashed or made corrupt easily.
- The array is terminated with a NULL pointer. */
-HIST_ENTRY **
-history_list ()
-{
- return (the_history);
-}
-
-/* Return the history entry at the current position, as determined by
- history_offset. If there is no entry there, return a NULL pointer. */
-HIST_ENTRY *
-current_history ()
-{
- return ((history_offset == history_length) || the_history == 0)
- ? (HIST_ENTRY *)NULL
- : the_history[history_offset];
-}
-
-/* Back up history_offset to the previous history entry, and return
- a pointer to that entry. If there is no previous entry then return
- a NULL pointer. */
-HIST_ENTRY *
-previous_history ()
-{
- return history_offset ? the_history[--history_offset] : (HIST_ENTRY *)NULL;
-}
-
-/* Move history_offset forward to the next history entry, and return
- a pointer to that entry. If there is no next entry then return a
- NULL pointer. */
-HIST_ENTRY *
-next_history ()
-{
- return (history_offset == history_length) ? (HIST_ENTRY *)NULL : the_history[++history_offset];
-}
-
-/* Return the history entry which is logically at OFFSET in the history array.
- OFFSET is relative to history_base. */
-HIST_ENTRY *
-history_get (offset)
- int offset;
-{
- int local_index;
-
- local_index = offset - history_base;
- return (local_index >= history_length || local_index < 0 || the_history == 0)
- ? (HIST_ENTRY *)NULL
- : the_history[local_index];
-}
-
-time_t
-history_get_time (hist)
- HIST_ENTRY *hist;
-{
- char *ts;
- time_t t;
-
- if (hist == 0 || hist->timestamp == 0)
- return 0;
- ts = hist->timestamp;
- if (ts[0] != history_comment_char)
- return 0;
- t = (time_t) atol (ts + 1); /* XXX - should use strtol() here */
- return t;
-}
-
-static char *
-hist_inittime ()
-{
- time_t t;
- char ts[64], *ret;
-
- t = (time_t) time ((time_t *)0);
-#if defined (HAVE_VSNPRINTF) /* assume snprintf if vsnprintf exists */
- snprintf (ts, sizeof (ts) - 1, "X%lu", (unsigned long) t);
-#else
- sprintf (ts, "X%lu", (unsigned long) t);
-#endif
- ret = savestring (ts);
- ret[0] = history_comment_char;
-
- return ret;
-}
-
-/* Place STRING at the end of the history list. The data field
- is set to NULL. */
-void
-add_history (string)
- const char *string;
-{
- HIST_ENTRY *temp;
-
- if (history_stifled && (history_length == history_max_entries))
- {
- register int i;
-
- /* If the history is stifled, and history_length is zero,
- and it equals history_max_entries, we don't save items. */
- if (history_length == 0)
- return;
-
- /* If there is something in the slot, then remove it. */
- if (the_history[0])
- (void) free_history_entry (the_history[0]);
-
- /* Copy the rest of the entries, moving down one slot. */
- for (i = 0; i < history_length; i++)
- the_history[i] = the_history[i + 1];
-
- history_base++;
- }
- else
- {
- if (history_size == 0)
- {
- history_size = DEFAULT_HISTORY_GROW_SIZE;
- the_history = (HIST_ENTRY **)xmalloc (history_size * sizeof (HIST_ENTRY *));
- history_length = 1;
- }
- else
- {
- if (history_length == (history_size - 1))
- {
- history_size += DEFAULT_HISTORY_GROW_SIZE;
- the_history = (HIST_ENTRY **)
- xrealloc (the_history, history_size * sizeof (HIST_ENTRY *));
- }
- history_length++;
- }
- }
-
- temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
- temp->line = savestring (string);
- temp->data = (char *)NULL;
-
- temp->timestamp = hist_inittime ();
-
- the_history[history_length] = (HIST_ENTRY *)NULL;
- the_history[history_length - 1] = temp;
-}
-
-/* Change the time stamp of the most recent history entry to STRING. */
-void
-add_history_time (string)
- const char *string;
-{
- HIST_ENTRY *hs;
-
- hs = the_history[history_length - 1];
- FREE (hs->timestamp);
- hs->timestamp = savestring (string);
-}
-
-/* Free HIST and return the data so the calling application can free it
- if necessary and desired. */
-histdata_t
-free_history_entry (hist)
- HIST_ENTRY *hist;
-{
- histdata_t x;
-
- if (hist == 0)
- return ((histdata_t) 0);
- FREE (hist->line);
- FREE (hist->timestamp);
- x = hist->data;
- free (hist);
- return (x);
-}
-
-/* Make the history entry at WHICH have LINE and DATA. This returns
- the old entry so you can dispose of the data. In the case of an
- invalid WHICH, a NULL pointer is returned. */
-HIST_ENTRY *
-replace_history_entry (which, line, data)
- int which;
- const char *line;
- histdata_t data;
-{
- HIST_ENTRY *temp, *old_value;
-
- if (which < 0 || which >= history_length)
- return ((HIST_ENTRY *)NULL);
-
- temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
- old_value = the_history[which];
-
- temp->line = savestring (line);
- temp->data = data;
- temp->timestamp = savestring (old_value->timestamp);
- the_history[which] = temp;
-
- return (old_value);
-}
-
-/* Replace the DATA in the specified history entries, replacing OLD with
- NEW. WHICH says which one(s) to replace: WHICH == -1 means to replace
- all of the history entries where entry->data == OLD; WHICH == -2 means
- to replace the `newest' history entry where entry->data == OLD; and
- WHICH >= 0 means to replace that particular history entry's data, as
- long as it matches OLD. */
-void
-replace_history_data (which,old, new)
- int which;
- histdata_t *old, *new;
-{
- HIST_ENTRY *entry;
- register int i, last;
-
- if (which < -2 || which >= history_length || history_length == 0 || the_history == 0)
- return;
-
- if (which >= 0)
- {
- entry = the_history[which];
- if (entry && entry->data == old)
- entry->data = new;
- return;
- }
-
- last = -1;
- for (i = 0; i < history_length; i++)
- {
- entry = the_history[i];
- if (entry == 0)
- continue;
- if (entry->data == old)
- {
- last = i;
- if (which == -1)
- entry->data = new;
- }
- }
- if (which == -2 && last >= 0)
- {
- entry = the_history[last];
- entry->data = new; /* XXX - we don't check entry->old */
- }
-}
-
-/* Remove history element WHICH from the history. The removed
- element is returned to you so you can free the line, data,
- and containing structure. */
-HIST_ENTRY *
-remove_history (which)
- int which;
-{
- HIST_ENTRY *return_value;
- register int i;
-
- if (which < 0 || which >= history_length || history_length == 0 || the_history == 0)
- return ((HIST_ENTRY *)NULL);
-
- return_value = the_history[which];
-
- for (i = which; i < history_length; i++)
- the_history[i] = the_history[i + 1];
-
- history_length--;
-
- return (return_value);
-}
-
-/* Stifle the history list, remembering only MAX number of lines. */
-void
-stifle_history (max)
- int max;
-{
- register int i, j;
-
- if (max < 0)
- max = 0;
-
- if (history_length > max)
- {
- /* This loses because we cannot free the data. */
- for (i = 0, j = history_length - max; i < j; i++)
- free_history_entry (the_history[i]);
-
- history_base = i;
- for (j = 0, i = history_length - max; j < max; i++, j++)
- the_history[j] = the_history[i];
- the_history[j] = (HIST_ENTRY *)NULL;
- history_length = j;
- }
-
- history_stifled = 1;
- max_input_history = history_max_entries = max;
-}
-
-/* Stop stifling the history. This returns the previous maximum
- number of history entries. The value is positive if the history
- was stifled, negative if it wasn't. */
-int
-unstifle_history ()
-{
- if (history_stifled)
- {
- history_stifled = 0;
- return (history_max_entries);
- }
- else
- return (-history_max_entries);
-}
-
-int
-history_is_stifled ()
-{
- return (history_stifled);
-}
-
-void
-clear_history ()
-{
- register int i;
-
- /* This loses because we cannot free the data. */
- for (i = 0; i < history_length; i++)
- {
- free_history_entry (the_history[i]);
- the_history[i] = (HIST_ENTRY *)NULL;
- }
-
- history_offset = history_length = 0;
-}
diff --git a/lib/readline/input.c~ b/lib/readline/input.c~
deleted file mode 100644
index 2c02ed07..00000000
--- a/lib/readline/input.c~
+++ /dev/null
@@ -1,591 +0,0 @@
-/* input.c -- character input functions for readline. */
-
-/* Copyright (C) 1994-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 <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 */
-
-#if defined (HAVE_SELECT)
-# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
-# include <sys/time.h>
-# endif
-#endif /* HAVE_SELECT */
-#if defined (HAVE_SYS_SELECT_H)
-# include <sys/select.h>
-#endif
-
-#if defined (FIONREAD_IN_SYS_IOCTL)
-# include <sys/ioctl.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-
-#include "rlprivate.h"
-#include "rlshell.h"
-#include "xmalloc.h"
-
-/* What kind of non-blocking I/O do we have? */
-#if !defined (O_NDELAY) && defined (O_NONBLOCK)
-# define O_NDELAY O_NONBLOCK /* Posix style */
-#endif
-
-/* Non-null means it is a pointer to a function to run while waiting for
- character input. */
-rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
-
-rl_getc_func_t *rl_getc_function = rl_getc;
-
-static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */
-
-static int ibuffer_space PARAMS((void));
-static int rl_get_char PARAMS((int *));
-static int rl_gather_tyi PARAMS((void));
-
-/* **************************************************************** */
-/* */
-/* Character Input Buffering */
-/* */
-/* **************************************************************** */
-
-static int pop_index, push_index;
-static unsigned char ibuffer[512];
-static int ibuffer_len = sizeof (ibuffer) - 1;
-
-#define any_typein (push_index != pop_index)
-
-int
-_rl_any_typein ()
-{
- return any_typein;
-}
-
-/* Return the amount of space available in the buffer for stuffing
- characters. */
-static int
-ibuffer_space ()
-{
- if (pop_index > push_index)
- return (pop_index - push_index - 1);
- else
- return (ibuffer_len - (push_index - pop_index));
-}
-
-/* Get a key from the buffer of characters to be read.
- Return the key in KEY.
- Result is KEY if there was a key, or 0 if there wasn't. */
-static int
-rl_get_char (key)
- int *key;
-{
- if (push_index == pop_index)
- return (0);
-
- *key = ibuffer[pop_index++];
-
- if (pop_index >= ibuffer_len)
- pop_index = 0;
-
- return (1);
-}
-
-/* Stuff KEY into the *front* of the input buffer.
- Returns non-zero if successful, zero if there is
- no space left in the buffer. */
-int
-_rl_unget_char (key)
- int key;
-{
- if (ibuffer_space ())
- {
- pop_index--;
- if (pop_index < 0)
- pop_index = ibuffer_len - 1;
- ibuffer[pop_index] = key;
- return (1);
- }
- return (0);
-}
-
-int
-_rl_pushed_input_available ()
-{
- return (push_index != pop_index);
-}
-
-/* If a character is available to be read, then read it and stuff it into
- IBUFFER. Otherwise, just return. Returns number of characters read
- (0 if none available) and -1 on error (EIO). */
-static int
-rl_gather_tyi ()
-{
- int tty;
- register int tem, result;
- int chars_avail, k;
- char input;
-#if defined(HAVE_SELECT)
- fd_set readfds, exceptfds;
- struct timeval timeout;
-#endif
-
- chars_avail = 0;
- tty = fileno (rl_instream);
-
-#if defined (HAVE_SELECT)
- FD_ZERO (&readfds);
- FD_ZERO (&exceptfds);
- FD_SET (tty, &readfds);
- FD_SET (tty, &exceptfds);
- timeout.tv_sec = 0;
- timeout.tv_usec = _keyboard_input_timeout;
- result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
- if (result <= 0)
- return 0; /* Nothing to read. */
-#endif
-
- result = -1;
-#if defined (FIONREAD)
- errno = 0;
- result = ioctl (tty, FIONREAD, &chars_avail);
- if (result == -1 && errno == EIO)
- return -1;
-#endif
-
-#if defined (O_NDELAY)
- if (result == -1)
- {
- tem = fcntl (tty, F_GETFL, 0);
-
- fcntl (tty, F_SETFL, (tem | O_NDELAY));
- chars_avail = read (tty, &input, 1);
-
- fcntl (tty, F_SETFL, tem);
- if (chars_avail == -1 && errno == EAGAIN)
- return 0;
- if (chars_avail == 0) /* EOF */
- {
- rl_stuff_char (EOF);
- return (0);
- }
- }
-#endif /* O_NDELAY */
-
-#if defined (__MINGW32__)
- /* Use getch/_kbhit to check for available console input, in the same way
- that we read it normally. */
- chars_avail = isatty (tty) ? _kbhit () : 0;
- result = 0;
-#endif
-
- /* If there's nothing available, don't waste time trying to read
- something. */
- if (chars_avail <= 0)
- return 0;
-
- tem = ibuffer_space ();
-
- if (chars_avail > tem)
- chars_avail = tem;
-
- /* One cannot read all of the available input. I can only read a single
- character at a time, or else programs which require input can be
- thwarted. If the buffer is larger than one character, I lose.
- Damn! */
- if (tem < ibuffer_len)
- chars_avail = 0;
-
- if (result != -1)
- {
- while (chars_avail--)
- {
- k = (*rl_getc_function) (rl_instream);
- rl_stuff_char (k);
- if (k == NEWLINE || k == RETURN)
- break;
- }
- }
- else
- {
- if (chars_avail)
- rl_stuff_char (input);
- }
-
- return 1;
-}
-
-int
-rl_set_keyboard_input_timeout (u)
- int u;
-{
- int o;
-
- o = _keyboard_input_timeout;
- if (u >= 0)
- _keyboard_input_timeout = u;
- return (o);
-}
-
-/* Is there input available to be read on the readline input file
- descriptor? Only works if the system has select(2) or FIONREAD.
- Uses the value of _keyboard_input_timeout as the timeout; if another
- readline function wants to specify a timeout and not leave it up to
- the user, it should use _rl_input_queued(timeout_value_in_microseconds)
- instead. */
-int
-_rl_input_available ()
-{
-#if defined(HAVE_SELECT)
- fd_set readfds, exceptfds;
- struct timeval timeout;
-#endif
-#if !defined (HAVE_SELECT) && defined(FIONREAD)
- int chars_avail;
-#endif
- int tty;
-
- tty = fileno (rl_instream);
-
-#if defined (HAVE_SELECT)
- FD_ZERO (&readfds);
- FD_ZERO (&exceptfds);
- FD_SET (tty, &readfds);
- FD_SET (tty, &exceptfds);
- timeout.tv_sec = 0;
- timeout.tv_usec = _keyboard_input_timeout;
- return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
-#else
-
-#if defined (FIONREAD)
- if (ioctl (tty, FIONREAD, &chars_avail) == 0)
- return (chars_avail);
-#endif
-
-#endif
-
-#if defined (__MINGW32__)
- if (isatty (tty))
- return (_kbhit ());
-#endif
-
- return 0;
-}
-
-int
-_rl_input_queued (t)
- int t;
-{
- int old_timeout, r;
-
- old_timeout = rl_set_keyboard_input_timeout (t);
- r = _rl_input_available ();
- rl_set_keyboard_input_timeout (old_timeout);
- return r;
-}
-
-void
-_rl_insert_typein (c)
- int c;
-{
- int key, t, i;
- char *string;
-
- i = key = 0;
- string = (char *)xmalloc (ibuffer_len + 1);
- string[i++] = (char) c;
-
- while ((t = rl_get_char (&key)) &&
- _rl_keymap[key].type == ISFUNC &&
- _rl_keymap[key].function == rl_insert)
- string[i++] = key;
-
- if (t)
- _rl_unget_char (key);
-
- string[i] = '\0';
- rl_insert_text (string);
- free (string);
-}
-
-/* Add KEY to the buffer of characters to be read. Returns 1 if the
- character was stuffed correctly; 0 otherwise. */
-int
-rl_stuff_char (key)
- int key;
-{
- if (ibuffer_space () == 0)
- return 0;
-
- if (key == EOF)
- {
- key = NEWLINE;
- rl_pending_input = EOF;
- RL_SETSTATE (RL_STATE_INPUTPENDING);
- }
- ibuffer[push_index++] = key;
- if (push_index >= ibuffer_len)
- push_index = 0;
-
- return 1;
-}
-
-/* Make C be the next command to be executed. */
-int
-rl_execute_next (c)
- int c;
-{
- rl_pending_input = c;
- RL_SETSTATE (RL_STATE_INPUTPENDING);
- return 0;
-}
-
-/* Clear any pending input pushed with rl_execute_next() */
-int
-rl_clear_pending_input ()
-{
- rl_pending_input = 0;
- RL_UNSETSTATE (RL_STATE_INPUTPENDING);
- return 0;
-}
-
-/* **************************************************************** */
-/* */
-/* Character Input */
-/* */
-/* **************************************************************** */
-
-/* Read a key, including pending input. */
-int
-rl_read_key ()
-{
- int c;
-
- rl_key_sequence_length++;
-
- if (rl_pending_input)
- {
- c = rl_pending_input;
- rl_clear_pending_input ();
- }
- else
- {
- /* If input is coming from a macro, then use that. */
- if (c = _rl_next_macro_key ())
- return (c);
-
- /* If the user has an event function, then call it periodically. */
- if (rl_event_hook)
- {
- while (rl_event_hook && rl_get_char (&c) == 0)
- {
- (*rl_event_hook) ();
- if (rl_done) /* XXX - experimental */
- return ('\n');
- if (rl_gather_tyi () < 0) /* XXX - EIO */
- {
- rl_done = 1;
- return ('\n');
- }
- }
- }
- else
- {
- if (rl_get_char (&c) == 0)
- c = (*rl_getc_function) (rl_instream);
- }
- }
-
- return (c);
-}
-
-int
-rl_getc (stream)
- FILE *stream;
-{
- int result;
- unsigned char c;
-
- while (1)
- {
-#if defined (__MINGW32__)
- if (isatty (fileno (stream)))
- return (getch ());
-#endif
- result = read (fileno (stream), &c, sizeof (unsigned char));
-
- if (result == sizeof (unsigned char))
- return (c);
-
- /* If zero characters are returned, then the file that we are
- reading from is empty! Return EOF in that case. */
- if (result == 0)
- return (EOF);
-
-#if defined (__BEOS__)
- if (errno == EINTR)
- continue;
-#endif
-
-#if defined (EWOULDBLOCK)
-# define X_EWOULDBLOCK EWOULDBLOCK
-#else
-# define X_EWOULDBLOCK -99
-#endif
-
-#if defined (EAGAIN)
-# define X_EAGAIN EAGAIN
-#else
-# define X_EAGAIN -99
-#endif
-
-fprintf(stderr, "\r\nread returns -1; errno == %d\r\n", errno);
- if (errno == X_EWOULDBLOCK || errno == X_EAGAIN)
- {
- if (sh_unset_nodelay_mode (fileno (stream)) < 0)
- return (EOF);
- continue;
- }
-
-#undef X_EWOULDBLOCK
-#undef X_EAGAIN
-
- /* If the error that we received was SIGINT, then try again,
- this is simply an interrupted system call to read ().
- Otherwise, some error ocurred, also signifying EOF. */
- if (errno != EINTR)
-#if 0
- return (EOF);
-#else
-{
-fprintf(stderr, "\r\nreturning %s\r\n", RL_ISSTATE (RL_STATE_READCMD) ? "READERR" : "EOF");
- return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
-}
-#endif
- }
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* read multibyte char */
-int
-_rl_read_mbchar (mbchar, size)
- char *mbchar;
- int size;
-{
- int mb_len = 0;
- size_t mbchar_bytes_length;
- wchar_t wc;
- mbstate_t ps, ps_back;
-
- memset(&ps, 0, sizeof (mbstate_t));
- memset(&ps_back, 0, sizeof (mbstate_t));
-
- while (mb_len < size)
- {
- RL_SETSTATE(RL_STATE_MOREINPUT);
- mbchar[mb_len++] = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
- mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
- if (mbchar_bytes_length == (size_t)(-1))
- break; /* invalid byte sequence for the current locale */
- else if (mbchar_bytes_length == (size_t)(-2))
- {
- /* shorted bytes */
- ps = ps_back;
- continue;
- }
- else if (mbchar_bytes_length == 0)
- {
- mbchar[0] = '\0'; /* null wide character */
- mb_len = 1;
- break;
- }
- else if (mbchar_bytes_length > (size_t)(0))
- break;
- }
-
- return mb_len;
-}
-
-/* Read a multibyte-character string whose first character is FIRST into
- the buffer MB of length MLEN. Returns the last character read, which
- may be FIRST. Used by the search functions, among others. Very similar
- to _rl_read_mbchar. */
-int
-_rl_read_mbstring (first, mb, mlen)
- int first;
- char *mb;
- int mlen;
-{
- int i, c;
- mbstate_t ps;
-
- c = first;
- memset (mb, 0, mlen);
- for (i = 0; i < mlen; i++)
- {
- mb[i] = (char)c;
- memset (&ps, 0, sizeof (mbstate_t));
- if (_rl_get_char_len (mb, &ps) == -2)
- {
- /* Read more for multibyte character */
- RL_SETSTATE (RL_STATE_MOREINPUT);
- c = rl_read_key ();
- RL_UNSETSTATE (RL_STATE_MOREINPUT);
- }
- else
- break;
- }
- return c;
-}
-#endif /* HANDLE_MULTIBYTE */
diff --git a/lib/readline/isearch.c.orig b/lib/readline/isearch.c.orig
deleted file mode 100644
index c1ea5b30..00000000
--- a/lib/readline/isearch.c.orig
+++ /dev/null
@@ -1,560 +0,0 @@
-/* **************************************************************** */
-/* */
-/* I-Search and Searching */
-/* */
-/* **************************************************************** */
-
-/* Copyright (C) 1987-2002 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;
-
-/* Variables imported from other files in the readline library. */
-extern HIST_ENTRY *_rl_saved_line_for_history;
-
-/* Forward declarations */
-static int rl_search_history PARAMS((int, 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";
-
-/* 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 1 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) ();
-}
-
-/* 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;
-{
- /* The string that the user types in to search for. */
- char *search_string;
-
- /* The current length of SEARCH_STRING. */
- int search_string_index;
-
- /* The amount of space that SEARCH_STRING has allocated to it. */
- int search_string_size;
-
- /* The list of lines to search through. */
- char **lines, *allocated_line;
-
- /* The length of LINES. */
- int hlen;
-
- /* Where we get LINES from. */
- HIST_ENTRY **hlist;
-
- register int i;
- int orig_point, orig_mark, orig_line, last_found_line;
- int c, found, failed, sline_len;
- int n, wstart, wlen;
-#if defined (HANDLE_MULTIBYTE)
- char mb[MB_LEN_MAX];
-#endif
-
- /* The line currently being searched. */
- char *sline;
-
- /* Offset in that line. */
- int line_index;
-
- /* Non-zero if we are doing a reverse search. */
- int reverse;
-
- /* The list of characters which terminate the search, but are not
- subsequently executed. If the variable isearch-terminators has
- been set, we use that value, otherwise we use ESC and C-J. */
- char *isearch_terminators;
-
- RL_SETSTATE(RL_STATE_ISEARCH);
- orig_point = rl_point;
- orig_mark = rl_mark;
- last_found_line = orig_line = where_history ();
- reverse = direction < 0;
- hlist = history_list ();
- allocated_line = (char *)NULL;
-
- isearch_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
- : default_isearch_terminators;
-
- /* Create an arrary of pointers to the lines that we want to search. */
- 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. */
- lines = (char **)xmalloc ((1 + (hlen = i)) * sizeof (char *));
- for (i = 0; i < hlen; i++)
- lines[i] = hlist[i]->line;
-
- if (_rl_saved_line_for_history)
- lines[i] = _rl_saved_line_for_history->line;
- else
- {
- /* Keep track of this so we can free it. */
- allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
- strcpy (allocated_line, &rl_line_buffer[0]);
- lines[i] = allocated_line;
- }
-
- hlen++;
-
- /* The line where we start the search. */
- i = orig_line;
-
- rl_save_prompt ();
-
- /* Initialize search parameters. */
- search_string = (char *)xmalloc (search_string_size = 128);
- *search_string = '\0';
- search_string_index = 0;
- prev_line_found = (char *)0; /* XXX */
-
- /* Normalize DIRECTION into 1 or -1. */
- direction = (direction >= 0) ? 1 : -1;
-
- rl_display_search (search_string, reverse, -1);
-
- sline = rl_line_buffer;
- sline_len = strlen (sline);
- line_index = rl_point;
-
- found = failed = 0;
- for (;;)
- {
- rl_command_func_t *f = (rl_command_func_t *)NULL;
-
- /* Read a key and decide how to proceed. */
- 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, MB_LEN_MAX);
-#endif
-
- /* 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)
- c = reverse ? -1 : -2;
- else if (f == rl_forward_search_history)
- c = !reverse ? -1 : -2;
- else if (f == rl_rubout)
- c = -3;
- else if (c == CTRL ('G'))
- c = -4;
- else if (c == CTRL ('W')) /* XXX */
- c = -5;
- else if (c == CTRL ('Y')) /* XXX */
- c = -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 (isearch_terminators, c))
- {
- /* 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 (c == ESC && _rl_input_available ())
- rl_execute_next (ESC);
- break;
- }
-
-#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 (c >= 0 && strlen (mb) == 1 && ENDSRCH_CHAR (c))
- {
- /* This sets rl_pending_input to c; it will be picked up the next
- time rl_read_key is called. */
- rl_execute_next (c);
- break;
- }
- }
- else
-#endif
- if (c >= 0 && ENDSRCH_CHAR (c))
- {
- /* This sets rl_pending_input to c; it will be picked up the next
- time rl_read_key is called. */
- rl_execute_next (c);
- break;
- }
-
- switch (c)
- {
- case -1:
- if (search_string_index == 0)
- {
- if (last_isearch_string)
- {
- search_string_size = 64 + last_isearch_string_len;
- search_string = (char *)xrealloc (search_string, search_string_size);
- strcpy (search_string, last_isearch_string);
- search_string_index = last_isearch_string_len;
- rl_display_search (search_string, reverse, -1);
- break;
- }
- continue;
- }
- else if (reverse)
- --line_index;
- else if (line_index != sline_len)
- ++line_index;
- else
- rl_ding ();
- break;
-
- /* switch directions */
- case -2:
- direction = -direction;
- reverse = direction < 0;
- 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 (search_string_index == 0)
- rl_ding ();
- else
- search_string[--search_string_index] = '\0';
-
- break;
-
- case -4: /* C-G */
- rl_replace_line (lines[orig_line], 0);
- rl_point = orig_point;
- rl_mark = orig_mark;
- rl_restore_prompt();
- rl_clear_message ();
- if (allocated_line)
- free (allocated_line);
- free (lines);
- RL_UNSETSTATE(RL_STATE_ISEARCH);
- return 0;
-
- case -5: /* C-W */
- /* skip over portion of line we already matched */
- wstart = rl_point + search_string_index;
- if (wstart >= rl_end)
- {
- rl_ding ();
- break;
- }
-
- /* if not in a word, move to one. */
- if (rl_alphabetic(rl_line_buffer[wstart]) == 0)
- {
- rl_ding ();
- break;
- }
- n = wstart;
- while (n < rl_end && rl_alphabetic(rl_line_buffer[n]))
- n++;
- wlen = n - wstart + 1;
- if (search_string_index + wlen + 1 >= search_string_size)
- {
- search_string_size += wlen + 1;
- search_string = (char *)xrealloc (search_string, search_string_size);
- }
- for (; wstart < n; wstart++)
- search_string[search_string_index++] = rl_line_buffer[wstart];
- search_string[search_string_index] = '\0';
- break;
-
- case -6: /* C-Y */
- /* skip over portion of line we already matched */
- wstart = rl_point + search_string_index;
- if (wstart >= rl_end)
- {
- rl_ding ();
- break;
- }
- n = rl_end - wstart + 1;
- if (search_string_index + n + 1 >= search_string_size)
- {
- search_string_size += n + 1;
- search_string = (char *)xrealloc (search_string, search_string_size);
- }
- for (n = wstart; n < rl_end; n++)
- search_string[search_string_index++] = rl_line_buffer[n];
- search_string[search_string_index] = '\0';
- break;
-
- default:
- /* Add character to search string and continue search. */
- if (search_string_index + 2 >= search_string_size)
- {
- search_string_size += 128;
- search_string = (char *)xrealloc (search_string, search_string_size);
- }
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- int j, l;
- for (j = 0, l = strlen (mb); j < l; )
- search_string[search_string_index++] = mb[j++];
- }
- else
-#endif
- search_string[search_string_index++] = c;
- search_string[search_string_index] = '\0';
- break;
- }
-
- for (found = failed = 0;;)
- {
- int limit = sline_len - search_string_index + 1;
-
- /* Search the current line. */
- while (reverse ? (line_index >= 0) : (line_index < limit))
- {
- if (STREQN (search_string, sline + line_index, search_string_index))
- {
- found++;
- break;
- }
- else
- line_index += direction;
- }
- if (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. */
- i += direction;
-
- /* At limit for direction? */
- if (reverse ? (i < 0) : (i == hlen))
- {
- failed++;
- break;
- }
-
- /* We will need these later. */
- sline = lines[i];
- sline_len = strlen (sline);
- }
- while ((prev_line_found && STREQ (prev_line_found, lines[i])) ||
- (search_string_index > sline_len));
-
- if (failed)
- break;
-
- /* Now set up the line for searching... */
- line_index = reverse ? sline_len - search_string_index : 0;
- }
-
- if (failed)
- {
- /* We cannot find the search string. Ding the bell. */
- rl_ding ();
- i = last_found_line;
- continue; /* XXX - was break */
- }
-
- /* 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 (found)
- {
- prev_line_found = lines[i];
- rl_replace_line (lines[i], 0);
- rl_point = line_index;
- last_found_line = i;
- rl_display_search (search_string, reverse, (i == orig_line) ? -1 : i);
- }
- }
-
- /* 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. */
-
- /* First put back the original state. */
- strcpy (rl_line_buffer, lines[orig_line]);
-
- rl_restore_prompt ();
-
- /* Save the search string for possible later use. */
- FREE (last_isearch_string);
- last_isearch_string = search_string;
- last_isearch_string_len = search_string_index;
-
- if (last_found_line < orig_line)
- rl_get_previous_history (orig_line - last_found_line, 0);
- else
- rl_get_next_history (last_found_line - orig_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 (line_index < 0)
- {
- if (last_found_line == orig_line)
- line_index = orig_point;
- else
- line_index = strlen (rl_line_buffer);
- rl_mark = orig_mark;
- }
-
- rl_point = line_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 ();
-
- FREE (allocated_line);
- free (lines);
-
- RL_UNSETSTATE(RL_STATE_ISEARCH);
-
- return 0;
-}
diff --git a/lib/readline/isearch.c~ b/lib/readline/isearch.c~
deleted file mode 100644
index d7d8520e..00000000
--- a/lib/readline/isearch.c~
+++ /dev/null
@@ -1,666 +0,0 @@
-/* **************************************************************** */
-/* */
-/* 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/kill.c~ b/lib/readline/kill.c~
deleted file mode 100644
index 1d3254c3..00000000
--- a/lib/readline/kill.c~
+++ /dev/null
@@ -1,693 +0,0 @@
-/* kill.c -- kill ring management. */
-
-/* Copyright (C) 1994 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>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h> /* for _POSIX_VERSION */
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.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 "xmalloc.h"
-
-/* **************************************************************** */
-/* */
-/* Killing Mechanism */
-/* */
-/* **************************************************************** */
-
-/* What we assume for a max number of kills. */
-#define DEFAULT_MAX_KILLS 10
-
-/* The real variable to look at to find out when to flush kills. */
-static int rl_max_kills = DEFAULT_MAX_KILLS;
-
-/* Where to store killed text. */
-static char **rl_kill_ring = (char **)NULL;
-
-/* Where we are in the kill ring. */
-static int rl_kill_index;
-
-/* How many slots we have in the kill ring. */
-static int rl_kill_ring_length;
-
-static int _rl_copy_to_kill_ring PARAMS((char *, int));
-static int region_kill_internal PARAMS((int));
-static int _rl_copy_word_as_kill PARAMS((int, int));
-static int rl_yank_nth_arg_internal PARAMS((int, int, int));
-
-/* How to say that you only want to save a certain amount
- of kill material. */
-int
-rl_set_retained_kills (num)
- int num;
-{
- return 0;
-}
-
-/* Add TEXT to the kill ring, allocating a new kill ring slot as necessary.
- This uses TEXT directly, so the caller must not free it. If APPEND is
- non-zero, and the last command was a kill, the text is appended to the
- current kill ring slot, otherwise prepended. */
-static int
-_rl_copy_to_kill_ring (text, append)
- char *text;
- int append;
-{
- char *old, *new;
- int slot;
-
- /* First, find the slot to work with. */
- if (_rl_last_command_was_kill == 0)
- {
- /* Get a new slot. */
- if (rl_kill_ring == 0)
- {
- /* If we don't have any defined, then make one. */
- rl_kill_ring = (char **)
- xmalloc (((rl_kill_ring_length = 1) + 1) * sizeof (char *));
- rl_kill_ring[slot = 0] = (char *)NULL;
- }
- else
- {
- /* We have to add a new slot on the end, unless we have
- exceeded the max limit for remembering kills. */
- slot = rl_kill_ring_length;
- if (slot == rl_max_kills)
- {
- register int i;
- free (rl_kill_ring[0]);
- for (i = 0; i < slot; i++)
- rl_kill_ring[i] = rl_kill_ring[i + 1];
- }
- else
- {
- slot = rl_kill_ring_length += 1;
- rl_kill_ring = (char **)xrealloc (rl_kill_ring, slot * sizeof (char *));
- }
- rl_kill_ring[--slot] = (char *)NULL;
- }
- }
- else
- slot = rl_kill_ring_length - 1;
-
- /* If the last command was a kill, prepend or append. */
- if (_rl_last_command_was_kill && rl_editing_mode != vi_mode)
- {
- old = rl_kill_ring[slot];
- new = (char *)xmalloc (1 + strlen (old) + strlen (text));
-
- if (append)
- {
- strcpy (new, old);
- strcat (new, text);
- }
- else
- {
- strcpy (new, text);
- strcat (new, old);
- }
- free (old);
- free (text);
- rl_kill_ring[slot] = new;
- }
- else
- rl_kill_ring[slot] = text;
-
- rl_kill_index = slot;
- return 0;
-}
-
-/* The way to kill something. This appends or prepends to the last
- kill, if the last command was a kill command. if FROM is less
- than TO, then the text is appended, otherwise prepended. If the
- last command was not a kill command, then a new slot is made for
- this kill. */
-int
-rl_kill_text (from, to)
- int from, to;
-{
- char *text;
-
- /* Is there anything to kill? */
- if (from == to)
- {
- _rl_last_command_was_kill++;
- return 0;
- }
-
- text = rl_copy_text (from, to);
-
- /* Delete the copied text from the line. */
- rl_delete_text (from, to);
-
- _rl_copy_to_kill_ring (text, from < to);
-
- _rl_last_command_was_kill++;
- return 0;
-}
-
-/* Now REMEMBER! In order to do prepending or appending correctly, kill
- commands always make rl_point's original position be the FROM argument,
- and rl_point's extent be the TO argument. */
-
-/* **************************************************************** */
-/* */
-/* Killing Commands */
-/* */
-/* **************************************************************** */
-
-/* Delete the word at point, saving the text in the kill ring. */
-int
-rl_kill_word (count, key)
- int count, key;
-{
- int orig_point;
-
- if (count < 0)
- return (rl_backward_kill_word (-count, key));
- else
- {
- orig_point = rl_point;
- rl_forward_word (count, key);
-
- if (rl_point != orig_point)
- rl_kill_text (orig_point, rl_point);
-
- rl_point = orig_point;
- if (rl_editing_mode == emacs_mode)
- rl_mark = rl_point;
- }
- return 0;
-}
-
-/* Rubout the word before point, placing it on the kill ring. */
-int
-rl_backward_kill_word (count, ignore)
- int count, ignore;
-{
- int orig_point;
-
- if (count < 0)
- return (rl_kill_word (-count, ignore));
- else
- {
- orig_point = rl_point;
- rl_backward_word (count, ignore);
-
- if (rl_point != orig_point)
- rl_kill_text (orig_point, rl_point);
-
- if (rl_editing_mode == emacs_mode)
- rl_mark = rl_point;
- }
- return 0;
-}
-
-/* Kill from here to the end of the line. If DIRECTION is negative, kill
- back to the line start instead. */
-int
-rl_kill_line (direction, ignore)
- int direction, ignore;
-{
- int orig_point;
-
- if (direction < 0)
- return (rl_backward_kill_line (1, ignore));
- else
- {
- orig_point = rl_point;
- rl_end_of_line (1, ignore);
- if (orig_point != rl_point)
- rl_kill_text (orig_point, rl_point);
- rl_point = orig_point;
- if (rl_editing_mode == emacs_mode)
- rl_mark = rl_point;
- }
- return 0;
-}
-
-/* Kill backwards to the start of the line. If DIRECTION is negative, kill
- forwards to the line end instead. */
-int
-rl_backward_kill_line (direction, ignore)
- int direction, ignore;
-{
- int orig_point;
-
- if (direction < 0)
- return (rl_kill_line (1, ignore));
- else
- {
- if (!rl_point)
- rl_ding ();
- else
- {
- orig_point = rl_point;
- rl_beg_of_line (1, ignore);
- if (rl_point != orig_point)
- rl_kill_text (orig_point, rl_point);
- if (rl_editing_mode == emacs_mode)
- rl_mark = rl_point;
- }
- }
- return 0;
-}
-
-/* Kill the whole line, no matter where point is. */
-int
-rl_kill_full_line (count, ignore)
- int count, ignore;
-{
- rl_begin_undo_group ();
- rl_point = 0;
- rl_kill_text (rl_point, rl_end);
- rl_mark = 0;
- rl_end_undo_group ();
- return 0;
-}
-
-/* The next two functions mimic unix line editing behaviour, except they
- save the deleted text on the kill ring. This is safer than not saving
- it, and since we have a ring, nobody should get screwed. */
-
-/* This does what C-w does in Unix. We can't prevent people from
- using behaviour that they expect. */
-int
-rl_unix_word_rubout (count, key)
- int count, key;
-{
- int orig_point;
-
- if (rl_point == 0)
- rl_ding ();
- else
- {
- orig_point = rl_point;
- if (count <= 0)
- count = 1;
-
- while (count--)
- {
- while (rl_point && whitespace (rl_line_buffer[rl_point - 1]))
- rl_point--;
-
- while (rl_point && (whitespace (rl_line_buffer[rl_point - 1]) == 0))
- rl_point--;
- }
-
- rl_kill_text (orig_point, rl_point);
- if (rl_editing_mode == emacs_mode)
- rl_mark = rl_point;
- }
-
- return 0;
-}
-
-/* This deletes one filename component in a Unix pathname. That is, it
- deletes backward to directory separator (`/') or whitespace. */
-int
-rl_unix_filename_rubout (count, key)
- int count, key;
-{
- int orig_point, c;
-
- if (rl_point == 0)
- rl_ding ();
- else
- {
- orig_point = rl_point;
- if (count <= 0)
- count = 1;
-
- while (count--)
- {
- c = rl_line_buffer[rl_point - 1];
- while (rl_point && (whitespace (c) || c == '/'))
- {
- rl_point--;
- c = rl_line_buffer[rl_point - 1];
- }
-
- while (rl_point && (whitespace (c) == 0) && c != '/')
- {
- rl_point--;
- c = rl_line_buffer[rl_point - 1];
- }
- }
-
- rl_kill_text (orig_point, rl_point);
- if (rl_editing_mode == emacs_mode)
- rl_mark = rl_point;
- }
-
- return 0;
-}
-
-/* Here is C-u doing what Unix does. You don't *have* to use these
- key-bindings. We have a choice of killing the entire line, or
- killing from where we are to the start of the line. We choose the
- latter, because if you are a Unix weenie, then you haven't backspaced
- into the line at all, and if you aren't, then you know what you are
- doing. */
-int
-rl_unix_line_discard (count, key)
- int count, key;
-{
- if (rl_point == 0)
- rl_ding ();
- else
- {
- rl_kill_text (rl_point, 0);
- rl_point = 0;
- if (rl_editing_mode == emacs_mode)
- rl_mark = rl_point;
- }
- return 0;
-}
-
-/* Copy the text in the `region' to the kill ring. If DELETE is non-zero,
- delete the text from the line as well. */
-static int
-region_kill_internal (delete)
- int delete;
-{
- char *text;
-
- if (rl_mark != rl_point)
- {
- text = rl_copy_text (rl_point, rl_mark);
- if (delete)
- rl_delete_text (rl_point, rl_mark);
- _rl_copy_to_kill_ring (text, rl_point < rl_mark);
- }
-
- _rl_last_command_was_kill++;
- return 0;
-}
-
-/* Copy the text in the region to the kill ring. */
-int
-rl_copy_region_to_kill (count, ignore)
- int count, ignore;
-{
- return (region_kill_internal (0));
-}
-
-/* Kill the text between the point and mark. */
-int
-rl_kill_region (count, ignore)
- int count, ignore;
-{
- int r, npoint;
-
- npoint = (rl_point < rl_mark) ? rl_point : rl_mark;
- r = region_kill_internal (1);
- _rl_fix_point (1);
- rl_point = npoint;
- return r;
-}
-
-/* Copy COUNT words to the kill ring. DIR says which direction we look
- to find the words. */
-static int
-_rl_copy_word_as_kill (count, dir)
- int count, dir;
-{
- int om, op, r;
-
- om = rl_mark;
- op = rl_point;
-
- if (dir > 0)
- rl_forward_word (count, 0);
- else
- rl_backward_word (count, 0);
-
- rl_mark = rl_point;
-
- if (dir > 0)
- rl_backward_word (count, 0);
- else
- rl_forward_word (count, 0);
-
- r = region_kill_internal (0);
-
- rl_mark = om;
- rl_point = op;
-
- return r;
-}
-
-int
-rl_copy_forward_word (count, key)
- int count, key;
-{
- if (count < 0)
- return (rl_copy_backward_word (-count, key));
-
- return (_rl_copy_word_as_kill (count, 1));
-}
-
-int
-rl_copy_backward_word (count, key)
- int count, key;
-{
- if (count < 0)
- return (rl_copy_forward_word (-count, key));
-
- return (_rl_copy_word_as_kill (count, -1));
-}
-
-/* Yank back the last killed text. This ignores arguments. */
-int
-rl_yank (count, ignore)
- int count, ignore;
-{
- if (rl_kill_ring == 0)
- {
- _rl_abort_internal ();
- return -1;
- }
-
- _rl_set_mark_at_pos (rl_point);
- rl_insert_text (rl_kill_ring[rl_kill_index]);
- return 0;
-}
-
-/* If the last command was yank, or yank_pop, and the text just
- before point is identical to the current kill item, then
- delete that text from the line, rotate the index down, and
- yank back some other text. */
-int
-rl_yank_pop (count, key)
- int count, key;
-{
- int l, n;
-
- if (((rl_last_func != rl_yank_pop) && (rl_last_func != rl_yank)) ||
- !rl_kill_ring)
- {
- _rl_abort_internal ();
- return -1;
- }
-
- l = strlen (rl_kill_ring[rl_kill_index]);
- n = rl_point - l;
- if (n >= 0 && STREQN (rl_line_buffer + n, rl_kill_ring[rl_kill_index], l))
- {
- rl_delete_text (n, rl_point);
- rl_point = n;
- rl_kill_index--;
- if (rl_kill_index < 0)
- rl_kill_index = rl_kill_ring_length - 1;
- rl_yank (1, 0);
- return 0;
- }
- else
- {
- _rl_abort_internal ();
- return -1;
- }
-}
-
-/* Yank the COUNTh argument from the previous history line, skipping
- HISTORY_SKIP lines before looking for the `previous line'. */
-static int
-rl_yank_nth_arg_internal (count, ignore, history_skip)
- int count, ignore, history_skip;
-{
- register HIST_ENTRY *entry;
- char *arg;
- int i, pos;
-
- pos = where_history ();
-
- if (history_skip)
- {
- for (i = 0; i < history_skip; i++)
- entry = previous_history ();
- }
-
- entry = previous_history ();
-
- history_set_pos (pos);
-
- if (entry == 0)
- {
- rl_ding ();
- return -1;
- }
-
- arg = history_arg_extract (count, count, entry->line);
- if (!arg || !*arg)
- {
- rl_ding ();
- return -1;
- }
-
- rl_begin_undo_group ();
-
- _rl_set_mark_at_pos (rl_point);
-
-#if defined (VI_MODE)
- /* Vi mode always inserts a space before yanking the argument, and it
- inserts it right *after* rl_point. */
- if (rl_editing_mode == vi_mode)
- {
- rl_vi_append_mode (1, ignore);
- rl_insert_text (" ");
- }
-#endif /* VI_MODE */
-
- rl_insert_text (arg);
- free (arg);
-
- rl_end_undo_group ();
- return 0;
-}
-
-/* Yank the COUNTth argument from the previous history line. */
-int
-rl_yank_nth_arg (count, ignore)
- int count, ignore;
-{
- return (rl_yank_nth_arg_internal (count, ignore, 0));
-}
-
-/* Yank the last argument from the previous history line. This `knows'
- how rl_yank_nth_arg treats a count of `$'. With an argument, this
- behaves the same as rl_yank_nth_arg. */
-int
-rl_yank_last_arg (count, key)
- int count, key;
-{
- static int history_skip = 0;
- static int explicit_arg_p = 0;
- static int count_passed = 1;
- static int direction = 1;
- static int undo_needed = 0;
- int retval;
-
- if (rl_last_func != rl_yank_last_arg)
- {
- history_skip = 0;
- explicit_arg_p = rl_explicit_arg;
- count_passed = count;
- direction = 1;
- }
- else
- {
- if (undo_needed)
- rl_do_undo ();
- if (count < 1)
- direction = -direction;
- history_skip += direction;
- if (history_skip < 0)
- history_skip = 0;
- }
-
- if (explicit_arg_p)
- retval = rl_yank_nth_arg_internal (count_passed, key, history_skip);
- else
- retval = rl_yank_nth_arg_internal ('$', key, history_skip);
-
- undo_needed = retval == 0;
- return retval;
-}
-
-/* A special paste command for users of Cygnus's cygwin32. */
-#if defined (__CYGWIN__)
-#include <windows.h>
-
-int
-rl_paste_from_clipboard (count, key)
- int count, key;
-{
- char *data, *ptr;
- int len;
-
- if (OpenClipboard (NULL) == 0)
- return (0);
-
- data = (char *)GetClipboardData (CF_TEXT);
- if (data)
- {
- ptr = strchr (data, '\r');
- if (ptr)
- {
- len = ptr - data;
- ptr = (char *)xmalloc (len + 1);
- ptr[len] = '\0';
- strncpy (ptr, data, len);
- }
- else
- ptr = data;
- _rl_set_mark_at_pos (rl_point);
- rl_insert_text (ptr);
- if (ptr != data)
- free (ptr);
- CloseClipboard ();
- }
- return (0);
-}
-#endif /* __CYGWIN__ */
diff --git a/lib/readline/misc.c~ b/lib/readline/misc.c~
deleted file mode 100644
index d4558321..00000000
--- a/lib/readline/misc.c~
+++ /dev/null
@@ -1,601 +0,0 @@
-/* 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/readline.c~ b/lib/readline/readline.c~
deleted file mode 100644
index d0924400..00000000
--- a/lib/readline/readline.c~
+++ /dev/null
@@ -1,1215 +0,0 @@
-/* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
-
-/* 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 <sys/types.h>
-#include "posixstat.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 */
-
-#if defined (HAVE_LOCALE_H)
-# include <locale.h>
-#endif
-
-#include <stdio.h>
-#include "posixjmp.h"
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-/* 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"
-
-#ifndef RL_LIBRARY_VERSION
-# define RL_LIBRARY_VERSION "5.1"
-#endif
-
-#ifndef RL_READLINE_VERSION
-# define RL_READLINE_VERSION 0x0501
-#endif
-
-extern void _rl_free_history_entry PARAMS((HIST_ENTRY *));
-
-/* Forward declarations used in this file. */
-static char *readline_internal PARAMS((void));
-static void readline_initialize_everything PARAMS((void));
-
-static void bind_arrow_keys_internal PARAMS((Keymap));
-static void bind_arrow_keys PARAMS((void));
-
-static void readline_default_bindings PARAMS((void));
-static void reset_default_bindings PARAMS((void));
-
-static int _rl_subseq_result PARAMS((int, Keymap, int, int));
-static int _rl_subseq_getchar PARAMS((int));
-
-/* **************************************************************** */
-/* */
-/* Line editing input utility */
-/* */
-/* **************************************************************** */
-
-const char *rl_library_version = RL_LIBRARY_VERSION;
-
-int rl_readline_version = RL_READLINE_VERSION;
-
-/* True if this is `real' readline as opposed to some stub substitute. */
-int rl_gnu_readline_p = 1;
-
-/* A pointer to the keymap that is currently in use.
- By default, it is the standard emacs keymap. */
-Keymap _rl_keymap = emacs_standard_keymap;
-
-
-/* The current style of editing. */
-int rl_editing_mode = emacs_mode;
-
-/* The current insert mode: input (the default) or overwrite */
-int rl_insert_mode = RL_IM_DEFAULT;
-
-/* Non-zero if we called this function from _rl_dispatch(). It's present
- so functions can find out whether they were called from a key binding
- or directly from an application. */
-int rl_dispatching;
-
-/* Non-zero if the previous command was a kill command. */
-int _rl_last_command_was_kill = 0;
-
-/* The current value of the numeric argument specified by the user. */
-int rl_numeric_arg = 1;
-
-/* Non-zero if an argument was typed. */
-int rl_explicit_arg = 0;
-
-/* Temporary value used while generating the argument. */
-int rl_arg_sign = 1;
-
-/* Non-zero means we have been called at least once before. */
-static int rl_initialized;
-
-#if 0
-/* If non-zero, this program is running in an EMACS buffer. */
-static int running_in_emacs;
-#endif
-
-/* Flags word encapsulating the current readline state. */
-int rl_readline_state = RL_STATE_NONE;
-
-/* The current offset in the current input line. */
-int rl_point;
-
-/* Mark in the current input line. */
-int rl_mark;
-
-/* Length of the current input line. */
-int rl_end;
-
-/* Make this non-zero to return the current input_line. */
-int rl_done;
-
-/* The last function executed by readline. */
-rl_command_func_t *rl_last_func = (rl_command_func_t *)NULL;
-
-/* Top level environment for readline_internal (). */
-procenv_t readline_top_level;
-
-/* The streams we interact with. */
-FILE *_rl_in_stream, *_rl_out_stream;
-
-/* The names of the streams that we do input and output to. */
-FILE *rl_instream = (FILE *)NULL;
-FILE *rl_outstream = (FILE *)NULL;
-
-/* Non-zero means echo characters as they are read. Defaults to no echo;
- set to 1 if there is a controlling terminal, we can get its attributes,
- and the attributes include `echo'. Look at rltty.c:prepare_terminal_settings
- for the code that sets it. */
-int readline_echoing_p = 0;
-
-/* Current prompt. */
-char *rl_prompt = (char *)NULL;
-int rl_visible_prompt_length = 0;
-
-/* Set to non-zero by calling application if it has already printed rl_prompt
- and does not want readline to do it the first time. */
-int rl_already_prompted = 0;
-
-/* The number of characters read in order to type this complete command. */
-int rl_key_sequence_length = 0;
-
-/* If non-zero, then this is the address of a function to call just
- before readline_internal_setup () prints the first prompt. */
-rl_hook_func_t *rl_startup_hook = (rl_hook_func_t *)NULL;
-
-/* If non-zero, this is the address of a function to call just before
- readline_internal_setup () returns and readline_internal starts
- reading input characters. */
-rl_hook_func_t *rl_pre_input_hook = (rl_hook_func_t *)NULL;
-
-/* What we use internally. You should always refer to RL_LINE_BUFFER. */
-static char *the_line;
-
-/* The character that can generate an EOF. Really read from
- the terminal driver... just defaulted here. */
-int _rl_eof_char = CTRL ('D');
-
-/* Non-zero makes this the next keystroke to read. */
-int rl_pending_input = 0;
-
-/* Pointer to a useful terminal name. */
-const char *rl_terminal_name = (const char *)NULL;
-
-/* Non-zero means to always use horizontal scrolling in line display. */
-int _rl_horizontal_scroll_mode = 0;
-
-/* Non-zero means to display an asterisk at the starts of history lines
- which have been modified. */
-int _rl_mark_modified_lines = 0;
-
-/* The style of `bell' notification preferred. This can be set to NO_BELL,
- AUDIBLE_BELL, or VISIBLE_BELL. */
-int _rl_bell_preference = AUDIBLE_BELL;
-
-/* String inserted into the line by rl_insert_comment (). */
-char *_rl_comment_begin;
-
-/* Keymap holding the function currently being executed. */
-Keymap rl_executing_keymap;
-
-/* Keymap we're currently using to dispatch. */
-Keymap _rl_dispatching_keymap;
-
-/* Non-zero means to erase entire line, including prompt, on empty input lines. */
-int rl_erase_empty_line = 0;
-
-/* Non-zero means to read only this many characters rather than up to a
- character bound to accept-line. */
-int rl_num_chars_to_read;
-
-/* Line buffer and maintenence. */
-char *rl_line_buffer = (char *)NULL;
-int rl_line_buffer_len = 0;
-
-/* Key sequence `contexts' */
-_rl_keyseq_cxt *_rl_kscxt = 0;
-
-/* Forward declarations used by the display, termcap, and history code. */
-
-/* **************************************************************** */
-/* */
-/* `Forward' declarations */
-/* */
-/* **************************************************************** */
-
-/* Non-zero means do not parse any lines other than comments and
- parser directives. */
-unsigned char _rl_parsing_conditionalized_out = 0;
-
-/* Non-zero means to convert characters with the meta bit set to
- escape-prefixed characters so we can indirect through
- emacs_meta_keymap or vi_escape_keymap. */
-int _rl_convert_meta_chars_to_ascii = 1;
-
-/* Non-zero means to output characters with the meta bit set directly
- rather than as a meta-prefixed escape sequence. */
-int _rl_output_meta_chars = 0;
-
-/* Non-zero means to look at the termios special characters and bind
- them to equivalent readline functions at startup. */
-int _rl_bind_stty_chars = 1;
-
-/* **************************************************************** */
-/* */
-/* Top Level Functions */
-/* */
-/* **************************************************************** */
-
-/* Non-zero means treat 0200 bit in terminal input as Meta bit. */
-int _rl_meta_flag = 0; /* Forward declaration */
-
-/* Set up the prompt and expand it. Called from readline() and
- rl_callback_handler_install (). */
-int
-rl_set_prompt (prompt)
- const char *prompt;
-{
- FREE (rl_prompt);
- rl_prompt = prompt ? savestring (prompt) : (char *)NULL;
- rl_display_prompt = rl_prompt ? rl_prompt : "";
-
- rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
- return 0;
-}
-
-/* Read a line of input. Prompt with PROMPT. An empty PROMPT means
- none. A return value of NULL means that EOF was encountered. */
-char *
-readline (prompt)
- const char *prompt;
-{
- char *value;
-
- /* If we are at EOF return a NULL string. */
- if (rl_pending_input == EOF)
- {
- rl_clear_pending_input ();
- return ((char *)NULL);
- }
-
- rl_set_prompt (prompt);
-
- rl_initialize ();
- if (rl_prep_term_function)
- (*rl_prep_term_function) (_rl_meta_flag);
-
-#if defined (HANDLE_SIGNALS)
- rl_set_signals ();
-#endif
-
- value = readline_internal ();
- if (rl_deprep_term_function)
- (*rl_deprep_term_function) ();
-
-#if defined (HANDLE_SIGNALS)
- rl_clear_signals ();
-#endif
-
- return (value);
-}
-
-#if defined (READLINE_CALLBACKS)
-# define STATIC_CALLBACK
-#else
-# define STATIC_CALLBACK static
-#endif
-
-STATIC_CALLBACK void
-readline_internal_setup ()
-{
- char *nprompt;
-
- _rl_in_stream = rl_instream;
- _rl_out_stream = rl_outstream;
-
- if (rl_startup_hook)
- (*rl_startup_hook) ();
-
- /* If we're not echoing, we still want to at least print a prompt, because
- rl_redisplay will not do it for us. If the calling application has a
- custom redisplay function, though, let that function handle it. */
- if (readline_echoing_p == 0 && rl_redisplay_function == rl_redisplay)
- {
- if (rl_prompt && rl_already_prompted == 0)
- {
- nprompt = _rl_strip_prompt (rl_prompt);
- fprintf (_rl_out_stream, "%s", nprompt);
- fflush (_rl_out_stream);
- free (nprompt);
- }
- }
- else
- {
- if (rl_prompt && rl_already_prompted)
- rl_on_new_line_with_prompt ();
- else
- rl_on_new_line ();
- (*rl_redisplay_function) ();
- }
-
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_vi_insertion_mode (1, 'i');
-#endif /* VI_MODE */
-
- if (rl_pre_input_hook)
- (*rl_pre_input_hook) ();
-}
-
-STATIC_CALLBACK char *
-readline_internal_teardown (eof)
- int eof;
-{
- char *temp;
- HIST_ENTRY *entry;
-
- /* Restore the original of this history line, iff the line that we
- are editing was originally in the history, AND the line has changed. */
- entry = current_history ();
-
- if (entry && rl_undo_list)
- {
- temp = savestring (the_line);
- rl_revert_line (1, 0);
- entry = replace_history_entry (where_history (), the_line, (histdata_t)NULL);
- _rl_free_history_entry (entry);
-
- strcpy (the_line, temp);
- free (temp);
- }
-
- /* At any rate, it is highly likely that this line has an undo list. Get
- rid of it now. */
- if (rl_undo_list)
- rl_free_undo_list ();
-
- /* Restore normal cursor, if available. */
- _rl_set_insert_mode (RL_IM_INSERT, 0);
-
- return (eof ? (char *)NULL : savestring (the_line));
-}
-
-void
-_rl_internal_char_cleanup ()
-{
-#if defined (VI_MODE)
- /* In vi mode, when you exit insert mode, the cursor moves back
- over the previous character. We explicitly check for that here. */
- if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
- rl_vi_check ();
-#endif /* VI_MODE */
-
- if (rl_num_chars_to_read && rl_end >= rl_num_chars_to_read)
- {
- (*rl_redisplay_function) ();
- _rl_want_redisplay = 0;
- rl_newline (1, '\n');
- }
-
- if (rl_done == 0)
- {
- (*rl_redisplay_function) ();
- _rl_want_redisplay = 0;
- }
-
- /* If the application writer has told us to erase the entire line if
- the only character typed was something bound to rl_newline, do so. */
- if (rl_erase_empty_line && rl_done && rl_last_func == rl_newline &&
- rl_point == 0 && rl_end == 0)
- _rl_erase_entire_line ();
-}
-
-STATIC_CALLBACK int
-#if defined (READLINE_CALLBACKS)
-readline_internal_char ()
-#else
-readline_internal_charloop ()
-#endif
-{
- static int lastc, eof_found;
- int c, code, lk;
-
- lastc = -1;
- eof_found = 0;
-
-#if !defined (READLINE_CALLBACKS)
- while (rl_done == 0)
- {
-#endif
- lk = _rl_last_command_was_kill;
-
- code = setjmp (readline_top_level);
-
- if (code)
- {
- (*rl_redisplay_function) ();
- _rl_want_redisplay = 0;
- /* If we get here, we're not being called from something dispatched
- from _rl_callback_read_char(), which sets up its own value of
- readline_top_level (saving and restoring the old, of course), so
- we can just return here. */
- if (RL_ISSTATE (RL_STATE_CALLBACK))
- return (0);
- }
-
- if (rl_pending_input == 0)
- {
- /* Then initialize the argument and number of keys read. */
- _rl_reset_argument ();
- rl_key_sequence_length = 0;
- }
-
- RL_SETSTATE(RL_STATE_READCMD);
- c = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_READCMD);
-
- if (c == READERR)
- {
-fprintf(stderr, "\r\nread error, errno = %d\r\n", errno);
-#if defined (READLINE_CALLBACKS)
- RL_SETSTATE(RL_STATE_DONE);
- return (rl_done = 1);
-#else
- eof_found = 1;
- break;
-#endif
- }
-
- /* EOF typed to a non-blank line is a <NL>. */
- if (c == EOF && rl_end)
-{
-fprintf(stderr, "\r\nsaw EOF on non-empty line, converting to newline\r\n");
-sleep(4);
- c = NEWLINE;
-}
- /* The character _rl_eof_char typed to blank line, and not as the
- previous character is interpreted as EOF. */
- if (((c == _rl_eof_char && lastc != c) || c == EOF) && !rl_end)
- {
-#if defined (READLINE_CALLBACKS)
- RL_SETSTATE(RL_STATE_DONE);
- return (rl_done = 1);
-#else
- eof_found = 1;
- break;
-#endif
- }
-
- lastc = c;
- _rl_dispatch ((unsigned char)c, _rl_keymap);
-
- /* If there was no change in _rl_last_command_was_kill, then no kill
- has taken place. Note that if input is pending we are reading
- a prefix command, so nothing has changed yet. */
- if (rl_pending_input == 0 && lk == _rl_last_command_was_kill)
- _rl_last_command_was_kill = 0;
-
- _rl_internal_char_cleanup ();
-
-#if defined (READLINE_CALLBACKS)
- return 0;
-#else
- }
-
- return (eof_found);
-#endif
-}
-
-#if defined (READLINE_CALLBACKS)
-static int
-readline_internal_charloop ()
-{
- int eof = 1;
-
- while (rl_done == 0)
- eof = readline_internal_char ();
- return (eof);
-}
-#endif /* READLINE_CALLBACKS */
-
-/* Read a line of input from the global rl_instream, doing output on
- the global rl_outstream.
- If rl_prompt is non-null, then that is our prompt. */
-static char *
-readline_internal ()
-{
- int eof;
-
- readline_internal_setup ();
- eof = readline_internal_charloop ();
- return (readline_internal_teardown (eof));
-}
-
-void
-_rl_init_line_state ()
-{
- rl_point = rl_end = rl_mark = 0;
- the_line = rl_line_buffer;
- the_line[0] = 0;
-}
-
-void
-_rl_set_the_line ()
-{
- the_line = rl_line_buffer;
-}
-
-#if defined (READLINE_CALLBACKS)
-_rl_keyseq_cxt *
-_rl_keyseq_cxt_alloc ()
-{
- _rl_keyseq_cxt *cxt;
-
- cxt = (_rl_keyseq_cxt *)xmalloc (sizeof (_rl_keyseq_cxt));
-
- cxt->flags = cxt->subseq_arg = cxt->subseq_retval = 0;
-
- cxt->okey = 0;
- cxt->ocxt = _rl_kscxt;
- cxt->childval = 42; /* sentinel value */
-
- return cxt;
-}
-
-void
-_rl_keyseq_cxt_dispose (cxt)
- _rl_keyseq_cxt *cxt;
-{
- free (cxt);
-}
-
-void
-_rl_keyseq_chain_dispose ()
-{
- _rl_keyseq_cxt *cxt;
-
- while (_rl_kscxt)
- {
- cxt = _rl_kscxt;
- _rl_kscxt = _rl_kscxt->ocxt;
- _rl_keyseq_cxt_dispose (cxt);
- }
-}
-#endif
-
-static int
-_rl_subseq_getchar (key)
- int key;
-{
- int k;
-
- if (key == ESC)
- RL_SETSTATE(RL_STATE_METANEXT);
- RL_SETSTATE(RL_STATE_MOREINPUT);
- k = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
- if (key == ESC)
- RL_UNSETSTATE(RL_STATE_METANEXT);
-
- return k;
-}
-
-#if defined (READLINE_CALLBACKS)
-int
-_rl_dispatch_callback (cxt)
- _rl_keyseq_cxt *cxt;
-{
- int nkey, r;
-
- /* For now */
-#if 1
- /* The first time this context is used, we want to read input and dispatch
- on it. When traversing the chain of contexts back `up', we want to use
- the value from the next context down. We're simulating recursion using
- a chain of contexts. */
- if ((cxt->flags & KSEQ_DISPATCHED) == 0)
- {
- nkey = _rl_subseq_getchar (cxt->okey);
- r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg);
- cxt->flags |= KSEQ_DISPATCHED;
- }
- else
- r = cxt->childval;
-#else
- r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg);
-#endif
-
- /* For now */
- r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ));
-
- if (r == 0) /* success! */
- {
- _rl_keyseq_chain_dispose ();
- RL_UNSETSTATE (RL_STATE_MULTIKEY);
- return r;
- }
-
- if (r != -3) /* magic value that says we added to the chain */
- _rl_kscxt = cxt->ocxt;
- if (_rl_kscxt)
- _rl_kscxt->childval = r;
- if (r != -3)
- _rl_keyseq_cxt_dispose (cxt);
-
- return r;
-}
-#endif /* READLINE_CALLBACKS */
-
-/* Do the command associated with KEY in MAP.
- If the associated command is really a keymap, then read
- another key, and dispatch into that map. */
-int
-_rl_dispatch (key, map)
- register int key;
- Keymap map;
-{
- _rl_dispatching_keymap = map;
- return _rl_dispatch_subseq (key, map, 0);
-}
-
-int
-_rl_dispatch_subseq (key, map, got_subseq)
- register int key;
- Keymap map;
- int got_subseq;
-{
- int r, newkey;
- char *macro;
- rl_command_func_t *func;
-#if defined (READLINE_CALLBACKS)
- _rl_keyseq_cxt *cxt;
-#endif
-
- if (META_CHAR (key) && _rl_convert_meta_chars_to_ascii)
- {
- if (map[ESC].type == ISKMAP)
- {
- if (RL_ISSTATE (RL_STATE_MACRODEF))
- _rl_add_macro_char (ESC);
- map = FUNCTION_TO_KEYMAP (map, ESC);
- key = UNMETA (key);
- rl_key_sequence_length += 2;
- return (_rl_dispatch (key, map));
- }
- else
- rl_ding ();
- return 0;
- }
-
- if (RL_ISSTATE (RL_STATE_MACRODEF))
- _rl_add_macro_char (key);
-
- r = 0;
- switch (map[key].type)
- {
- case ISFUNC:
- func = map[key].function;
- if (func)
- {
- /* Special case rl_do_lowercase_version (). */
- if (func == rl_do_lowercase_version)
- return (_rl_dispatch (_rl_to_lower (key), map));
-
- rl_executing_keymap = map;
-
- rl_dispatching = 1;
- RL_SETSTATE(RL_STATE_DISPATCHING);
- (*map[key].function)(rl_numeric_arg * rl_arg_sign, key);
- RL_UNSETSTATE(RL_STATE_DISPATCHING);
- rl_dispatching = 0;
-
- /* If we have input pending, then the last command was a prefix
- command. Don't change the state of rl_last_func. Otherwise,
- remember the last command executed in this variable. */
- if (rl_pending_input == 0 && map[key].function != rl_digit_argument)
- rl_last_func = map[key].function;
- }
- else if (map[ANYOTHERKEY].function)
- {
- /* OK, there's no function bound in this map, but there is a
- shadow function that was overridden when the current keymap
- was created. Return -2 to note that. */
- _rl_unget_char (key);
- return -2;
- }
- else if (got_subseq)
- {
- /* Return -1 to note that we're in a subsequence, but we don't
- have a matching key, nor was one overridden. This means
- we need to back up the recursion chain and find the last
- subsequence that is bound to a function. */
- _rl_unget_char (key);
- return -1;
- }
- else
- {
-#if defined (READLINE_CALLBACKS)
- RL_UNSETSTATE (RL_STATE_MULTIKEY);
- _rl_keyseq_chain_dispose ();
-#endif
- _rl_abort_internal ();
- return -1;
- }
- break;
-
- case ISKMAP:
- if (map[key].function != 0)
- {
-#if defined (VI_MODE)
- /* The only way this test will be true is if a subsequence has been
- bound starting with ESC, generally the arrow keys. What we do is
- check whether there's input in the queue, which there generally
- will be if an arrow key has been pressed, and, if there's not,
- just dispatch to (what we assume is) rl_vi_movement_mode right
- away. This is essentially an input test with a zero timeout. */
- if (rl_editing_mode == vi_mode && key == ESC && map == vi_insertion_keymap
- && _rl_input_queued (0) == 0)
- return (_rl_dispatch (ANYOTHERKEY, FUNCTION_TO_KEYMAP (map, key)));
-#endif
-
- rl_key_sequence_length++;
- _rl_dispatching_keymap = FUNCTION_TO_KEYMAP (map, key);
-
- /* Allocate new context here. Use linked contexts (linked through
- cxt->ocxt) to simulate recursion */
-#if defined (READLINE_CALLBACKS)
- if (RL_ISSTATE (RL_STATE_CALLBACK))
- {
- /* Return 0 only the first time, to indicate success to
- _rl_callback_read_char. The rest of the time, we're called
- from _rl_dispatch_callback, so we return 3 to indicate
- special handling is necessary. */
- r = RL_ISSTATE (RL_STATE_MULTIKEY) ? -3 : 0;
- cxt = _rl_keyseq_cxt_alloc ();
-
- if (got_subseq)
- cxt->flags |= KSEQ_SUBSEQ;
- cxt->okey = key;
- cxt->oldmap = map;
- cxt->dmap = _rl_dispatching_keymap;
- cxt->subseq_arg = got_subseq || cxt->dmap[ANYOTHERKEY].function;
-
- RL_SETSTATE (RL_STATE_MULTIKEY);
- _rl_kscxt = cxt;
-
- return r; /* don't indicate immediate success */
- }
-#endif
-
- newkey = _rl_subseq_getchar (key);
- if (newkey < 0)
- {
- _rl_abort_internal ();
- return -1;
- }
-
- r = _rl_dispatch_subseq (newkey, _rl_dispatching_keymap, got_subseq || map[ANYOTHERKEY].function);
- return _rl_subseq_result (r, map, key, got_subseq);
- }
- else
- {
- _rl_abort_internal ();
- return -1;
- }
- break;
-
- case ISMACR:
- if (map[key].function != 0)
- {
- macro = savestring ((char *)map[key].function);
- _rl_with_macro_input (macro);
- return 0;
- }
- break;
- }
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap &&
- key != ANYOTHERKEY &&
- _rl_vi_textmod_command (key))
- _rl_vi_set_last (key, rl_numeric_arg, rl_arg_sign);
-#endif
-
- return (r);
-}
-
-static int
-_rl_subseq_result (r, map, key, got_subseq)
- int r;
- Keymap map;
- int key, got_subseq;
-{
- Keymap m;
- int type, nt;
- rl_command_func_t *func, *nf;
-
- if (r == -2)
- /* We didn't match anything, and the keymap we're indexed into
- shadowed a function previously bound to that prefix. Call
- the function. The recursive call to _rl_dispatch_subseq has
- already taken care of pushing any necessary input back onto
- the input queue with _rl_unget_char. */
- {
- m = _rl_dispatching_keymap;
- type = m[ANYOTHERKEY].type;
- func = m[ANYOTHERKEY].function;
- if (type == ISFUNC && func == rl_do_lowercase_version)
- r = _rl_dispatch (_rl_to_lower (key), map);
- else if (type == ISFUNC && func == rl_insert)
- {
- /* If the function that was shadowed was self-insert, we
- somehow need a keymap with map[key].func == self-insert.
- Let's use this one. */
- nt = m[key].type;
- nf = m[key].function;
-
- m[key].type = type;
- m[key].function = func;
- r = _rl_dispatch (key, m);
- m[key].type = nt;
- m[key].function = nf;
- }
- else
- r = _rl_dispatch (ANYOTHERKEY, m);
- }
- else if (r && map[ANYOTHERKEY].function)
- {
- /* We didn't match (r is probably -1), so return something to
- tell the caller that it should try ANYOTHERKEY for an
- overridden function. */
- _rl_unget_char (key);
- _rl_dispatching_keymap = map;
- return -2;
- }
- else if (r && got_subseq)
- {
- /* OK, back up the chain. */
- _rl_unget_char (key);
- _rl_dispatching_keymap = map;
- return -1;
- }
-
- return r;
-}
-
-/* **************************************************************** */
-/* */
-/* Initializations */
-/* */
-/* **************************************************************** */
-
-/* Initialize readline (and terminal if not already). */
-int
-rl_initialize ()
-{
- /* If we have never been called before, initialize the
- terminal and data structures. */
- if (!rl_initialized)
- {
- RL_SETSTATE(RL_STATE_INITIALIZING);
- readline_initialize_everything ();
- RL_UNSETSTATE(RL_STATE_INITIALIZING);
- rl_initialized++;
- RL_SETSTATE(RL_STATE_INITIALIZED);
- }
-
- /* Initalize the current line information. */
- _rl_init_line_state ();
-
- /* We aren't done yet. We haven't even gotten started yet! */
- rl_done = 0;
- RL_UNSETSTATE(RL_STATE_DONE);
-
- /* Tell the history routines what is going on. */
- _rl_start_using_history ();
-
- /* Make the display buffer match the state of the line. */
- rl_reset_line_state ();
-
- /* No such function typed yet. */
- rl_last_func = (rl_command_func_t *)NULL;
-
- /* Parsing of key-bindings begins in an enabled state. */
- _rl_parsing_conditionalized_out = 0;
-
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- _rl_vi_initialize_line ();
-#endif
-
- /* Each line starts in insert mode (the default). */
- _rl_set_insert_mode (RL_IM_DEFAULT, 1);
-
- return 0;
-}
-
-#if 0
-#if defined (__EMX__)
-static void
-_emx_build_environ ()
-{
- TIB *tibp;
- PIB *pibp;
- char *t, **tp;
- int c;
-
- DosGetInfoBlocks (&tibp, &pibp);
- t = pibp->pib_pchenv;
- for (c = 1; *t; c++)
- t += strlen (t) + 1;
- tp = environ = (char **)xmalloc ((c + 1) * sizeof (char *));
- t = pibp->pib_pchenv;
- while (*t)
- {
- *tp++ = t;
- t += strlen (t) + 1;
- }
- *tp = 0;
-}
-#endif /* __EMX__ */
-#endif
-
-/* Initialize the entire state of the world. */
-static void
-readline_initialize_everything ()
-{
-#if 0
-#if defined (__EMX__)
- if (environ == 0)
- _emx_build_environ ();
-#endif
-#endif
-
-#if 0
- /* Find out if we are running in Emacs -- UNUSED. */
- running_in_emacs = sh_get_env_value ("EMACS") != (char *)0;
-#endif
-
- /* Set up input and output if they are not already set up. */
- if (!rl_instream)
- rl_instream = stdin;
-
- if (!rl_outstream)
- rl_outstream = stdout;
-
- /* Bind _rl_in_stream and _rl_out_stream immediately. These values
- may change, but they may also be used before readline_internal ()
- is called. */
- _rl_in_stream = rl_instream;
- _rl_out_stream = rl_outstream;
-
- /* Allocate data structures. */
- if (rl_line_buffer == 0)
- rl_line_buffer = (char *)xmalloc (rl_line_buffer_len = DEFAULT_BUFFER_SIZE);
-
- /* Initialize the terminal interface. */
- if (rl_terminal_name == 0)
- rl_terminal_name = sh_get_env_value ("TERM");
- _rl_init_terminal_io (rl_terminal_name);
-
- /* Bind tty characters to readline functions. */
- readline_default_bindings ();
-
- /* Initialize the function names. */
- rl_initialize_funmap ();
-
- /* Decide whether we should automatically go into eight-bit mode. */
- _rl_init_eightbit ();
-
- /* Read in the init file. */
- rl_read_init_file ((char *)NULL);
-
- /* XXX */
- if (_rl_horizontal_scroll_mode && _rl_term_autowrap)
- {
- _rl_screenwidth--;
- _rl_screenchars -= _rl_screenheight;
- }
-
- /* Override the effect of any `set keymap' assignments in the
- inputrc file. */
- rl_set_keymap_from_edit_mode ();
-
- /* Try to bind a common arrow key prefix, if not already bound. */
- bind_arrow_keys ();
-
- /* Enable the meta key, if this terminal has one. */
- if (_rl_enable_meta)
- _rl_enable_meta_key ();
-
- /* If the completion parser's default word break characters haven't
- been set yet, then do so now. */
- if (rl_completer_word_break_characters == (char *)NULL)
- rl_completer_word_break_characters = (char *)rl_basic_word_break_characters;
-}
-
-/* If this system allows us to look at the values of the regular
- input editing characters, then bind them to their readline
- equivalents, iff the characters are not bound to keymaps. */
-static void
-readline_default_bindings ()
-{
- if (_rl_bind_stty_chars)
- rl_tty_set_default_bindings (_rl_keymap);
-}
-
-/* Reset the default bindings for the terminal special characters we're
- interested in back to rl_insert and read the new ones. */
-static void
-reset_default_bindings ()
-{
- if (_rl_bind_stty_chars)
- {
- rl_tty_unset_default_bindings (_rl_keymap);
- rl_tty_set_default_bindings (_rl_keymap);
- }
-}
-
-/* Bind some common arrow key sequences in MAP. */
-static void
-bind_arrow_keys_internal (map)
- Keymap map;
-{
- Keymap xkeymap;
-
- xkeymap = _rl_keymap;
- _rl_keymap = map;
-
-#if defined (__MSDOS__)
- rl_bind_keyseq_if_unbound ("\033[0A", rl_get_previous_history);
- rl_bind_keyseq_if_unbound ("\033[0B", rl_backward_char);
- rl_bind_keyseq_if_unbound ("\033[0C", rl_forward_char);
- rl_bind_keyseq_if_unbound ("\033[0D", rl_get_next_history);
-#endif
-
- rl_bind_keyseq_if_unbound ("\033[A", rl_get_previous_history);
- rl_bind_keyseq_if_unbound ("\033[B", rl_get_next_history);
- rl_bind_keyseq_if_unbound ("\033[C", rl_forward_char);
- rl_bind_keyseq_if_unbound ("\033[D", rl_backward_char);
- rl_bind_keyseq_if_unbound ("\033[H", rl_beg_of_line);
- rl_bind_keyseq_if_unbound ("\033[F", rl_end_of_line);
-
- rl_bind_keyseq_if_unbound ("\033OA", rl_get_previous_history);
- rl_bind_keyseq_if_unbound ("\033OB", rl_get_next_history);
- rl_bind_keyseq_if_unbound ("\033OC", rl_forward_char);
- rl_bind_keyseq_if_unbound ("\033OD", rl_backward_char);
- rl_bind_keyseq_if_unbound ("\033OH", rl_beg_of_line);
- rl_bind_keyseq_if_unbound ("\033OF", rl_end_of_line);
-
-#if defined (__MINGW32__)
- rl_bind_keyseq_if_unbound ("\340H", rl_get_previous_history);
- rl_bind_keyseq_if_unbound ("\340P", rl_get_next_history);
- rl_bind_keyseq_if_unbound ("\340M", rl_forward_char);
- rl_bind_keyseq_if_unbound ("\340K", rl_backward_char);
-#endif
-
- _rl_keymap = xkeymap;
-}
-
-/* Try and bind the common arrow key prefixes after giving termcap and
- the inputrc file a chance to bind them and create `real' keymaps
- for the arrow key prefix. */
-static void
-bind_arrow_keys ()
-{
- bind_arrow_keys_internal (emacs_standard_keymap);
-
-#if defined (VI_MODE)
- bind_arrow_keys_internal (vi_movement_keymap);
- bind_arrow_keys_internal (vi_insertion_keymap);
-#endif
-}
-
-/* **************************************************************** */
-/* */
-/* Saving and Restoring Readline's state */
-/* */
-/* **************************************************************** */
-
-int
-rl_save_state (sp)
- struct readline_state *sp;
-{
- if (sp == 0)
- return -1;
-
- sp->point = rl_point;
- sp->end = rl_end;
- sp->mark = rl_mark;
- sp->buffer = rl_line_buffer;
- sp->buflen = rl_line_buffer_len;
- sp->ul = rl_undo_list;
- sp->prompt = rl_prompt;
-
- sp->rlstate = rl_readline_state;
- sp->done = rl_done;
- sp->kmap = _rl_keymap;
-
- sp->lastfunc = rl_last_func;
- sp->insmode = rl_insert_mode;
- sp->edmode = rl_editing_mode;
- sp->kseqlen = rl_key_sequence_length;
- sp->inf = rl_instream;
- sp->outf = rl_outstream;
- sp->pendingin = rl_pending_input;
- sp->macro = rl_executing_macro;
-
- sp->catchsigs = rl_catch_signals;
- sp->catchsigwinch = rl_catch_sigwinch;
-
- return (0);
-}
-
-int
-rl_restore_state (sp)
- struct readline_state *sp;
-{
- if (sp == 0)
- return -1;
-
- rl_point = sp->point;
- rl_end = sp->end;
- rl_mark = sp->mark;
- the_line = rl_line_buffer = sp->buffer;
- rl_line_buffer_len = sp->buflen;
- rl_undo_list = sp->ul;
- rl_prompt = sp->prompt;
-
- rl_readline_state = sp->rlstate;
- rl_done = sp->done;
- _rl_keymap = sp->kmap;
-
- rl_last_func = sp->lastfunc;
- rl_insert_mode = sp->insmode;
- rl_editing_mode = sp->edmode;
- rl_key_sequence_length = sp->kseqlen;
- rl_instream = sp->inf;
- rl_outstream = sp->outf;
- rl_pending_input = sp->pendingin;
- rl_executing_macro = sp->macro;
-
- rl_catch_signals = sp->catchsigs;
- rl_catch_sigwinch = sp->catchsigwinch;
-
- return (0);
-}
diff --git a/lib/readline/readline.h~ b/lib/readline/readline.h~
deleted file mode 100644
index 6eb682cd..00000000
--- a/lib/readline/readline.h~
+++ /dev/null
@@ -1,849 +0,0 @@
-/* Readline.h -- the names of functions callable from within 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. */
-
-#if !defined (_READLINE_H_)
-#define _READLINE_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined (READLINE_LIBRARY)
-# include "rlstdc.h"
-# include "rltypedefs.h"
-# include "keymaps.h"
-# include "tilde.h"
-#else
-# include <readline/rlstdc.h>
-# include <readline/rltypedefs.h>
-# include <readline/keymaps.h>
-# include <readline/tilde.h>
-#endif
-
-/* Hex-encoded Readline version number. */
-#define RL_READLINE_VERSION 0x0502 /* Readline 5.2 */
-#define RL_VERSION_MAJOR 5
-#define RL_VERSION_MINOR 2
-
-/* Readline data structures. */
-
-/* Maintaining the state of undo. We remember individual deletes and inserts
- on a chain of things to do. */
-
-/* The actions that undo knows how to undo. Notice that UNDO_DELETE means
- to insert some text, and UNDO_INSERT means to delete some text. I.e.,
- the code tells undo what to undo, not how to undo it. */
-enum undo_code { UNDO_DELETE, UNDO_INSERT, UNDO_BEGIN, UNDO_END };
-
-/* What an element of THE_UNDO_LIST looks like. */
-typedef struct undo_list {
- struct undo_list *next;
- int start, end; /* Where the change took place. */
- char *text; /* The text to insert, if undoing a delete. */
- enum undo_code what; /* Delete, Insert, Begin, End. */
-} UNDO_LIST;
-
-/* The current undo list for RL_LINE_BUFFER. */
-extern UNDO_LIST *rl_undo_list;
-
-/* The data structure for mapping textual names to code addresses. */
-typedef struct _funmap {
- const char *name;
- rl_command_func_t *function;
-} FUNMAP;
-
-extern FUNMAP **funmap;
-
-/* **************************************************************** */
-/* */
-/* Functions available to bind to key sequences */
-/* */
-/* **************************************************************** */
-
-/* Bindable commands for numeric arguments. */
-extern int rl_digit_argument PARAMS((int, int));
-extern int rl_universal_argument PARAMS((int, int));
-
-/* Bindable commands for moving the cursor. */
-extern int rl_forward_byte PARAMS((int, int));
-extern int rl_forward_char PARAMS((int, int));
-extern int rl_forward PARAMS((int, int));
-extern int rl_backward_byte PARAMS((int, int));
-extern int rl_backward_char PARAMS((int, int));
-extern int rl_backward PARAMS((int, int));
-extern int rl_beg_of_line PARAMS((int, int));
-extern int rl_end_of_line PARAMS((int, int));
-extern int rl_forward_word PARAMS((int, int));
-extern int rl_backward_word PARAMS((int, int));
-extern int rl_refresh_line PARAMS((int, int));
-extern int rl_clear_screen PARAMS((int, int));
-extern int rl_arrow_keys PARAMS((int, int));
-
-/* Bindable commands for inserting and deleting text. */
-extern int rl_insert PARAMS((int, int));
-extern int rl_quoted_insert PARAMS((int, int));
-extern int rl_tab_insert PARAMS((int, int));
-extern int rl_newline PARAMS((int, int));
-extern int rl_do_lowercase_version PARAMS((int, int));
-extern int rl_rubout PARAMS((int, int));
-extern int rl_delete PARAMS((int, int));
-extern int rl_rubout_or_delete PARAMS((int, int));
-extern int rl_delete_horizontal_space PARAMS((int, int));
-extern int rl_delete_or_show_completions PARAMS((int, int));
-extern int rl_insert_comment PARAMS((int, int));
-
-/* Bindable commands for changing case. */
-extern int rl_upcase_word PARAMS((int, int));
-extern int rl_downcase_word PARAMS((int, int));
-extern int rl_capitalize_word PARAMS((int, int));
-
-/* Bindable commands for transposing characters and words. */
-extern int rl_transpose_words PARAMS((int, int));
-extern int rl_transpose_chars PARAMS((int, int));
-
-/* Bindable commands for searching within a line. */
-extern int rl_char_search PARAMS((int, int));
-extern int rl_backward_char_search PARAMS((int, int));
-
-/* Bindable commands for readline's interface to the command history. */
-extern int rl_beginning_of_history PARAMS((int, int));
-extern int rl_end_of_history PARAMS((int, int));
-extern int rl_get_next_history PARAMS((int, int));
-extern int rl_get_previous_history PARAMS((int, int));
-
-/* Bindable commands for managing the mark and region. */
-extern int rl_set_mark PARAMS((int, int));
-extern int rl_exchange_point_and_mark PARAMS((int, int));
-
-/* Bindable commands to set the editing mode (emacs or vi). */
-extern int rl_vi_editing_mode PARAMS((int, int));
-extern int rl_emacs_editing_mode PARAMS((int, int));
-
-/* Bindable commands to change the insert mode (insert or overwrite) */
-extern int rl_overwrite_mode PARAMS((int, int));
-
-/* Bindable commands for managing key bindings. */
-extern int rl_re_read_init_file PARAMS((int, int));
-extern int rl_dump_functions PARAMS((int, int));
-extern int rl_dump_macros PARAMS((int, int));
-extern int rl_dump_variables PARAMS((int, int));
-
-/* Bindable commands for word completion. */
-extern int rl_complete PARAMS((int, int));
-extern int rl_possible_completions PARAMS((int, int));
-extern int rl_insert_completions PARAMS((int, int));
-extern int rl_menu_complete PARAMS((int, int));
-
-/* Bindable commands for killing and yanking text, and managing the kill ring. */
-extern int rl_kill_word PARAMS((int, int));
-extern int rl_backward_kill_word PARAMS((int, int));
-extern int rl_kill_line PARAMS((int, int));
-extern int rl_backward_kill_line PARAMS((int, int));
-extern int rl_kill_full_line PARAMS((int, int));
-extern int rl_unix_word_rubout PARAMS((int, int));
-extern int rl_unix_filename_rubout PARAMS((int, int));
-extern int rl_unix_line_discard PARAMS((int, int));
-extern int rl_copy_region_to_kill PARAMS((int, int));
-extern int rl_kill_region PARAMS((int, int));
-extern int rl_copy_forward_word PARAMS((int, int));
-extern int rl_copy_backward_word PARAMS((int, int));
-extern int rl_yank PARAMS((int, int));
-extern int rl_yank_pop PARAMS((int, int));
-extern int rl_yank_nth_arg PARAMS((int, int));
-extern int rl_yank_last_arg PARAMS((int, int));
-/* Not available unless __CYGWIN__ is defined. */
-#ifdef __CYGWIN__
-extern int rl_paste_from_clipboard PARAMS((int, int));
-#endif
-
-/* Bindable commands for incremental searching. */
-extern int rl_reverse_search_history PARAMS((int, int));
-extern int rl_forward_search_history PARAMS((int, int));
-
-/* Bindable keyboard macro commands. */
-extern int rl_start_kbd_macro PARAMS((int, int));
-extern int rl_end_kbd_macro PARAMS((int, int));
-extern int rl_call_last_kbd_macro PARAMS((int, int));
-
-/* Bindable undo commands. */
-extern int rl_revert_line PARAMS((int, int));
-extern int rl_undo_command PARAMS((int, int));
-
-/* Bindable tilde expansion commands. */
-extern int rl_tilde_expand PARAMS((int, int));
-
-/* Bindable terminal control commands. */
-extern int rl_restart_output PARAMS((int, int));
-extern int rl_stop_output PARAMS((int, int));
-
-/* Miscellaneous bindable commands. */
-extern int rl_abort PARAMS((int, int));
-extern int rl_tty_status PARAMS((int, int));
-
-/* Bindable commands for incremental and non-incremental history searching. */
-extern int rl_history_search_forward PARAMS((int, int));
-extern int rl_history_search_backward PARAMS((int, int));
-extern int rl_noninc_forward_search PARAMS((int, int));
-extern int rl_noninc_reverse_search PARAMS((int, int));
-extern int rl_noninc_forward_search_again PARAMS((int, int));
-extern int rl_noninc_reverse_search_again PARAMS((int, int));
-
-/* Bindable command used when inserting a matching close character. */
-extern int rl_insert_close PARAMS((int, int));
-
-/* Not available unless READLINE_CALLBACKS is defined. */
-extern void rl_callback_handler_install PARAMS((const char *, rl_vcpfunc_t *));
-extern void rl_callback_read_char PARAMS((void));
-extern void rl_callback_handler_remove PARAMS((void));
-
-/* Things for vi mode. Not available unless readline is compiled -DVI_MODE. */
-/* VI-mode bindable commands. */
-extern int rl_vi_redo PARAMS((int, int));
-extern int rl_vi_undo PARAMS((int, int));
-extern int rl_vi_yank_arg PARAMS((int, int));
-extern int rl_vi_fetch_history PARAMS((int, int));
-extern int rl_vi_search_again PARAMS((int, int));
-extern int rl_vi_search PARAMS((int, int));
-extern int rl_vi_complete PARAMS((int, int));
-extern int rl_vi_tilde_expand PARAMS((int, int));
-extern int rl_vi_prev_word PARAMS((int, int));
-extern int rl_vi_next_word PARAMS((int, int));
-extern int rl_vi_end_word PARAMS((int, int));
-extern int rl_vi_insert_beg PARAMS((int, int));
-extern int rl_vi_append_mode PARAMS((int, int));
-extern int rl_vi_append_eol PARAMS((int, int));
-extern int rl_vi_eof_maybe PARAMS((int, int));
-extern int rl_vi_insertion_mode PARAMS((int, int));
-extern int rl_vi_movement_mode PARAMS((int, int));
-extern int rl_vi_arg_digit PARAMS((int, int));
-extern int rl_vi_change_case PARAMS((int, int));
-extern int rl_vi_put PARAMS((int, int));
-extern int rl_vi_column PARAMS((int, int));
-extern int rl_vi_delete_to PARAMS((int, int));
-extern int rl_vi_change_to PARAMS((int, int));
-extern int rl_vi_yank_to PARAMS((int, int));
-extern int rl_vi_rubout PARAMS((int, int));
-extern int rl_vi_delete PARAMS((int, int));
-extern int rl_vi_back_to_indent PARAMS((int, int));
-extern int rl_vi_first_print PARAMS((int, int));
-extern int rl_vi_char_search PARAMS((int, int));
-extern int rl_vi_match PARAMS((int, int));
-extern int rl_vi_change_char PARAMS((int, int));
-extern int rl_vi_subst PARAMS((int, int));
-extern int rl_vi_overstrike PARAMS((int, int));
-extern int rl_vi_overstrike_delete PARAMS((int, int));
-extern int rl_vi_replace PARAMS((int, int));
-extern int rl_vi_set_mark PARAMS((int, int));
-extern int rl_vi_goto_mark PARAMS((int, int));
-
-/* VI-mode utility functions. */
-extern int rl_vi_check PARAMS((void));
-extern int rl_vi_domove PARAMS((int, int *));
-extern int rl_vi_bracktype PARAMS((int));
-
-extern void rl_vi_start_inserting PARAMS((int, int, int));
-
-/* VI-mode pseudo-bindable commands, used as utility functions. */
-extern int rl_vi_fWord PARAMS((int, int));
-extern int rl_vi_bWord PARAMS((int, int));
-extern int rl_vi_eWord PARAMS((int, int));
-extern int rl_vi_fword PARAMS((int, int));
-extern int rl_vi_bword PARAMS((int, int));
-extern int rl_vi_eword PARAMS((int, int));
-
-/* **************************************************************** */
-/* */
-/* Well Published Functions */
-/* */
-/* **************************************************************** */
-
-/* Readline functions. */
-/* Read a line of input. Prompt with PROMPT. A NULL PROMPT means none. */
-extern char *readline PARAMS((const char *));
-
-extern int rl_set_prompt PARAMS((const char *));
-extern int rl_expand_prompt PARAMS((char *));
-
-extern int rl_initialize PARAMS((void));
-
-/* Undocumented; unused by readline */
-extern int rl_discard_argument PARAMS((void));
-
-/* Utility functions to bind keys to readline commands. */
-extern int rl_add_defun PARAMS((const char *, rl_command_func_t *, int));
-extern int rl_bind_key PARAMS((int, rl_command_func_t *));
-extern int rl_bind_key_in_map PARAMS((int, rl_command_func_t *, Keymap));
-extern int rl_unbind_key PARAMS((int));
-extern int rl_unbind_key_in_map PARAMS((int, Keymap));
-extern int rl_bind_key_if_unbound PARAMS((int, rl_command_func_t *));
-extern int rl_bind_key_if_unbound_in_map PARAMS((int, rl_command_func_t *, Keymap));
-extern int rl_unbind_function_in_map PARAMS((rl_command_func_t *, Keymap));
-extern int rl_unbind_command_in_map PARAMS((const char *, Keymap));
-extern int rl_bind_keyseq PARAMS((const char *, rl_command_func_t *));
-extern int rl_bind_keyseq_in_map PARAMS((const char *, rl_command_func_t *, Keymap));
-extern int rl_bind_keyseq_if_unbound PARAMS((const char *, rl_command_func_t *));
-extern int rl_bind_keyseq_if_unbound_in_map PARAMS((const char *, rl_command_func_t *, Keymap));
-extern int rl_generic_bind PARAMS((int, const char *, char *, Keymap));
-
-extern char *rl_variable_value PARAMS((const char *));
-extern int rl_variable_bind PARAMS((const char *, const char *));
-
-/* Backwards compatibility, use rl_bind_keyseq_in_map instead. */
-extern int rl_set_key PARAMS((const char *, rl_command_func_t *, Keymap));
-
-/* Backwards compatibility, use rl_generic_bind instead. */
-extern int rl_macro_bind PARAMS((const char *, const char *, Keymap));
-
-/* Undocumented in the texinfo manual; not really useful to programs. */
-extern int rl_translate_keyseq PARAMS((const char *, char *, int *));
-extern char *rl_untranslate_keyseq PARAMS((int));
-
-extern rl_command_func_t *rl_named_function PARAMS((const char *));
-extern rl_command_func_t *rl_function_of_keyseq PARAMS((const char *, Keymap, int *));
-
-extern void rl_list_funmap_names PARAMS((void));
-extern char **rl_invoking_keyseqs_in_map PARAMS((rl_command_func_t *, Keymap));
-extern char **rl_invoking_keyseqs PARAMS((rl_command_func_t *));
-
-extern void rl_function_dumper PARAMS((int));
-extern void rl_macro_dumper PARAMS((int));
-extern void rl_variable_dumper PARAMS((int));
-
-extern int rl_read_init_file PARAMS((const char *));
-extern int rl_parse_and_bind PARAMS((char *));
-
-/* Functions for manipulating keymaps. */
-extern Keymap rl_make_bare_keymap PARAMS((void));
-extern Keymap rl_copy_keymap PARAMS((Keymap));
-extern Keymap rl_make_keymap PARAMS((void));
-extern void rl_discard_keymap PARAMS((Keymap));
-
-extern Keymap rl_get_keymap_by_name PARAMS((const char *));
-extern char *rl_get_keymap_name PARAMS((Keymap));
-extern void rl_set_keymap PARAMS((Keymap));
-extern Keymap rl_get_keymap PARAMS((void));
-/* Undocumented; used internally only. */
-extern void rl_set_keymap_from_edit_mode PARAMS((void));
-extern char *rl_get_keymap_name_from_edit_mode PARAMS((void));
-
-/* Functions for manipulating the funmap, which maps command names to functions. */
-extern int rl_add_funmap_entry PARAMS((const char *, rl_command_func_t *));
-extern const char **rl_funmap_names PARAMS((void));
-/* Undocumented, only used internally -- there is only one funmap, and this
- function may be called only once. */
-extern void rl_initialize_funmap PARAMS((void));
-
-/* Utility functions for managing keyboard macros. */
-extern void rl_push_macro_input PARAMS((char *));
-
-/* Functions for undoing, from undo.c */
-extern void rl_add_undo PARAMS((enum undo_code, int, int, char *));
-extern void rl_free_undo_list PARAMS((void));
-extern int rl_do_undo PARAMS((void));
-extern int rl_begin_undo_group PARAMS((void));
-extern int rl_end_undo_group PARAMS((void));
-extern int rl_modifying PARAMS((int, int));
-
-/* Functions for redisplay. */
-extern void rl_redisplay PARAMS((void));
-extern int rl_on_new_line PARAMS((void));
-extern int rl_on_new_line_with_prompt PARAMS((void));
-extern int rl_forced_update_display PARAMS((void));
-extern int rl_clear_message PARAMS((void));
-extern int rl_reset_line_state PARAMS((void));
-extern int rl_crlf PARAMS((void));
-
-#if defined (USE_VARARGS) && defined (PREFER_STDARG)
-extern int rl_message (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
-#else
-extern int rl_message ();
-#endif
-
-extern int rl_show_char PARAMS((int));
-
-/* Undocumented in texinfo manual. */
-extern int rl_character_len PARAMS((int, int));
-
-/* Save and restore internal prompt redisplay information. */
-extern void rl_save_prompt PARAMS((void));
-extern void rl_restore_prompt PARAMS((void));
-
-/* Modifying text. */
-extern void rl_replace_line PARAMS((const char *, int));
-extern int rl_insert_text PARAMS((const char *));
-extern int rl_delete_text PARAMS((int, int));
-extern int rl_kill_text PARAMS((int, int));
-extern char *rl_copy_text PARAMS((int, int));
-
-/* Terminal and tty mode management. */
-extern void rl_prep_terminal PARAMS((int));
-extern void rl_deprep_terminal PARAMS((void));
-extern void rl_tty_set_default_bindings PARAMS((Keymap));
-extern void rl_tty_unset_default_bindings PARAMS((Keymap));
-
-extern int rl_reset_terminal PARAMS((const char *));
-extern void rl_resize_terminal PARAMS((void));
-extern void rl_set_screen_size PARAMS((int, int));
-extern void rl_get_screen_size PARAMS((int *, int *));
-extern void rl_reset_screen_size PARAMS((void));
-
-extern char *rl_get_termcap PARAMS((const char *));
-
-/* Functions for character input. */
-extern int rl_stuff_char PARAMS((int));
-extern int rl_execute_next PARAMS((int));
-extern int rl_clear_pending_input PARAMS((void));
-extern int rl_read_key PARAMS((void));
-extern int rl_getc PARAMS((FILE *));
-extern int rl_set_keyboard_input_timeout PARAMS((int));
-
-/* `Public' utility functions . */
-extern void rl_extend_line_buffer PARAMS((int));
-extern int rl_ding PARAMS((void));
-extern int rl_alphabetic PARAMS((int));
-
-/* Readline signal handling, from signals.c */
-extern int rl_set_signals PARAMS((void));
-extern int rl_clear_signals PARAMS((void));
-extern void rl_cleanup_after_signal PARAMS((void));
-extern void rl_reset_after_signal PARAMS((void));
-extern void rl_free_line_state PARAMS((void));
-
-extern int rl_set_paren_blink_timeout PARAMS((int));
-
-/* Undocumented. */
-extern int rl_maybe_save_line PARAMS((void));
-extern int rl_maybe_unsave_line PARAMS((void));
-extern int rl_maybe_replace_line PARAMS((void));
-
-/* Completion functions. */
-extern int rl_complete_internal PARAMS((int));
-extern void rl_display_match_list PARAMS((char **, int, int));
-
-extern char **rl_completion_matches PARAMS((const char *, rl_compentry_func_t *));
-extern char *rl_username_completion_function PARAMS((const char *, int));
-extern char *rl_filename_completion_function PARAMS((const char *, int));
-
-extern int rl_completion_mode PARAMS((rl_command_func_t *));
-
-#if 0
-/* Backwards compatibility (compat.c). These will go away sometime. */
-extern void free_undo_list PARAMS((void));
-extern int maybe_save_line PARAMS((void));
-extern int maybe_unsave_line PARAMS((void));
-extern int maybe_replace_line PARAMS((void));
-
-extern int ding PARAMS((void));
-extern int alphabetic PARAMS((int));
-extern int crlf PARAMS((void));
-
-extern char **completion_matches PARAMS((char *, rl_compentry_func_t *));
-extern char *username_completion_function PARAMS((const char *, int));
-extern char *filename_completion_function PARAMS((const char *, int));
-#endif
-
-/* **************************************************************** */
-/* */
-/* Well Published Variables */
-/* */
-/* **************************************************************** */
-
-/* The version of this incarnation of the readline library. */
-extern const char *rl_library_version; /* e.g., "4.2" */
-extern int rl_readline_version; /* e.g., 0x0402 */
-
-/* True if this is real GNU readline. */
-extern int rl_gnu_readline_p;
-
-/* Flags word encapsulating the current readline state. */
-extern int rl_readline_state;
-
-/* Says which editing mode readline is currently using. 1 means emacs mode;
- 0 means vi mode. */
-extern int rl_editing_mode;
-
-/* Insert or overwrite mode for emacs mode. 1 means insert mode; 0 means
- overwrite mode. Reset to insert mode on each input line. */
-extern int rl_insert_mode;
-
-/* The name of the calling program. You should initialize this to
- whatever was in argv[0]. It is used when parsing conditionals. */
-extern const char *rl_readline_name;
-
-/* The prompt readline uses. This is set from the argument to
- readline (), and should not be assigned to directly. */
-extern char *rl_prompt;
-
-/* The line buffer that is in use. */
-extern char *rl_line_buffer;
-
-/* The location of point, and end. */
-extern int rl_point;
-extern int rl_end;
-
-/* The mark, or saved cursor position. */
-extern int rl_mark;
-
-/* Flag to indicate that readline has finished with the current input
- line and should return it. */
-extern int rl_done;
-
-/* If set to a character value, that will be the next keystroke read. */
-extern int rl_pending_input;
-
-/* Non-zero if we called this function from _rl_dispatch(). It's present
- so functions can find out whether they were called from a key binding
- or directly from an application. */
-extern int rl_dispatching;
-
-/* Non-zero if the user typed a numeric argument before executing the
- current function. */
-extern int rl_explicit_arg;
-
-/* The current value of the numeric argument specified by the user. */
-extern int rl_numeric_arg;
-
-/* The address of the last command function Readline executed. */
-extern rl_command_func_t *rl_last_func;
-
-/* The name of the terminal to use. */
-extern const char *rl_terminal_name;
-
-/* The input and output streams. */
-extern FILE *rl_instream;
-extern FILE *rl_outstream;
-
-/* If non-zero, Readline gives values of LINES and COLUMNS from the environment
- greater precedence than values fetched from the kernel when computing the
- screen dimensions. */
-extern int rl_prefer_env_winsize;
-
-/* If non-zero, then this is the address of a function to call just
- before readline_internal () prints the first prompt. */
-extern rl_hook_func_t *rl_startup_hook;
-
-/* If non-zero, this is the address of a function to call just before
- readline_internal_setup () returns and readline_internal starts
- reading input characters. */
-extern rl_hook_func_t *rl_pre_input_hook;
-
-/* The address of a function to call periodically while Readline is
- awaiting character input, or NULL, for no event handling. */
-extern rl_hook_func_t *rl_event_hook;
-
-/* The address of the function to call to fetch a character from the current
- Readline input stream */
-extern rl_getc_func_t *rl_getc_function;
-
-extern rl_voidfunc_t *rl_redisplay_function;
-
-extern rl_vintfunc_t *rl_prep_term_function;
-extern rl_voidfunc_t *rl_deprep_term_function;
-
-/* Dispatch variables. */
-extern Keymap rl_executing_keymap;
-extern Keymap rl_binding_keymap;
-
-/* Display variables. */
-/* If non-zero, readline will erase the entire line, including any prompt,
- if the only thing typed on an otherwise-blank line is something bound to
- rl_newline. */
-extern int rl_erase_empty_line;
-
-/* If non-zero, the application has already printed the prompt (rl_prompt)
- before calling readline, so readline should not output it the first time
- redisplay is done. */
-extern int rl_already_prompted;
-
-/* A non-zero value means to read only this many characters rather than
- up to a character bound to accept-line. */
-extern int rl_num_chars_to_read;
-
-/* The text of a currently-executing keyboard macro. */
-extern char *rl_executing_macro;
-
-/* Variables to control readline signal handling. */
-/* If non-zero, readline will install its own signal handlers for
- SIGINT, SIGTERM, SIGQUIT, SIGALRM, SIGTSTP, SIGTTIN, and SIGTTOU. */
-extern int rl_catch_signals;
-
-/* If non-zero, readline will install a signal handler for SIGWINCH
- that also attempts to call any calling application's SIGWINCH signal
- handler. Note that the terminal is not cleaned up before the
- application's signal handler is called; use rl_cleanup_after_signal()
- to do that. */
-extern int rl_catch_sigwinch;
-
-/* Completion variables. */
-/* Pointer to the generator function for completion_matches ().
- NULL means to use rl_filename_completion_function (), the default
- filename completer. */
-extern rl_compentry_func_t *rl_completion_entry_function;
-
-/* If rl_ignore_some_completions_function is non-NULL it is the address
- of a function to call after all of the possible matches have been
- generated, but before the actual completion is done to the input line.
- The function is called with one argument; a NULL terminated array
- of (char *). If your function removes any of the elements, they
- must be free()'ed. */
-extern rl_compignore_func_t *rl_ignore_some_completions_function;
-
-/* Pointer to alternative function to create matches.
- Function is called with TEXT, START, and END.
- START and END are indices in RL_LINE_BUFFER saying what the boundaries
- of TEXT are.
- If this function exists and returns NULL then call the value of
- rl_completion_entry_function to try to match, otherwise use the
- array of strings returned. */
-extern rl_completion_func_t *rl_attempted_completion_function;
-
-/* The basic list of characters that signal a break between words for the
- completer routine. The initial contents of this variable is what
- breaks words in the shell, i.e. "n\"\\'`@$>". */
-extern const char *rl_basic_word_break_characters;
-
-/* The list of characters that signal a break between words for
- rl_complete_internal. The default list is the contents of
- rl_basic_word_break_characters. */
-extern /*const*/ char *rl_completer_word_break_characters;
-
-/* Hook function to allow an application to set the completion word
- break characters before readline breaks up the line. Allows
- position-dependent word break characters. */
-extern rl_cpvfunc_t *rl_completion_word_break_hook;
-
-/* List of characters which can be used to quote a substring of the line.
- Completion occurs on the entire substring, and within the substring
- rl_completer_word_break_characters are treated as any other character,
- unless they also appear within this list. */
-extern const char *rl_completer_quote_characters;
-
-/* List of quote characters which cause a word break. */
-extern const char *rl_basic_quote_characters;
-
-/* List of characters that need to be quoted in filenames by the completer. */
-extern const char *rl_filename_quote_characters;
-
-/* List of characters that are word break characters, but should be left
- in TEXT when it is passed to the completion function. The shell uses
- this to help determine what kind of completing to do. */
-extern const char *rl_special_prefixes;
-
-/* If non-zero, then this is the address of a function to call when
- completing on a directory name. The function is called with
- the address of a string (the current directory name) as an arg. It
- changes what is displayed when the possible completions are printed
- or inserted. */
-extern rl_icppfunc_t *rl_directory_completion_hook;
-
-/* If non-zero, this is the address of a function to call when completing
- a directory name. This function takes the address of the directory name
- to be modified as an argument. Unlike rl_directory_completion_hook, it
- only modifies the directory name used in opendir(2), not what is displayed
- when the possible completions are printed or inserted. It is called
- before rl_directory_completion_hook. I'm not happy with how this works
- yet, so it's undocumented. */
-extern rl_icppfunc_t *rl_directory_rewrite_hook;
-
-/* Backwards compatibility with previous versions of readline. */
-#define rl_symbolic_link_hook rl_directory_completion_hook
-
-/* If non-zero, then this is the address of a function to call when
- completing a word would normally display the list of possible matches.
- This function is called instead of actually doing the display.
- It takes three arguments: (char **matches, int num_matches, int max_length)
- where MATCHES is the array of strings that matched, NUM_MATCHES is the
- number of strings in that array, and MAX_LENGTH is the length of the
- longest string in that array. */
-extern rl_compdisp_func_t *rl_completion_display_matches_hook;
-
-/* Non-zero means that the results of the matches are to be treated
- as filenames. This is ALWAYS zero on entry, and can only be changed
- within a completion entry finder function. */
-extern int rl_filename_completion_desired;
-
-/* Non-zero means that the results of the matches are to be quoted using
- double quotes (or an application-specific quoting mechanism) if the
- filename contains any characters in rl_word_break_chars. This is
- ALWAYS non-zero on entry, and can only be changed within a completion
- entry finder function. */
-extern int rl_filename_quoting_desired;
-
-/* Set to a function to quote a filename in an application-specific fashion.
- Called with the text to quote, the type of match found (single or multiple)
- and a pointer to the quoting character to be used, which the function can
- reset if desired. */
-extern rl_quote_func_t *rl_filename_quoting_function;
-
-/* Function to call to remove quoting characters from a filename. Called
- before completion is attempted, so the embedded quotes do not interfere
- with matching names in the file system. */
-extern rl_dequote_func_t *rl_filename_dequoting_function;
-
-/* Function to call to decide whether or not a word break character is
- quoted. If a character is quoted, it does not break words for the
- completer. */
-extern rl_linebuf_func_t *rl_char_is_quoted_p;
-
-/* Non-zero means to suppress normal filename completion after the
- user-specified completion function has been called. */
-extern int rl_attempted_completion_over;
-
-/* Set to a character describing the type of completion being attempted by
- rl_complete_internal; available for use by application completion
- functions. */
-extern int rl_completion_type;
-
-/* Up to this many items will be displayed in response to a
- possible-completions call. After that, we ask the user if she
- is sure she wants to see them all. The default value is 100. */
-extern int rl_completion_query_items;
-
-/* Character appended to completed words when at the end of the line. The
- default is a space. Nothing is added if this is '\0'. */
-extern int rl_completion_append_character;
-
-/* If set to non-zero by an application completion function,
- rl_completion_append_character will not be appended. */
-extern int rl_completion_suppress_append;
-
-/* Set to any quote character readline thinks it finds before any application
- completion function is called. */
-extern int rl_completion_quote_character;
-
-/* Set to a non-zero value if readline found quoting anywhere in the word to
- be completed; set before any application completion function is called. */
-extern int rl_completion_found_quote;
-
-/* If non-zero, the completion functions don't append any closing quote.
- This is set to 0 by rl_complete_internal and may be changed by an
- application-specific completion function. */
-extern int rl_completion_suppress_quote;
-
-/* If non-zero, a slash will be appended to completed filenames that are
- symbolic links to directory names, subject to the value of the
- mark-directories variable (which is user-settable). This exists so
- that application completion functions can override the user's preference
- (set via the mark-symlinked-directories variable) if appropriate.
- It's set to the value of _rl_complete_mark_symlink_dirs in
- rl_complete_internal before any application-specific completion
- function is called, so without that function doing anything, the user's
- preferences are honored. */
-extern int rl_completion_mark_symlink_dirs;
-
-/* If non-zero, then disallow duplicates in the matches. */
-extern int rl_ignore_completion_duplicates;
-
-/* If this is non-zero, completion is (temporarily) inhibited, and the
- completion character will be inserted as any other. */
-extern int rl_inhibit_completion;
-
-/* Definitions available for use by readline clients. */
-#define RL_PROMPT_START_IGNORE '\001'
-#define RL_PROMPT_END_IGNORE '\002'
-
-/* Possible values for do_replace argument to rl_filename_quoting_function,
- called by rl_complete_internal. */
-#define NO_MATCH 0
-#define SINGLE_MATCH 1
-#define MULT_MATCH 2
-
-/* Possible state values for rl_readline_state */
-#define RL_STATE_NONE 0x000000 /* no state; before first call */
-
-#define RL_STATE_INITIALIZING 0x000001 /* initializing */
-#define RL_STATE_INITIALIZED 0x000002 /* initialization done */
-#define RL_STATE_TERMPREPPED 0x000004 /* terminal is prepped */
-#define RL_STATE_READCMD 0x000008 /* reading a command key */
-#define RL_STATE_METANEXT 0x000010 /* reading input after ESC */
-#define RL_STATE_DISPATCHING 0x000020 /* dispatching to a command */
-#define RL_STATE_MOREINPUT 0x000040 /* reading more input in a command function */
-#define RL_STATE_ISEARCH 0x000080 /* doing incremental search */
-#define RL_STATE_NSEARCH 0x000100 /* doing non-inc search */
-#define RL_STATE_SEARCH 0x000200 /* doing a history search */
-#define RL_STATE_NUMERICARG 0x000400 /* reading numeric argument */
-#define RL_STATE_MACROINPUT 0x000800 /* getting input from a macro */
-#define RL_STATE_MACRODEF 0x001000 /* defining keyboard macro */
-#define RL_STATE_OVERWRITE 0x002000 /* overwrite mode */
-#define RL_STATE_COMPLETING 0x004000 /* doing completion */
-#define RL_STATE_SIGHANDLER 0x008000 /* in readline sighandler */
-#define RL_STATE_UNDOING 0x010000 /* doing an undo */
-#define RL_STATE_INPUTPENDING 0x020000 /* rl_execute_next called */
-#define RL_STATE_TTYCSAVED 0x040000 /* tty special chars saved */
-#define RL_STATE_CALLBACK 0x080000 /* using the callback interface */
-#define RL_STATE_VIMOTION 0x100000 /* reading vi motion arg */
-#define RL_STATE_MULTIKEY 0x200000 /* reading multiple-key command */
-#define RL_STATE_VICMDONCE 0x400000 /* entered vi command mode at least once */
-
-#define RL_STATE_DONE 0x800000 /* done; accepted line */
-
-#define RL_SETSTATE(x) (rl_readline_state |= (x))
-#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x))
-#define RL_ISSTATE(x) (rl_readline_state & (x))
-
-struct readline_state {
- /* line state */
- int point;
- int end;
- int mark;
- char *buffer;
- int buflen;
- UNDO_LIST *ul;
- char *prompt;
-
- /* global state */
- int rlstate;
- int done;
- Keymap kmap;
-
- /* input state */
- rl_command_func_t *lastfunc;
- int insmode;
- int edmode;
- int kseqlen;
- FILE *inf;
- FILE *outf;
- int pendingin;
- char *macro;
-
- /* signal state */
- int catchsigs;
- int catchsigwinch;
-
- /* search state */
-
- /* completion state */
-
- /* options state */
-
- /* reserved for future expansion, so the struct size doesn't change */
- char reserved[64];
-};
-
-extern int rl_save_state PARAMS((struct readline_state *));
-extern int rl_restore_state PARAMS((struct readline_state *));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _READLINE_H_ */
diff --git a/lib/readline/rlprivate.h~ b/lib/readline/rlprivate.h~
deleted file mode 100644
index 71cbc0b2..00000000
--- a/lib/readline/rlprivate.h~
+++ /dev/null
@@ -1,429 +0,0 @@
-/* rlprivate.h -- functions and variables global to the readline library,
- but not intended for use by applications. */
-
-/* Copyright (C) 1999-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. */
-
-#if !defined (_RL_PRIVATE_H_)
-#define _RL_PRIVATE_H_
-
-#include "rlconf.h" /* for VISIBLE_STATS */
-#include "rlstdc.h"
-#include "posixjmp.h" /* defines procenv_t */
-
-/*************************************************************************
- * *
- * Global structs undocumented in texinfo manual and not in readline.h *
- * *
- *************************************************************************/
-
-/* input error */
-#define READERR (-2)
-
-/* search types */
-#define RL_SEARCH_ISEARCH 0x01 /* incremental search */
-#define RL_SEARCH_NSEARCH 0x02 /* non-incremental search */
-#define RL_SEARCH_CSEARCH 0x04 /* intra-line char search */
-
-/* search flags */
-#define SF_REVERSE 0x01
-#define SF_FOUND 0x02
-#define SF_FAILED 0x04
-
-typedef struct __rl_search_context
-{
- int type;
- int sflags;
-
- char *search_string;
- int search_string_index;
- int search_string_size;
-
- char **lines;
- char *allocated_line;
- int hlen;
- int hindex;
-
- int save_point;
- int save_mark;
- int save_line;
- int last_found_line;
- char *prev_line_found;
-
- UNDO_LIST *save_undo_list;
-
- int history_pos;
- int direction;
-
- int lastc;
-#if defined (HANDLE_MULTIBYTE)
- char mb[MB_LEN_MAX];
-#endif
-
- char *sline;
- int sline_len;
- int sline_index;
-
- char *search_terminators;
-} _rl_search_cxt;
-
-/* Callback data for reading numeric arguments */
-#define NUM_SAWMINUS 0x01
-#define NUM_SAWDIGITS 0x02
-#define NUM_READONE 0x04
-
-typedef int _rl_arg_cxt;
-
-/* A context for reading key sequences longer than a single character when
- using the callback interface. */
-#define KSEQ_DISPATCHED 0x01
-#define KSEQ_SUBSEQ 0x02
-#define KSEQ_RECURSIVE 0x04
-
-typedef struct __rl_keyseq_context
-{
- int flags;
- int subseq_arg;
- int subseq_retval; /* XXX */
- Keymap dmap;
-
- Keymap oldmap;
- int okey;
- struct __rl_keyseq_context *ocxt;
- int childval;
-} _rl_keyseq_cxt;
-
- /* fill in more as needed */
-/* `Generic' callback data and functions */
-typedef struct __rl_callback_generic_arg
-{
- int count;
- int i1, i2;
- /* add here as needed */
-} _rl_callback_generic_arg;
-
-typedef int _rl_callback_func_t PARAMS((_rl_callback_generic_arg *));
-
-/*************************************************************************
- * *
- * Global functions undocumented in texinfo manual and not in readline.h *
- * *
- *************************************************************************/
-
-/*************************************************************************
- * *
- * Global variables undocumented in texinfo manual and not in readline.h *
- * *
- *************************************************************************/
-
-/* complete.c */
-extern int rl_complete_with_tilde_expansion;
-#if defined (VISIBLE_STATS)
-extern int rl_visible_stats;
-#endif /* VISIBLE_STATS */
-
-/* readline.c */
-extern int rl_line_buffer_len;
-extern int rl_arg_sign;
-extern int rl_visible_prompt_length;
-extern int readline_echoing_p;
-extern int rl_key_sequence_length;
-extern int rl_byte_oriented;
-
-extern _rl_keyseq_cxt *_rl_kscxt;
-
-/* display.c */
-extern int rl_display_fixed;
-
-/* parens.c */
-extern int rl_blink_matching_paren;
-
-/*************************************************************************
- * *
- * Global functions and variables unsed and undocumented *
- * *
- *************************************************************************/
-
-/* kill.c */
-extern int rl_set_retained_kills PARAMS((int));
-
-/* terminal.c */
-extern void _rl_set_screen_size PARAMS((int, int));
-
-/* undo.c */
-extern int _rl_fix_last_undo_of_type PARAMS((int, int, int));
-
-/* util.c */
-extern char *_rl_savestring PARAMS((const char *));
-
-/*************************************************************************
- * *
- * Functions and variables private to the readline library *
- * *
- *************************************************************************/
-
-/* NOTE: Functions and variables prefixed with `_rl_' are
- pseudo-global: they are global so they can be shared
- between files in the readline library, but are not intended
- to be visible to readline callers. */
-
-/*************************************************************************
- * Undocumented private functions *
- *************************************************************************/
-
-#if defined(READLINE_CALLBACKS)
-
-/* readline.c */
-extern void readline_internal_setup PARAMS((void));
-extern char *readline_internal_teardown PARAMS((int));
-extern int readline_internal_char PARAMS((void));
-
-extern _rl_keyseq_cxt *_rl_keyseq_cxt_alloc PARAMS((void));
-extern void _rl_keyseq_cxt_dispose PARAMS((_rl_keyseq_cxt *));
-extern void _rl_keyseq_chain_dispose PARAMS((void));
-
-extern int _rl_dispatch_callback PARAMS((_rl_keyseq_cxt *));
-
-/* callback.c */
-extern _rl_callback_generic_arg *_rl_callback_data_alloc PARAMS((int));
-extern void _rl_callback_data_dispose PARAMS((_rl_callback_generic_arg *));
-
-#endif /* READLINE_CALLBACKS */
-
-/* bind.c */
-
-/* complete.c */
-extern char _rl_find_completion_word PARAMS((int *, int *));
-extern void _rl_free_match_list PARAMS((char **));
-
-/* display.c */
-extern char *_rl_strip_prompt PARAMS((char *));
-extern void _rl_move_cursor_relative PARAMS((int, const char *));
-extern void _rl_move_vert PARAMS((int));
-extern void _rl_save_prompt PARAMS((void));
-extern void _rl_restore_prompt PARAMS((void));
-extern char *_rl_make_prompt_for_search PARAMS((int));
-extern void _rl_erase_at_end_of_line PARAMS((int));
-extern void _rl_clear_to_eol PARAMS((int));
-extern void _rl_clear_screen PARAMS((void));
-extern void _rl_update_final PARAMS((void));
-extern void _rl_redisplay_after_sigwinch PARAMS((void));
-extern void _rl_clean_up_for_exit PARAMS((void));
-extern void _rl_erase_entire_line PARAMS((void));
-extern int _rl_current_display_line PARAMS((void));
-
-/* input.c */
-extern int _rl_any_typein PARAMS((void));
-extern int _rl_input_available PARAMS((void));
-extern int _rl_input_queued PARAMS((int));
-extern void _rl_insert_typein PARAMS((int));
-extern int _rl_unget_char PARAMS((int));
-extern int _rl_pushed_input_available PARAMS((void));
-
-/* isearch.c */
-extern _rl_search_cxt *_rl_scxt_alloc PARAMS((int, int));
-extern void _rl_scxt_dispose PARAMS((_rl_search_cxt *, int));
-
-extern int _rl_isearch_dispatch PARAMS((_rl_search_cxt *, int));
-extern int _rl_isearch_callback PARAMS((_rl_search_cxt *));
-
-extern int _rl_search_getchar PARAMS((_rl_search_cxt *));
-
-/* macro.c */
-extern void _rl_with_macro_input PARAMS((char *));
-extern int _rl_next_macro_key PARAMS((void));
-extern void _rl_push_executing_macro PARAMS((void));
-extern void _rl_pop_executing_macro PARAMS((void));
-extern void _rl_add_macro_char PARAMS((int));
-extern void _rl_kill_kbd_macro PARAMS((void));
-
-/* misc.c */
-extern int _rl_arg_overflow PARAMS((void));
-extern void _rl_arg_init PARAMS((void));
-extern int _rl_arg_getchar PARAMS((void));
-extern int _rl_arg_callback PARAMS((_rl_arg_cxt));
-extern void _rl_reset_argument PARAMS((void));
-
-extern void _rl_start_using_history PARAMS((void));
-extern int _rl_free_saved_history_line PARAMS((void));
-extern void _rl_set_insert_mode PARAMS((int, int));
-
-/* nls.c */
-extern int _rl_init_eightbit PARAMS((void));
-
-/* parens.c */
-extern void _rl_enable_paren_matching PARAMS((int));
-
-/* readline.c */
-extern void _rl_init_line_state PARAMS((void));
-extern void _rl_set_the_line PARAMS((void));
-extern int _rl_dispatch PARAMS((int, Keymap));
-extern int _rl_dispatch_subseq PARAMS((int, Keymap, int));
-extern void _rl_internal_char_cleanup PARAMS((void));
-
-/* rltty.c */
-extern int _rl_disable_tty_signals PARAMS((void));
-extern int _rl_restore_tty_signals PARAMS((void));
-
-/* search.c */
-extern int _rl_nsearch_callback PARAMS((_rl_search_cxt *));
-
-/* terminal.c */
-extern void _rl_get_screen_size PARAMS((int, int));
-extern int _rl_init_terminal_io PARAMS((const char *));
-#ifdef _MINIX
-extern void _rl_output_character_function PARAMS((int));
-#else
-extern int _rl_output_character_function PARAMS((int));
-#endif
-extern void _rl_output_some_chars PARAMS((const char *, int));
-extern int _rl_backspace PARAMS((int));
-extern void _rl_enable_meta_key PARAMS((void));
-extern void _rl_control_keypad PARAMS((int));
-extern void _rl_set_cursor PARAMS((int, int));
-
-/* text.c */
-extern void _rl_fix_point PARAMS((int));
-extern int _rl_replace_text PARAMS((const char *, int, int));
-extern int _rl_insert_char PARAMS((int, int));
-extern int _rl_overwrite_char PARAMS((int, int));
-extern int _rl_overwrite_rubout PARAMS((int, int));
-extern int _rl_rubout_char PARAMS((int, int));
-#if defined (HANDLE_MULTIBYTE)
-extern int _rl_char_search_internal PARAMS((int, int, char *, int));
-#else
-extern int _rl_char_search_internal PARAMS((int, int, int));
-#endif
-extern int _rl_set_mark_at_pos PARAMS((int));
-
-/* undo.c */
-extern UNDO_LIST *_rl_copy_undo_entry PARAMS((UNDO_LIST *));
-extern UNDO_LIST *_rl_copy_undo_list PARAMS((UNDO_LIST *));
-
-/* util.c */
-extern int _rl_abort_internal PARAMS((void));
-extern char *_rl_strindex PARAMS((const char *, const char *));
-extern int _rl_qsort_string_compare PARAMS((char **, char **));
-extern int (_rl_uppercase_p) PARAMS((int));
-extern int (_rl_lowercase_p) PARAMS((int));
-extern int (_rl_pure_alphabetic) PARAMS((int));
-extern int (_rl_digit_p) PARAMS((int));
-extern int (_rl_to_lower) PARAMS((int));
-extern int (_rl_to_upper) PARAMS((int));
-extern int (_rl_digit_value) PARAMS((int));
-
-/* vi_mode.c */
-extern void _rl_vi_initialize_line PARAMS((void));
-extern void _rl_vi_reset_last PARAMS((void));
-extern void _rl_vi_set_last PARAMS((int, int, int));
-extern int _rl_vi_textmod_command PARAMS((int));
-extern void _rl_vi_done_inserting PARAMS((void));
-
-/*************************************************************************
- * Undocumented private variables *
- *************************************************************************/
-
-/* bind.c */
-extern const char *_rl_possible_control_prefixes[];
-extern const char *_rl_possible_meta_prefixes[];
-
-/* callback.c */
-extern _rl_callback_func_t *_rl_callback_func;
-extern _rl_callback_generic_arg *_rl_callback_data;
-
-/* complete.c */
-extern int _rl_complete_show_all;
-extern int _rl_complete_show_unmodified;
-extern int _rl_complete_mark_directories;
-extern int _rl_complete_mark_symlink_dirs;
-extern int _rl_print_completions_horizontally;
-extern int _rl_completion_case_fold;
-extern int _rl_match_hidden_files;
-extern int _rl_page_completions;
-
-/* display.c */
-extern int _rl_vis_botlin;
-extern int _rl_last_c_pos;
-extern int _rl_suppress_redisplay;
-extern int _rl_want_redisplay;
-extern char *rl_display_prompt;
-
-/* isearch.c */
-extern char *_rl_isearch_terminators;
-
-extern _rl_search_cxt *_rl_iscxt;
-
-/* macro.c */
-extern char *_rl_executing_macro;
-
-/* misc.c */
-extern int _rl_history_preserve_point;
-extern int _rl_history_saved_point;
-
-extern _rl_arg_cxt _rl_argcxt;
-
-/* readline.c */
-extern int _rl_horizontal_scroll_mode;
-extern int _rl_mark_modified_lines;
-extern int _rl_bell_preference;
-extern int _rl_meta_flag;
-extern int _rl_convert_meta_chars_to_ascii;
-extern int _rl_output_meta_chars;
-extern int _rl_bind_stty_chars;
-extern char *_rl_comment_begin;
-extern unsigned char _rl_parsing_conditionalized_out;
-extern Keymap _rl_keymap;
-extern FILE *_rl_in_stream;
-extern FILE *_rl_out_stream;
-extern int _rl_last_command_was_kill;
-extern int _rl_eof_char;
-extern procenv_t readline_top_level;
-
-/* search.c */
-extern _rl_search_cxt *_rl_nscxt;
-
-/* terminal.c */
-extern int _rl_enable_keypad;
-extern int _rl_enable_meta;
-extern char *_rl_term_clreol;
-extern char *_rl_term_clrpag;
-extern char *_rl_term_im;
-extern char *_rl_term_ic;
-extern char *_rl_term_ei;
-extern char *_rl_term_DC;
-extern char *_rl_term_up;
-extern char *_rl_term_dc;
-extern char *_rl_term_cr;
-extern char *_rl_term_IC;
-extern char *_rl_term_forward_char;
-extern int _rl_screenheight;
-extern int _rl_screenwidth;
-extern int _rl_screenchars;
-extern int _rl_terminal_can_insert;
-extern int _rl_term_autowrap;
-
-/* undo.c */
-extern int _rl_doing_an_undo;
-extern int _rl_undo_group_level;
-
-/* vi_mode.c */
-extern int _rl_vi_last_command;
-
-#endif /* _RL_PRIVATE_H_ */
diff --git a/lib/readline/rltty.c~ b/lib/readline/rltty.c~
deleted file mode 100644
index 9a0326ed..00000000
--- a/lib/readline/rltty.c~
+++ /dev/null
@@ -1,1035 +0,0 @@
-/* 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~
deleted file mode 100644
index 8013916c..00000000
--- a/lib/readline/search.c~
+++ /dev/null
@@ -1,572 +0,0 @@
-/* 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~
deleted file mode 100644
index be6f41fa..00000000
--- a/lib/readline/signals.c~
+++ /dev/null
@@ -1,470 +0,0 @@
-/* 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/terminal.c~ b/lib/readline/terminal.c~
deleted file mode 100644
index d41eb62f..00000000
--- a/lib/readline/terminal.c~
+++ /dev/null
@@ -1,701 +0,0 @@
-/* terminal.c -- controlling the terminal with termcap. */
-
-/* Copyright (C) 1996-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 "posixstat.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 */
-
-#if defined (HAVE_LOCALE_H)
-# include <locale.h>
-#endif
-
-#include <stdio.h>
-
-/* System-specific feature definitions and include files. */
-#include "rldefs.h"
-
-#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
-# include <sys/ioctl.h>
-#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
-
-#include "rltty.h"
-#include "tcap.h"
-
-/* Some standard library routines. */
-#include "readline.h"
-#include "history.h"
-
-#include "rlprivate.h"
-#include "rlshell.h"
-#include "xmalloc.h"
-
-#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
-#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
-
-int rl_prefer_env_winsize;
-
-/* **************************************************************** */
-/* */
-/* Terminal and Termcap */
-/* */
-/* **************************************************************** */
-
-static char *term_buffer = (char *)NULL;
-static char *term_string_buffer = (char *)NULL;
-
-static int tcap_initialized;
-
-#if !defined (__linux__)
-# if defined (__EMX__) || defined (NEED_EXTERN_PC)
-extern
-# endif /* __EMX__ || NEED_EXTERN_PC */
-char PC, *BC, *UP;
-#endif /* __linux__ */
-
-/* Some strings to control terminal actions. These are output by tputs (). */
-char *_rl_term_clreol;
-char *_rl_term_clrpag;
-char *_rl_term_cr;
-char *_rl_term_backspace;
-char *_rl_term_goto;
-char *_rl_term_pc;
-
-/* Non-zero if we determine that the terminal can do character insertion. */
-int _rl_terminal_can_insert = 0;
-
-/* How to insert characters. */
-char *_rl_term_im;
-char *_rl_term_ei;
-char *_rl_term_ic;
-char *_rl_term_ip;
-char *_rl_term_IC;
-
-/* How to delete characters. */
-char *_rl_term_dc;
-char *_rl_term_DC;
-
-#if defined (HACK_TERMCAP_MOTION)
-char *_rl_term_forward_char;
-#endif /* HACK_TERMCAP_MOTION */
-
-/* How to go up a line. */
-char *_rl_term_up;
-
-/* A visible bell; char if the terminal can be made to flash the screen. */
-static char *_rl_visible_bell;
-
-/* Non-zero means the terminal can auto-wrap lines. */
-int _rl_term_autowrap;
-
-/* Non-zero means that this terminal has a meta key. */
-static int term_has_meta;
-
-/* The sequences to write to turn on and off the meta key, if this
- terminal has one. */
-static char *_rl_term_mm;
-static char *_rl_term_mo;
-
-/* The key sequences output by the arrow keys, if this terminal has any. */
-static char *_rl_term_ku;
-static char *_rl_term_kd;
-static char *_rl_term_kr;
-static char *_rl_term_kl;
-
-/* How to initialize and reset the arrow keys, if this terminal has any. */
-static char *_rl_term_ks;
-static char *_rl_term_ke;
-
-/* The key sequences sent by the Home and End keys, if any. */
-static char *_rl_term_kh;
-static char *_rl_term_kH;
-static char *_rl_term_at7; /* @7 */
-
-/* Delete key */
-static char *_rl_term_kD;
-
-/* Insert key */
-static char *_rl_term_kI;
-
-/* Cursor control */
-static char *_rl_term_vs; /* very visible */
-static char *_rl_term_ve; /* normal */
-
-static void bind_termcap_arrow_keys PARAMS((Keymap));
-
-/* Variables that hold the screen dimensions, used by the display code. */
-int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
-
-/* Non-zero means the user wants to enable the keypad. */
-int _rl_enable_keypad;
-
-/* Non-zero means the user wants to enable a meta key. */
-int _rl_enable_meta = 1;
-
-#if defined (__EMX__)
-static void
-_emx_get_screensize (swp, shp)
- int *swp, *shp;
-{
- int sz[2];
-
- _scrsize (sz);
-
- if (swp)
- *swp = sz[0];
- if (shp)
- *shp = sz[1];
-}
-#endif
-
-/* Get readline's idea of the screen size. TTY is a file descriptor open
- to the terminal. If IGNORE_ENV is true, we do not pay attention to the
- values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
- non-null serve to check whether or not we have initialized termcap. */
-void
-_rl_get_screen_size (tty, ignore_env)
- int tty, ignore_env;
-{
- char *ss;
-#if defined (TIOCGWINSZ)
- struct winsize window_size;
-#endif /* TIOCGWINSZ */
- int wr, wc;
-
- wr = wc = -1;
-#if defined (TIOCGWINSZ)
- if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
- {
- wc = (int) window_size.ws_col;
- wr = (int) window_size.ws_row;
- }
-#endif /* TIOCGWINSZ */
-
-#if defined (__EMX__)
- _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
-#endif
-
- if (ignore_env || rl_prefer_env_winsize == 0)
- {
- _rl_screenwidth = wc;
- _rl_screenheight = wr;
- }
- else
- _rl_screenwidth = _rl_screenheight = -1;
-
- /* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
- is unset. If we prefer the environment, check it first before
- assigning the value returned by the kernel. */
- if (_rl_screenwidth <= 0)
- {
- if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
- _rl_screenwidth = atoi (ss);
-
- if (_rl_screenwidth <= 0)
- _rl_screenwidth = wc;
-
-#if !defined (__DJGPP__)
- if (_rl_screenwidth <= 0 && term_string_buffer)
- _rl_screenwidth = tgetnum ("co");
-#endif
- }
-
- /* Environment variable LINES overrides setting of "li" if IGNORE_ENV
- is unset. */
- if (_rl_screenheight <= 0)
- {
- if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
- _rl_screenheight = atoi (ss);
-
- if (_rl_screenheight <= 0)
- _rl_screenheight = wr;
-
-#if !defined (__DJGPP__)
- if (_rl_screenheight <= 0 && term_string_buffer)
- _rl_screenheight = tgetnum ("li");
-#endif
- }
-
- /* If all else fails, default to 80x24 terminal. */
- if (_rl_screenwidth <= 1)
- _rl_screenwidth = 80;
-
- if (_rl_screenheight <= 0)
- _rl_screenheight = 24;
-
- /* If we're being compiled as part of bash, set the environment
- variables $LINES and $COLUMNS to new values. Otherwise, just
- do a pair of putenv () or setenv () calls. */
- sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
-
- if (_rl_term_autowrap == 0)
- _rl_screenwidth--;
-
- _rl_screenchars = _rl_screenwidth * _rl_screenheight;
-}
-
-void
-_rl_set_screen_size (rows, cols)
- int rows, cols;
-{
- if (RL_ISSTATE(RL_STATE_INITIALIZED) == 0)
- _rl_init_terminal_io (rl_terminal_name);
-
- if (rows > 0)
- _rl_screenheight = rows;
- if (cols > 0)
- {
- _rl_screenwidth = cols;
- if (_rl_term_autowrap == 0)
- _rl_screenwidth--;
- }
-
- if (rows > 0 || cols > 0)
- _rl_screenchars = _rl_screenwidth * _rl_screenheight;
-}
-
-void
-rl_set_screen_size (rows, cols)
- int rows, cols;
-{
- _rl_set_screen_size (rows, cols);
-}
-
-void
-rl_get_screen_size (rows, cols)
- int *rows, *cols;
-{
- if (rows)
- *rows = _rl_screenheight;
- if (cols)
- *cols = _rl_screenwidth;
-}
-
-void
-rl_reset_screen_size ()
-{
- _rl_get_screen_size (fileno (rl_instream), 0);
-}
-
-void
-rl_resize_terminal ()
-{
- if (readline_echoing_p)
- {
- _rl_get_screen_size (fileno (rl_instream), 1);
- if (CUSTOM_REDISPLAY_FUNC ())
- rl_forced_update_display ();
- else
- _rl_redisplay_after_sigwinch ();
- }
-}
-
-struct _tc_string {
- const char *tc_var;
- char **tc_value;
-};
-
-/* This should be kept sorted, just in case we decide to change the
- search algorithm to something smarter. */
-static struct _tc_string tc_strings[] =
-{
- { "@7", &_rl_term_at7 },
- { "DC", &_rl_term_DC },
- { "IC", &_rl_term_IC },
- { "ce", &_rl_term_clreol },
- { "cl", &_rl_term_clrpag },
- { "cr", &_rl_term_cr },
- { "dc", &_rl_term_dc },
- { "ei", &_rl_term_ei },
- { "ic", &_rl_term_ic },
- { "im", &_rl_term_im },
- { "kD", &_rl_term_kD }, /* delete */
- { "kH", &_rl_term_kH }, /* home down ?? */
- { "kI", &_rl_term_kI }, /* insert */
- { "kd", &_rl_term_kd },
- { "ke", &_rl_term_ke }, /* end keypad mode */
- { "kh", &_rl_term_kh }, /* home */
- { "kl", &_rl_term_kl },
- { "kr", &_rl_term_kr },
- { "ks", &_rl_term_ks }, /* start keypad mode */
- { "ku", &_rl_term_ku },
- { "le", &_rl_term_backspace },
- { "mm", &_rl_term_mm },
- { "mo", &_rl_term_mo },
-#if defined (HACK_TERMCAP_MOTION)
- { "nd", &_rl_term_forward_char },
-#endif
- { "pc", &_rl_term_pc },
- { "up", &_rl_term_up },
- { "vb", &_rl_visible_bell },
- { "vs", &_rl_term_vs },
- { "ve", &_rl_term_ve },
-};
-
-#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
-
-/* Read the desired terminal capability strings into BP. The capabilities
- are described in the TC_STRINGS table. */
-static void
-get_term_capabilities (bp)
- char **bp;
-{
-#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
- register int i;
-
- for (i = 0; i < NUM_TC_STRINGS; i++)
- *(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
-#endif
- tcap_initialized = 1;
-}
-
-int
-_rl_init_terminal_io (terminal_name)
- const char *terminal_name;
-{
- const char *term;
- char *buffer;
- int tty, tgetent_ret;
-
- term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
- _rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
- tty = rl_instream ? fileno (rl_instream) : 0;
-
- if (term == 0)
- term = "dumb";
-
- /* I've separated this out for later work on not calling tgetent at all
- if the calling application has supplied a custom redisplay function,
- (and possibly if the application has supplied a custom input function). */
- if (CUSTOM_REDISPLAY_FUNC())
- {
- tgetent_ret = -1;
- }
- else
- {
- if (term_string_buffer == 0)
- term_string_buffer = (char *)xmalloc(2032);
-
- if (term_buffer == 0)
- term_buffer = (char *)xmalloc(4080);
-
- buffer = term_string_buffer;
-
- tgetent_ret = tgetent (term_buffer, term);
- }
-
- if (tgetent_ret <= 0)
- {
- FREE (term_string_buffer);
- FREE (term_buffer);
- buffer = term_buffer = term_string_buffer = (char *)NULL;
-
- _rl_term_autowrap = 0; /* used by _rl_get_screen_size */
-
- /* Allow calling application to set default height and width, using
- rl_set_screen_size */
- if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
- {
-#if defined (__EMX__)
- _emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
- _rl_screenwidth--;
-#else /* !__EMX__ */
- _rl_get_screen_size (tty, 0);
-#endif /* !__EMX__ */
- }
-
- /* Defaults. */
- if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
- {
- _rl_screenwidth = 79;
- _rl_screenheight = 24;
- }
-
- /* Everything below here is used by the redisplay code (tputs). */
- _rl_screenchars = _rl_screenwidth * _rl_screenheight;
- _rl_term_cr = "\r";
- _rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
- _rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
- _rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
- _rl_term_kh = _rl_term_kH = _rl_term_kI = _rl_term_kD = (char *)NULL;
- _rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
- _rl_term_mm = _rl_term_mo = (char *)NULL;
- _rl_term_ve = _rl_term_vs = (char *)NULL;
-#if defined (HACK_TERMCAP_MOTION)
- term_forward_char = (char *)NULL;
-#endif
- _rl_terminal_can_insert = term_has_meta = 0;
-
- /* Reasonable defaults for tgoto(). Readline currently only uses
- tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
- change that later... */
- PC = '\0';
- BC = _rl_term_backspace = "\b";
- UP = _rl_term_up;
-
- return 0;
- }
-
- get_term_capabilities (&buffer);
-
- /* Set up the variables that the termcap library expects the application
- to provide. */
- PC = _rl_term_pc ? *_rl_term_pc : 0;
- BC = _rl_term_backspace;
- UP = _rl_term_up;
-
- if (!_rl_term_cr)
- _rl_term_cr = "\r";
-
- _rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
-
- /* Allow calling application to set default height and width, using
- rl_set_screen_size */
- if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
- _rl_get_screen_size (tty, 0);
-
- /* "An application program can assume that the terminal can do
- character insertion if *any one of* the capabilities `IC',
- `im', `ic' or `ip' is provided." But we can't do anything if
- only `ip' is provided, so... */
- _rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
-
- /* Check to see if this terminal has a meta key and clear the capability
- variables if there is none. */
- term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
- if (!term_has_meta)
- _rl_term_mm = _rl_term_mo = (char *)NULL;
-
- /* Attempt to find and bind the arrow keys. Do not override already
- bound keys in an overzealous attempt, however. */
-
- bind_termcap_arrow_keys (emacs_standard_keymap);
-
-#if defined (VI_MODE)
- bind_termcap_arrow_keys (vi_movement_keymap);
- bind_termcap_arrow_keys (vi_insertion_keymap);
-#endif /* VI_MODE */
-
- return 0;
-}
-
-/* Bind the arrow key sequences from the termcap description in MAP. */
-static void
-bind_termcap_arrow_keys (map)
- Keymap map;
-{
- Keymap xkeymap;
-
- xkeymap = _rl_keymap;
- _rl_keymap = map;
-
- rl_bind_keyseq_if_unbound (_rl_term_ku, rl_get_previous_history);
- rl_bind_keyseq_if_unbound (_rl_term_kd, rl_get_next_history);
- rl_bind_keyseq_if_unbound (_rl_term_kr, rl_forward_char);
- rl_bind_keyseq_if_unbound (_rl_term_kl, rl_backward_char);
-
- rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
- rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
-
- rl_bind_keyseq_if_unbound (_rl_term_kD, rl_delete);
-
- _rl_keymap = xkeymap;
-}
-
-char *
-rl_get_termcap (cap)
- const char *cap;
-{
- register int i;
-
- if (tcap_initialized == 0)
- return ((char *)NULL);
- for (i = 0; i < NUM_TC_STRINGS; i++)
- {
- if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
- return *(tc_strings[i].tc_value);
- }
- return ((char *)NULL);
-}
-
-/* Re-initialize the terminal considering that the TERM/TERMCAP variable
- has changed. */
-int
-rl_reset_terminal (terminal_name)
- const char *terminal_name;
-{
- _rl_screenwidth = _rl_screenheight = 0;
- _rl_init_terminal_io (terminal_name);
- return 0;
-}
-
-/* A function for the use of tputs () */
-#ifdef _MINIX
-void
-_rl_output_character_function (c)
- int c;
-{
- putc (c, _rl_out_stream);
-}
-#else /* !_MINIX */
-int
-_rl_output_character_function (c)
- int c;
-{
- return putc (c, _rl_out_stream);
-}
-#endif /* !_MINIX */
-
-/* Write COUNT characters from STRING to the output stream. */
-void
-_rl_output_some_chars (string, count)
- const char *string;
- int count;
-{
- fwrite (string, 1, count, _rl_out_stream);
-}
-
-/* Move the cursor back. */
-int
-_rl_backspace (count)
- int count;
-{
- register int i;
-
- if (_rl_term_backspace)
- for (i = 0; i < count; i++)
- tputs (_rl_term_backspace, 1, _rl_output_character_function);
- else
- for (i = 0; i < count; i++)
- putc ('\b', _rl_out_stream);
- return 0;
-}
-
-/* Move to the start of the next line. */
-int
-rl_crlf ()
-{
-#if defined (NEW_TTY_DRIVER)
- if (_rl_term_cr)
- tputs (_rl_term_cr, 1, _rl_output_character_function);
-#endif /* NEW_TTY_DRIVER */
- putc ('\n', _rl_out_stream);
- return 0;
-}
-
-/* Ring the terminal bell. */
-int
-rl_ding ()
-{
- if (readline_echoing_p)
- {
- switch (_rl_bell_preference)
- {
- case NO_BELL:
- default:
- break;
- case VISIBLE_BELL:
- if (_rl_visible_bell)
- {
- tputs (_rl_visible_bell, 1, _rl_output_character_function);
- break;
- }
- /* FALLTHROUGH */
- case AUDIBLE_BELL:
- fprintf (stderr, "\007");
- fflush (stderr);
- break;
- }
- return (0);
- }
- return (-1);
-}
-
-/* **************************************************************** */
-/* */
-/* Controlling the Meta Key and Keypad */
-/* */
-/* **************************************************************** */
-
-void
-_rl_enable_meta_key ()
-{
-#if !defined (__DJGPP__)
- if (term_has_meta && _rl_term_mm)
- tputs (_rl_term_mm, 1, _rl_output_character_function);
-#endif
-}
-
-void
-_rl_control_keypad (on)
- int on;
-{
-#if !defined (__DJGPP__)
- if (on && _rl_term_ks)
- tputs (_rl_term_ks, 1, _rl_output_character_function);
- else if (!on && _rl_term_ke)
- tputs (_rl_term_ke, 1, _rl_output_character_function);
-#endif
-}
-
-/* **************************************************************** */
-/* */
-/* Controlling the Cursor */
-/* */
-/* **************************************************************** */
-
-/* Set the cursor appropriately depending on IM, which is one of the
- insert modes (insert or overwrite). Insert mode gets the normal
- cursor. Overwrite mode gets a very visible cursor. Only does
- anything if we have both capabilities. */
-void
-_rl_set_cursor (im, force)
- int im, force;
-{
- if (_rl_term_ve && _rl_term_vs)
- {
- if (force || im != rl_insert_mode)
- {
- if (im == RL_IM_OVERWRITE)
- tputs (_rl_term_vs, 1, _rl_output_character_function);
- else
- tputs (_rl_term_ve, 1, _rl_output_character_function);
- }
- }
-}
diff --git a/lib/readline/text.c~ b/lib/readline/text.c~
deleted file mode 100644
index d771de0d..00000000
--- a/lib/readline/text.c~
+++ /dev/null
@@ -1,1637 +0,0 @@
-/* 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;
- mbstate_t mps;
-#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 (&mps, 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, &mps);
- nwc = (nop == UpCase) ? _rl_to_wupper (wc) : _rl_to_wlower (wc);
- if (nwc != wc) /* just skip unchanged characters */
- {
- mblen = wcrtomb (mb, nwc, &mps);
- 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/undo.c~ b/lib/readline/undo.c~
deleted file mode 100644
index a27089a2..00000000
--- a/lib/readline/undo.c~
+++ /dev/null
@@ -1,292 +0,0 @@
-/* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
-
-/* Copyright (C) 1987, 1989, 1992, 2006 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>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h> /* for _POSIX_VERSION */
-#endif /* HAVE_UNISTD_H */
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif /* HAVE_STDLIB_H */
-
-#include <stdio.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 "xmalloc.h"
-
-extern void replace_history_data PARAMS((int, histdata_t *, histdata_t *));
-
-/* Non-zero tells rl_delete_text and rl_insert_text to not add to
- the undo list. */
-int _rl_doing_an_undo = 0;
-
-/* How many unclosed undo groups we currently have. */
-int _rl_undo_group_level = 0;
-
-/* The current undo list for THE_LINE. */
-UNDO_LIST *rl_undo_list = (UNDO_LIST *)NULL;
-
-/* **************************************************************** */
-/* */
-/* Undo, and Undoing */
-/* */
-/* **************************************************************** */
-
-static UNDO_LIST *
-alloc_undo_entry (what, start, end, text)
- enum undo_code what;
- int start, end;
- char *text;
-{
- UNDO_LIST *temp;
-
- temp = (UNDO_LIST *)xmalloc (sizeof (UNDO_LIST));
- temp->what = what;
- temp->start = start;
- temp->end = end;
- temp->text = text;
-
- temp->next = (UNDO_LIST *)NULL;
- return temp;
-}
-
-/* Remember how to undo something. Concatenate some undos if that
- seems right. */
-void
-rl_add_undo (what, start, end, text)
- enum undo_code what;
- int start, end;
- char *text;
-{
- UNDO_LIST *temp;
-
- temp = alloc_undo_entry (what, start, end, text);
- temp->next = rl_undo_list;
- rl_undo_list = temp;
-}
-
-/* Free the existing undo list. */
-void
-rl_free_undo_list ()
-{
- UNDO_LIST *release, *orig_list;
-
- orig_list = rl_undo_list;
- while (rl_undo_list)
- {
- release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
-
- if (release->what == UNDO_DELETE)
- free (release->text);
-
- free (release);
- }
- rl_undo_list = (UNDO_LIST *)NULL;
- replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
-}
-
-/* Undo the next thing in the list. Return 0 if there
- is nothing to undo, or non-zero if there was. */
-int
-rl_do_undo ()
-{
- UNDO_LIST *release;
- int waiting_for_begin, start, end;
-
-#define TRANS(i) ((i) == -1 ? rl_point : ((i) == -2 ? rl_end : (i)))
-
- start = end = waiting_for_begin = 0;
- do
- {
- if (!rl_undo_list)
- return (0);
-
- _rl_doing_an_undo = 1;
- RL_SETSTATE(RL_STATE_UNDOING);
-
- /* To better support vi-mode, a start or end value of -1 means
- rl_point, and a value of -2 means rl_end. */
- if (rl_undo_list->what == UNDO_DELETE || rl_undo_list->what == UNDO_INSERT)
- {
- start = TRANS (rl_undo_list->start);
- end = TRANS (rl_undo_list->end);
- }
-
- switch (rl_undo_list->what)
- {
- /* Undoing deletes means inserting some text. */
- case UNDO_DELETE:
- rl_point = start;
- rl_insert_text (rl_undo_list->text);
- free (rl_undo_list->text);
- break;
-
- /* Undoing inserts means deleting some text. */
- case UNDO_INSERT:
- rl_delete_text (start, end);
- rl_point = start;
- break;
-
- /* Undoing an END means undoing everything 'til we get to a BEGIN. */
- case UNDO_END:
- waiting_for_begin++;
- break;
-
- /* Undoing a BEGIN means that we are done with this group. */
- case UNDO_BEGIN:
- if (waiting_for_begin)
- waiting_for_begin--;
- else
- rl_ding ();
- break;
- }
-
- _rl_doing_an_undo = 0;
- RL_UNSETSTATE(RL_STATE_UNDOING);
-
- release = rl_undo_list;
- rl_undo_list = rl_undo_list->next;
- replace_history_data (-1, (histdata_t *)release, (histdata_t *)rl_undo_list);
-
- free (release);
- }
- while (waiting_for_begin);
-
- return (1);
-}
-#undef TRANS
-
-int
-_rl_fix_last_undo_of_type (type, start, end)
- int type, start, end;
-{
- UNDO_LIST *rl;
-
- for (rl = rl_undo_list; rl; rl = rl->next)
- {
- if (rl->what == type)
- {
- rl->start = start;
- rl->end = end;
- return 0;
- }
- }
- return 1;
-}
-
-/* Begin a group. Subsequent undos are undone as an atomic operation. */
-int
-rl_begin_undo_group ()
-{
- rl_add_undo (UNDO_BEGIN, 0, 0, 0);
- _rl_undo_group_level++;
- return 0;
-}
-
-/* End an undo group started with rl_begin_undo_group (). */
-int
-rl_end_undo_group ()
-{
- rl_add_undo (UNDO_END, 0, 0, 0);
- _rl_undo_group_level--;
- return 0;
-}
-
-/* Save an undo entry for the text from START to END. */
-int
-rl_modifying (start, end)
- int start, end;
-{
- if (start > end)
- {
- SWAP (start, end);
- }
-
- if (start != end)
- {
- char *temp = rl_copy_text (start, end);
- rl_begin_undo_group ();
- rl_add_undo (UNDO_DELETE, start, end, temp);
- rl_add_undo (UNDO_INSERT, start, end, (char *)NULL);
- rl_end_undo_group ();
- }
- return 0;
-}
-
-/* Revert the current line to its previous state. */
-int
-rl_revert_line (count, key)
- int count, key;
-{
- if (!rl_undo_list)
- rl_ding ();
- else
- {
- while (rl_undo_list)
- rl_do_undo ();
-#if defined (VI_MODE)
- if (rl_editing_mode == vi_mode)
- rl_point = rl_mark = 0; /* rl_end should be set correctly */
-#endif
- }
-
- return 0;
-}
-
-/* Do some undoing of things that were done. */
-int
-rl_undo_command (count, key)
- int count, key;
-{
- if (count < 0)
- return 0; /* Nothing to do. */
-
- while (count)
- {
- if (rl_do_undo ())
- count--;
- else
- {
- rl_ding ();
- break;
- }
- }
- return 0;
-}
diff --git a/lib/readline/vi_mode.c~ b/lib/readline/vi_mode.c~
deleted file mode 100644
index 7cb838b0..00000000
--- a/lib/readline/vi_mode.c~
+++ /dev/null
@@ -1,1748 +0,0 @@
-/* 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 void _rl_vi_backup PARAMS((void));
-
-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 void _rl_vi_append_forward PARAMS((int));
-
-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_vi_backup ();
- }
- /* Ditto for redoing an insert with `a', but move forward a character first
- like the `a' command does. */
- else if (_rl_vi_last_command == 'a' && vi_insert_buffer && *vi_insert_buffer)
- {
- _rl_vi_append_forward ('a');
- _rl_vi_stuff_insert (count);
- if (rl_point > 0)
- _rl_vi_backup ();
- }
- 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);
-}
-
-static void
-_rl_vi_append_forward (key)
- int key;
-{
- int point;
-
- if (rl_point < rl_end)
- {
- if (MB_CUR_MAX == 1 || rl_byte_oriented)
- rl_point++;
- else
- {
- point = rl_point;
- rl_forward_char (1, key);
- if (point == rl_point)
- rl_point = rl_end;
- }
- }
-}
-
-int
-rl_vi_append_mode (count, key)
- int count, key;
-{
- _rl_vi_append_forward (key);
- rl_vi_start_inserting (key, 1, rl_arg_sign);
- 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 || up->what != UNDO_INSERT)
- {
- 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);
-}
-
-static void
-_rl_vi_backup ()
-{
- 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--;
-}
-
-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 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, mlen)
- char *mb;
- int mlen;
-{
- 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, mlen);
-#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/lib/sh/Makefile.in~ b/lib/sh/Makefile.in~
deleted file mode 100644
index f40474a2..00000000
--- a/lib/sh/Makefile.in~
+++ /dev/null
@@ -1,470 +0,0 @@
-#
-# Makefile for the Bash library
-#
-#
-# Copyright (C) 1998-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.
-
-PACKAGE = @PACKAGE_NAME@
-VERSION = @PACKAGE_VERSION@
-
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-
-srcdir = @srcdir@
-VPATH = .:@srcdir@
-topdir = @top_srcdir@
-BUILD_DIR = @BUILD_DIR@
-
-LIBBUILD = ${BUILD_DIR}/lib
-
-BASHINCDIR = ${topdir}/include
-
-INTL_LIBSRC = ${topdir}/lib/intl
-INTL_BUILDDIR = ${LIBBUILD}/intl
-INTL_INC = @INTL_INC@
-LIBINTL_H = @LIBINTL_H@
-
-INSTALL = @INSTALL@
-INSTALL_PROGRAM = @INSTALL_PROGRAM@
-INSTALL_DATA = @INSTALL_DATA@
-
-CC = @CC@
-RANLIB = @RANLIB@
-AR = @AR@
-ARFLAGS = @ARFLAGS@
-RM = rm -f
-CP = cp
-MV = mv
-
-SHELL = @MAKE_SHELL@
-
-CFLAGS = @CFLAGS@
-LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG}
-CPPFLAGS = @CPPFLAGS@
-LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@
-
-PROFILE_FLAGS = @PROFILE_FLAGS@
-
-DEFS = @DEFS@
-LOCAL_DEFS = @LOCAL_DEFS@
-
-INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(BASHINCDIR) -I$(srcdir) $(INTL_INC)
-
-CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \
- $(CFLAGS) $(CPPFLAGS)
-
-GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
- -Wcast-align -Wstrict-prototypes -Wconversion \
- -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
-
-.c.o:
- $(CC) -c $(CCFLAGS) $<
-
-# The name of the library target.
-LIBRARY_NAME = libsh.a
-
-# The C code source files for this library.
-CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
- strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \
- vprint.c itos.c rename.c zread.c zwrite.c shtty.c \
- inet_aton.c netconn.c netopen.c strpbrk.c timeval.c makepath.c \
- pathcanon.c pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
- shquote.c strtrans.c strindex.c snprintf.c mailstat.c \
- fmtulong.c fmtullong.c fmtumax.c shmatch.c strnlen.c \
- strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c strstr.c \
- mktime.c strftime.c xstrchr.c zcatfd.c winsize.c shaccess.c
-
-# The header files for this library.
-HSOURCES =
-
-# The object files contained in $(LIBRARY_NAME)
-LIBOBJS = @LIBOBJS@
-OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
- itos.o zread.o zwrite.o shtty.o shmatch.o shaccess.o \
- netconn.o netopen.o timeval.o makepath.o pathcanon.o \
- pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
- strtrans.o strindex.o snprintf.o mailstat.o fmtulong.o \
- fmtullong.o fmtumax.o xstrchr.o zcatfd.o winsize.o ${LIBOBJS}
-
-SUPPORT = Makefile
-
-all: $(LIBRARY_NAME)
-
-$(LIBRARY_NAME): $(OBJECTS)
- $(RM) $@
- $(AR) $(ARFLAGS) $@ $(OBJECTS)
- -test -n "$(RANLIB)" && $(RANLIB) $@
-
-force:
-
-# The rule for 'includes' is written funny so that the if statement
-# always returns TRUE unless there really was an error installing the
-# include files.
-install:
-
-clean:
- $(RM) $(OBJECTS) $(LIBRARY_NAME)
-
-realclean distclean maintainer-clean: clean
- $(RM) Makefile
-
-mostlyclean: clean
-
-# Dependencies
-
-${BUILD_DIR}/version.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
- -( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} version.h )
-
-# rules for losing makes, like SunOS
-clktck.o: clktck.c
-clock.o: clock.c
-fmtullong.o: fmtullong.c
-fmtulong.o: fmtulong.c
-fmtumax.o: fmtumax.c
-getcwd.o: getcwd.c
-getenv.o: getenv.c
-inet_aton.o: inet_aton.c
-itos.o: itos.c
-mailstat.o: mailstat.c
-makepath.o: makepath.c
-memset.o: memset.c
-mktime.o: mktime.c
-netconn.o: netconn.c
-netopen.o: netopen.c
-oslib.o: oslib.c
-pathcanon.o: pathcanon.c
-pathphys.o: pathphys.c
-rename.o: rename.c
-setlinebuf.o: setlinebuf.c
-shaccess.o: shaccess.c
-shquote.o: shquote.c
-shtty.o: shtty.c
-snprintf.o: snprintf.c
-spell.o: spell.c
-strcasecmp.o: strcasecmp.c
-strerror.o: strerror.c
-strftime.o: strftime.c
-strindex.o: strindex.c
-stringlist.o: stringlist.c
-stringvec.o: stringvec.c
-strnlen.o: strnlen.c
-strpbrk.o: strpbrk.c
-strtod.o: strtod.c
-strtoimax.o: strtoimax.c
-strtol.o: strtol.c
-strtoll.o: strtoll.c
-strtoul.o: strtoul.c
-strtoull.o: strtoull.c
-strtoumax.o: strtoumax.c
-strtrans.o: strtrans.c
-times.o: times.c
-timeval.o: timeval.c
-tmpfile.o: tmpfile.c
-vprint.o: vprint.c
-xstrchr.o: xstrchr.c
-zcatfd.o: zcatfd.c
-zread.o: zread.c
-zwrite.o: zwrite.c
-
-# dependencies for c files that include other c files
-fmtullong.o: fmtulong.c
-fmtumax.o: fmtulong.c
-strtoll.o: strtol.c
-strtoul.o: strtol.c
-strtoull.o: strtol.c
-
-# all files in the library depend on config.h
-clktck.o: ${BUILD_DIR}/config.h
-clock.o: ${BUILD_DIR}/config.h
-fmtullong.o: ${BUILD_DIR}/config.h
-fmtulong.o: ${BUILD_DIR}/config.h
-fmtumax.o: ${BUILD_DIR}/config.h
-getcwd.o: ${BUILD_DIR}/config.h
-getenv.o: ${BUILD_DIR}/config.h
-inet_aton.o: ${BUILD_DIR}/config.h
-itos.o: ${BUILD_DIR}/config.h
-mailstat.o: ${BUILD_DIR}/config.h
-makepath.o: ${BUILD_DIR}/config.h
-memset.o: ${BUILD_DIR}/config.h
-mktime.o: ${BUILD_DIR}/config.h
-netconn.o: ${BUILD_DIR}/config.h
-netopen.o: ${BUILD_DIR}/config.h
-oslib.o: ${BUILD_DIR}/config.h
-pathcanon.o: ${BUILD_DIR}/config.h
-pathphys.o: ${BUILD_DIR}/config.h
-rename.o: ${BUILD_DIR}/config.h
-setlinebuf.o: ${BUILD_DIR}/config.h
-shaccess.o: ${BUILD_DIR}/config.h
-shquote.o: ${BUILD_DIR}/config.h
-shtty.o: ${BUILD_DIR}/config.h
-snprintf.o: ${BUILD_DIR}/config.h
-spell.o: ${BUILD_DIR}/config.h
-strcasecmp.o: ${BUILD_DIR}/config.h
-strerror.o: ${BUILD_DIR}/config.h
-strftime.o: ${BUILD_DIR}/config.h
-strindex.o: ${BUILD_DIR}/config.h
-stringlist.o: ${BUILD_DIR}/config.h
-stringvec.o: ${BUILD_DIR}/config.h
-strnlen.o: ${BUILD_DIR}/config.h
-strpbrk.o: ${BUILD_DIR}/config.h
-strtod.o: ${BUILD_DIR}/config.h
-strtoimax.o: ${BUILD_DIR}/config.h
-strtol.o: ${BUILD_DIR}/config.h
-strtoll.o: ${BUILD_DIR}/config.h
-strtoul.o: ${BUILD_DIR}/config.h
-strtoull.o: ${BUILD_DIR}/config.h
-strtoumax.o: ${BUILD_DIR}/config.h
-strtrans.o: ${BUILD_DIR}/config.h
-times.o: ${BUILD_DIR}/config.h
-timeval.o: ${BUILD_DIR}/config.h
-tmpfile.o: ${BUILD_DIR}/config.h
-vprint.o: ${BUILD_DIR}/config.h
-xstrchr.o: ${BUILD_DIR}/config.h
-zcatfd.o: ${BUILD_DIR}/config.h
-zread.o: ${BUILD_DIR}/config.h
-zwrite.o: ${BUILD_DIR}/config.h
-
-clktck.o: ${topdir}/bashtypes.h
-
-getcwd.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
-getcwd.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h
-getcwd.o: ${BASHINCDIR}/memalloc.h ${BASHINCDIR}/ansi_stdlib.h
-
-getenv.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
-getenv.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-getenv.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-getenv.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
-getenv.o: ${BUILD_DIR}/version.h
-
-inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
-inet_aton.o: ${BASHINCDIR}/stdc.h
-
-itos.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
-itos.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-itos.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-
-makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
-makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-makepath.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-
-netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
-netconn.o: ${topdir}/bashtypes.h
-
-netopen.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
-netopen.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-netopen.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-
-oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
-oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-oslib.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
-oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-
-pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
-pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-pathcanon.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
-pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-
-pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
-pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-pathphys.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
-pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-
-rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
-rename.o: ${BASHINCDIR}/posixstat.h
-
-setlinebuf.o: ${topdir}/xmalloc.h ${topdir}/bashansi.h
-setlinebuf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/stdc.h
-
-shaccess.o: ${topdir}/bashtypes.h
-shaccess.o: ${BASHINCDIR}/posixstat.h
-shaccess.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
-shaccess.o: ${BASHINCDIR}/filecntl.h
-shaccess.o: ${BASHINCDIR}/stdc.h
-shaccess.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-shaccess.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-shaccess.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-shaccess.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-shaccess.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-shaccess.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-shaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-
-shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
-shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
-
-shtty.o: ${BASHINCDIR}/shtty.h
-shtty.o: ${BASHINCDIR}/stdc.h
-
-snprintf.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h ${topdir}/xmalloc.h
-snprintf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-snprintf.o: ${BASHINCDIR}/typemax.h
-
-spell.o: ${topdir}/bashtypes.h
-spell.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h
-spell.o: ${BASHINCDIR}/ansi_stdlib.h
-
-strcasecmp.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
-strcasecmp.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-
-strerror.o: ${topdir}/bashtypes.h
-strerror.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-strerror.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-
-strindex.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
-strindex.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-
-stringlist.o: ${topdir}/bashansi.h
-stringlist.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-stringlist.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-
-stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h
-stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-stringvec.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-
-strnlen.o: ${BASHINCDIR}/stdc.h
-
-strpbrk.o: ${BASHINCDIR}/stdc.h
-
-strtod.o: ${topdir}/bashansi.h
-strtod.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-
-strtoimax.o: ${BASHINCDIR}/stdc.h
-
-strtol.o: ${topdir}/bashansi.h
-strtol.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-strtol.o: ${BASHINCDIR}/typemax.h
-
-strtoll.o: ${topdir}/bashansi.h
-strtoll.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-strtoll.o: ${BASHINCDIR}/typemax.h
-
-strtoul.o: ${topdir}/bashansi.h
-strtoul.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-strtoul.o: ${BASHINCDIR}/typemax.h
-
-strtoull.o: ${topdir}/bashansi.h
-strtoull.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-strtoull.o: ${BASHINCDIR}/typemax.h
-
-strtoumax.o: ${BASHINCDIR}/stdc.h
-
-strtrans.o: ${topdir}/bashansi.h
-strtrans.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
-strtrans.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
-strtrans.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
-strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
-strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
-strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
-strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
-strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
-
-times.o: ${BASHINCDIR}/systimes.h
-times.o: ${BASHINCDIR}/posixtime.h
-
-timeval.o: ${BASHINCDIR}/posixtime.h
-
-tmpfile.o: ${topdir}/bashtypes.h
-tmpfile.o: ${BASHINCDIR}/posixstat.h
-tmpfile.o: ${BASHINCDIR}/filecntl.h
-
-clock.o: ${BASHINCDIR}/posixtime.h
-
-mailstat.o: ${topdir}/bashansi.h
-mailstat.o: ${topdir}/bashtypes.h
-mailstat.o: ${BASHINCDIR}/ansi_stdlib.h
-mailstat.o: ${BASHINCDIR}/posixstat.h
-mailstat.o: ${BASHINCDIR}/posixdir.h
-mailstat.o: ${BASHINCDIR}/maxpath.h
-
-fmtulong.o: ${topdir}/bashansi.h
-fmtulong.o: ${BASHINCDIR}/ansi_stdlib.h
-fmtulong.o: ${BASHINCDIR}/chartypes.h
-fmtulong.o: ${BASHINCDIR}/stdc.h
-fmtulong.o: ${BASHINCDIR}/typemax.h
-fmtulong.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
-
-fmtullong.o: ${topdir}/bashansi.h
-fmtullong.o: ${BASHINCDIR}/ansi_stdlib.h
-fmtullong.o: ${BASHINCDIR}/chartypes.h
-fmtullong.o: ${BASHINCDIR}/stdc.h
-fmtullong.o: ${BASHINCDIR}/typemax.h
-fmtullong.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
-
-fmtumax.o: ${topdir}/bashansi.h
-fmtumax.o: ${BASHINCDIR}/ansi_stdlib.h
-fmtumax.o: ${BASHINCDIR}/chartypes.h
-fmtumax.o: ${BASHINCDIR}/stdc.h
-fmtumax.o: ${BASHINCDIR}/typemax.h
-fmtumax.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
-
-xstrchr.o: ${topdir}/bashansi.h
-xstrchr.o: ${BASHINCDIR}/ansi_stdlib.h
-xstrchr.o: ${BASHINCDIR}/shmbutil.h
diff --git a/lib/sh/eaccess.c~ b/lib/sh/eaccess.c~
deleted file mode 100644
index 8f946a49..00000000
--- a/lib/sh/eaccess.c~
+++ /dev/null
@@ -1,222 +0,0 @@
-/* sheaccess.c - eaccess replacement for the shell. */
-
-/* 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. */
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include "bashtypes.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "bashansi.h"
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#if !defined (_POSIX_VERSION) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif /* !_POSIX_VERSION */
-#include "posixstat.h"
-#include "filecntl.h"
-
-#include "shell.h"
-
-#if !defined (R_OK)
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#define F_OK 0
-#endif /* R_OK */
-
-static int path_is_devfd __P((const char *));
-static int sh_stataccess __P((char *, int));
-#if HAVE_DECL_SETREGID
-static int sh_euidaccess __P((char *, int));
-#endif
-
-static int
-path_is_devfd (path)
- const char *path;
-{
- if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
- return 1;
- else if (STREQN (path, "/dev/std", 8))
- {
- if (STREQ (path+8, "in") || STREQ (path+8, "out") || STREQ (path+8, "err"))
- return 1;
- else
- return 0;
- }
- else
- return 0;
-}
-
-/* A wrapper for stat () which disallows pathnames that are empty strings
- and handles /dev/fd emulation on systems that don't have it. */
-int
-sh_stat (path, finfo)
- const char *path;
- struct stat *finfo;
-{
- if (*path == '\0')
- {
- errno = ENOENT;
- return (-1);
- }
- if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
- {
-#if !defined (HAVE_DEV_FD)
- intmax_t fd;
- int r;
-
- if (legal_number (path + 8, &fd) && fd == (int)fd)
- {
- r = fstat ((int)fd, finfo);
- if (r == 0 || errno != EBADF)
- return (r);
- }
- errno = ENOENT;
- return (-1);
-#else
- /* If HAVE_DEV_FD is defined, DEV_FD_PREFIX is defined also, and has a
- trailing slash. Make sure /dev/fd/xx really uses DEV_FD_PREFIX/xx.
- On most systems, with the notable exception of linux, this is
- effectively a no-op. */
- char pbuf[32];
- strcpy (pbuf, DEV_FD_PREFIX);
- strcat (pbuf, path + 8);
- return (stat (pbuf, finfo));
-#endif /* !HAVE_DEV_FD */
- }
-#if !defined (HAVE_DEV_STDIN)
- else if (STREQN (path, "/dev/std", 8))
- {
- if (STREQ (path+8, "in"))
- return (fstat (0, finfo));
- else if (STREQ (path+8, "out"))
- return (fstat (1, finfo));
- else if (STREQ (path+8, "err"))
- return (fstat (2, finfo));
- else
- return (stat (path, finfo));
- }
-#endif /* !HAVE_DEV_STDIN */
- return (stat (path, finfo));
-}
-
-/* Do the same thing access(2) does, but use the effective uid and gid,
- and don't make the mistake of telling root that any file is
- executable. This version uses stat(2). */
-static int
-sh_stataccess (path, mode)
- char *path;
- int mode;
-{
- struct stat st;
-
- if (sh_stat (path, &st) < 0)
- return (-1);
-
- if (current_user.euid == 0)
- {
- /* Root can read or write any file. */
- if ((mode & X_OK) == 0)
- return (0);
-
- /* Root can execute any file that has any one of the execute
- bits set. */
- if (st.st_mode & S_IXUGO)
- return (0);
- }
-
- if (st.st_uid == current_user.euid) /* owner */
- mode <<= 6;
- else if (group_member (st.st_gid))
- mode <<= 3;
-
- if (st.st_mode & mode)
- return (0);
-
- errno = EACCES;
- return (-1);
-}
-
-#if HAVE_DECL_SETREGID
-/* Version to call when uid != euid or gid != egid. We temporarily swap
- the effective and real uid and gid as appropriate. */
-static int
-sh_euidaccess (path, mode)
- char *path;
- int mode;
-{
- int r, e;
-
- if (current_user.uid != current_user.euid)
- setreuid (current_user.euid, current_user.uid);
- if (current_user.gid != current_user.egid)
- setregid (current_user.egid, current_user.gid);
-
- r = access (path, mode);
- e = errno;
-
- if (current_user.uid != current_user.euid)
- setreuid (current_user.uid, current_user.euid);
- if (current_user.gid != current_user.egid)
- setregid (current_user.gid, current_user.egid);
-
- errno = e;
- return r;
-}
-#endif
-
-int
-sh_eaccess (path, mode)
- char *path;
- int mode;
-{
- if (path_is_devfd (path))
- return (sh_stataccess (path, mode));
-
-#if defined (HAVE_EACCESS) /* FreeBSD */
- return (eaccess (path, mode));
-#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
- return access (path, mode|EFF_ONLY_OK);
-#else
- if (mode == F_OK)
- return (sh_stataccess (path, mode));
-
-# if HAVE_DECL_SETREGID
- if (current_user.uid != current_user.euid || current_user.gid != current_user.egid)
- return (sh_euidaccess (path, mode));
-# endif
-
- if (current_user.uid == current_user.euid && current_user.gid == current_user.egid)
- return (access (path, mode));
-
- return (sh_stataccess (path, mode));
-#endif
-}
diff --git a/lib/sh/netopen.c~ b/lib/sh/netopen.c~
deleted file mode 100644
index aaf0c475..00000000
--- a/lib/sh/netopen.c~
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * netopen.c -- functions to make tcp/udp connections
- *
- * Chet Ramey
- * chet@ins.CWRU.Edu
- */
-
-/* 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. */
-
-#include <config.h>
-
-#if defined (HAVE_NETWORK)
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <sys/types.h>
-
-#if defined (HAVE_SYS_SOCKET_H)
-# include <sys/socket.h>
-#endif
-
-#if defined (HAVE_NETINET_IN_H)
-# include <netinet/in.h>
-#endif
-
-#if defined (HAVE_NETDB_H)
-# include <netdb.h>
-#endif
-
-#if defined (HAVE_ARPA_INET_H)
-# include <arpa/inet.h>
-#endif
-
-#include <bashansi.h>
-#include <bashintl.h>
-
-#include <errno.h>
-
-#include <shell.h>
-#include <xmalloc.h>
-
-#ifndef errno
-extern int errno;
-#endif
-
-#if !defined (HAVE_INET_ATON)
-extern int inet_aton __P((const char *, struct in_addr *));
-#endif
-
-#ifndef HAVE_GETADDRINFO
-/* Stuff the internet address corresponding to HOST into AP, in network
- byte order. Return 1 on success, 0 on failure. */
-
-static int
-_getaddr (host, ap)
- char *host;
- struct in_addr *ap;
-{
- struct hostent *h;
- int r;
-
- r = 0;
- if (host[0] >= '0' && host[0] <= '9')
- {
- /* If the first character is a digit, guess that it's an
- Internet address and return immediately if inet_aton succeeds. */
- r = inet_aton (host, ap);
- if (r)
- return r;
- }
-#if !defined (HAVE_GETHOSTBYNAME)
- return 0;
-#else
- h = gethostbyname (host);
- if (h && h->h_addr)
- {
- bcopy(h->h_addr, (char *)ap, h->h_length);
- return 1;
- }
-#endif
- return 0;
-
-}
-
-/* Return 1 if SERV is a valid port number and stuff the converted value into
- PP in network byte order. */
-static int
-_getserv (serv, proto, pp)
- char *serv;
- int proto;
- unsigned short *pp;
-{
- intmax_t l;
- unsigned short s;
-
- if (legal_number (serv, &l))
- {
- s = (unsigned short)(l & 0xFFFF);
- if (s != l)
- return (0);
- s = htons (s);
- if (pp)
- *pp = s;
- return 1;
- }
- else
-#if defined (HAVE_GETSERVBYNAME)
- {
- struct servent *se;
-
- se = getservbyname (serv, (proto == 't') ? "tcp" : "udp");
- if (se == 0)
- return 0;
- if (pp)
- *pp = se->s_port; /* ports returned in network byte order */
- return 1;
- }
-#else /* !HAVE_GETSERVBYNAME */
- return 0;
-#endif /* !HAVE_GETSERVBYNAME */
-}
-
-/*
- * Open a TCP or UDP connection to HOST on port SERV. Uses the
- * traditional BSD mechanisms. Returns the connected socket or -1 on error.
- */
-static int
-_netopen4(host, serv, typ)
- char *host, *serv;
- int typ;
-{
- struct in_addr ina;
- struct sockaddr_in sin;
- unsigned short p;
- int s, e;
-
- if (_getaddr(host, &ina) == 0)
- {
- internal_error (_("%s: host unknown"), host);
- errno = EINVAL;
- return -1;
- }
-
- if (_getserv(serv, typ, &p) == 0)
- {
- internal_error(_("%s: invalid service"), serv);
- errno = EINVAL;
- return -1;
- }
-
- memset ((char *)&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_port = p;
- sin.sin_addr = ina;
-
- s = socket(AF_INET, (typ == 't') ? SOCK_STREAM : SOCK_DGRAM, 0);
- if (s < 0)
- {
- sys_error ("socket");
- return (-1);
- }
-
- if (connect (s, (struct sockaddr *)&sin, sizeof (sin)) < 0)
- {
- e = errno;
- sys_error("connect");
- close(s);
- errno = e;
- return (-1);
- }
-
- return(s);
-}
-#endif /* ! HAVE_GETADDRINFO */
-
-#ifdef HAVE_GETADDRINFO
-/*
- * Open a TCP or UDP connection to HOST on port SERV. Uses getaddrinfo(3)
- * which provides support for IPv6. Returns the connected socket or -1
- * on error.
- */
-static int
-_netopen6 (host, serv, typ)
- char *host, *serv;
- int typ;
-{
- int s, e;
- struct addrinfo hints, *res, *res0;
- int gerr;
-
- memset ((char *)&hints, 0, sizeof (hints));
- /* XXX -- if problems with IPv6, set to PF_INET for IPv4 only */
-#ifdef DEBUG /* PF_INET is the one that works for me */
- hints.ai_family = PF_INET;
-#else
- hints.ai_family = PF_UNSPEC;
-#endif
- hints.ai_socktype = (typ == 't') ? SOCK_STREAM : SOCK_DGRAM;
-
- gerr = getaddrinfo (host, serv, &hints, &res0);
- if (gerr)
- {
- if (gerr == EAI_SERVICE)
- internal_error ("%s: %s", serv, gai_strerror (gerr));
- else
- internal_error ("%s: %s", host, gai_strerror (gerr));
- errno = EINVAL;
- return -1;
- }
-
- for (res = res0; res; res = res->ai_next)
- {
- if ((s = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
- {
- if (res->ai_next)
- continue;
- sys_error ("socket");
- freeaddrinfo (res0);
- return -1;
- }
- if (connect (s, res->ai_addr, res->ai_addrlen) < 0)
- {
- if (res->ai_next)
- {
- close (s);
- continue;
- }
- e = errno;
- sys_error ("connect");
- close (s);
- freeaddrinfo (res0);
- errno = e;
- return -1;
- }
- freeaddrinfo (res0);
- break;
- }
- return s;
-}
-#endif /* HAVE_GETADDRINFO */
-
-/*
- * Open a TCP or UDP connection to HOST on port SERV. Uses getaddrinfo(3)
- * if available, falling back to the traditional BSD mechanisms otherwise.
- * Returns the connected socket or -1 on error.
- */
-static int
-_netopen(host, serv, typ)
- char *host, *serv;
- int typ;
-{
-#ifdef HAVE_GETADDRINFO
- return (_netopen6 (host, serv, typ));
-#else
- return (_netopen4 (host, serv, typ));
-#endif
-}
-
-/*
- * Open a TCP or UDP connection given a path like `/dev/tcp/host/port' to
- * host `host' on port `port' and return the connected socket.
- */
-int
-netopen (path)
- char *path;
-{
- char *np, *s, *t;
- int fd;
-
- np = (char *)xmalloc (strlen (path) + 1);
- strcpy (np, path);
-
- s = np + 9;
- t = strchr (s, '/');
- if (t == 0)
- {
- internal_error (_("%s: bad network path specification"), path);
- return -1;
- }
- *t++ = '\0';
- fd = _netopen (s, t, path[5]);
- free (np);
-
- return fd;
-}
-
-#if 0
-/*
- * Open a TCP connection to host `host' on the port defined for service
- * `serv' and return the connected socket.
- */
-int
-tcpopen (host, serv)
- char *host, *serv;
-{
- return (_netopen (host, serv, 't'));
-}
-
-/*
- * Open a UDP connection to host `host' on the port defined for service
- * `serv' and return the connected socket.
- */
-int
-udpopen (host, serv)
- char *host, *serv;
-{
- return _netopen (host, serv, 'u');
-}
-#endif
-
-#else /* !HAVE_NETWORK */
-
-int
-netopen (path)
- char *path;
-{
- internal_error (_("network operations not supported"));
- return -1;
-}
-
-#endif /* !HAVE_NETWORK */
diff --git a/lib/sh/shaccess.c~ b/lib/sh/shaccess.c~
deleted file mode 100644
index 339f3dbf..00000000
--- a/lib/sh/shaccess.c~
+++ /dev/null
@@ -1,219 +0,0 @@
-/* sheaccess.c - eaccess replacement for the shell. */
-
-/* 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. */
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include "bashtypes.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "bashansi.h"
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#if !defined (_POSIX_VERSION) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif /* !_POSIX_VERSION */
-#include "posixstat.h"
-#include "filecntl.h"
-
-#include "shell.h"
-
-#if !defined (R_OK)
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#define F_OK 0
-#endif /* R_OK */
-
-static int path_is_devfd __P((const char *));
-static int sh_stataccess __P((char *, int));
-#if HAVE_DECL_SETREGID
-static int sh_euidaccess __P((char *, int));
-#endif
-
-static int
-path_is_devfd (path)
- const char *path;
-{
- if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
- return 1;
- else if (STREQN (path, "/dev/std", 8))
- {
- if (STREQ (path+8, "in") || STREQ (path+8, "out") || STREQ (path+8, "err"))
- return 1;
- else
- return 0;
- }
- else
- return 0;
-}
-
-/* A wrapper for stat () which disallows pathnames that are empty strings
- and handles /dev/fd emulation on systems that don't have it. */
-int
-sh_stat (path, finfo)
- const char *path;
- struct stat *finfo;
-{
- if (*path == '\0')
- {
- errno = ENOENT;
- return (-1);
- }
- if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
- {
-#if !defined (HAVE_DEV_FD)
- intmax_t fd;
- int r;
-
- if (legal_number (path + 8, &fd) && fd == (int)fd)
- {
- r = fstat ((int)fd, finfo);
- if (r == 0 || errno != EBADF)
- return (r);
- }
- errno = ENOENT;
- return (-1);
-#else
- /* If HAVE_DEV_FD is defined, DEV_FD_PREFIX is defined also, and has a
- trailing slash. Make sure /dev/fd/xx really uses DEV_FD_PREFIX/xx.
- On most systems, with the notable exception of linux, this is
- effectively a no-op. */
- char pbuf[32];
- strcpy (pbuf, DEV_FD_PREFIX);
- strcat (pbuf, path + 8);
- return (stat (pbuf, finfo));
-#endif /* !HAVE_DEV_FD */
- }
-#if !defined (HAVE_DEV_STDIN)
- else if (STREQN (path, "/dev/std", 8))
- {
- if (STREQ (path+8, "in"))
- return (fstat (0, finfo));
- else if (STREQ (path+8, "out"))
- return (fstat (1, finfo));
- else if (STREQ (path+8, "err"))
- return (fstat (2, finfo));
- else
- return (stat (path, finfo));
- }
-#endif /* !HAVE_DEV_STDIN */
- return (stat (path, finfo));
-}
-
-/* Do the same thing access(2) does, but use the effective uid and gid,
- and don't make the mistake of telling root that any file is
- executable. This version uses stat(2). */
-static int
-sh_stataccess (path, mode)
- char *path;
- int mode;
-{
- struct stat st;
-
- if (sh_stat (path, &st) < 0)
- return (-1);
-
- if (current_user.euid == 0)
- {
- /* Root can read or write any file. */
- if ((mode & X_OK) == 0)
- return (0);
-
- /* Root can execute any file that has any one of the execute
- bits set. */
- if (st.st_mode & S_IXUGO)
- return (0);
- }
-
- if (st.st_uid == current_user.euid) /* owner */
- mode <<= 6;
- else if (group_member (st.st_gid))
- mode <<= 3;
-
- if (st.st_mode & mode)
- return (0);
-
- errno = EACCES;
- return (-1);
-}
-
-#if HAVE_DECL_SETREGID
-/* Version to call when uid != euid or gid != egid. We temporarily swap
- the effective and real uid and gid as appropriate. */
-static int
-sh_euidaccess (path, mode)
- char *path;
- int mode;
-{
- int r, e;
-
- if (current_user.uid != current_user.euid)
- setreuid (current_user.euid, current_user.uid);
- if (current_user.gid != current_user.egid)
- setregid (current_user.egid, current_user.gid);
-
- r = access (path, mode);
- e = errno;
-
- if (current_user.uid != current_user.euid)
- setreuid (current_user.uid, current_user.euid);
- if (current_user.gid != current_user.egid)
- setregid (current_user.gid, current_user.egid);
-
- errno = e;
- return r;
-}
-#endif
-
-int
-sh_eaccess (path, mode)
- char *path;
- int mode;
-{
-#if defined (HAVE_EACCESS) /* FreeBSD */
- return (eaccess (path, mode));
-#elif defined (EFF_ONLY_OK) /* SVR4(?), SVR4.2 */
- return access (path, mode|EFF_ONLY_OK);
-#else
- if (mode == F_OK)
- return (sh_stataccess (path, mode));
-
-# if HAVE_DECL_SETREGID
- if (current_user.uid != current_user.euid || current_user.gid != current_user.egid)
- return (sh_euidaccess (path, mode));
-# endif
-
- if (current_user.uid == current_user.euid && current_user.gid == current_user.egid)
- return (access (path, mode));
-
- return (sh_stataccess (path, mode));
-#endif
-}
diff --git a/lib/sh/shmatch.c~ b/lib/sh/shmatch.c~
deleted file mode 100644
index 4508ed02..00000000
--- a/lib/sh/shmatch.c~
+++ /dev/null
@@ -1,121 +0,0 @@
-/* Copyright (C) 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. */
-
-/*
- * shmatch.c -- shell interface to posix regular expression matching.
- */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#if defined (HAVE_POSIX_REGEXP)
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include "bashansi.h"
-
-#include <stdio.h>
-#include <regex.h>
-
-#include "shell.h"
-#include "variables.h"
-#include "externs.h"
-
-extern int glob_ignore_case, match_ignore_case;
-
-int
-sh_regmatch (string, pattern, flags)
- const char *string;
- const char *pattern;
- int flags;
-{
- regex_t regex = { 0 };
- regmatch_t *matches;
- int rflags;
-#if defined (ARRAY_VARS)
- SHELL_VAR *rematch;
- ARRAY *amatch;
- int subexp_ind;
- char *subexp_str;
- int subexp_len;
-#endif
- int result;
-
-
-#if defined (ARRAY_VARS)
- rematch = (SHELL_VAR *)NULL;
-#endif
-
- rflags = REG_EXTENDED;
- if (glob_ignore_case || match_ignore_case)
- rflags |= REG_ICASE;
-#if !defined (ARRAY_VARS)
- rflags |= REG_NOSUB;
-#endif
-
- if (regcomp (&regex, pattern, rflags))
- return 2; /* flag for printing a warning here. */
-
-#if defined (ARRAY_VARS)
- matches = (regmatch_t *)malloc (sizeof (regmatch_t) * (regex.re_nsub + 1));
-#else
- matches = NULL;
-#endif
-
- if (regexec (&regex, string, regex.re_nsub + 1, matches, 0))
- result = EXECUTION_FAILURE;
- else
- result = EXECUTION_SUCCESS; /* match */
-
-#if defined (ARRAY_VARS)
- subexp_len = strlen (string) + 10;
- subexp_str = malloc (subexp_len + 1);
-
- /* Store the parenthesized subexpressions in the array BASH_REMATCH.
- Element 0 is the portion that matched the entire regexp. Element 1
- is the part that matched the first subexpression, and so on. */
- unbind_variable ("BASH_REMATCH");
- rematch = make_new_array_variable ("BASH_REMATCH");
- amatch = array_cell (rematch);
-
- if ((flags & SHMAT_SUBEXP) && result == EXECUTION_SUCCESS && subexp_str)
- {
- for (subexp_ind = 0; subexp_ind <= regex.re_nsub; subexp_ind++)
- {
- memset (subexp_str, 0, subexp_len);
- strncpy (subexp_str, string + matches[subexp_ind].rm_so,
- matches[subexp_ind].rm_eo - matches[subexp_ind].rm_so);
- array_insert (amatch, subexp_ind, subexp_str);
- }
- }
-
- VSETATTR (rematch, att_readonly);
-
- free (subexp_str);
- free (matches);
-#endif /* ARRAY_VARS */
-
- regfree (&regex);
-
- return result;
-}
-
-#endif /* HAVE_POSIX_REGEXP */
diff --git a/lib/sh/strtrans.c~ b/lib/sh/strtrans.c~
deleted file mode 100644
index db7b1ba8..00000000
--- a/lib/sh/strtrans.c~
+++ /dev/null
@@ -1,284 +0,0 @@
-/* strtrans.c - Translate and untranslate strings with ANSI-C escape
- sequences. */
-
-/* Copyright (C) 2000
- 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 <bashansi.h>
-#include <stdio.h>
-#include <chartypes.h>
-
-#include "shell.h"
-
-#ifdef ESC
-#undef ESC
-#endif
-#define ESC '\033' /* ASCII */
-
-/* Convert STRING by expanding the escape sequences specified by the
- ANSI C standard. If SAWC is non-null, recognize `\c' and use that
- as a string terminator. If we see \c, set *SAWC to 1 before
- returning. LEN is the length of STRING. If (FLAGS&1) is non-zero,
- that we're translating a string for `echo -e', and therefore should not
- treat a single quote as a character that may be escaped with a backslash.
- If (FLAGS&2) is non-zero, we're expanding for the parser and want to
- quote CTLESC and CTLNUL with CTLESC. If (flags&4) is non-zero, we want
- to remove the backslash before any unrecognized escape sequence. */
-char *
-ansicstr (string, len, flags, sawc, rlen)
- char *string;
- int len, flags, *sawc, *rlen;
-{
- int c, temp;
- char *ret, *r, *s;
-
- if (string == 0 || *string == '\0')
- return ((char *)NULL);
-
- ret = (char *)xmalloc (2*len + 1); /* 2*len for possible CTLESC */
- for (r = ret, s = string; s && *s; )
- {
- c = *s++;
- if (c != '\\' || *s == '\0')
- *r++ = c;
- else
- {
- switch (c = *s++)
- {
-#if defined (__STDC__)
- case 'a': c = '\a'; break;
- case 'v': c = '\v'; break;
-#else
- case 'a': c = '\007'; break;
- case 'v': c = (int) 0x0B; break;
-#endif
- case 'b': c = '\b'; break;
- case 'e': case 'E': /* ESC -- non-ANSI */
- c = ESC; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7':
-#if 1
- if (flags & 1)
- {
- *r++ = '\\';
- break;
- }
-#endif
- /*FALLTHROUGH*/
- case '0':
- /* If (FLAGS & 1), we're translating a string for echo -e (or
- the equivalent xpg_echo option), so we obey the SUSv3/
- POSIX-2001 requirement and accept 0-3 octal digits after
- a leading `0'. */
- temp = 2 + ((flags & 1) && (c == '0'));
- for (c -= '0'; ISOCTAL (*s) && temp--; s++)
- c = (c * 8) + OCTVALUE (*s);
- c &= 0xFF;
- break;
- case 'x': /* Hex digit -- non-ANSI */
- if ((flags & 2) && *s == '{')
- {
- flags |= 16; /* internal flag value */
- s++;
- }
- /* Consume at least two hex characters */
- for (temp = 2, c = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++)
- c = (c * 16) + HEXVALUE (*s);
- /* DGK says that after a `\x{' ksh93 consumes ISXDIGIT chars
- until a non-xdigit or `}', so potentially more than two
- chars are consumed. */
- if (flags & 16)
- {
- for ( ; ISXDIGIT ((unsigned char)*s); s++)
- c = (c * 16) + HEXVALUE (*s);
- flags &= ~16;
- if (*s == '}')
- s++;
- }
- /* \x followed by non-hex digits is passed through unchanged */
- else if (temp == 2)
- {
- *r++ = '\\';
- c = 'x';
- }
- c &= 0xFF;
- break;
- case '\\':
- break;
- case '\'': case '"': case '?':
- if (flags & 1)
- *r++ = '\\';
- break;
- case 'c':
- if (sawc)
- {
- *sawc = 1;
- *r = '\0';
- if (rlen)
- *rlen = r - ret;
- return ret;
- }
- else if ((flags & 1) == 0 && (c = *s))
- {
- s++;
- c = TOCTRL(c);
- break;
- }
- /*FALLTHROUGH*/
- default:
- if ((flags & 4) == 0)
- *r++ = '\\';
- break;
- }
- if ((flags & 2) && (c == CTLESC || c == CTLNUL))
- *r++ = CTLESC;
- *r++ = c;
- }
- }
- *r = '\0';
- if (rlen)
- *rlen = r - ret;
- return ret;
-}
-
-/* Take a string STR, possibly containing non-printing characters, and turn it
- into a $'...' ANSI-C style quoted string. Returns a new string. */
-char *
-ansic_quote (str, flags, rlen)
- char *str;
- int flags, *rlen;
-{
- char *r, *ret, *s;
- int l, rsize, t;
- unsigned char c;
-
- if (str == 0 || *str == 0)
- return ((char *)0);
-
- l = strlen (str);
- rsize = 4 * l + 4;
- r = ret = (char *)xmalloc (rsize);
-
- *r++ = '$';
- *r++ = '\'';
-
- for (s = str, l = 0; *s; s++)
- {
- c = *s;
- l = 1; /* 1 == add backslash; 0 == no backslash */
- switch (c)
- {
- case ESC: c = 'E'; break;
-#ifdef __STDC__
- case '\a': c = 'a'; break;
- case '\v': c = 'v'; break;
-#else
- case '\007': c = 'a'; break;
- case 0x0b: c = 'v'; break;
-#endif
-
- case '\b': c = 'b'; break;
- case '\f': c = 'f'; break;
- case '\n': c = 'n'; break;
- case '\r': c = 'r'; break;
- case '\t': c = 't'; break;
- case '\\':
- case '\'':
- break;
- default:
- if (ISPRINT (c) == 0)
- {
- *r++ = '\\';
- *r++ = TOCHAR ((c >> 6) & 07);
- *r++ = TOCHAR ((c >> 3) & 07);
- *r++ = TOCHAR (c & 07);
- continue;
- }
- l = 0;
- break;
- }
- if (l)
- *r++ = '\\';
- *r++ = c;
- }
-
- *r++ = '\'';
- *r = '\0';
- if (rlen)
- *rlen = r - ret;
- return ret;
-}
-
-/* return 1 if we need to quote with $'...' because of non-printing chars. */
-int
-ansic_shouldquote (string)
- const char *string;
-{
- const char *s;
- unsigned char c;
-
- if (string == 0)
- return 0;
-
- for (s = string; c = *s; s++)
- if (ISPRINT (c) == 0)
- return 1;
-
- return 0;
-}
-
-/* $'...' ANSI-C expand the portion of STRING between START and END and
- return the result. The result cannot be longer than the input string. */
-char *
-ansiexpand (string, start, end, lenp)
- char *string;
- int start, end, *lenp;
-{
- char *temp, *t;
- int len, tlen;
-
- temp = (char *)xmalloc (end - start + 1);
- for (tlen = 0, len = start; len < end; )
- temp[tlen++] = string[len++];
- temp[tlen] = '\0';
-
- if (*temp)
- {
- t = ansicstr (temp, tlen, 2, (int *)NULL, lenp);
- free (temp);
- return (t);
- }
- else
- {
- if (lenp)
- *lenp = 0;
- return (temp);
- }
-}
diff --git a/lib/sh/tmpfile.c~ b/lib/sh/tmpfile.c~
deleted file mode 100644
index f6e04fd5..00000000
--- a/lib/sh/tmpfile.c~
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * tmpfile.c - functions to create and safely open temp files for the shell.
- */
-
-/* Copyright (C) 2000 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 <posixstat.h>
-#include <posixtime.h>
-#include <filecntl.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <errno.h>
-
-#include <shell.h>
-
-#ifndef errno
-extern int errno;
-#endif
-
-#define BASEOPENFLAGS (O_CREAT | O_TRUNC | O_EXCL)
-
-#define DEFAULT_TMPDIR "." /* bogus default, should be changed */
-#define DEFAULT_NAMEROOT "shtmp"
-
-extern pid_t dollar_dollar_pid;
-
-static char *sys_tmpdir = (char *)NULL;
-static int ntmpfiles;
-static int tmpnamelen = -1;
-static unsigned long filenum = 1L;
-
-static char *
-get_sys_tmpdir ()
-{
- if (sys_tmpdir)
- return sys_tmpdir;
-
-#ifdef P_tmpdir
- sys_tmpdir = P_tmpdir;
- if (file_iswdir (sys_tmpdir))
- return sys_tmpdir;
-#endif
-
- sys_tmpdir = "/tmp";
- if (file_iswdir (sys_tmpdir))
- return sys_tmpdir;
-
- sys_tmpdir = "/var/tmp";
- if (file_iswdir (sys_tmpdir))
- return sys_tmpdir;
-
- sys_tmpdir = "/usr/tmp";
- if (file_iswdir (sys_tmpdir))
- return sys_tmpdir;
-
- sys_tmpdir = DEFAULT_TMPDIR;
-
- return sys_tmpdir;
-}
-
-static char *
-get_tmpdir (flags)
- int flags;
-{
- char *tdir;
-
- tdir = (flags & MT_USETMPDIR) ? get_string_value ("TMPDIR") : (char *)NULL;
- if (tdir == 0)
- tdir = get_sys_tmpdir ();
-
-#if defined (HAVE_PATHCONF) && defined (_PC_NAME_MAX)
- if (tmpnamelen == -1)
- tmpnamelen = pathconf (tdir, _PC_NAME_MAX);
-#else
- tmpnamelen = 0;
-#endif
-
- return tdir;
-}
-
-char *
-sh_mktmpname (nameroot, flags)
- char *nameroot;
- int flags;
-{
- char *filename, *tdir, *lroot;
- struct stat sb;
- int r, tdlen;
-
- filename = (char *)xmalloc (PATH_MAX + 1);
- tdir = get_tmpdir (flags);
- tdlen = strlen (tdir);
-
- lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
-
-#ifdef USE_MKTEMP
- sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
- if (mktemp (filename) == 0)
- {
- free (filename);
- filename = NULL;
- }
-#else /* !USE_MKTEMP */
- while (1)
- {
- filenum = (filenum << 1) ^
- (unsigned long) time ((time_t *)0) ^
- (unsigned long) dollar_dollar_pid ^
- (unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
- sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
- if (tmpnamelen > 0 && tmpnamelen < 32)
- filename[tdlen + 1 + tmpnamelen] = '\0';
-# ifdef HAVE_LSTAT
- r = lstat (filename, &sb);
-# else
- r = stat (filename, &sb);
-# endif
- if (r < 0 && errno == ENOENT)
- break;
- }
-#endif /* !USE_MKTEMP */
-
- return filename;
-}
-
-int
-sh_mktmpfd (nameroot, flags, namep)
- char *nameroot;
- int flags;
- char **namep;
-{
- char *filename, *tdir, *lroot;
- int fd, tdlen;
-
- filename = (char *)xmalloc (PATH_MAX + 1);
- tdir = get_tmpdir (flags);
- tdlen = strlen (tdir);
-
- lroot = nameroot ? nameroot : DEFAULT_NAMEROOT;
-
-#ifdef USE_MKSTEMP
- sprintf (filename, "%s/%s.XXXXXX", tdir, lroot);
- fd = mkstemp (filename);
- if (fd < 0 || namep == 0)
- {
- free (filename);
- filename = NULL;
- }
- if (namep)
- *namep = filename;
- return fd;
-#else /* !USE_MKSTEMP */
- do
- {
- filenum = (filenum << 1) ^
- (unsigned long) time ((time_t *)0) ^
- (unsigned long) dollar_dollar_pid ^
- (unsigned long) ((flags & MT_USERANDOM) ? get_random_number () : ntmpfiles++);
- sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum);
- if (tmpnamelen > 0 && tmpnamelen < 32)
- filename[tdlen + 1 + tmpnamelen] = '\0';
- fd = open (filename, BASEOPENFLAGS | ((flags & MT_READWRITE) ? O_RDWR : O_WRONLY), 0600);
- }
- while (fd < 0 && errno == EEXIST);
-
- if (namep)
- *namep = filename;
- else
- free (filename);
-
- return fd;
-#endif /* !USE_MKSTEMP */
-}
-
-FILE *
-sh_mktmpfp (nameroot, flags, namep)
- char *nameroot;
- int flags;
- char **namep;
-{
- int fd;
- FILE *fp;
-
- fd = sh_mktmpfd (nameroot, flags, namep);
- if (fd < 0)
- return ((FILE *)NULL);
- fp = fdopen (fd, (flags & MT_READWRITE) ? "w+" : "w");
- if (fp == 0)
- close (fd);
- return fp;
-}
diff --git a/lib/sh/winsize.c~ b/lib/sh/winsize.c~
deleted file mode 100644
index 8b39c99e..00000000
--- a/lib/sh/winsize.c~
+++ /dev/null
@@ -1,82 +0,0 @@
-/* Handle window size changes and information. */
-
-/* Copyright (C) 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 <stdc.h>
-
-#include "bashtypes.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <sys/ioctl.h>
-
-#if !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
-/* For struct winsize on SCO */
-/* sys/ptem.h has winsize but needs mblk_t from sys/stream.h */
-# if defined (HAVE_SYS_PTEM_H) && defined (TIOCGWINSZ) && defined (SIGWINCH)
-# if defined (HAVE_SYS_STREAM_H)
-# include <sys/stream.h>
-# endif
-# include <sys/ptem.h>
-# endif /* HAVE_SYS_PTEM_H && TIOCGWINSZ && SIGWINCH */
-#endif /* !STRUCT_WINSIZE_IN_SYS_IOCTL */
-
-#include <stdio.h>
-
-/* Return the fd from which we are actually getting input. */
-#define input_tty() (shell_tty != -1) ? shell_tty : fileno (stderr)
-
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-extern int shell_tty;
-
-#if defined (READLINE)
-extern void rl_set_screen_size __P((int, int));
-#endif
-
-void
-get_new_window_size (from_sig, rp, cp)
- int from_sig;
- int *rp, *cp;
-{
-#if defined (TIOCGWINSZ)
- struct winsize win;
- int tty;
-
- tty = input_tty ();
- if (tty >= 0 && (ioctl (tty, TIOCGWINSZ, &win) == 0) &&
- win.ws_row > 0 && win.ws_col > 0)
- {
- sh_set_lines_and_columns (win.ws_row, win.ws_col);
-#if defined (READLINE)
- rl_set_screen_size (win.ws_row, win.ws_col);
- if (rp)
- *rp = win.ws_row;
- if (cp)
- *cp = win.ws_col;
-#endif
- }
-#endif
-}
diff --git a/lib/termcap/termcap.c~ b/lib/termcap/termcap.c~
deleted file mode 100644
index 780b15ce..00000000
--- a/lib/termcap/termcap.c~
+++ /dev/null
@@ -1,800 +0,0 @@
-/* Work-alike for termcap, plus extra features.
- Copyright (C) 1985, 86, 93, 94, 95 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; see the file COPYING. If not, write to the
-Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
-
-/* Emacs config.h may rename various library functions such as malloc. */
-#ifdef HAVE_CONFIG_H
-
-#include <config.h>
-
-/* Get the O_* definitions for open et al. */
-#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-
-#include <fcntl.h>
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-extern char *getenv ();
-extern char *malloc ();
-extern char *realloc ();
-#endif
-
-#else /* not HAVE_CONFIG_H */
-
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#include <string.h>
-#else
-char *getenv ();
-char *malloc ();
-char *realloc ();
-#endif
-
-/* Do this after the include, in case string.h prototypes bcopy. */
-#if (defined(HAVE_STRING_H) || defined(STDC_HEADERS)) && !defined(bcopy)
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef _POSIX_VERSION
-#include <fcntl.h>
-#endif
-
-#endif /* not HAVE_CONFIG_H */
-
-#ifndef NULL
-#define NULL (char *) 0
-#endif
-
-#ifndef O_RDONLY
-#define O_RDONLY 0
-#endif
-
-/* BUFSIZE is the initial size allocated for the buffer
- for reading the termcap file.
- It is not a limit.
- Make it large normally for speed.
- Make it variable when debugging, so can exercise
- increasing the space dynamically. */
-
-#ifndef BUFSIZE
-#ifdef DEBUG
-#define BUFSIZE bufsize
-
-int bufsize = 128;
-#else
-#define BUFSIZE 2048
-#endif
-#endif
-
-#include "ltcap.h"
-
-#ifndef TERMCAP_FILE
-#define TERMCAP_FILE "/etc/termcap"
-#endif
-
-#ifndef emacs
-static void
-memory_out ()
-{
- write (2, "virtual memory exhausted\n", 25);
- exit (1);
-}
-
-static char *
-xmalloc (size)
- unsigned size;
-{
- register char *tem = malloc (size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-
-static char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
-{
- register char *tem = realloc (ptr, size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-#endif /* not emacs */
-
-/* Looking up capabilities in the entry already found. */
-
-/* The pointer to the data made by tgetent is left here
- for tgetnum, tgetflag and tgetstr to find. */
-static char *term_entry;
-
-static char *tgetst1 ();
-
-/* Search entry BP for capability CAP.
- Return a pointer to the capability (in BP) if found,
- 0 if not found. */
-
-static char *
-find_capability (bp, cap)
- register char *bp, *cap;
-{
- for (; *bp; bp++)
- if (bp[0] == ':'
- && bp[1] == cap[0]
- && bp[2] == cap[1])
- return &bp[4];
- return NULL;
-}
-
-__private_extern__
-int
-tgetnum (cap)
- char *cap;
-{
- register char *ptr = find_capability (term_entry, cap);
- if (!ptr || ptr[-1] != '#')
- return -1;
- return atoi (ptr);
-}
-
-__private_extern__
-int
-tgetflag (cap)
- char *cap;
-{
- register char *ptr = find_capability (term_entry, cap);
- return ptr && ptr[-1] == ':';
-}
-
-/* Look up a string-valued capability CAP.
- If AREA is non-null, it points to a pointer to a block in which
- to store the string. That pointer is advanced over the space used.
- If AREA is null, space is allocated with `malloc'. */
-
-__private_extern__
-char *
-tgetstr (cap, area)
- char *cap;
- char **area;
-{
- register char *ptr = find_capability (term_entry, cap);
- if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~'))
- return NULL;
- return tgetst1 (ptr, area);
-}
-
-/* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted,
- gives meaning of character following \, or a space if no special meaning.
- Eight characters per line within the string. */
-
-static char esctab[]
- = " \007\010 \033\014 \
- \012 \
- \015 \011 \013 \
- ";
-
-/* PTR points to a string value inside a termcap entry.
- Copy that value, processing \ and ^ abbreviations,
- into the block that *AREA points to,
- or to newly allocated storage if AREA is NULL.
- Return the address to which we copied the value,
- or NULL if PTR is NULL. */
-
-static char *
-tgetst1 (ptr, area)
- char *ptr;
- char **area;
-{
- register char *p, *r;
- register int c;
- register int size;
- char *ret;
- register int c1;
-
- if (!ptr)
- return NULL;
-
- /* `ret' gets address of where to store the string. */
- if (!area)
- {
- /* Compute size of block needed (may overestimate). */
- p = ptr;
- while ((c = *p++) && c != ':' && c != '\n')
- ;
- ret = (char *) xmalloc (p - ptr + 1);
- }
- else
- ret = *area;
-
- /* Copy the string value, stopping at null or colon.
- Also process ^ and \ abbreviations. */
- p = ptr;
- r = ret;
- while ((c = *p++) && c != ':' && c != '\n')
- {
- if (c == '^')
- {
- c = *p++;
- if (c == '?')
- c = 0177;
- else
- c &= 037;
- }
- else if (c == '\\')
- {
- c = *p++;
- if (c >= '0' && c <= '7')
- {
- c -= '0';
- size = 0;
-
- while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7')
- {
- c *= 8;
- c += c1 - '0';
- p++;
- }
- }
- else if (c >= 0100 && c < 0200)
- {
- c1 = esctab[(c & ~040) - 0100];
- if (c1 != ' ')
- c = c1;
- }
- }
- *r++ = c;
- }
- *r = '\0';
- /* Update *AREA. */
- if (area)
- *area = r + 1;
- return ret;
-}
-
-/* Outputting a string with padding. */
-
-short ospeed;
-/* If OSPEED is 0, we use this as the actual baud rate. */
-int tputs_baud_rate;
-__private_extern__ char PC = '\0';
-
-/* Actual baud rate if positive;
- - baud rate / 100 if negative. */
-
-static int speeds[] =
- {
-#ifdef VMS
- 0, 50, 75, 110, 134, 150, -3, -6, -12, -18,
- -20, -24, -36, -48, -72, -96, -192
-#else /* not VMS */
- 0, 50, 75, 110, 135, 150, -2, -3, -6, -12,
- -18, -24, -48, -96, -192, -288, -384, -576, -1152
-#endif /* not VMS */
- };
-
-__private_extern__
-void
-tputs (str, nlines, outfun)
- register char *str;
- int nlines;
- register int (*outfun) ();
-{
- register int padcount = 0;
- register int speed;
-
-#ifdef emacs
- extern baud_rate;
- speed = baud_rate;
- /* For quite high speeds, convert to the smaller
- units to avoid overflow. */
- if (speed > 10000)
- speed = - speed / 100;
-#else
- if (ospeed == 0)
- speed = tputs_baud_rate;
- else if (ospeed > 0 && ospeed < (sizeof speeds / sizeof speeds[0]))
- speed = speeds[ospeed];
- else
- speed = 0;
-#endif
-
- if (!str)
- return;
-
- while (*str >= '0' && *str <= '9')
- {
- padcount += *str++ - '0';
- padcount *= 10;
- }
- if (*str == '.')
- {
- str++;
- padcount += *str++ - '0';
- }
- if (*str == '*')
- {
- str++;
- padcount *= nlines;
- }
- while (*str)
- (*outfun) (*str++);
-
- /* PADCOUNT is now in units of tenths of msec.
- SPEED is measured in characters per 10 seconds
- or in characters per .1 seconds (if negative).
- We use the smaller units for larger speeds to avoid overflow. */
- padcount *= speed;
- padcount += 500;
- padcount /= 1000;
- if (speed < 0)
- padcount = -padcount;
- else
- {
- padcount += 50;
- padcount /= 100;
- }
-
- while (padcount-- > 0)
- (*outfun) (PC);
-}
-
-/* Finding the termcap entry in the termcap data base. */
-
-struct buffer
- {
- char *beg;
- int size;
- char *ptr;
- int ateof;
- int full;
- };
-
-/* Forward declarations of static functions. */
-
-static int scan_file ();
-static char *gobble_line ();
-static int compare_contin ();
-static int name_match ();
-
-#ifdef VMS
-
-#include <rmsdef.h>
-#include <fab.h>
-#include <nam.h>
-
-static int
-valid_filename_p (fn)
- char *fn;
-{
- struct FAB fab = cc$rms_fab;
- struct NAM nam = cc$rms_nam;
- char esa[NAM$C_MAXRSS];
-
- fab.fab$l_fna = fn;
- fab.fab$b_fns = strlen(fn);
- fab.fab$l_nam = &nam;
- fab.fab$l_fop = FAB$M_NAM;
-
- nam.nam$l_esa = esa;
- nam.nam$b_ess = sizeof esa;
-
- return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL;
-}
-
-#else /* !VMS */
-
-#ifdef MSDOS /* MW, May 1993 */
-static int
-valid_filename_p (fn)
- char *fn;
-{
- return *fn == '\\' || *fn == '/' ||
- (*fn >= 'A' && *fn <= 'z' && fn[1] == ':');
-}
-#else
-#define valid_filename_p(fn) (*(fn) == '/')
-#endif
-
-#endif /* !VMS */
-
-/* Find the termcap entry data for terminal type NAME
- and store it in the block that BP points to.
- Record its address for future use.
-
- If BP is null, space is dynamically allocated.
-
- Return -1 if there is some difficulty accessing the data base
- of terminal types,
- 0 if the data base is accessible but the type NAME is not defined
- in it, and some other value otherwise. */
-
-__private_extern__
-int
-tgetent (bp, name)
- char *bp, *name;
-{
- register char *termcap_name;
- register int fd;
- struct buffer buf;
- register char *bp1;
- char *bp2;
- char *term;
- int malloc_size = 0;
- register int c;
- char *tcenv; /* TERMCAP value, if it contains :tc=. */
- char *indirect = NULL; /* Terminal type in :tc= in TERMCAP value. */
- int filep;
-
-#ifdef INTERNAL_TERMINAL
- /* For the internal terminal we don't want to read any termcap file,
- so fake it. */
- if (!strcmp (name, "internal"))
- {
- term = INTERNAL_TERMINAL;
- if (!bp)
- {
- malloc_size = 1 + strlen (term);
- bp = (char *) xmalloc (malloc_size);
- }
- strcpy (bp, term);
- goto ret;
- }
-#endif /* INTERNAL_TERMINAL */
-
- /* For compatibility with programs like `less' that want to
- put data in the termcap buffer themselves as a fallback. */
- if (bp)
- term_entry = bp;
-
- termcap_name = getenv ("TERMCAP");
- if (termcap_name && *termcap_name == '\0')
- termcap_name = NULL;
-#if 0
-#if defined (MSDOS) && !defined (TEST)
- if (termcap_name && (*termcap_name == '\\'
- || *termcap_name == '/'
- || termcap_name[1] == ':'))
- dostounix_filename(termcap_name);
-#endif
-#endif
-
- filep = termcap_name && valid_filename_p (termcap_name);
-
- /* If termcap_name is non-null and starts with / (in the un*x case, that is),
- it is a file name to use instead of /etc/termcap.
- If it is non-null and does not start with /,
- it is the entry itself, but only if
- the name the caller requested matches the TERM variable. */
-
- if (termcap_name && !filep && !strcmp (name, getenv ("TERM")))
- {
- indirect = tgetst1 (find_capability (termcap_name, "tc"), (char **) 0);
- if (!indirect)
- {
- if (!bp)
- bp = termcap_name;
- else
- strcpy (bp, termcap_name);
- goto ret;
- }
- else
- { /* It has tc=. Need to read /etc/termcap. */
- tcenv = termcap_name;
- termcap_name = NULL;
- }
- }
-
- if (!termcap_name || !filep)
- termcap_name = TERMCAP_FILE;
-
- /* Here we know we must search a file and termcap_name has its name. */
-
-#ifdef MSDOS
- fd = open (termcap_name, O_RDONLY|O_TEXT, 0);
-#else
- fd = open (termcap_name, O_RDONLY, 0);
-#endif
- if (fd < 0)
- return -1;
-
- buf.size = BUFSIZE;
- /* Add 1 to size to ensure room for terminating null. */
- buf.beg = (char *) xmalloc (buf.size + 1);
- term = indirect ? indirect : name;
-
- if (!bp)
- {
- malloc_size = indirect ? strlen (tcenv) + 1 : buf.size;
- bp = (char *) xmalloc (malloc_size);
- }
- bp1 = bp;
-
- if (indirect)
- /* Copy the data from the environment variable. */
- {
- strcpy (bp, tcenv);
- bp1 += strlen (tcenv);
- }
-
- while (term)
- {
- /* Scan the file, reading it via buf, till find start of main entry. */
- if (scan_file (term, fd, &buf) == 0)
- {
- close (fd);
- free (buf.beg);
- if (malloc_size)
- free (bp);
- return 0;
- }
-
- /* Free old `term' if appropriate. */
- if (term != name)
- free (term);
-
- /* If BP is malloc'd by us, make sure it is big enough. */
- if (malloc_size)
- {
- malloc_size = bp1 - bp + buf.size;
- termcap_name = (char *) xrealloc (bp, malloc_size);
- bp1 += termcap_name - bp;
- bp = termcap_name;
- }
-
- bp2 = bp1;
-
- /* Copy the line of the entry from buf into bp. */
- termcap_name = buf.ptr;
- while ((*bp1++ = c = *termcap_name++) && c != '\n')
- /* Drop out any \ newline sequence. */
- if (c == '\\' && *termcap_name == '\n')
- {
- bp1--;
- termcap_name++;
- }
- *bp1 = '\0';
-
- /* Does this entry refer to another terminal type's entry?
- If something is found, copy it into heap and null-terminate it. */
- term = tgetst1 (find_capability (bp2, "tc"), (char **) 0);
- }
-
- close (fd);
- free (buf.beg);
-
- if (malloc_size)
- bp = (char *) xrealloc (bp, bp1 - bp + 1);
-
- ret:
- term_entry = bp;
- return 1;
-}
-
-/* Given file open on FD and buffer BUFP,
- scan the file from the beginning until a line is found
- that starts the entry for terminal type STR.
- Return 1 if successful, with that line in BUFP,
- or 0 if no entry is found in the file. */
-
-static int
-scan_file (str, fd, bufp)
- char *str;
- int fd;
- register struct buffer *bufp;
-{
- register char *end;
-
- bufp->ptr = bufp->beg;
- bufp->full = 0;
- bufp->ateof = 0;
- *bufp->ptr = '\0';
-
- lseek (fd, 0L, 0);
-
- while (!bufp->ateof)
- {
- /* Read a line into the buffer. */
- end = NULL;
- do
- {
- /* if it is continued, append another line to it,
- until a non-continued line ends. */
- end = gobble_line (fd, bufp, end);
- }
- while (!bufp->ateof && end[-2] == '\\');
-
- if (*bufp->ptr != '#'
- && name_match (bufp->ptr, str))
- return 1;
-
- /* Discard the line just processed. */
- bufp->ptr = end;
- }
- return 0;
-}
-
-/* Return nonzero if NAME is one of the names specified
- by termcap entry LINE. */
-
-static int
-name_match (line, name)
- char *line, *name;
-{
- register char *tem;
-
- if (!compare_contin (line, name))
- return 1;
- /* This line starts an entry. Is it the right one? */
- for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++)
- if (*tem == '|' && !compare_contin (tem + 1, name))
- return 1;
-
- return 0;
-}
-
-static int
-compare_contin (str1, str2)
- register char *str1, *str2;
-{
- register int c1, c2;
- while (1)
- {
- c1 = *str1++;
- c2 = *str2++;
- while (c1 == '\\' && *str1 == '\n')
- {
- str1++;
- while ((c1 = *str1++) == ' ' || c1 == '\t');
- }
- if (c2 == '\0')
- {
- /* End of type being looked up. */
- if (c1 == '|' || c1 == ':')
- /* If end of name in data base, we win. */
- return 0;
- else
- return 1;
- }
- else if (c1 != c2)
- return 1;
- }
-}
-
-/* Make sure that the buffer <- BUFP contains a full line
- of the file open on FD, starting at the place BUFP->ptr
- points to. Can read more of the file, discard stuff before
- BUFP->ptr, or make the buffer bigger.
-
- Return the pointer to after the newline ending the line,
- or to the end of the file, if there is no newline to end it.
-
- Can also merge on continuation lines. If APPEND_END is
- non-null, it points past the newline of a line that is
- continued; we add another line onto it and regard the whole
- thing as one line. The caller decides when a line is continued. */
-
-static char *
-gobble_line (fd, bufp, append_end)
- int fd;
- register struct buffer *bufp;
- char *append_end;
-{
- register char *end;
- register int nread;
- register char *buf = bufp->beg;
- register char *tem;
-
- if (!append_end)
- append_end = bufp->ptr;
-
- while (1)
- {
- end = append_end;
- while (*end && *end != '\n') end++;
- if (*end)
- break;
- if (bufp->ateof)
- return buf + bufp->full;
- if (bufp->ptr == buf)
- {
- if (bufp->full == bufp->size)
- {
- bufp->size *= 2;
- /* Add 1 to size to ensure room for terminating null. */
- tem = (char *) xrealloc (buf, bufp->size + 1);
- bufp->ptr = (bufp->ptr - buf) + tem;
- append_end = (append_end - buf) + tem;
- bufp->beg = buf = tem;
- }
- }
- else
- {
- append_end -= bufp->ptr - buf;
- bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf);
- bufp->ptr = buf;
- }
- if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full)))
- bufp->ateof = 1;
- bufp->full += nread;
- buf[bufp->full] = '\0';
- }
- return end + 1;
-}
-
-#ifdef TEST
-
-#ifdef NULL
-#undef NULL
-#endif
-
-#include <stdio.h>
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- char *term;
- char *buf;
-
- term = argv[1];
- printf ("TERM: %s\n", term);
-
- buf = (char *) tgetent (0, term);
- if ((int) buf <= 0)
- {
- printf ("No entry.\n");
- return 0;
- }
-
- printf ("Entry: %s\n", buf);
-
- tprint ("cm");
- tprint ("AL");
-
- printf ("co: %d\n", tgetnum ("co"));
- printf ("am: %d\n", tgetflag ("am"));
-}
-
-tprint (cap)
- char *cap;
-{
- char *x = tgetstr (cap, 0);
- register char *y;
-
- printf ("%s: ", cap);
- if (x)
- {
- for (y = x; *y; y++)
- if (*y <= ' ' || *y == 0177)
- printf ("\\%0o", *y);
- else
- putchar (*y);
- free (x);
- }
- else
- printf ("none");
- putchar ('\n');
-}
-
-#endif /* TEST */
diff --git a/lib/termcap/tparam.c~ b/lib/termcap/tparam.c~
deleted file mode 100644
index 1c83f045..00000000
--- a/lib/termcap/tparam.c~
+++ /dev/null
@@ -1,334 +0,0 @@
-/* Merge parameters into a termcap entry string.
- Copyright (C) 1985, 87, 93, 95 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; see the file COPYING. If not, write to the
-Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
-
-/* Emacs config.h may rename various library functions such as malloc. */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#else
-extern char *getenv ();
-extern char *malloc ();
-extern char *realloc ();
-#endif
-
-#else /* not HAVE_CONFIG_H */
-
-#if defined(HAVE_STRING_H) || defined(STDC_HEADERS)
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#endif
-
-#ifdef STDC_HEADERS
-#include <stdlib.h>
-#include <string.h>
-#else
-char *malloc ();
-char *realloc ();
-#endif
-
-#endif /* not HAVE_CONFIG_H */
-
-#include "ltcap.h"
-
-#ifndef NULL
-#define NULL (char *) 0
-#endif
-
-#ifndef emacs
-static void
-memory_out ()
-{
- write (2, "virtual memory exhausted\n", 25);
- exit (1);
-}
-
-static char *
-xmalloc (size)
- unsigned size;
-{
- register char *tem = malloc (size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-
-static char *
-xrealloc (ptr, size)
- char *ptr;
- unsigned size;
-{
- register char *tem = realloc (ptr, size);
-
- if (!tem)
- memory_out ();
- return tem;
-}
-#endif /* not emacs */
-
-/* Assuming STRING is the value of a termcap string entry
- containing `%' constructs to expand parameters,
- merge in parameter values and store result in block OUTSTRING points to.
- LEN is the length of OUTSTRING. If more space is needed,
- a block is allocated with `malloc'.
-
- The value returned is the address of the resulting string.
- This may be OUTSTRING or may be the address of a block got with `malloc'.
- In the latter case, the caller must free the block.
-
- The fourth and following args to tparam serve as the parameter values. */
-
-static char *tparam1 ();
-
-/* VARARGS 2 */
-char *
-tparam (string, outstring, len, arg0, arg1, arg2, arg3)
- char *string;
- char *outstring;
- int len;
- int arg0, arg1, arg2, arg3;
-{
- int arg[4];
-
- arg[0] = arg0;
- arg[1] = arg1;
- arg[2] = arg2;
- arg[3] = arg3;
- return tparam1 (string, outstring, len, NULL, NULL, arg);
-}
-
-__private_extern__ char *BC;
-__private_extern__ char *UP;
-
-static char tgoto_buf[50];
-
-__private_extern__
-char *
-tgoto (cm, hpos, vpos)
- char *cm;
- int hpos, vpos;
-{
- int args[2];
- if (!cm)
- return NULL;
- args[0] = vpos;
- args[1] = hpos;
- return tparam1 (cm, tgoto_buf, 50, UP, BC, args);
-}
-
-static char *
-tparam1 (string, outstring, len, up, left, argp)
- char *string;
- char *outstring;
- int len;
- char *up, *left;
- register int *argp;
-{
- register int c;
- register char *p = string;
- register char *op = outstring;
- char *outend;
- int outlen = 0;
-
- register int tem;
- int *old_argp = argp;
- int doleft = 0;
- int doup = 0;
-
- outend = outstring + len;
-
- while (1)
- {
- /* If the buffer might be too short, make it bigger. */
- if (op + 5 >= outend)
- {
- register char *new;
- if (outlen == 0)
- {
- outlen = len + 40;
- new = (char *) xmalloc (outlen);
- outend += 40;
- bcopy (outstring, new, op - outstring);
- }
- else
- {
- outend += outlen;
- outlen *= 2;
- new = (char *) xrealloc (outstring, outlen);
- }
- op += new - outstring;
- outend += new - outstring;
- outstring = new;
- }
- c = *p++;
- if (!c)
- break;
- if (c == '%')
- {
- c = *p++;
- tem = *argp;
- switch (c)
- {
- case 'd': /* %d means output in decimal. */
- if (tem < 10)
- goto onedigit;
- if (tem < 100)
- goto twodigit;
- case '3': /* %3 means output in decimal, 3 digits. */
- if (tem > 999)
- {
- *op++ = tem / 1000 + '0';
- tem %= 1000;
- }
- *op++ = tem / 100 + '0';
- case '2': /* %2 means output in decimal, 2 digits. */
- twodigit:
- tem %= 100;
- *op++ = tem / 10 + '0';
- onedigit:
- *op++ = tem % 10 + '0';
- argp++;
- break;
-
- case 'C':
- /* For c-100: print quotient of value by 96, if nonzero,
- then do like %+. */
- if (tem >= 96)
- {
- *op++ = tem / 96;
- tem %= 96;
- }
- case '+': /* %+x means add character code of char x. */
- tem += *p++;
- case '.': /* %. means output as character. */
- if (left)
- {
- /* If want to forbid output of 0 and \n and \t,
- and this is one of them, increment it. */
- while (tem == 0 || tem == '\n' || tem == '\t')
- {
- tem++;
- if (argp == old_argp)
- doup++, outend -= strlen (up);
- else
- doleft++, outend -= strlen (left);
- }
- }
- *op++ = tem ? tem : 0200;
- case 'f': /* %f means discard next arg. */
- argp++;
- break;
-
- case 'b': /* %b means back up one arg (and re-use it). */
- argp--;
- break;
-
- case 'r': /* %r means interchange following two args. */
- argp[0] = argp[1];
- argp[1] = tem;
- old_argp++;
- break;
-
- case '>': /* %>xy means if arg is > char code of x, */
- if (argp[0] > *p++) /* then add char code of y to the arg, */
- argp[0] += *p; /* and in any case don't output. */
- p++; /* Leave the arg to be output later. */
- break;
-
- case 'a': /* %a means arithmetic. */
- /* Next character says what operation.
- Add or subtract either a constant or some other arg. */
- /* First following character is + to add or - to subtract
- or = to assign. */
- /* Next following char is 'p' and an arg spec
- (0100 plus position of that arg relative to this one)
- or 'c' and a constant stored in a character. */
- tem = p[2] & 0177;
- if (p[1] == 'p')
- tem = argp[tem - 0100];
- if (p[0] == '-')
- argp[0] -= tem;
- else if (p[0] == '+')
- argp[0] += tem;
- else if (p[0] == '*')
- argp[0] *= tem;
- else if (p[0] == '/')
- argp[0] /= tem;
- else
- argp[0] = tem;
-
- p += 3;
- break;
-
- case 'i': /* %i means add one to arg, */
- argp[0] ++; /* and leave it to be output later. */
- argp[1] ++; /* Increment the following arg, too! */
- break;
-
- case '%': /* %% means output %; no arg. */
- goto ordinary;
-
- case 'n': /* %n means xor each of next two args with 140. */
- argp[0] ^= 0140;
- argp[1] ^= 0140;
- break;
-
- case 'm': /* %m means xor each of next two args with 177. */
- argp[0] ^= 0177;
- argp[1] ^= 0177;
- break;
-
- case 'B': /* %B means express arg as BCD char code. */
- argp[0] += 6 * (tem / 10);
- break;
-
- case 'D': /* %D means weird Delta Data transformation. */
- argp[0] -= 2 * (tem % 16);
- break;
- }
- }
- else
- /* Ordinary character in the argument string. */
- ordinary:
- *op++ = c;
- }
- *op = 0;
- while (doup-- > 0)
- strcat (op, up);
- while (doleft-- > 0)
- strcat (op, left);
- return outstring;
-}
-
-#ifdef DEBUG
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- char buf[50];
- int args[3];
- args[0] = atoi (argv[2]);
- args[1] = atoi (argv[3]);
- args[2] = atoi (argv[4]);
- tparam1 (argv[1], buf, "LEFT", "UP", args);
- printf ("%s\n", buf);
- return 0;
-}
-
-#endif /* DEBUG */
diff --git a/locale.c~ b/locale.c~
deleted file mode 100644
index a3870ed2..00000000
--- a/locale.c~
+++ /dev/null
@@ -1,507 +0,0 @@
-/* locale.c - Miscellaneous internationalization functions. */
-
-/* Copyright (C) 1996-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"
-
-#include "bashtypes.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "bashintl.h"
-#include "bashansi.h"
-#include <stdio.h>
-#include "chartypes.h"
-
-#include "shell.h"
-#include "input.h" /* For bash_input */
-
-extern int dump_translatable_strings, dump_po_strings;
-
-/* The current locale when the program begins */
-static char *default_locale;
-
-/* The current domain for textdomain(3). */
-static char *default_domain;
-static char *default_dir;
-
-/* tracks the value of LC_ALL; used to override values for other locale
- categories */
-static char *lc_all;
-
-/* tracks the value of LC_ALL; used to provide defaults for locale
- categories */
-static char *lang;
-
-/* Called to reset all of the locale variables to their appropriate values
- if (and only if) LC_ALL has not been assigned a value. */
-static int reset_locale_vars __P((void));
-
-static void locale_setblanks __P((void));
-
-/* Set the value of default_locale and make the current locale the
- system default locale. This should be called very early in main(). */
-void
-set_default_locale ()
-{
-#if defined (HAVE_SETLOCALE)
- default_locale = setlocale (LC_ALL, "");
- if (default_locale)
- default_locale = savestring (default_locale);
-#endif /* HAVE_SETLOCALE */
- bindtextdomain (PACKAGE, LOCALEDIR);
- textdomain (PACKAGE);
-}
-
-/* Set default values for LC_CTYPE, LC_COLLATE, LC_MESSAGES, LC_NUMERIC and
- LC_TIME if they are not specified in the environment, but LC_ALL is. This
- should be called from main() after parsing the environment. */
-void
-set_default_locale_vars ()
-{
- char *val;
- int r;
-
-#if defined (HAVE_SETLOCALE)
-
-# if defined (LC_CTYPE)
- val = get_string_value ("LC_CTYPE");
- if (val == 0 && lc_all && *lc_all)
- {
- setlocale (LC_CTYPE, lc_all);
- locale_setblanks ();
- }
-# endif
-
-# if defined (LC_COLLATE)
- val = get_string_value ("LC_COLLATE");
- if (val == 0 && lc_all && *lc_all)
- setlocale (LC_COLLATE, lc_all);
-# endif /* LC_COLLATE */
-
-# if defined (LC_MESSAGES)
- val = get_string_value ("LC_MESSAGES");
- if (val == 0 && lc_all && *lc_all)
- setlocale (LC_MESSAGES, lc_all);
-# endif /* LC_MESSAGES */
-
-# if defined (LC_NUMERIC)
- val = get_string_value ("LC_NUMERIC");
- if (val == 0 && lc_all && *lc_all)
- setlocale (LC_NUMERIC, lc_all);
-# endif /* LC_NUMERIC */
-
-# if defined (LC_TIME)
- val = get_string_value ("LC_TIME");
- if (val == 0 && lc_all && *lc_all)
- setlocale (LC_TIME, lc_all);
-# endif /* LC_TIME */
-
-#endif /* HAVE_SETLOCALE */
-
- val = get_string_value ("TEXTDOMAIN");
- if (val && *val)
- {
- FREE (default_domain);
- default_domain = savestring (val);
-#if 0
- /* Don't want to override the shell's textdomain as the default */
- textdomain (default_domain);
-#endif
- }
-
- val = get_string_value ("TEXTDOMAINDIR");
- if (val && *val)
- {
- FREE (default_dir);
- default_dir = savestring (val);
- if (default_domain && *default_domain)
- bindtextdomain (default_domain, default_dir);
- }
-}
-
-/* Set one of the locale categories (specified by VAR) to VALUE. Returns 1
- if successful, 0 otherwise. */
-int
-set_locale_var (var, value)
- char *var, *value;
-{
- int r;
-
- if (var[0] == 'T' && var[10] == 0) /* TEXTDOMAIN */
- {
- FREE (default_domain);
- default_domain = value ? savestring (value) : (char *)NULL;
-#if 0
- /* Don't want to override the shell's textdomain as the default */
- textdomain (default_domain);
-#endif
- return (1);
- }
- else if (var[0] == 'T') /* TEXTDOMAINDIR */
- {
- FREE (default_dir);
- default_dir = value ? savestring (value) : (char *)NULL;
- if (default_domain && *default_domain)
- bindtextdomain (default_domain, default_dir);
- return (1);
- }
-
- /* var[0] == 'L' && var[1] == 'C' && var[2] == '_' */
-
- else if (var[3] == 'A') /* LC_ALL */
- {
- FREE (lc_all);
- if (value)
- lc_all = savestring (value);
- else
- {
- lc_all = (char *)xmalloc (1);
- lc_all[0] = '\0';
- }
-#if defined (HAVE_SETLOCALE)
- r = *lc_all ? (setlocale (LC_ALL, lc_all) != 0) : reset_locale_vars ();
- locale_setblanks ();
- return r;
-#else
- return (1);
-#endif
- }
-
-#if defined (HAVE_SETLOCALE)
- else if (var[3] == 'C' && var[4] == 'T') /* LC_CTYPE */
- {
-# if defined (LC_CTYPE)
- if (lc_all == 0 || *lc_all == '\0')
- {
- r = (setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE")) != 0);
- locale_setblanks ();
- return r;
- }
-# endif
- }
- else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
- {
-# if defined (LC_COLLATE)
- if (lc_all == 0 || *lc_all == '\0')
- return (setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE")) != 0);
-# endif /* LC_COLLATE */
- }
- else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
- {
-# if defined (LC_MESSAGES)
- if (lc_all == 0 || *lc_all == '\0')
- return (setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES")) != 0);
-# endif /* LC_MESSAGES */
- }
- else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
- {
-# if defined (LC_NUMERIC)
- if (lc_all == 0 || *lc_all == '\0')
- return (setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC")) != 0);
-# endif /* LC_NUMERIC */
- }
- else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
- {
-# if defined (LC_TIME)
- if (lc_all == 0 || *lc_all == '\0')
- return (setlocale (LC_TIME, get_locale_var ("LC_TIME")) != 0);
-# endif /* LC_TIME */
- }
-#endif /* HAVE_SETLOCALE */
-
-
- return (0);
-}
-
-/* Called when LANG is assigned a value. Tracks value in `lang'. Calls
- reset_locale_vars() to reset any default values if LC_ALL is unset or
- null. */
-int
-set_lang (var, value)
- char *var, *value;
-{
- FREE (lang);
- if (value)
- lang = savestring (value);
- else
- {
- lang = (char *)xmalloc (1);
- lang[0] = '\0';
- }
-
- return ((lc_all == 0 || *lc_all == 0) ? reset_locale_vars () : 0);
-}
-
-/* Set default values for LANG and LC_ALL. Default values for all other
- locale-related variables depend on these. */
-void
-set_default_lang ()
-{
- char *v;
-
- v = get_string_value ("LC_ALL");
- set_locale_var ("LC_ALL", v);
-
- v = get_string_value ("LANG");
- set_lang ("LANG", v);
-}
-
-/* Get the value of one of the locale variables (LC_MESSAGES, LC_CTYPE).
- The precedence is as POSIX.2 specifies: LC_ALL has precedence over
- the specific locale variables, and LANG, if set, is used as the default. */
-char *
-get_locale_var (var)
- char *var;
-{
- char *locale;
-
- locale = lc_all;
-
- if (locale == 0 || *locale == 0)
- locale = get_string_value (var);
- if (locale == 0 || *locale == 0)
- locale = lang;
- if (locale == 0 || *locale == 0)
- locale = default_locale; /* system-dependent; not really portable. should it be "C"? */
-
- return (locale);
-}
-
-/* Called to reset all of the locale variables to their appropriate values
- if (and only if) LC_ALL has not been assigned a value. DO NOT CALL THIS
- IF LC_ALL HAS BEEN ASSIGNED A VALUE. */
-static int
-reset_locale_vars ()
-{
-#if defined (HAVE_SETLOCALE)
- if (lang == 0 || *lang == '\0')
- maybe_make_export_env (); /* trust that this will change environment for setlocale */
- if (setlocale (LC_ALL, lang ? lang : "") == 0)
- return 0;
-
-# if defined (LC_CTYPE)
- setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
-# endif
-# if defined (LC_COLLATE)
- setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
-# endif
-# if defined (LC_MESSAGES)
- setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
-# endif
-# if defined (LC_NUMERIC)
- setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
-# endif
-# if defined (LC_TIME)
- setlocale (LC_TIME, get_locale_var ("LC_TIME"));
-# endif
-
- locale_setblanks ();
-
-#endif
- return 1;
-}
-
-/* Translate the contents of STRING, a $"..." quoted string, according
- to the current locale. In the `C' or `POSIX' locale, or if gettext()
- is not available, the passed string is returned unchanged. The
- length of the translated string is returned in LENP, if non-null. */
-char *
-localetrans (string, len, lenp)
- char *string;
- int len, *lenp;
-{
- char *locale, *t;
- char *translated;
- int tlen;
-
- /* Don't try to translate null strings. */
- if (string == 0 || *string == 0)
- {
- if (lenp)
- *lenp = 0;
- return ((char *)NULL);
- }
-
- locale = get_locale_var ("LC_MESSAGES");
-
- /* If we don't have setlocale() or the current locale is `C' or `POSIX',
- just return the string. If we don't have gettext(), there's no use
- doing anything else. */
- if (locale == 0 || locale[0] == '\0' ||
- (locale[0] == 'C' && locale[1] == '\0') || STREQ (locale, "POSIX"))
- {
- t = (char *)xmalloc (len + 1);
- strcpy (t, string);
- if (lenp)
- *lenp = len;
- return (t);
- }
-
- /* Now try to translate it. */
- if (default_domain && *default_domain)
- translated = dgettext (default_domain, string);
- else
- translated = string;
-
- if (translated == string) /* gettext returns its argument if untranslatable */
- {
- t = (char *)xmalloc (len + 1);
- strcpy (t, string);
- if (lenp)
- *lenp = len;
- }
- else
- {
- tlen = strlen (translated);
- t = (char *)xmalloc (tlen + 1);
- strcpy (t, translated);
- if (lenp)
- *lenp = tlen;
- }
- return (t);
-}
-
-/* Change a bash string into a string suitable for inclusion in a `po' file.
- This backslash-escapes `"' and `\' and changes newlines into \\\n"\n". */
-char *
-mk_msgstr (string, foundnlp)
- char *string;
- int *foundnlp;
-{
- register int c, len;
- char *result, *r, *s;
-
- for (len = 0, s = string; s && *s; s++)
- {
- len++;
- if (*s == '"' || *s == '\\')
- len++;
- else if (*s == '\n')
- len += 5;
- }
-
- r = result = (char *)xmalloc (len + 3);
- *r++ = '"';
-
- for (s = string; s && (c = *s); s++)
- {
- if (c == '\n') /* <NL> -> \n"<NL>" */
- {
- *r++ = '\\';
- *r++ = 'n';
- *r++ = '"';
- *r++ = '\n';
- *r++ = '"';
- if (foundnlp)
- *foundnlp = 1;
- continue;
- }
- if (c == '"' || c == '\\')
- *r++ = '\\';
- *r++ = c;
- }
-
- *r++ = '"';
- *r++ = '\0';
-
- return result;
-}
-
-/* $"..." -- Translate the portion of STRING between START and END
- according to current locale using gettext (if available) and return
- the result. The caller will take care of leaving the quotes intact.
- The string will be left without the leading `$' by the caller.
- If translation is performed, the translated string will be double-quoted
- by the caller. The length of the translated string is returned in LENP,
- if non-null. */
-char *
-localeexpand (string, start, end, lineno, lenp)
- char *string;
- int start, end, lineno, *lenp;
-{
- int len, tlen, foundnl;
- char *temp, *t, *t2;
-
- temp = (char *)xmalloc (end - start + 1);
- for (tlen = 0, len = start; len < end; )
- temp[tlen++] = string[len++];
- temp[tlen] = '\0';
-
- /* If we're just dumping translatable strings, don't do anything with the
- string itself, but if we're dumping in `po' file format, convert it into
- a form more palatable to gettext(3) and friends by quoting `"' and `\'
- with backslashes and converting <NL> into `\n"<NL>"'. If we find a
- newline in TEMP, we first output a `msgid ""' line and then the
- translated string; otherwise we output the `msgid' and translated
- string all on one line. */
- if (dump_translatable_strings)
- {
- if (dump_po_strings)
- {
- foundnl = 0;
- t = mk_msgstr (temp, &foundnl);
- t2 = foundnl ? "\"\"\n" : "";
-
- printf ("#: %s:%d\nmsgid %s%s\nmsgstr \"\"\n",
- yy_input_name (), lineno, t2, t);
- free (t);
- }
- else
- printf ("\"%s\"\n", temp);
-
- if (lenp)
- *lenp = tlen;
- return (temp);
- }
- else if (*temp)
- {
- t = localetrans (temp, tlen, &len);
- free (temp);
- if (lenp)
- *lenp = len;
- return (t);
- }
- else
- {
- if (lenp)
- *lenp = 0;
- return (temp);
- }
-}
-
-/* Set every character in the <blank> character class to be a shell break
- character for the lexical analyzer when the locale changes. */
-static void
-locale_setblanks ()
-{
- int x;
-
- for (x = 0; x < sh_syntabsiz; x++)
- {
- if (isblank (x))
- sh_syntaxtab[x] |= CSHBRK|CBLANK;
- else if (member (x, shell_break_chars))
- sh_syntaxtab[x] |= CSHBRK;
- else
- sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
- }
-}
diff --git a/make_cmd.c~ b/make_cmd.c~
deleted file mode 100644
index 824df288..00000000
--- a/make_cmd.c~
+++ /dev/null
@@ -1,853 +0,0 @@
-/* make_cmd.c -- Functions for making instances of the various
- parser constructs. */
-
-/* Copyright (C) 1989-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 <stdio.h>
-#include "bashtypes.h"
-#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-#include "filecntl.h"
-#include "bashansi.h"
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include "bashintl.h"
-
-#include "syntax.h"
-#include "command.h"
-#include "general.h"
-#include "error.h"
-#include "flags.h"
-#include "make_cmd.h"
-#include "dispose_cmd.h"
-#include "variables.h"
-#include "subst.h"
-#include "input.h"
-#include "ocache.h"
-#include "externs.h"
-
-#if defined (JOB_CONTROL)
-#include "jobs.h"
-#endif
-
-#include "shmbutil.h"
-
-extern int line_number, current_command_line_count;
-extern int last_command_exit_value;
-
-/* Object caching */
-sh_obj_cache_t wdcache = {0, 0, 0};
-sh_obj_cache_t wlcache = {0, 0, 0};
-
-#define WDCACHESIZE 60
-#define WLCACHESIZE 60
-
-static COMMAND *make_for_or_select __P((enum command_type, WORD_DESC *, WORD_LIST *, COMMAND *, int));
-#if defined (ARITH_FOR_COMMAND)
-static WORD_LIST *make_arith_for_expr __P((char *));
-#endif
-static COMMAND *make_until_or_while __P((enum command_type, COMMAND *, COMMAND *));
-
-void
-cmd_init ()
-{
- ocache_create (wdcache, WORD_DESC, WDCACHESIZE);
- ocache_create (wlcache, WORD_LIST, WLCACHESIZE);
-}
-
-WORD_DESC *
-alloc_word_desc ()
-{
- WORD_DESC *temp;
-
- ocache_alloc (wdcache, WORD_DESC, temp);
- temp->flags = 0;
- temp->word = 0;
- return temp;
-}
-
-WORD_DESC *
-make_bare_word (string)
- const char *string;
-{
- WORD_DESC *temp;
-
- temp = alloc_word_desc ();
-
- if (*string)
- temp->word = savestring (string);
- else
- {
- temp->word = (char *)xmalloc (1);
- temp->word[0] = '\0';
- }
-
- return (temp);
-}
-
-WORD_DESC *
-make_word_flags (w, string)
- WORD_DESC *w;
- const char *string;
-{
- register int i;
- size_t slen;
- DECLARE_MBSTATE;
-
- i = 0;
- slen = strlen (string);
- while (i < slen)
- {
- switch (string[i])
- {
- case '$':
- w->flags |= W_HASDOLLAR;
- break;
- case '\\':
- break; /* continue the loop */
- case '\'':
- case '`':
- case '"':
- w->flags |= W_QUOTED;
- break;
- }
-
- ADVANCE_CHAR (string, slen, i);
- }
-
- return (w);
-}
-
-WORD_DESC *
-make_word (string)
- const char *string;
-{
- WORD_DESC *temp;
-
- temp = make_bare_word (string);
- return (make_word_flags (temp, string));
-}
-
-WORD_DESC *
-make_word_from_token (token)
- int token;
-{
- char tokenizer[2];
-
- tokenizer[0] = token;
- tokenizer[1] = '\0';
-
- return (make_word (tokenizer));
-}
-
-WORD_LIST *
-make_word_list (word, wlink)
- WORD_DESC *word;
- WORD_LIST *wlink;
-{
- WORD_LIST *temp;
-
- ocache_alloc (wlcache, WORD_LIST, temp);
-
- temp->word = word;
- temp->next = wlink;
- return (temp);
-}
-
-COMMAND *
-make_command (type, pointer)
- enum command_type type;
- SIMPLE_COM *pointer;
-{
- COMMAND *temp;
-
- temp = (COMMAND *)xmalloc (sizeof (COMMAND));
- temp->type = type;
- temp->value.Simple = pointer;
- temp->value.Simple->flags = temp->flags = 0;
- temp->redirects = (REDIRECT *)NULL;
- return (temp);
-}
-
-COMMAND *
-command_connect (com1, com2, connector)
- COMMAND *com1, *com2;
- int connector;
-{
- CONNECTION *temp;
-
- temp = (CONNECTION *)xmalloc (sizeof (CONNECTION));
- temp->connector = connector;
- temp->first = com1;
- temp->second = com2;
- return (make_command (cm_connection, (SIMPLE_COM *)temp));
-}
-
-static COMMAND *
-make_for_or_select (type, name, map_list, action, lineno)
- enum command_type type;
- WORD_DESC *name;
- WORD_LIST *map_list;
- COMMAND *action;
- int lineno;
-{
- FOR_COM *temp;
-
- temp = (FOR_COM *)xmalloc (sizeof (FOR_COM));
- temp->flags = 0;
- temp->name = name;
- temp->line = lineno;
- temp->map_list = map_list;
- temp->action = action;
- return (make_command (type, (SIMPLE_COM *)temp));
-}
-
-COMMAND *
-make_for_command (name, map_list, action, lineno)
- WORD_DESC *name;
- WORD_LIST *map_list;
- COMMAND *action;
- int lineno;
-{
- return (make_for_or_select (cm_for, name, map_list, action, lineno));
-}
-
-COMMAND *
-make_select_command (name, map_list, action, lineno)
- WORD_DESC *name;
- WORD_LIST *map_list;
- COMMAND *action;
- int lineno;
-{
-#if defined (SELECT_COMMAND)
- return (make_for_or_select (cm_select, name, map_list, action, lineno));
-#else
- last_command_exit_value = 2;
- return ((COMMAND *)NULL);
-#endif
-}
-
-#if defined (ARITH_FOR_COMMAND)
-static WORD_LIST *
-make_arith_for_expr (s)
- char *s;
-{
- WORD_LIST *result;
- WORD_DESC *wd;
-
- if (s == 0 || *s == '\0')
- return ((WORD_LIST *)NULL);
- wd = make_word (s);
- wd->flags |= W_NOGLOB|W_NOSPLIT|W_QUOTED|W_DQUOTE; /* no word splitting or globbing */
- result = make_word_list (wd, (WORD_LIST *)NULL);
- return result;
-}
-#endif
-
-/* Note that this function calls dispose_words on EXPRS, since it doesn't
- use the word list directly. We free it here rather than at the caller
- because no other function in this file requires that the caller free
- any arguments. */
-COMMAND *
-make_arith_for_command (exprs, action, lineno)
- WORD_LIST *exprs;
- COMMAND *action;
- int lineno;
-{
-#if defined (ARITH_FOR_COMMAND)
- ARITH_FOR_COM *temp;
- WORD_LIST *init, *test, *step;
- char *s, *t, *start;
- int nsemi;
-
- init = test = step = (WORD_LIST *)NULL;
- /* Parse the string into the three component sub-expressions. */
- start = t = s = exprs->word->word;
- for (nsemi = 0; ;)
- {
- /* skip whitespace at the start of each sub-expression. */
- while (whitespace (*s))
- s++;
- start = s;
- /* skip to the semicolon or EOS */
- while (*s && *s != ';')
- s++;
-
- t = (s > start) ? substring (start, 0, s - start) : (char *)NULL;
-
- nsemi++;
- switch (nsemi)
- {
- case 1:
- init = make_arith_for_expr (t);
- break;
- case 2:
- test = make_arith_for_expr (t);
- break;
- case 3:
- step = make_arith_for_expr (t);
- break;
- }
-
- FREE (t);
- if (*s == '\0')
- break;
- s++; /* skip over semicolon */
- }
-
- if (nsemi != 3)
- {
- if (nsemi < 3)
- parser_error (lineno, _("syntax error: arithmetic expression required"));
- else
- parser_error (lineno, _("syntax error: `;' unexpected"));
- parser_error (lineno, _("syntax error: `((%s))'"), exprs->word->word);
- last_command_exit_value = 2;
- return ((COMMAND *)NULL);
- }
-
- temp = (ARITH_FOR_COM *)xmalloc (sizeof (ARITH_FOR_COM));
- temp->flags = 0;
- temp->line = lineno;
- temp->init = init ? init : make_arith_for_expr ("1");
- temp->test = test ? test : make_arith_for_expr ("1");
- temp->step = step ? step : make_arith_for_expr ("1");
- temp->action = action;
-
- dispose_words (exprs);
- return (make_command (cm_arith_for, (SIMPLE_COM *)temp));
-#else
- dispose_words (exprs);
- last_command_exit_value = 2;
- return ((COMMAND *)NULL);
-#endif /* ARITH_FOR_COMMAND */
-}
-
-COMMAND *
-make_group_command (command)
- COMMAND *command;
-{
- GROUP_COM *temp;
-
- temp = (GROUP_COM *)xmalloc (sizeof (GROUP_COM));
- temp->command = command;
- return (make_command (cm_group, (SIMPLE_COM *)temp));
-}
-
-COMMAND *
-make_case_command (word, clauses, lineno)
- WORD_DESC *word;
- PATTERN_LIST *clauses;
- int lineno;
-{
- CASE_COM *temp;
-
- temp = (CASE_COM *)xmalloc (sizeof (CASE_COM));
- temp->flags = 0;
- temp->line = lineno;
- temp->word = word;
- temp->clauses = REVERSE_LIST (clauses, PATTERN_LIST *);
- return (make_command (cm_case, (SIMPLE_COM *)temp));
-}
-
-PATTERN_LIST *
-make_pattern_list (patterns, action)
- WORD_LIST *patterns;
- COMMAND *action;
-{
- PATTERN_LIST *temp;
-
- temp = (PATTERN_LIST *)xmalloc (sizeof (PATTERN_LIST));
- temp->patterns = REVERSE_LIST (patterns, WORD_LIST *);
- temp->action = action;
- temp->next = NULL;
- temp->flags = 0;
- return (temp);
-}
-
-COMMAND *
-make_if_command (test, true_case, false_case)
- COMMAND *test, *true_case, *false_case;
-{
- IF_COM *temp;
-
- temp = (IF_COM *)xmalloc (sizeof (IF_COM));
- temp->flags = 0;
- temp->test = test;
- temp->true_case = true_case;
- temp->false_case = false_case;
- return (make_command (cm_if, (SIMPLE_COM *)temp));
-}
-
-static COMMAND *
-make_until_or_while (which, test, action)
- enum command_type which;
- COMMAND *test, *action;
-{
- WHILE_COM *temp;
-
- temp = (WHILE_COM *)xmalloc (sizeof (WHILE_COM));
- temp->flags = 0;
- temp->test = test;
- temp->action = action;
- return (make_command (which, (SIMPLE_COM *)temp));
-}
-
-COMMAND *
-make_while_command (test, action)
- COMMAND *test, *action;
-{
- return (make_until_or_while (cm_while, test, action));
-}
-
-COMMAND *
-make_until_command (test, action)
- COMMAND *test, *action;
-{
- return (make_until_or_while (cm_until, test, action));
-}
-
-COMMAND *
-make_arith_command (exp)
- WORD_LIST *exp;
-{
-#if defined (DPAREN_ARITHMETIC)
- COMMAND *command;
- ARITH_COM *temp;
-
- command = (COMMAND *)xmalloc (sizeof (COMMAND));
- command->value.Arith = temp = (ARITH_COM *)xmalloc (sizeof (ARITH_COM));
-
- temp->flags = 0;
- temp->line = line_number;
- temp->exp = exp;
-
- command->type = cm_arith;
- command->redirects = (REDIRECT *)NULL;
- command->flags = 0;
-
- return (command);
-#else
- last_command_exit_value = 2;
- return ((COMMAND *)NULL);
-#endif
-}
-
-#if defined (COND_COMMAND)
-struct cond_com *
-make_cond_node (type, op, left, right)
- int type;
- WORD_DESC *op;
- struct cond_com *left, *right;
-{
- COND_COM *temp;
-
- temp = (COND_COM *)xmalloc (sizeof (COND_COM));
- temp->flags = 0;
- temp->line = line_number;
- temp->type = type;
- temp->op = op;
- temp->left = left;
- temp->right = right;
-
- return (temp);
-}
-#endif
-
-COMMAND *
-make_cond_command (cond_node)
- COND_COM *cond_node;
-{
-#if defined (COND_COMMAND)
- COMMAND *command;
-
- command = (COMMAND *)xmalloc (sizeof (COMMAND));
- command->value.Cond = cond_node;
-
- command->type = cm_cond;
- command->redirects = (REDIRECT *)NULL;
- command->flags = 0;
- command->line = cond_node ? cond_node->line : 0;
-
- return (command);
-#else
- last_command_exit_value = 2;
- return ((COMMAND *)NULL);
-#endif
-}
-
-COMMAND *
-make_bare_simple_command ()
-{
- COMMAND *command;
- SIMPLE_COM *temp;
-
- command = (COMMAND *)xmalloc (sizeof (COMMAND));
- command->value.Simple = temp = (SIMPLE_COM *)xmalloc (sizeof (SIMPLE_COM));
-
- temp->flags = 0;
-itrace("make_bare_simple_command: line_number = %d", line_number);
- temp->line = line_number;
- temp->words = (WORD_LIST *)NULL;
- temp->redirects = (REDIRECT *)NULL;
-
- command->type = cm_simple;
- command->redirects = (REDIRECT *)NULL;
- command->flags = 0;
-
- return (command);
-}
-
-/* Return a command which is the connection of the word or redirection
- in ELEMENT, and the command * or NULL in COMMAND. */
-COMMAND *
-make_simple_command (element, command)
- ELEMENT element;
- COMMAND *command;
-{
- /* If we are starting from scratch, then make the initial command
- structure. Also note that we have to fill in all the slots, since
- malloc doesn't return zeroed space. */
- if (!command)
- command = make_bare_simple_command ();
-
- if (element.word)
- command->value.Simple->words = make_word_list (element.word, command->value.Simple->words);
- else if (element.redirect)
- {
- REDIRECT *r = element.redirect;
- /* Due to the way <> is implemented, there may be more than a single
- redirection in element.redirect. We just follow the chain as far
- as it goes, and hook onto the end. */
- while (r->next)
- r = r->next;
- r->next = command->value.Simple->redirects;
- command->value.Simple->redirects = element.redirect;
- }
- return (command);
-}
-
-/* Because we are Bourne compatible, we read the input for this
- << or <<- redirection now, from wherever input is coming from.
- We store the input read into a WORD_DESC. Replace the text of
- the redirectee.word with the new input text. If <<- is on,
- then remove leading TABS from each line. */
-void
-make_here_document (temp)
- REDIRECT *temp;
-{
- int kill_leading, redir_len;
- char *redir_word, *document, *full_line;
- int document_index, document_size, delim_unquoted;
-
- if (temp->instruction != r_deblank_reading_until &&
- temp->instruction != r_reading_until)
- {
- internal_error (_("make_here_document: bad instruction type %d"), temp->instruction);
- return;
- }
-
- kill_leading = temp->instruction == r_deblank_reading_until;
-
- document = (char *)NULL;
- document_index = document_size = 0;
-
- /* Quote removal is the only expansion performed on the delimiter
- for here documents, making it an extremely special case. */
- redir_word = string_quote_removal (temp->redirectee.filename->word, 0);
-
- /* redirection_expand will return NULL if the expansion results in
- multiple words or no words. Check for that here, and just abort
- this here document if it does. */
- if (redir_word)
- redir_len = strlen (redir_word);
- else
- {
- temp->here_doc_eof = (char *)xmalloc (1);
- temp->here_doc_eof[0] = '\0';
- goto document_done;
- }
-
- free (temp->redirectee.filename->word);
- temp->here_doc_eof = redir_word;
-
- /* Read lines from wherever lines are coming from.
- For each line read, if kill_leading, then kill the
- leading tab characters.
- If the line matches redir_word exactly, then we have
- manufactured the document. Otherwise, add the line to the
- list of lines in the document. */
-
- /* If the here-document delimiter was quoted, the lines should
- be read verbatim from the input. If it was not quoted, we
- need to perform backslash-quoted newline removal. */
- delim_unquoted = (temp->redirectee.filename->flags & W_QUOTED) == 0;
- while (full_line = read_secondary_line (delim_unquoted))
- {
- register char *line;
- int len;
-
- line = full_line;
- line_number++;
-
- if (kill_leading && *line)
- {
- /* Hack: To be compatible with some Bourne shells, we
- check the word before stripping the whitespace. This
- is a hack, though. */
- if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n')
- goto document_done;
-
- while (*line == '\t')
- line++;
- }
-
- if (*line == 0)
- continue;
-
- if (STREQN (line, redir_word, redir_len) && line[redir_len] == '\n')
- goto document_done;
-
- len = strlen (line);
- if (len + document_index >= document_size)
- {
- document_size = document_size ? 2 * (document_size + len) : len + 2;
- document = (char *)xrealloc (document, document_size);
- }
-
- /* len is guaranteed to be > 0 because of the check for line
- being an empty string before the call to strlen. */
- FASTCOPY (line, document + document_index, len);
- document_index += len;
- }
-
-document_done:
- if (document)
- document[document_index] = '\0';
- else
- {
- document = (char *)xmalloc (1);
- document[0] = '\0';
- }
- temp->redirectee.filename->word = document;
-}
-
-/* Generate a REDIRECT from SOURCE, DEST, and INSTRUCTION.
- INSTRUCTION is the instruction type, SOURCE is a file descriptor,
- and DEST is a file descriptor or a WORD_DESC *. */
-REDIRECT *
-make_redirection (source, instruction, dest_and_filename)
- int source;
- enum r_instruction instruction;
- REDIRECTEE dest_and_filename;
-{
- REDIRECT *temp;
- WORD_DESC *w;
- int wlen;
- intmax_t lfd;
-
- temp = (REDIRECT *)xmalloc (sizeof (REDIRECT));
-
- /* First do the common cases. */
- temp->redirector = source;
- temp->redirectee = dest_and_filename;
- temp->instruction = instruction;
- temp->flags = 0;
- temp->next = (REDIRECT *)NULL;
-
- switch (instruction)
- {
-
- case r_output_direction: /* >foo */
- case r_output_force: /* >| foo */
- case r_err_and_out: /* command &>filename */
- temp->flags = O_TRUNC | O_WRONLY | O_CREAT;
- break;
-
- case r_appending_to: /* >>foo */
- temp->flags = O_APPEND | O_WRONLY | O_CREAT;
- break;
-
- case r_input_direction: /* <foo */
- case r_inputa_direction: /* foo & makes this. */
- temp->flags = O_RDONLY;
- break;
-
- case r_input_output: /* <>foo */
- temp->flags = O_RDWR | O_CREAT;
- break;
-
- case r_deblank_reading_until: /* <<-foo */
- case r_reading_until: /* << foo */
- case r_reading_string: /* <<< foo */
- case r_close_this: /* <&- */
- case r_duplicating_input: /* 1<&2 */
- case r_duplicating_output: /* 1>&2 */
- break;
-
- /* the parser doesn't pass these. */
- case r_move_input: /* 1<&2- */
- case r_move_output: /* 1>&2- */
- case r_move_input_word: /* 1<&$foo- */
- case r_move_output_word: /* 1>&$foo- */
- break;
-
- /* The way the lexer works we have to do this here. */
- case r_duplicating_input_word: /* 1<&$foo */
- case r_duplicating_output_word: /* 1>&$foo */
- w = dest_and_filename.filename;
- wlen = strlen (w->word) - 1;
- if (w->word[wlen] == '-') /* Yuck */
- {
- w->word[wlen] = '\0';
- if (all_digits (w->word) && legal_number (w->word, &lfd) && lfd == (int)lfd)
- {
- dispose_word (w);
- temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input : r_move_output;
- temp->redirectee.dest = lfd;
- }
- else
- temp->instruction = (instruction == r_duplicating_input_word) ? r_move_input_word : r_move_output_word;
- }
-
- break;
-
- default:
- programming_error (_("make_redirection: redirection instruction `%d' out of range"), instruction);
- abort ();
- break;
- }
- return (temp);
-}
-
-COMMAND *
-make_function_def (name, command, lineno, lstart)
- WORD_DESC *name;
- COMMAND *command;
- int lineno, lstart;
-{
- FUNCTION_DEF *temp;
-#if defined (ARRAY_VARS)
- SHELL_VAR *bash_source_v;
- ARRAY *bash_source_a;
- char *t;
-#endif
-
- temp = (FUNCTION_DEF *)xmalloc (sizeof (FUNCTION_DEF));
- temp->command = command;
- temp->name = name;
- temp->line = lineno;
- temp->flags = 0;
- command->line = lstart;
-
- /* Information used primarily for debugging. */
- temp->source_file = 0;
-#if defined (ARRAY_VARS)
- GET_ARRAY_FROM_VAR ("BASH_SOURCE", bash_source_v, bash_source_a);
- if (bash_source_a && array_num_elements (bash_source_a) > 0)
- temp->source_file = array_reference (bash_source_a, 0);
-#endif
- bind_function_def (name->word, temp);
-
- temp->source_file = 0;
- return (make_command (cm_function_def, (SIMPLE_COM *)temp));
-}
-
-COMMAND *
-make_subshell_command (command)
- COMMAND *command;
-{
- SUBSHELL_COM *temp;
-
- temp = (SUBSHELL_COM *)xmalloc (sizeof (SUBSHELL_COM));
- temp->command = command;
- temp->flags = CMD_WANT_SUBSHELL;
- return (make_command (cm_subshell, (SIMPLE_COM *)temp));
-}
-
-/* Reverse the word list and redirection list in the simple command
- has just been parsed. It seems simpler to do this here the one
- time then by any other method that I can think of. */
-COMMAND *
-clean_simple_command (command)
- COMMAND *command;
-{
- if (command->type != cm_simple)
- command_error ("clean_simple_command", CMDERR_BADTYPE, command->type, 0);
- else
- {
- command->value.Simple->words =
- REVERSE_LIST (command->value.Simple->words, WORD_LIST *);
- command->value.Simple->redirects =
- REVERSE_LIST (command->value.Simple->redirects, REDIRECT *);
- }
-
- return (command);
-}
-
-/* The Yacc grammar productions have a problem, in that they take a
- list followed by an ampersand (`&') and do a simple command connection,
- making the entire list effectively asynchronous, instead of just
- the last command. This means that when the list is executed, all
- the commands have stdin set to /dev/null when job control is not
- active, instead of just the last. This is wrong, and needs fixing
- up. This function takes the `&' and applies it to the last command
- in the list. This is done only for lists connected by `;'; it makes
- `;' bind `tighter' than `&'. */
-COMMAND *
-connect_async_list (command, command2, connector)
- COMMAND *command, *command2;
- int connector;
-{
- COMMAND *t, *t1, *t2;
-
- t1 = command;
- t = command->value.Connection->second;
-
- if (!t || (command->flags & CMD_WANT_SUBSHELL) ||
- command->value.Connection->connector != ';')
- {
- t = command_connect (command, command2, connector);
- return t;
- }
-
- /* This is just defensive programming. The Yacc precedence rules
- will generally hand this function a command where t points directly
- to the command we want (e.g. given a ; b ; c ; d &, t1 will point
- to the `a ; b ; c' list and t will be the `d'). We only want to do
- this if the list is not being executed as a unit in the background
- with `( ... )', so we have to check for CMD_WANT_SUBSHELL. That's
- the only way to tell. */
- while (((t->flags & CMD_WANT_SUBSHELL) == 0) && t->type == cm_connection &&
- t->value.Connection->connector == ';')
- {
- t1 = t;
- t = t->value.Connection->second;
- }
- /* Now we have t pointing to the last command in the list, and
- t1->value.Connection->second == t. */
- t2 = command_connect (t, command2, connector);
- t1->value.Connection->second = t2;
- return command;
-}
diff --git a/mksyntax.c~ b/mksyntax.c~
deleted file mode 100644
index f4955855..00000000
--- a/mksyntax.c~
+++ /dev/null
@@ -1,413 +0,0 @@
-/*
- * mksyntax.c - construct shell syntax table for fast char attribute lookup.
- */
-
-/* Copyright (C) 2000-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. */
-
-#include "config.h"
-
-#include <stdio.h>
-#include "bashansi.h"
-#include "chartypes.h"
-#include <errno.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include "syntax.h"
-
-extern int optind;
-extern char *optarg;
-
-#ifndef errno
-extern int errno;
-#endif
-
-#ifndef HAVE_STRERROR
-extern char *strerror();
-#endif
-
-struct wordflag {
- int flag;
- char *fstr;
-} wordflags[] = {
- { CWORD, "CWORD" },
- { CSHMETA, "CSHMETA" },
- { CSHBRK, "CSHBRK" },
- { CBACKQ, "CBACKQ" },
- { CQUOTE, "CQUOTE" },
- { CSPECL, "CSPECL" },
- { CEXP, "CEXP" },
- { CBSDQUOTE, "CBSDQUOTE" },
- { CBSHDOC, "CBSHDOC" },
- { CGLOB, "CGLOB" },
- { CXGLOB, "CXGLOB" },
- { CXQUOTE, "CXQUOTE" },
- { CSPECVAR, "CSPECVAR" },
- { CSUBSTOP, "CSUBSTOP" },
- { CBLANK, "CBLANK" },
-};
-
-#define N_WFLAGS (sizeof (wordflags) / sizeof (wordflags[0]))
-#define SYNSIZE 256
-
-int lsyntax[SYNSIZE];
-int debug;
-char *progname;
-
-char preamble[] = "\
-/*\n\
- * This file was generated by mksyntax. DO NOT EDIT.\n\
- */\n\
-\n";
-
-char includes[] = "\
-#include \"config.h\"\n\
-#include \"stdc.h\"\n\
-#include \"syntax.h\"\n\n";
-
-static void
-usage()
-{
- fprintf (stderr, "%s: usage: %s [-d] [-o filename]\n", progname, progname);
- exit (2);
-}
-
-#ifdef INCLUDE_UNUSED
-static int
-getcflag (s)
- char *s;
-{
- int i;
-
- for (i = 0; i < N_WFLAGS; i++)
- if (strcmp (s, wordflags[i].fstr) == 0)
- return wordflags[i].flag;
- return -1;
-}
-#endif
-
-static char *
-cdesc (i)
- int i;
-{
- static char xbuf[16];
-
- if (i == ' ')
- return "SPC";
- else if (ISPRINT (i))
- {
- xbuf[0] = i;
- xbuf[1] = '\0';
- return (xbuf);
- }
- else if (i == CTLESC)
- return "CTLESC";
- else if (i == CTLNUL)
- return "CTLNUL";
- else if (i == '\033') /* ASCII */
- return "ESC";
-
- xbuf[0] = '\\';
- xbuf[2] = '\0';
-
- switch (i)
- {
-#ifdef __STDC__
- case '\a': xbuf[1] = 'a'; break;
- case '\v': xbuf[1] = 'v'; break;
-#else
- case '\007': xbuf[1] = 'a'; break;
- case 0x0B: xbuf[1] = 'v'; break;
-#endif
- case '\b': xbuf[1] = 'b'; break;
- case '\f': xbuf[1] = 'f'; break;
- case '\n': xbuf[1] = 'n'; break;
- case '\r': xbuf[1] = 'r'; break;
- case '\t': xbuf[1] = 't'; break;
- default: sprintf (xbuf, "%d", i); break;
- }
-
- return xbuf;
-}
-
-static char *
-getcstr (f)
- int f;
-{
- int i;
-
- for (i = 0; i < N_WFLAGS; i++)
- if (f == wordflags[i].flag)
- return (wordflags[i].fstr);
- return ((char *)NULL);
-}
-
-static void
-addcstr (str, flag)
- char *str;
- int flag;
-{
- char *s, *fstr;
- unsigned char uc;
-
- for (s = str; s && *s; s++)
- {
- uc = *s;
-
- if (debug)
- {
- fstr = getcstr (flag);
- fprintf(stderr, "added %s for character %s\n", fstr, cdesc(uc));
- }
-
- lsyntax[uc] |= flag;
- }
-}
-
-static void
-addcchar (c, flag)
- unsigned char c;
- int flag;
-{
- char *fstr;
-
- if (debug)
- {
- fstr = getcstr (flag);
- fprintf (stderr, "added %s for character %s\n", fstr, cdesc(c));
- }
- lsyntax[c] |= flag;
-}
-
-static void
-addblanks ()
-{
- register int i;
- unsigned char uc;
-
- for (i = 0; i < SYNSIZE; i++)
- {
- uc = i;
- if (isblank (uc))
- lsyntax[uc] |= CBLANK;
- }
-}
-
-/* load up the correct flag values in lsyntax */
-static void
-load_lsyntax ()
-{
- /* shell metacharacters */
- addcstr (shell_meta_chars, CSHMETA);
-
- /* shell word break characters */
- addcstr (shell_break_chars, CSHBRK);
-
- addcchar ('`', CBACKQ);
-
- addcstr (shell_quote_chars, CQUOTE);
-
- addcchar (CTLESC, CSPECL);
- addcchar (CTLNUL, CSPECL);
-
- addcstr (shell_exp_chars, CEXP);
-
- addcstr (slashify_in_quotes, CBSDQUOTE);
- addcstr (slashify_in_here_document, CBSHDOC);
-
- addcstr (shell_glob_chars, CGLOB);
-
-#if defined (EXTENDED_GLOB)
- addcstr (ext_glob_chars, CXGLOB);
-#endif
-
- addcstr (shell_quote_chars, CXQUOTE);
- addcchar ('\\', CXQUOTE);
-
- addcstr ("@*#?-$!", CSPECVAR); /* omits $0...$9 and $_ */
-
- addcstr ("-=?+", CSUBSTOP); /* OP in ${paramOPword} */
-
- addblanks ();
-}
-
-static void
-dump_lflags (fp, ind)
- FILE *fp;
- int ind;
-{
- int xflags, first, i;
-
- xflags = lsyntax[ind];
- first = 1;
-
- if (xflags == 0)
- fputs (wordflags[0].fstr, fp);
- else
- {
- for (i = 1; i < N_WFLAGS; i++)
- if (xflags & wordflags[i].flag)
- {
- if (first)
- first = 0;
- else
- putc ('|', fp);
- fputs (wordflags[i].fstr, fp);
- }
- }
-}
-
-static void
-wcomment (fp, i)
- FILE *fp;
- int i;
-{
- fputs ("\t\t/* ", fp);
-
- fprintf (fp, "%s", cdesc(i));
-
- fputs (" */", fp);
-}
-
-static void
-dump_lsyntax (fp)
- FILE *fp;
-{
- int i;
-
- fprintf (fp, "int sh_syntabsiz = %d;\n", SYNSIZE);
- fprintf (fp, "int sh_syntaxtab[%d] = {\n", SYNSIZE);
-
- for (i = 0; i < SYNSIZE; i++)
- {
- putc ('\t', fp);
- dump_lflags (fp, i);
- putc (',', fp);
- wcomment (fp, i);
- putc ('\n', fp);
- }
-
- fprintf (fp, "};\n");
-}
-
-int
-main(argc, argv)
- int argc;
- char **argv;
-{
- int opt, i;
- char *filename;
- FILE *fp;
-
- if ((progname = strrchr (argv[0], '/')) == 0)
- progname = argv[0];
- else
- progname++;
-
- filename = (char *)NULL;
- debug = 0;
-
- while ((opt = getopt (argc, argv, "do:")) != EOF)
- {
- switch (opt)
- {
- case 'd':
- debug = 1;
- break;
- case 'o':
- filename = optarg;
- break;
- default:
- usage();
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (filename)
- {
- fp = fopen (filename, "w");
- if (fp == 0)
- {
- fprintf (stderr, "%s: %s: cannot open: %s\n", progname, filename, strerror(errno));
- exit (1);
- }
- }
- else
- {
- filename = "stdout";
- fp = stdout;
- }
-
-
- for (i = 0; i < SYNSIZE; i++)
- lsyntax[i] = CWORD;
-
- load_lsyntax ();
-
- fprintf (fp, "%s\n", preamble);
- fprintf (fp, "%s\n", includes);
-
- dump_lsyntax (fp);
-
- if (fp != stdout)
- fclose (fp);
- exit (0);
-}
-
-
-#if !defined (HAVE_STRERROR)
-
-#include <bashtypes.h>
-#ifndef _MINIX
-# include <sys/param.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-/* Return a string corresponding to the error number E. From
- the ANSI C spec. */
-#if defined (strerror)
-# undef strerror
-#endif
-
-char *
-strerror (e)
- int e;
-{
- static char emsg[40];
-#if defined (HAVE_SYS_ERRLIST)
- extern int sys_nerr;
- extern char *sys_errlist[];
-
- if (e > 0 && e < sys_nerr)
- return (sys_errlist[e]);
- else
-#endif /* HAVE_SYS_ERRLIST */
- {
- sprintf (emsg, "Unknown system error %d", e);
- return (&emsg[0]);
- }
-}
-#endif /* HAVE_STRERROR */
diff --git a/parse.y.diff b/parse.y.diff
deleted file mode 100644
index b675aad5..00000000
--- a/parse.y.diff
+++ /dev/null
@@ -1,251 +0,0 @@
-*** ../bash-3.1/parse.y Fri Nov 11 23:14:18 2005
---- parse.y Wed Jan 25 14:55:18 2006
-***************
-*** 1,5 ****
- /* Yacc grammar for bash. */
-
-! /* Copyright (C) 1989-2005 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
---- 1,5 ----
- /* Yacc grammar for bash. */
-
-! /* Copyright (C) 1989-2006 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-***************
-*** 119,123 ****
- extern int posixly_correct;
- extern int last_command_exit_value;
-- extern int interrupt_immediately;
- extern char *shell_name, *current_host_name;
- extern char *dist_version;
---- 119,122 ----
-***************
-*** 1213,1220 ****
---- 1212,1221 ----
- interrupt_immediately++;
- }
-+ terminate_immediately = 1;
-
- current_readline_line = readline (current_readline_prompt ?
- current_readline_prompt : "");
-
-+ terminate_immediately = 0;
- if (signal_is_ignored (SIGINT) == 0 && old_sigint)
- {
-***************
-*** 1348,1355 ****
- {
- if (interactive)
-! interrupt_immediately++;
- result = getc_with_restart (bash_input.location.file);
- if (interactive)
-! interrupt_immediately--;
- }
- return (result);
---- 1349,1362 ----
- {
- if (interactive)
-! {
-! interrupt_immediately++;
-! terminate_immediately++;
-! }
- result = getc_with_restart (bash_input.location.file);
- if (interactive)
-! {
-! interrupt_immediately--;
-! terminate_immediately--;
-! }
- }
- return (result);
-***************
-*** 2743,2751 ****
- while (count)
- {
-- #if 0
-- ch = shell_getc ((qc != '\'' || (flags & P_ALLOWESC)) && pass_next_character == 0);
-- #else
- ch = shell_getc (qc != '\'' && pass_next_character == 0);
-! #endif
- if (ch == EOF)
- {
---- 2750,2755 ----
- while (count)
- {
- ch = shell_getc (qc != '\'' && pass_next_character == 0);
-!
- if (ch == EOF)
- {
-***************
-*** 2772,2776 ****
- }
- /* Not exactly right yet */
-! else if (check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind -1])))
- in_comment = 1;
-
---- 2776,2780 ----
- }
- /* Not exactly right yet */
-! else if MBTEST(check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind - 1])))
- in_comment = 1;
-
-***************
-*** 2799,2807 ****
- else if MBTEST(ch == close) /* ending delimiter */
- count--;
-- #if 1
- /* handle nested ${...} specially. */
- else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
- count++;
-- #endif
- else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
- count++;
---- 2803,2809 ----
-***************
-*** 2899,2903 ****
- else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
- {
-! nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags);
- goto add_nestret;
- }
---- 2901,2909 ----
- else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
- {
-! /* Add P_ALLOWESC so backslash quotes the next character and
-! shell_getc does the right thing with \<newline>. We do this for
-! a measure of backwards compatibility -- it's not strictly the
-! right POSIX thing. */
-! nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags|P_ALLOWESC);
- goto add_nestret;
- }
-***************
-*** 2908,2912 ****
- count--;
- if (ch == '(') /* ) */
-! nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags);
- else if (ch == '{') /* } */
- nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
---- 2914,2918 ----
- count--;
- if (ch == '(') /* ) */
-! nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE);
- else if (ch == '{') /* } */
- nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
-***************
-*** 2947,2951 ****
- wd = alloc_word_desc ();
- wd->word = wval;
-- wd = make_word (wval);
- yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
- return (ARITH_FOR_EXPRS);
---- 2953,2956 ----
-***************
-*** 3497,3501 ****
- else
- {
-! /* Try to locale)-expand the converted string. */
- ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
- free (ttok);
---- 3502,3506 ----
- else
- {
-! /* Try to locale-expand the converted string. */
- ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
- free (ttok);
-***************
-*** 3579,3583 ****
- all_digit_token = 0;
- compound_assignment = 1;
-! #if 0
- goto next_character;
- #else
---- 3584,3588 ----
- all_digit_token = 0;
- compound_assignment = 1;
-! #if 1
- goto next_character;
- #else
-***************
-*** 3696,3700 ****
- b = builtin_address_internal (token, 0);
- if (b && (b->flags & ASSIGNMENT_BUILTIN))
-! parser_state |= PST_ASSIGNOK;
- }
-
---- 3701,3707 ----
- b = builtin_address_internal (token, 0);
- if (b && (b->flags & ASSIGNMENT_BUILTIN))
-! parser_state |= PST_ASSIGNOK;
-! else if (STREQ (token, "eval") || STREQ (token, "let"))
-! parser_state |= PST_ASSIGNOK;
- }
-
-***************
-*** 4247,4251 ****
- }
- temp = (char *)xmalloc (3);
-! temp[0] = '\001';
- temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
- temp[2] = '\0';
---- 4254,4258 ----
- }
- temp = (char *)xmalloc (3);
-! temp[0] = CTLESC;
- temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
- temp[2] = '\0';
-***************
-*** 4687,4691 ****
- {
- WORD_LIST *wl, *rl;
-! int tok, orig_line_number, orig_token_size;
- char *saved_token, *ret;
-
---- 4694,4698 ----
- {
- WORD_LIST *wl, *rl;
-! int tok, orig_line_number, orig_token_size, orig_last_token, assignok;
- char *saved_token, *ret;
-
-***************
-*** 4693,4696 ****
---- 4700,4704 ----
- orig_token_size = token_buffer_size;
- orig_line_number = line_number;
-+ orig_last_token = last_read_token;
-
- last_read_token = WORD; /* WORD to allow reserved words here */
-***************
-*** 4699,4702 ****
---- 4707,4712 ----
- token_buffer_size = 0;
-
-+ assignok = parser_state&PST_ASSIGNOK; /* XXX */
-+
- wl = (WORD_LIST *)NULL; /* ( */
- parser_state |= PST_COMPASSIGN;
-***************
-*** 4741,4745 ****
- }
-
-! last_read_token = WORD;
- if (wl)
- {
---- 4751,4756 ----
- }
-
-! last_read_token = orig_last_token; /* XXX - was WORD? */
-!
- if (wl)
- {
-***************
-*** 4753,4756 ****
---- 4764,4771 ----
- if (retlenp)
- *retlenp = (ret && *ret) ? strlen (ret) : 0;
-+
-+ if (assignok)
-+ parser_state |= PST_ASSIGNOK;
-+
- return ret;
- }
diff --git a/parse.y.save1 b/parse.y.save1
deleted file mode 100644
index ea9129f4..00000000
--- a/parse.y.save1
+++ /dev/null
@@ -1,4911 +0,0 @@
-/* Yacc grammar for bash. */
-
-/* Copyright (C) 1989-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 LICENSE. If not, write to the Free Software
- Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
-
-%{
-#include "config.h"
-
-#include "bashtypes.h"
-#include "bashansi.h"
-
-#include "filecntl.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_LOCALE_H)
-# include <locale.h>
-#endif
-
-#include <stdio.h>
-#include "chartypes.h"
-#include <signal.h>
-
-#include "memalloc.h"
-
-#include "bashintl.h"
-
-#define NEED_STRFTIME_DECL /* used in externs.h */
-
-#include "shell.h"
-#include "trap.h"
-#include "flags.h"
-#include "parser.h"
-#include "mailcheck.h"
-#include "test.h"
-#include "builtins.h"
-#include "builtins/common.h"
-#include "builtins/builtext.h"
-
-#include "shmbutil.h"
-
-#if defined (READLINE)
-# include "bashline.h"
-# include <readline/readline.h>
-#endif /* READLINE */
-
-#if defined (HISTORY)
-# include "bashhist.h"
-# include <readline/history.h>
-#endif /* HISTORY */
-
-#if defined (JOB_CONTROL)
-# include "jobs.h"
-#endif /* JOB_CONTROL */
-
-#if defined (ALIAS)
-# include "alias.h"
-#else
-typedef void *alias_t;
-#endif /* ALIAS */
-
-#if defined (PROMPT_STRING_DECODE)
-# ifndef _MINIX
-# include <sys/param.h>
-# endif
-# include <time.h>
-# if defined (TM_IN_SYS_TIME)
-# include <sys/types.h>
-# include <sys/time.h>
-# endif /* TM_IN_SYS_TIME */
-# include "maxpath.h"
-#endif /* PROMPT_STRING_DECODE */
-
-#define RE_READ_TOKEN -99
-#define NO_EXPANSION -100
-
-#ifdef DEBUG
-# define YYDEBUG 1
-#else
-# define YYDEBUG 0
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
-# define last_shell_getc_is_singlebyte \
- ((shell_input_line_index > 1) \
- ? shell_input_line_property[shell_input_line_index - 1] \
- : 1)
-# define MBTEST(x) ((x) && last_shell_getc_is_singlebyte)
-#else
-# define last_shell_getc_is_singlebyte 1
-# define MBTEST(x) ((x))
-#endif
-
-#if defined (EXTENDED_GLOB)
-extern int extended_glob;
-#endif
-
-extern int eof_encountered;
-extern int no_line_editing, running_under_emacs;
-extern int current_command_number;
-extern int sourcelevel;
-extern int posixly_correct;
-extern int last_command_exit_value;
-extern int interrupt_immediately;
-extern char *shell_name, *current_host_name;
-extern char *dist_version;
-extern int patch_level;
-extern int dump_translatable_strings, dump_po_strings;
-extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
-#if defined (BUFFERED_INPUT)
-extern int bash_input_fd_changed;
-#endif
-
-extern int errno;
-/* **************************************************************** */
-/* */
-/* "Forward" declarations */
-/* */
-/* **************************************************************** */
-
-#ifdef DEBUG
-static void debug_parser __P((int));
-#endif
-
-static int yy_getc __P((void));
-static int yy_ungetc __P((int));
-
-#if defined (READLINE)
-static int yy_readline_get __P((void));
-static int yy_readline_unget __P((int));
-#endif
-
-static int yy_string_get __P((void));
-static int yy_string_unget __P((int));
-static int yy_stream_get __P((void));
-static int yy_stream_unget __P((int));
-
-static int shell_getc __P((int));
-static void shell_ungetc __P((int));
-static void discard_until __P((int));
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
-static void push_string __P((char *, int, alias_t *));
-static void pop_string __P((void));
-static void free_string_list __P((void));
-#endif
-
-static char *read_a_line __P((int));
-
-static int reserved_word_acceptable __P((int));
-static int yylex __P((void));
-static int alias_expand_token __P((char *));
-static int time_command_acceptable __P((void));
-static int special_case_tokens __P((char *));
-static int read_token __P((int));
-static char *parse_matched_pair __P((int, int, int, int *, int));
-#if defined (ARRAY_VARS)
-static char *parse_compound_assignment __P((int *));
-#endif
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
-static int parse_dparen __P((int));
-static int parse_arith_cmd __P((char **, int));
-#endif
-#if defined (COND_COMMAND)
-static void cond_error __P((void));
-static COND_COM *cond_expr __P((void));
-static COND_COM *cond_or __P((void));
-static COND_COM *cond_and __P((void));
-static COND_COM *cond_term __P((void));
-static int cond_skip_newlines __P((void));
-static COMMAND *parse_cond_command __P((void));
-#endif
-#if defined (ARRAY_VARS)
-static int token_is_assignment __P((char *, int));
-static int token_is_ident __P((char *, int));
-#endif
-static int read_token_word __P((int));
-static void discard_parser_constructs __P((int));
-
-static char *error_token_from_token __P((int));
-static char *error_token_from_text __P((void));
-static void print_offending_line __P((void));
-static void report_syntax_error __P((char *));
-
-static void handle_eof_input_unit __P((void));
-static void prompt_again __P((void));
-#if 0
-static void reset_readline_prompt __P((void));
-#endif
-static void print_prompt __P((void));
-
-#if defined (HISTORY)
-char *history_delimiting_chars __P((void));
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
-static void set_line_mbstate __P((void));
-static char *shell_input_line_property = NULL;
-#else
-# define set_line_mbstate()
-#endif
-
-extern int yyerror __P((const char *));
-
-#ifdef DEBUG
-extern int yydebug;
-#endif
-
-/* Default prompt strings */
-char *primary_prompt = PPROMPT;
-char *secondary_prompt = SPROMPT;
-
-/* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
-char *ps1_prompt, *ps2_prompt;
-
-/* Handle on the current prompt string. Indirectly points through
- ps1_ or ps2_prompt. */
-char **prompt_string_pointer = (char **)NULL;
-char *current_prompt_string;
-
-/* Non-zero means we expand aliases in commands. */
-int expand_aliases = 0;
-
-/* If non-zero, the decoded prompt string undergoes parameter and
- variable substitution, command substitution, arithmetic substitution,
- string expansion, process substitution, and quote removal in
- decode_prompt_string. */
-int promptvars = 1;
-
-/* If non-zero, $'...' and $"..." are expanded when they appear within
- a ${...} expansion, even when the expansion appears within double
- quotes. */
-int extended_quote = 1;
-
-/* The decoded prompt string. Used if READLINE is not defined or if
- editing is turned off. Analogous to current_readline_prompt. */
-static char *current_decoded_prompt;
-
-/* The number of lines read from input while creating the current command. */
-int current_command_line_count;
-
-/* Variables to manage the task of reading here documents, because we need to
- defer the reading until after a complete command has been collected. */
-static REDIRECT *redir_stack[10];
-int need_here_doc;
-
-/* Where shell input comes from. History expansion is performed on each
- line when the shell is interactive. */
-static char *shell_input_line = (char *)NULL;
-static int shell_input_line_index;
-static int shell_input_line_size; /* Amount allocated for shell_input_line. */
-static int shell_input_line_len; /* strlen (shell_input_line) */
-
-/* Either zero or EOF. */
-static int shell_input_line_terminator;
-
-/* The line number in a script on which a function definition starts. */
-static int function_dstart;
-
-/* The line number in a script on which a function body starts. */
-static int function_bstart;
-
-/* The line number in a script at which an arithmetic for command starts. */
-static int arith_for_lineno;
-
-/* The line number in a script where the word in a `case WORD', `select WORD'
- or `for WORD' begins. This is a nested command maximum, since the array
- index is decremented after a case, select, or for command is parsed. */
-#define MAX_CASE_NEST 128
-static int word_lineno[MAX_CASE_NEST];
-static int word_top = -1;
-
-/* If non-zero, it is the token that we want read_token to return
- regardless of what text is (or isn't) present to be read. This
- is reset by read_token. If token_to_read == WORD or
- ASSIGNMENT_WORD, yylval.word should be set to word_desc_to_read. */
-static int token_to_read;
-static WORD_DESC *word_desc_to_read;
-
-static REDIRECTEE redir;
-%}
-
-%union {
- WORD_DESC *word; /* the word that we read. */
- int number; /* the number that we read. */
- WORD_LIST *word_list;
- COMMAND *command;
- REDIRECT *redirect;
- ELEMENT element;
- PATTERN_LIST *pattern;
-}
-
-/* Reserved words. Members of the first group are only recognized
- in the case that they are preceded by a list_terminator. Members
- of the second group are for [[...]] commands. Members of the
- third group are recognized only under special circumstances. */
-%token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION
-%token COND_START COND_END COND_ERROR
-%token IN BANG TIME TIMEOPT
-
-/* More general tokens. yylex () knows how to make these. */
-%token <word> WORD ASSIGNMENT_WORD
-%token <number> NUMBER
-%token <word_list> ARITH_CMD ARITH_FOR_EXPRS
-%token <command> COND_CMD
-%token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND LESS_LESS_LESS
-%token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER
-%token GREATER_BAR
-
-/* The types that the various syntactical units return. */
-
-%type <command> inputunit command pipeline pipeline_command
-%type <command> list list0 list1 compound_list simple_list simple_list1
-%type <command> simple_command shell_command
-%type <command> for_command select_command case_command group_command
-%type <command> arith_command
-%type <command> cond_command
-%type <command> arith_for_command
-%type <command> function_def function_body if_command elif_clause subshell
-%type <redirect> redirection redirection_list
-%type <element> simple_command_element
-%type <word_list> word_list pattern
-%type <pattern> pattern_list case_clause_sequence case_clause
-%type <number> timespec
-%type <number> list_terminator
-
-%start inputunit
-
-%left '&' ';' '\n' yacc_EOF
-%left AND_AND OR_OR
-%right '|'
-%%
-
-inputunit: simple_list simple_list_terminator
- {
- /* Case of regular command. Discard the error
- safety net,and return the command just parsed. */
- global_command = $1;
- eof_encountered = 0;
- /* discard_parser_constructs (0); */
- YYACCEPT;
- }
- | '\n'
- {
- /* Case of regular command, but not a very
- interesting one. Return a NULL command. */
- global_command = (COMMAND *)NULL;
- YYACCEPT;
- }
- | error '\n'
- {
- /* Error during parsing. Return NULL command. */
- global_command = (COMMAND *)NULL;
- eof_encountered = 0;
- /* discard_parser_constructs (1); */
- if (interactive)
- {
- YYACCEPT;
- }
- else
- {
- YYABORT;
- }
- }
- | yacc_EOF
- {
- /* Case of EOF seen by itself. Do ignoreeof or
- not. */
- global_command = (COMMAND *)NULL;
- handle_eof_input_unit ();
- YYACCEPT;
- }
- ;
-
-word_list: WORD
- { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
- | word_list WORD
- { $$ = make_word_list ($2, $1); }
- ;
-
-redirection: '>' WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_output_direction, redir);
- }
- | '<' WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_input_direction, redir);
- }
- | NUMBER '>' WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_output_direction, redir);
- }
- | NUMBER '<' WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_input_direction, redir);
- }
- | GREATER_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_appending_to, redir);
- }
- | NUMBER GREATER_GREATER WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_appending_to, redir);
- }
- | LESS_LESS WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | NUMBER LESS_LESS WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | LESS_LESS_LESS WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_reading_string, redir);
- }
- | NUMBER LESS_LESS_LESS WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_reading_string, redir);
- }
- | LESS_AND NUMBER
- {
- redir.dest = $2;
- $$ = make_redirection (0, r_duplicating_input, redir);
- }
- | NUMBER LESS_AND NUMBER
- {
- redir.dest = $3;
- $$ = make_redirection ($1, r_duplicating_input, redir);
- }
- | GREATER_AND NUMBER
- {
- redir.dest = $2;
- $$ = make_redirection (1, r_duplicating_output, redir);
- }
- | NUMBER GREATER_AND NUMBER
- {
- redir.dest = $3;
- $$ = make_redirection ($1, r_duplicating_output, redir);
- }
- | LESS_AND WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_duplicating_input_word, redir);
- }
- | NUMBER LESS_AND WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_duplicating_input_word, redir);
- }
- | GREATER_AND WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_duplicating_output_word, redir);
- }
- | NUMBER GREATER_AND WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_duplicating_output_word, redir);
- }
- | LESS_LESS_MINUS WORD
- {
- redir.filename = $2;
- $$ = make_redirection
- (0, r_deblank_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | NUMBER LESS_LESS_MINUS WORD
- {
- redir.filename = $3;
- $$ = make_redirection
- ($1, r_deblank_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | GREATER_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection (1, r_close_this, redir);
- }
- | NUMBER GREATER_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection ($1, r_close_this, redir);
- }
- | LESS_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection (0, r_close_this, redir);
- }
- | NUMBER LESS_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection ($1, r_close_this, redir);
- }
- | AND_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_err_and_out, redir);
- }
- | NUMBER LESS_GREATER WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_input_output, redir);
- }
- | LESS_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_input_output, redir);
- }
- | GREATER_BAR WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_output_force, redir);
- }
- | NUMBER GREATER_BAR WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_output_force, redir);
- }
- ;
-
-simple_command_element: WORD
- { $$.word = $1; $$.redirect = 0; }
- | ASSIGNMENT_WORD
- { $$.word = $1; $$.redirect = 0; }
- | redirection
- { $$.redirect = $1; $$.word = 0; }
- ;
-
-redirection_list: redirection
- {
- $$ = $1;
- }
- | redirection_list redirection
- {
- register REDIRECT *t;
-
- for (t = $1; t->next; t = t->next)
- ;
- t->next = $2;
- $$ = $1;
- }
- ;
-
-simple_command: simple_command_element
- { $$ = make_simple_command ($1, (COMMAND *)NULL); }
- | simple_command simple_command_element
- { $$ = make_simple_command ($2, $1); }
- ;
-
-command: simple_command
- { $$ = clean_simple_command ($1); }
- | shell_command
- { $$ = $1; }
- | shell_command redirection_list
- {
- COMMAND *tc;
-
- tc = $1;
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = $2;
- }
- else
- tc->redirects = $2;
- $$ = $1;
- }
- | function_def
- { $$ = $1; }
- ;
-
-shell_command: for_command
- { $$ = $1; }
- | case_command
- { $$ = $1; }
- | WHILE compound_list DO compound_list DONE
- { $$ = make_while_command ($2, $4); }
- | UNTIL compound_list DO compound_list DONE
- { $$ = make_until_command ($2, $4); }
- | select_command
- { $$ = $1; }
- | if_command
- { $$ = $1; }
- | subshell
- { $$ = $1; }
- | group_command
- { $$ = $1; }
- | arith_command
- { $$ = $1; }
- | cond_command
- { $$ = $1; }
- | arith_for_command
- { $$ = $1; }
- ;
-
-for_command: FOR WORD newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD ';' newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD ';' newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN word_list list_terminator newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN word_list list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN list_terminator newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-arith_for_command: FOR ARITH_FOR_EXPRS list_terminator newline_list DO compound_list DONE
- {
- $$ = make_arith_for_command ($2, $6, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_arith_for_command ($2, $6, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS DO compound_list DONE
- {
- $$ = make_arith_for_command ($2, $4, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS '{' compound_list '}'
- {
- $$ = make_arith_for_command ($2, $4, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- ;
-
-select_command: SELECT WORD newline_list DO list DONE
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list '{' list '}'
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD ';' newline_list DO list DONE
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD ';' newline_list '{' list '}'
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list IN word_list list_terminator newline_list DO list DONE
- {
- $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list IN word_list list_terminator newline_list '{' list '}'
- {
- $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-case_command: CASE WORD newline_list IN newline_list ESAC
- {
- $$ = make_case_command ($2, (PATTERN_LIST *)NULL, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | CASE WORD newline_list IN case_clause_sequence newline_list ESAC
- {
- $$ = make_case_command ($2, $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | CASE WORD newline_list IN case_clause ESAC
- {
- $$ = make_case_command ($2, $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-function_def: WORD '(' ')' newline_list function_body
- { $$ = make_function_def ($1, $5, function_dstart, function_bstart); }
-
- | FUNCTION WORD '(' ')' newline_list function_body
- { $$ = make_function_def ($2, $6, function_dstart, function_bstart); }
-
- | FUNCTION WORD newline_list function_body
- { $$ = make_function_def ($2, $4, function_dstart, function_bstart); }
- ;
-
-
-function_body: shell_command
- { $$ = $1; }
- | shell_command redirection_list
- {
- COMMAND *tc;
-
- tc = $1;
- /* According to Posix.2 3.9.5, redirections
- specified after the body of a function should
- be attached to the function and performed when
- the function is executed, not as part of the
- function definition command. */
- /* XXX - I don't think it matters, but we might
- want to change this in the future to avoid
- problems differentiating between a function
- definition with a redirection and a function
- definition containing a single command with a
- redirection. The two are semantically equivalent,
- though -- the only difference is in how the
- command printing code displays the redirections. */
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = $2;
- }
- else
- tc->redirects = $2;
- $$ = $1;
- }
- ;
-
-subshell: '(' compound_list ')'
- {
- $$ = make_subshell_command ($2);
- $$->flags |= CMD_WANT_SUBSHELL;
- }
- ;
-
-if_command: IF compound_list THEN compound_list FI
- { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
- | IF compound_list THEN compound_list ELSE compound_list FI
- { $$ = make_if_command ($2, $4, $6); }
- | IF compound_list THEN compound_list elif_clause FI
- { $$ = make_if_command ($2, $4, $5); }
- ;
-
-
-group_command: '{' compound_list '}'
- { $$ = make_group_command ($2); }
- ;
-
-arith_command: ARITH_CMD
- { $$ = make_arith_command ($1); }
- ;
-
-cond_command: COND_START COND_CMD COND_END
- { $$ = $2; }
- ;
-
-elif_clause: ELIF compound_list THEN compound_list
- { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
- | ELIF compound_list THEN compound_list ELSE compound_list
- { $$ = make_if_command ($2, $4, $6); }
- | ELIF compound_list THEN compound_list elif_clause
- { $$ = make_if_command ($2, $4, $5); }
- ;
-
-case_clause: pattern_list
- | case_clause_sequence pattern_list
- { $2->next = $1; $$ = $2; }
- ;
-
-pattern_list: newline_list pattern ')' compound_list
- { $$ = make_pattern_list ($2, $4); }
- | newline_list pattern ')' newline_list
- { $$ = make_pattern_list ($2, (COMMAND *)NULL); }
- | newline_list '(' pattern ')' compound_list
- { $$ = make_pattern_list ($3, $5); }
- | newline_list '(' pattern ')' newline_list
- { $$ = make_pattern_list ($3, (COMMAND *)NULL); }
- ;
-
-case_clause_sequence: pattern_list SEMI_SEMI
- | case_clause_sequence pattern_list SEMI_SEMI
- { $2->next = $1; $$ = $2; }
- ;
-
-pattern: WORD
- { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
- | pattern '|' WORD
- { $$ = make_word_list ($3, $1); }
- ;
-
-/* A list allows leading or trailing newlines and
- newlines as operators (equivalent to semicolons).
- It must end with a newline or semicolon.
- Lists are used within commands such as if, for, while. */
-
-list: newline_list list0
- {
- $$ = $2;
- if (need_here_doc)
- gather_here_documents ();
- }
- ;
-
-compound_list: list
- | newline_list list1
- {
- $$ = $2;
- }
- ;
-
-list0: list1 '\n' newline_list
- | list1 '&' newline_list
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
- else
- $$ = command_connect ($1, (COMMAND *)NULL, '&');
- }
- | list1 ';' newline_list
-
- ;
-
-list1: list1 AND_AND newline_list list1
- { $$ = command_connect ($1, $4, AND_AND); }
- | list1 OR_OR newline_list list1
- { $$ = command_connect ($1, $4, OR_OR); }
- | list1 '&' newline_list list1
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, $4, '&');
- else
- $$ = command_connect ($1, $4, '&');
- }
- | list1 ';' newline_list list1
- { $$ = command_connect ($1, $4, ';'); }
- | list1 '\n' newline_list list1
- { $$ = command_connect ($1, $4, ';'); }
- | pipeline_command
- { $$ = $1; }
- ;
-
-simple_list_terminator: '\n'
- | yacc_EOF
- ;
-
-list_terminator:'\n'
- { $$ = '\n'; }
- | ';'
- { $$ = ';'; }
- | yacc_EOF
- { $$ = yacc_EOF; }
- ;
-
-newline_list:
- | newline_list '\n'
- ;
-
-/* A simple_list is a list that contains no significant newlines
- and no leading or trailing newlines. Newlines are allowed
- only following operators, where they are not significant.
-
- This is what an inputunit consists of. */
-
-simple_list: simple_list1
- {
- $$ = $1;
- if (need_here_doc)
- gather_here_documents ();
- }
- | simple_list1 '&'
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
- else
- $$ = command_connect ($1, (COMMAND *)NULL, '&');
- if (need_here_doc)
- gather_here_documents ();
- }
- | simple_list1 ';'
- {
- $$ = $1;
- if (need_here_doc)
- gather_here_documents ();
- }
- ;
-
-simple_list1: simple_list1 AND_AND newline_list simple_list1
- { $$ = command_connect ($1, $4, AND_AND); }
- | simple_list1 OR_OR newline_list simple_list1
- { $$ = command_connect ($1, $4, OR_OR); }
- | simple_list1 '&' simple_list1
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, $3, '&');
- else
- $$ = command_connect ($1, $3, '&');
- }
- | simple_list1 ';' simple_list1
- { $$ = command_connect ($1, $3, ';'); }
-
- | pipeline_command
- { $$ = $1; }
- ;
-
-pipeline_command: pipeline
- { $$ = $1; }
- | BANG pipeline
- {
- if ($2)
- $2->flags |= CMD_INVERT_RETURN;
- $$ = $2;
- }
- | timespec pipeline
- {
- if ($2)
- $2->flags |= $1;
- $$ = $2;
- }
- | timespec BANG pipeline
- {
- if ($3)
- $3->flags |= $1|CMD_INVERT_RETURN;
- $$ = $3;
- }
- | BANG timespec pipeline
- {
- if ($3)
- $3->flags |= $2|CMD_INVERT_RETURN;
- $$ = $3;
- }
- | timespec list_terminator
- {
- ELEMENT x;
-
- /* Boy, this is unclean. `time' by itself can
- time a null command. We cheat and push a
- newline back if the list_terminator was a newline
- to avoid the double-newline problem (one to
- terminate this, one to terminate the command) */
- x.word = 0;
- x.redirect = 0;
- $$ = make_simple_command (x, (COMMAND *)NULL);
- $$->flags |= $1;
- /* XXX - let's cheat and push a newline back */
- if ($2 == '\n')
- token_to_read = '\n';
- }
-
- ;
-
-pipeline:
- pipeline '|' newline_list pipeline
- { $$ = command_connect ($1, $4, '|'); }
- | command
- { $$ = $1; }
- ;
-
-timespec: TIME
- { $$ = CMD_TIME_PIPELINE; }
- | TIME TIMEOPT
- { $$ = CMD_TIME_PIPELINE|CMD_TIME_POSIX; }
- ;
-%%
-
-/* Possible states for the parser that require it to do special things. */
-#define PST_CASEPAT 0x0001 /* in a case pattern list */
-#define PST_ALEXPNEXT 0x0002 /* expand next word for aliases */
-#define PST_ALLOWOPNBRC 0x0004 /* allow open brace for function def */
-#define PST_NEEDCLOSBRC 0x0008 /* need close brace */
-#define PST_DBLPAREN 0x0010 /* double-paren parsing */
-#define PST_SUBSHELL 0x0020 /* ( ... ) subshell */
-#define PST_CMDSUBST 0x0040 /* $( ... ) command substitution */
-#define PST_CASESTMT 0x0080 /* parsing a case statement */
-#define PST_CONDCMD 0x0100 /* parsing a [[...]] command */
-#define PST_CONDEXPR 0x0200 /* parsing the guts of [[...]] */
-#define PST_ARITHFOR 0x0400 /* parsing an arithmetic for command */
-#define PST_ALEXPAND 0x0800 /* OK to expand aliases - unused */
-#define PST_CMDTOKEN 0x1000 /* command token OK - unused */
-#define PST_COMPASSIGN 0x2000 /* parsing x=(...) compound assignment */
-#define PST_ASSIGNOK 0x4000 /* assignment statement ok in this context */
-
-/* Initial size to allocate for tokens, and the
- amount to grow them by. */
-#define TOKEN_DEFAULT_INITIAL_SIZE 496
-#define TOKEN_DEFAULT_GROW_SIZE 512
-
-/* Should we call prompt_again? */
-#define SHOULD_PROMPT() \
- (interactive && (bash_input.type == st_stdin || bash_input.type == st_stream))
-
-#if defined (ALIAS)
-# define expanding_alias() (pushed_string_list && pushed_string_list->expander)
-#else
-# define expanding_alias() 0
-#endif
-
-/* The token currently being read. */
-static int current_token;
-
-/* The last read token, or NULL. read_token () uses this for context
- checking. */
-static int last_read_token;
-
-/* The token read prior to last_read_token. */
-static int token_before_that;
-
-/* The token read prior to token_before_that. */
-static int two_tokens_ago;
-
-/* The current parser state. */
-static int parser_state;
-
-/* Global var is non-zero when end of file has been reached. */
-int EOF_Reached = 0;
-
-#ifdef DEBUG
-static void
-debug_parser (i)
- int i;
-{
-#if YYDEBUG != 0
- yydebug = i;
-#endif
-}
-#endif
-
-/* yy_getc () returns the next available character from input or EOF.
- yy_ungetc (c) makes `c' the next character to read.
- init_yy_io (get, unget, type, location) makes the function GET the
- installed function for getting the next character, makes UNGET the
- installed function for un-getting a character, sets the type of stream
- (either string or file) from TYPE, and makes LOCATION point to where
- the input is coming from. */
-
-/* Unconditionally returns end-of-file. */
-int
-return_EOF ()
-{
- return (EOF);
-}
-
-/* Variable containing the current get and unget functions.
- See ./input.h for a clearer description. */
-BASH_INPUT bash_input;
-
-/* Set all of the fields in BASH_INPUT to NULL. Free bash_input.name if it
- is non-null, avoiding a memory leak. */
-void
-initialize_bash_input ()
-{
- bash_input.type = st_none;
- FREE (bash_input.name);
- bash_input.name = (char *)NULL;
- bash_input.location.file = (FILE *)NULL;
- bash_input.location.string = (char *)NULL;
- bash_input.getter = (sh_cget_func_t *)NULL;
- bash_input.ungetter = (sh_cunget_func_t *)NULL;
-}
-
-/* Set the contents of the current bash input stream from
- GET, UNGET, TYPE, NAME, and LOCATION. */
-void
-init_yy_io (get, unget, type, name, location)
- sh_cget_func_t *get;
- sh_cunget_func_t *unget;
- enum stream_type type;
- const char *name;
- INPUT_STREAM location;
-{
- bash_input.type = type;
- FREE (bash_input.name);
- bash_input.name = name ? savestring (name) : (char *)NULL;
-
- /* XXX */
-#if defined (CRAY)
- memcpy((char *)&bash_input.location.string, (char *)&location.string, sizeof(location));
-#else
- bash_input.location = location;
-#endif
- bash_input.getter = get;
- bash_input.ungetter = unget;
-}
-
-char *
-yy_input_name ()
-{
- return (bash_input.name ? bash_input.name : "stdin");
-}
-
-/* Call this to get the next character of input. */
-static int
-yy_getc ()
-{
- return (*(bash_input.getter)) ();
-}
-
-/* Call this to unget C. That is, to make C the next character
- to be read. */
-static int
-yy_ungetc (c)
- int c;
-{
- return (*(bash_input.ungetter)) (c);
-}
-
-#if defined (BUFFERED_INPUT)
-#ifdef INCLUDE_UNUSED
-int
-input_file_descriptor ()
-{
- switch (bash_input.type)
- {
- case st_stream:
- return (fileno (bash_input.location.file));
- case st_bstream:
- return (bash_input.location.buffered_fd);
- case st_stdin:
- default:
- return (fileno (stdin));
- }
-}
-#endif
-#endif /* BUFFERED_INPUT */
-
-/* **************************************************************** */
-/* */
-/* Let input be read from readline (). */
-/* */
-/* **************************************************************** */
-
-#if defined (READLINE)
-char *current_readline_prompt = (char *)NULL;
-char *current_readline_line = (char *)NULL;
-int current_readline_line_index = 0;
-
-static int
-yy_readline_get ()
-{
- SigHandler *old_sigint;
- int line_len;
- unsigned char c;
-
- if (!current_readline_line)
- {
- if (!bash_readline_initialized)
- initialize_readline ();
-
-#if defined (JOB_CONTROL)
- if (job_control)
- give_terminal_to (shell_pgrp, 0);
-#endif /* JOB_CONTROL */
-
- old_sigint = (SigHandler *)NULL;
- if (signal_is_ignored (SIGINT) == 0)
- {
- old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
- interrupt_immediately++;
- }
-
- current_readline_line = readline (current_readline_prompt ?
- current_readline_prompt : "");
-
- if (signal_is_ignored (SIGINT) == 0 && old_sigint)
- {
- interrupt_immediately--;
- set_signal_handler (SIGINT, old_sigint);
- }
-
-#if 0
- /* Reset the prompt to the decoded value of prompt_string_pointer. */
- reset_readline_prompt ();
-#endif
-
- if (current_readline_line == 0)
- return (EOF);
-
- current_readline_line_index = 0;
- line_len = strlen (current_readline_line);
-
- current_readline_line = (char *)xrealloc (current_readline_line, 2 + line_len);
- current_readline_line[line_len++] = '\n';
- current_readline_line[line_len] = '\0';
- }
-
- if (current_readline_line[current_readline_line_index] == 0)
- {
- free (current_readline_line);
- current_readline_line = (char *)NULL;
- return (yy_readline_get ());
- }
- else
- {
- c = current_readline_line[current_readline_line_index++];
- return (c);
- }
-}
-
-static int
-yy_readline_unget (c)
- int c;
-{
- if (current_readline_line_index && current_readline_line)
- current_readline_line[--current_readline_line_index] = c;
- return (c);
-}
-
-void
-with_input_from_stdin ()
-{
- INPUT_STREAM location;
-
- if (bash_input.type != st_stdin && stream_on_stack (st_stdin) == 0)
- {
- location.string = current_readline_line;
- init_yy_io (yy_readline_get, yy_readline_unget,
- st_stdin, "readline stdin", location);
- }
-}
-
-#else /* !READLINE */
-
-void
-with_input_from_stdin ()
-{
- with_input_from_stream (stdin, "stdin");
-}
-#endif /* !READLINE */
-
-/* **************************************************************** */
-/* */
-/* Let input come from STRING. STRING is zero terminated. */
-/* */
-/* **************************************************************** */
-
-static int
-yy_string_get ()
-{
- register char *string;
- register unsigned char c;
-
- string = bash_input.location.string;
-
- /* If the string doesn't exist, or is empty, EOF found. */
- if (string && *string)
- {
- c = *string++;
- bash_input.location.string = string;
- return (c);
- }
- else
- return (EOF);
-}
-
-static int
-yy_string_unget (c)
- int c;
-{
- *(--bash_input.location.string) = c;
- return (c);
-}
-
-void
-with_input_from_string (string, name)
- char *string;
- const char *name;
-{
- INPUT_STREAM location;
-
- location.string = string;
- init_yy_io (yy_string_get, yy_string_unget, st_string, name, location);
-}
-
-/* **************************************************************** */
-/* */
-/* Let input come from STREAM. */
-/* */
-/* **************************************************************** */
-
-/* These two functions used to test the value of the HAVE_RESTARTABLE_SYSCALLS
- define, and just use getc/ungetc if it was defined, but since bash
- installs its signal handlers without the SA_RESTART flag, some signals
- (like SIGCHLD, SIGWINCH, etc.) received during a read(2) will not cause
- the read to be restarted. We need to restart it ourselves. */
-
-static int
-yy_stream_get ()
-{
- int result;
-
- result = EOF;
- if (bash_input.location.file)
- {
- if (interactive)
- interrupt_immediately++;
- result = getc_with_restart (bash_input.location.file);
- if (interactive)
- interrupt_immediately--;
- }
- return (result);
-}
-
-static int
-yy_stream_unget (c)
- int c;
-{
- return (ungetc_with_restart (c, bash_input.location.file));
-}
-
-void
-with_input_from_stream (stream, name)
- FILE *stream;
- const char *name;
-{
- INPUT_STREAM location;
-
- location.file = stream;
- init_yy_io (yy_stream_get, yy_stream_unget, st_stream, name, location);
-}
-
-typedef struct stream_saver {
- struct stream_saver *next;
- BASH_INPUT bash_input;
- int line;
-#if defined (BUFFERED_INPUT)
- BUFFERED_STREAM *bstream;
-#endif /* BUFFERED_INPUT */
-} STREAM_SAVER;
-
-/* The globally known line number. */
-int line_number = 0;
-
-#if defined (COND_COMMAND)
-static int cond_lineno;
-static int cond_token;
-#endif
-
-STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL;
-
-void
-push_stream (reset_lineno)
- int reset_lineno;
-{
- STREAM_SAVER *saver = (STREAM_SAVER *)xmalloc (sizeof (STREAM_SAVER));
-
- xbcopy ((char *)&bash_input, (char *)&(saver->bash_input), sizeof (BASH_INPUT));
-
-#if defined (BUFFERED_INPUT)
- saver->bstream = (BUFFERED_STREAM *)NULL;
- /* If we have a buffered stream, clear out buffers[fd]. */
- if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
- saver->bstream = set_buffered_stream (bash_input.location.buffered_fd,
- (BUFFERED_STREAM *)NULL);
-#endif /* BUFFERED_INPUT */
-
- saver->line = line_number;
- bash_input.name = (char *)NULL;
- saver->next = stream_list;
- stream_list = saver;
- EOF_Reached = 0;
- if (reset_lineno)
- line_number = 0;
-}
-
-void
-pop_stream ()
-{
- if (!stream_list)
- EOF_Reached = 1;
- else
- {
- STREAM_SAVER *saver = stream_list;
-
- EOF_Reached = 0;
- stream_list = stream_list->next;
-
- init_yy_io (saver->bash_input.getter,
- saver->bash_input.ungetter,
- saver->bash_input.type,
- saver->bash_input.name,
- saver->bash_input.location);
-
-#if defined (BUFFERED_INPUT)
- /* If we have a buffered stream, restore buffers[fd]. */
- /* If the input file descriptor was changed while this was on the
- save stack, update the buffered fd to the new file descriptor and
- re-establish the buffer <-> bash_input fd correspondence. */
- if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
- {
- if (bash_input_fd_changed)
- {
- bash_input_fd_changed = 0;
- if (default_buffered_input >= 0)
- {
- bash_input.location.buffered_fd = default_buffered_input;
- saver->bstream->b_fd = default_buffered_input;
- SET_CLOSE_ON_EXEC (default_buffered_input);
- }
- }
- /* XXX could free buffered stream returned as result here. */
- set_buffered_stream (bash_input.location.buffered_fd, saver->bstream);
- }
-#endif /* BUFFERED_INPUT */
-
- line_number = saver->line;
-
- FREE (saver->bash_input.name);
- free (saver);
- }
-}
-
-/* Return 1 if a stream of type TYPE is saved on the stack. */
-int
-stream_on_stack (type)
- enum stream_type type;
-{
- register STREAM_SAVER *s;
-
- for (s = stream_list; s; s = s->next)
- if (s->bash_input.type == type)
- return 1;
- return 0;
-}
-
-/* Save the current token state and return it in a malloced array. */
-int *
-save_token_state ()
-{
- int *ret;
-
- ret = (int *)xmalloc (3 * sizeof (int));
- ret[0] = last_read_token;
- ret[1] = token_before_that;
- ret[2] = two_tokens_ago;
- return ret;
-}
-
-void
-restore_token_state (ts)
- int *ts;
-{
- if (ts == 0)
- return;
- last_read_token = ts[0];
- token_before_that = ts[1];
- two_tokens_ago = ts[2];
-}
-
-/*
- * This is used to inhibit alias expansion and reserved word recognition
- * inside case statement pattern lists. A `case statement pattern list' is:
- *
- * everything between the `in' in a `case word in' and the next ')'
- * or `esac'
- * everything between a `;;' and the next `)' or `esac'
- */
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
-
-#define END_OF_ALIAS 0
-
-/*
- * Pseudo-global variables used in implementing token-wise alias expansion.
- */
-
-/*
- * Pushing and popping strings. This works together with shell_getc to
- * implement alias expansion on a per-token basis.
- */
-
-typedef struct string_saver {
- struct string_saver *next;
- int expand_alias; /* Value to set expand_alias to when string is popped. */
- char *saved_line;
-#if defined (ALIAS)
- alias_t *expander; /* alias that caused this line to be pushed. */
-#endif
- int saved_line_size, saved_line_index, saved_line_terminator;
-} STRING_SAVER;
-
-STRING_SAVER *pushed_string_list = (STRING_SAVER *)NULL;
-
-/*
- * Push the current shell_input_line onto a stack of such lines and make S
- * the current input. Used when expanding aliases. EXPAND is used to set
- * the value of expand_next_token when the string is popped, so that the
- * word after the alias in the original line is handled correctly when the
- * alias expands to multiple words. TOKEN is the token that was expanded
- * into S; it is saved and used to prevent infinite recursive expansion.
- */
-static void
-push_string (s, expand, ap)
- char *s;
- int expand;
- alias_t *ap;
-{
- STRING_SAVER *temp = (STRING_SAVER *)xmalloc (sizeof (STRING_SAVER));
-
- temp->expand_alias = expand;
- temp->saved_line = shell_input_line;
- temp->saved_line_size = shell_input_line_size;
- temp->saved_line_index = shell_input_line_index;
- temp->saved_line_terminator = shell_input_line_terminator;
-#if defined (ALIAS)
- temp->expander = ap;
-#endif
- temp->next = pushed_string_list;
- pushed_string_list = temp;
-
-#if defined (ALIAS)
- if (ap)
- ap->flags |= AL_BEINGEXPANDED;
-#endif
-
- shell_input_line = s;
- shell_input_line_size = strlen (s);
- shell_input_line_index = 0;
- shell_input_line_terminator = '\0';
-#if 0
- parser_state &= ~PST_ALEXPNEXT; /* XXX */
-#endif
-
- set_line_mbstate ();
-}
-
-/*
- * Make the top of the pushed_string stack be the current shell input.
- * Only called when there is something on the stack. Called from shell_getc
- * when it thinks it has consumed the string generated by an alias expansion
- * and needs to return to the original input line.
- */
-static void
-pop_string ()
-{
- STRING_SAVER *t;
-
- FREE (shell_input_line);
- shell_input_line = pushed_string_list->saved_line;
- shell_input_line_index = pushed_string_list->saved_line_index;
- shell_input_line_size = pushed_string_list->saved_line_size;
- shell_input_line_terminator = pushed_string_list->saved_line_terminator;
-
- if (pushed_string_list->expand_alias)
- parser_state |= PST_ALEXPNEXT;
- else
- parser_state &= ~PST_ALEXPNEXT;
-
- t = pushed_string_list;
- pushed_string_list = pushed_string_list->next;
-
-#if defined (ALIAS)
- if (t->expander)
- t->expander->flags &= ~AL_BEINGEXPANDED;
-#endif
-
- free ((char *)t);
-
- set_line_mbstate ();
-}
-
-static void
-free_string_list ()
-{
- register STRING_SAVER *t, *t1;
-
- for (t = pushed_string_list; t; )
- {
- t1 = t->next;
- FREE (t->saved_line);
-#if defined (ALIAS)
- if (t->expander)
- t->expander->flags &= ~AL_BEINGEXPANDED;
-#endif
- free ((char *)t);
- t = t1;
- }
- pushed_string_list = (STRING_SAVER *)NULL;
-}
-
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
-void
-free_pushed_string_input ()
-{
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- free_string_list ();
-#endif
-}
-
-/* Return a line of text, taken from wherever yylex () reads input.
- If there is no more input, then we return NULL. If REMOVE_QUOTED_NEWLINE
- is non-zero, we remove unquoted \<newline> pairs. This is used by
- read_secondary_line to read here documents. */
-static char *
-read_a_line (remove_quoted_newline)
- int remove_quoted_newline;
-{
- static char *line_buffer = (char *)NULL;
- static int buffer_size = 0;
- int indx = 0, c, peekc, pass_next;
-
-#if defined (READLINE)
- if (no_line_editing && SHOULD_PROMPT ())
-#else
- if (SHOULD_PROMPT ())
-#endif
- print_prompt ();
-
- pass_next = 0;
- while (1)
- {
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- c = yy_getc ();
-
- /* Ignore null bytes in input. */
- if (c == 0)
- {
-#if 0
- internal_warning ("read_a_line: ignored null byte in input");
-#endif
- continue;
- }
-
- /* If there is no more input, then we return NULL. */
- if (c == EOF)
- {
- if (interactive && bash_input.type == st_stream)
- clearerr (stdin);
- if (indx == 0)
- return ((char *)NULL);
- c = '\n';
- }
-
- /* `+2' in case the final character in the buffer is a newline. */
- RESIZE_MALLOCED_BUFFER (line_buffer, indx, 2, buffer_size, 128);
-
- /* IF REMOVE_QUOTED_NEWLINES is non-zero, we are reading a
- here document with an unquoted delimiter. In this case,
- the line will be expanded as if it were in double quotes.
- We allow a backslash to escape the next character, but we
- need to treat the backslash specially only if a backslash
- quoting a backslash-newline pair appears in the line. */
- if (pass_next)
- {
- line_buffer[indx++] = c;
- pass_next = 0;
- }
- else if (c == '\\' && remove_quoted_newline)
- {
- peekc = yy_getc ();
- if (peekc == '\n')
- {
- line_number++;
- continue; /* Make the unquoted \<newline> pair disappear. */
- }
- else
- {
- yy_ungetc (peekc);
- pass_next = 1;
- line_buffer[indx++] = c; /* Preserve the backslash. */
- }
- }
- else
- line_buffer[indx++] = c;
-
- if (c == '\n')
- {
- line_buffer[indx] = '\0';
- return (line_buffer);
- }
- }
-}
-
-/* Return a line as in read_a_line (), but insure that the prompt is
- the secondary prompt. This is used to read the lines of a here
- document. REMOVE_QUOTED_NEWLINE is non-zero if we should remove
- newlines quoted with backslashes while reading the line. It is
- non-zero unless the delimiter of the here document was quoted. */
-char *
-read_secondary_line (remove_quoted_newline)
- int remove_quoted_newline;
-{
- prompt_string_pointer = &ps2_prompt;
- if (SHOULD_PROMPT())
- prompt_again ();
- return (read_a_line (remove_quoted_newline));
-}
-
-/* **************************************************************** */
-/* */
-/* YYLEX () */
-/* */
-/* **************************************************************** */
-
-/* Reserved words. These are only recognized as the first word of a
- command. */
-STRING_INT_ALIST word_token_alist[] = {
- { "if", IF },
- { "then", THEN },
- { "else", ELSE },
- { "elif", ELIF },
- { "fi", FI },
- { "case", CASE },
- { "esac", ESAC },
- { "for", FOR },
-#if defined (SELECT_COMMAND)
- { "select", SELECT },
-#endif
- { "while", WHILE },
- { "until", UNTIL },
- { "do", DO },
- { "done", DONE },
- { "in", IN },
- { "function", FUNCTION },
-#if defined (COMMAND_TIMING)
- { "time", TIME },
-#endif
- { "{", '{' },
- { "}", '}' },
- { "!", BANG },
-#if defined (COND_COMMAND)
- { "[[", COND_START },
- { "]]", COND_END },
-#endif
- { (char *)NULL, 0}
-};
-
-/* other tokens that can be returned by read_token() */
-STRING_INT_ALIST other_token_alist[] = {
- /* Multiple-character tokens with special values */
- { "-p", TIMEOPT },
- { "&&", AND_AND },
- { "||", OR_OR },
- { ">>", GREATER_GREATER },
- { "<<", LESS_LESS },
- { "<&", LESS_AND },
- { ">&", GREATER_AND },
- { ";;", SEMI_SEMI },
- { "<<-", LESS_LESS_MINUS },
- { "<<<", LESS_LESS_LESS },
- { "&>", AND_GREATER },
- { "<>", LESS_GREATER },
- { ">|", GREATER_BAR },
- { "EOF", yacc_EOF },
- /* Tokens whose value is the character itself */
- { ">", '>' },
- { "<", '<' },
- { "-", '-' },
- { "{", '{' },
- { "}", '}' },
- { ";", ';' },
- { "(", '(' },
- { ")", ')' },
- { "|", '|' },
- { "&", '&' },
- { "newline", '\n' },
- { (char *)NULL, 0}
-};
-
-/* others not listed here:
- WORD look at yylval.word
- ASSIGNMENT_WORD look at yylval.word
- NUMBER look at yylval.number
- ARITH_CMD look at yylval.word_list
- ARITH_FOR_EXPRS look at yylval.word_list
- COND_CMD look at yylval.command
-*/
-
-/* These are used by read_token_word, but appear up here so that shell_getc
- can use them to decide when to add otherwise blank lines to the history. */
-
-/* The primary delimiter stack. */
-struct dstack dstack = { (char *)NULL, 0, 0 };
-
-/* A temporary delimiter stack to be used when decoding prompt strings.
- This is needed because command substitutions in prompt strings (e.g., PS2)
- can screw up the parser's quoting state. */
-static struct dstack temp_dstack = { (char *)NULL, 0, 0 };
-
-/* Macro for accessing the top delimiter on the stack. Returns the
- delimiter or zero if none. */
-#define current_delimiter(ds) \
- (ds.delimiter_depth ? ds.delimiters[ds.delimiter_depth - 1] : 0)
-
-#define push_delimiter(ds, character) \
- do \
- { \
- if (ds.delimiter_depth + 2 > ds.delimiter_space) \
- ds.delimiters = (char *)xrealloc \
- (ds.delimiters, (ds.delimiter_space += 10) * sizeof (char)); \
- ds.delimiters[ds.delimiter_depth] = character; \
- ds.delimiter_depth++; \
- } \
- while (0)
-
-#define pop_delimiter(ds) ds.delimiter_depth--
-
-/* Return the next shell input character. This always reads characters
- from shell_input_line; when that line is exhausted, it is time to
- read the next line. This is called by read_token when the shell is
- processing normal command input. */
-
-/* This implements one-character lookahead/lookbehind across physical input
- lines, to avoid something being lost because it's pushed back with
- shell_ungetc when we're at the start of a line. */
-static int eol_ungetc_lookahead = 0;
-
-static int
-shell_getc (remove_quoted_newline)
- int remove_quoted_newline;
-{
- register int i;
- int c;
- unsigned char uc;
- static int mustpop = 0;
-
- QUIT;
-
- if (eol_ungetc_lookahead)
- {
- c = eol_ungetc_lookahead;
- eol_ungetc_lookahead = 0;
- return (c);
- }
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- /* If shell_input_line[shell_input_line_index] == 0, but there is
- something on the pushed list of strings, then we don't want to go
- off and get another line. We let the code down below handle it. */
-
- if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) &&
- (pushed_string_list == (STRING_SAVER *)NULL)))
-#else /* !ALIAS && !DPAREN_ARITHMETIC */
- if (!shell_input_line || !shell_input_line[shell_input_line_index])
-#endif /* !ALIAS && !DPAREN_ARITHMETIC */
- {
- line_number++;
-
- restart_read:
-
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- i = 0;
- shell_input_line_terminator = 0;
-
- /* If the shell is interatctive, but not currently printing a prompt
- (interactive_shell && interactive == 0), we don't want to print
- notifies or cleanup the jobs -- we want to defer it until we do
- print the next prompt. */
- if (interactive_shell == 0 || SHOULD_PROMPT())
- {
-#if defined (JOB_CONTROL)
- /* This can cause a problem when reading a command as the result
- of a trap, when the trap is called from flush_child. This call
- had better not cause jobs to disappear from the job table in
- that case, or we will have big trouble. */
- notify_and_cleanup ();
-#else /* !JOB_CONTROL */
- cleanup_dead_jobs ();
-#endif /* !JOB_CONTROL */
- }
-
-#if defined (READLINE)
- if (no_line_editing && SHOULD_PROMPT())
-#else
- if (SHOULD_PROMPT())
-#endif
- print_prompt ();
-
- if (bash_input.type == st_stream)
- clearerr (stdin);
-
- while (1)
- {
- c = yy_getc ();
-
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- if (c == '\0')
- {
-#if 0
- internal_warning ("shell_getc: ignored null byte in input");
-#endif
- continue;
- }
-
- RESIZE_MALLOCED_BUFFER (shell_input_line, i, 2, shell_input_line_size, 256);
-
- if (c == EOF)
- {
- if (bash_input.type == st_stream)
- clearerr (stdin);
-
- if (i == 0)
- shell_input_line_terminator = EOF;
-
- shell_input_line[i] = '\0';
- break;
- }
-
- shell_input_line[i++] = c;
-
- if (c == '\n')
- {
- shell_input_line[--i] = '\0';
- current_command_line_count++;
- break;
- }
- }
-
- shell_input_line_index = 0;
- shell_input_line_len = i; /* == strlen (shell_input_line) */
-
- set_line_mbstate ();
-
-#if defined (HISTORY)
- if (remember_on_history && shell_input_line && shell_input_line[0])
- {
- char *expansions;
-# if defined (BANG_HISTORY)
- int old_hist;
-
- /* If the current delimiter is a single quote, we should not be
- performing history expansion, even if we're on a different
- line from the original single quote. */
- old_hist = history_expansion_inhibited;
- if (current_delimiter (dstack) == '\'')
- history_expansion_inhibited = 1;
-# endif
- expansions = pre_process_line (shell_input_line, 1, 1);
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = old_hist;
-# endif
- if (expansions != shell_input_line)
- {
- free (shell_input_line);
- shell_input_line = expansions;
- shell_input_line_len = shell_input_line ?
- strlen (shell_input_line) : 0;
- if (!shell_input_line_len)
- current_command_line_count--;
-
- /* We have to force the xrealloc below because we don't know
- the true allocated size of shell_input_line anymore. */
- shell_input_line_size = shell_input_line_len;
-
- set_line_mbstate ();
- }
- }
- /* Try to do something intelligent with blank lines encountered while
- entering multi-line commands. XXX - this is grotesque */
- else if (remember_on_history && shell_input_line &&
- shell_input_line[0] == '\0' &&
- current_command_line_count > 1)
- {
- if (current_delimiter (dstack))
- /* We know shell_input_line[0] == 0 and we're reading some sort of
- quoted string. This means we've got a line consisting of only
- a newline in a quoted string. We want to make sure this line
- gets added to the history. */
- maybe_add_history (shell_input_line);
- else
- {
- char *hdcs;
- hdcs = history_delimiting_chars ();
- if (hdcs && hdcs[0] == ';')
- maybe_add_history (shell_input_line);
- }
- }
-
-#endif /* HISTORY */
-
- if (shell_input_line)
- {
- /* Lines that signify the end of the shell's input should not be
- echoed. */
- if (echo_input_at_read && (shell_input_line[0] ||
- shell_input_line_terminator != EOF))
- fprintf (stderr, "%s\n", shell_input_line);
- }
- else
- {
- shell_input_line_size = 0;
- prompt_string_pointer = &current_prompt_string;
- if (SHOULD_PROMPT ())
- prompt_again ();
- goto restart_read;
- }
-
- /* Add the newline to the end of this string, iff the string does
- not already end in an EOF character. */
- if (shell_input_line_terminator != EOF)
- {
- if (shell_input_line_len + 3 > shell_input_line_size)
- shell_input_line = (char *)xrealloc (shell_input_line,
- 1 + (shell_input_line_size += 2));
-
- shell_input_line[shell_input_line_len] = '\n';
- shell_input_line[shell_input_line_len + 1] = '\0';
-
- set_line_mbstate ();
- }
- }
-
- uc = shell_input_line[shell_input_line_index];
-
- if (uc)
- shell_input_line_index++;
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- /* If UC is NULL, we have reached the end of the current input string. If
- pushed_string_list is non-empty, it's time to pop to the previous string
- because we have fully consumed the result of the last alias expansion.
- Do it transparently; just return the next character of the string popped
- to. */
- if (!uc && (pushed_string_list != (STRING_SAVER *)NULL))
- {
- pop_string ();
- uc = shell_input_line[shell_input_line_index];
- if (uc)
- shell_input_line_index++;
- }
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
- if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n')
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- line_number++;
- goto restart_read;
- }
-
- if (!uc && shell_input_line_terminator == EOF)
- return ((shell_input_line_index != 0) ? '\n' : EOF);
-
- return (uc);
-}
-
-/* Put C back into the input for the shell. This might need changes for
- HANDLE_MULTIBYTE around EOLs. Since we (currently) never push back a
- character different than we read, shell_input_line_property doesn't need
- to change when manipulating shell_input_line. The define for
- last_shell_getc_is_singlebyte should take care of it, though. */
-static void
-shell_ungetc (c)
- int c;
-{
- if (shell_input_line && shell_input_line_index)
- shell_input_line[--shell_input_line_index] = c;
- else
- eol_ungetc_lookahead = c;
-}
-
-#ifdef INCLUDE_UNUSED
-/* Back the input pointer up by one, effectively `ungetting' a character. */
-static void
-shell_ungetchar ()
-{
- if (shell_input_line && shell_input_line_index)
- shell_input_line_index--;
-}
-#endif
-
-/* Discard input until CHARACTER is seen, then push that character back
- onto the input stream. */
-static void
-discard_until (character)
- int character;
-{
- int c;
-
- while ((c = shell_getc (0)) != EOF && c != character)
- ;
-
- if (c != EOF)
- shell_ungetc (c);
-}
-
-void
-execute_prompt_command (command)
- char *command;
-{
- char *last_lastarg;
- sh_parser_state_t ps;
-
- save_parser_state (&ps);
- last_lastarg = get_string_value ("_");
- if (last_lastarg)
- last_lastarg = savestring (last_lastarg);
-
- parse_and_execute (savestring (command), "PROMPT_COMMAND", SEVAL_NONINT|SEVAL_NOHIST);
-
- restore_parser_state (&ps);
- bind_variable ("_", last_lastarg, 0);
- FREE (last_lastarg);
-
- if (token_to_read == '\n') /* reset_parser was called */
- token_to_read = 0;
-}
-
-/* Place to remember the token. We try to keep the buffer
- at a reasonable size, but it can grow. */
-static char *token = (char *)NULL;
-
-/* Current size of the token buffer. */
-static int token_buffer_size;
-
-/* Command to read_token () explaining what we want it to do. */
-#define READ 0
-#define RESET 1
-#define prompt_is_ps1 \
- (!prompt_string_pointer || prompt_string_pointer == &ps1_prompt)
-
-/* Function for yyparse to call. yylex keeps track of
- the last two tokens read, and calls read_token. */
-static int
-yylex ()
-{
- if (interactive && (current_token == 0 || current_token == '\n'))
- {
- /* Before we print a prompt, we might have to check mailboxes.
- We do this only if it is time to do so. Notice that only here
- is the mail alarm reset; nothing takes place in check_mail ()
- except the checking of mail. Please don't change this. */
- if (prompt_is_ps1 && time_to_check_mail ())
- {
- check_mail ();
- reset_mail_timer ();
- }
-
- /* Avoid printing a prompt if we're not going to read anything, e.g.
- after resetting the parser with read_token (RESET). */
- if (token_to_read == 0 && SHOULD_PROMPT ())
- prompt_again ();
- }
-
- two_tokens_ago = token_before_that;
- token_before_that = last_read_token;
- last_read_token = current_token;
- current_token = read_token (READ);
- return (current_token);
-}
-
-/* When non-zero, we have read the required tokens
- which allow ESAC to be the next one read. */
-static int esacs_needed_count;
-
-void
-gather_here_documents ()
-{
- int r = 0;
- while (need_here_doc)
- {
- make_here_document (redir_stack[r++]);
- need_here_doc--;
- }
-}
-
-/* When non-zero, an open-brace used to create a group is awaiting a close
- brace partner. */
-static int open_brace_count;
-
-#define command_token_position(token) \
- (((token) == ASSIGNMENT_WORD) || \
- ((token) != SEMI_SEMI && reserved_word_acceptable(token)))
-
-#define assignment_acceptable(token) \
- (command_token_position(token) && ((parser_state & PST_CASEPAT) == 0))
-
-/* Check to see if TOKEN is a reserved word and return the token
- value if it is. */
-#define CHECK_FOR_RESERVED_WORD(tok) \
- do { \
- if (!dollar_present && !quoted && \
- reserved_word_acceptable (last_read_token)) \
- { \
- int i; \
- for (i = 0; word_token_alist[i].word != (char *)NULL; i++) \
- if (STREQ (tok, word_token_alist[i].word)) \
- { \
- if ((parser_state & PST_CASEPAT) && (word_token_alist[i].token != ESAC)) \
- break; \
- if (word_token_alist[i].token == TIME && time_command_acceptable () == 0) \
- break; \
- if (word_token_alist[i].token == ESAC) \
- parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \
- else if (word_token_alist[i].token == CASE) \
- parser_state |= PST_CASESTMT; \
- else if (word_token_alist[i].token == COND_END) \
- parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \
- else if (word_token_alist[i].token == COND_START) \
- parser_state |= PST_CONDCMD; \
- else if (word_token_alist[i].token == '{') \
- open_brace_count++; \
- else if (word_token_alist[i].token == '}' && open_brace_count) \
- open_brace_count--; \
- return (word_token_alist[i].token); \
- } \
- } \
- } while (0)
-
-#if defined (ALIAS)
-
- /* OK, we have a token. Let's try to alias expand it, if (and only if)
- it's eligible.
-
- It is eligible for expansion if EXPAND_ALIASES is set, and
- the token is unquoted and the last token read was a command
- separator (or expand_next_token is set), and we are currently
- processing an alias (pushed_string_list is non-empty) and this
- token is not the same as the current or any previously
- processed alias.
-
- Special cases that disqualify:
- In a pattern list in a case statement (parser_state & PST_CASEPAT). */
-
-static char *
-mk_alexpansion (s)
- char *s;
-{
- int l;
- char *r;
-
- l = strlen (s);
- r = xmalloc (l + 2);
- strcpy (r, s);
- if (r[l -1] != ' ')
- r[l++] = ' ';
- r[l] = '\0';
- return r;
-}
-
-static int
-alias_expand_token (tokstr)
- char *tokstr;
-{
- char *expanded;
- alias_t *ap;
-
- if (((parser_state & PST_ALEXPNEXT) || command_token_position (last_read_token)) &&
- (parser_state & PST_CASEPAT) == 0)
- {
- ap = find_alias (tokstr);
-
- /* Currently expanding this token. */
- if (ap && (ap->flags & AL_BEINGEXPANDED))
- return (NO_EXPANSION);
-
- /* mk_alexpansion puts an extra space on the end of the alias expansion,
- so the lookahead by the parser works right. If this gets changed,
- make sure the code in shell_getc that deals with reaching the end of
- an expanded alias is changed with it. */
- expanded = ap ? mk_alexpansion (ap->value) : (char *)NULL;
-
- if (expanded)
- {
- push_string (expanded, ap->flags & AL_EXPANDNEXT, ap);
- return (RE_READ_TOKEN);
- }
- else
- /* This is an eligible token that does not have an expansion. */
- return (NO_EXPANSION);
- }
- return (NO_EXPANSION);
-}
-#endif /* ALIAS */
-
-static int
-time_command_acceptable ()
-{
-#if defined (COMMAND_TIMING)
- switch (last_read_token)
- {
- case 0:
- case ';':
- case '\n':
- case AND_AND:
- case OR_OR:
- case '&':
- case DO:
- case THEN:
- case ELSE:
- case '{': /* } */
- case '(': /* ) */
- return 1;
- default:
- return 0;
- }
-#else
- return 0;
-#endif /* COMMAND_TIMING */
-}
-
-/* Handle special cases of token recognition:
- IN is recognized if the last token was WORD and the token
- before that was FOR or CASE or SELECT.
-
- DO is recognized if the last token was WORD and the token
- before that was FOR or SELECT.
-
- ESAC is recognized if the last token caused `esacs_needed_count'
- to be set
-
- `{' is recognized if the last token as WORD and the token
- before that was FUNCTION, or if we just parsed an arithmetic
- `for' command.
-
- `}' is recognized if there is an unclosed `{' present.
-
- `-p' is returned as TIMEOPT if the last read token was TIME.
-
- ']]' is returned as COND_END if the parser is currently parsing
- a conditional expression ((parser_state & PST_CONDEXPR) != 0)
-
- `time' is returned as TIME if and only if it is immediately
- preceded by one of `;', `\n', `||', `&&', or `&'.
-*/
-
-static int
-special_case_tokens (tokstr)
- char *tokstr;
-{
- if ((last_read_token == WORD) &&
-#if defined (SELECT_COMMAND)
- ((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
-#else
- ((token_before_that == FOR) || (token_before_that == CASE)) &&
-#endif
- (tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
- {
- if (token_before_that == CASE)
- {
- parser_state |= PST_CASEPAT;
- esacs_needed_count++;
- }
- return (IN);
- }
-
- if (last_read_token == WORD &&
-#if defined (SELECT_COMMAND)
- (token_before_that == FOR || token_before_that == SELECT) &&
-#else
- (token_before_that == FOR) &&
-#endif
- (tokstr[0] == 'd' && tokstr[1] == 'o' && tokstr[2] == '\0'))
- return (DO);
-
- /* Ditto for ESAC in the CASE case.
- Specifically, this handles "case word in esac", which is a legal
- construct, certainly because someone will pass an empty arg to the
- case construct, and we don't want it to barf. Of course, we should
- insist that the case construct has at least one pattern in it, but
- the designers disagree. */
- if (esacs_needed_count)
- {
- esacs_needed_count--;
- if (STREQ (tokstr, "esac"))
- {
- parser_state &= ~PST_CASEPAT;
- return (ESAC);
- }
- }
-
- /* The start of a shell function definition. */
- if (parser_state & PST_ALLOWOPNBRC)
- {
- parser_state &= ~PST_ALLOWOPNBRC;
- if (tokstr[0] == '{' && tokstr[1] == '\0') /* } */
- {
- open_brace_count++;
- function_bstart = line_number;
- return ('{'); /* } */
- }
- }
-
- /* We allow a `do' after a for ((...)) without an intervening
- list_terminator */
- if (last_read_token == ARITH_FOR_EXPRS && tokstr[0] == 'd' && tokstr[1] == 'o' && !tokstr[2])
- return (DO);
- if (last_read_token == ARITH_FOR_EXPRS && tokstr[0] == '{' && tokstr[1] == '\0') /* } */
- {
- open_brace_count++;
- return ('{'); /* } */
- }
-
- if (open_brace_count && reserved_word_acceptable (last_read_token) && tokstr[0] == '}' && !tokstr[1])
- {
- open_brace_count--; /* { */
- return ('}');
- }
-
-#if defined (COMMAND_TIMING)
- /* Handle -p after `time'. */
- if (last_read_token == TIME && tokstr[0] == '-' && tokstr[1] == 'p' && !tokstr[2])
- return (TIMEOPT);
-#endif
-
-#if 0
-#if defined (COMMAND_TIMING)
- if (STREQ (token, "time") && ((parser_state & PST_CASEPAT) == 0) && time_command_acceptable ())
- return (TIME);
-#endif /* COMMAND_TIMING */
-#endif
-
-#if defined (COND_COMMAND) /* [[ */
- if ((parser_state & PST_CONDEXPR) && tokstr[0] == ']' && tokstr[1] == ']' && tokstr[2] == '\0')
- return (COND_END);
-#endif
-
- return (-1);
-}
-
-/* Called from shell.c when Control-C is typed at top level. Or
- by the error rule at top level. */
-void
-reset_parser ()
-{
- dstack.delimiter_depth = 0; /* No delimiters found so far. */
- open_brace_count = 0;
-
- parser_state = 0;
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- if (pushed_string_list)
- free_string_list ();
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
- if (shell_input_line)
- {
- free (shell_input_line);
- shell_input_line = (char *)NULL;
- shell_input_line_size = shell_input_line_index = 0;
- }
-
- FREE (word_desc_to_read);
- word_desc_to_read = (WORD_DESC *)NULL;
-
- last_read_token = '\n';
- token_to_read = '\n';
-}
-
-/* Read the next token. Command can be READ (normal operation) or
- RESET (to normalize state). */
-static int
-read_token (command)
- int command;
-{
- int character; /* Current character. */
- int peek_char; /* Temporary look-ahead character. */
- int result; /* The thing to return. */
-
- if (command == RESET)
- {
- reset_parser ();
- return ('\n');
- }
-
- if (token_to_read)
- {
- result = token_to_read;
- if (token_to_read == WORD || token_to_read == ASSIGNMENT_WORD)
- {
- yylval.word = word_desc_to_read;
- word_desc_to_read = (WORD_DESC *)NULL;
- }
- token_to_read = 0;
- return (result);
- }
-
-#if defined (COND_COMMAND)
- if ((parser_state & (PST_CONDCMD|PST_CONDEXPR)) == PST_CONDCMD)
- {
- cond_lineno = line_number;
- parser_state |= PST_CONDEXPR;
- yylval.command = parse_cond_command ();
- if (cond_token != COND_END)
- {
- cond_error ();
- return (-1);
- }
- token_to_read = COND_END;
- parser_state &= ~(PST_CONDEXPR|PST_CONDCMD);
- return (COND_CMD);
- }
-#endif
-
-#if defined (ALIAS)
- /* This is a place to jump back to once we have successfully expanded a
- token with an alias and pushed the string with push_string () */
- re_read_token:
-#endif /* ALIAS */
-
- /* Read a single word from input. Start by skipping blanks. */
- while ((character = shell_getc (1)) != EOF && whitespace (character))
- ;
-
- if (character == EOF)
- {
- EOF_Reached = 1;
- return (yacc_EOF);
- }
-
- if MBTEST(character == '#' && (!interactive || interactive_comments))
- {
- /* A comment. Discard until EOL or EOF, and then return a newline. */
- discard_until ('\n');
- shell_getc (0);
- character = '\n'; /* this will take the next if statement and return. */
- }
-
- if (character == '\n')
- {
- /* If we're about to return an unquoted newline, we can go and collect
- the text of any pending here document. */
- if (need_here_doc)
- gather_here_documents ();
-
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- parser_state &= ~PST_ASSIGNOK;
-
- return (character);
- }
-
- /* Shell meta-characters. */
- if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
- {
-#if defined (ALIAS)
- /* Turn off alias tokenization iff this character sequence would
- not leave us ready to read a command. */
- if (character == '<' || character == '>')
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- parser_state &= ~PST_ASSIGNOK;
-
- peek_char = shell_getc (1);
- if (character == peek_char)
- {
- switch (character)
- {
- case '<':
- /* If '<' then we could be at "<<" or at "<<-". We have to
- look ahead one more character. */
- peek_char = shell_getc (1);
- if (peek_char == '-')
- return (LESS_LESS_MINUS);
- else if (peek_char == '<')
- return (LESS_LESS_LESS);
- else
- {
- shell_ungetc (peek_char);
- return (LESS_LESS);
- }
-
- case '>':
- return (GREATER_GREATER);
-
- case ';':
- parser_state |= PST_CASEPAT;
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- return (SEMI_SEMI);
-
- case '&':
- return (AND_AND);
-
- case '|':
- return (OR_OR);
-
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
- case '(': /* ) */
- result = parse_dparen (character);
- if (result == -2)
- break;
- else
- return result;
-#endif
- }
- }
- else if MBTEST(character == '<' && peek_char == '&')
- return (LESS_AND);
- else if MBTEST(character == '>' && peek_char == '&')
- return (GREATER_AND);
- else if MBTEST(character == '<' && peek_char == '>')
- return (LESS_GREATER);
- else if MBTEST(character == '>' && peek_char == '|')
- return (GREATER_BAR);
- else if MBTEST(peek_char == '>' && character == '&')
- return (AND_GREATER);
-
- shell_ungetc (peek_char);
-
- /* If we look like we are reading the start of a function
- definition, then let the reader know about it so that
- we will do the right thing with `{'. */
- if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
- {
- parser_state |= PST_ALLOWOPNBRC;
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
- function_dstart = line_number;
- }
-
- /* case pattern lists may be preceded by an optional left paren. If
- we're not trying to parse a case pattern list, the left paren
- indicates a subshell. */
- if MBTEST(character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
- parser_state |= PST_SUBSHELL;
- /*(*/
- else if MBTEST((parser_state & PST_CASEPAT) && character == ')')
- parser_state &= ~PST_CASEPAT;
- /*(*/
- else if MBTEST((parser_state & PST_SUBSHELL) && character == ')')
- parser_state &= ~PST_SUBSHELL;
-
-#if defined (PROCESS_SUBSTITUTION)
- /* Check for the constructs which introduce process substitution.
- Shells running in `posix mode' don't do process substitution. */
- if MBTEST(posixly_correct || ((character != '>' && character != '<') || peek_char != '(')) /*)*/
-#endif /* PROCESS_SUBSTITUTION */
- return (character);
- }
-
- /* Hack <&- (close stdin) case. Also <&N- (dup and close). */
- if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
- return (character);
-
- /* Okay, if we got this far, we have to read a word. Read one,
- and then check it against the known ones. */
- result = read_token_word (character);
-#if defined (ALIAS)
- if (result == RE_READ_TOKEN)
- goto re_read_token;
-#endif
- return result;
-}
-
-/*
- * Match a $(...) or other grouping construct. This has to handle embedded
- * quoted strings ('', ``, "") and nested constructs. It also must handle
- * reprompting the user, if necessary, after reading a newline, and returning
- * correct error values if it reads EOF.
- */
-#define P_FIRSTCLOSE 0x01
-#define P_ALLOWESC 0x02
-#define P_DQUOTE 0x04
-#define P_COMMAND 0x08 /* parsing a command, so look for comments */
-
-static char matched_pair_error;
-static char *
-parse_matched_pair (qc, open, close, lenp, flags)
- int qc; /* `"' if this construct is within double quotes */
- int open, close;
- int *lenp, flags;
-{
- int count, ch, was_dollar, in_comment, check_comment;
- int pass_next_character, nestlen, ttranslen, start_lineno;
- char *ret, *nestret, *ttrans;
- int retind, retsize, rflags;
-
- count = 1;
- pass_next_character = was_dollar = in_comment = 0;
- check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
-
-itrace("parse_matched_pair: check_comment set to %d", check_comment);
-
- /* RFLAGS is the set of flags we want to pass to recursive calls. */
- rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE);
-
- ret = (char *)xmalloc (retsize = 64);
- retind = 0;
-
- start_lineno = line_number;
- while (count)
- {
-#if 0
- ch = shell_getc ((qc != '\'' || (flags & P_ALLOWESC)) && pass_next_character == 0);
-#else
- ch = shell_getc (qc != '\'' && pass_next_character == 0);
-#endif
- if (ch == EOF)
- {
- free (ret);
- parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
- EOF_Reached = 1; /* XXX */
- return (&matched_pair_error);
- }
-
- /* Possible reprompting. */
- if (ch == '\n' && SHOULD_PROMPT ())
- prompt_again ();
-
- if (in_comment && ch == '\n')
- in_comment = 0;
- else if (check_comment && in_comment == 0 && ch == '#')
-{
- in_comment = 1;
-itrace("parse_matched_pair: set in_comment to 1");
-}
- if (pass_next_character) /* last char was backslash */
- {
- pass_next_character = 0;
- if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
- {
- if (retind > 0) retind--; /* swallow previously-added backslash */
- continue;
- }
-
- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
- if MBTEST(ch == CTLESC || ch == CTLNUL)
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
- else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
- else if MBTEST(ch == close) /* ending delimiter */
- count--;
-#if 1
- /* handle nested ${...} specially. */
- else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
- count++;
-#endif
- else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
- count++;
-
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
-
- if (open == '\'') /* '' inside grouping construct */
- {
- if MBTEST((flags & P_ALLOWESC) && ch == '\\')
- pass_next_character++;
- continue;
- }
-
- if MBTEST(ch == '\\') /* backslashes */
- pass_next_character++;
-
- if (open != close) /* a grouping construct */
- {
- if MBTEST(shellquote (ch))
- {
- /* '', ``, or "" inside $(...) or other grouping construct. */
- push_delimiter (dstack, ch);
- if MBTEST(was_dollar && ch == '\'') /* $'...' inside group */
- nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC|rflags);
- else
- nestret = parse_matched_pair (ch, ch, ch, &nestlen, rflags);
- pop_delimiter (dstack);
- if (nestret == &matched_pair_error)
- {
- free (ret);
- return &matched_pair_error;
- }
- if MBTEST(was_dollar && ch == '\'' && (extended_quote || (rflags & P_DQUOTE) == 0))
- {
- /* Translate $'...' here. */
- ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
- xfree (nestret);
-
- if ((rflags & P_DQUOTE) == 0)
- {
- nestret = sh_single_quote (ttrans);
- free (ttrans);
- nestlen = strlen (nestret);
- }
- else
- {
- nestret = ttrans;
- nestlen = ttranslen;
- }
- retind -= 2; /* back up before the $' */
- }
- else if MBTEST(was_dollar && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0))
- {
- /* Locale expand $"..." here. */
- ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
- xfree (nestret);
-
- nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
- free (ttrans);
- nestlen = ttranslen + 2;
- retind -= 2; /* back up before the $" */
- }
-
- if (nestlen)
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
- strcpy (ret + retind, nestret);
- retind += nestlen;
- }
- FREE (nestret);
- }
- }
- /* Parse an old-style command substitution within double quotes as a
- single word. */
- /* XXX - sh and ksh93 don't do this - XXX */
- else if MBTEST(open == '"' && ch == '`')
- {
- nestret = parse_matched_pair (0, '`', '`', &nestlen, rflags);
-add_nestret:
- if (nestret == &matched_pair_error)
- {
- free (ret);
- return &matched_pair_error;
- }
- if (nestlen)
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
- strcpy (ret + retind, nestret);
- retind += nestlen;
- }
- FREE (nestret);
- }
- else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
- {
-itrace("parse_matched_pair: parsing quoted string in backquotes");
- nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags);
- goto add_nestret;
- }
- else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
- /* check for $(), $[], or ${} inside quoted string. */
- {
- if (open == ch) /* undo previous increment */
- count--;
- if (ch == '(') /* ) */
- nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags);
- else if (ch == '{') /* } */
- nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
- else if (ch == '[') /* ] */
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
-
- goto add_nestret;
- }
- was_dollar = MBTEST(ch == '$');
- }
-
- ret[retind] = '\0';
- if (lenp)
- *lenp = retind;
- return ret;
-}
-
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
-/* Parse a double-paren construct. It can be either an arithmetic
- command, an arithmetic `for' command, or a nested subshell. Returns
- the parsed token, -1 on error, or -2 if we didn't do anything and
- should just go on. */
-static int
-parse_dparen (c)
- int c;
-{
- int cmdtyp, len, sline;
- char *wval, *wv2;
- WORD_DESC *wd;
-
-#if defined (ARITH_FOR_COMMAND)
- if (last_read_token == FOR)
- {
- arith_for_lineno = line_number;
- cmdtyp = parse_arith_cmd (&wval, 0);
- if (cmdtyp == 1)
- {
- wd = alloc_word_desc ();
- wd->word = wval;
- wd = make_word (wval);
- yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
- return (ARITH_FOR_EXPRS);
- }
- else
- return -1; /* ERROR */
- }
-#endif
-
-#if defined (DPAREN_ARITHMETIC)
- if (reserved_word_acceptable (last_read_token))
- {
- sline = line_number;
-
- cmdtyp = parse_arith_cmd (&wval, 0);
- if (cmdtyp == 1) /* arithmetic command */
- {
- wd = alloc_word_desc ();
- wd->word = wval;
- wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB|W_DQUOTE;
- yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
- return (ARITH_CMD);
- }
- else if (cmdtyp == 0) /* nested subshell */
- {
- push_string (wval, 0, (alias_t *)NULL);
- if ((parser_state & PST_CASEPAT) == 0)
- parser_state |= PST_SUBSHELL;
- return (c);
- }
- else /* ERROR */
- return -1;
- }
-#endif
-
- return -2; /* XXX */
-}
-
-/* We've seen a `(('. Look for the matching `))'. If we get it, return 1.
- If not, assume it's a nested subshell for backwards compatibility and
- return 0. In any case, put the characters we've consumed into a locally-
- allocated buffer and make *ep point to that buffer. Return -1 on an
- error, for example EOF. */
-static int
-parse_arith_cmd (ep, adddq)
- char **ep;
- int adddq;
-{
- int exp_lineno, rval, c;
- char *ttok, *tokstr;
- int ttoklen;
-
- exp_lineno = line_number;
- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
- rval = 1;
- if (ttok == &matched_pair_error)
- return -1;
- /* Check that the next character is the closing right paren. If
- not, this is a syntax error. ( */
- c = shell_getc (0);
- if MBTEST(c != ')')
- rval = 0;
-
- tokstr = (char *)xmalloc (ttoklen + 4);
-
- /* if ADDDQ != 0 then (( ... )) -> "..." */
- if (rval == 1 && adddq) /* arith cmd, add double quotes */
- {
- tokstr[0] = '"';
- strncpy (tokstr + 1, ttok, ttoklen - 1);
- tokstr[ttoklen] = '"';
- tokstr[ttoklen+1] = '\0';
- }
- else if (rval == 1) /* arith cmd, don't add double quotes */
- {
- strncpy (tokstr, ttok, ttoklen - 1);
- tokstr[ttoklen-1] = '\0';
- }
- else /* nested subshell */
- {
- tokstr[0] = '(';
- strncpy (tokstr + 1, ttok, ttoklen - 1);
- tokstr[ttoklen] = ')';
- tokstr[ttoklen+1] = c;
- tokstr[ttoklen+2] = '\0';
- }
-
- *ep = tokstr;
- FREE (ttok);
- return rval;
-}
-#endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
-
-#if defined (COND_COMMAND)
-static void
-cond_error ()
-{
- char *etext;
-
- if (EOF_Reached && cond_token != COND_ERROR) /* [[ */
- parser_error (cond_lineno, _("unexpected EOF while looking for `]]'"));
- else if (cond_token != COND_ERROR)
- {
- if (etext = error_token_from_token (cond_token))
- {
- parser_error (cond_lineno, _("syntax error in conditional expression: unexpected token `%s'"), etext);
- free (etext);
- }
- else
- parser_error (cond_lineno, _("syntax error in conditional expression"));
- }
-}
-
-static COND_COM *
-cond_expr ()
-{
- return (cond_or ());
-}
-
-static COND_COM *
-cond_or ()
-{
- COND_COM *l, *r;
-
- l = cond_and ();
- if (cond_token == OR_OR)
- {
- r = cond_or ();
- l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r);
- }
- return l;
-}
-
-static COND_COM *
-cond_and ()
-{
- COND_COM *l, *r;
-
- l = cond_term ();
- if (cond_token == AND_AND)
- {
- r = cond_and ();
- l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r);
- }
- return l;
-}
-
-static int
-cond_skip_newlines ()
-{
- while ((cond_token = read_token (READ)) == '\n')
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- }
- return (cond_token);
-}
-
-#define COND_RETURN_ERROR() \
- do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0)
-
-static COND_COM *
-cond_term ()
-{
- WORD_DESC *op;
- COND_COM *term, *tleft, *tright;
- int tok, lineno;
- char *etext;
-
- /* Read a token. It can be a left paren, a `!', a unary operator, or a
- word that should be the first argument of a binary operator. Start by
- skipping newlines, since this is a compound command. */
- tok = cond_skip_newlines ();
- lineno = line_number;
- if (tok == COND_END)
- {
- COND_RETURN_ERROR ();
- }
- else if (tok == '(')
- {
- term = cond_expr ();
- if (cond_token != ')')
- {
- if (term)
- dispose_cond_node (term); /* ( */
- if (etext = error_token_from_token (cond_token))
- {
- parser_error (lineno, _("unexpected token `%s', expected `)'"), etext);
- free (etext);
- }
- else
- parser_error (lineno, _("expected `)'"));
- COND_RETURN_ERROR ();
- }
- term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
- (void)cond_skip_newlines ();
- }
- else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0')))
- {
- if (tok == WORD)
- dispose_word (yylval.word); /* not needed */
- term = cond_term ();
- if (term)
- term->flags |= CMD_INVERT_RETURN;
- }
- else if (tok == WORD && test_unop (yylval.word->word))
- {
- op = yylval.word;
- tok = read_token (READ);
- if (tok == WORD)
- {
- tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
- term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
- }
- else
- {
- dispose_word (op);
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected argument `%s' to conditional unary operator"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected argument to conditional unary operator"));
- COND_RETURN_ERROR ();
- }
-
- (void)cond_skip_newlines ();
- }
- else if (tok == WORD) /* left argument to binary operator */
- {
- /* lhs */
- tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
-
- /* binop */
- tok = read_token (READ);
- if (tok == WORD && test_binop (yylval.word->word))
- op = yylval.word;
-#if defined (COND_REGEXP)
- else if (tok == WORD && STREQ (yylval.word->word,"=~"))
- op = yylval.word;
-#endif
- else if (tok == '<' || tok == '>')
- op = make_word_from_token (tok); /* ( */
- /* There should be a check before blindly accepting the `)' that we have
- seen the opening `('. */
- else if (tok == COND_END || tok == AND_AND || tok == OR_OR || tok == ')')
- {
- /* Special case. [[ x ]] is equivalent to [[ -n x ]], just like
- the test command. Similarly for [[ x && expr ]] or
- [[ x || expr ]] or [[ (x) ]]. */
- op = make_word ("-n");
- term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
- cond_token = tok;
- return (term);
- }
- else
- {
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected token `%s', conditional binary operator expected"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("conditional binary operator expected"));
- dispose_cond_node (tleft);
- COND_RETURN_ERROR ();
- }
-
- /* rhs */
- tok = read_token (READ);
- if (tok == WORD)
- {
- tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
- term = make_cond_node (COND_BINARY, op, tleft, tright);
- }
- else
- {
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected argument `%s' to conditional binary operator"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected argument to conditional binary operator"));
- dispose_cond_node (tleft);
- dispose_word (op);
- COND_RETURN_ERROR ();
- }
-
- (void)cond_skip_newlines ();
- }
- else
- {
- if (tok < 256)
- parser_error (line_number, _("unexpected token `%c' in conditional command"), tok);
- else if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected token `%s' in conditional command"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected token %d in conditional command"), tok);
- COND_RETURN_ERROR ();
- }
- return (term);
-}
-
-/* This is kind of bogus -- we slip a mini recursive-descent parser in
- here to handle the conditional statement syntax. */
-static COMMAND *
-parse_cond_command ()
-{
- COND_COM *cexp;
-
- cexp = cond_expr ();
- return (make_cond_command (cexp));
-}
-#endif
-
-#if defined (ARRAY_VARS)
-/* When this is called, it's guaranteed that we don't care about anything
- in t beyond i. We do save and restore the chars, though. */
-static int
-token_is_assignment (t, i)
- char *t;
- int i;
-{
- unsigned char c, c1;
- int r;
-
- c = t[i]; c1 = t[i+1];
- t[i] = '='; t[i+1] = '\0';
- r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
- t[i] = c; t[i+1] = c1;
- return r;
-}
-
-/* XXX - possible changes here for `+=' */
-static int
-token_is_ident (t, i)
- char *t;
- int i;
-{
- unsigned char c;
- int r;
-
- c = t[i];
- t[i] = '\0';
- r = legal_identifier (t);
- t[i] = c;
- return r;
-}
-#endif
-
-static int
-read_token_word (character)
- int character;
-{
- /* The value for YYLVAL when a WORD is read. */
- WORD_DESC *the_word;
-
- /* Index into the token that we are building. */
- int token_index;
-
- /* ALL_DIGITS becomes zero when we see a non-digit. */
- int all_digit_token;
-
- /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
- int dollar_present;
-
- /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
- assignment. */
- int compound_assignment;
-
- /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
- int quoted;
-
- /* Non-zero means to ignore the value of the next character, and just
- to add it no matter what. */
- int pass_next_character;
-
- /* The current delimiting character. */
- int cd;
- int result, peek_char;
- char *ttok, *ttrans;
- int ttoklen, ttranslen;
- intmax_t lvalue;
-
- if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
- token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
-
- token_index = 0;
- all_digit_token = DIGIT (character);
- dollar_present = quoted = pass_next_character = compound_assignment = 0;
-
- for (;;)
- {
- if (character == EOF)
- goto got_token;
-
- if (pass_next_character)
- {
- pass_next_character = 0;
- goto got_character;
- }
-
- cd = current_delimiter (dstack);
-
- /* Handle backslashes. Quote lots of things when not inside of
- double-quotes, quote some things inside of double-quotes. */
- if MBTEST(character == '\\')
- {
- peek_char = shell_getc (0);
-
- /* Backslash-newline is ignored in all cases except
- when quoted with single quotes. */
- if (peek_char == '\n')
- {
- character = '\n';
- goto next_character;
- }
- else
- {
- shell_ungetc (peek_char);
-
- /* If the next character is to be quoted, note it now. */
- if (cd == 0 || cd == '`' ||
- (cd == '"' && peek_char >= 0 && (sh_syntaxtab[peek_char] & CBSDQUOTE)))
- pass_next_character++;
-
- quoted = 1;
- goto got_character;
- }
- }
-
- /* Parse a matched pair of quote characters. */
- if MBTEST(shellquote (character))
- {
- push_delimiter (dstack, character);
-itrace("read_token_word: calling parse_matched_pair: character = %c", character);
-#if 0
- ttok = parse_matched_pair (character, character, character, &ttoklen, 0);
-#else
- ttok = parse_matched_pair (character, character, character, &ttoklen, (character == '`') ? P_COMMAND : 0);
-#endif
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- all_digit_token = 0;
- quoted = 1;
- dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
- FREE (ttok);
- goto next_character;
- }
-
-#ifdef EXTENDED_GLOB
- /* Parse a ksh-style extended pattern matching specification. */
- if (extended_glob && PATTERN_CHAR (character))
- {
- peek_char = shell_getc (1);
- if MBTEST(peek_char == '(') /* ) */
- {
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- token[token_index++] = peek_char;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- dollar_present = all_digit_token = 0;
- goto next_character;
- }
- else
- shell_ungetc (peek_char);
- }
-#endif /* EXTENDED_GLOB */
-
- /* If the delimiter character is not single quote, parse some of
- the shell expansions that must be read as a single word. */
- if (shellexp (character))
- {
- peek_char = shell_getc (1);
- /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
- if MBTEST(peek_char == '(' || \
- ((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
- {
- if (peek_char == '{') /* } */
- ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
- else if (peek_char == '(') /* ) */
- {
- /* XXX - push and pop the `(' as a delimiter for use by
- the command-oriented-history code. This way newlines
- appearing in the $(...) string get added to the
- history literally rather than causing a possibly-
- incorrect `;' to be added. ) */
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (cd, '(', ')', &ttoklen, P_COMMAND);
- pop_delimiter (dstack);
- }
- else
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- token[token_index++] = peek_char;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- dollar_present = 1;
- all_digit_token = 0;
- goto next_character;
- }
- /* This handles $'...' and $"..." new-style quoted strings. */
- else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
- {
- int first_line;
-
- first_line = line_number;
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (peek_char, peek_char, peek_char,
- &ttoklen,
- (peek_char == '\'') ? P_ALLOWESC : 0);
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1;
- if (peek_char == '\'')
- {
- ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen);
- free (ttok);
-
- /* Insert the single quotes and correctly quote any
- embedded single quotes (allowed because P_ALLOWESC was
- passed to parse_matched_pair). */
- ttok = sh_single_quote (ttrans);
- free (ttrans);
- ttranslen = strlen (ttok);
- ttrans = ttok;
- }
- else
- {
- /* Try to locale)-expand the converted string. */
- ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
- free (ttok);
-
- /* Add the double quotes back */
- ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
- free (ttrans);
- ttranslen += 2;
- ttrans = ttok;
- }
-
- RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- strcpy (token + token_index, ttrans);
- token_index += ttranslen;
- FREE (ttrans);
- quoted = 1;
- all_digit_token = 0;
- goto next_character;
- }
- /* This could eventually be extended to recognize all of the
- shell's single-character parameter expansions, and set flags.*/
- else if MBTEST(character == '$' && peek_char == '$')
- {
- ttok = (char *)xmalloc (3);
- ttok[0] = ttok[1] = '$';
- ttok[2] = '\0';
- RESIZE_MALLOCED_BUFFER (token, token_index, 3,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- strcpy (token + token_index, ttok);
- token_index += 2;
- dollar_present = 1;
- all_digit_token = 0;
- FREE (ttok);
- goto next_character;
- }
- else
- shell_ungetc (peek_char);
- }
-
-#if defined (ARRAY_VARS)
- /* Identify possible array subscript assignment; match [...] */
- else if MBTEST(character == '[' && token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) /* ] */
- {
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- all_digit_token = 0;
- goto next_character;
- }
- /* Identify possible compound array variable assignment. */
- else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index))
- {
- peek_char = shell_getc (1);
- if MBTEST(peek_char == '(') /* ) */
- {
- ttok = parse_compound_assignment (&ttoklen);
-
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
-
- token[token_index++] = '=';
- token[token_index++] = '(';
- if (ttok)
- {
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- }
- token[token_index++] = ')';
- FREE (ttok);
- all_digit_token = 0;
- compound_assignment = 1;
-#if 0
- goto next_character;
-#else
- goto got_token; /* ksh93 seems to do this */
-#endif
- }
- else
- shell_ungetc (peek_char);
- }
-#endif
-
- /* When not parsing a multi-character word construct, shell meta-
- characters break words. */
- if MBTEST(shellbreak (character))
- {
- shell_ungetc (character);
- goto got_token;
- }
-
- got_character:
-
- all_digit_token &= DIGIT (character);
- dollar_present |= character == '$';
-
- if (character == CTLESC || character == CTLNUL)
- token[token_index++] = CTLESC;
-
- token[token_index++] = character;
-
- RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
-
- next_character:
- if (character == '\n' && SHOULD_PROMPT ())
- prompt_again ();
-
- /* We want to remove quoted newlines (that is, a \<newline> pair)
- unless we are within single quotes or pass_next_character is
- set (the shell equivalent of literal-next). */
- cd = current_delimiter (dstack);
- character = shell_getc (cd != '\'' && pass_next_character == 0);
- } /* end for (;;) */
-
-got_token:
-
- token[token_index] = '\0';
-
- /* Check to see what thing we should return. If the last_read_token
- is a `<', or a `&', or the character which ended this token is
- a '>' or '<', then, and ONLY then, is this input token a NUMBER.
- Otherwise, it is just a word, and should be returned as such. */
- if MBTEST(all_digit_token && (character == '<' || character == '>' || \
- last_read_token == LESS_AND || \
- last_read_token == GREATER_AND))
- {
- if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
- yylval.number = lvalue;
- else
- yylval.number = -1;
- return (NUMBER);
- }
-
- /* Check for special case tokens. */
- result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
- if (result >= 0)
- return result;
-
-#if defined (ALIAS)
- /* Posix.2 does not allow reserved words to be aliased, so check for all
- of them, including special cases, before expanding the current token
- as an alias. */
- if MBTEST(posixly_correct)
- CHECK_FOR_RESERVED_WORD (token);
-
- /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
- inhibits alias expansion. */
- if (expand_aliases && quoted == 0)
- {
- result = alias_expand_token (token);
- if (result == RE_READ_TOKEN)
- return (RE_READ_TOKEN);
- else if (result == NO_EXPANSION)
- parser_state &= ~PST_ALEXPNEXT;
- }
-
- /* If not in Posix.2 mode, check for reserved words after alias
- expansion. */
- if MBTEST(posixly_correct == 0)
-#endif
- CHECK_FOR_RESERVED_WORD (token);
-
- the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
- the_word->word = (char *)xmalloc (1 + token_index);
- the_word->flags = 0;
- strcpy (the_word->word, token);
- if (dollar_present)
- the_word->flags |= W_HASDOLLAR;
- if (quoted)
- the_word->flags |= W_QUOTED;
- if (compound_assignment)
- the_word->flags |= W_COMPASSIGN;
- /* A word is an assignment if it appears at the beginning of a
- simple command, or after another assignment word. This is
- context-dependent, so it cannot be handled in the grammar. */
- if (assignment (token, (parser_state & PST_COMPASSIGN) != 0))
- {
- the_word->flags |= W_ASSIGNMENT;
- /* Don't perform word splitting on assignment statements. */
- if (assignment_acceptable (last_read_token) || (parser_state & PST_COMPASSIGN) != 0)
- the_word->flags |= W_NOSPLIT;
- }
-
- if (command_token_position (last_read_token))
- {
- struct builtin *b;
- b = builtin_address_internal (token, 0);
- if (b && (b->flags & ASSIGNMENT_BUILTIN))
- parser_state |= PST_ASSIGNOK;
- }
-
- yylval.word = the_word;
-
- result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT))
- ? ASSIGNMENT_WORD : WORD;
-
- switch (last_read_token)
- {
- case FUNCTION:
- parser_state |= PST_ALLOWOPNBRC;
- function_dstart = line_number;
- break;
- case CASE:
- case SELECT:
- case FOR:
- if (word_top < MAX_CASE_NEST)
- word_top++;
- word_lineno[word_top] = line_number;
- break;
- }
-
- return (result);
-}
-
-/* Return 1 if TOKSYM is a token that after being read would allow
- a reserved word to be seen, else 0. */
-static int
-reserved_word_acceptable (toksym)
- int toksym;
-{
- switch (toksym)
- {
- case '\n':
- case ';':
- case '(':
- case ')':
- case '|':
- case '&':
- case '{':
- case '}': /* XXX */
- case AND_AND:
- case BANG:
- case DO:
- case DONE:
- case ELIF:
- case ELSE:
- case ESAC:
- case FI:
- case IF:
- case OR_OR:
- case SEMI_SEMI:
- case THEN:
- case TIME:
- case TIMEOPT:
- case UNTIL:
- case WHILE:
- case 0:
- return 1;
- default:
- return 0;
- }
-}
-
-/* Return the index of TOKEN in the alist of reserved words, or -1 if
- TOKEN is not a shell reserved word. */
-int
-find_reserved_word (tokstr)
- char *tokstr;
-{
- int i;
- for (i = 0; word_token_alist[i].word; i++)
- if (STREQ (tokstr, word_token_alist[i].word))
- return i;
- return -1;
-}
-
-#if 0
-#if defined (READLINE)
-/* Called after each time readline is called. This insures that whatever
- the new prompt string is gets propagated to readline's local prompt
- variable. */
-static void
-reset_readline_prompt ()
-{
- char *temp_prompt;
-
- if (prompt_string_pointer)
- {
- temp_prompt = (*prompt_string_pointer)
- ? decode_prompt_string (*prompt_string_pointer)
- : (char *)NULL;
-
- if (temp_prompt == 0)
- {
- temp_prompt = (char *)xmalloc (1);
- temp_prompt[0] = '\0';
- }
-
- FREE (current_readline_prompt);
- current_readline_prompt = temp_prompt;
- }
-}
-#endif /* READLINE */
-#endif /* 0 */
-
-#if defined (HISTORY)
-/* A list of tokens which can be followed by newlines, but not by
- semi-colons. When concatenating multiple lines of history, the
- newline separator for such tokens is replaced with a space. */
-static int no_semi_successors[] = {
- '\n', '{', '(', ')', ';', '&', '|',
- CASE, DO, ELSE, IF, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR, IN,
- 0
-};
-
-/* If we are not within a delimited expression, try to be smart
- about which separators can be semi-colons and which must be
- newlines. Returns the string that should be added into the
- history entry. */
-char *
-history_delimiting_chars ()
-{
- register int i;
-
- if (dstack.delimiter_depth != 0)
- return ("\n");
-
- /* First, handle some special cases. */
- /*(*/
- /* If we just read `()', assume it's a function definition, and don't
- add a semicolon. If the token before the `)' was not `(', and we're
- not in the midst of parsing a case statement, assume it's a
- parenthesized command and add the semicolon. */
- /*)(*/
- if (token_before_that == ')')
- {
- if (two_tokens_ago == '(') /*)*/ /* function def */
- return " ";
- /* This does not work for subshells inside case statement
- command lists. It's a suboptimal solution. */
- else if (parser_state & PST_CASESTMT) /* case statement pattern */
- return " ";
- else
- return "; "; /* (...) subshell */
- }
- else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
- return " "; /* function def using `function name' without `()' */
-
- else if (token_before_that == WORD && two_tokens_ago == FOR)
- {
- /* Tricky. `for i\nin ...' should not have a semicolon, but
- `for i\ndo ...' should. We do what we can. */
- for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)
- ;
- if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
- return " ";
- return ";";
- }
- else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
- return " ";
-
- for (i = 0; no_semi_successors[i]; i++)
- {
- if (token_before_that == no_semi_successors[i])
- return (" ");
- }
-
- return ("; ");
-}
-#endif /* HISTORY */
-
-/* Issue a prompt, or prepare to issue a prompt when the next character
- is read. */
-static void
-prompt_again ()
-{
- char *temp_prompt;
-
- if (interactive == 0 || expanding_alias()) /* XXX */
- return;
-
- ps1_prompt = get_string_value ("PS1");
- ps2_prompt = get_string_value ("PS2");
-
- if (!prompt_string_pointer)
- prompt_string_pointer = &ps1_prompt;
-
- temp_prompt = *prompt_string_pointer
- ? decode_prompt_string (*prompt_string_pointer)
- : (char *)NULL;
-
- if (temp_prompt == 0)
- {
- temp_prompt = (char *)xmalloc (1);
- temp_prompt[0] = '\0';
- }
-
- current_prompt_string = *prompt_string_pointer;
- prompt_string_pointer = &ps2_prompt;
-
-#if defined (READLINE)
- if (!no_line_editing)
- {
- FREE (current_readline_prompt);
- current_readline_prompt = temp_prompt;
- }
- else
-#endif /* READLINE */
- {
- FREE (current_decoded_prompt);
- current_decoded_prompt = temp_prompt;
- }
-}
-
-int
-get_current_prompt_level ()
-{
- return ((current_prompt_string && current_prompt_string == ps2_prompt) ? 2 : 1);
-}
-
-void
-set_current_prompt_level (x)
- int x;
-{
- prompt_string_pointer = (x == 2) ? &ps2_prompt : &ps1_prompt;
- current_prompt_string = *prompt_string_pointer;
-}
-
-static void
-print_prompt ()
-{
- fprintf (stderr, "%s", current_decoded_prompt);
- fflush (stderr);
-}
-
-/* Return a string which will be printed as a prompt. The string
- may contain special characters which are decoded as follows:
-
- \a bell (ascii 07)
- \d the date in Day Mon Date format
- \e escape (ascii 033)
- \h the hostname up to the first `.'
- \H the hostname
- \j the number of active jobs
- \l the basename of the shell's tty device name
- \n CRLF
- \r CR
- \s the name of the shell
- \t the time in 24-hour hh:mm:ss format
- \T the time in 12-hour hh:mm:ss format
- \@ the time in 12-hour hh:mm am/pm format
- \A the time in 24-hour hh:mm format
- \D{fmt} the result of passing FMT to strftime(3)
- \u your username
- \v the version of bash (e.g., 2.00)
- \V the release of bash, version + patchlevel (e.g., 2.00.0)
- \w the current working directory
- \W the last element of $PWD
- \! the history number of this command
- \# the command number of this command
- \$ a $ or a # if you are root
- \nnn character code nnn in octal
- \\ a backslash
- \[ begin a sequence of non-printing chars
- \] end a sequence of non-printing chars
-*/
-#define PROMPT_GROWTH 48
-char *
-decode_prompt_string (string)
- char *string;
-{
- WORD_LIST *list;
- char *result, *t;
- struct dstack save_dstack;
- int last_exit_value;
-#if defined (PROMPT_STRING_DECODE)
- int result_size, result_index;
- int c, n;
- char *temp, octal_string[4];
- struct tm *tm;
- time_t the_time;
- char timebuf[128];
- char *timefmt;
-
- result = (char *)xmalloc (result_size = PROMPT_GROWTH);
- result[result_index = 0] = 0;
- temp = (char *)NULL;
-
- while (c = *string++)
- {
- if (posixly_correct && c == '!')
- {
- if (*string == '!')
- {
- temp = savestring ("!");
- goto add_string;
- }
- else
- {
-#if !defined (HISTORY)
- temp = savestring ("1");
-#else /* HISTORY */
- temp = itos (history_number ());
-#endif /* HISTORY */
- string--; /* add_string increments string again. */
- goto add_string;
- }
- }
- if (c == '\\')
- {
- c = *string;
-
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- strncpy (octal_string, string, 3);
- octal_string[3] = '\0';
-
- n = read_octal (octal_string);
- temp = (char *)xmalloc (3);
-
- if (n == CTLESC || n == CTLNUL)
- {
- temp[0] = CTLESC;
- temp[1] = n;
- temp[2] = '\0';
- }
- else if (n == -1)
- {
- temp[0] = '\\';
- temp[1] = '\0';
- }
- else
- {
- temp[0] = n;
- temp[1] = '\0';
- }
-
- for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
- string++;
-
- c = 0; /* tested at add_string: */
- goto add_string;
-
- case 'd':
- case 't':
- case 'T':
- case '@':
- case 'A':
- /* Make the current time/date into a string. */
- (void) time (&the_time);
- tm = localtime (&the_time);
-
- if (c == 'd')
- n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
- else if (c == 't')
- n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
- else if (c == 'T')
- n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
- else if (c == '@')
- n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
- else if (c == 'A')
- n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
-
- if (n == 0)
- timebuf[0] = '\0';
- else
- timebuf[sizeof(timebuf) - 1] = '\0';
-
- temp = savestring (timebuf);
- goto add_string;
-
- case 'D': /* strftime format */
- if (string[1] != '{') /* } */
- goto not_escape;
-
- (void) time (&the_time);
- tm = localtime (&the_time);
- string += 2; /* skip { */
- timefmt = xmalloc (strlen (string) + 3);
- for (t = timefmt; *string && *string != '}'; )
- *t++ = *string++;
- *t = '\0';
- c = *string; /* tested at add_string */
- if (timefmt[0] == '\0')
- {
- timefmt[0] = '%';
- timefmt[1] = 'X'; /* locale-specific current time */
- timefmt[2] = '\0';
- }
- n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
- free (timefmt);
-
- if (n == 0)
- timebuf[0] = '\0';
- else
- timebuf[sizeof(timebuf) - 1] = '\0';
-
- if (promptvars || posixly_correct)
- /* Make sure that expand_prompt_string is called with a
- second argument of Q_DOUBLE_QUOTES if we use this
- function here. */
- temp = sh_backslash_quote_for_double_quotes (timebuf);
- else
- temp = savestring (timebuf);
- goto add_string;
-
- case 'n':
- temp = (char *)xmalloc (3);
- temp[0] = no_line_editing ? '\n' : '\r';
- temp[1] = no_line_editing ? '\0' : '\n';
- temp[2] = '\0';
- goto add_string;
-
- case 's':
- temp = base_pathname (shell_name);
- temp = savestring (temp);
- goto add_string;
-
- case 'v':
- case 'V':
- temp = (char *)xmalloc (16);
- if (c == 'v')
- strcpy (temp, dist_version);
- else
- sprintf (temp, "%s.%d", dist_version, patch_level);
- goto add_string;
-
- case 'w':
- case 'W':
- {
- /* Use the value of PWD because it is much more efficient. */
- char t_string[PATH_MAX], *t;
- int tlen;
-
- temp = get_string_value ("PWD");
-
- if (temp == 0)
- {
- if (getcwd (t_string, sizeof(t_string)) == 0)
- {
- t_string[0] = '.';
- tlen = 1;
- }
- else
- tlen = strlen (t_string);
- }
- else
- {
- tlen = sizeof (t_string) - 1;
- strncpy (t_string, temp, tlen);
- }
- t_string[tlen] = '\0';
-
-#define ROOT_PATH(x) ((x)[0] == '/' && (x)[1] == 0)
-#define DOUBLE_SLASH_ROOT(x) ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
- /* Abbreviate \W as ~ if $PWD == $HOME */
- if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0))
- {
- if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
- {
- t = strrchr (t_string, '/');
- if (t)
- strcpy (t_string, t + 1);
- }
- }
-#undef ROOT_PATH
-#undef DOUBLE_SLASH_ROOT
- else
- /* polite_directory_format is guaranteed to return a string
- no longer than PATH_MAX - 1 characters. */
- strcpy (t_string, polite_directory_format (t_string));
-
- /* If we're going to be expanding the prompt string later,
- quote the directory name. */
- if (promptvars || posixly_correct)
- /* Make sure that expand_prompt_string is called with a
- second argument of Q_DOUBLE_QUOTES if we use this
- function here. */
- temp = sh_backslash_quote_for_double_quotes (t_string);
- else
- temp = savestring (t_string);
-
- goto add_string;
- }
-
- case 'u':
- if (current_user.user_name == 0)
- get_current_user_info ();
- temp = savestring (current_user.user_name);
- goto add_string;
-
- case 'h':
- case 'H':
- temp = savestring (current_host_name);
- if (c == 'h' && (t = (char *)strchr (temp, '.')))
- *t = '\0';
- goto add_string;
-
- case '#':
- temp = itos (current_command_number);
- goto add_string;
-
- case '!':
-#if !defined (HISTORY)
- temp = savestring ("1");
-#else /* HISTORY */
- temp = itos (history_number ());
-#endif /* HISTORY */
- goto add_string;
-
- case '$':
- t = temp = (char *)xmalloc (3);
- if ((promptvars || posixly_correct) && (current_user.euid != 0))
- *t++ = '\\';
- *t++ = current_user.euid == 0 ? '#' : '$';
- *t = '\0';
- goto add_string;
-
- case 'j':
- temp = itos (count_all_jobs ());
- goto add_string;
-
- case 'l':
-#if defined (HAVE_TTYNAME)
- temp = (char *)ttyname (fileno (stdin));
- t = temp ? base_pathname (temp) : "tty";
- temp = savestring (t);
-#else
- temp = savestring ("tty");
-#endif /* !HAVE_TTYNAME */
- goto add_string;
-
-#if defined (READLINE)
- case '[':
- case ']':
- if (no_line_editing)
- {
- string++;
- break;
- }
- temp = (char *)xmalloc (3);
- temp[0] = '\001';
- temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
- temp[2] = '\0';
- goto add_string;
-#endif /* READLINE */
-
- case '\\':
- case 'a':
- case 'e':
- case 'r':
- temp = (char *)xmalloc (2);
- if (c == 'a')
- temp[0] = '\07';
- else if (c == 'e')
- temp[0] = '\033';
- else if (c == 'r')
- temp[0] = '\r';
- else /* (c == '\\') */
- temp[0] = c;
- temp[1] = '\0';
- goto add_string;
-
- default:
-not_escape:
- temp = (char *)xmalloc (3);
- temp[0] = '\\';
- temp[1] = c;
- temp[2] = '\0';
-
- add_string:
- if (c)
- string++;
- result =
- sub_append_string (temp, result, &result_index, &result_size);
- temp = (char *)NULL; /* Freed in sub_append_string (). */
- result[result_index] = '\0';
- break;
- }
- }
- else
- {
- RESIZE_MALLOCED_BUFFER (result, result_index, 3, result_size, PROMPT_GROWTH);
- result[result_index++] = c;
- result[result_index] = '\0';
- }
- }
-#else /* !PROMPT_STRING_DECODE */
- result = savestring (string);
-#endif /* !PROMPT_STRING_DECODE */
-
- /* Save the delimiter stack and point `dstack' to temp space so any
- command substitutions in the prompt string won't result in screwing
- up the parser's quoting state. */
- save_dstack = dstack;
- dstack = temp_dstack;
- dstack.delimiter_depth = 0;
-
- /* Perform variable and parameter expansion and command substitution on
- the prompt string. */
- if (promptvars || posixly_correct)
- {
- last_exit_value = last_command_exit_value;
- list = expand_prompt_string (result, Q_DOUBLE_QUOTES);
- free (result);
- result = string_list (list);
- dispose_words (list);
- last_command_exit_value = last_exit_value;
- }
- else
- {
- t = dequote_string (result);
- free (result);
- result = t;
- }
-
- dstack = save_dstack;
-
- return (result);
-}
-
-/************************************************
- * *
- * ERROR HANDLING *
- * *
- ************************************************/
-
-/* Report a syntax error, and restart the parser. Call here for fatal
- errors. */
-int
-yyerror (msg)
- const char *msg;
-{
- report_syntax_error ((char *)NULL);
- reset_parser ();
- return (0);
-}
-
-static char *
-error_token_from_token (token)
- int token;
-{
- char *t;
-
- if (t = find_token_in_alist (token, word_token_alist, 0))
- return t;
-
- if (t = find_token_in_alist (token, other_token_alist, 0))
- return t;
-
- t = (char *)NULL;
- /* This stuff is dicy and needs closer inspection */
- switch (current_token)
- {
- case WORD:
- case ASSIGNMENT_WORD:
- if (yylval.word)
- t = savestring (yylval.word->word);
- break;
- case NUMBER:
- t = itos (yylval.number);
- break;
- case ARITH_CMD:
- if (yylval.word_list)
- t = string_list (yylval.word_list);
- break;
- case ARITH_FOR_EXPRS:
- if (yylval.word_list)
- t = string_list_internal (yylval.word_list, " ; ");
- break;
- case COND_CMD:
- t = (char *)NULL; /* punt */
- break;
- }
-
- return t;
-}
-
-static char *
-error_token_from_text ()
-{
- char *msg, *t;
- int token_end, i;
-
- t = shell_input_line;
- i = shell_input_line_index;
- token_end = 0;
- msg = (char *)NULL;
-
- if (i && t[i] == '\0')
- i--;
-
- while (i && (whitespace (t[i]) || t[i] == '\n'))
- i--;
-
- if (i)
- token_end = i + 1;
-
- while (i && (member (t[i], " \n\t;|&") == 0))
- i--;
-
- while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
- i++;
-
- /* Return our idea of the offending token. */
- if (token_end || (i == 0 && token_end == 0))
- {
- if (token_end)
- msg = substring (t, i, token_end);
- else /* one-character token */
- {
- msg = (char *)xmalloc (2);
- msg[0] = t[i];
- msg[1] = '\0';
- }
- }
-
- return (msg);
-}
-
-static void
-print_offending_line ()
-{
- char *msg;
- int token_end;
-
- msg = savestring (shell_input_line);
- token_end = strlen (msg);
- while (token_end && msg[token_end - 1] == '\n')
- msg[--token_end] = '\0';
-
- parser_error (line_number, "`%s'", msg);
- free (msg);
-}
-
-/* Report a syntax error with line numbers, etc.
- Call here for recoverable errors. If you have a message to print,
- then place it in MESSAGE, otherwise pass NULL and this will figure
- out an appropriate message for you. */
-static void
-report_syntax_error (message)
- char *message;
-{
- char *msg;
-
- if (message)
- {
- parser_error (line_number, "%s", message);
- if (interactive && EOF_Reached)
- EOF_Reached = 0;
- last_command_exit_value = EX_USAGE;
- return;
- }
-
- /* If the line of input we're reading is not null, try to find the
- objectionable token. First, try to figure out what token the
- parser's complaining about by looking at current_token. */
- if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
- {
- parser_error (line_number, _("syntax error near unexpected token `%s'"), msg);
- free (msg);
-
- if (interactive == 0)
- print_offending_line ();
-
- last_command_exit_value = EX_USAGE;
- return;
- }
-
- /* If looking at the current token doesn't prove fruitful, try to find the
- offending token by analyzing the text of the input line near the current
- input line index and report what we find. */
- if (shell_input_line && *shell_input_line)
- {
- msg = error_token_from_text ();
- if (msg)
- {
- parser_error (line_number, _("syntax error near `%s'"), msg);
- free (msg);
- }
-
- /* If not interactive, print the line containing the error. */
- if (interactive == 0)
- print_offending_line ();
- }
- else
- {
- msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
- parser_error (line_number, "%s", msg);
- /* When the shell is interactive, this file uses EOF_Reached
- only for error reporting. Other mechanisms are used to
- decide whether or not to exit. */
- if (interactive && EOF_Reached)
- EOF_Reached = 0;
- }
-
- last_command_exit_value = EX_USAGE;
-}
-
-/* ??? Needed function. ??? We have to be able to discard the constructs
- created during parsing. In the case of error, we want to return
- allocated objects to the memory pool. In the case of no error, we want
- to throw away the information about where the allocated objects live.
- (dispose_command () will actually free the command.) */
-static void
-discard_parser_constructs (error_p)
- int error_p;
-{
-}
-
-/************************************************
- * *
- * EOF HANDLING *
- * *
- ************************************************/
-
-/* Do that silly `type "bye" to exit' stuff. You know, "ignoreeof". */
-
-/* A flag denoting whether or not ignoreeof is set. */
-int ignoreeof = 0;
-
-/* The number of times that we have encountered an EOF character without
- another character intervening. When this gets above the limit, the
- shell terminates. */
-int eof_encountered = 0;
-
-/* The limit for eof_encountered. */
-int eof_encountered_limit = 10;
-
-/* If we have EOF as the only input unit, this user wants to leave
- the shell. If the shell is not interactive, then just leave.
- Otherwise, if ignoreeof is set, and we haven't done this the
- required number of times in a row, print a message. */
-static void
-handle_eof_input_unit ()
-{
- if (interactive)
- {
- /* shell.c may use this to decide whether or not to write out the
- history, among other things. We use it only for error reporting
- in this file. */
- if (EOF_Reached)
- EOF_Reached = 0;
-
- /* If the user wants to "ignore" eof, then let her do so, kind of. */
- if (ignoreeof)
- {
- if (eof_encountered < eof_encountered_limit)
- {
- fprintf (stderr, _("Use \"%s\" to leave the shell.\n"),
- login_shell ? "logout" : "exit");
- eof_encountered++;
- /* Reset the parsing state. */
- last_read_token = current_token = '\n';
- /* Reset the prompt string to be $PS1. */
- prompt_string_pointer = (char **)NULL;
- prompt_again ();
- return;
- }
- }
-
- /* In this case EOF should exit the shell. Do it now. */
- reset_parser ();
- exit_builtin ((WORD_LIST *)NULL);
- }
- else
- {
- /* We don't write history files, etc., for non-interactive shells. */
- EOF_Reached = 1;
- }
-}
-
-/************************************************
- * *
- * STRING PARSING FUNCTIONS *
- * *
- ************************************************/
-
-/* It's very important that these two functions treat the characters
- between ( and ) identically. */
-
-static WORD_LIST parse_string_error;
-
-/* Take a string and run it through the shell parser, returning the
- resultant word list. Used by compound array assignment. */
-WORD_LIST *
-parse_string_to_word_list (s, flags, whom)
- char *s;
- int flags;
- const char *whom;
-{
- WORD_LIST *wl;
- int tok, orig_current_token, orig_line_number, orig_input_terminator;
- int orig_line_count;
- int old_echo_input, old_expand_aliases;
-#if defined (HISTORY)
- int old_remember_on_history, old_history_expansion_inhibited;
-#endif
-
-#if defined (HISTORY)
- old_remember_on_history = remember_on_history;
-# if defined (BANG_HISTORY)
- old_history_expansion_inhibited = history_expansion_inhibited;
-# endif
- bash_history_disable ();
-#endif
-
- orig_line_number = line_number;
- orig_line_count = current_command_line_count;
- orig_input_terminator = shell_input_line_terminator;
- old_echo_input = echo_input_at_read;
- old_expand_aliases = expand_aliases;
-
- push_stream (1);
- last_read_token = WORD; /* WORD to allow reserved words here */
- current_command_line_count = 0;
- echo_input_at_read = expand_aliases = 0;
-
- with_input_from_string (s, whom);
- wl = (WORD_LIST *)NULL;
-
- if (flags & 1)
- parser_state |= PST_COMPASSIGN;
-
- while ((tok = read_token (READ)) != yacc_EOF)
- {
- if (tok == '\n' && *bash_input.location.string == '\0')
- break;
- if (tok == '\n') /* Allow newlines in compound assignments */
- continue;
- if (tok != WORD && tok != ASSIGNMENT_WORD)
- {
- line_number = orig_line_number + line_number - 1;
- orig_current_token = current_token;
- current_token = tok;
- yyerror (NULL); /* does the right thing */
- current_token = orig_current_token;
- if (wl)
- dispose_words (wl);
- wl = &parse_string_error;
- break;
- }
- wl = make_word_list (yylval.word, wl);
- }
-
- last_read_token = '\n';
- pop_stream ();
-
-#if defined (HISTORY)
- remember_on_history = old_remember_on_history;
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = old_history_expansion_inhibited;
-# endif /* BANG_HISTORY */
-#endif /* HISTORY */
-
- echo_input_at_read = old_echo_input;
- expand_aliases = old_expand_aliases;
-
- current_command_line_count = orig_line_count;
- shell_input_line_terminator = orig_input_terminator;
-
- if (flags & 1)
- parser_state &= ~PST_COMPASSIGN;
-
- if (wl == &parse_string_error)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- if (interactive_shell == 0 && posixly_correct)
- jump_to_top_level (FORCE_EOF);
- else
- jump_to_top_level (DISCARD);
- }
-
- return (REVERSE_LIST (wl, WORD_LIST *));
-}
-
-static char *
-parse_compound_assignment (retlenp)
- int *retlenp;
-{
- WORD_LIST *wl, *rl;
- int tok, orig_line_number, orig_token_size;
- char *saved_token, *ret;
-
- saved_token = token;
- orig_token_size = token_buffer_size;
- orig_line_number = line_number;
-
- last_read_token = WORD; /* WORD to allow reserved words here */
-
- token = (char *)NULL;
- token_buffer_size = 0;
-
- wl = (WORD_LIST *)NULL; /* ( */
- parser_state |= PST_COMPASSIGN;
-
- while ((tok = read_token (READ)) != ')')
- {
- if (tok == '\n') /* Allow newlines in compound assignments */
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- continue;
- }
- if (tok != WORD && tok != ASSIGNMENT_WORD)
- {
- current_token = tok; /* for error reporting */
- if (tok == yacc_EOF) /* ( */
- parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'"));
- else
- yyerror(NULL); /* does the right thing */
- if (wl)
- dispose_words (wl);
- wl = &parse_string_error;
- break;
- }
- wl = make_word_list (yylval.word, wl);
- }
-
- FREE (token);
- token = saved_token;
- token_buffer_size = orig_token_size;
-
- parser_state &= ~PST_COMPASSIGN;
-
- if (wl == &parse_string_error)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- last_read_token = '\n'; /* XXX */
- if (interactive_shell == 0 && posixly_correct)
- jump_to_top_level (FORCE_EOF);
- else
- jump_to_top_level (DISCARD);
- }
-
- last_read_token = WORD;
- if (wl)
- {
- rl = REVERSE_LIST (wl, WORD_LIST *);
- ret = string_list (rl);
- dispose_words (rl);
- }
- else
- ret = (char *)NULL;
-
- if (retlenp)
- *retlenp = (ret && *ret) ? strlen (ret) : 0;
- return ret;
-}
-
-/************************************************
- * *
- * SAVING AND RESTORING PARTIAL PARSE STATE *
- * *
- ************************************************/
-
-sh_parser_state_t *
-save_parser_state (ps)
- sh_parser_state_t *ps;
-{
-#if defined (ARRAY_VARS)
- SHELL_VAR *v;
-#endif
-
- if (ps == 0)
- ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t));
- if (ps == 0)
- return ((sh_parser_state_t *)NULL);
-
- ps->parser_state = parser_state;
- ps->token_state = save_token_state ();
-
- ps->input_line_terminator = shell_input_line_terminator;
- ps->eof_encountered = eof_encountered;
-
- ps->current_command_line_count = current_command_line_count;
-
-#if defined (HISTORY)
- ps->remember_on_history = remember_on_history;
-# if defined (BANG_HISTORY)
- ps->history_expansion_inhibited = history_expansion_inhibited;
-# endif
-#endif
-
- ps->last_command_exit_value = last_command_exit_value;
-#if defined (ARRAY_VARS)
- v = find_variable ("PIPESTATUS");
- if (v && array_p (v) && array_cell (v))
- ps->pipestatus = array_copy (array_cell (v));
- else
- ps->pipestatus = (ARRAY *)NULL;
-#endif
-
- ps->last_shell_builtin = last_shell_builtin;
- ps->this_shell_builtin = this_shell_builtin;
-
- ps->expand_aliases = expand_aliases;
- ps->echo_input_at_read = echo_input_at_read;
-
- return (ps);
-}
-
-void
-restore_parser_state (ps)
- sh_parser_state_t *ps;
-{
-#if defined (ARRAY_VARS)
- SHELL_VAR *v;
-#endif
-
- if (ps == 0)
- return;
-
- parser_state = ps->parser_state;
- if (ps->token_state)
- {
- restore_token_state (ps->token_state);
- free (ps->token_state);
- }
-
- shell_input_line_terminator = ps->input_line_terminator;
- eof_encountered = ps->eof_encountered;
-
- current_command_line_count = ps->current_command_line_count;
-
-#if defined (HISTORY)
- remember_on_history = ps->remember_on_history;
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = ps->history_expansion_inhibited;
-# endif
-#endif
-
- last_command_exit_value = ps->last_command_exit_value;
-#if defined (ARRAY_VARS)
- v = find_variable ("PIPESTATUS");
- if (v && array_p (v) && array_cell (v))
- {
- array_dispose (array_cell (v));
- var_setarray (v, ps->pipestatus);
- }
-#endif
-
- last_shell_builtin = ps->last_shell_builtin;
- this_shell_builtin = ps->this_shell_builtin;
-
- expand_aliases = ps->expand_aliases;
- echo_input_at_read = ps->echo_input_at_read;
-}
-
-/************************************************
- * *
- * MULTIBYTE CHARACTER HANDLING *
- * *
- ************************************************/
-
-#if defined (HANDLE_MULTIBYTE)
-static void
-set_line_mbstate ()
-{
- int i, previ, len, c;
- mbstate_t mbs, prevs;
- size_t mbclen;
-
- if (shell_input_line == NULL)
- return;
- len = strlen (shell_input_line); /* XXX - shell_input_line_len ? */
- FREE (shell_input_line_property);
- shell_input_line_property = (char *)xmalloc (len + 1);
-
- memset (&prevs, '\0', sizeof (mbstate_t));
- for (i = previ = 0; i < len; i++)
- {
- mbs = prevs;
-
- c = shell_input_line[i];
- if (c == EOF)
- {
- int j;
- for (j = i; j < len; j++)
- shell_input_line_property[j] = 1;
- break;
- }
-
- mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
- if (mbclen == 1 || mbclen == (size_t)-1)
- {
- mbclen = 1;
- previ = i + 1;
- }
- else if (mbclen == (size_t)-2)
- mbclen = 0;
- else if (mbclen > 1)
- {
- mbclen = 0;
- previ = i + 1;
- prevs = mbs;
- }
- else
- {
- /* XXX - what to do if mbrlen returns 0? (null wide character) */
- int j;
- for (j = i; j < len; j++)
- shell_input_line_property[j] = 1;
- break;
- }
-
- shell_input_line_property[i] = mbclen;
- }
-}
-#endif /* HANDLE_MULTIBYTE */
diff --git a/parse.y.save26 b/parse.y.save26
deleted file mode 100644
index 97f603b7..00000000
--- a/parse.y.save26
+++ /dev/null
@@ -1,4927 +0,0 @@
-/* Yacc grammar for bash. */
-
-/* Copyright (C) 1989-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 LICENSE. If not, write to the Free Software
- Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
-
-%{
-#include "config.h"
-
-#include "bashtypes.h"
-#include "bashansi.h"
-
-#include "filecntl.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_LOCALE_H)
-# include <locale.h>
-#endif
-
-#include <stdio.h>
-#include "chartypes.h"
-#include <signal.h>
-
-#include "memalloc.h"
-
-#include "bashintl.h"
-
-#define NEED_STRFTIME_DECL /* used in externs.h */
-
-#include "shell.h"
-#include "trap.h"
-#include "flags.h"
-#include "parser.h"
-#include "mailcheck.h"
-#include "test.h"
-#include "builtins.h"
-#include "builtins/common.h"
-#include "builtins/builtext.h"
-
-#include "shmbutil.h"
-
-#if defined (READLINE)
-# include "bashline.h"
-# include <readline/readline.h>
-#endif /* READLINE */
-
-#if defined (HISTORY)
-# include "bashhist.h"
-# include <readline/history.h>
-#endif /* HISTORY */
-
-#if defined (JOB_CONTROL)
-# include "jobs.h"
-#endif /* JOB_CONTROL */
-
-#if defined (ALIAS)
-# include "alias.h"
-#else
-typedef void *alias_t;
-#endif /* ALIAS */
-
-#if defined (PROMPT_STRING_DECODE)
-# ifndef _MINIX
-# include <sys/param.h>
-# endif
-# include <time.h>
-# if defined (TM_IN_SYS_TIME)
-# include <sys/types.h>
-# include <sys/time.h>
-# endif /* TM_IN_SYS_TIME */
-# include "maxpath.h"
-#endif /* PROMPT_STRING_DECODE */
-
-#define RE_READ_TOKEN -99
-#define NO_EXPANSION -100
-
-#ifdef DEBUG
-# define YYDEBUG 1
-#else
-# define YYDEBUG 0
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
-# define last_shell_getc_is_singlebyte \
- ((shell_input_line_index > 1) \
- ? shell_input_line_property[shell_input_line_index - 1] \
- : 1)
-# define MBTEST(x) ((x) && last_shell_getc_is_singlebyte)
-#else
-# define last_shell_getc_is_singlebyte 1
-# define MBTEST(x) ((x))
-#endif
-
-#if defined (EXTENDED_GLOB)
-extern int extended_glob;
-#endif
-
-extern int eof_encountered;
-extern int no_line_editing, running_under_emacs;
-extern int current_command_number;
-extern int sourcelevel;
-extern int posixly_correct;
-extern int last_command_exit_value;
-extern int interrupt_immediately;
-extern char *shell_name, *current_host_name;
-extern char *dist_version;
-extern int patch_level;
-extern int dump_translatable_strings, dump_po_strings;
-extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
-#if defined (BUFFERED_INPUT)
-extern int bash_input_fd_changed;
-#endif
-
-extern int errno;
-/* **************************************************************** */
-/* */
-/* "Forward" declarations */
-/* */
-/* **************************************************************** */
-
-#ifdef DEBUG
-static void debug_parser __P((int));
-#endif
-
-static int yy_getc __P((void));
-static int yy_ungetc __P((int));
-
-#if defined (READLINE)
-static int yy_readline_get __P((void));
-static int yy_readline_unget __P((int));
-#endif
-
-static int yy_string_get __P((void));
-static int yy_string_unget __P((int));
-static int yy_stream_get __P((void));
-static int yy_stream_unget __P((int));
-
-static int shell_getc __P((int));
-static void shell_ungetc __P((int));
-static void discard_until __P((int));
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
-static void push_string __P((char *, int, alias_t *));
-static void pop_string __P((void));
-static void free_string_list __P((void));
-#endif
-
-static char *read_a_line __P((int));
-
-static int reserved_word_acceptable __P((int));
-static int yylex __P((void));
-static int alias_expand_token __P((char *));
-static int time_command_acceptable __P((void));
-static int special_case_tokens __P((char *));
-static int read_token __P((int));
-static char *parse_matched_pair __P((int, int, int, int *, int));
-#if defined (ARRAY_VARS)
-static char *parse_compound_assignment __P((int *));
-#endif
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
-static int parse_dparen __P((int));
-static int parse_arith_cmd __P((char **, int));
-#endif
-#if defined (COND_COMMAND)
-static void cond_error __P((void));
-static COND_COM *cond_expr __P((void));
-static COND_COM *cond_or __P((void));
-static COND_COM *cond_and __P((void));
-static COND_COM *cond_term __P((void));
-static int cond_skip_newlines __P((void));
-static COMMAND *parse_cond_command __P((void));
-#endif
-#if defined (ARRAY_VARS)
-static int token_is_assignment __P((char *, int));
-static int token_is_ident __P((char *, int));
-#endif
-static int read_token_word __P((int));
-static void discard_parser_constructs __P((int));
-
-static char *error_token_from_token __P((int));
-static char *error_token_from_text __P((void));
-static void print_offending_line __P((void));
-static void report_syntax_error __P((char *));
-
-static void handle_eof_input_unit __P((void));
-static void prompt_again __P((void));
-#if 0
-static void reset_readline_prompt __P((void));
-#endif
-static void print_prompt __P((void));
-
-#if defined (HISTORY)
-char *history_delimiting_chars __P((void));
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
-static void set_line_mbstate __P((void));
-static char *shell_input_line_property = NULL;
-#else
-# define set_line_mbstate()
-#endif
-
-extern int yyerror __P((const char *));
-
-#ifdef DEBUG
-extern int yydebug;
-#endif
-
-/* Default prompt strings */
-char *primary_prompt = PPROMPT;
-char *secondary_prompt = SPROMPT;
-
-/* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
-char *ps1_prompt, *ps2_prompt;
-
-/* Handle on the current prompt string. Indirectly points through
- ps1_ or ps2_prompt. */
-char **prompt_string_pointer = (char **)NULL;
-char *current_prompt_string;
-
-/* Non-zero means we expand aliases in commands. */
-int expand_aliases = 0;
-
-/* If non-zero, the decoded prompt string undergoes parameter and
- variable substitution, command substitution, arithmetic substitution,
- string expansion, process substitution, and quote removal in
- decode_prompt_string. */
-int promptvars = 1;
-
-/* If non-zero, $'...' and $"..." are expanded when they appear within
- a ${...} expansion, even when the expansion appears within double
- quotes. */
-int extended_quote = 1;
-
-/* The decoded prompt string. Used if READLINE is not defined or if
- editing is turned off. Analogous to current_readline_prompt. */
-static char *current_decoded_prompt;
-
-/* The number of lines read from input while creating the current command. */
-int current_command_line_count;
-
-/* Variables to manage the task of reading here documents, because we need to
- defer the reading until after a complete command has been collected. */
-static REDIRECT *redir_stack[10];
-int need_here_doc;
-
-/* Where shell input comes from. History expansion is performed on each
- line when the shell is interactive. */
-static char *shell_input_line = (char *)NULL;
-static int shell_input_line_index;
-static int shell_input_line_size; /* Amount allocated for shell_input_line. */
-static int shell_input_line_len; /* strlen (shell_input_line) */
-
-/* Either zero or EOF. */
-static int shell_input_line_terminator;
-
-/* The line number in a script on which a function definition starts. */
-static int function_dstart;
-
-/* The line number in a script on which a function body starts. */
-static int function_bstart;
-
-/* The line number in a script at which an arithmetic for command starts. */
-static int arith_for_lineno;
-
-/* The line number in a script where the word in a `case WORD', `select WORD'
- or `for WORD' begins. This is a nested command maximum, since the array
- index is decremented after a case, select, or for command is parsed. */
-#define MAX_CASE_NEST 128
-static int word_lineno[MAX_CASE_NEST];
-static int word_top = -1;
-
-/* If non-zero, it is the token that we want read_token to return
- regardless of what text is (or isn't) present to be read. This
- is reset by read_token. If token_to_read == WORD or
- ASSIGNMENT_WORD, yylval.word should be set to word_desc_to_read. */
-static int token_to_read;
-static WORD_DESC *word_desc_to_read;
-
-static REDIRECTEE redir;
-%}
-
-%union {
- WORD_DESC *word; /* the word that we read. */
- int number; /* the number that we read. */
- WORD_LIST *word_list;
- COMMAND *command;
- REDIRECT *redirect;
- ELEMENT element;
- PATTERN_LIST *pattern;
-}
-
-/* Reserved words. Members of the first group are only recognized
- in the case that they are preceded by a list_terminator. Members
- of the second group are for [[...]] commands. Members of the
- third group are recognized only under special circumstances. */
-%token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION
-%token COND_START COND_END COND_ERROR
-%token IN BANG TIME TIMEOPT
-
-/* More general tokens. yylex () knows how to make these. */
-%token <word> WORD ASSIGNMENT_WORD
-%token <number> NUMBER
-%token <word_list> ARITH_CMD ARITH_FOR_EXPRS
-%token <command> COND_CMD
-%token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND LESS_LESS_LESS
-%token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER
-%token GREATER_BAR
-
-/* The types that the various syntactical units return. */
-
-%type <command> inputunit command pipeline pipeline_command
-%type <command> list list0 list1 compound_list simple_list simple_list1
-%type <command> simple_command shell_command
-%type <command> for_command select_command case_command group_command
-%type <command> arith_command
-%type <command> cond_command
-%type <command> arith_for_command
-%type <command> function_def function_body if_command elif_clause subshell
-%type <redirect> redirection redirection_list
-%type <element> simple_command_element
-%type <word_list> word_list pattern
-%type <pattern> pattern_list case_clause_sequence case_clause
-%type <number> timespec
-%type <number> list_terminator
-
-%start inputunit
-
-%left '&' ';' '\n' yacc_EOF
-%left AND_AND OR_OR
-%right '|'
-%%
-
-inputunit: simple_list simple_list_terminator
- {
- /* Case of regular command. Discard the error
- safety net,and return the command just parsed. */
- global_command = $1;
- eof_encountered = 0;
- /* discard_parser_constructs (0); */
- YYACCEPT;
- }
- | '\n'
- {
- /* Case of regular command, but not a very
- interesting one. Return a NULL command. */
- global_command = (COMMAND *)NULL;
- YYACCEPT;
- }
- | error '\n'
- {
- /* Error during parsing. Return NULL command. */
- global_command = (COMMAND *)NULL;
- eof_encountered = 0;
- /* discard_parser_constructs (1); */
- if (interactive)
- {
- YYACCEPT;
- }
- else
- {
- YYABORT;
- }
- }
- | yacc_EOF
- {
- /* Case of EOF seen by itself. Do ignoreeof or
- not. */
- global_command = (COMMAND *)NULL;
- handle_eof_input_unit ();
- YYACCEPT;
- }
- ;
-
-word_list: WORD
- { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
- | word_list WORD
- { $$ = make_word_list ($2, $1); }
- ;
-
-redirection: '>' WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_output_direction, redir);
- }
- | '<' WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_input_direction, redir);
- }
- | NUMBER '>' WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_output_direction, redir);
- }
- | NUMBER '<' WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_input_direction, redir);
- }
- | GREATER_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_appending_to, redir);
- }
- | NUMBER GREATER_GREATER WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_appending_to, redir);
- }
- | LESS_LESS WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | NUMBER LESS_LESS WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | LESS_LESS_LESS WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_reading_string, redir);
- }
- | NUMBER LESS_LESS_LESS WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_reading_string, redir);
- }
- | LESS_AND NUMBER
- {
- redir.dest = $2;
- $$ = make_redirection (0, r_duplicating_input, redir);
- }
- | NUMBER LESS_AND NUMBER
- {
- redir.dest = $3;
- $$ = make_redirection ($1, r_duplicating_input, redir);
- }
- | GREATER_AND NUMBER
- {
- redir.dest = $2;
- $$ = make_redirection (1, r_duplicating_output, redir);
- }
- | NUMBER GREATER_AND NUMBER
- {
- redir.dest = $3;
- $$ = make_redirection ($1, r_duplicating_output, redir);
- }
- | LESS_AND WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_duplicating_input_word, redir);
- }
- | NUMBER LESS_AND WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_duplicating_input_word, redir);
- }
- | GREATER_AND WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_duplicating_output_word, redir);
- }
- | NUMBER GREATER_AND WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_duplicating_output_word, redir);
- }
- | LESS_LESS_MINUS WORD
- {
- redir.filename = $2;
- $$ = make_redirection
- (0, r_deblank_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | NUMBER LESS_LESS_MINUS WORD
- {
- redir.filename = $3;
- $$ = make_redirection
- ($1, r_deblank_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | GREATER_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection (1, r_close_this, redir);
- }
- | NUMBER GREATER_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection ($1, r_close_this, redir);
- }
- | LESS_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection (0, r_close_this, redir);
- }
- | NUMBER LESS_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection ($1, r_close_this, redir);
- }
- | AND_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_err_and_out, redir);
- }
- | NUMBER LESS_GREATER WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_input_output, redir);
- }
- | LESS_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_input_output, redir);
- }
- | GREATER_BAR WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_output_force, redir);
- }
- | NUMBER GREATER_BAR WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_output_force, redir);
- }
- ;
-
-simple_command_element: WORD
- { $$.word = $1; $$.redirect = 0; }
- | ASSIGNMENT_WORD
- { $$.word = $1; $$.redirect = 0; }
- | redirection
- { $$.redirect = $1; $$.word = 0; }
- ;
-
-redirection_list: redirection
- {
- $$ = $1;
- }
- | redirection_list redirection
- {
- register REDIRECT *t;
-
- for (t = $1; t->next; t = t->next)
- ;
- t->next = $2;
- $$ = $1;
- }
- ;
-
-simple_command: simple_command_element
- { $$ = make_simple_command ($1, (COMMAND *)NULL); }
- | simple_command simple_command_element
- { $$ = make_simple_command ($2, $1); }
- ;
-
-command: simple_command
- { $$ = clean_simple_command ($1); }
- | shell_command
- { $$ = $1; }
- | shell_command redirection_list
- {
- COMMAND *tc;
-
- tc = $1;
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = $2;
- }
- else
- tc->redirects = $2;
- $$ = $1;
- }
- | function_def
- { $$ = $1; }
- ;
-
-shell_command: for_command
- { $$ = $1; }
- | case_command
- { $$ = $1; }
- | WHILE compound_list DO compound_list DONE
- { $$ = make_while_command ($2, $4); }
- | UNTIL compound_list DO compound_list DONE
- { $$ = make_until_command ($2, $4); }
- | select_command
- { $$ = $1; }
- | if_command
- { $$ = $1; }
- | subshell
- { $$ = $1; }
- | group_command
- { $$ = $1; }
- | arith_command
- { $$ = $1; }
- | cond_command
- { $$ = $1; }
- | arith_for_command
- { $$ = $1; }
- ;
-
-for_command: FOR WORD newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD ';' newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD ';' newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN word_list list_terminator newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN word_list list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN list_terminator newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-arith_for_command: FOR ARITH_FOR_EXPRS list_terminator newline_list DO compound_list DONE
- {
- $$ = make_arith_for_command ($2, $6, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_arith_for_command ($2, $6, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS DO compound_list DONE
- {
- $$ = make_arith_for_command ($2, $4, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS '{' compound_list '}'
- {
- $$ = make_arith_for_command ($2, $4, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- ;
-
-select_command: SELECT WORD newline_list DO list DONE
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list '{' list '}'
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD ';' newline_list DO list DONE
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD ';' newline_list '{' list '}'
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list IN word_list list_terminator newline_list DO list DONE
- {
- $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list IN word_list list_terminator newline_list '{' list '}'
- {
- $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-case_command: CASE WORD newline_list IN newline_list ESAC
- {
- $$ = make_case_command ($2, (PATTERN_LIST *)NULL, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | CASE WORD newline_list IN case_clause_sequence newline_list ESAC
- {
- $$ = make_case_command ($2, $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | CASE WORD newline_list IN case_clause ESAC
- {
- $$ = make_case_command ($2, $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-function_def: WORD '(' ')' newline_list function_body
- { $$ = make_function_def ($1, $5, function_dstart, function_bstart); }
-
- | FUNCTION WORD '(' ')' newline_list function_body
- { $$ = make_function_def ($2, $6, function_dstart, function_bstart); }
-
- | FUNCTION WORD newline_list function_body
- { $$ = make_function_def ($2, $4, function_dstart, function_bstart); }
- ;
-
-
-function_body: shell_command
- { $$ = $1; }
- | shell_command redirection_list
- {
- COMMAND *tc;
-
- tc = $1;
- /* According to Posix.2 3.9.5, redirections
- specified after the body of a function should
- be attached to the function and performed when
- the function is executed, not as part of the
- function definition command. */
- /* XXX - I don't think it matters, but we might
- want to change this in the future to avoid
- problems differentiating between a function
- definition with a redirection and a function
- definition containing a single command with a
- redirection. The two are semantically equivalent,
- though -- the only difference is in how the
- command printing code displays the redirections. */
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = $2;
- }
- else
- tc->redirects = $2;
- $$ = $1;
- }
- ;
-
-subshell: '(' compound_list ')'
- {
- $$ = make_subshell_command ($2);
- $$->flags |= CMD_WANT_SUBSHELL;
- }
- ;
-
-if_command: IF compound_list THEN compound_list FI
- { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
- | IF compound_list THEN compound_list ELSE compound_list FI
- { $$ = make_if_command ($2, $4, $6); }
- | IF compound_list THEN compound_list elif_clause FI
- { $$ = make_if_command ($2, $4, $5); }
- ;
-
-
-group_command: '{' compound_list '}'
- { $$ = make_group_command ($2); }
- ;
-
-arith_command: ARITH_CMD
- { $$ = make_arith_command ($1); }
- ;
-
-cond_command: COND_START COND_CMD COND_END
- { $$ = $2; }
- ;
-
-elif_clause: ELIF compound_list THEN compound_list
- { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
- | ELIF compound_list THEN compound_list ELSE compound_list
- { $$ = make_if_command ($2, $4, $6); }
- | ELIF compound_list THEN compound_list elif_clause
- { $$ = make_if_command ($2, $4, $5); }
- ;
-
-case_clause: pattern_list
- | case_clause_sequence pattern_list
- { $2->next = $1; $$ = $2; }
- ;
-
-pattern_list: newline_list pattern ')' compound_list
- { $$ = make_pattern_list ($2, $4); }
- | newline_list pattern ')' newline_list
- { $$ = make_pattern_list ($2, (COMMAND *)NULL); }
- | newline_list '(' pattern ')' compound_list
- { $$ = make_pattern_list ($3, $5); }
- | newline_list '(' pattern ')' newline_list
- { $$ = make_pattern_list ($3, (COMMAND *)NULL); }
- ;
-
-case_clause_sequence: pattern_list SEMI_SEMI
- | case_clause_sequence pattern_list SEMI_SEMI
- { $2->next = $1; $$ = $2; }
- ;
-
-pattern: WORD
- { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
- | pattern '|' WORD
- { $$ = make_word_list ($3, $1); }
- ;
-
-/* A list allows leading or trailing newlines and
- newlines as operators (equivalent to semicolons).
- It must end with a newline or semicolon.
- Lists are used within commands such as if, for, while. */
-
-list: newline_list list0
- {
- $$ = $2;
- if (need_here_doc)
- gather_here_documents ();
- }
- ;
-
-compound_list: list
- | newline_list list1
- {
- $$ = $2;
- }
- ;
-
-list0: list1 '\n' newline_list
- | list1 '&' newline_list
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
- else
- $$ = command_connect ($1, (COMMAND *)NULL, '&');
- }
- | list1 ';' newline_list
-
- ;
-
-list1: list1 AND_AND newline_list list1
- { $$ = command_connect ($1, $4, AND_AND); }
- | list1 OR_OR newline_list list1
- { $$ = command_connect ($1, $4, OR_OR); }
- | list1 '&' newline_list list1
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, $4, '&');
- else
- $$ = command_connect ($1, $4, '&');
- }
- | list1 ';' newline_list list1
- { $$ = command_connect ($1, $4, ';'); }
- | list1 '\n' newline_list list1
- { $$ = command_connect ($1, $4, ';'); }
- | pipeline_command
- { $$ = $1; }
- ;
-
-simple_list_terminator: '\n'
- | yacc_EOF
- ;
-
-list_terminator:'\n'
- { $$ = '\n'; }
- | ';'
- { $$ = ';'; }
- | yacc_EOF
- { $$ = yacc_EOF; }
- ;
-
-newline_list:
- | newline_list '\n'
- ;
-
-/* A simple_list is a list that contains no significant newlines
- and no leading or trailing newlines. Newlines are allowed
- only following operators, where they are not significant.
-
- This is what an inputunit consists of. */
-
-simple_list: simple_list1
- {
- $$ = $1;
- if (need_here_doc)
- gather_here_documents ();
- }
- | simple_list1 '&'
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
- else
- $$ = command_connect ($1, (COMMAND *)NULL, '&');
- if (need_here_doc)
- gather_here_documents ();
- }
- | simple_list1 ';'
- {
- $$ = $1;
- if (need_here_doc)
- gather_here_documents ();
- }
- ;
-
-simple_list1: simple_list1 AND_AND newline_list simple_list1
- { $$ = command_connect ($1, $4, AND_AND); }
- | simple_list1 OR_OR newline_list simple_list1
- { $$ = command_connect ($1, $4, OR_OR); }
- | simple_list1 '&' simple_list1
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, $3, '&');
- else
- $$ = command_connect ($1, $3, '&');
- }
- | simple_list1 ';' simple_list1
- { $$ = command_connect ($1, $3, ';'); }
-
- | pipeline_command
- { $$ = $1; }
- ;
-
-pipeline_command: pipeline
- { $$ = $1; }
- | BANG pipeline
- {
- if ($2)
- $2->flags |= CMD_INVERT_RETURN;
- $$ = $2;
- }
- | timespec pipeline
- {
- if ($2)
- $2->flags |= $1;
- $$ = $2;
- }
- | timespec BANG pipeline
- {
- if ($3)
- $3->flags |= $1|CMD_INVERT_RETURN;
- $$ = $3;
- }
- | BANG timespec pipeline
- {
- if ($3)
- $3->flags |= $2|CMD_INVERT_RETURN;
- $$ = $3;
- }
- | timespec list_terminator
- {
- ELEMENT x;
-
- /* Boy, this is unclean. `time' by itself can
- time a null command. We cheat and push a
- newline back if the list_terminator was a newline
- to avoid the double-newline problem (one to
- terminate this, one to terminate the command) */
- x.word = 0;
- x.redirect = 0;
- $$ = make_simple_command (x, (COMMAND *)NULL);
- $$->flags |= $1;
- /* XXX - let's cheat and push a newline back */
- if ($2 == '\n')
- token_to_read = '\n';
- }
-
- ;
-
-pipeline:
- pipeline '|' newline_list pipeline
- { $$ = command_connect ($1, $4, '|'); }
- | command
- { $$ = $1; }
- ;
-
-timespec: TIME
- { $$ = CMD_TIME_PIPELINE; }
- | TIME TIMEOPT
- { $$ = CMD_TIME_PIPELINE|CMD_TIME_POSIX; }
- ;
-%%
-
-/* Possible states for the parser that require it to do special things. */
-#define PST_CASEPAT 0x0001 /* in a case pattern list */
-#define PST_ALEXPNEXT 0x0002 /* expand next word for aliases */
-#define PST_ALLOWOPNBRC 0x0004 /* allow open brace for function def */
-#define PST_NEEDCLOSBRC 0x0008 /* need close brace */
-#define PST_DBLPAREN 0x0010 /* double-paren parsing */
-#define PST_SUBSHELL 0x0020 /* ( ... ) subshell */
-#define PST_CMDSUBST 0x0040 /* $( ... ) command substitution */
-#define PST_CASESTMT 0x0080 /* parsing a case statement */
-#define PST_CONDCMD 0x0100 /* parsing a [[...]] command */
-#define PST_CONDEXPR 0x0200 /* parsing the guts of [[...]] */
-#define PST_ARITHFOR 0x0400 /* parsing an arithmetic for command */
-#define PST_ALEXPAND 0x0800 /* OK to expand aliases - unused */
-#define PST_CMDTOKEN 0x1000 /* command token OK - unused */
-#define PST_COMPASSIGN 0x2000 /* parsing x=(...) compound assignment */
-#define PST_ASSIGNOK 0x4000 /* assignment statement ok in this context */
-
-/* Initial size to allocate for tokens, and the
- amount to grow them by. */
-#define TOKEN_DEFAULT_INITIAL_SIZE 496
-#define TOKEN_DEFAULT_GROW_SIZE 512
-
-/* Should we call prompt_again? */
-#define SHOULD_PROMPT() \
- (interactive && (bash_input.type == st_stdin || bash_input.type == st_stream))
-
-#if defined (ALIAS)
-# define expanding_alias() (pushed_string_list && pushed_string_list->expander)
-#else
-# define expanding_alias() 0
-#endif
-
-/* The token currently being read. */
-static int current_token;
-
-/* The last read token, or NULL. read_token () uses this for context
- checking. */
-static int last_read_token;
-
-/* The token read prior to last_read_token. */
-static int token_before_that;
-
-/* The token read prior to token_before_that. */
-static int two_tokens_ago;
-
-/* The current parser state. */
-static int parser_state;
-
-/* Global var is non-zero when end of file has been reached. */
-int EOF_Reached = 0;
-
-#ifdef DEBUG
-static void
-debug_parser (i)
- int i;
-{
-#if YYDEBUG != 0
- yydebug = i;
-#endif
-}
-#endif
-
-/* yy_getc () returns the next available character from input or EOF.
- yy_ungetc (c) makes `c' the next character to read.
- init_yy_io (get, unget, type, location) makes the function GET the
- installed function for getting the next character, makes UNGET the
- installed function for un-getting a character, sets the type of stream
- (either string or file) from TYPE, and makes LOCATION point to where
- the input is coming from. */
-
-/* Unconditionally returns end-of-file. */
-int
-return_EOF ()
-{
- return (EOF);
-}
-
-/* Variable containing the current get and unget functions.
- See ./input.h for a clearer description. */
-BASH_INPUT bash_input;
-
-/* Set all of the fields in BASH_INPUT to NULL. Free bash_input.name if it
- is non-null, avoiding a memory leak. */
-void
-initialize_bash_input ()
-{
- bash_input.type = st_none;
- FREE (bash_input.name);
- bash_input.name = (char *)NULL;
- bash_input.location.file = (FILE *)NULL;
- bash_input.location.string = (char *)NULL;
- bash_input.getter = (sh_cget_func_t *)NULL;
- bash_input.ungetter = (sh_cunget_func_t *)NULL;
-}
-
-/* Set the contents of the current bash input stream from
- GET, UNGET, TYPE, NAME, and LOCATION. */
-void
-init_yy_io (get, unget, type, name, location)
- sh_cget_func_t *get;
- sh_cunget_func_t *unget;
- enum stream_type type;
- const char *name;
- INPUT_STREAM location;
-{
- bash_input.type = type;
- FREE (bash_input.name);
- bash_input.name = name ? savestring (name) : (char *)NULL;
-
- /* XXX */
-#if defined (CRAY)
- memcpy((char *)&bash_input.location.string, (char *)&location.string, sizeof(location));
-#else
- bash_input.location = location;
-#endif
- bash_input.getter = get;
- bash_input.ungetter = unget;
-}
-
-char *
-yy_input_name ()
-{
- return (bash_input.name ? bash_input.name : "stdin");
-}
-
-/* Call this to get the next character of input. */
-static int
-yy_getc ()
-{
- return (*(bash_input.getter)) ();
-}
-
-/* Call this to unget C. That is, to make C the next character
- to be read. */
-static int
-yy_ungetc (c)
- int c;
-{
- return (*(bash_input.ungetter)) (c);
-}
-
-#if defined (BUFFERED_INPUT)
-#ifdef INCLUDE_UNUSED
-int
-input_file_descriptor ()
-{
- switch (bash_input.type)
- {
- case st_stream:
- return (fileno (bash_input.location.file));
- case st_bstream:
- return (bash_input.location.buffered_fd);
- case st_stdin:
- default:
- return (fileno (stdin));
- }
-}
-#endif
-#endif /* BUFFERED_INPUT */
-
-/* **************************************************************** */
-/* */
-/* Let input be read from readline (). */
-/* */
-/* **************************************************************** */
-
-#if defined (READLINE)
-char *current_readline_prompt = (char *)NULL;
-char *current_readline_line = (char *)NULL;
-int current_readline_line_index = 0;
-
-static int
-yy_readline_get ()
-{
- SigHandler *old_sigint;
- int line_len;
- unsigned char c;
-
- if (!current_readline_line)
- {
- if (!bash_readline_initialized)
- initialize_readline ();
-
-#if defined (JOB_CONTROL)
- if (job_control)
- give_terminal_to (shell_pgrp, 0);
-#endif /* JOB_CONTROL */
-
- old_sigint = (SigHandler *)NULL;
- if (signal_is_ignored (SIGINT) == 0)
- {
- old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
- interrupt_immediately++;
- }
-
- current_readline_line = readline (current_readline_prompt ?
- current_readline_prompt : "");
-
- if (signal_is_ignored (SIGINT) == 0 && old_sigint)
- {
- interrupt_immediately--;
- set_signal_handler (SIGINT, old_sigint);
- }
-
-#if 0
- /* Reset the prompt to the decoded value of prompt_string_pointer. */
- reset_readline_prompt ();
-#endif
-
- if (current_readline_line == 0)
- return (EOF);
-
- current_readline_line_index = 0;
- line_len = strlen (current_readline_line);
-
- current_readline_line = (char *)xrealloc (current_readline_line, 2 + line_len);
- current_readline_line[line_len++] = '\n';
- current_readline_line[line_len] = '\0';
- }
-
- if (current_readline_line[current_readline_line_index] == 0)
- {
- free (current_readline_line);
- current_readline_line = (char *)NULL;
- return (yy_readline_get ());
- }
- else
- {
- c = current_readline_line[current_readline_line_index++];
- return (c);
- }
-}
-
-static int
-yy_readline_unget (c)
- int c;
-{
- if (current_readline_line_index && current_readline_line)
- current_readline_line[--current_readline_line_index] = c;
- return (c);
-}
-
-void
-with_input_from_stdin ()
-{
- INPUT_STREAM location;
-
- if (bash_input.type != st_stdin && stream_on_stack (st_stdin) == 0)
- {
- location.string = current_readline_line;
- init_yy_io (yy_readline_get, yy_readline_unget,
- st_stdin, "readline stdin", location);
- }
-}
-
-#else /* !READLINE */
-
-void
-with_input_from_stdin ()
-{
- with_input_from_stream (stdin, "stdin");
-}
-#endif /* !READLINE */
-
-/* **************************************************************** */
-/* */
-/* Let input come from STRING. STRING is zero terminated. */
-/* */
-/* **************************************************************** */
-
-static int
-yy_string_get ()
-{
- register char *string;
- register unsigned char c;
-
- string = bash_input.location.string;
-
- /* If the string doesn't exist, or is empty, EOF found. */
- if (string && *string)
- {
- c = *string++;
- bash_input.location.string = string;
- return (c);
- }
- else
- return (EOF);
-}
-
-static int
-yy_string_unget (c)
- int c;
-{
- *(--bash_input.location.string) = c;
- return (c);
-}
-
-void
-with_input_from_string (string, name)
- char *string;
- const char *name;
-{
- INPUT_STREAM location;
-
- location.string = string;
- init_yy_io (yy_string_get, yy_string_unget, st_string, name, location);
-}
-
-/* **************************************************************** */
-/* */
-/* Let input come from STREAM. */
-/* */
-/* **************************************************************** */
-
-/* These two functions used to test the value of the HAVE_RESTARTABLE_SYSCALLS
- define, and just use getc/ungetc if it was defined, but since bash
- installs its signal handlers without the SA_RESTART flag, some signals
- (like SIGCHLD, SIGWINCH, etc.) received during a read(2) will not cause
- the read to be restarted. We need to restart it ourselves. */
-
-static int
-yy_stream_get ()
-{
- int result;
-
- result = EOF;
- if (bash_input.location.file)
- {
- if (interactive)
- interrupt_immediately++;
- result = getc_with_restart (bash_input.location.file);
- if (interactive)
- interrupt_immediately--;
- }
- return (result);
-}
-
-static int
-yy_stream_unget (c)
- int c;
-{
- return (ungetc_with_restart (c, bash_input.location.file));
-}
-
-void
-with_input_from_stream (stream, name)
- FILE *stream;
- const char *name;
-{
- INPUT_STREAM location;
-
- location.file = stream;
- init_yy_io (yy_stream_get, yy_stream_unget, st_stream, name, location);
-}
-
-typedef struct stream_saver {
- struct stream_saver *next;
- BASH_INPUT bash_input;
- int line;
-#if defined (BUFFERED_INPUT)
- BUFFERED_STREAM *bstream;
-#endif /* BUFFERED_INPUT */
-} STREAM_SAVER;
-
-/* The globally known line number. */
-int line_number = 0;
-
-#if defined (COND_COMMAND)
-static int cond_lineno;
-static int cond_token;
-#endif
-
-STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL;
-
-void
-push_stream (reset_lineno)
- int reset_lineno;
-{
- STREAM_SAVER *saver = (STREAM_SAVER *)xmalloc (sizeof (STREAM_SAVER));
-
- xbcopy ((char *)&bash_input, (char *)&(saver->bash_input), sizeof (BASH_INPUT));
-
-#if defined (BUFFERED_INPUT)
- saver->bstream = (BUFFERED_STREAM *)NULL;
- /* If we have a buffered stream, clear out buffers[fd]. */
- if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
- saver->bstream = set_buffered_stream (bash_input.location.buffered_fd,
- (BUFFERED_STREAM *)NULL);
-#endif /* BUFFERED_INPUT */
-
- saver->line = line_number;
- bash_input.name = (char *)NULL;
- saver->next = stream_list;
- stream_list = saver;
- EOF_Reached = 0;
- if (reset_lineno)
- line_number = 0;
-}
-
-void
-pop_stream ()
-{
- if (!stream_list)
- EOF_Reached = 1;
- else
- {
- STREAM_SAVER *saver = stream_list;
-
- EOF_Reached = 0;
- stream_list = stream_list->next;
-
- init_yy_io (saver->bash_input.getter,
- saver->bash_input.ungetter,
- saver->bash_input.type,
- saver->bash_input.name,
- saver->bash_input.location);
-
-#if defined (BUFFERED_INPUT)
- /* If we have a buffered stream, restore buffers[fd]. */
- /* If the input file descriptor was changed while this was on the
- save stack, update the buffered fd to the new file descriptor and
- re-establish the buffer <-> bash_input fd correspondence. */
- if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
- {
- if (bash_input_fd_changed)
- {
- bash_input_fd_changed = 0;
- if (default_buffered_input >= 0)
- {
- bash_input.location.buffered_fd = default_buffered_input;
- saver->bstream->b_fd = default_buffered_input;
- SET_CLOSE_ON_EXEC (default_buffered_input);
- }
- }
- /* XXX could free buffered stream returned as result here. */
- set_buffered_stream (bash_input.location.buffered_fd, saver->bstream);
- }
-#endif /* BUFFERED_INPUT */
-
- line_number = saver->line;
-
- FREE (saver->bash_input.name);
- free (saver);
- }
-}
-
-/* Return 1 if a stream of type TYPE is saved on the stack. */
-int
-stream_on_stack (type)
- enum stream_type type;
-{
- register STREAM_SAVER *s;
-
- for (s = stream_list; s; s = s->next)
- if (s->bash_input.type == type)
- return 1;
- return 0;
-}
-
-/* Save the current token state and return it in a malloced array. */
-int *
-save_token_state ()
-{
- int *ret;
-
- ret = (int *)xmalloc (3 * sizeof (int));
- ret[0] = last_read_token;
- ret[1] = token_before_that;
- ret[2] = two_tokens_ago;
- return ret;
-}
-
-void
-restore_token_state (ts)
- int *ts;
-{
- if (ts == 0)
- return;
- last_read_token = ts[0];
- token_before_that = ts[1];
- two_tokens_ago = ts[2];
-}
-
-/*
- * This is used to inhibit alias expansion and reserved word recognition
- * inside case statement pattern lists. A `case statement pattern list' is:
- *
- * everything between the `in' in a `case word in' and the next ')'
- * or `esac'
- * everything between a `;;' and the next `)' or `esac'
- */
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
-
-#define END_OF_ALIAS 0
-
-/*
- * Pseudo-global variables used in implementing token-wise alias expansion.
- */
-
-/*
- * Pushing and popping strings. This works together with shell_getc to
- * implement alias expansion on a per-token basis.
- */
-
-typedef struct string_saver {
- struct string_saver *next;
- int expand_alias; /* Value to set expand_alias to when string is popped. */
- char *saved_line;
-#if defined (ALIAS)
- alias_t *expander; /* alias that caused this line to be pushed. */
-#endif
- int saved_line_size, saved_line_index, saved_line_terminator;
-} STRING_SAVER;
-
-STRING_SAVER *pushed_string_list = (STRING_SAVER *)NULL;
-
-/*
- * Push the current shell_input_line onto a stack of such lines and make S
- * the current input. Used when expanding aliases. EXPAND is used to set
- * the value of expand_next_token when the string is popped, so that the
- * word after the alias in the original line is handled correctly when the
- * alias expands to multiple words. TOKEN is the token that was expanded
- * into S; it is saved and used to prevent infinite recursive expansion.
- */
-static void
-push_string (s, expand, ap)
- char *s;
- int expand;
- alias_t *ap;
-{
- STRING_SAVER *temp = (STRING_SAVER *)xmalloc (sizeof (STRING_SAVER));
-
- temp->expand_alias = expand;
- temp->saved_line = shell_input_line;
- temp->saved_line_size = shell_input_line_size;
- temp->saved_line_index = shell_input_line_index;
- temp->saved_line_terminator = shell_input_line_terminator;
-#if defined (ALIAS)
- temp->expander = ap;
-#endif
- temp->next = pushed_string_list;
- pushed_string_list = temp;
-
-#if defined (ALIAS)
- if (ap)
- ap->flags |= AL_BEINGEXPANDED;
-#endif
-
- shell_input_line = s;
- shell_input_line_size = strlen (s);
- shell_input_line_index = 0;
- shell_input_line_terminator = '\0';
-#if 0
- parser_state &= ~PST_ALEXPNEXT; /* XXX */
-#endif
-
- set_line_mbstate ();
-}
-
-/*
- * Make the top of the pushed_string stack be the current shell input.
- * Only called when there is something on the stack. Called from shell_getc
- * when it thinks it has consumed the string generated by an alias expansion
- * and needs to return to the original input line.
- */
-static void
-pop_string ()
-{
- STRING_SAVER *t;
-
- FREE (shell_input_line);
- shell_input_line = pushed_string_list->saved_line;
- shell_input_line_index = pushed_string_list->saved_line_index;
- shell_input_line_size = pushed_string_list->saved_line_size;
- shell_input_line_terminator = pushed_string_list->saved_line_terminator;
-
- if (pushed_string_list->expand_alias)
- parser_state |= PST_ALEXPNEXT;
- else
- parser_state &= ~PST_ALEXPNEXT;
-
- t = pushed_string_list;
- pushed_string_list = pushed_string_list->next;
-
-#if defined (ALIAS)
- if (t->expander)
- t->expander->flags &= ~AL_BEINGEXPANDED;
-#endif
-
- free ((char *)t);
-
- set_line_mbstate ();
-}
-
-static void
-free_string_list ()
-{
- register STRING_SAVER *t, *t1;
-
- for (t = pushed_string_list; t; )
- {
- t1 = t->next;
- FREE (t->saved_line);
-#if defined (ALIAS)
- if (t->expander)
- t->expander->flags &= ~AL_BEINGEXPANDED;
-#endif
- free ((char *)t);
- t = t1;
- }
- pushed_string_list = (STRING_SAVER *)NULL;
-}
-
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
-void
-free_pushed_string_input ()
-{
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- free_string_list ();
-#endif
-}
-
-/* Return a line of text, taken from wherever yylex () reads input.
- If there is no more input, then we return NULL. If REMOVE_QUOTED_NEWLINE
- is non-zero, we remove unquoted \<newline> pairs. This is used by
- read_secondary_line to read here documents. */
-static char *
-read_a_line (remove_quoted_newline)
- int remove_quoted_newline;
-{
- static char *line_buffer = (char *)NULL;
- static int buffer_size = 0;
- int indx = 0, c, peekc, pass_next;
-
-#if defined (READLINE)
- if (no_line_editing && SHOULD_PROMPT ())
-#else
- if (SHOULD_PROMPT ())
-#endif
- print_prompt ();
-
- pass_next = 0;
- while (1)
- {
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- c = yy_getc ();
-
- /* Ignore null bytes in input. */
- if (c == 0)
- {
-#if 0
- internal_warning ("read_a_line: ignored null byte in input");
-#endif
- continue;
- }
-
- /* If there is no more input, then we return NULL. */
- if (c == EOF)
- {
- if (interactive && bash_input.type == st_stream)
- clearerr (stdin);
- if (indx == 0)
- return ((char *)NULL);
- c = '\n';
- }
-
- /* `+2' in case the final character in the buffer is a newline. */
- RESIZE_MALLOCED_BUFFER (line_buffer, indx, 2, buffer_size, 128);
-
- /* IF REMOVE_QUOTED_NEWLINES is non-zero, we are reading a
- here document with an unquoted delimiter. In this case,
- the line will be expanded as if it were in double quotes.
- We allow a backslash to escape the next character, but we
- need to treat the backslash specially only if a backslash
- quoting a backslash-newline pair appears in the line. */
- if (pass_next)
- {
- line_buffer[indx++] = c;
- pass_next = 0;
- }
- else if (c == '\\' && remove_quoted_newline)
- {
- peekc = yy_getc ();
- if (peekc == '\n')
- {
- line_number++;
- continue; /* Make the unquoted \<newline> pair disappear. */
- }
- else
- {
- yy_ungetc (peekc);
- pass_next = 1;
- line_buffer[indx++] = c; /* Preserve the backslash. */
- }
- }
- else
- line_buffer[indx++] = c;
-
- if (c == '\n')
- {
- line_buffer[indx] = '\0';
- return (line_buffer);
- }
- }
-}
-
-/* Return a line as in read_a_line (), but insure that the prompt is
- the secondary prompt. This is used to read the lines of a here
- document. REMOVE_QUOTED_NEWLINE is non-zero if we should remove
- newlines quoted with backslashes while reading the line. It is
- non-zero unless the delimiter of the here document was quoted. */
-char *
-read_secondary_line (remove_quoted_newline)
- int remove_quoted_newline;
-{
- prompt_string_pointer = &ps2_prompt;
- if (SHOULD_PROMPT())
- prompt_again ();
- return (read_a_line (remove_quoted_newline));
-}
-
-/* **************************************************************** */
-/* */
-/* YYLEX () */
-/* */
-/* **************************************************************** */
-
-/* Reserved words. These are only recognized as the first word of a
- command. */
-STRING_INT_ALIST word_token_alist[] = {
- { "if", IF },
- { "then", THEN },
- { "else", ELSE },
- { "elif", ELIF },
- { "fi", FI },
- { "case", CASE },
- { "esac", ESAC },
- { "for", FOR },
-#if defined (SELECT_COMMAND)
- { "select", SELECT },
-#endif
- { "while", WHILE },
- { "until", UNTIL },
- { "do", DO },
- { "done", DONE },
- { "in", IN },
- { "function", FUNCTION },
-#if defined (COMMAND_TIMING)
- { "time", TIME },
-#endif
- { "{", '{' },
- { "}", '}' },
- { "!", BANG },
-#if defined (COND_COMMAND)
- { "[[", COND_START },
- { "]]", COND_END },
-#endif
- { (char *)NULL, 0}
-};
-
-/* other tokens that can be returned by read_token() */
-STRING_INT_ALIST other_token_alist[] = {
- /* Multiple-character tokens with special values */
- { "-p", TIMEOPT },
- { "&&", AND_AND },
- { "||", OR_OR },
- { ">>", GREATER_GREATER },
- { "<<", LESS_LESS },
- { "<&", LESS_AND },
- { ">&", GREATER_AND },
- { ";;", SEMI_SEMI },
- { "<<-", LESS_LESS_MINUS },
- { "<<<", LESS_LESS_LESS },
- { "&>", AND_GREATER },
- { "<>", LESS_GREATER },
- { ">|", GREATER_BAR },
- { "EOF", yacc_EOF },
- /* Tokens whose value is the character itself */
- { ">", '>' },
- { "<", '<' },
- { "-", '-' },
- { "{", '{' },
- { "}", '}' },
- { ";", ';' },
- { "(", '(' },
- { ")", ')' },
- { "|", '|' },
- { "&", '&' },
- { "newline", '\n' },
- { (char *)NULL, 0}
-};
-
-/* others not listed here:
- WORD look at yylval.word
- ASSIGNMENT_WORD look at yylval.word
- NUMBER look at yylval.number
- ARITH_CMD look at yylval.word_list
- ARITH_FOR_EXPRS look at yylval.word_list
- COND_CMD look at yylval.command
-*/
-
-/* These are used by read_token_word, but appear up here so that shell_getc
- can use them to decide when to add otherwise blank lines to the history. */
-
-/* The primary delimiter stack. */
-struct dstack dstack = { (char *)NULL, 0, 0 };
-
-/* A temporary delimiter stack to be used when decoding prompt strings.
- This is needed because command substitutions in prompt strings (e.g., PS2)
- can screw up the parser's quoting state. */
-static struct dstack temp_dstack = { (char *)NULL, 0, 0 };
-
-/* Macro for accessing the top delimiter on the stack. Returns the
- delimiter or zero if none. */
-#define current_delimiter(ds) \
- (ds.delimiter_depth ? ds.delimiters[ds.delimiter_depth - 1] : 0)
-
-#define push_delimiter(ds, character) \
- do \
- { \
- if (ds.delimiter_depth + 2 > ds.delimiter_space) \
- ds.delimiters = (char *)xrealloc \
- (ds.delimiters, (ds.delimiter_space += 10) * sizeof (char)); \
- ds.delimiters[ds.delimiter_depth] = character; \
- ds.delimiter_depth++; \
- } \
- while (0)
-
-#define pop_delimiter(ds) ds.delimiter_depth--
-
-/* Return the next shell input character. This always reads characters
- from shell_input_line; when that line is exhausted, it is time to
- read the next line. This is called by read_token when the shell is
- processing normal command input. */
-
-/* This implements one-character lookahead/lookbehind across physical input
- lines, to avoid something being lost because it's pushed back with
- shell_ungetc when we're at the start of a line. */
-static int eol_ungetc_lookahead = 0;
-
-static int
-shell_getc (remove_quoted_newline)
- int remove_quoted_newline;
-{
- register int i;
- int c;
- unsigned char uc;
- static int mustpop = 0;
-
- QUIT;
-
- if (sigwinch_received)
- {
- sigwinch_received = 0;
- get_new_window_size (0, (int *)0, (int *)0);
- }
-
- if (eol_ungetc_lookahead)
- {
- c = eol_ungetc_lookahead;
- eol_ungetc_lookahead = 0;
- return (c);
- }
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- /* If shell_input_line[shell_input_line_index] == 0, but there is
- something on the pushed list of strings, then we don't want to go
- off and get another line. We let the code down below handle it. */
-
- if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) &&
- (pushed_string_list == (STRING_SAVER *)NULL)))
-#else /* !ALIAS && !DPAREN_ARITHMETIC */
- if (!shell_input_line || !shell_input_line[shell_input_line_index])
-#endif /* !ALIAS && !DPAREN_ARITHMETIC */
- {
- line_number++;
-
- restart_read:
-
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- i = 0;
- shell_input_line_terminator = 0;
-
- /* If the shell is interatctive, but not currently printing a prompt
- (interactive_shell && interactive == 0), we don't want to print
- notifies or cleanup the jobs -- we want to defer it until we do
- print the next prompt. */
- if (interactive_shell == 0 || SHOULD_PROMPT())
- {
-#if defined (JOB_CONTROL)
- /* This can cause a problem when reading a command as the result
- of a trap, when the trap is called from flush_child. This call
- had better not cause jobs to disappear from the job table in
- that case, or we will have big trouble. */
- notify_and_cleanup ();
-#else /* !JOB_CONTROL */
- cleanup_dead_jobs ();
-#endif /* !JOB_CONTROL */
- }
-
-#if defined (READLINE)
- if (no_line_editing && SHOULD_PROMPT())
-#else
- if (SHOULD_PROMPT())
-#endif
- print_prompt ();
-
- if (bash_input.type == st_stream)
- clearerr (stdin);
-
- while (1)
- {
- c = yy_getc ();
-
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- if (c == '\0')
- {
-#if 0
- internal_warning ("shell_getc: ignored null byte in input");
-#endif
- continue;
- }
-
- RESIZE_MALLOCED_BUFFER (shell_input_line, i, 2, shell_input_line_size, 256);
-
- if (c == EOF)
- {
- if (bash_input.type == st_stream)
- clearerr (stdin);
-
- if (i == 0)
- shell_input_line_terminator = EOF;
-
- shell_input_line[i] = '\0';
- break;
- }
-
- shell_input_line[i++] = c;
-
- if (c == '\n')
- {
- shell_input_line[--i] = '\0';
- current_command_line_count++;
- break;
- }
- }
-
- shell_input_line_index = 0;
- shell_input_line_len = i; /* == strlen (shell_input_line) */
-
- set_line_mbstate ();
-
-#if defined (HISTORY)
- if (remember_on_history && shell_input_line && shell_input_line[0])
- {
- char *expansions;
-# if defined (BANG_HISTORY)
- int old_hist;
-
- /* If the current delimiter is a single quote, we should not be
- performing history expansion, even if we're on a different
- line from the original single quote. */
- old_hist = history_expansion_inhibited;
- if (current_delimiter (dstack) == '\'')
- history_expansion_inhibited = 1;
-# endif
- expansions = pre_process_line (shell_input_line, 1, 1);
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = old_hist;
-# endif
- if (expansions != shell_input_line)
- {
- free (shell_input_line);
- shell_input_line = expansions;
- shell_input_line_len = shell_input_line ?
- strlen (shell_input_line) : 0;
- if (!shell_input_line_len)
- current_command_line_count--;
-
- /* We have to force the xrealloc below because we don't know
- the true allocated size of shell_input_line anymore. */
- shell_input_line_size = shell_input_line_len;
-
- set_line_mbstate ();
- }
- }
- /* Try to do something intelligent with blank lines encountered while
- entering multi-line commands. XXX - this is grotesque */
- else if (remember_on_history && shell_input_line &&
- shell_input_line[0] == '\0' &&
- current_command_line_count > 1)
- {
- if (current_delimiter (dstack))
- /* We know shell_input_line[0] == 0 and we're reading some sort of
- quoted string. This means we've got a line consisting of only
- a newline in a quoted string. We want to make sure this line
- gets added to the history. */
- maybe_add_history (shell_input_line);
- else
- {
- char *hdcs;
- hdcs = history_delimiting_chars ();
- if (hdcs && hdcs[0] == ';')
- maybe_add_history (shell_input_line);
- }
- }
-
-#endif /* HISTORY */
-
- if (shell_input_line)
- {
- /* Lines that signify the end of the shell's input should not be
- echoed. */
- if (echo_input_at_read && (shell_input_line[0] ||
- shell_input_line_terminator != EOF))
- fprintf (stderr, "%s\n", shell_input_line);
- }
- else
- {
- shell_input_line_size = 0;
- prompt_string_pointer = &current_prompt_string;
- if (SHOULD_PROMPT ())
- prompt_again ();
- goto restart_read;
- }
-
- /* Add the newline to the end of this string, iff the string does
- not already end in an EOF character. */
- if (shell_input_line_terminator != EOF)
- {
- if (shell_input_line_len + 3 > shell_input_line_size)
- shell_input_line = (char *)xrealloc (shell_input_line,
- 1 + (shell_input_line_size += 2));
-
- shell_input_line[shell_input_line_len] = '\n';
- shell_input_line[shell_input_line_len + 1] = '\0';
-
- set_line_mbstate ();
- }
- }
-
- uc = shell_input_line[shell_input_line_index];
-
- if (uc)
- shell_input_line_index++;
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- /* If UC is NULL, we have reached the end of the current input string. If
- pushed_string_list is non-empty, it's time to pop to the previous string
- because we have fully consumed the result of the last alias expansion.
- Do it transparently; just return the next character of the string popped
- to. */
- if (!uc && (pushed_string_list != (STRING_SAVER *)NULL))
- {
- pop_string ();
- uc = shell_input_line[shell_input_line_index];
- if (uc)
- shell_input_line_index++;
- }
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
- if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n')
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- line_number++;
- goto restart_read;
- }
-
- if (!uc && shell_input_line_terminator == EOF)
- return ((shell_input_line_index != 0) ? '\n' : EOF);
-
- return (uc);
-}
-
-/* Put C back into the input for the shell. This might need changes for
- HANDLE_MULTIBYTE around EOLs. Since we (currently) never push back a
- character different than we read, shell_input_line_property doesn't need
- to change when manipulating shell_input_line. The define for
- last_shell_getc_is_singlebyte should take care of it, though. */
-static void
-shell_ungetc (c)
- int c;
-{
- if (shell_input_line && shell_input_line_index)
- shell_input_line[--shell_input_line_index] = c;
- else
- eol_ungetc_lookahead = c;
-}
-
-#ifdef INCLUDE_UNUSED
-/* Back the input pointer up by one, effectively `ungetting' a character. */
-static void
-shell_ungetchar ()
-{
- if (shell_input_line && shell_input_line_index)
- shell_input_line_index--;
-}
-#endif
-
-/* Discard input until CHARACTER is seen, then push that character back
- onto the input stream. */
-static void
-discard_until (character)
- int character;
-{
- int c;
-
- while ((c = shell_getc (0)) != EOF && c != character)
- ;
-
- if (c != EOF)
- shell_ungetc (c);
-}
-
-void
-execute_prompt_command (command)
- char *command;
-{
- char *last_lastarg;
- sh_parser_state_t ps;
-
- save_parser_state (&ps);
- last_lastarg = get_string_value ("_");
- if (last_lastarg)
- last_lastarg = savestring (last_lastarg);
-
- parse_and_execute (savestring (command), "PROMPT_COMMAND", SEVAL_NONINT|SEVAL_NOHIST);
-
- restore_parser_state (&ps);
- bind_variable ("_", last_lastarg, 0);
- FREE (last_lastarg);
-
- if (token_to_read == '\n') /* reset_parser was called */
- token_to_read = 0;
-}
-
-/* Place to remember the token. We try to keep the buffer
- at a reasonable size, but it can grow. */
-static char *token = (char *)NULL;
-
-/* Current size of the token buffer. */
-static int token_buffer_size;
-
-/* Command to read_token () explaining what we want it to do. */
-#define READ 0
-#define RESET 1
-#define prompt_is_ps1 \
- (!prompt_string_pointer || prompt_string_pointer == &ps1_prompt)
-
-/* Function for yyparse to call. yylex keeps track of
- the last two tokens read, and calls read_token. */
-static int
-yylex ()
-{
- if (interactive && (current_token == 0 || current_token == '\n'))
- {
- /* Before we print a prompt, we might have to check mailboxes.
- We do this only if it is time to do so. Notice that only here
- is the mail alarm reset; nothing takes place in check_mail ()
- except the checking of mail. Please don't change this. */
- if (prompt_is_ps1 && time_to_check_mail ())
- {
- check_mail ();
- reset_mail_timer ();
- }
-
- /* Avoid printing a prompt if we're not going to read anything, e.g.
- after resetting the parser with read_token (RESET). */
- if (token_to_read == 0 && SHOULD_PROMPT ())
- prompt_again ();
- }
-
- two_tokens_ago = token_before_that;
- token_before_that = last_read_token;
- last_read_token = current_token;
- current_token = read_token (READ);
- return (current_token);
-}
-
-/* When non-zero, we have read the required tokens
- which allow ESAC to be the next one read. */
-static int esacs_needed_count;
-
-void
-gather_here_documents ()
-{
- int r = 0;
- while (need_here_doc)
- {
- make_here_document (redir_stack[r++]);
- need_here_doc--;
- }
-}
-
-/* When non-zero, an open-brace used to create a group is awaiting a close
- brace partner. */
-static int open_brace_count;
-
-#define command_token_position(token) \
- (((token) == ASSIGNMENT_WORD) || \
- ((token) != SEMI_SEMI && reserved_word_acceptable(token)))
-
-#define assignment_acceptable(token) \
- (command_token_position(token) && ((parser_state & PST_CASEPAT) == 0))
-
-/* Check to see if TOKEN is a reserved word and return the token
- value if it is. */
-#define CHECK_FOR_RESERVED_WORD(tok) \
- do { \
- if (!dollar_present && !quoted && \
- reserved_word_acceptable (last_read_token)) \
- { \
- int i; \
- for (i = 0; word_token_alist[i].word != (char *)NULL; i++) \
- if (STREQ (tok, word_token_alist[i].word)) \
- { \
- if ((parser_state & PST_CASEPAT) && (word_token_alist[i].token != ESAC)) \
- break; \
- if (word_token_alist[i].token == TIME && time_command_acceptable () == 0) \
- break; \
- if (word_token_alist[i].token == ESAC) \
- parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \
- else if (word_token_alist[i].token == CASE) \
- parser_state |= PST_CASESTMT; \
- else if (word_token_alist[i].token == COND_END) \
- parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \
- else if (word_token_alist[i].token == COND_START) \
- parser_state |= PST_CONDCMD; \
- else if (word_token_alist[i].token == '{') \
- open_brace_count++; \
- else if (word_token_alist[i].token == '}' && open_brace_count) \
- open_brace_count--; \
- return (word_token_alist[i].token); \
- } \
- } \
- } while (0)
-
-#if defined (ALIAS)
-
- /* OK, we have a token. Let's try to alias expand it, if (and only if)
- it's eligible.
-
- It is eligible for expansion if EXPAND_ALIASES is set, and
- the token is unquoted and the last token read was a command
- separator (or expand_next_token is set), and we are currently
- processing an alias (pushed_string_list is non-empty) and this
- token is not the same as the current or any previously
- processed alias.
-
- Special cases that disqualify:
- In a pattern list in a case statement (parser_state & PST_CASEPAT). */
-
-static char *
-mk_alexpansion (s)
- char *s;
-{
- int l;
- char *r;
-
- l = strlen (s);
- r = xmalloc (l + 2);
- strcpy (r, s);
- if (r[l -1] != ' ')
- r[l++] = ' ';
- r[l] = '\0';
- return r;
-}
-
-static int
-alias_expand_token (tokstr)
- char *tokstr;
-{
- char *expanded;
- alias_t *ap;
-
- if (((parser_state & PST_ALEXPNEXT) || command_token_position (last_read_token)) &&
- (parser_state & PST_CASEPAT) == 0)
- {
- ap = find_alias (tokstr);
-
- /* Currently expanding this token. */
- if (ap && (ap->flags & AL_BEINGEXPANDED))
- return (NO_EXPANSION);
-
- /* mk_alexpansion puts an extra space on the end of the alias expansion,
- so the lookahead by the parser works right. If this gets changed,
- make sure the code in shell_getc that deals with reaching the end of
- an expanded alias is changed with it. */
- expanded = ap ? mk_alexpansion (ap->value) : (char *)NULL;
-
- if (expanded)
- {
- push_string (expanded, ap->flags & AL_EXPANDNEXT, ap);
- return (RE_READ_TOKEN);
- }
- else
- /* This is an eligible token that does not have an expansion. */
- return (NO_EXPANSION);
- }
- return (NO_EXPANSION);
-}
-#endif /* ALIAS */
-
-static int
-time_command_acceptable ()
-{
-#if defined (COMMAND_TIMING)
- switch (last_read_token)
- {
- case 0:
- case ';':
- case '\n':
- case AND_AND:
- case OR_OR:
- case '&':
- case DO:
- case THEN:
- case ELSE:
- case '{': /* } */
- case '(': /* ) */
- return 1;
- default:
- return 0;
- }
-#else
- return 0;
-#endif /* COMMAND_TIMING */
-}
-
-/* Handle special cases of token recognition:
- IN is recognized if the last token was WORD and the token
- before that was FOR or CASE or SELECT.
-
- DO is recognized if the last token was WORD and the token
- before that was FOR or SELECT.
-
- ESAC is recognized if the last token caused `esacs_needed_count'
- to be set
-
- `{' is recognized if the last token as WORD and the token
- before that was FUNCTION, or if we just parsed an arithmetic
- `for' command.
-
- `}' is recognized if there is an unclosed `{' present.
-
- `-p' is returned as TIMEOPT if the last read token was TIME.
-
- ']]' is returned as COND_END if the parser is currently parsing
- a conditional expression ((parser_state & PST_CONDEXPR) != 0)
-
- `time' is returned as TIME if and only if it is immediately
- preceded by one of `;', `\n', `||', `&&', or `&'.
-*/
-
-static int
-special_case_tokens (tokstr)
- char *tokstr;
-{
- if ((last_read_token == WORD) &&
-#if defined (SELECT_COMMAND)
- ((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
-#else
- ((token_before_that == FOR) || (token_before_that == CASE)) &&
-#endif
- (tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
- {
- if (token_before_that == CASE)
- {
- parser_state |= PST_CASEPAT;
- esacs_needed_count++;
- }
- return (IN);
- }
-
- if (last_read_token == WORD &&
-#if defined (SELECT_COMMAND)
- (token_before_that == FOR || token_before_that == SELECT) &&
-#else
- (token_before_that == FOR) &&
-#endif
- (tokstr[0] == 'd' && tokstr[1] == 'o' && tokstr[2] == '\0'))
- return (DO);
-
- /* Ditto for ESAC in the CASE case.
- Specifically, this handles "case word in esac", which is a legal
- construct, certainly because someone will pass an empty arg to the
- case construct, and we don't want it to barf. Of course, we should
- insist that the case construct has at least one pattern in it, but
- the designers disagree. */
- if (esacs_needed_count)
- {
- esacs_needed_count--;
- if (STREQ (tokstr, "esac"))
- {
- parser_state &= ~PST_CASEPAT;
- return (ESAC);
- }
- }
-
- /* The start of a shell function definition. */
- if (parser_state & PST_ALLOWOPNBRC)
- {
- parser_state &= ~PST_ALLOWOPNBRC;
- if (tokstr[0] == '{' && tokstr[1] == '\0') /* } */
- {
- open_brace_count++;
- function_bstart = line_number;
- return ('{'); /* } */
- }
- }
-
- /* We allow a `do' after a for ((...)) without an intervening
- list_terminator */
- if (last_read_token == ARITH_FOR_EXPRS && tokstr[0] == 'd' && tokstr[1] == 'o' && !tokstr[2])
- return (DO);
- if (last_read_token == ARITH_FOR_EXPRS && tokstr[0] == '{' && tokstr[1] == '\0') /* } */
- {
- open_brace_count++;
- return ('{'); /* } */
- }
-
- if (open_brace_count && reserved_word_acceptable (last_read_token) && tokstr[0] == '}' && !tokstr[1])
- {
- open_brace_count--; /* { */
- return ('}');
- }
-
-#if defined (COMMAND_TIMING)
- /* Handle -p after `time'. */
- if (last_read_token == TIME && tokstr[0] == '-' && tokstr[1] == 'p' && !tokstr[2])
- return (TIMEOPT);
-#endif
-
-#if 0
-#if defined (COMMAND_TIMING)
- if (STREQ (token, "time") && ((parser_state & PST_CASEPAT) == 0) && time_command_acceptable ())
- return (TIME);
-#endif /* COMMAND_TIMING */
-#endif
-
-#if defined (COND_COMMAND) /* [[ */
- if ((parser_state & PST_CONDEXPR) && tokstr[0] == ']' && tokstr[1] == ']' && tokstr[2] == '\0')
- return (COND_END);
-#endif
-
- return (-1);
-}
-
-/* Called from shell.c when Control-C is typed at top level. Or
- by the error rule at top level. */
-void
-reset_parser ()
-{
- dstack.delimiter_depth = 0; /* No delimiters found so far. */
- open_brace_count = 0;
-
- parser_state = 0;
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- if (pushed_string_list)
- free_string_list ();
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
- if (shell_input_line)
- {
- free (shell_input_line);
- shell_input_line = (char *)NULL;
- shell_input_line_size = shell_input_line_index = 0;
- }
-
- FREE (word_desc_to_read);
- word_desc_to_read = (WORD_DESC *)NULL;
-
- last_read_token = '\n';
- token_to_read = '\n';
-}
-
-/* Read the next token. Command can be READ (normal operation) or
- RESET (to normalize state). */
-static int
-read_token (command)
- int command;
-{
- int character; /* Current character. */
- int peek_char; /* Temporary look-ahead character. */
- int result; /* The thing to return. */
-
- if (command == RESET)
- {
- reset_parser ();
- return ('\n');
- }
-
- if (token_to_read)
- {
- result = token_to_read;
- if (token_to_read == WORD || token_to_read == ASSIGNMENT_WORD)
- {
- yylval.word = word_desc_to_read;
- word_desc_to_read = (WORD_DESC *)NULL;
- }
- token_to_read = 0;
- return (result);
- }
-
-#if defined (COND_COMMAND)
- if ((parser_state & (PST_CONDCMD|PST_CONDEXPR)) == PST_CONDCMD)
- {
- cond_lineno = line_number;
- parser_state |= PST_CONDEXPR;
- yylval.command = parse_cond_command ();
- if (cond_token != COND_END)
- {
- cond_error ();
- return (-1);
- }
- token_to_read = COND_END;
- parser_state &= ~(PST_CONDEXPR|PST_CONDCMD);
- return (COND_CMD);
- }
-#endif
-
-#if defined (ALIAS)
- /* This is a place to jump back to once we have successfully expanded a
- token with an alias and pushed the string with push_string () */
- re_read_token:
-#endif /* ALIAS */
-
- /* Read a single word from input. Start by skipping blanks. */
- while ((character = shell_getc (1)) != EOF && whitespace (character))
- ;
-
- if (character == EOF)
- {
- EOF_Reached = 1;
- return (yacc_EOF);
- }
-
- if MBTEST(character == '#' && (!interactive || interactive_comments))
- {
- /* A comment. Discard until EOL or EOF, and then return a newline. */
- discard_until ('\n');
- shell_getc (0);
- character = '\n'; /* this will take the next if statement and return. */
- }
-
- if (character == '\n')
- {
- /* If we're about to return an unquoted newline, we can go and collect
- the text of any pending here document. */
- if (need_here_doc)
- gather_here_documents ();
-
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- parser_state &= ~PST_ASSIGNOK;
-
- return (character);
- }
-
- /* Shell meta-characters. */
- if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
- {
-#if defined (ALIAS)
- /* Turn off alias tokenization iff this character sequence would
- not leave us ready to read a command. */
- if (character == '<' || character == '>')
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- parser_state &= ~PST_ASSIGNOK;
-
- peek_char = shell_getc (1);
- if (character == peek_char)
- {
- switch (character)
- {
- case '<':
- /* If '<' then we could be at "<<" or at "<<-". We have to
- look ahead one more character. */
- peek_char = shell_getc (1);
- if (peek_char == '-')
- return (LESS_LESS_MINUS);
- else if (peek_char == '<')
- return (LESS_LESS_LESS);
- else
- {
- shell_ungetc (peek_char);
- return (LESS_LESS);
- }
-
- case '>':
- return (GREATER_GREATER);
-
- case ';':
- parser_state |= PST_CASEPAT;
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- return (SEMI_SEMI);
-
- case '&':
- return (AND_AND);
-
- case '|':
- return (OR_OR);
-
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
- case '(': /* ) */
- result = parse_dparen (character);
- if (result == -2)
- break;
- else
- return result;
-#endif
- }
- }
- else if MBTEST(character == '<' && peek_char == '&')
- return (LESS_AND);
- else if MBTEST(character == '>' && peek_char == '&')
- return (GREATER_AND);
- else if MBTEST(character == '<' && peek_char == '>')
- return (LESS_GREATER);
- else if MBTEST(character == '>' && peek_char == '|')
- return (GREATER_BAR);
- else if MBTEST(peek_char == '>' && character == '&')
- return (AND_GREATER);
-
- shell_ungetc (peek_char);
-
- /* If we look like we are reading the start of a function
- definition, then let the reader know about it so that
- we will do the right thing with `{'. */
- if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
- {
- parser_state |= PST_ALLOWOPNBRC;
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
- function_dstart = line_number;
- }
-
- /* case pattern lists may be preceded by an optional left paren. If
- we're not trying to parse a case pattern list, the left paren
- indicates a subshell. */
- if MBTEST(character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
- parser_state |= PST_SUBSHELL;
- /*(*/
- else if MBTEST((parser_state & PST_CASEPAT) && character == ')')
- parser_state &= ~PST_CASEPAT;
- /*(*/
- else if MBTEST((parser_state & PST_SUBSHELL) && character == ')')
- parser_state &= ~PST_SUBSHELL;
-
-#if defined (PROCESS_SUBSTITUTION)
- /* Check for the constructs which introduce process substitution.
- Shells running in `posix mode' don't do process substitution. */
- if MBTEST(posixly_correct || ((character != '>' && character != '<') || peek_char != '(')) /*)*/
-#endif /* PROCESS_SUBSTITUTION */
- return (character);
- }
-
- /* Hack <&- (close stdin) case. Also <&N- (dup and close). */
- if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
- return (character);
-
- /* Okay, if we got this far, we have to read a word. Read one,
- and then check it against the known ones. */
- result = read_token_word (character);
-#if defined (ALIAS)
- if (result == RE_READ_TOKEN)
- goto re_read_token;
-#endif
- return result;
-}
-
-/*
- * Match a $(...) or other grouping construct. This has to handle embedded
- * quoted strings ('', ``, "") and nested constructs. It also must handle
- * reprompting the user, if necessary, after reading a newline, and returning
- * correct error values if it reads EOF.
- */
-#define P_FIRSTCLOSE 0x01
-#define P_ALLOWESC 0x02
-#define P_DQUOTE 0x04
-#define P_COMMAND 0x08 /* parsing a command, so look for comments */
-
-static char matched_pair_error;
-static char *
-parse_matched_pair (qc, open, close, lenp, flags)
- int qc; /* `"' if this construct is within double quotes */
- int open, close;
- int *lenp, flags;
-{
- int count, ch, was_dollar, in_comment, check_comment;
- int pass_next_character, nestlen, ttranslen, start_lineno;
- char *ret, *nestret, *ttrans;
- int retind, retsize, rflags;
-
- count = 1;
- pass_next_character = was_dollar = in_comment = 0;
- check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
-
- /* RFLAGS is the set of flags we want to pass to recursive calls. */
- rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE);
-
- ret = (char *)xmalloc (retsize = 64);
- retind = 0;
-
- start_lineno = line_number;
- while (count)
- {
-#if 0
- ch = shell_getc ((qc != '\'' || (flags & P_ALLOWESC)) && pass_next_character == 0);
-#else
- ch = shell_getc (qc != '\'' && pass_next_character == 0);
-#endif
- if (ch == EOF)
- {
- free (ret);
- parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
- EOF_Reached = 1; /* XXX */
- return (&matched_pair_error);
- }
-
- /* Possible reprompting. */
- if (ch == '\n' && SHOULD_PROMPT ())
- prompt_again ();
-
- if (in_comment)
- {
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
-
- if (ch == '\n')
- in_comment = 0;
-
- continue;
- }
- /* Not exactly right yet */
- else if (check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind -1])))
- in_comment = 1;
-
- if (pass_next_character) /* last char was backslash */
- {
- pass_next_character = 0;
- if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
- {
- if (retind > 0) retind--; /* swallow previously-added backslash */
- continue;
- }
-
- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
- if MBTEST(ch == CTLESC || ch == CTLNUL)
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
- else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
- else if MBTEST(ch == close) /* ending delimiter */
- count--;
-#if 1
- /* handle nested ${...} specially. */
- else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
- count++;
-#endif
- else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
- count++;
-
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
-
- if (open == '\'') /* '' inside grouping construct */
- {
- if MBTEST((flags & P_ALLOWESC) && ch == '\\')
- pass_next_character++;
- continue;
- }
-
- if MBTEST(ch == '\\') /* backslashes */
- pass_next_character++;
-
- if (open != close) /* a grouping construct */
- {
- if MBTEST(shellquote (ch))
- {
- /* '', ``, or "" inside $(...) or other grouping construct. */
- push_delimiter (dstack, ch);
- if MBTEST(was_dollar && ch == '\'') /* $'...' inside group */
- nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC|rflags);
- else
- nestret = parse_matched_pair (ch, ch, ch, &nestlen, rflags);
- pop_delimiter (dstack);
- if (nestret == &matched_pair_error)
- {
- free (ret);
- return &matched_pair_error;
- }
- if MBTEST(was_dollar && ch == '\'' && (extended_quote || (rflags & P_DQUOTE) == 0))
- {
- /* Translate $'...' here. */
- ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
- xfree (nestret);
-
- if ((rflags & P_DQUOTE) == 0)
- {
- nestret = sh_single_quote (ttrans);
- free (ttrans);
- nestlen = strlen (nestret);
- }
- else
- {
- nestret = ttrans;
- nestlen = ttranslen;
- }
- retind -= 2; /* back up before the $' */
- }
- else if MBTEST(was_dollar && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0))
- {
- /* Locale expand $"..." here. */
- ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
- xfree (nestret);
-
- nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
- free (ttrans);
- nestlen = ttranslen + 2;
- retind -= 2; /* back up before the $" */
- }
-
- if (nestlen)
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
- strcpy (ret + retind, nestret);
- retind += nestlen;
- }
- FREE (nestret);
- }
- }
- /* Parse an old-style command substitution within double quotes as a
- single word. */
- /* XXX - sh and ksh93 don't do this - XXX */
- else if MBTEST(open == '"' && ch == '`')
- {
- nestret = parse_matched_pair (0, '`', '`', &nestlen, rflags);
-add_nestret:
- if (nestret == &matched_pair_error)
- {
- free (ret);
- return &matched_pair_error;
- }
- if (nestlen)
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
- strcpy (ret + retind, nestret);
- retind += nestlen;
- }
- FREE (nestret);
- }
- else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
- {
- nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags);
- goto add_nestret;
- }
- else if MBTEST(was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
- /* check for $(), $[], or ${} inside quoted string. */
- {
- if (open == ch) /* undo previous increment */
- count--;
- if (ch == '(') /* ) */
- nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE);
- else if (ch == '{') /* } */
- nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
- else if (ch == '[') /* ] */
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
-
- goto add_nestret;
- }
- was_dollar = MBTEST(ch == '$');
- }
-
- ret[retind] = '\0';
- if (lenp)
- *lenp = retind;
- return ret;
-}
-
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
-/* Parse a double-paren construct. It can be either an arithmetic
- command, an arithmetic `for' command, or a nested subshell. Returns
- the parsed token, -1 on error, or -2 if we didn't do anything and
- should just go on. */
-static int
-parse_dparen (c)
- int c;
-{
- int cmdtyp, len, sline;
- char *wval, *wv2;
- WORD_DESC *wd;
-
-#if defined (ARITH_FOR_COMMAND)
- if (last_read_token == FOR)
- {
- arith_for_lineno = line_number;
- cmdtyp = parse_arith_cmd (&wval, 0);
- if (cmdtyp == 1)
- {
- wd = alloc_word_desc ();
- wd->word = wval;
- wd = make_word (wval);
- yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
- return (ARITH_FOR_EXPRS);
- }
- else
- return -1; /* ERROR */
- }
-#endif
-
-#if defined (DPAREN_ARITHMETIC)
- if (reserved_word_acceptable (last_read_token))
- {
- sline = line_number;
-
- cmdtyp = parse_arith_cmd (&wval, 0);
- if (cmdtyp == 1) /* arithmetic command */
- {
- wd = alloc_word_desc ();
- wd->word = wval;
- wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB|W_DQUOTE;
- yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
- return (ARITH_CMD);
- }
- else if (cmdtyp == 0) /* nested subshell */
- {
- push_string (wval, 0, (alias_t *)NULL);
- if ((parser_state & PST_CASEPAT) == 0)
- parser_state |= PST_SUBSHELL;
- return (c);
- }
- else /* ERROR */
- return -1;
- }
-#endif
-
- return -2; /* XXX */
-}
-
-/* We've seen a `(('. Look for the matching `))'. If we get it, return 1.
- If not, assume it's a nested subshell for backwards compatibility and
- return 0. In any case, put the characters we've consumed into a locally-
- allocated buffer and make *ep point to that buffer. Return -1 on an
- error, for example EOF. */
-static int
-parse_arith_cmd (ep, adddq)
- char **ep;
- int adddq;
-{
- int exp_lineno, rval, c;
- char *ttok, *tokstr;
- int ttoklen;
-
- exp_lineno = line_number;
- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
- rval = 1;
- if (ttok == &matched_pair_error)
- return -1;
- /* Check that the next character is the closing right paren. If
- not, this is a syntax error. ( */
- c = shell_getc (0);
- if MBTEST(c != ')')
- rval = 0;
-
- tokstr = (char *)xmalloc (ttoklen + 4);
-
- /* if ADDDQ != 0 then (( ... )) -> "..." */
- if (rval == 1 && adddq) /* arith cmd, add double quotes */
- {
- tokstr[0] = '"';
- strncpy (tokstr + 1, ttok, ttoklen - 1);
- tokstr[ttoklen] = '"';
- tokstr[ttoklen+1] = '\0';
- }
- else if (rval == 1) /* arith cmd, don't add double quotes */
- {
- strncpy (tokstr, ttok, ttoklen - 1);
- tokstr[ttoklen-1] = '\0';
- }
- else /* nested subshell */
- {
- tokstr[0] = '(';
- strncpy (tokstr + 1, ttok, ttoklen - 1);
- tokstr[ttoklen] = ')';
- tokstr[ttoklen+1] = c;
- tokstr[ttoklen+2] = '\0';
- }
-
- *ep = tokstr;
- FREE (ttok);
- return rval;
-}
-#endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
-
-#if defined (COND_COMMAND)
-static void
-cond_error ()
-{
- char *etext;
-
- if (EOF_Reached && cond_token != COND_ERROR) /* [[ */
- parser_error (cond_lineno, _("unexpected EOF while looking for `]]'"));
- else if (cond_token != COND_ERROR)
- {
- if (etext = error_token_from_token (cond_token))
- {
- parser_error (cond_lineno, _("syntax error in conditional expression: unexpected token `%s'"), etext);
- free (etext);
- }
- else
- parser_error (cond_lineno, _("syntax error in conditional expression"));
- }
-}
-
-static COND_COM *
-cond_expr ()
-{
- return (cond_or ());
-}
-
-static COND_COM *
-cond_or ()
-{
- COND_COM *l, *r;
-
- l = cond_and ();
- if (cond_token == OR_OR)
- {
- r = cond_or ();
- l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r);
- }
- return l;
-}
-
-static COND_COM *
-cond_and ()
-{
- COND_COM *l, *r;
-
- l = cond_term ();
- if (cond_token == AND_AND)
- {
- r = cond_and ();
- l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r);
- }
- return l;
-}
-
-static int
-cond_skip_newlines ()
-{
- while ((cond_token = read_token (READ)) == '\n')
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- }
- return (cond_token);
-}
-
-#define COND_RETURN_ERROR() \
- do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0)
-
-static COND_COM *
-cond_term ()
-{
- WORD_DESC *op;
- COND_COM *term, *tleft, *tright;
- int tok, lineno;
- char *etext;
-
- /* Read a token. It can be a left paren, a `!', a unary operator, or a
- word that should be the first argument of a binary operator. Start by
- skipping newlines, since this is a compound command. */
- tok = cond_skip_newlines ();
- lineno = line_number;
- if (tok == COND_END)
- {
- COND_RETURN_ERROR ();
- }
- else if (tok == '(')
- {
- term = cond_expr ();
- if (cond_token != ')')
- {
- if (term)
- dispose_cond_node (term); /* ( */
- if (etext = error_token_from_token (cond_token))
- {
- parser_error (lineno, _("unexpected token `%s', expected `)'"), etext);
- free (etext);
- }
- else
- parser_error (lineno, _("expected `)'"));
- COND_RETURN_ERROR ();
- }
- term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
- (void)cond_skip_newlines ();
- }
- else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0')))
- {
- if (tok == WORD)
- dispose_word (yylval.word); /* not needed */
- term = cond_term ();
- if (term)
- term->flags |= CMD_INVERT_RETURN;
- }
- else if (tok == WORD && test_unop (yylval.word->word))
- {
- op = yylval.word;
- tok = read_token (READ);
- if (tok == WORD)
- {
- tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
- term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
- }
- else
- {
- dispose_word (op);
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected argument `%s' to conditional unary operator"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected argument to conditional unary operator"));
- COND_RETURN_ERROR ();
- }
-
- (void)cond_skip_newlines ();
- }
- else if (tok == WORD) /* left argument to binary operator */
- {
- /* lhs */
- tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
-
- /* binop */
- tok = read_token (READ);
- if (tok == WORD && test_binop (yylval.word->word))
- op = yylval.word;
-#if defined (COND_REGEXP)
- else if (tok == WORD && STREQ (yylval.word->word,"=~"))
- op = yylval.word;
-#endif
- else if (tok == '<' || tok == '>')
- op = make_word_from_token (tok); /* ( */
- /* There should be a check before blindly accepting the `)' that we have
- seen the opening `('. */
- else if (tok == COND_END || tok == AND_AND || tok == OR_OR || tok == ')')
- {
- /* Special case. [[ x ]] is equivalent to [[ -n x ]], just like
- the test command. Similarly for [[ x && expr ]] or
- [[ x || expr ]] or [[ (x) ]]. */
- op = make_word ("-n");
- term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
- cond_token = tok;
- return (term);
- }
- else
- {
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected token `%s', conditional binary operator expected"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("conditional binary operator expected"));
- dispose_cond_node (tleft);
- COND_RETURN_ERROR ();
- }
-
- /* rhs */
- tok = read_token (READ);
- if (tok == WORD)
- {
- tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
- term = make_cond_node (COND_BINARY, op, tleft, tright);
- }
- else
- {
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected argument `%s' to conditional binary operator"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected argument to conditional binary operator"));
- dispose_cond_node (tleft);
- dispose_word (op);
- COND_RETURN_ERROR ();
- }
-
- (void)cond_skip_newlines ();
- }
- else
- {
- if (tok < 256)
- parser_error (line_number, _("unexpected token `%c' in conditional command"), tok);
- else if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected token `%s' in conditional command"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected token %d in conditional command"), tok);
- COND_RETURN_ERROR ();
- }
- return (term);
-}
-
-/* This is kind of bogus -- we slip a mini recursive-descent parser in
- here to handle the conditional statement syntax. */
-static COMMAND *
-parse_cond_command ()
-{
- COND_COM *cexp;
-
- cexp = cond_expr ();
- return (make_cond_command (cexp));
-}
-#endif
-
-#if defined (ARRAY_VARS)
-/* When this is called, it's guaranteed that we don't care about anything
- in t beyond i. We do save and restore the chars, though. */
-static int
-token_is_assignment (t, i)
- char *t;
- int i;
-{
- unsigned char c, c1;
- int r;
-
- c = t[i]; c1 = t[i+1];
- t[i] = '='; t[i+1] = '\0';
- r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
- t[i] = c; t[i+1] = c1;
- return r;
-}
-
-/* XXX - possible changes here for `+=' */
-static int
-token_is_ident (t, i)
- char *t;
- int i;
-{
- unsigned char c;
- int r;
-
- c = t[i];
- t[i] = '\0';
- r = legal_identifier (t);
- t[i] = c;
- return r;
-}
-#endif
-
-static int
-read_token_word (character)
- int character;
-{
- /* The value for YYLVAL when a WORD is read. */
- WORD_DESC *the_word;
-
- /* Index into the token that we are building. */
- int token_index;
-
- /* ALL_DIGITS becomes zero when we see a non-digit. */
- int all_digit_token;
-
- /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
- int dollar_present;
-
- /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
- assignment. */
- int compound_assignment;
-
- /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
- int quoted;
-
- /* Non-zero means to ignore the value of the next character, and just
- to add it no matter what. */
- int pass_next_character;
-
- /* The current delimiting character. */
- int cd;
- int result, peek_char;
- char *ttok, *ttrans;
- int ttoklen, ttranslen;
- intmax_t lvalue;
-
- if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
- token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
-
- token_index = 0;
- all_digit_token = DIGIT (character);
- dollar_present = quoted = pass_next_character = compound_assignment = 0;
-
- for (;;)
- {
- if (character == EOF)
- goto got_token;
-
- if (pass_next_character)
- {
- pass_next_character = 0;
- goto got_character;
- }
-
- cd = current_delimiter (dstack);
-
- /* Handle backslashes. Quote lots of things when not inside of
- double-quotes, quote some things inside of double-quotes. */
- if MBTEST(character == '\\')
- {
- peek_char = shell_getc (0);
-
- /* Backslash-newline is ignored in all cases except
- when quoted with single quotes. */
- if (peek_char == '\n')
- {
- character = '\n';
- goto next_character;
- }
- else
- {
- shell_ungetc (peek_char);
-
- /* If the next character is to be quoted, note it now. */
- if (cd == 0 || cd == '`' ||
- (cd == '"' && peek_char >= 0 && (sh_syntaxtab[peek_char] & CBSDQUOTE)))
- pass_next_character++;
-
- quoted = 1;
- goto got_character;
- }
- }
-
- /* Parse a matched pair of quote characters. */
- if MBTEST(shellquote (character))
- {
- push_delimiter (dstack, character);
- ttok = parse_matched_pair (character, character, character, &ttoklen, (character == '`') ? P_COMMAND : 0);
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- all_digit_token = 0;
- quoted = 1;
- dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
- FREE (ttok);
- goto next_character;
- }
-
-#ifdef EXTENDED_GLOB
- /* Parse a ksh-style extended pattern matching specification. */
- if (extended_glob && PATTERN_CHAR (character))
- {
- peek_char = shell_getc (1);
- if MBTEST(peek_char == '(') /* ) */
- {
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- token[token_index++] = peek_char;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- dollar_present = all_digit_token = 0;
- goto next_character;
- }
- else
- shell_ungetc (peek_char);
- }
-#endif /* EXTENDED_GLOB */
-
- /* If the delimiter character is not single quote, parse some of
- the shell expansions that must be read as a single word. */
- if (shellexp (character))
- {
- peek_char = shell_getc (1);
- /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
- if MBTEST(peek_char == '(' || \
- ((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
- {
- if (peek_char == '{') /* } */
- ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
- else if (peek_char == '(') /* ) */
- {
- /* XXX - push and pop the `(' as a delimiter for use by
- the command-oriented-history code. This way newlines
- appearing in the $(...) string get added to the
- history literally rather than causing a possibly-
- incorrect `;' to be added. ) */
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (cd, '(', ')', &ttoklen, P_COMMAND);
- pop_delimiter (dstack);
- }
- else
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- token[token_index++] = peek_char;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- dollar_present = 1;
- all_digit_token = 0;
- goto next_character;
- }
- /* This handles $'...' and $"..." new-style quoted strings. */
- else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
- {
- int first_line;
-
- first_line = line_number;
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (peek_char, peek_char, peek_char,
- &ttoklen,
- (peek_char == '\'') ? P_ALLOWESC : 0);
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1;
- if (peek_char == '\'')
- {
- ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen);
- free (ttok);
-
- /* Insert the single quotes and correctly quote any
- embedded single quotes (allowed because P_ALLOWESC was
- passed to parse_matched_pair). */
- ttok = sh_single_quote (ttrans);
- free (ttrans);
- ttranslen = strlen (ttok);
- ttrans = ttok;
- }
- else
- {
- /* Try to locale)-expand the converted string. */
- ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
- free (ttok);
-
- /* Add the double quotes back */
- ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
- free (ttrans);
- ttranslen += 2;
- ttrans = ttok;
- }
-
- RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- strcpy (token + token_index, ttrans);
- token_index += ttranslen;
- FREE (ttrans);
- quoted = 1;
- all_digit_token = 0;
- goto next_character;
- }
- /* This could eventually be extended to recognize all of the
- shell's single-character parameter expansions, and set flags.*/
- else if MBTEST(character == '$' && peek_char == '$')
- {
- ttok = (char *)xmalloc (3);
- ttok[0] = ttok[1] = '$';
- ttok[2] = '\0';
- RESIZE_MALLOCED_BUFFER (token, token_index, 3,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- strcpy (token + token_index, ttok);
- token_index += 2;
- dollar_present = 1;
- all_digit_token = 0;
- FREE (ttok);
- goto next_character;
- }
- else
- shell_ungetc (peek_char);
- }
-
-#if defined (ARRAY_VARS)
- /* Identify possible array subscript assignment; match [...] */
- else if MBTEST(character == '[' && token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) /* ] */
- {
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- all_digit_token = 0;
- goto next_character;
- }
- /* Identify possible compound array variable assignment. */
- else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index))
- {
- peek_char = shell_getc (1);
- if MBTEST(peek_char == '(') /* ) */
- {
- ttok = parse_compound_assignment (&ttoklen);
-
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
-
- token[token_index++] = '=';
- token[token_index++] = '(';
- if (ttok)
- {
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- }
- token[token_index++] = ')';
- FREE (ttok);
- all_digit_token = 0;
- compound_assignment = 1;
-#if 0
- goto next_character;
-#else
- goto got_token; /* ksh93 seems to do this */
-#endif
- }
- else
- shell_ungetc (peek_char);
- }
-#endif
-
- /* When not parsing a multi-character word construct, shell meta-
- characters break words. */
- if MBTEST(shellbreak (character))
- {
- shell_ungetc (character);
- goto got_token;
- }
-
- got_character:
-
- all_digit_token &= DIGIT (character);
- dollar_present |= character == '$';
-
- if (character == CTLESC || character == CTLNUL)
- token[token_index++] = CTLESC;
-
- token[token_index++] = character;
-
- RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
-
- next_character:
- if (character == '\n' && SHOULD_PROMPT ())
- prompt_again ();
-
- /* We want to remove quoted newlines (that is, a \<newline> pair)
- unless we are within single quotes or pass_next_character is
- set (the shell equivalent of literal-next). */
- cd = current_delimiter (dstack);
- character = shell_getc (cd != '\'' && pass_next_character == 0);
- } /* end for (;;) */
-
-got_token:
-
- token[token_index] = '\0';
-
- /* Check to see what thing we should return. If the last_read_token
- is a `<', or a `&', or the character which ended this token is
- a '>' or '<', then, and ONLY then, is this input token a NUMBER.
- Otherwise, it is just a word, and should be returned as such. */
- if MBTEST(all_digit_token && (character == '<' || character == '>' || \
- last_read_token == LESS_AND || \
- last_read_token == GREATER_AND))
- {
- if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
- yylval.number = lvalue;
- else
- yylval.number = -1;
- return (NUMBER);
- }
-
- /* Check for special case tokens. */
- result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
- if (result >= 0)
- return result;
-
-#if defined (ALIAS)
- /* Posix.2 does not allow reserved words to be aliased, so check for all
- of them, including special cases, before expanding the current token
- as an alias. */
- if MBTEST(posixly_correct)
- CHECK_FOR_RESERVED_WORD (token);
-
- /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
- inhibits alias expansion. */
- if (expand_aliases && quoted == 0)
- {
- result = alias_expand_token (token);
- if (result == RE_READ_TOKEN)
- return (RE_READ_TOKEN);
- else if (result == NO_EXPANSION)
- parser_state &= ~PST_ALEXPNEXT;
- }
-
- /* If not in Posix.2 mode, check for reserved words after alias
- expansion. */
- if MBTEST(posixly_correct == 0)
-#endif
- CHECK_FOR_RESERVED_WORD (token);
-
- the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
- the_word->word = (char *)xmalloc (1 + token_index);
- the_word->flags = 0;
- strcpy (the_word->word, token);
- if (dollar_present)
- the_word->flags |= W_HASDOLLAR;
- if (quoted)
- the_word->flags |= W_QUOTED;
- if (compound_assignment)
- the_word->flags |= W_COMPASSIGN;
- /* A word is an assignment if it appears at the beginning of a
- simple command, or after another assignment word. This is
- context-dependent, so it cannot be handled in the grammar. */
- if (assignment (token, (parser_state & PST_COMPASSIGN) != 0))
- {
- the_word->flags |= W_ASSIGNMENT;
- /* Don't perform word splitting on assignment statements. */
- if (assignment_acceptable (last_read_token) || (parser_state & PST_COMPASSIGN) != 0)
- the_word->flags |= W_NOSPLIT;
- }
-
- if (command_token_position (last_read_token))
- {
- struct builtin *b;
- b = builtin_address_internal (token, 0);
- if (b && (b->flags & ASSIGNMENT_BUILTIN))
- parser_state |= PST_ASSIGNOK;
- else if (STREQ (token, "eval") || STREQ (token, "let"))
- parser_state |= PST_ASSIGNOK;
- }
-
- yylval.word = the_word;
-
- result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT))
- ? ASSIGNMENT_WORD : WORD;
-
- switch (last_read_token)
- {
- case FUNCTION:
- parser_state |= PST_ALLOWOPNBRC;
- function_dstart = line_number;
- break;
- case CASE:
- case SELECT:
- case FOR:
- if (word_top < MAX_CASE_NEST)
- word_top++;
- word_lineno[word_top] = line_number;
- break;
- }
-
- return (result);
-}
-
-/* Return 1 if TOKSYM is a token that after being read would allow
- a reserved word to be seen, else 0. */
-static int
-reserved_word_acceptable (toksym)
- int toksym;
-{
- switch (toksym)
- {
- case '\n':
- case ';':
- case '(':
- case ')':
- case '|':
- case '&':
- case '{':
- case '}': /* XXX */
- case AND_AND:
- case BANG:
- case DO:
- case DONE:
- case ELIF:
- case ELSE:
- case ESAC:
- case FI:
- case IF:
- case OR_OR:
- case SEMI_SEMI:
- case THEN:
- case TIME:
- case TIMEOPT:
- case UNTIL:
- case WHILE:
- case 0:
- return 1;
- default:
- return 0;
- }
-}
-
-/* Return the index of TOKEN in the alist of reserved words, or -1 if
- TOKEN is not a shell reserved word. */
-int
-find_reserved_word (tokstr)
- char *tokstr;
-{
- int i;
- for (i = 0; word_token_alist[i].word; i++)
- if (STREQ (tokstr, word_token_alist[i].word))
- return i;
- return -1;
-}
-
-#if 0
-#if defined (READLINE)
-/* Called after each time readline is called. This insures that whatever
- the new prompt string is gets propagated to readline's local prompt
- variable. */
-static void
-reset_readline_prompt ()
-{
- char *temp_prompt;
-
- if (prompt_string_pointer)
- {
- temp_prompt = (*prompt_string_pointer)
- ? decode_prompt_string (*prompt_string_pointer)
- : (char *)NULL;
-
- if (temp_prompt == 0)
- {
- temp_prompt = (char *)xmalloc (1);
- temp_prompt[0] = '\0';
- }
-
- FREE (current_readline_prompt);
- current_readline_prompt = temp_prompt;
- }
-}
-#endif /* READLINE */
-#endif /* 0 */
-
-#if defined (HISTORY)
-/* A list of tokens which can be followed by newlines, but not by
- semi-colons. When concatenating multiple lines of history, the
- newline separator for such tokens is replaced with a space. */
-static int no_semi_successors[] = {
- '\n', '{', '(', ')', ';', '&', '|',
- CASE, DO, ELSE, IF, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR, IN,
- 0
-};
-
-/* If we are not within a delimited expression, try to be smart
- about which separators can be semi-colons and which must be
- newlines. Returns the string that should be added into the
- history entry. */
-char *
-history_delimiting_chars ()
-{
- register int i;
-
- if (dstack.delimiter_depth != 0)
- return ("\n");
-
- /* First, handle some special cases. */
- /*(*/
- /* If we just read `()', assume it's a function definition, and don't
- add a semicolon. If the token before the `)' was not `(', and we're
- not in the midst of parsing a case statement, assume it's a
- parenthesized command and add the semicolon. */
- /*)(*/
- if (token_before_that == ')')
- {
- if (two_tokens_ago == '(') /*)*/ /* function def */
- return " ";
- /* This does not work for subshells inside case statement
- command lists. It's a suboptimal solution. */
- else if (parser_state & PST_CASESTMT) /* case statement pattern */
- return " ";
- else
- return "; "; /* (...) subshell */
- }
- else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
- return " "; /* function def using `function name' without `()' */
-
- else if (token_before_that == WORD && two_tokens_ago == FOR)
- {
- /* Tricky. `for i\nin ...' should not have a semicolon, but
- `for i\ndo ...' should. We do what we can. */
- for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)
- ;
- if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
- return " ";
- return ";";
- }
- else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
- return " ";
-
- for (i = 0; no_semi_successors[i]; i++)
- {
- if (token_before_that == no_semi_successors[i])
- return (" ");
- }
-
- return ("; ");
-}
-#endif /* HISTORY */
-
-/* Issue a prompt, or prepare to issue a prompt when the next character
- is read. */
-static void
-prompt_again ()
-{
- char *temp_prompt;
-
- if (interactive == 0 || expanding_alias()) /* XXX */
- return;
-
- ps1_prompt = get_string_value ("PS1");
- ps2_prompt = get_string_value ("PS2");
-
- if (!prompt_string_pointer)
- prompt_string_pointer = &ps1_prompt;
-
- temp_prompt = *prompt_string_pointer
- ? decode_prompt_string (*prompt_string_pointer)
- : (char *)NULL;
-
- if (temp_prompt == 0)
- {
- temp_prompt = (char *)xmalloc (1);
- temp_prompt[0] = '\0';
- }
-
- current_prompt_string = *prompt_string_pointer;
- prompt_string_pointer = &ps2_prompt;
-
-#if defined (READLINE)
- if (!no_line_editing)
- {
- FREE (current_readline_prompt);
- current_readline_prompt = temp_prompt;
- }
- else
-#endif /* READLINE */
- {
- FREE (current_decoded_prompt);
- current_decoded_prompt = temp_prompt;
- }
-}
-
-int
-get_current_prompt_level ()
-{
- return ((current_prompt_string && current_prompt_string == ps2_prompt) ? 2 : 1);
-}
-
-void
-set_current_prompt_level (x)
- int x;
-{
- prompt_string_pointer = (x == 2) ? &ps2_prompt : &ps1_prompt;
- current_prompt_string = *prompt_string_pointer;
-}
-
-static void
-print_prompt ()
-{
- fprintf (stderr, "%s", current_decoded_prompt);
- fflush (stderr);
-}
-
-/* Return a string which will be printed as a prompt. The string
- may contain special characters which are decoded as follows:
-
- \a bell (ascii 07)
- \d the date in Day Mon Date format
- \e escape (ascii 033)
- \h the hostname up to the first `.'
- \H the hostname
- \j the number of active jobs
- \l the basename of the shell's tty device name
- \n CRLF
- \r CR
- \s the name of the shell
- \t the time in 24-hour hh:mm:ss format
- \T the time in 12-hour hh:mm:ss format
- \@ the time in 12-hour hh:mm am/pm format
- \A the time in 24-hour hh:mm format
- \D{fmt} the result of passing FMT to strftime(3)
- \u your username
- \v the version of bash (e.g., 2.00)
- \V the release of bash, version + patchlevel (e.g., 2.00.0)
- \w the current working directory
- \W the last element of $PWD
- \! the history number of this command
- \# the command number of this command
- \$ a $ or a # if you are root
- \nnn character code nnn in octal
- \\ a backslash
- \[ begin a sequence of non-printing chars
- \] end a sequence of non-printing chars
-*/
-#define PROMPT_GROWTH 48
-char *
-decode_prompt_string (string)
- char *string;
-{
- WORD_LIST *list;
- char *result, *t;
- struct dstack save_dstack;
- int last_exit_value;
-#if defined (PROMPT_STRING_DECODE)
- int result_size, result_index;
- int c, n;
- char *temp, octal_string[4];
- struct tm *tm;
- time_t the_time;
- char timebuf[128];
- char *timefmt;
-
- result = (char *)xmalloc (result_size = PROMPT_GROWTH);
- result[result_index = 0] = 0;
- temp = (char *)NULL;
-
- while (c = *string++)
- {
- if (posixly_correct && c == '!')
- {
- if (*string == '!')
- {
- temp = savestring ("!");
- goto add_string;
- }
- else
- {
-#if !defined (HISTORY)
- temp = savestring ("1");
-#else /* HISTORY */
- temp = itos (history_number ());
-#endif /* HISTORY */
- string--; /* add_string increments string again. */
- goto add_string;
- }
- }
- if (c == '\\')
- {
- c = *string;
-
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- strncpy (octal_string, string, 3);
- octal_string[3] = '\0';
-
- n = read_octal (octal_string);
- temp = (char *)xmalloc (3);
-
- if (n == CTLESC || n == CTLNUL)
- {
- temp[0] = CTLESC;
- temp[1] = n;
- temp[2] = '\0';
- }
- else if (n == -1)
- {
- temp[0] = '\\';
- temp[1] = '\0';
- }
- else
- {
- temp[0] = n;
- temp[1] = '\0';
- }
-
- for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
- string++;
-
- c = 0; /* tested at add_string: */
- goto add_string;
-
- case 'd':
- case 't':
- case 'T':
- case '@':
- case 'A':
- /* Make the current time/date into a string. */
- (void) time (&the_time);
- tm = localtime (&the_time);
-
- if (c == 'd')
- n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
- else if (c == 't')
- n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
- else if (c == 'T')
- n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
- else if (c == '@')
- n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
- else if (c == 'A')
- n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
-
- if (n == 0)
- timebuf[0] = '\0';
- else
- timebuf[sizeof(timebuf) - 1] = '\0';
-
- temp = savestring (timebuf);
- goto add_string;
-
- case 'D': /* strftime format */
- if (string[1] != '{') /* } */
- goto not_escape;
-
- (void) time (&the_time);
- tm = localtime (&the_time);
- string += 2; /* skip { */
- timefmt = xmalloc (strlen (string) + 3);
- for (t = timefmt; *string && *string != '}'; )
- *t++ = *string++;
- *t = '\0';
- c = *string; /* tested at add_string */
- if (timefmt[0] == '\0')
- {
- timefmt[0] = '%';
- timefmt[1] = 'X'; /* locale-specific current time */
- timefmt[2] = '\0';
- }
- n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
- free (timefmt);
-
- if (n == 0)
- timebuf[0] = '\0';
- else
- timebuf[sizeof(timebuf) - 1] = '\0';
-
- if (promptvars || posixly_correct)
- /* Make sure that expand_prompt_string is called with a
- second argument of Q_DOUBLE_QUOTES if we use this
- function here. */
- temp = sh_backslash_quote_for_double_quotes (timebuf);
- else
- temp = savestring (timebuf);
- goto add_string;
-
- case 'n':
- temp = (char *)xmalloc (3);
- temp[0] = no_line_editing ? '\n' : '\r';
- temp[1] = no_line_editing ? '\0' : '\n';
- temp[2] = '\0';
- goto add_string;
-
- case 's':
- temp = base_pathname (shell_name);
- temp = savestring (temp);
- goto add_string;
-
- case 'v':
- case 'V':
- temp = (char *)xmalloc (16);
- if (c == 'v')
- strcpy (temp, dist_version);
- else
- sprintf (temp, "%s.%d", dist_version, patch_level);
- goto add_string;
-
- case 'w':
- case 'W':
- {
- /* Use the value of PWD because it is much more efficient. */
- char t_string[PATH_MAX], *t;
- int tlen;
-
- temp = get_string_value ("PWD");
-
- if (temp == 0)
- {
- if (getcwd (t_string, sizeof(t_string)) == 0)
- {
- t_string[0] = '.';
- tlen = 1;
- }
- else
- tlen = strlen (t_string);
- }
- else
- {
- tlen = sizeof (t_string) - 1;
- strncpy (t_string, temp, tlen);
- }
- t_string[tlen] = '\0';
-
-#define ROOT_PATH(x) ((x)[0] == '/' && (x)[1] == 0)
-#define DOUBLE_SLASH_ROOT(x) ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
- /* Abbreviate \W as ~ if $PWD == $HOME */
- if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0))
- {
- if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
- {
- t = strrchr (t_string, '/');
- if (t)
- strcpy (t_string, t + 1);
- }
- }
-#undef ROOT_PATH
-#undef DOUBLE_SLASH_ROOT
- else
- /* polite_directory_format is guaranteed to return a string
- no longer than PATH_MAX - 1 characters. */
- strcpy (t_string, polite_directory_format (t_string));
-
- /* If we're going to be expanding the prompt string later,
- quote the directory name. */
- if (promptvars || posixly_correct)
- /* Make sure that expand_prompt_string is called with a
- second argument of Q_DOUBLE_QUOTES if we use this
- function here. */
- temp = sh_backslash_quote_for_double_quotes (t_string);
- else
- temp = savestring (t_string);
-
- goto add_string;
- }
-
- case 'u':
- if (current_user.user_name == 0)
- get_current_user_info ();
- temp = savestring (current_user.user_name);
- goto add_string;
-
- case 'h':
- case 'H':
- temp = savestring (current_host_name);
- if (c == 'h' && (t = (char *)strchr (temp, '.')))
- *t = '\0';
- goto add_string;
-
- case '#':
- temp = itos (current_command_number);
- goto add_string;
-
- case '!':
-#if !defined (HISTORY)
- temp = savestring ("1");
-#else /* HISTORY */
- temp = itos (history_number ());
-#endif /* HISTORY */
- goto add_string;
-
- case '$':
- t = temp = (char *)xmalloc (3);
- if ((promptvars || posixly_correct) && (current_user.euid != 0))
- *t++ = '\\';
- *t++ = current_user.euid == 0 ? '#' : '$';
- *t = '\0';
- goto add_string;
-
- case 'j':
- temp = itos (count_all_jobs ());
- goto add_string;
-
- case 'l':
-#if defined (HAVE_TTYNAME)
- temp = (char *)ttyname (fileno (stdin));
- t = temp ? base_pathname (temp) : "tty";
- temp = savestring (t);
-#else
- temp = savestring ("tty");
-#endif /* !HAVE_TTYNAME */
- goto add_string;
-
-#if defined (READLINE)
- case '[':
- case ']':
- if (no_line_editing)
- {
- string++;
- break;
- }
- temp = (char *)xmalloc (3);
- temp[0] = CTLESC;
- temp[1] = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
- temp[2] = '\0';
- goto add_string;
-#endif /* READLINE */
-
- case '\\':
- case 'a':
- case 'e':
- case 'r':
- temp = (char *)xmalloc (2);
- if (c == 'a')
- temp[0] = '\07';
- else if (c == 'e')
- temp[0] = '\033';
- else if (c == 'r')
- temp[0] = '\r';
- else /* (c == '\\') */
- temp[0] = c;
- temp[1] = '\0';
- goto add_string;
-
- default:
-not_escape:
- temp = (char *)xmalloc (3);
- temp[0] = '\\';
- temp[1] = c;
- temp[2] = '\0';
-
- add_string:
- if (c)
- string++;
- result =
- sub_append_string (temp, result, &result_index, &result_size);
- temp = (char *)NULL; /* Freed in sub_append_string (). */
- result[result_index] = '\0';
- break;
- }
- }
- else
- {
- RESIZE_MALLOCED_BUFFER (result, result_index, 3, result_size, PROMPT_GROWTH);
- result[result_index++] = c;
- result[result_index] = '\0';
- }
- }
-#else /* !PROMPT_STRING_DECODE */
- result = savestring (string);
-#endif /* !PROMPT_STRING_DECODE */
-
- /* Save the delimiter stack and point `dstack' to temp space so any
- command substitutions in the prompt string won't result in screwing
- up the parser's quoting state. */
- save_dstack = dstack;
- dstack = temp_dstack;
- dstack.delimiter_depth = 0;
-
- /* Perform variable and parameter expansion and command substitution on
- the prompt string. */
- if (promptvars || posixly_correct)
- {
- last_exit_value = last_command_exit_value;
- list = expand_prompt_string (result, Q_DOUBLE_QUOTES);
- free (result);
- result = string_list (list);
- dispose_words (list);
- last_command_exit_value = last_exit_value;
- }
- else
- {
- t = dequote_string (result);
- free (result);
- result = t;
- }
-
- dstack = save_dstack;
-
- return (result);
-}
-
-/************************************************
- * *
- * ERROR HANDLING *
- * *
- ************************************************/
-
-/* Report a syntax error, and restart the parser. Call here for fatal
- errors. */
-int
-yyerror (msg)
- const char *msg;
-{
- report_syntax_error ((char *)NULL);
- reset_parser ();
- return (0);
-}
-
-static char *
-error_token_from_token (token)
- int token;
-{
- char *t;
-
- if (t = find_token_in_alist (token, word_token_alist, 0))
- return t;
-
- if (t = find_token_in_alist (token, other_token_alist, 0))
- return t;
-
- t = (char *)NULL;
- /* This stuff is dicy and needs closer inspection */
- switch (current_token)
- {
- case WORD:
- case ASSIGNMENT_WORD:
- if (yylval.word)
- t = savestring (yylval.word->word);
- break;
- case NUMBER:
- t = itos (yylval.number);
- break;
- case ARITH_CMD:
- if (yylval.word_list)
- t = string_list (yylval.word_list);
- break;
- case ARITH_FOR_EXPRS:
- if (yylval.word_list)
- t = string_list_internal (yylval.word_list, " ; ");
- break;
- case COND_CMD:
- t = (char *)NULL; /* punt */
- break;
- }
-
- return t;
-}
-
-static char *
-error_token_from_text ()
-{
- char *msg, *t;
- int token_end, i;
-
- t = shell_input_line;
- i = shell_input_line_index;
- token_end = 0;
- msg = (char *)NULL;
-
- if (i && t[i] == '\0')
- i--;
-
- while (i && (whitespace (t[i]) || t[i] == '\n'))
- i--;
-
- if (i)
- token_end = i + 1;
-
- while (i && (member (t[i], " \n\t;|&") == 0))
- i--;
-
- while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
- i++;
-
- /* Return our idea of the offending token. */
- if (token_end || (i == 0 && token_end == 0))
- {
- if (token_end)
- msg = substring (t, i, token_end);
- else /* one-character token */
- {
- msg = (char *)xmalloc (2);
- msg[0] = t[i];
- msg[1] = '\0';
- }
- }
-
- return (msg);
-}
-
-static void
-print_offending_line ()
-{
- char *msg;
- int token_end;
-
- msg = savestring (shell_input_line);
- token_end = strlen (msg);
- while (token_end && msg[token_end - 1] == '\n')
- msg[--token_end] = '\0';
-
- parser_error (line_number, "`%s'", msg);
- free (msg);
-}
-
-/* Report a syntax error with line numbers, etc.
- Call here for recoverable errors. If you have a message to print,
- then place it in MESSAGE, otherwise pass NULL and this will figure
- out an appropriate message for you. */
-static void
-report_syntax_error (message)
- char *message;
-{
- char *msg;
-
- if (message)
- {
- parser_error (line_number, "%s", message);
- if (interactive && EOF_Reached)
- EOF_Reached = 0;
- last_command_exit_value = EX_USAGE;
- return;
- }
-
- /* If the line of input we're reading is not null, try to find the
- objectionable token. First, try to figure out what token the
- parser's complaining about by looking at current_token. */
- if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
- {
- parser_error (line_number, _("syntax error near unexpected token `%s'"), msg);
- free (msg);
-
- if (interactive == 0)
- print_offending_line ();
-
- last_command_exit_value = EX_USAGE;
- return;
- }
-
- /* If looking at the current token doesn't prove fruitful, try to find the
- offending token by analyzing the text of the input line near the current
- input line index and report what we find. */
- if (shell_input_line && *shell_input_line)
- {
- msg = error_token_from_text ();
- if (msg)
- {
- parser_error (line_number, _("syntax error near `%s'"), msg);
- free (msg);
- }
-
- /* If not interactive, print the line containing the error. */
- if (interactive == 0)
- print_offending_line ();
- }
- else
- {
- msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
- parser_error (line_number, "%s", msg);
- /* When the shell is interactive, this file uses EOF_Reached
- only for error reporting. Other mechanisms are used to
- decide whether or not to exit. */
- if (interactive && EOF_Reached)
- EOF_Reached = 0;
- }
-
- last_command_exit_value = EX_USAGE;
-}
-
-/* ??? Needed function. ??? We have to be able to discard the constructs
- created during parsing. In the case of error, we want to return
- allocated objects to the memory pool. In the case of no error, we want
- to throw away the information about where the allocated objects live.
- (dispose_command () will actually free the command.) */
-static void
-discard_parser_constructs (error_p)
- int error_p;
-{
-}
-
-/************************************************
- * *
- * EOF HANDLING *
- * *
- ************************************************/
-
-/* Do that silly `type "bye" to exit' stuff. You know, "ignoreeof". */
-
-/* A flag denoting whether or not ignoreeof is set. */
-int ignoreeof = 0;
-
-/* The number of times that we have encountered an EOF character without
- another character intervening. When this gets above the limit, the
- shell terminates. */
-int eof_encountered = 0;
-
-/* The limit for eof_encountered. */
-int eof_encountered_limit = 10;
-
-/* If we have EOF as the only input unit, this user wants to leave
- the shell. If the shell is not interactive, then just leave.
- Otherwise, if ignoreeof is set, and we haven't done this the
- required number of times in a row, print a message. */
-static void
-handle_eof_input_unit ()
-{
- if (interactive)
- {
- /* shell.c may use this to decide whether or not to write out the
- history, among other things. We use it only for error reporting
- in this file. */
- if (EOF_Reached)
- EOF_Reached = 0;
-
- /* If the user wants to "ignore" eof, then let her do so, kind of. */
- if (ignoreeof)
- {
- if (eof_encountered < eof_encountered_limit)
- {
- fprintf (stderr, _("Use \"%s\" to leave the shell.\n"),
- login_shell ? "logout" : "exit");
- eof_encountered++;
- /* Reset the parsing state. */
- last_read_token = current_token = '\n';
- /* Reset the prompt string to be $PS1. */
- prompt_string_pointer = (char **)NULL;
- prompt_again ();
- return;
- }
- }
-
- /* In this case EOF should exit the shell. Do it now. */
- reset_parser ();
- exit_builtin ((WORD_LIST *)NULL);
- }
- else
- {
- /* We don't write history files, etc., for non-interactive shells. */
- EOF_Reached = 1;
- }
-}
-
-/************************************************
- * *
- * STRING PARSING FUNCTIONS *
- * *
- ************************************************/
-
-/* It's very important that these two functions treat the characters
- between ( and ) identically. */
-
-static WORD_LIST parse_string_error;
-
-/* Take a string and run it through the shell parser, returning the
- resultant word list. Used by compound array assignment. */
-WORD_LIST *
-parse_string_to_word_list (s, flags, whom)
- char *s;
- int flags;
- const char *whom;
-{
- WORD_LIST *wl;
- int tok, orig_current_token, orig_line_number, orig_input_terminator;
- int orig_line_count;
- int old_echo_input, old_expand_aliases;
-#if defined (HISTORY)
- int old_remember_on_history, old_history_expansion_inhibited;
-#endif
-
-#if defined (HISTORY)
- old_remember_on_history = remember_on_history;
-# if defined (BANG_HISTORY)
- old_history_expansion_inhibited = history_expansion_inhibited;
-# endif
- bash_history_disable ();
-#endif
-
- orig_line_number = line_number;
- orig_line_count = current_command_line_count;
- orig_input_terminator = shell_input_line_terminator;
- old_echo_input = echo_input_at_read;
- old_expand_aliases = expand_aliases;
-
- push_stream (1);
- last_read_token = WORD; /* WORD to allow reserved words here */
- current_command_line_count = 0;
- echo_input_at_read = expand_aliases = 0;
-
- with_input_from_string (s, whom);
- wl = (WORD_LIST *)NULL;
-
- if (flags & 1)
- parser_state |= PST_COMPASSIGN;
-
- while ((tok = read_token (READ)) != yacc_EOF)
- {
- if (tok == '\n' && *bash_input.location.string == '\0')
- break;
- if (tok == '\n') /* Allow newlines in compound assignments */
- continue;
- if (tok != WORD && tok != ASSIGNMENT_WORD)
- {
- line_number = orig_line_number + line_number - 1;
- orig_current_token = current_token;
- current_token = tok;
- yyerror (NULL); /* does the right thing */
- current_token = orig_current_token;
- if (wl)
- dispose_words (wl);
- wl = &parse_string_error;
- break;
- }
- wl = make_word_list (yylval.word, wl);
- }
-
- last_read_token = '\n';
- pop_stream ();
-
-#if defined (HISTORY)
- remember_on_history = old_remember_on_history;
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = old_history_expansion_inhibited;
-# endif /* BANG_HISTORY */
-#endif /* HISTORY */
-
- echo_input_at_read = old_echo_input;
- expand_aliases = old_expand_aliases;
-
- current_command_line_count = orig_line_count;
- shell_input_line_terminator = orig_input_terminator;
-
- if (flags & 1)
- parser_state &= ~PST_COMPASSIGN;
-
- if (wl == &parse_string_error)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- if (interactive_shell == 0 && posixly_correct)
- jump_to_top_level (FORCE_EOF);
- else
- jump_to_top_level (DISCARD);
- }
-
- return (REVERSE_LIST (wl, WORD_LIST *));
-}
-
-static char *
-parse_compound_assignment (retlenp)
- int *retlenp;
-{
- WORD_LIST *wl, *rl;
- int tok, orig_line_number, orig_token_size, orig_last_token, assignok;
- char *saved_token, *ret;
-
- saved_token = token;
- orig_token_size = token_buffer_size;
- orig_line_number = line_number;
- orig_last_token = last_read_token;
-
- last_read_token = WORD; /* WORD to allow reserved words here */
-
- token = (char *)NULL;
- token_buffer_size = 0;
-
- assignok = parser_state&PST_ASSIGNOK; /* XXX */
-
- wl = (WORD_LIST *)NULL; /* ( */
- parser_state |= PST_COMPASSIGN;
-
- while ((tok = read_token (READ)) != ')')
- {
- if (tok == '\n') /* Allow newlines in compound assignments */
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- continue;
- }
- if (tok != WORD && tok != ASSIGNMENT_WORD)
- {
- current_token = tok; /* for error reporting */
- if (tok == yacc_EOF) /* ( */
- parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'"));
- else
- yyerror(NULL); /* does the right thing */
- if (wl)
- dispose_words (wl);
- wl = &parse_string_error;
- break;
- }
- wl = make_word_list (yylval.word, wl);
- }
-
- FREE (token);
- token = saved_token;
- token_buffer_size = orig_token_size;
-
- parser_state &= ~PST_COMPASSIGN;
-
- if (wl == &parse_string_error)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- last_read_token = '\n'; /* XXX */
- if (interactive_shell == 0 && posixly_correct)
- jump_to_top_level (FORCE_EOF);
- else
- jump_to_top_level (DISCARD);
- }
-
- last_read_token = orig_last_token; /* XXX - was WORD? */
-
- if (wl)
- {
- rl = REVERSE_LIST (wl, WORD_LIST *);
- ret = string_list (rl);
- dispose_words (rl);
- }
- else
- ret = (char *)NULL;
-
- if (retlenp)
- *retlenp = (ret && *ret) ? strlen (ret) : 0;
-
- if (assignok)
- parser_state |= PST_ASSIGNOK;
-
- return ret;
-}
-
-/************************************************
- * *
- * SAVING AND RESTORING PARTIAL PARSE STATE *
- * *
- ************************************************/
-
-sh_parser_state_t *
-save_parser_state (ps)
- sh_parser_state_t *ps;
-{
-#if defined (ARRAY_VARS)
- SHELL_VAR *v;
-#endif
-
- if (ps == 0)
- ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t));
- if (ps == 0)
- return ((sh_parser_state_t *)NULL);
-
- ps->parser_state = parser_state;
- ps->token_state = save_token_state ();
-
- ps->input_line_terminator = shell_input_line_terminator;
- ps->eof_encountered = eof_encountered;
-
- ps->current_command_line_count = current_command_line_count;
-
-#if defined (HISTORY)
- ps->remember_on_history = remember_on_history;
-# if defined (BANG_HISTORY)
- ps->history_expansion_inhibited = history_expansion_inhibited;
-# endif
-#endif
-
- ps->last_command_exit_value = last_command_exit_value;
-#if defined (ARRAY_VARS)
- v = find_variable ("PIPESTATUS");
- if (v && array_p (v) && array_cell (v))
- ps->pipestatus = array_copy (array_cell (v));
- else
- ps->pipestatus = (ARRAY *)NULL;
-#endif
-
- ps->last_shell_builtin = last_shell_builtin;
- ps->this_shell_builtin = this_shell_builtin;
-
- ps->expand_aliases = expand_aliases;
- ps->echo_input_at_read = echo_input_at_read;
-
- return (ps);
-}
-
-void
-restore_parser_state (ps)
- sh_parser_state_t *ps;
-{
-#if defined (ARRAY_VARS)
- SHELL_VAR *v;
-#endif
-
- if (ps == 0)
- return;
-
- parser_state = ps->parser_state;
- if (ps->token_state)
- {
- restore_token_state (ps->token_state);
- free (ps->token_state);
- }
-
- shell_input_line_terminator = ps->input_line_terminator;
- eof_encountered = ps->eof_encountered;
-
- current_command_line_count = ps->current_command_line_count;
-
-#if defined (HISTORY)
- remember_on_history = ps->remember_on_history;
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = ps->history_expansion_inhibited;
-# endif
-#endif
-
- last_command_exit_value = ps->last_command_exit_value;
-#if defined (ARRAY_VARS)
- v = find_variable ("PIPESTATUS");
- if (v && array_p (v) && array_cell (v))
- {
- array_dispose (array_cell (v));
- var_setarray (v, ps->pipestatus);
- }
-#endif
-
- last_shell_builtin = ps->last_shell_builtin;
- this_shell_builtin = ps->this_shell_builtin;
-
- expand_aliases = ps->expand_aliases;
- echo_input_at_read = ps->echo_input_at_read;
-}
-
-/************************************************
- * *
- * MULTIBYTE CHARACTER HANDLING *
- * *
- ************************************************/
-
-#if defined (HANDLE_MULTIBYTE)
-static void
-set_line_mbstate ()
-{
- int i, previ, len, c;
- mbstate_t mbs, prevs;
- size_t mbclen;
-
- if (shell_input_line == NULL)
- return;
- len = strlen (shell_input_line); /* XXX - shell_input_line_len ? */
- FREE (shell_input_line_property);
- shell_input_line_property = (char *)xmalloc (len + 1);
-
- memset (&prevs, '\0', sizeof (mbstate_t));
- for (i = previ = 0; i < len; i++)
- {
- mbs = prevs;
-
- c = shell_input_line[i];
- if (c == EOF)
- {
- int j;
- for (j = i; j < len; j++)
- shell_input_line_property[j] = 1;
- break;
- }
-
- mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
- if (mbclen == 1 || mbclen == (size_t)-1)
- {
- mbclen = 1;
- previ = i + 1;
- }
- else if (mbclen == (size_t)-2)
- mbclen = 0;
- else if (mbclen > 1)
- {
- mbclen = 0;
- previ = i + 1;
- prevs = mbs;
- }
- else
- {
- /* XXX - what to do if mbrlen returns 0? (null wide character) */
- int j;
- for (j = i; j < len; j++)
- shell_input_line_property[j] = 1;
- break;
- }
-
- shell_input_line_property[i] = mbclen;
- }
-}
-#endif /* HANDLE_MULTIBYTE */
diff --git a/parse.y~ b/parse.y~
deleted file mode 100644
index f654d103..00000000
--- a/parse.y~
+++ /dev/null
@@ -1,4951 +0,0 @@
-/* Yacc grammar for bash. */
-
-/* Copyright (C) 1989-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 LICENSE. If not, write to the Free Software
- Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
-
-%{
-#include "config.h"
-
-#include "bashtypes.h"
-#include "bashansi.h"
-
-#include "filecntl.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_LOCALE_H)
-# include <locale.h>
-#endif
-
-#include <stdio.h>
-#include "chartypes.h"
-#include <signal.h>
-
-#include "memalloc.h"
-
-#include "bashintl.h"
-
-#define NEED_STRFTIME_DECL /* used in externs.h */
-
-#include "shell.h"
-#include "trap.h"
-#include "flags.h"
-#include "parser.h"
-#include "mailcheck.h"
-#include "test.h"
-#include "builtins.h"
-#include "builtins/common.h"
-#include "builtins/builtext.h"
-
-#include "shmbutil.h"
-
-#if defined (READLINE)
-# include "bashline.h"
-# include <readline/readline.h>
-#endif /* READLINE */
-
-#if defined (HISTORY)
-# include "bashhist.h"
-# include <readline/history.h>
-#endif /* HISTORY */
-
-#if defined (JOB_CONTROL)
-# include "jobs.h"
-#endif /* JOB_CONTROL */
-
-#if defined (ALIAS)
-# include "alias.h"
-#else
-typedef void *alias_t;
-#endif /* ALIAS */
-
-#if defined (PROMPT_STRING_DECODE)
-# ifndef _MINIX
-# include <sys/param.h>
-# endif
-# include <time.h>
-# if defined (TM_IN_SYS_TIME)
-# include <sys/types.h>
-# include <sys/time.h>
-# endif /* TM_IN_SYS_TIME */
-# include "maxpath.h"
-#endif /* PROMPT_STRING_DECODE */
-
-#define RE_READ_TOKEN -99
-#define NO_EXPANSION -100
-
-#ifdef DEBUG
-# define YYDEBUG 1
-#else
-# define YYDEBUG 0
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
-# define last_shell_getc_is_singlebyte \
- ((shell_input_line_index > 1) \
- ? shell_input_line_property[shell_input_line_index - 1] \
- : 1)
-# define MBTEST(x) ((x) && last_shell_getc_is_singlebyte)
-#else
-# define last_shell_getc_is_singlebyte 1
-# define MBTEST(x) ((x))
-#endif
-
-#if defined (EXTENDED_GLOB)
-extern int extended_glob;
-#endif
-
-extern int eof_encountered;
-extern int no_line_editing, running_under_emacs;
-extern int current_command_number;
-extern int sourcelevel;
-extern int posixly_correct;
-extern int last_command_exit_value;
-extern char *shell_name, *current_host_name;
-extern char *dist_version;
-extern int patch_level;
-extern int dump_translatable_strings, dump_po_strings;
-extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
-#if defined (BUFFERED_INPUT)
-extern int bash_input_fd_changed;
-#endif
-
-extern int errno;
-/* **************************************************************** */
-/* */
-/* "Forward" declarations */
-/* */
-/* **************************************************************** */
-
-#ifdef DEBUG
-static void debug_parser __P((int));
-#endif
-
-static int yy_getc __P((void));
-static int yy_ungetc __P((int));
-
-#if defined (READLINE)
-static int yy_readline_get __P((void));
-static int yy_readline_unget __P((int));
-#endif
-
-static int yy_string_get __P((void));
-static int yy_string_unget __P((int));
-static int yy_stream_get __P((void));
-static int yy_stream_unget __P((int));
-
-static int shell_getc __P((int));
-static void shell_ungetc __P((int));
-static void discard_until __P((int));
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
-static void push_string __P((char *, int, alias_t *));
-static void pop_string __P((void));
-static void free_string_list __P((void));
-#endif
-
-static char *read_a_line __P((int));
-
-static int reserved_word_acceptable __P((int));
-static int yylex __P((void));
-static int alias_expand_token __P((char *));
-static int time_command_acceptable __P((void));
-static int special_case_tokens __P((char *));
-static int read_token __P((int));
-static char *parse_matched_pair __P((int, int, int, int *, int));
-#if defined (ARRAY_VARS)
-static char *parse_compound_assignment __P((int *));
-#endif
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
-static int parse_dparen __P((int));
-static int parse_arith_cmd __P((char **, int));
-#endif
-#if defined (COND_COMMAND)
-static void cond_error __P((void));
-static COND_COM *cond_expr __P((void));
-static COND_COM *cond_or __P((void));
-static COND_COM *cond_and __P((void));
-static COND_COM *cond_term __P((void));
-static int cond_skip_newlines __P((void));
-static COMMAND *parse_cond_command __P((void));
-#endif
-#if defined (ARRAY_VARS)
-static int token_is_assignment __P((char *, int));
-static int token_is_ident __P((char *, int));
-#endif
-static int read_token_word __P((int));
-static void discard_parser_constructs __P((int));
-
-static char *error_token_from_token __P((int));
-static char *error_token_from_text __P((void));
-static void print_offending_line __P((void));
-static void report_syntax_error __P((char *));
-
-static void handle_eof_input_unit __P((void));
-static void prompt_again __P((void));
-#if 0
-static void reset_readline_prompt __P((void));
-#endif
-static void print_prompt __P((void));
-
-#if defined (HISTORY)
-char *history_delimiting_chars __P((void));
-#endif
-
-#if defined (HANDLE_MULTIBYTE)
-static void set_line_mbstate __P((void));
-static char *shell_input_line_property = NULL;
-#else
-# define set_line_mbstate()
-#endif
-
-extern int yyerror __P((const char *));
-
-#ifdef DEBUG
-extern int yydebug;
-#endif
-
-/* Default prompt strings */
-char *primary_prompt = PPROMPT;
-char *secondary_prompt = SPROMPT;
-
-/* PROMPT_STRING_POINTER points to one of these, never to an actual string. */
-char *ps1_prompt, *ps2_prompt;
-
-/* Handle on the current prompt string. Indirectly points through
- ps1_ or ps2_prompt. */
-char **prompt_string_pointer = (char **)NULL;
-char *current_prompt_string;
-
-/* Non-zero means we expand aliases in commands. */
-int expand_aliases = 0;
-
-/* If non-zero, the decoded prompt string undergoes parameter and
- variable substitution, command substitution, arithmetic substitution,
- string expansion, process substitution, and quote removal in
- decode_prompt_string. */
-int promptvars = 1;
-
-/* If non-zero, $'...' and $"..." are expanded when they appear within
- a ${...} expansion, even when the expansion appears within double
- quotes. */
-int extended_quote = 1;
-
-/* The decoded prompt string. Used if READLINE is not defined or if
- editing is turned off. Analogous to current_readline_prompt. */
-static char *current_decoded_prompt;
-
-/* The number of lines read from input while creating the current command. */
-int current_command_line_count;
-
-/* Variables to manage the task of reading here documents, because we need to
- defer the reading until after a complete command has been collected. */
-static REDIRECT *redir_stack[10];
-int need_here_doc;
-
-/* Where shell input comes from. History expansion is performed on each
- line when the shell is interactive. */
-static char *shell_input_line = (char *)NULL;
-static int shell_input_line_index;
-static int shell_input_line_size; /* Amount allocated for shell_input_line. */
-static int shell_input_line_len; /* strlen (shell_input_line) */
-
-/* Either zero or EOF. */
-static int shell_input_line_terminator;
-
-/* The line number in a script on which a function definition starts. */
-static int function_dstart;
-
-/* The line number in a script on which a function body starts. */
-static int function_bstart;
-
-/* The line number in a script at which an arithmetic for command starts. */
-static int arith_for_lineno;
-
-/* The line number in a script where the word in a `case WORD', `select WORD'
- or `for WORD' begins. This is a nested command maximum, since the array
- index is decremented after a case, select, or for command is parsed. */
-#define MAX_CASE_NEST 128
-static int word_lineno[MAX_CASE_NEST];
-static int word_top = -1;
-
-/* If non-zero, it is the token that we want read_token to return
- regardless of what text is (or isn't) present to be read. This
- is reset by read_token. If token_to_read == WORD or
- ASSIGNMENT_WORD, yylval.word should be set to word_desc_to_read. */
-static int token_to_read;
-static WORD_DESC *word_desc_to_read;
-
-static REDIRECTEE redir;
-%}
-
-%union {
- WORD_DESC *word; /* the word that we read. */
- int number; /* the number that we read. */
- WORD_LIST *word_list;
- COMMAND *command;
- REDIRECT *redirect;
- ELEMENT element;
- PATTERN_LIST *pattern;
-}
-
-/* Reserved words. Members of the first group are only recognized
- in the case that they are preceded by a list_terminator. Members
- of the second group are for [[...]] commands. Members of the
- third group are recognized only under special circumstances. */
-%token IF THEN ELSE ELIF FI CASE ESAC FOR SELECT WHILE UNTIL DO DONE FUNCTION
-%token COND_START COND_END COND_ERROR
-%token IN BANG TIME TIMEOPT
-
-/* More general tokens. yylex () knows how to make these. */
-%token <word> WORD ASSIGNMENT_WORD
-%token <number> NUMBER
-%token <word_list> ARITH_CMD ARITH_FOR_EXPRS
-%token <command> COND_CMD
-%token AND_AND OR_OR GREATER_GREATER LESS_LESS LESS_AND LESS_LESS_LESS
-%token GREATER_AND SEMI_SEMI LESS_LESS_MINUS AND_GREATER LESS_GREATER
-%token GREATER_BAR
-
-/* The types that the various syntactical units return. */
-
-%type <command> inputunit command pipeline pipeline_command
-%type <command> list list0 list1 compound_list simple_list simple_list1
-%type <command> simple_command shell_command
-%type <command> for_command select_command case_command group_command
-%type <command> arith_command
-%type <command> cond_command
-%type <command> arith_for_command
-%type <command> function_def function_body if_command elif_clause subshell
-%type <redirect> redirection redirection_list
-%type <element> simple_command_element
-%type <word_list> word_list pattern
-%type <pattern> pattern_list case_clause_sequence case_clause
-%type <number> timespec
-%type <number> list_terminator
-
-%start inputunit
-
-%left '&' ';' '\n' yacc_EOF
-%left AND_AND OR_OR
-%right '|'
-%%
-
-inputunit: simple_list simple_list_terminator
- {
- /* Case of regular command. Discard the error
- safety net,and return the command just parsed. */
- global_command = $1;
- eof_encountered = 0;
- /* discard_parser_constructs (0); */
- YYACCEPT;
- }
- | '\n'
- {
- /* Case of regular command, but not a very
- interesting one. Return a NULL command. */
- global_command = (COMMAND *)NULL;
- YYACCEPT;
- }
- | error '\n'
- {
- /* Error during parsing. Return NULL command. */
- global_command = (COMMAND *)NULL;
- eof_encountered = 0;
- /* discard_parser_constructs (1); */
- if (interactive)
- {
- YYACCEPT;
- }
- else
- {
- YYABORT;
- }
- }
- | yacc_EOF
- {
- /* Case of EOF seen by itself. Do ignoreeof or
- not. */
- global_command = (COMMAND *)NULL;
- handle_eof_input_unit ();
- YYACCEPT;
- }
- ;
-
-word_list: WORD
- { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
- | word_list WORD
- { $$ = make_word_list ($2, $1); }
- ;
-
-redirection: '>' WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_output_direction, redir);
- }
- | '<' WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_input_direction, redir);
- }
- | NUMBER '>' WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_output_direction, redir);
- }
- | NUMBER '<' WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_input_direction, redir);
- }
- | GREATER_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_appending_to, redir);
- }
- | NUMBER GREATER_GREATER WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_appending_to, redir);
- }
- | LESS_LESS WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | NUMBER LESS_LESS WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | LESS_LESS_LESS WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_reading_string, redir);
- }
- | NUMBER LESS_LESS_LESS WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_reading_string, redir);
- }
- | LESS_AND NUMBER
- {
- redir.dest = $2;
- $$ = make_redirection (0, r_duplicating_input, redir);
- }
- | NUMBER LESS_AND NUMBER
- {
- redir.dest = $3;
- $$ = make_redirection ($1, r_duplicating_input, redir);
- }
- | GREATER_AND NUMBER
- {
- redir.dest = $2;
- $$ = make_redirection (1, r_duplicating_output, redir);
- }
- | NUMBER GREATER_AND NUMBER
- {
- redir.dest = $3;
- $$ = make_redirection ($1, r_duplicating_output, redir);
- }
- | LESS_AND WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_duplicating_input_word, redir);
- }
- | NUMBER LESS_AND WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_duplicating_input_word, redir);
- }
- | GREATER_AND WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_duplicating_output_word, redir);
- }
- | NUMBER GREATER_AND WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_duplicating_output_word, redir);
- }
- | LESS_LESS_MINUS WORD
- {
- redir.filename = $2;
- $$ = make_redirection
- (0, r_deblank_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | NUMBER LESS_LESS_MINUS WORD
- {
- redir.filename = $3;
- $$ = make_redirection
- ($1, r_deblank_reading_until, redir);
- redir_stack[need_here_doc++] = $$;
- }
- | GREATER_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection (1, r_close_this, redir);
- }
- | NUMBER GREATER_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection ($1, r_close_this, redir);
- }
- | LESS_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection (0, r_close_this, redir);
- }
- | NUMBER LESS_AND '-'
- {
- redir.dest = 0;
- $$ = make_redirection ($1, r_close_this, redir);
- }
- | AND_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_err_and_out, redir);
- }
- | NUMBER LESS_GREATER WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_input_output, redir);
- }
- | LESS_GREATER WORD
- {
- redir.filename = $2;
- $$ = make_redirection (0, r_input_output, redir);
- }
- | GREATER_BAR WORD
- {
- redir.filename = $2;
- $$ = make_redirection (1, r_output_force, redir);
- }
- | NUMBER GREATER_BAR WORD
- {
- redir.filename = $3;
- $$ = make_redirection ($1, r_output_force, redir);
- }
- ;
-
-simple_command_element: WORD
- { $$.word = $1; $$.redirect = 0; }
- | ASSIGNMENT_WORD
- { $$.word = $1; $$.redirect = 0; }
- | redirection
- { $$.redirect = $1; $$.word = 0; }
- ;
-
-redirection_list: redirection
- {
- $$ = $1;
- }
- | redirection_list redirection
- {
- register REDIRECT *t;
-
- for (t = $1; t->next; t = t->next)
- ;
- t->next = $2;
- $$ = $1;
- }
- ;
-
-simple_command: simple_command_element
- { $$ = make_simple_command ($1, (COMMAND *)NULL); }
- | simple_command simple_command_element
- { $$ = make_simple_command ($2, $1); }
- ;
-
-command: simple_command
- { $$ = clean_simple_command ($1); }
- | shell_command
- { $$ = $1; }
- | shell_command redirection_list
- {
- COMMAND *tc;
-
- tc = $1;
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = $2;
- }
- else
- tc->redirects = $2;
- $$ = $1;
- }
- | function_def
- { $$ = $1; }
- ;
-
-shell_command: for_command
- { $$ = $1; }
- | case_command
- { $$ = $1; }
- | WHILE compound_list DO compound_list DONE
- { $$ = make_while_command ($2, $4); }
- | UNTIL compound_list DO compound_list DONE
- { $$ = make_until_command ($2, $4); }
- | select_command
- { $$ = $1; }
- | if_command
- { $$ = $1; }
- | subshell
- { $$ = $1; }
- | group_command
- { $$ = $1; }
- | arith_command
- { $$ = $1; }
- | cond_command
- { $$ = $1; }
- | arith_for_command
- { $$ = $1; }
- ;
-
-for_command: FOR WORD newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD ';' newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD ';' newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN word_list list_terminator newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN word_list list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN list_terminator newline_list DO compound_list DONE
- {
- $$ = make_for_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | FOR WORD newline_list IN list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_for_command ($2, (WORD_LIST *)NULL, $8, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-arith_for_command: FOR ARITH_FOR_EXPRS list_terminator newline_list DO compound_list DONE
- {
- $$ = make_arith_for_command ($2, $6, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS list_terminator newline_list '{' compound_list '}'
- {
- $$ = make_arith_for_command ($2, $6, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS DO compound_list DONE
- {
- $$ = make_arith_for_command ($2, $4, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- | FOR ARITH_FOR_EXPRS '{' compound_list '}'
- {
- $$ = make_arith_for_command ($2, $4, arith_for_lineno);
- if (word_top > 0) word_top--;
- }
- ;
-
-select_command: SELECT WORD newline_list DO list DONE
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list '{' list '}'
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD ';' newline_list DO list DONE
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD ';' newline_list '{' list '}'
- {
- $$ = make_select_command ($2, add_string_to_list ("\"$@\"", (WORD_LIST *)NULL), $6, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list IN word_list list_terminator newline_list DO list DONE
- {
- $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | SELECT WORD newline_list IN word_list list_terminator newline_list '{' list '}'
- {
- $$ = make_select_command ($2, REVERSE_LIST ($5, WORD_LIST *), $9, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-case_command: CASE WORD newline_list IN newline_list ESAC
- {
- $$ = make_case_command ($2, (PATTERN_LIST *)NULL, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | CASE WORD newline_list IN case_clause_sequence newline_list ESAC
- {
- $$ = make_case_command ($2, $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- | CASE WORD newline_list IN case_clause ESAC
- {
- $$ = make_case_command ($2, $5, word_lineno[word_top]);
- if (word_top > 0) word_top--;
- }
- ;
-
-function_def: WORD '(' ')' newline_list function_body
- { $$ = make_function_def ($1, $5, function_dstart, function_bstart); }
-
- | FUNCTION WORD '(' ')' newline_list function_body
- { $$ = make_function_def ($2, $6, function_dstart, function_bstart); }
-
- | FUNCTION WORD newline_list function_body
- { $$ = make_function_def ($2, $4, function_dstart, function_bstart); }
- ;
-
-
-function_body: shell_command
- { $$ = $1; }
- | shell_command redirection_list
- {
- COMMAND *tc;
-
- tc = $1;
- /* According to Posix.2 3.9.5, redirections
- specified after the body of a function should
- be attached to the function and performed when
- the function is executed, not as part of the
- function definition command. */
- /* XXX - I don't think it matters, but we might
- want to change this in the future to avoid
- problems differentiating between a function
- definition with a redirection and a function
- definition containing a single command with a
- redirection. The two are semantically equivalent,
- though -- the only difference is in how the
- command printing code displays the redirections. */
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = $2;
- }
- else
- tc->redirects = $2;
- $$ = $1;
- }
- ;
-
-subshell: '(' compound_list ')'
- {
- $$ = make_subshell_command ($2);
- $$->flags |= CMD_WANT_SUBSHELL;
- }
- ;
-
-if_command: IF compound_list THEN compound_list FI
- { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
- | IF compound_list THEN compound_list ELSE compound_list FI
- { $$ = make_if_command ($2, $4, $6); }
- | IF compound_list THEN compound_list elif_clause FI
- { $$ = make_if_command ($2, $4, $5); }
- ;
-
-
-group_command: '{' compound_list '}'
- { $$ = make_group_command ($2); }
- ;
-
-arith_command: ARITH_CMD
- { $$ = make_arith_command ($1); }
- ;
-
-cond_command: COND_START COND_CMD COND_END
- { $$ = $2; }
- ;
-
-elif_clause: ELIF compound_list THEN compound_list
- { $$ = make_if_command ($2, $4, (COMMAND *)NULL); }
- | ELIF compound_list THEN compound_list ELSE compound_list
- { $$ = make_if_command ($2, $4, $6); }
- | ELIF compound_list THEN compound_list elif_clause
- { $$ = make_if_command ($2, $4, $5); }
- ;
-
-case_clause: pattern_list
- | case_clause_sequence pattern_list
- { $2->next = $1; $$ = $2; }
- ;
-
-pattern_list: newline_list pattern ')' compound_list
- { $$ = make_pattern_list ($2, $4); }
- | newline_list pattern ')' newline_list
- { $$ = make_pattern_list ($2, (COMMAND *)NULL); }
- | newline_list '(' pattern ')' compound_list
- { $$ = make_pattern_list ($3, $5); }
- | newline_list '(' pattern ')' newline_list
- { $$ = make_pattern_list ($3, (COMMAND *)NULL); }
- ;
-
-case_clause_sequence: pattern_list SEMI_SEMI
- | case_clause_sequence pattern_list SEMI_SEMI
- { $2->next = $1; $$ = $2; }
- ;
-
-pattern: WORD
- { $$ = make_word_list ($1, (WORD_LIST *)NULL); }
- | pattern '|' WORD
- { $$ = make_word_list ($3, $1); }
- ;
-
-/* A list allows leading or trailing newlines and
- newlines as operators (equivalent to semicolons).
- It must end with a newline or semicolon.
- Lists are used within commands such as if, for, while. */
-
-list: newline_list list0
- {
- $$ = $2;
- if (need_here_doc)
- gather_here_documents ();
- }
- ;
-
-compound_list: list
- | newline_list list1
- {
- $$ = $2;
- }
- ;
-
-list0: list1 '\n' newline_list
- | list1 '&' newline_list
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
- else
- $$ = command_connect ($1, (COMMAND *)NULL, '&');
- }
- | list1 ';' newline_list
-
- ;
-
-list1: list1 AND_AND newline_list list1
- { $$ = command_connect ($1, $4, AND_AND); }
- | list1 OR_OR newline_list list1
- { $$ = command_connect ($1, $4, OR_OR); }
- | list1 '&' newline_list list1
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, $4, '&');
- else
- $$ = command_connect ($1, $4, '&');
- }
- | list1 ';' newline_list list1
- { $$ = command_connect ($1, $4, ';'); }
- | list1 '\n' newline_list list1
- { $$ = command_connect ($1, $4, ';'); }
- | pipeline_command
- { $$ = $1; }
- ;
-
-simple_list_terminator: '\n'
- | yacc_EOF
- ;
-
-list_terminator:'\n'
- { $$ = '\n'; }
- | ';'
- { $$ = ';'; }
- | yacc_EOF
- { $$ = yacc_EOF; }
- ;
-
-newline_list:
- | newline_list '\n'
- ;
-
-/* A simple_list is a list that contains no significant newlines
- and no leading or trailing newlines. Newlines are allowed
- only following operators, where they are not significant.
-
- This is what an inputunit consists of. */
-
-simple_list: simple_list1
- {
- $$ = $1;
- if (need_here_doc)
- gather_here_documents ();
- }
- | simple_list1 '&'
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, (COMMAND *)NULL, '&');
- else
- $$ = command_connect ($1, (COMMAND *)NULL, '&');
- if (need_here_doc)
- gather_here_documents ();
- }
- | simple_list1 ';'
- {
- $$ = $1;
- if (need_here_doc)
- gather_here_documents ();
- }
- ;
-
-simple_list1: simple_list1 AND_AND newline_list simple_list1
- { $$ = command_connect ($1, $4, AND_AND); }
- | simple_list1 OR_OR newline_list simple_list1
- { $$ = command_connect ($1, $4, OR_OR); }
- | simple_list1 '&' simple_list1
- {
- if ($1->type == cm_connection)
- $$ = connect_async_list ($1, $3, '&');
- else
- $$ = command_connect ($1, $3, '&');
- }
- | simple_list1 ';' simple_list1
- { $$ = command_connect ($1, $3, ';'); }
-
- | pipeline_command
- { $$ = $1; }
- ;
-
-pipeline_command: pipeline
- { $$ = $1; }
- | BANG pipeline
- {
- if ($2)
- $2->flags |= CMD_INVERT_RETURN;
- $$ = $2;
- }
- | timespec pipeline
- {
- if ($2)
- $2->flags |= $1;
- $$ = $2;
- }
- | timespec BANG pipeline
- {
- if ($3)
- $3->flags |= $1|CMD_INVERT_RETURN;
- $$ = $3;
- }
- | BANG timespec pipeline
- {
- if ($3)
- $3->flags |= $2|CMD_INVERT_RETURN;
- $$ = $3;
- }
- | timespec list_terminator
- {
- ELEMENT x;
-
- /* Boy, this is unclean. `time' by itself can
- time a null command. We cheat and push a
- newline back if the list_terminator was a newline
- to avoid the double-newline problem (one to
- terminate this, one to terminate the command) */
- x.word = 0;
- x.redirect = 0;
- $$ = make_simple_command (x, (COMMAND *)NULL);
- $$->flags |= $1;
- /* XXX - let's cheat and push a newline back */
- if ($2 == '\n')
- token_to_read = '\n';
- }
-
- ;
-
-pipeline:
- pipeline '|' newline_list pipeline
- { $$ = command_connect ($1, $4, '|'); }
- | command
- { $$ = $1; }
- ;
-
-timespec: TIME
- { $$ = CMD_TIME_PIPELINE; }
- | TIME TIMEOPT
- { $$ = CMD_TIME_PIPELINE|CMD_TIME_POSIX; }
- ;
-%%
-
-/* Possible states for the parser that require it to do special things. */
-#define PST_CASEPAT 0x0001 /* in a case pattern list */
-#define PST_ALEXPNEXT 0x0002 /* expand next word for aliases */
-#define PST_ALLOWOPNBRC 0x0004 /* allow open brace for function def */
-#define PST_NEEDCLOSBRC 0x0008 /* need close brace */
-#define PST_DBLPAREN 0x0010 /* double-paren parsing */
-#define PST_SUBSHELL 0x0020 /* ( ... ) subshell */
-#define PST_CMDSUBST 0x0040 /* $( ... ) command substitution */
-#define PST_CASESTMT 0x0080 /* parsing a case statement */
-#define PST_CONDCMD 0x0100 /* parsing a [[...]] command */
-#define PST_CONDEXPR 0x0200 /* parsing the guts of [[...]] */
-#define PST_ARITHFOR 0x0400 /* parsing an arithmetic for command */
-#define PST_ALEXPAND 0x0800 /* OK to expand aliases - unused */
-#define PST_CMDTOKEN 0x1000 /* command token OK - unused */
-#define PST_COMPASSIGN 0x2000 /* parsing x=(...) compound assignment */
-#define PST_ASSIGNOK 0x4000 /* assignment statement ok in this context */
-
-/* Initial size to allocate for tokens, and the
- amount to grow them by. */
-#define TOKEN_DEFAULT_INITIAL_SIZE 496
-#define TOKEN_DEFAULT_GROW_SIZE 512
-
-/* Should we call prompt_again? */
-#define SHOULD_PROMPT() \
- (interactive && (bash_input.type == st_stdin || bash_input.type == st_stream))
-
-#if defined (ALIAS)
-# define expanding_alias() (pushed_string_list && pushed_string_list->expander)
-#else
-# define expanding_alias() 0
-#endif
-
-/* The token currently being read. */
-static int current_token;
-
-/* The last read token, or NULL. read_token () uses this for context
- checking. */
-static int last_read_token;
-
-/* The token read prior to last_read_token. */
-static int token_before_that;
-
-/* The token read prior to token_before_that. */
-static int two_tokens_ago;
-
-/* The current parser state. */
-static int parser_state;
-
-/* Global var is non-zero when end of file has been reached. */
-int EOF_Reached = 0;
-
-#ifdef DEBUG
-static void
-debug_parser (i)
- int i;
-{
-#if YYDEBUG != 0
- yydebug = i;
-#endif
-}
-#endif
-
-/* yy_getc () returns the next available character from input or EOF.
- yy_ungetc (c) makes `c' the next character to read.
- init_yy_io (get, unget, type, location) makes the function GET the
- installed function for getting the next character, makes UNGET the
- installed function for un-getting a character, sets the type of stream
- (either string or file) from TYPE, and makes LOCATION point to where
- the input is coming from. */
-
-/* Unconditionally returns end-of-file. */
-int
-return_EOF ()
-{
- return (EOF);
-}
-
-/* Variable containing the current get and unget functions.
- See ./input.h for a clearer description. */
-BASH_INPUT bash_input;
-
-/* Set all of the fields in BASH_INPUT to NULL. Free bash_input.name if it
- is non-null, avoiding a memory leak. */
-void
-initialize_bash_input ()
-{
- bash_input.type = st_none;
- FREE (bash_input.name);
- bash_input.name = (char *)NULL;
- bash_input.location.file = (FILE *)NULL;
- bash_input.location.string = (char *)NULL;
- bash_input.getter = (sh_cget_func_t *)NULL;
- bash_input.ungetter = (sh_cunget_func_t *)NULL;
-}
-
-/* Set the contents of the current bash input stream from
- GET, UNGET, TYPE, NAME, and LOCATION. */
-void
-init_yy_io (get, unget, type, name, location)
- sh_cget_func_t *get;
- sh_cunget_func_t *unget;
- enum stream_type type;
- const char *name;
- INPUT_STREAM location;
-{
- bash_input.type = type;
- FREE (bash_input.name);
- bash_input.name = name ? savestring (name) : (char *)NULL;
-
- /* XXX */
-#if defined (CRAY)
- memcpy((char *)&bash_input.location.string, (char *)&location.string, sizeof(location));
-#else
- bash_input.location = location;
-#endif
- bash_input.getter = get;
- bash_input.ungetter = unget;
-}
-
-char *
-yy_input_name ()
-{
- return (bash_input.name ? bash_input.name : "stdin");
-}
-
-/* Call this to get the next character of input. */
-static int
-yy_getc ()
-{
- return (*(bash_input.getter)) ();
-}
-
-/* Call this to unget C. That is, to make C the next character
- to be read. */
-static int
-yy_ungetc (c)
- int c;
-{
- return (*(bash_input.ungetter)) (c);
-}
-
-#if defined (BUFFERED_INPUT)
-#ifdef INCLUDE_UNUSED
-int
-input_file_descriptor ()
-{
- switch (bash_input.type)
- {
- case st_stream:
- return (fileno (bash_input.location.file));
- case st_bstream:
- return (bash_input.location.buffered_fd);
- case st_stdin:
- default:
- return (fileno (stdin));
- }
-}
-#endif
-#endif /* BUFFERED_INPUT */
-
-/* **************************************************************** */
-/* */
-/* Let input be read from readline (). */
-/* */
-/* **************************************************************** */
-
-#if defined (READLINE)
-char *current_readline_prompt = (char *)NULL;
-char *current_readline_line = (char *)NULL;
-int current_readline_line_index = 0;
-
-static int
-yy_readline_get ()
-{
- SigHandler *old_sigint;
- int line_len;
- unsigned char c;
-
- if (!current_readline_line)
- {
- if (!bash_readline_initialized)
- initialize_readline ();
-
-#if defined (JOB_CONTROL)
- if (job_control)
- give_terminal_to (shell_pgrp, 0);
-#endif /* JOB_CONTROL */
-
- old_sigint = (SigHandler *)NULL;
- if (signal_is_ignored (SIGINT) == 0)
- {
- old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
- interrupt_immediately++;
- }
- terminate_immediately = 1;
-
- current_readline_line = readline (current_readline_prompt ?
- current_readline_prompt : "");
-
- terminate_immediately = 0;
- if (signal_is_ignored (SIGINT) == 0 && old_sigint)
- {
- interrupt_immediately--;
- set_signal_handler (SIGINT, old_sigint);
- }
-
-#if 0
- /* Reset the prompt to the decoded value of prompt_string_pointer. */
- reset_readline_prompt ();
-#endif
-
- if (current_readline_line == 0)
- return (EOF);
-
- current_readline_line_index = 0;
- line_len = strlen (current_readline_line);
-
- current_readline_line = (char *)xrealloc (current_readline_line, 2 + line_len);
- current_readline_line[line_len++] = '\n';
- current_readline_line[line_len] = '\0';
- }
-
- if (current_readline_line[current_readline_line_index] == 0)
- {
- free (current_readline_line);
- current_readline_line = (char *)NULL;
- return (yy_readline_get ());
- }
- else
- {
- c = current_readline_line[current_readline_line_index++];
- return (c);
- }
-}
-
-static int
-yy_readline_unget (c)
- int c;
-{
- if (current_readline_line_index && current_readline_line)
- current_readline_line[--current_readline_line_index] = c;
- return (c);
-}
-
-void
-with_input_from_stdin ()
-{
- INPUT_STREAM location;
-
- if (bash_input.type != st_stdin && stream_on_stack (st_stdin) == 0)
- {
- location.string = current_readline_line;
- init_yy_io (yy_readline_get, yy_readline_unget,
- st_stdin, "readline stdin", location);
- }
-}
-
-#else /* !READLINE */
-
-void
-with_input_from_stdin ()
-{
- with_input_from_stream (stdin, "stdin");
-}
-#endif /* !READLINE */
-
-/* **************************************************************** */
-/* */
-/* Let input come from STRING. STRING is zero terminated. */
-/* */
-/* **************************************************************** */
-
-static int
-yy_string_get ()
-{
- register char *string;
- register unsigned char c;
-
- string = bash_input.location.string;
-
- /* If the string doesn't exist, or is empty, EOF found. */
- if (string && *string)
- {
- c = *string++;
- bash_input.location.string = string;
- return (c);
- }
- else
- return (EOF);
-}
-
-static int
-yy_string_unget (c)
- int c;
-{
- *(--bash_input.location.string) = c;
- return (c);
-}
-
-void
-with_input_from_string (string, name)
- char *string;
- const char *name;
-{
- INPUT_STREAM location;
-
- location.string = string;
- init_yy_io (yy_string_get, yy_string_unget, st_string, name, location);
-}
-
-/* **************************************************************** */
-/* */
-/* Let input come from STREAM. */
-/* */
-/* **************************************************************** */
-
-/* These two functions used to test the value of the HAVE_RESTARTABLE_SYSCALLS
- define, and just use getc/ungetc if it was defined, but since bash
- installs its signal handlers without the SA_RESTART flag, some signals
- (like SIGCHLD, SIGWINCH, etc.) received during a read(2) will not cause
- the read to be restarted. We need to restart it ourselves. */
-
-static int
-yy_stream_get ()
-{
- int result;
-
- result = EOF;
- if (bash_input.location.file)
- {
- if (interactive)
- {
- interrupt_immediately++;
- terminate_immediately++;
- }
- result = getc_with_restart (bash_input.location.file);
- if (interactive)
- {
- interrupt_immediately--;
- terminate_immediately--;
- }
- }
- return (result);
-}
-
-static int
-yy_stream_unget (c)
- int c;
-{
- return (ungetc_with_restart (c, bash_input.location.file));
-}
-
-void
-with_input_from_stream (stream, name)
- FILE *stream;
- const char *name;
-{
- INPUT_STREAM location;
-
- location.file = stream;
- init_yy_io (yy_stream_get, yy_stream_unget, st_stream, name, location);
-}
-
-typedef struct stream_saver {
- struct stream_saver *next;
- BASH_INPUT bash_input;
- int line;
-#if defined (BUFFERED_INPUT)
- BUFFERED_STREAM *bstream;
-#endif /* BUFFERED_INPUT */
-} STREAM_SAVER;
-
-/* The globally known line number. */
-int line_number = 0;
-
-#if defined (COND_COMMAND)
-static int cond_lineno;
-static int cond_token;
-#endif
-
-STREAM_SAVER *stream_list = (STREAM_SAVER *)NULL;
-
-void
-push_stream (reset_lineno)
- int reset_lineno;
-{
- STREAM_SAVER *saver = (STREAM_SAVER *)xmalloc (sizeof (STREAM_SAVER));
-
- xbcopy ((char *)&bash_input, (char *)&(saver->bash_input), sizeof (BASH_INPUT));
-
-#if defined (BUFFERED_INPUT)
- saver->bstream = (BUFFERED_STREAM *)NULL;
- /* If we have a buffered stream, clear out buffers[fd]. */
- if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
- saver->bstream = set_buffered_stream (bash_input.location.buffered_fd,
- (BUFFERED_STREAM *)NULL);
-#endif /* BUFFERED_INPUT */
-
- saver->line = line_number;
- bash_input.name = (char *)NULL;
- saver->next = stream_list;
- stream_list = saver;
- EOF_Reached = 0;
- if (reset_lineno)
- line_number = 0;
-}
-
-void
-pop_stream ()
-{
- if (!stream_list)
- EOF_Reached = 1;
- else
- {
- STREAM_SAVER *saver = stream_list;
-
- EOF_Reached = 0;
- stream_list = stream_list->next;
-
- init_yy_io (saver->bash_input.getter,
- saver->bash_input.ungetter,
- saver->bash_input.type,
- saver->bash_input.name,
- saver->bash_input.location);
-
-#if defined (BUFFERED_INPUT)
- /* If we have a buffered stream, restore buffers[fd]. */
- /* If the input file descriptor was changed while this was on the
- save stack, update the buffered fd to the new file descriptor and
- re-establish the buffer <-> bash_input fd correspondence. */
- if (bash_input.type == st_bstream && bash_input.location.buffered_fd >= 0)
- {
- if (bash_input_fd_changed)
- {
- bash_input_fd_changed = 0;
- if (default_buffered_input >= 0)
- {
- bash_input.location.buffered_fd = default_buffered_input;
- saver->bstream->b_fd = default_buffered_input;
- SET_CLOSE_ON_EXEC (default_buffered_input);
- }
- }
- /* XXX could free buffered stream returned as result here. */
- set_buffered_stream (bash_input.location.buffered_fd, saver->bstream);
- }
-#endif /* BUFFERED_INPUT */
-
- line_number = saver->line;
-
- FREE (saver->bash_input.name);
- free (saver);
- }
-}
-
-/* Return 1 if a stream of type TYPE is saved on the stack. */
-int
-stream_on_stack (type)
- enum stream_type type;
-{
- register STREAM_SAVER *s;
-
- for (s = stream_list; s; s = s->next)
- if (s->bash_input.type == type)
- return 1;
- return 0;
-}
-
-/* Save the current token state and return it in a malloced array. */
-int *
-save_token_state ()
-{
- int *ret;
-
- ret = (int *)xmalloc (3 * sizeof (int));
- ret[0] = last_read_token;
- ret[1] = token_before_that;
- ret[2] = two_tokens_ago;
- return ret;
-}
-
-void
-restore_token_state (ts)
- int *ts;
-{
- if (ts == 0)
- return;
- last_read_token = ts[0];
- token_before_that = ts[1];
- two_tokens_ago = ts[2];
-}
-
-/*
- * This is used to inhibit alias expansion and reserved word recognition
- * inside case statement pattern lists. A `case statement pattern list' is:
- *
- * everything between the `in' in a `case word in' and the next ')'
- * or `esac'
- * everything between a `;;' and the next `)' or `esac'
- */
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
-
-#define END_OF_ALIAS 0
-
-/*
- * Pseudo-global variables used in implementing token-wise alias expansion.
- */
-
-/*
- * Pushing and popping strings. This works together with shell_getc to
- * implement alias expansion on a per-token basis.
- */
-
-typedef struct string_saver {
- struct string_saver *next;
- int expand_alias; /* Value to set expand_alias to when string is popped. */
- char *saved_line;
-#if defined (ALIAS)
- alias_t *expander; /* alias that caused this line to be pushed. */
-#endif
- int saved_line_size, saved_line_index, saved_line_terminator;
-} STRING_SAVER;
-
-STRING_SAVER *pushed_string_list = (STRING_SAVER *)NULL;
-
-/*
- * Push the current shell_input_line onto a stack of such lines and make S
- * the current input. Used when expanding aliases. EXPAND is used to set
- * the value of expand_next_token when the string is popped, so that the
- * word after the alias in the original line is handled correctly when the
- * alias expands to multiple words. TOKEN is the token that was expanded
- * into S; it is saved and used to prevent infinite recursive expansion.
- */
-static void
-push_string (s, expand, ap)
- char *s;
- int expand;
- alias_t *ap;
-{
- STRING_SAVER *temp = (STRING_SAVER *)xmalloc (sizeof (STRING_SAVER));
-
- temp->expand_alias = expand;
- temp->saved_line = shell_input_line;
- temp->saved_line_size = shell_input_line_size;
- temp->saved_line_index = shell_input_line_index;
- temp->saved_line_terminator = shell_input_line_terminator;
-#if defined (ALIAS)
- temp->expander = ap;
-#endif
- temp->next = pushed_string_list;
- pushed_string_list = temp;
-
-#if defined (ALIAS)
- if (ap)
- ap->flags |= AL_BEINGEXPANDED;
-#endif
-
- shell_input_line = s;
- shell_input_line_size = strlen (s);
- shell_input_line_index = 0;
- shell_input_line_terminator = '\0';
-#if 0
- parser_state &= ~PST_ALEXPNEXT; /* XXX */
-#endif
-
- set_line_mbstate ();
-}
-
-/*
- * Make the top of the pushed_string stack be the current shell input.
- * Only called when there is something on the stack. Called from shell_getc
- * when it thinks it has consumed the string generated by an alias expansion
- * and needs to return to the original input line.
- */
-static void
-pop_string ()
-{
- STRING_SAVER *t;
-
- FREE (shell_input_line);
- shell_input_line = pushed_string_list->saved_line;
- shell_input_line_index = pushed_string_list->saved_line_index;
- shell_input_line_size = pushed_string_list->saved_line_size;
- shell_input_line_terminator = pushed_string_list->saved_line_terminator;
-
- if (pushed_string_list->expand_alias)
- parser_state |= PST_ALEXPNEXT;
- else
- parser_state &= ~PST_ALEXPNEXT;
-
- t = pushed_string_list;
- pushed_string_list = pushed_string_list->next;
-
-#if defined (ALIAS)
- if (t->expander)
- t->expander->flags &= ~AL_BEINGEXPANDED;
-#endif
-
- free ((char *)t);
-
- set_line_mbstate ();
-}
-
-static void
-free_string_list ()
-{
- register STRING_SAVER *t, *t1;
-
- for (t = pushed_string_list; t; )
- {
- t1 = t->next;
- FREE (t->saved_line);
-#if defined (ALIAS)
- if (t->expander)
- t->expander->flags &= ~AL_BEINGEXPANDED;
-#endif
- free ((char *)t);
- t = t1;
- }
- pushed_string_list = (STRING_SAVER *)NULL;
-}
-
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
-void
-free_pushed_string_input ()
-{
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- free_string_list ();
-#endif
-}
-
-/* Return a line of text, taken from wherever yylex () reads input.
- If there is no more input, then we return NULL. If REMOVE_QUOTED_NEWLINE
- is non-zero, we remove unquoted \<newline> pairs. This is used by
- read_secondary_line to read here documents. */
-static char *
-read_a_line (remove_quoted_newline)
- int remove_quoted_newline;
-{
- static char *line_buffer = (char *)NULL;
- static int buffer_size = 0;
- int indx = 0, c, peekc, pass_next;
-
-#if defined (READLINE)
- if (no_line_editing && SHOULD_PROMPT ())
-#else
- if (SHOULD_PROMPT ())
-#endif
- print_prompt ();
-
- pass_next = 0;
- while (1)
- {
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- c = yy_getc ();
-
- /* Ignore null bytes in input. */
- if (c == 0)
- {
-#if 0
- internal_warning ("read_a_line: ignored null byte in input");
-#endif
- continue;
- }
-
- /* If there is no more input, then we return NULL. */
- if (c == EOF)
- {
- if (interactive && bash_input.type == st_stream)
- clearerr (stdin);
- if (indx == 0)
- return ((char *)NULL);
- c = '\n';
- }
-
- /* `+2' in case the final character in the buffer is a newline. */
- RESIZE_MALLOCED_BUFFER (line_buffer, indx, 2, buffer_size, 128);
-
- /* IF REMOVE_QUOTED_NEWLINES is non-zero, we are reading a
- here document with an unquoted delimiter. In this case,
- the line will be expanded as if it were in double quotes.
- We allow a backslash to escape the next character, but we
- need to treat the backslash specially only if a backslash
- quoting a backslash-newline pair appears in the line. */
- if (pass_next)
- {
- line_buffer[indx++] = c;
- pass_next = 0;
- }
- else if (c == '\\' && remove_quoted_newline)
- {
- peekc = yy_getc ();
- if (peekc == '\n')
- {
- line_number++;
- continue; /* Make the unquoted \<newline> pair disappear. */
- }
- else
- {
- yy_ungetc (peekc);
- pass_next = 1;
- line_buffer[indx++] = c; /* Preserve the backslash. */
- }
- }
- else
- line_buffer[indx++] = c;
-
- if (c == '\n')
- {
- line_buffer[indx] = '\0';
- return (line_buffer);
- }
- }
-}
-
-/* Return a line as in read_a_line (), but insure that the prompt is
- the secondary prompt. This is used to read the lines of a here
- document. REMOVE_QUOTED_NEWLINE is non-zero if we should remove
- newlines quoted with backslashes while reading the line. It is
- non-zero unless the delimiter of the here document was quoted. */
-char *
-read_secondary_line (remove_quoted_newline)
- int remove_quoted_newline;
-{
- prompt_string_pointer = &ps2_prompt;
- if (SHOULD_PROMPT())
- prompt_again ();
- return (read_a_line (remove_quoted_newline));
-}
-
-/* **************************************************************** */
-/* */
-/* YYLEX () */
-/* */
-/* **************************************************************** */
-
-/* Reserved words. These are only recognized as the first word of a
- command. */
-STRING_INT_ALIST word_token_alist[] = {
- { "if", IF },
- { "then", THEN },
- { "else", ELSE },
- { "elif", ELIF },
- { "fi", FI },
- { "case", CASE },
- { "esac", ESAC },
- { "for", FOR },
-#if defined (SELECT_COMMAND)
- { "select", SELECT },
-#endif
- { "while", WHILE },
- { "until", UNTIL },
- { "do", DO },
- { "done", DONE },
- { "in", IN },
- { "function", FUNCTION },
-#if defined (COMMAND_TIMING)
- { "time", TIME },
-#endif
- { "{", '{' },
- { "}", '}' },
- { "!", BANG },
-#if defined (COND_COMMAND)
- { "[[", COND_START },
- { "]]", COND_END },
-#endif
- { (char *)NULL, 0}
-};
-
-/* other tokens that can be returned by read_token() */
-STRING_INT_ALIST other_token_alist[] = {
- /* Multiple-character tokens with special values */
- { "-p", TIMEOPT },
- { "&&", AND_AND },
- { "||", OR_OR },
- { ">>", GREATER_GREATER },
- { "<<", LESS_LESS },
- { "<&", LESS_AND },
- { ">&", GREATER_AND },
- { ";;", SEMI_SEMI },
- { "<<-", LESS_LESS_MINUS },
- { "<<<", LESS_LESS_LESS },
- { "&>", AND_GREATER },
- { "<>", LESS_GREATER },
- { ">|", GREATER_BAR },
- { "EOF", yacc_EOF },
- /* Tokens whose value is the character itself */
- { ">", '>' },
- { "<", '<' },
- { "-", '-' },
- { "{", '{' },
- { "}", '}' },
- { ";", ';' },
- { "(", '(' },
- { ")", ')' },
- { "|", '|' },
- { "&", '&' },
- { "newline", '\n' },
- { (char *)NULL, 0}
-};
-
-/* others not listed here:
- WORD look at yylval.word
- ASSIGNMENT_WORD look at yylval.word
- NUMBER look at yylval.number
- ARITH_CMD look at yylval.word_list
- ARITH_FOR_EXPRS look at yylval.word_list
- COND_CMD look at yylval.command
-*/
-
-/* These are used by read_token_word, but appear up here so that shell_getc
- can use them to decide when to add otherwise blank lines to the history. */
-
-/* The primary delimiter stack. */
-struct dstack dstack = { (char *)NULL, 0, 0 };
-
-/* A temporary delimiter stack to be used when decoding prompt strings.
- This is needed because command substitutions in prompt strings (e.g., PS2)
- can screw up the parser's quoting state. */
-static struct dstack temp_dstack = { (char *)NULL, 0, 0 };
-
-/* Macro for accessing the top delimiter on the stack. Returns the
- delimiter or zero if none. */
-#define current_delimiter(ds) \
- (ds.delimiter_depth ? ds.delimiters[ds.delimiter_depth - 1] : 0)
-
-#define push_delimiter(ds, character) \
- do \
- { \
- if (ds.delimiter_depth + 2 > ds.delimiter_space) \
- ds.delimiters = (char *)xrealloc \
- (ds.delimiters, (ds.delimiter_space += 10) * sizeof (char)); \
- ds.delimiters[ds.delimiter_depth] = character; \
- ds.delimiter_depth++; \
- } \
- while (0)
-
-#define pop_delimiter(ds) ds.delimiter_depth--
-
-/* Return the next shell input character. This always reads characters
- from shell_input_line; when that line is exhausted, it is time to
- read the next line. This is called by read_token when the shell is
- processing normal command input. */
-
-/* This implements one-character lookahead/lookbehind across physical input
- lines, to avoid something being lost because it's pushed back with
- shell_ungetc when we're at the start of a line. */
-static int eol_ungetc_lookahead = 0;
-
-static int
-shell_getc (remove_quoted_newline)
- int remove_quoted_newline;
-{
- register int i;
- int c;
- unsigned char uc;
-
- QUIT;
-
- if (sigwinch_received)
- {
- sigwinch_received = 0;
- get_new_window_size (0, (int *)0, (int *)0);
- }
-
- if (eol_ungetc_lookahead)
- {
- c = eol_ungetc_lookahead;
- eol_ungetc_lookahead = 0;
- return (c);
- }
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- /* If shell_input_line[shell_input_line_index] == 0, but there is
- something on the pushed list of strings, then we don't want to go
- off and get another line. We let the code down below handle it. */
-
- if (!shell_input_line || ((!shell_input_line[shell_input_line_index]) &&
- (pushed_string_list == (STRING_SAVER *)NULL)))
-#else /* !ALIAS && !DPAREN_ARITHMETIC */
- if (!shell_input_line || !shell_input_line[shell_input_line_index])
-#endif /* !ALIAS && !DPAREN_ARITHMETIC */
- {
- line_number++;
-
- restart_read:
-
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- i = 0;
- shell_input_line_terminator = 0;
-
- /* If the shell is interatctive, but not currently printing a prompt
- (interactive_shell && interactive == 0), we don't want to print
- notifies or cleanup the jobs -- we want to defer it until we do
- print the next prompt. */
- if (interactive_shell == 0 || SHOULD_PROMPT())
- {
-#if defined (JOB_CONTROL)
- /* This can cause a problem when reading a command as the result
- of a trap, when the trap is called from flush_child. This call
- had better not cause jobs to disappear from the job table in
- that case, or we will have big trouble. */
- notify_and_cleanup ();
-#else /* !JOB_CONTROL */
- cleanup_dead_jobs ();
-#endif /* !JOB_CONTROL */
- }
-
-#if defined (READLINE)
- if (no_line_editing && SHOULD_PROMPT())
-#else
- if (SHOULD_PROMPT())
-#endif
- print_prompt ();
-
- if (bash_input.type == st_stream)
- clearerr (stdin);
-
- while (1)
- {
- c = yy_getc ();
-
- /* Allow immediate exit if interrupted during input. */
- QUIT;
-
- if (c == '\0')
- {
-#if 0
- internal_warning ("shell_getc: ignored null byte in input");
-#endif
- continue;
- }
-
- RESIZE_MALLOCED_BUFFER (shell_input_line, i, 2, shell_input_line_size, 256);
-
- if (c == EOF)
- {
- if (bash_input.type == st_stream)
- clearerr (stdin);
-
- if (i == 0)
- shell_input_line_terminator = EOF;
-
- shell_input_line[i] = '\0';
- break;
- }
-
- shell_input_line[i++] = c;
-
- if (c == '\n')
- {
- shell_input_line[--i] = '\0';
- current_command_line_count++;
- break;
- }
- }
-
- shell_input_line_index = 0;
- shell_input_line_len = i; /* == strlen (shell_input_line) */
-
- set_line_mbstate ();
-
-#if defined (HISTORY)
- if (remember_on_history && shell_input_line && shell_input_line[0])
- {
- char *expansions;
-# if defined (BANG_HISTORY)
- int old_hist;
-
- /* If the current delimiter is a single quote, we should not be
- performing history expansion, even if we're on a different
- line from the original single quote. */
- old_hist = history_expansion_inhibited;
- if (current_delimiter (dstack) == '\'')
- history_expansion_inhibited = 1;
-# endif
- expansions = pre_process_line (shell_input_line, 1, 1);
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = old_hist;
-# endif
- if (expansions != shell_input_line)
- {
- free (shell_input_line);
- shell_input_line = expansions;
- shell_input_line_len = shell_input_line ?
- strlen (shell_input_line) : 0;
- if (!shell_input_line_len)
- current_command_line_count--;
-
- /* We have to force the xrealloc below because we don't know
- the true allocated size of shell_input_line anymore. */
- shell_input_line_size = shell_input_line_len;
-
- set_line_mbstate ();
- }
- }
- /* Try to do something intelligent with blank lines encountered while
- entering multi-line commands. XXX - this is grotesque */
- else if (remember_on_history && shell_input_line &&
- shell_input_line[0] == '\0' &&
- current_command_line_count > 1)
- {
- if (current_delimiter (dstack))
- /* We know shell_input_line[0] == 0 and we're reading some sort of
- quoted string. This means we've got a line consisting of only
- a newline in a quoted string. We want to make sure this line
- gets added to the history. */
- maybe_add_history (shell_input_line);
- else
- {
- char *hdcs;
- hdcs = history_delimiting_chars ();
- if (hdcs && hdcs[0] == ';')
- maybe_add_history (shell_input_line);
- }
- }
-
-#endif /* HISTORY */
-
- if (shell_input_line)
- {
- /* Lines that signify the end of the shell's input should not be
- echoed. */
- if (echo_input_at_read && (shell_input_line[0] ||
- shell_input_line_terminator != EOF))
- fprintf (stderr, "%s\n", shell_input_line);
- }
- else
- {
- shell_input_line_size = 0;
- prompt_string_pointer = &current_prompt_string;
- if (SHOULD_PROMPT ())
- prompt_again ();
- goto restart_read;
- }
-
- /* Add the newline to the end of this string, iff the string does
- not already end in an EOF character. */
- if (shell_input_line_terminator != EOF)
- {
- if (shell_input_line_len + 3 > shell_input_line_size)
- shell_input_line = (char *)xrealloc (shell_input_line,
- 1 + (shell_input_line_size += 2));
-
- shell_input_line[shell_input_line_len] = '\n';
- shell_input_line[shell_input_line_len + 1] = '\0';
-
- set_line_mbstate ();
- }
- }
-
- uc = shell_input_line[shell_input_line_index];
-
- if (uc)
- shell_input_line_index++;
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- /* If UC is NULL, we have reached the end of the current input string. If
- pushed_string_list is non-empty, it's time to pop to the previous string
- because we have fully consumed the result of the last alias expansion.
- Do it transparently; just return the next character of the string popped
- to. */
- if (!uc && (pushed_string_list != (STRING_SAVER *)NULL))
- {
- pop_string ();
- uc = shell_input_line[shell_input_line_index];
- if (uc)
- shell_input_line_index++;
- }
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
- if MBTEST(uc == '\\' && remove_quoted_newline && shell_input_line[shell_input_line_index] == '\n')
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- line_number++;
- goto restart_read;
- }
-
- if (!uc && shell_input_line_terminator == EOF)
- return ((shell_input_line_index != 0) ? '\n' : EOF);
-
- return (uc);
-}
-
-/* Put C back into the input for the shell. This might need changes for
- HANDLE_MULTIBYTE around EOLs. Since we (currently) never push back a
- character different than we read, shell_input_line_property doesn't need
- to change when manipulating shell_input_line. The define for
- last_shell_getc_is_singlebyte should take care of it, though. */
-static void
-shell_ungetc (c)
- int c;
-{
- if (shell_input_line && shell_input_line_index)
- shell_input_line[--shell_input_line_index] = c;
- else
- eol_ungetc_lookahead = c;
-}
-
-#ifdef INCLUDE_UNUSED
-/* Back the input pointer up by one, effectively `ungetting' a character. */
-static void
-shell_ungetchar ()
-{
- if (shell_input_line && shell_input_line_index)
- shell_input_line_index--;
-}
-#endif
-
-/* Discard input until CHARACTER is seen, then push that character back
- onto the input stream. */
-static void
-discard_until (character)
- int character;
-{
- int c;
-
- while ((c = shell_getc (0)) != EOF && c != character)
- ;
-
- if (c != EOF)
- shell_ungetc (c);
-}
-
-void
-execute_variable_command (command, vname)
- char *command, *vname;
-{
- char *last_lastarg;
- sh_parser_state_t ps;
-
- save_parser_state (&ps);
- last_lastarg = get_string_value ("_");
- if (last_lastarg)
- last_lastarg = savestring (last_lastarg);
-
- parse_and_execute (savestring (command), vname, SEVAL_NONINT|SEVAL_NOHIST);
-
- restore_parser_state (&ps);
- bind_variable ("_", last_lastarg, 0);
- FREE (last_lastarg);
-
- if (token_to_read == '\n') /* reset_parser was called */
- token_to_read = 0;
-}
-
-/* Place to remember the token. We try to keep the buffer
- at a reasonable size, but it can grow. */
-static char *token = (char *)NULL;
-
-/* Current size of the token buffer. */
-static int token_buffer_size;
-
-/* Command to read_token () explaining what we want it to do. */
-#define READ 0
-#define RESET 1
-#define prompt_is_ps1 \
- (!prompt_string_pointer || prompt_string_pointer == &ps1_prompt)
-
-/* Function for yyparse to call. yylex keeps track of
- the last two tokens read, and calls read_token. */
-static int
-yylex ()
-{
- if (interactive && (current_token == 0 || current_token == '\n'))
- {
- /* Before we print a prompt, we might have to check mailboxes.
- We do this only if it is time to do so. Notice that only here
- is the mail alarm reset; nothing takes place in check_mail ()
- except the checking of mail. Please don't change this. */
- if (prompt_is_ps1 && time_to_check_mail ())
- {
- check_mail ();
- reset_mail_timer ();
- }
-
- /* Avoid printing a prompt if we're not going to read anything, e.g.
- after resetting the parser with read_token (RESET). */
- if (token_to_read == 0 && SHOULD_PROMPT ())
- prompt_again ();
- }
-
- two_tokens_ago = token_before_that;
- token_before_that = last_read_token;
- last_read_token = current_token;
- current_token = read_token (READ);
- return (current_token);
-}
-
-/* When non-zero, we have read the required tokens
- which allow ESAC to be the next one read. */
-static int esacs_needed_count;
-
-void
-gather_here_documents ()
-{
- int r = 0;
- while (need_here_doc)
- {
- make_here_document (redir_stack[r++]);
- need_here_doc--;
- }
-}
-
-/* When non-zero, an open-brace used to create a group is awaiting a close
- brace partner. */
-static int open_brace_count;
-
-#define command_token_position(token) \
- (((token) == ASSIGNMENT_WORD) || \
- ((token) != SEMI_SEMI && reserved_word_acceptable(token)))
-
-#define assignment_acceptable(token) \
- (command_token_position(token) && ((parser_state & PST_CASEPAT) == 0))
-
-/* Check to see if TOKEN is a reserved word and return the token
- value if it is. */
-#define CHECK_FOR_RESERVED_WORD(tok) \
- do { \
- if (!dollar_present && !quoted && \
- reserved_word_acceptable (last_read_token)) \
- { \
- int i; \
- for (i = 0; word_token_alist[i].word != (char *)NULL; i++) \
- if (STREQ (tok, word_token_alist[i].word)) \
- { \
- if ((parser_state & PST_CASEPAT) && (word_token_alist[i].token != ESAC)) \
- break; \
- if (word_token_alist[i].token == TIME && time_command_acceptable () == 0) \
- break; \
- if (word_token_alist[i].token == ESAC) \
- parser_state &= ~(PST_CASEPAT|PST_CASESTMT); \
- else if (word_token_alist[i].token == CASE) \
- parser_state |= PST_CASESTMT; \
- else if (word_token_alist[i].token == COND_END) \
- parser_state &= ~(PST_CONDCMD|PST_CONDEXPR); \
- else if (word_token_alist[i].token == COND_START) \
- parser_state |= PST_CONDCMD; \
- else if (word_token_alist[i].token == '{') \
- open_brace_count++; \
- else if (word_token_alist[i].token == '}' && open_brace_count) \
- open_brace_count--; \
- return (word_token_alist[i].token); \
- } \
- } \
- } while (0)
-
-#if defined (ALIAS)
-
- /* OK, we have a token. Let's try to alias expand it, if (and only if)
- it's eligible.
-
- It is eligible for expansion if EXPAND_ALIASES is set, and
- the token is unquoted and the last token read was a command
- separator (or expand_next_token is set), and we are currently
- processing an alias (pushed_string_list is non-empty) and this
- token is not the same as the current or any previously
- processed alias.
-
- Special cases that disqualify:
- In a pattern list in a case statement (parser_state & PST_CASEPAT). */
-
-static char *
-mk_alexpansion (s)
- char *s;
-{
- int l;
- char *r;
-
- l = strlen (s);
- r = xmalloc (l + 2);
- strcpy (r, s);
- if (r[l -1] != ' ')
- r[l++] = ' ';
- r[l] = '\0';
- return r;
-}
-
-static int
-alias_expand_token (tokstr)
- char *tokstr;
-{
- char *expanded;
- alias_t *ap;
-
- if (((parser_state & PST_ALEXPNEXT) || command_token_position (last_read_token)) &&
- (parser_state & PST_CASEPAT) == 0)
- {
- ap = find_alias (tokstr);
-
- /* Currently expanding this token. */
- if (ap && (ap->flags & AL_BEINGEXPANDED))
- return (NO_EXPANSION);
-
- /* mk_alexpansion puts an extra space on the end of the alias expansion,
- so the lookahead by the parser works right. If this gets changed,
- make sure the code in shell_getc that deals with reaching the end of
- an expanded alias is changed with it. */
- expanded = ap ? mk_alexpansion (ap->value) : (char *)NULL;
-
- if (expanded)
- {
- push_string (expanded, ap->flags & AL_EXPANDNEXT, ap);
- return (RE_READ_TOKEN);
- }
- else
- /* This is an eligible token that does not have an expansion. */
- return (NO_EXPANSION);
- }
- return (NO_EXPANSION);
-}
-#endif /* ALIAS */
-
-static int
-time_command_acceptable ()
-{
-#if defined (COMMAND_TIMING)
- switch (last_read_token)
- {
- case 0:
- case ';':
- case '\n':
- case AND_AND:
- case OR_OR:
- case '&':
- case DO:
- case THEN:
- case ELSE:
- case '{': /* } */
- case '(': /* ) */
- return 1;
- default:
- return 0;
- }
-#else
- return 0;
-#endif /* COMMAND_TIMING */
-}
-
-/* Handle special cases of token recognition:
- IN is recognized if the last token was WORD and the token
- before that was FOR or CASE or SELECT.
-
- DO is recognized if the last token was WORD and the token
- before that was FOR or SELECT.
-
- ESAC is recognized if the last token caused `esacs_needed_count'
- to be set
-
- `{' is recognized if the last token as WORD and the token
- before that was FUNCTION, or if we just parsed an arithmetic
- `for' command.
-
- `}' is recognized if there is an unclosed `{' present.
-
- `-p' is returned as TIMEOPT if the last read token was TIME.
-
- ']]' is returned as COND_END if the parser is currently parsing
- a conditional expression ((parser_state & PST_CONDEXPR) != 0)
-
- `time' is returned as TIME if and only if it is immediately
- preceded by one of `;', `\n', `||', `&&', or `&'.
-*/
-
-static int
-special_case_tokens (tokstr)
- char *tokstr;
-{
- if ((last_read_token == WORD) &&
-#if defined (SELECT_COMMAND)
- ((token_before_that == FOR) || (token_before_that == CASE) || (token_before_that == SELECT)) &&
-#else
- ((token_before_that == FOR) || (token_before_that == CASE)) &&
-#endif
- (tokstr[0] == 'i' && tokstr[1] == 'n' && tokstr[2] == 0))
- {
- if (token_before_that == CASE)
- {
- parser_state |= PST_CASEPAT;
- esacs_needed_count++;
- }
- return (IN);
- }
-
- if (last_read_token == WORD &&
-#if defined (SELECT_COMMAND)
- (token_before_that == FOR || token_before_that == SELECT) &&
-#else
- (token_before_that == FOR) &&
-#endif
- (tokstr[0] == 'd' && tokstr[1] == 'o' && tokstr[2] == '\0'))
- return (DO);
-
- /* Ditto for ESAC in the CASE case.
- Specifically, this handles "case word in esac", which is a legal
- construct, certainly because someone will pass an empty arg to the
- case construct, and we don't want it to barf. Of course, we should
- insist that the case construct has at least one pattern in it, but
- the designers disagree. */
- if (esacs_needed_count)
- {
- esacs_needed_count--;
- if (STREQ (tokstr, "esac"))
- {
- parser_state &= ~PST_CASEPAT;
- return (ESAC);
- }
- }
-
- /* The start of a shell function definition. */
- if (parser_state & PST_ALLOWOPNBRC)
- {
- parser_state &= ~PST_ALLOWOPNBRC;
- if (tokstr[0] == '{' && tokstr[1] == '\0') /* } */
- {
- open_brace_count++;
- function_bstart = line_number;
- return ('{'); /* } */
- }
- }
-
- /* We allow a `do' after a for ((...)) without an intervening
- list_terminator */
- if (last_read_token == ARITH_FOR_EXPRS && tokstr[0] == 'd' && tokstr[1] == 'o' && !tokstr[2])
- return (DO);
- if (last_read_token == ARITH_FOR_EXPRS && tokstr[0] == '{' && tokstr[1] == '\0') /* } */
- {
- open_brace_count++;
- return ('{'); /* } */
- }
-
- if (open_brace_count && reserved_word_acceptable (last_read_token) && tokstr[0] == '}' && !tokstr[1])
- {
- open_brace_count--; /* { */
- return ('}');
- }
-
-#if defined (COMMAND_TIMING)
- /* Handle -p after `time'. */
- if (last_read_token == TIME && tokstr[0] == '-' && tokstr[1] == 'p' && !tokstr[2])
- return (TIMEOPT);
-#endif
-
-#if 0
-#if defined (COMMAND_TIMING)
- if (STREQ (token, "time") && ((parser_state & PST_CASEPAT) == 0) && time_command_acceptable ())
- return (TIME);
-#endif /* COMMAND_TIMING */
-#endif
-
-#if defined (COND_COMMAND) /* [[ */
- if ((parser_state & PST_CONDEXPR) && tokstr[0] == ']' && tokstr[1] == ']' && tokstr[2] == '\0')
- return (COND_END);
-#endif
-
- return (-1);
-}
-
-/* Called from shell.c when Control-C is typed at top level. Or
- by the error rule at top level. */
-void
-reset_parser ()
-{
- dstack.delimiter_depth = 0; /* No delimiters found so far. */
- open_brace_count = 0;
-
- parser_state = 0;
-
-#if defined (ALIAS) || defined (DPAREN_ARITHMETIC)
- if (pushed_string_list)
- free_string_list ();
-#endif /* ALIAS || DPAREN_ARITHMETIC */
-
- if (shell_input_line)
- {
- free (shell_input_line);
- shell_input_line = (char *)NULL;
- shell_input_line_size = shell_input_line_index = 0;
- }
-
- FREE (word_desc_to_read);
- word_desc_to_read = (WORD_DESC *)NULL;
-
- last_read_token = '\n';
- token_to_read = '\n';
-}
-
-/* Read the next token. Command can be READ (normal operation) or
- RESET (to normalize state). */
-static int
-read_token (command)
- int command;
-{
- int character; /* Current character. */
- int peek_char; /* Temporary look-ahead character. */
- int result; /* The thing to return. */
-
- if (command == RESET)
- {
- reset_parser ();
- return ('\n');
- }
-
- if (token_to_read)
- {
- result = token_to_read;
- if (token_to_read == WORD || token_to_read == ASSIGNMENT_WORD)
- {
- yylval.word = word_desc_to_read;
- word_desc_to_read = (WORD_DESC *)NULL;
- }
- token_to_read = 0;
- return (result);
- }
-
-#if defined (COND_COMMAND)
- if ((parser_state & (PST_CONDCMD|PST_CONDEXPR)) == PST_CONDCMD)
- {
- cond_lineno = line_number;
- parser_state |= PST_CONDEXPR;
- yylval.command = parse_cond_command ();
- if (cond_token != COND_END)
- {
- cond_error ();
- return (-1);
- }
- token_to_read = COND_END;
- parser_state &= ~(PST_CONDEXPR|PST_CONDCMD);
- return (COND_CMD);
- }
-#endif
-
-#if defined (ALIAS)
- /* This is a place to jump back to once we have successfully expanded a
- token with an alias and pushed the string with push_string () */
- re_read_token:
-#endif /* ALIAS */
-
- /* Read a single word from input. Start by skipping blanks. */
- while ((character = shell_getc (1)) != EOF && shellblank (character))
- ;
-
- if (character == EOF)
- {
- EOF_Reached = 1;
- return (yacc_EOF);
- }
-
- if MBTEST(character == '#' && (!interactive || interactive_comments))
- {
- /* A comment. Discard until EOL or EOF, and then return a newline. */
- discard_until ('\n');
- shell_getc (0);
- character = '\n'; /* this will take the next if statement and return. */
- }
-
- if (character == '\n')
- {
- /* If we're about to return an unquoted newline, we can go and collect
- the text of any pending here document. */
- if (need_here_doc)
- gather_here_documents ();
-
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- parser_state &= ~PST_ASSIGNOK;
-
- return (character);
- }
-
- /* Shell meta-characters. */
- if MBTEST(shellmeta (character) && ((parser_state & PST_DBLPAREN) == 0))
- {
-#if defined (ALIAS)
- /* Turn off alias tokenization iff this character sequence would
- not leave us ready to read a command. */
- if (character == '<' || character == '>')
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- parser_state &= ~PST_ASSIGNOK;
-
- peek_char = shell_getc (1);
- if (character == peek_char)
- {
- switch (character)
- {
- case '<':
- /* If '<' then we could be at "<<" or at "<<-". We have to
- look ahead one more character. */
- peek_char = shell_getc (1);
- if (peek_char == '-')
- return (LESS_LESS_MINUS);
- else if (peek_char == '<')
- return (LESS_LESS_LESS);
- else
- {
- shell_ungetc (peek_char);
- return (LESS_LESS);
- }
-
- case '>':
- return (GREATER_GREATER);
-
- case ';':
- parser_state |= PST_CASEPAT;
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
-
- return (SEMI_SEMI);
-
- case '&':
- return (AND_AND);
-
- case '|':
- return (OR_OR);
-
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
- case '(': /* ) */
- result = parse_dparen (character);
- if (result == -2)
- break;
- else
- return result;
-#endif
- }
- }
- else if MBTEST(character == '<' && peek_char == '&')
- return (LESS_AND);
- else if MBTEST(character == '>' && peek_char == '&')
- return (GREATER_AND);
- else if MBTEST(character == '<' && peek_char == '>')
- return (LESS_GREATER);
- else if MBTEST(character == '>' && peek_char == '|')
- return (GREATER_BAR);
- else if MBTEST(peek_char == '>' && character == '&')
- return (AND_GREATER);
-
- shell_ungetc (peek_char);
-
- /* If we look like we are reading the start of a function
- definition, then let the reader know about it so that
- we will do the right thing with `{'. */
- if MBTEST(character == ')' && last_read_token == '(' && token_before_that == WORD)
- {
- parser_state |= PST_ALLOWOPNBRC;
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
- function_dstart = line_number;
- }
-
- /* case pattern lists may be preceded by an optional left paren. If
- we're not trying to parse a case pattern list, the left paren
- indicates a subshell. */
- if MBTEST(character == '(' && (parser_state & PST_CASEPAT) == 0) /* ) */
- parser_state |= PST_SUBSHELL;
- /*(*/
- else if MBTEST((parser_state & PST_CASEPAT) && character == ')')
- parser_state &= ~PST_CASEPAT;
- /*(*/
- else if MBTEST((parser_state & PST_SUBSHELL) && character == ')')
- parser_state &= ~PST_SUBSHELL;
-
-#if defined (PROCESS_SUBSTITUTION)
- /* Check for the constructs which introduce process substitution.
- Shells running in `posix mode' don't do process substitution. */
- if MBTEST(posixly_correct || ((character != '>' && character != '<') || peek_char != '(')) /*)*/
-#endif /* PROCESS_SUBSTITUTION */
- return (character);
- }
-
- /* Hack <&- (close stdin) case. Also <&N- (dup and close). */
- if MBTEST(character == '-' && (last_read_token == LESS_AND || last_read_token == GREATER_AND))
- return (character);
-
- /* Okay, if we got this far, we have to read a word. Read one,
- and then check it against the known ones. */
- result = read_token_word (character);
-#if defined (ALIAS)
- if (result == RE_READ_TOKEN)
- goto re_read_token;
-#endif
- return result;
-}
-
-/*
- * Match a $(...) or other grouping construct. This has to handle embedded
- * quoted strings ('', ``, "") and nested constructs. It also must handle
- * reprompting the user, if necessary, after reading a newline, and returning
- * correct error values if it reads EOF.
- */
-#define P_FIRSTCLOSE 0x01
-#define P_ALLOWESC 0x02
-#define P_DQUOTE 0x04
-#define P_COMMAND 0x08 /* parsing a command, so look for comments */
-#define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
-
-static char matched_pair_error;
-static char *
-parse_matched_pair (qc, open, close, lenp, flags)
- int qc; /* `"' if this construct is within double quotes */
- int open, close;
- int *lenp, flags;
-{
- int count, ch, was_dollar, in_comment, check_comment;
- int pass_next_character, backq_backslash, nestlen, ttranslen, start_lineno;
- char *ret, *nestret, *ttrans;
- int retind, retsize, rflags;
-
-/* itrace("parse_matched_pair: open = %c close = %c", open, close); */
- count = 1;
- pass_next_character = backq_backslash = was_dollar = in_comment = 0;
- check_comment = (flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0;
-
- /* RFLAGS is the set of flags we want to pass to recursive calls. */
- rflags = (qc == '"') ? P_DQUOTE : (flags & P_DQUOTE);
-
- ret = (char *)xmalloc (retsize = 64);
- retind = 0;
-
- start_lineno = line_number;
- while (count)
- {
- ch = shell_getc (qc != '\'' && pass_next_character == 0 && backq_backslash == 0);
-
- if (ch == EOF)
- {
- free (ret);
- parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
- EOF_Reached = 1; /* XXX */
- return (&matched_pair_error);
- }
-
- /* Possible reprompting. */
- if (ch == '\n' && SHOULD_PROMPT ())
- prompt_again ();
-
- if (in_comment)
- {
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
-
- if (ch == '\n')
- in_comment = 0;
-
- continue;
- }
- /* Not exactly right yet, should handle shell metacharacters, too. If
- any changes are made to this test, make analogous changes to subst.c:
- extract_delimited_string(). */
- else if MBTEST(check_comment && in_comment == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || whitespace (ret[retind - 1])))
- in_comment = 1;
-
- /* last char was backslash inside backquoted command substitution */
- if (backq_backslash)
- {
- backq_backslash = 0;
- /* Placeholder for adding special characters */
- }
-
- if (pass_next_character) /* last char was backslash */
- {
- pass_next_character = 0;
- if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
- {
- if (retind > 0) retind--; /* swallow previously-added backslash */
- continue;
- }
-
- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
- if MBTEST(ch == CTLESC || ch == CTLNUL)
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
- else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
- else if MBTEST(ch == close) /* ending delimiter */
- count--;
- /* handle nested ${...} specially. */
- else if MBTEST(open != close && was_dollar && open == '{' && ch == open) /* } */
- count++;
- else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && ch == open) /* nested begin */
- count++;
-
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
-
- if (open == '\'') /* '' inside grouping construct */
- {
- if MBTEST((flags & P_ALLOWESC) && ch == '\\')
- pass_next_character++;
-#if 0
- else if MBTEST((flags & P_BACKQUOTE) && ch == '\\')
- backq_backslash++;
-#endif
- continue;
- }
-
- if MBTEST(ch == '\\') /* backslashes */
- pass_next_character++;
-
- if (open != close) /* a grouping construct */
- {
- if MBTEST(shellquote (ch))
- {
- /* '', ``, or "" inside $(...) or other grouping construct. */
- push_delimiter (dstack, ch);
- if MBTEST(was_dollar && ch == '\'') /* $'...' inside group */
- nestret = parse_matched_pair (ch, ch, ch, &nestlen, P_ALLOWESC|rflags);
- else
- nestret = parse_matched_pair (ch, ch, ch, &nestlen, rflags);
- pop_delimiter (dstack);
- if (nestret == &matched_pair_error)
- {
- free (ret);
- return &matched_pair_error;
- }
- if MBTEST(was_dollar && ch == '\'' && (extended_quote || (rflags & P_DQUOTE) == 0))
- {
- /* Translate $'...' here. */
- ttrans = ansiexpand (nestret, 0, nestlen - 1, &ttranslen);
- xfree (nestret);
-
- if ((rflags & P_DQUOTE) == 0)
- {
- nestret = sh_single_quote (ttrans);
- free (ttrans);
- nestlen = strlen (nestret);
- }
- else
- {
- nestret = ttrans;
- nestlen = ttranslen;
- }
- retind -= 2; /* back up before the $' */
- }
- else if MBTEST(was_dollar && ch == '"' && (extended_quote || (rflags & P_DQUOTE) == 0))
- {
- /* Locale expand $"..." here. */
- ttrans = localeexpand (nestret, 0, nestlen - 1, start_lineno, &ttranslen);
- xfree (nestret);
-
- nestret = sh_mkdoublequoted (ttrans, ttranslen, 0);
- free (ttrans);
- nestlen = ttranslen + 2;
- retind -= 2; /* back up before the $" */
- }
-
- if (nestlen)
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
- strcpy (ret + retind, nestret);
- retind += nestlen;
- }
- FREE (nestret);
- }
- }
- /* Parse an old-style command substitution within double quotes as a
- single word. */
- /* XXX - sh and ksh93 don't do this - XXX */
- else if MBTEST(open == '"' && ch == '`')
- {
- nestret = parse_matched_pair (0, '`', '`', &nestlen, rflags);
-add_nestret:
- if (nestret == &matched_pair_error)
- {
- free (ret);
- return &matched_pair_error;
- }
- if (nestlen)
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64);
- strcpy (ret + retind, nestret);
- retind += nestlen;
- }
- FREE (nestret);
- }
-#if 0
- else if MBTEST(qc == '`' && (ch == '"' || ch == '\'') && in_comment == 0)
- {
- /* Add P_BACKQUOTE so backslash quotes the next character and
- shell_getc does the right thing with \<newline>. We do this for
- a measure of backwards compatibility -- it's not strictly the
- right POSIX thing. */
- nestret = parse_matched_pair (0, ch, ch, &nestlen, rflags|P_BACKQUOTE);
- goto add_nestret;
- }
-#endif
- else if MBTEST(open != '`' && was_dollar && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
- /* check for $(), $[], or ${} inside quoted string. */
- {
- if (open == ch) /* undo previous increment */
- count--;
- if (ch == '(') /* ) */
- nestret = parse_matched_pair (0, '(', ')', &nestlen, rflags & ~P_DQUOTE);
- else if (ch == '{') /* } */
- nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|rflags);
- else if (ch == '[') /* ] */
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
-
- goto add_nestret;
- }
- was_dollar = MBTEST(ch == '$');
- }
-
- ret[retind] = '\0';
- if (lenp)
- *lenp = retind;
- return ret;
-}
-
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
-/* Parse a double-paren construct. It can be either an arithmetic
- command, an arithmetic `for' command, or a nested subshell. Returns
- the parsed token, -1 on error, or -2 if we didn't do anything and
- should just go on. */
-static int
-parse_dparen (c)
- int c;
-{
- int cmdtyp, sline;
- char *wval;
- WORD_DESC *wd;
-
-#if defined (ARITH_FOR_COMMAND)
- if (last_read_token == FOR)
- {
- arith_for_lineno = line_number;
- cmdtyp = parse_arith_cmd (&wval, 0);
- if (cmdtyp == 1)
- {
- wd = alloc_word_desc ();
- wd->word = wval;
- yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
- return (ARITH_FOR_EXPRS);
- }
- else
- return -1; /* ERROR */
- }
-#endif
-
-#if defined (DPAREN_ARITHMETIC)
- if (reserved_word_acceptable (last_read_token))
- {
- sline = line_number;
-
- cmdtyp = parse_arith_cmd (&wval, 0);
- if (cmdtyp == 1) /* arithmetic command */
- {
- wd = alloc_word_desc ();
- wd->word = wval;
- wd->flags = W_QUOTED|W_NOSPLIT|W_NOGLOB|W_DQUOTE;
- yylval.word_list = make_word_list (wd, (WORD_LIST *)NULL);
- return (ARITH_CMD);
- }
- else if (cmdtyp == 0) /* nested subshell */
- {
- push_string (wval, 0, (alias_t *)NULL);
- if ((parser_state & PST_CASEPAT) == 0)
- parser_state |= PST_SUBSHELL;
- return (c);
- }
- else /* ERROR */
- return -1;
- }
-#endif
-
- return -2; /* XXX */
-}
-
-/* We've seen a `(('. Look for the matching `))'. If we get it, return 1.
- If not, assume it's a nested subshell for backwards compatibility and
- return 0. In any case, put the characters we've consumed into a locally-
- allocated buffer and make *ep point to that buffer. Return -1 on an
- error, for example EOF. */
-static int
-parse_arith_cmd (ep, adddq)
- char **ep;
- int adddq;
-{
- int exp_lineno, rval, c;
- char *ttok, *tokstr;
- int ttoklen;
-
- exp_lineno = line_number;
- ttok = parse_matched_pair (0, '(', ')', &ttoklen, 0);
- rval = 1;
- if (ttok == &matched_pair_error)
- return -1;
- /* Check that the next character is the closing right paren. If
- not, this is a syntax error. ( */
- c = shell_getc (0);
- if MBTEST(c != ')')
- rval = 0;
-
- tokstr = (char *)xmalloc (ttoklen + 4);
-
- /* if ADDDQ != 0 then (( ... )) -> "..." */
- if (rval == 1 && adddq) /* arith cmd, add double quotes */
- {
- tokstr[0] = '"';
- strncpy (tokstr + 1, ttok, ttoklen - 1);
- tokstr[ttoklen] = '"';
- tokstr[ttoklen+1] = '\0';
- }
- else if (rval == 1) /* arith cmd, don't add double quotes */
- {
- strncpy (tokstr, ttok, ttoklen - 1);
- tokstr[ttoklen-1] = '\0';
- }
- else /* nested subshell */
- {
- tokstr[0] = '(';
- strncpy (tokstr + 1, ttok, ttoklen - 1);
- tokstr[ttoklen] = ')';
- tokstr[ttoklen+1] = c;
- tokstr[ttoklen+2] = '\0';
- }
-
- *ep = tokstr;
- FREE (ttok);
- return rval;
-}
-#endif /* DPAREN_ARITHMETIC || ARITH_FOR_COMMAND */
-
-#if defined (COND_COMMAND)
-static void
-cond_error ()
-{
- char *etext;
-
- if (EOF_Reached && cond_token != COND_ERROR) /* [[ */
- parser_error (cond_lineno, _("unexpected EOF while looking for `]]'"));
- else if (cond_token != COND_ERROR)
- {
- if (etext = error_token_from_token (cond_token))
- {
- parser_error (cond_lineno, _("syntax error in conditional expression: unexpected token `%s'"), etext);
- free (etext);
- }
- else
- parser_error (cond_lineno, _("syntax error in conditional expression"));
- }
-}
-
-static COND_COM *
-cond_expr ()
-{
- return (cond_or ());
-}
-
-static COND_COM *
-cond_or ()
-{
- COND_COM *l, *r;
-
- l = cond_and ();
- if (cond_token == OR_OR)
- {
- r = cond_or ();
- l = make_cond_node (COND_OR, (WORD_DESC *)NULL, l, r);
- }
- return l;
-}
-
-static COND_COM *
-cond_and ()
-{
- COND_COM *l, *r;
-
- l = cond_term ();
- if (cond_token == AND_AND)
- {
- r = cond_and ();
- l = make_cond_node (COND_AND, (WORD_DESC *)NULL, l, r);
- }
- return l;
-}
-
-static int
-cond_skip_newlines ()
-{
- while ((cond_token = read_token (READ)) == '\n')
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- }
- return (cond_token);
-}
-
-#define COND_RETURN_ERROR() \
- do { cond_token = COND_ERROR; return ((COND_COM *)NULL); } while (0)
-
-static COND_COM *
-cond_term ()
-{
- WORD_DESC *op;
- COND_COM *term, *tleft, *tright;
- int tok, lineno;
- char *etext;
-
- /* Read a token. It can be a left paren, a `!', a unary operator, or a
- word that should be the first argument of a binary operator. Start by
- skipping newlines, since this is a compound command. */
- tok = cond_skip_newlines ();
- lineno = line_number;
- if (tok == COND_END)
- {
- COND_RETURN_ERROR ();
- }
- else if (tok == '(')
- {
- term = cond_expr ();
- if (cond_token != ')')
- {
- if (term)
- dispose_cond_node (term); /* ( */
- if (etext = error_token_from_token (cond_token))
- {
- parser_error (lineno, _("unexpected token `%s', expected `)'"), etext);
- free (etext);
- }
- else
- parser_error (lineno, _("expected `)'"));
- COND_RETURN_ERROR ();
- }
- term = make_cond_node (COND_EXPR, (WORD_DESC *)NULL, term, (COND_COM *)NULL);
- (void)cond_skip_newlines ();
- }
- else if (tok == BANG || (tok == WORD && (yylval.word->word[0] == '!' && yylval.word->word[1] == '\0')))
- {
- if (tok == WORD)
- dispose_word (yylval.word); /* not needed */
- term = cond_term ();
- if (term)
- term->flags |= CMD_INVERT_RETURN;
- }
- else if (tok == WORD && test_unop (yylval.word->word))
- {
- op = yylval.word;
- tok = read_token (READ);
- if (tok == WORD)
- {
- tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
- term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
- }
- else
- {
- dispose_word (op);
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected argument `%s' to conditional unary operator"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected argument to conditional unary operator"));
- COND_RETURN_ERROR ();
- }
-
- (void)cond_skip_newlines ();
- }
- else if (tok == WORD) /* left argument to binary operator */
- {
- /* lhs */
- tleft = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
-
- /* binop */
- tok = read_token (READ);
- if (tok == WORD && test_binop (yylval.word->word))
- op = yylval.word;
-#if defined (COND_REGEXP)
- else if (tok == WORD && STREQ (yylval.word->word,"=~"))
- op = yylval.word;
-#endif
- else if (tok == '<' || tok == '>')
- op = make_word_from_token (tok); /* ( */
- /* There should be a check before blindly accepting the `)' that we have
- seen the opening `('. */
- else if (tok == COND_END || tok == AND_AND || tok == OR_OR || tok == ')')
- {
- /* Special case. [[ x ]] is equivalent to [[ -n x ]], just like
- the test command. Similarly for [[ x && expr ]] or
- [[ x || expr ]] or [[ (x) ]]. */
- op = make_word ("-n");
- term = make_cond_node (COND_UNARY, op, tleft, (COND_COM *)NULL);
- cond_token = tok;
- return (term);
- }
- else
- {
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected token `%s', conditional binary operator expected"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("conditional binary operator expected"));
- dispose_cond_node (tleft);
- COND_RETURN_ERROR ();
- }
-
- /* rhs */
- tok = read_token (READ);
- if (tok == WORD)
- {
- tright = make_cond_node (COND_TERM, yylval.word, (COND_COM *)NULL, (COND_COM *)NULL);
- term = make_cond_node (COND_BINARY, op, tleft, tright);
- }
- else
- {
- if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected argument `%s' to conditional binary operator"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected argument to conditional binary operator"));
- dispose_cond_node (tleft);
- dispose_word (op);
- COND_RETURN_ERROR ();
- }
-
- (void)cond_skip_newlines ();
- }
- else
- {
- if (tok < 256)
- parser_error (line_number, _("unexpected token `%c' in conditional command"), tok);
- else if (etext = error_token_from_token (tok))
- {
- parser_error (line_number, _("unexpected token `%s' in conditional command"), etext);
- free (etext);
- }
- else
- parser_error (line_number, _("unexpected token %d in conditional command"), tok);
- COND_RETURN_ERROR ();
- }
- return (term);
-}
-
-/* This is kind of bogus -- we slip a mini recursive-descent parser in
- here to handle the conditional statement syntax. */
-static COMMAND *
-parse_cond_command ()
-{
- COND_COM *cexp;
-
- cexp = cond_expr ();
- return (make_cond_command (cexp));
-}
-#endif
-
-#if defined (ARRAY_VARS)
-/* When this is called, it's guaranteed that we don't care about anything
- in t beyond i. We do save and restore the chars, though. */
-static int
-token_is_assignment (t, i)
- char *t;
- int i;
-{
- unsigned char c, c1;
- int r;
-
- c = t[i]; c1 = t[i+1];
- t[i] = '='; t[i+1] = '\0';
- r = assignment (t, (parser_state & PST_COMPASSIGN) != 0);
- t[i] = c; t[i+1] = c1;
- return r;
-}
-
-/* XXX - possible changes here for `+=' */
-static int
-token_is_ident (t, i)
- char *t;
- int i;
-{
- unsigned char c;
- int r;
-
- c = t[i];
- t[i] = '\0';
- r = legal_identifier (t);
- t[i] = c;
- return r;
-}
-#endif
-
-static int
-read_token_word (character)
- int character;
-{
- /* The value for YYLVAL when a WORD is read. */
- WORD_DESC *the_word;
-
- /* Index into the token that we are building. */
- int token_index;
-
- /* ALL_DIGITS becomes zero when we see a non-digit. */
- int all_digit_token;
-
- /* DOLLAR_PRESENT becomes non-zero if we see a `$'. */
- int dollar_present;
-
- /* COMPOUND_ASSIGNMENT becomes non-zero if we are parsing a compound
- assignment. */
- int compound_assignment;
-
- /* QUOTED becomes non-zero if we see one of ("), ('), (`), or (\). */
- int quoted;
-
- /* Non-zero means to ignore the value of the next character, and just
- to add it no matter what. */
- int pass_next_character;
-
- /* The current delimiting character. */
- int cd;
- int result, peek_char;
- char *ttok, *ttrans;
- int ttoklen, ttranslen;
- intmax_t lvalue;
-
- if (token_buffer_size < TOKEN_DEFAULT_INITIAL_SIZE)
- token = (char *)xrealloc (token, token_buffer_size = TOKEN_DEFAULT_INITIAL_SIZE);
-
- token_index = 0;
- all_digit_token = DIGIT (character);
- dollar_present = quoted = pass_next_character = compound_assignment = 0;
-
- for (;;)
- {
- if (character == EOF)
- goto got_token;
-
- if (pass_next_character)
- {
- pass_next_character = 0;
- goto got_character;
- }
-
- cd = current_delimiter (dstack);
-
- /* Handle backslashes. Quote lots of things when not inside of
- double-quotes, quote some things inside of double-quotes. */
- if MBTEST(character == '\\')
- {
- peek_char = shell_getc (0);
-
- /* Backslash-newline is ignored in all cases except
- when quoted with single quotes. */
- if (peek_char == '\n')
- {
- character = '\n';
- goto next_character;
- }
- else
- {
- shell_ungetc (peek_char);
-
- /* If the next character is to be quoted, note it now. */
- if (cd == 0 || cd == '`' ||
- (cd == '"' && peek_char >= 0 && (sh_syntaxtab[peek_char] & CBSDQUOTE)))
- pass_next_character++;
-
- quoted = 1;
- goto got_character;
- }
- }
-
- /* Parse a matched pair of quote characters. */
- if MBTEST(shellquote (character))
- {
- push_delimiter (dstack, character);
- ttok = parse_matched_pair (character, character, character, &ttoklen, (character == '`') ? P_COMMAND : 0);
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size, TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- all_digit_token = 0;
- quoted = 1;
- dollar_present |= (character == '"' && strchr (ttok, '$') != 0);
- FREE (ttok);
- goto next_character;
- }
-
-#ifdef EXTENDED_GLOB
- /* Parse a ksh-style extended pattern matching specification. */
- if (extended_glob && PATTERN_CHAR (character))
- {
- peek_char = shell_getc (1);
- if MBTEST(peek_char == '(') /* ) */
- {
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (cd, '(', ')', &ttoklen, 0);
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- token[token_index++] = peek_char;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- dollar_present = all_digit_token = 0;
- goto next_character;
- }
- else
- shell_ungetc (peek_char);
- }
-#endif /* EXTENDED_GLOB */
-
- /* If the delimiter character is not single quote, parse some of
- the shell expansions that must be read as a single word. */
- if (shellexp (character))
- {
- peek_char = shell_getc (1);
- /* $(...), <(...), >(...), $((...)), ${...}, and $[...] constructs */
- if MBTEST(peek_char == '(' || \
- ((peek_char == '{' || peek_char == '[') && character == '$')) /* ) ] } */
- {
- if (peek_char == '{') /* } */
- ttok = parse_matched_pair (cd, '{', '}', &ttoklen, P_FIRSTCLOSE);
- else if (peek_char == '(') /* ) */
- {
- /* XXX - push and pop the `(' as a delimiter for use by
- the command-oriented-history code. This way newlines
- appearing in the $(...) string get added to the
- history literally rather than causing a possibly-
- incorrect `;' to be added. ) */
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (cd, '(', ')', &ttoklen, P_COMMAND);
- pop_delimiter (dstack);
- }
- else
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- token[token_index++] = peek_char;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- dollar_present = 1;
- all_digit_token = 0;
- goto next_character;
- }
- /* This handles $'...' and $"..." new-style quoted strings. */
- else if MBTEST(character == '$' && (peek_char == '\'' || peek_char == '"'))
- {
- int first_line;
-
- first_line = line_number;
- push_delimiter (dstack, peek_char);
- ttok = parse_matched_pair (peek_char, peek_char, peek_char,
- &ttoklen,
- (peek_char == '\'') ? P_ALLOWESC : 0);
- pop_delimiter (dstack);
- if (ttok == &matched_pair_error)
- return -1;
- if (peek_char == '\'')
- {
- ttrans = ansiexpand (ttok, 0, ttoklen - 1, &ttranslen);
- free (ttok);
-
- /* Insert the single quotes and correctly quote any
- embedded single quotes (allowed because P_ALLOWESC was
- passed to parse_matched_pair). */
- ttok = sh_single_quote (ttrans);
- free (ttrans);
- ttranslen = strlen (ttok);
- ttrans = ttok;
- }
- else
- {
- /* Try to locale-expand the converted string. */
- ttrans = localeexpand (ttok, 0, ttoklen - 1, first_line, &ttranslen);
- free (ttok);
-
- /* Add the double quotes back */
- ttok = sh_mkdoublequoted (ttrans, ttranslen, 0);
- free (ttrans);
- ttranslen += 2;
- ttrans = ttok;
- }
-
- RESIZE_MALLOCED_BUFFER (token, token_index, ttranslen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- strcpy (token + token_index, ttrans);
- token_index += ttranslen;
- FREE (ttrans);
- quoted = 1;
- all_digit_token = 0;
- goto next_character;
- }
- /* This could eventually be extended to recognize all of the
- shell's single-character parameter expansions, and set flags.*/
- else if MBTEST(character == '$' && peek_char == '$')
- {
- ttok = (char *)xmalloc (3);
- ttok[0] = ttok[1] = '$';
- ttok[2] = '\0';
- RESIZE_MALLOCED_BUFFER (token, token_index, 3,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- strcpy (token + token_index, ttok);
- token_index += 2;
- dollar_present = 1;
- all_digit_token = 0;
- FREE (ttok);
- goto next_character;
- }
- else
- shell_ungetc (peek_char);
- }
-
-#if defined (ARRAY_VARS)
- /* Identify possible array subscript assignment; match [...] */
- else if MBTEST(character == '[' && token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) /* ] */
- {
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
- if (ttok == &matched_pair_error)
- return -1; /* Bail immediately. */
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = character;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- all_digit_token = 0;
- goto next_character;
- }
- /* Identify possible compound array variable assignment. */
- else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index))
- {
- peek_char = shell_getc (1);
- if MBTEST(peek_char == '(') /* ) */
- {
- ttok = parse_compound_assignment (&ttoklen);
-
- RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 4,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
-
- token[token_index++] = '=';
- token[token_index++] = '(';
- if (ttok)
- {
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- }
- token[token_index++] = ')';
- FREE (ttok);
- all_digit_token = 0;
- compound_assignment = 1;
-#if 1
- goto next_character;
-#else
- goto got_token; /* ksh93 seems to do this */
-#endif
- }
- else
- shell_ungetc (peek_char);
- }
-#endif
-
- /* When not parsing a multi-character word construct, shell meta-
- characters break words. */
- if MBTEST(shellbreak (character))
- {
- shell_ungetc (character);
- goto got_token;
- }
-
- got_character:
-
- all_digit_token &= DIGIT (character);
- dollar_present |= character == '$';
-
- if (character == CTLESC || character == CTLNUL)
- token[token_index++] = CTLESC;
-
- token[token_index++] = character;
-
- RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
-
- next_character:
- if (character == '\n' && SHOULD_PROMPT ())
- prompt_again ();
-
- /* We want to remove quoted newlines (that is, a \<newline> pair)
- unless we are within single quotes or pass_next_character is
- set (the shell equivalent of literal-next). */
- cd = current_delimiter (dstack);
- character = shell_getc (cd != '\'' && pass_next_character == 0);
- } /* end for (;;) */
-
-got_token:
-
- token[token_index] = '\0';
-
- /* Check to see what thing we should return. If the last_read_token
- is a `<', or a `&', or the character which ended this token is
- a '>' or '<', then, and ONLY then, is this input token a NUMBER.
- Otherwise, it is just a word, and should be returned as such. */
- if MBTEST(all_digit_token && (character == '<' || character == '>' || \
- last_read_token == LESS_AND || \
- last_read_token == GREATER_AND))
- {
- if (legal_number (token, &lvalue) && (int)lvalue == lvalue)
- yylval.number = lvalue;
- else
- yylval.number = -1;
- return (NUMBER);
- }
-
- /* Check for special case tokens. */
- result = (last_shell_getc_is_singlebyte) ? special_case_tokens (token) : -1;
- if (result >= 0)
- return result;
-
-#if defined (ALIAS)
- /* Posix.2 does not allow reserved words to be aliased, so check for all
- of them, including special cases, before expanding the current token
- as an alias. */
- if MBTEST(posixly_correct)
- CHECK_FOR_RESERVED_WORD (token);
-
- /* Aliases are expanded iff EXPAND_ALIASES is non-zero, and quoting
- inhibits alias expansion. */
- if (expand_aliases && quoted == 0)
- {
- result = alias_expand_token (token);
- if (result == RE_READ_TOKEN)
- return (RE_READ_TOKEN);
- else if (result == NO_EXPANSION)
- parser_state &= ~PST_ALEXPNEXT;
- }
-
- /* If not in Posix.2 mode, check for reserved words after alias
- expansion. */
- if MBTEST(posixly_correct == 0)
-#endif
- CHECK_FOR_RESERVED_WORD (token);
-
- the_word = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
- the_word->word = (char *)xmalloc (1 + token_index);
- the_word->flags = 0;
- strcpy (the_word->word, token);
- if (dollar_present)
- the_word->flags |= W_HASDOLLAR;
- if (quoted)
- the_word->flags |= W_QUOTED; /*(*/
- if (compound_assignment && token[token_index-1] == ')')
- the_word->flags |= W_COMPASSIGN;
- /* A word is an assignment if it appears at the beginning of a
- simple command, or after another assignment word. This is
- context-dependent, so it cannot be handled in the grammar. */
- if (assignment (token, (parser_state & PST_COMPASSIGN) != 0))
- {
- the_word->flags |= W_ASSIGNMENT;
- /* Don't perform word splitting on assignment statements. */
- if (assignment_acceptable (last_read_token) || (parser_state & PST_COMPASSIGN) != 0)
- the_word->flags |= W_NOSPLIT;
- }
-
- if (command_token_position (last_read_token))
- {
- struct builtin *b;
- b = builtin_address_internal (token, 0);
- if (b && (b->flags & ASSIGNMENT_BUILTIN))
- parser_state |= PST_ASSIGNOK;
- else if (STREQ (token, "eval") || STREQ (token, "let"))
- parser_state |= PST_ASSIGNOK;
- }
-
- yylval.word = the_word;
-
- result = ((the_word->flags & (W_ASSIGNMENT|W_NOSPLIT)) == (W_ASSIGNMENT|W_NOSPLIT))
- ? ASSIGNMENT_WORD : WORD;
-
- switch (last_read_token)
- {
- case FUNCTION:
- parser_state |= PST_ALLOWOPNBRC;
- function_dstart = line_number;
- break;
- case CASE:
- case SELECT:
- case FOR:
- if (word_top < MAX_CASE_NEST)
- word_top++;
- word_lineno[word_top] = line_number;
- break;
- }
-
- return (result);
-}
-
-/* Return 1 if TOKSYM is a token that after being read would allow
- a reserved word to be seen, else 0. */
-static int
-reserved_word_acceptable (toksym)
- int toksym;
-{
- switch (toksym)
- {
- case '\n':
- case ';':
- case '(':
- case ')':
- case '|':
- case '&':
- case '{':
- case '}': /* XXX */
- case AND_AND:
- case BANG:
- case DO:
- case DONE:
- case ELIF:
- case ELSE:
- case ESAC:
- case FI:
- case IF:
- case OR_OR:
- case SEMI_SEMI:
- case THEN:
- case TIME:
- case TIMEOPT:
- case UNTIL:
- case WHILE:
- case 0:
- return 1;
- default:
- return 0;
- }
-}
-
-/* Return the index of TOKEN in the alist of reserved words, or -1 if
- TOKEN is not a shell reserved word. */
-int
-find_reserved_word (tokstr)
- char *tokstr;
-{
- int i;
- for (i = 0; word_token_alist[i].word; i++)
- if (STREQ (tokstr, word_token_alist[i].word))
- return i;
- return -1;
-}
-
-#if 0
-#if defined (READLINE)
-/* Called after each time readline is called. This insures that whatever
- the new prompt string is gets propagated to readline's local prompt
- variable. */
-static void
-reset_readline_prompt ()
-{
- char *temp_prompt;
-
- if (prompt_string_pointer)
- {
- temp_prompt = (*prompt_string_pointer)
- ? decode_prompt_string (*prompt_string_pointer)
- : (char *)NULL;
-
- if (temp_prompt == 0)
- {
- temp_prompt = (char *)xmalloc (1);
- temp_prompt[0] = '\0';
- }
-
- FREE (current_readline_prompt);
- current_readline_prompt = temp_prompt;
- }
-}
-#endif /* READLINE */
-#endif /* 0 */
-
-#if defined (HISTORY)
-/* A list of tokens which can be followed by newlines, but not by
- semi-colons. When concatenating multiple lines of history, the
- newline separator for such tokens is replaced with a space. */
-static int no_semi_successors[] = {
- '\n', '{', '(', ')', ';', '&', '|',
- CASE, DO, ELSE, IF, SEMI_SEMI, THEN, UNTIL, WHILE, AND_AND, OR_OR, IN,
- 0
-};
-
-/* If we are not within a delimited expression, try to be smart
- about which separators can be semi-colons and which must be
- newlines. Returns the string that should be added into the
- history entry. */
-char *
-history_delimiting_chars ()
-{
- register int i;
-
- if (dstack.delimiter_depth != 0)
- return ("\n");
-
- /* First, handle some special cases. */
- /*(*/
- /* If we just read `()', assume it's a function definition, and don't
- add a semicolon. If the token before the `)' was not `(', and we're
- not in the midst of parsing a case statement, assume it's a
- parenthesized command and add the semicolon. */
- /*)(*/
- if (token_before_that == ')')
- {
- if (two_tokens_ago == '(') /*)*/ /* function def */
- return " ";
- /* This does not work for subshells inside case statement
- command lists. It's a suboptimal solution. */
- else if (parser_state & PST_CASESTMT) /* case statement pattern */
- return " ";
- else
- return "; "; /* (...) subshell */
- }
- else if (token_before_that == WORD && two_tokens_ago == FUNCTION)
- return " "; /* function def using `function name' without `()' */
-
- else if (token_before_that == WORD && two_tokens_ago == FOR)
- {
- /* Tricky. `for i\nin ...' should not have a semicolon, but
- `for i\ndo ...' should. We do what we can. */
- for (i = shell_input_line_index; whitespace(shell_input_line[i]); i++)
- ;
- if (shell_input_line[i] && shell_input_line[i] == 'i' && shell_input_line[i+1] == 'n')
- return " ";
- return ";";
- }
- else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
- return " ";
-
- for (i = 0; no_semi_successors[i]; i++)
- {
- if (token_before_that == no_semi_successors[i])
- return (" ");
- }
-
- return ("; ");
-}
-#endif /* HISTORY */
-
-/* Issue a prompt, or prepare to issue a prompt when the next character
- is read. */
-static void
-prompt_again ()
-{
- char *temp_prompt;
-
- if (interactive == 0 || expanding_alias()) /* XXX */
- return;
-
- ps1_prompt = get_string_value ("PS1");
- ps2_prompt = get_string_value ("PS2");
-
- if (!prompt_string_pointer)
- prompt_string_pointer = &ps1_prompt;
-
- temp_prompt = *prompt_string_pointer
- ? decode_prompt_string (*prompt_string_pointer)
- : (char *)NULL;
-
- if (temp_prompt == 0)
- {
- temp_prompt = (char *)xmalloc (1);
- temp_prompt[0] = '\0';
- }
-
- current_prompt_string = *prompt_string_pointer;
- prompt_string_pointer = &ps2_prompt;
-
-#if defined (READLINE)
- if (!no_line_editing)
- {
- FREE (current_readline_prompt);
- current_readline_prompt = temp_prompt;
- }
- else
-#endif /* READLINE */
- {
- FREE (current_decoded_prompt);
- current_decoded_prompt = temp_prompt;
- }
-}
-
-int
-get_current_prompt_level ()
-{
- return ((current_prompt_string && current_prompt_string == ps2_prompt) ? 2 : 1);
-}
-
-void
-set_current_prompt_level (x)
- int x;
-{
- prompt_string_pointer = (x == 2) ? &ps2_prompt : &ps1_prompt;
- current_prompt_string = *prompt_string_pointer;
-}
-
-static void
-print_prompt ()
-{
- fprintf (stderr, "%s", current_decoded_prompt);
- fflush (stderr);
-}
-
-/* Return a string which will be printed as a prompt. The string
- may contain special characters which are decoded as follows:
-
- \a bell (ascii 07)
- \d the date in Day Mon Date format
- \e escape (ascii 033)
- \h the hostname up to the first `.'
- \H the hostname
- \j the number of active jobs
- \l the basename of the shell's tty device name
- \n CRLF
- \r CR
- \s the name of the shell
- \t the time in 24-hour hh:mm:ss format
- \T the time in 12-hour hh:mm:ss format
- \@ the time in 12-hour hh:mm am/pm format
- \A the time in 24-hour hh:mm format
- \D{fmt} the result of passing FMT to strftime(3)
- \u your username
- \v the version of bash (e.g., 2.00)
- \V the release of bash, version + patchlevel (e.g., 2.00.0)
- \w the current working directory
- \W the last element of $PWD
- \! the history number of this command
- \# the command number of this command
- \$ a $ or a # if you are root
- \nnn character code nnn in octal
- \\ a backslash
- \[ begin a sequence of non-printing chars
- \] end a sequence of non-printing chars
-*/
-#define PROMPT_GROWTH 48
-char *
-decode_prompt_string (string)
- char *string;
-{
- WORD_LIST *list;
- char *result, *t;
- struct dstack save_dstack;
- int last_exit_value;
-#if defined (PROMPT_STRING_DECODE)
- int result_size, result_index;
- int c, n, i;
- char *temp, octal_string[4];
- struct tm *tm;
- time_t the_time;
- char timebuf[128];
- char *timefmt;
-
- result = (char *)xmalloc (result_size = PROMPT_GROWTH);
- result[result_index = 0] = 0;
- temp = (char *)NULL;
-
- while (c = *string++)
- {
- if (posixly_correct && c == '!')
- {
- if (*string == '!')
- {
- temp = savestring ("!");
- goto add_string;
- }
- else
- {
-#if !defined (HISTORY)
- temp = savestring ("1");
-#else /* HISTORY */
- temp = itos (history_number ());
-#endif /* HISTORY */
- string--; /* add_string increments string again. */
- goto add_string;
- }
- }
- if (c == '\\')
- {
- c = *string;
-
- switch (c)
- {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- strncpy (octal_string, string, 3);
- octal_string[3] = '\0';
-
- n = read_octal (octal_string);
- temp = (char *)xmalloc (3);
-
- if (n == CTLESC || n == CTLNUL)
- {
- temp[0] = CTLESC;
- temp[1] = n;
- temp[2] = '\0';
- }
- else if (n == -1)
- {
- temp[0] = '\\';
- temp[1] = '\0';
- }
- else
- {
- temp[0] = n;
- temp[1] = '\0';
- }
-
- for (c = 0; n != -1 && c < 3 && ISOCTAL (*string); c++)
- string++;
-
- c = 0; /* tested at add_string: */
- goto add_string;
-
- case 'd':
- case 't':
- case 'T':
- case '@':
- case 'A':
- /* Make the current time/date into a string. */
- (void) time (&the_time);
- tm = localtime (&the_time);
-
- if (c == 'd')
- n = strftime (timebuf, sizeof (timebuf), "%a %b %d", tm);
- else if (c == 't')
- n = strftime (timebuf, sizeof (timebuf), "%H:%M:%S", tm);
- else if (c == 'T')
- n = strftime (timebuf, sizeof (timebuf), "%I:%M:%S", tm);
- else if (c == '@')
- n = strftime (timebuf, sizeof (timebuf), "%I:%M %p", tm);
- else if (c == 'A')
- n = strftime (timebuf, sizeof (timebuf), "%H:%M", tm);
-
- if (n == 0)
- timebuf[0] = '\0';
- else
- timebuf[sizeof(timebuf) - 1] = '\0';
-
- temp = savestring (timebuf);
- goto add_string;
-
- case 'D': /* strftime format */
- if (string[1] != '{') /* } */
- goto not_escape;
-
- (void) time (&the_time);
- tm = localtime (&the_time);
- string += 2; /* skip { */
- timefmt = xmalloc (strlen (string) + 3);
- for (t = timefmt; *string && *string != '}'; )
- *t++ = *string++;
- *t = '\0';
- c = *string; /* tested at add_string */
- if (timefmt[0] == '\0')
- {
- timefmt[0] = '%';
- timefmt[1] = 'X'; /* locale-specific current time */
- timefmt[2] = '\0';
- }
- n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
- free (timefmt);
-
- if (n == 0)
- timebuf[0] = '\0';
- else
- timebuf[sizeof(timebuf) - 1] = '\0';
-
- if (promptvars || posixly_correct)
- /* Make sure that expand_prompt_string is called with a
- second argument of Q_DOUBLE_QUOTES if we use this
- function here. */
- temp = sh_backslash_quote_for_double_quotes (timebuf);
- else
- temp = savestring (timebuf);
- goto add_string;
-
- case 'n':
- temp = (char *)xmalloc (3);
- temp[0] = no_line_editing ? '\n' : '\r';
- temp[1] = no_line_editing ? '\0' : '\n';
- temp[2] = '\0';
- goto add_string;
-
- case 's':
- temp = base_pathname (shell_name);
- temp = savestring (temp);
- goto add_string;
-
- case 'v':
- case 'V':
- temp = (char *)xmalloc (16);
- if (c == 'v')
- strcpy (temp, dist_version);
- else
- sprintf (temp, "%s.%d", dist_version, patch_level);
- goto add_string;
-
- case 'w':
- case 'W':
- {
- /* Use the value of PWD because it is much more efficient. */
- char t_string[PATH_MAX];
- int tlen;
-
- temp = get_string_value ("PWD");
-
- if (temp == 0)
- {
- if (getcwd (t_string, sizeof(t_string)) == 0)
- {
- t_string[0] = '.';
- tlen = 1;
- }
- else
- tlen = strlen (t_string);
- }
- else
- {
- tlen = sizeof (t_string) - 1;
- strncpy (t_string, temp, tlen);
- }
- t_string[tlen] = '\0';
-
-#define ROOT_PATH(x) ((x)[0] == '/' && (x)[1] == 0)
-#define DOUBLE_SLASH_ROOT(x) ((x)[0] == '/' && (x)[1] == '/' && (x)[2] == 0)
- /* Abbreviate \W as ~ if $PWD == $HOME */
- if (c == 'W' && (((t = get_string_value ("HOME")) == 0) || STREQ (t, t_string) == 0))
- {
- if (ROOT_PATH (t_string) == 0 && DOUBLE_SLASH_ROOT (t_string) == 0)
- {
- t = strrchr (t_string, '/');
- if (t)
- strcpy (t_string, t + 1);
- }
- }
-#undef ROOT_PATH
-#undef DOUBLE_SLASH_ROOT
- else
- /* polite_directory_format is guaranteed to return a string
- no longer than PATH_MAX - 1 characters. */
- strcpy (t_string, polite_directory_format (t_string));
-
- /* If we're going to be expanding the prompt string later,
- quote the directory name. */
- if (promptvars || posixly_correct)
- /* Make sure that expand_prompt_string is called with a
- second argument of Q_DOUBLE_QUOTES if we use this
- function here. */
- temp = sh_backslash_quote_for_double_quotes (t_string);
- else
- temp = savestring (t_string);
-
- goto add_string;
- }
-
- case 'u':
- if (current_user.user_name == 0)
- get_current_user_info ();
- temp = savestring (current_user.user_name);
- goto add_string;
-
- case 'h':
- case 'H':
- temp = savestring (current_host_name);
- if (c == 'h' && (t = (char *)strchr (temp, '.')))
- *t = '\0';
- goto add_string;
-
- case '#':
- temp = itos (current_command_number);
- goto add_string;
-
- case '!':
-#if !defined (HISTORY)
- temp = savestring ("1");
-#else /* HISTORY */
- temp = itos (history_number ());
-#endif /* HISTORY */
- goto add_string;
-
- case '$':
- t = temp = (char *)xmalloc (3);
- if ((promptvars || posixly_correct) && (current_user.euid != 0))
- *t++ = '\\';
- *t++ = current_user.euid == 0 ? '#' : '$';
- *t = '\0';
- goto add_string;
-
- case 'j':
- temp = itos (count_all_jobs ());
- goto add_string;
-
- case 'l':
-#if defined (HAVE_TTYNAME)
- temp = (char *)ttyname (fileno (stdin));
- t = temp ? base_pathname (temp) : "tty";
- temp = savestring (t);
-#else
- temp = savestring ("tty");
-#endif /* !HAVE_TTYNAME */
- goto add_string;
-
-#if defined (READLINE)
- case '[':
- case ']':
- if (no_line_editing)
- {
- string++;
- break;
- }
- temp = (char *)xmalloc (3);
- n = (c == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE;
- i = 0;
- if (n == CTLESC || n == CTLNUL)
- temp[i++] = CTLESC;
- temp[i++] = n;
- temp[i] = '\0';
- goto add_string;
-#endif /* READLINE */
-
- case '\\':
- case 'a':
- case 'e':
- case 'r':
- temp = (char *)xmalloc (2);
- if (c == 'a')
- temp[0] = '\07';
- else if (c == 'e')
- temp[0] = '\033';
- else if (c == 'r')
- temp[0] = '\r';
- else /* (c == '\\') */
- temp[0] = c;
- temp[1] = '\0';
- goto add_string;
-
- default:
-not_escape:
- temp = (char *)xmalloc (3);
- temp[0] = '\\';
- temp[1] = c;
- temp[2] = '\0';
-
- add_string:
- if (c)
- string++;
- result =
- sub_append_string (temp, result, &result_index, &result_size);
- temp = (char *)NULL; /* Freed in sub_append_string (). */
- result[result_index] = '\0';
- break;
- }
- }
- else
- {
- RESIZE_MALLOCED_BUFFER (result, result_index, 3, result_size, PROMPT_GROWTH);
- result[result_index++] = c;
- result[result_index] = '\0';
- }
- }
-#else /* !PROMPT_STRING_DECODE */
- result = savestring (string);
-#endif /* !PROMPT_STRING_DECODE */
-
- /* Save the delimiter stack and point `dstack' to temp space so any
- command substitutions in the prompt string won't result in screwing
- up the parser's quoting state. */
- save_dstack = dstack;
- dstack = temp_dstack;
- dstack.delimiter_depth = 0;
-
- /* Perform variable and parameter expansion and command substitution on
- the prompt string. */
- if (promptvars || posixly_correct)
- {
- last_exit_value = last_command_exit_value;
- list = expand_prompt_string (result, Q_DOUBLE_QUOTES);
- free (result);
- result = string_list (list);
- dispose_words (list);
- last_command_exit_value = last_exit_value;
- }
- else
- {
- t = dequote_string (result);
- free (result);
- result = t;
- }
-
- dstack = save_dstack;
-
- return (result);
-}
-
-/************************************************
- * *
- * ERROR HANDLING *
- * *
- ************************************************/
-
-/* Report a syntax error, and restart the parser. Call here for fatal
- errors. */
-int
-yyerror (msg)
- const char *msg;
-{
- report_syntax_error ((char *)NULL);
- reset_parser ();
- return (0);
-}
-
-static char *
-error_token_from_token (tok)
- int tok;
-{
- char *t;
-
- if (t = find_token_in_alist (tok, word_token_alist, 0))
- return t;
-
- if (t = find_token_in_alist (tok, other_token_alist, 0))
- return t;
-
- t = (char *)NULL;
- /* This stuff is dicy and needs closer inspection */
- switch (current_token)
- {
- case WORD:
- case ASSIGNMENT_WORD:
- if (yylval.word)
- t = savestring (yylval.word->word);
- break;
- case NUMBER:
- t = itos (yylval.number);
- break;
- case ARITH_CMD:
- if (yylval.word_list)
- t = string_list (yylval.word_list);
- break;
- case ARITH_FOR_EXPRS:
- if (yylval.word_list)
- t = string_list_internal (yylval.word_list, " ; ");
- break;
- case COND_CMD:
- t = (char *)NULL; /* punt */
- break;
- }
-
- return t;
-}
-
-static char *
-error_token_from_text ()
-{
- char *msg, *t;
- int token_end, i;
-
- t = shell_input_line;
- i = shell_input_line_index;
- token_end = 0;
- msg = (char *)NULL;
-
- if (i && t[i] == '\0')
- i--;
-
- while (i && (whitespace (t[i]) || t[i] == '\n'))
- i--;
-
- if (i)
- token_end = i + 1;
-
- while (i && (member (t[i], " \n\t;|&") == 0))
- i--;
-
- while (i != token_end && (whitespace (t[i]) || t[i] == '\n'))
- i++;
-
- /* Return our idea of the offending token. */
- if (token_end || (i == 0 && token_end == 0))
- {
- if (token_end)
- msg = substring (t, i, token_end);
- else /* one-character token */
- {
- msg = (char *)xmalloc (2);
- msg[0] = t[i];
- msg[1] = '\0';
- }
- }
-
- return (msg);
-}
-
-static void
-print_offending_line ()
-{
- char *msg;
- int token_end;
-
- msg = savestring (shell_input_line);
- token_end = strlen (msg);
- while (token_end && msg[token_end - 1] == '\n')
- msg[--token_end] = '\0';
-
- parser_error (line_number, "`%s'", msg);
- free (msg);
-}
-
-/* Report a syntax error with line numbers, etc.
- Call here for recoverable errors. If you have a message to print,
- then place it in MESSAGE, otherwise pass NULL and this will figure
- out an appropriate message for you. */
-static void
-report_syntax_error (message)
- char *message;
-{
- char *msg;
-
- if (message)
- {
- parser_error (line_number, "%s", message);
- if (interactive && EOF_Reached)
- EOF_Reached = 0;
- last_command_exit_value = EX_USAGE;
- return;
- }
-
- /* If the line of input we're reading is not null, try to find the
- objectionable token. First, try to figure out what token the
- parser's complaining about by looking at current_token. */
- if (current_token != 0 && EOF_Reached == 0 && (msg = error_token_from_token (current_token)))
- {
- parser_error (line_number, _("syntax error near unexpected token `%s'"), msg);
- free (msg);
-
- if (interactive == 0)
- print_offending_line ();
-
- last_command_exit_value = EX_USAGE;
- return;
- }
-
- /* If looking at the current token doesn't prove fruitful, try to find the
- offending token by analyzing the text of the input line near the current
- input line index and report what we find. */
- if (shell_input_line && *shell_input_line)
- {
- msg = error_token_from_text ();
- if (msg)
- {
- parser_error (line_number, _("syntax error near `%s'"), msg);
- free (msg);
- }
-
- /* If not interactive, print the line containing the error. */
- if (interactive == 0)
- print_offending_line ();
- }
- else
- {
- msg = EOF_Reached ? _("syntax error: unexpected end of file") : _("syntax error");
- parser_error (line_number, "%s", msg);
- /* When the shell is interactive, this file uses EOF_Reached
- only for error reporting. Other mechanisms are used to
- decide whether or not to exit. */
- if (interactive && EOF_Reached)
- EOF_Reached = 0;
- }
-
- last_command_exit_value = EX_USAGE;
-}
-
-/* ??? Needed function. ??? We have to be able to discard the constructs
- created during parsing. In the case of error, we want to return
- allocated objects to the memory pool. In the case of no error, we want
- to throw away the information about where the allocated objects live.
- (dispose_command () will actually free the command.) */
-static void
-discard_parser_constructs (error_p)
- int error_p;
-{
-}
-
-/************************************************
- * *
- * EOF HANDLING *
- * *
- ************************************************/
-
-/* Do that silly `type "bye" to exit' stuff. You know, "ignoreeof". */
-
-/* A flag denoting whether or not ignoreeof is set. */
-int ignoreeof = 0;
-
-/* The number of times that we have encountered an EOF character without
- another character intervening. When this gets above the limit, the
- shell terminates. */
-int eof_encountered = 0;
-
-/* The limit for eof_encountered. */
-int eof_encountered_limit = 10;
-
-/* If we have EOF as the only input unit, this user wants to leave
- the shell. If the shell is not interactive, then just leave.
- Otherwise, if ignoreeof is set, and we haven't done this the
- required number of times in a row, print a message. */
-static void
-handle_eof_input_unit ()
-{
- if (interactive)
- {
- /* shell.c may use this to decide whether or not to write out the
- history, among other things. We use it only for error reporting
- in this file. */
- if (EOF_Reached)
- EOF_Reached = 0;
-
- /* If the user wants to "ignore" eof, then let her do so, kind of. */
- if (ignoreeof)
- {
- if (eof_encountered < eof_encountered_limit)
- {
- fprintf (stderr, _("Use \"%s\" to leave the shell.\n"),
- login_shell ? "logout" : "exit");
- eof_encountered++;
- /* Reset the parsing state. */
- last_read_token = current_token = '\n';
- /* Reset the prompt string to be $PS1. */
- prompt_string_pointer = (char **)NULL;
- prompt_again ();
- return;
- }
- }
-
- /* In this case EOF should exit the shell. Do it now. */
- reset_parser ();
- exit_builtin ((WORD_LIST *)NULL);
- }
- else
- {
- /* We don't write history files, etc., for non-interactive shells. */
- EOF_Reached = 1;
- }
-}
-
-/************************************************
- * *
- * STRING PARSING FUNCTIONS *
- * *
- ************************************************/
-
-/* It's very important that these two functions treat the characters
- between ( and ) identically. */
-
-static WORD_LIST parse_string_error;
-
-/* Take a string and run it through the shell parser, returning the
- resultant word list. Used by compound array assignment. */
-WORD_LIST *
-parse_string_to_word_list (s, flags, whom)
- char *s;
- int flags;
- const char *whom;
-{
- WORD_LIST *wl;
- int tok, orig_current_token, orig_line_number, orig_input_terminator;
- int orig_line_count;
- int old_echo_input, old_expand_aliases;
-#if defined (HISTORY)
- int old_remember_on_history, old_history_expansion_inhibited;
-#endif
-
-#if defined (HISTORY)
- old_remember_on_history = remember_on_history;
-# if defined (BANG_HISTORY)
- old_history_expansion_inhibited = history_expansion_inhibited;
-# endif
- bash_history_disable ();
-#endif
-
- orig_line_number = line_number;
- orig_line_count = current_command_line_count;
- orig_input_terminator = shell_input_line_terminator;
- old_echo_input = echo_input_at_read;
- old_expand_aliases = expand_aliases;
-
- push_stream (1);
- last_read_token = WORD; /* WORD to allow reserved words here */
- current_command_line_count = 0;
- echo_input_at_read = expand_aliases = 0;
-
- with_input_from_string (s, whom);
- wl = (WORD_LIST *)NULL;
-
- if (flags & 1)
- parser_state |= PST_COMPASSIGN;
-
- while ((tok = read_token (READ)) != yacc_EOF)
- {
- if (tok == '\n' && *bash_input.location.string == '\0')
- break;
- if (tok == '\n') /* Allow newlines in compound assignments */
- continue;
- if (tok != WORD && tok != ASSIGNMENT_WORD)
- {
- line_number = orig_line_number + line_number - 1;
- orig_current_token = current_token;
- current_token = tok;
- yyerror (NULL); /* does the right thing */
- current_token = orig_current_token;
- if (wl)
- dispose_words (wl);
- wl = &parse_string_error;
- break;
- }
- wl = make_word_list (yylval.word, wl);
- }
-
- last_read_token = '\n';
- pop_stream ();
-
-#if defined (HISTORY)
- remember_on_history = old_remember_on_history;
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = old_history_expansion_inhibited;
-# endif /* BANG_HISTORY */
-#endif /* HISTORY */
-
- echo_input_at_read = old_echo_input;
- expand_aliases = old_expand_aliases;
-
- current_command_line_count = orig_line_count;
- shell_input_line_terminator = orig_input_terminator;
-
- if (flags & 1)
- parser_state &= ~PST_COMPASSIGN;
-
- if (wl == &parse_string_error)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- if (interactive_shell == 0 && posixly_correct)
- jump_to_top_level (FORCE_EOF);
- else
- jump_to_top_level (DISCARD);
- }
-
- return (REVERSE_LIST (wl, WORD_LIST *));
-}
-
-static char *
-parse_compound_assignment (retlenp)
- int *retlenp;
-{
- WORD_LIST *wl, *rl;
- int tok, orig_line_number, orig_token_size, orig_last_token, assignok;
- char *saved_token, *ret;
-
- saved_token = token;
- orig_token_size = token_buffer_size;
- orig_line_number = line_number;
- orig_last_token = last_read_token;
-
- last_read_token = WORD; /* WORD to allow reserved words here */
-
- token = (char *)NULL;
- token_buffer_size = 0;
-
- assignok = parser_state&PST_ASSIGNOK; /* XXX */
-
- wl = (WORD_LIST *)NULL; /* ( */
- parser_state |= PST_COMPASSIGN;
-
- while ((tok = read_token (READ)) != ')')
- {
- if (tok == '\n') /* Allow newlines in compound assignments */
- {
- if (SHOULD_PROMPT ())
- prompt_again ();
- continue;
- }
- if (tok != WORD && tok != ASSIGNMENT_WORD)
- {
- current_token = tok; /* for error reporting */
- if (tok == yacc_EOF) /* ( */
- parser_error (orig_line_number, _("unexpected EOF while looking for matching `)'"));
- else
- yyerror(NULL); /* does the right thing */
- if (wl)
- dispose_words (wl);
- wl = &parse_string_error;
- break;
- }
- wl = make_word_list (yylval.word, wl);
- }
-
- FREE (token);
- token = saved_token;
- token_buffer_size = orig_token_size;
-
- parser_state &= ~PST_COMPASSIGN;
-
- if (wl == &parse_string_error)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- last_read_token = '\n'; /* XXX */
- if (interactive_shell == 0 && posixly_correct)
- jump_to_top_level (FORCE_EOF);
- else
- jump_to_top_level (DISCARD);
- }
-
- last_read_token = orig_last_token; /* XXX - was WORD? */
-
- if (wl)
- {
- rl = REVERSE_LIST (wl, WORD_LIST *);
- ret = string_list (rl);
- dispose_words (rl);
- }
- else
- ret = (char *)NULL;
-
- if (retlenp)
- *retlenp = (ret && *ret) ? strlen (ret) : 0;
-
- if (assignok)
- parser_state |= PST_ASSIGNOK;
-
- return ret;
-}
-
-/************************************************
- * *
- * SAVING AND RESTORING PARTIAL PARSE STATE *
- * *
- ************************************************/
-
-sh_parser_state_t *
-save_parser_state (ps)
- sh_parser_state_t *ps;
-{
-#if defined (ARRAY_VARS)
- SHELL_VAR *v;
-#endif
-
- if (ps == 0)
- ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t));
- if (ps == 0)
- return ((sh_parser_state_t *)NULL);
-
- ps->parser_state = parser_state;
- ps->token_state = save_token_state ();
-
- ps->input_line_terminator = shell_input_line_terminator;
- ps->eof_encountered = eof_encountered;
-
- ps->current_command_line_count = current_command_line_count;
-
-#if defined (HISTORY)
- ps->remember_on_history = remember_on_history;
-# if defined (BANG_HISTORY)
- ps->history_expansion_inhibited = history_expansion_inhibited;
-# endif
-#endif
-
- ps->last_command_exit_value = last_command_exit_value;
-#if defined (ARRAY_VARS)
- v = find_variable ("PIPESTATUS");
- if (v && array_p (v) && array_cell (v))
- ps->pipestatus = array_copy (array_cell (v));
- else
- ps->pipestatus = (ARRAY *)NULL;
-#endif
-
- ps->last_shell_builtin = last_shell_builtin;
- ps->this_shell_builtin = this_shell_builtin;
-
- ps->expand_aliases = expand_aliases;
- ps->echo_input_at_read = echo_input_at_read;
-
- return (ps);
-}
-
-void
-restore_parser_state (ps)
- sh_parser_state_t *ps;
-{
-#if defined (ARRAY_VARS)
- SHELL_VAR *v;
-#endif
-
- if (ps == 0)
- return;
-
- parser_state = ps->parser_state;
- if (ps->token_state)
- {
- restore_token_state (ps->token_state);
- free (ps->token_state);
- }
-
- shell_input_line_terminator = ps->input_line_terminator;
- eof_encountered = ps->eof_encountered;
-
- current_command_line_count = ps->current_command_line_count;
-
-#if defined (HISTORY)
- remember_on_history = ps->remember_on_history;
-# if defined (BANG_HISTORY)
- history_expansion_inhibited = ps->history_expansion_inhibited;
-# endif
-#endif
-
- last_command_exit_value = ps->last_command_exit_value;
-#if defined (ARRAY_VARS)
- v = find_variable ("PIPESTATUS");
- if (v && array_p (v) && array_cell (v))
- {
- array_dispose (array_cell (v));
- var_setarray (v, ps->pipestatus);
- }
-#endif
-
- last_shell_builtin = ps->last_shell_builtin;
- this_shell_builtin = ps->this_shell_builtin;
-
- expand_aliases = ps->expand_aliases;
- echo_input_at_read = ps->echo_input_at_read;
-}
-
-/************************************************
- * *
- * MULTIBYTE CHARACTER HANDLING *
- * *
- ************************************************/
-
-#if defined (HANDLE_MULTIBYTE)
-static void
-set_line_mbstate ()
-{
- int i, previ, len, c;
- mbstate_t mbs, prevs;
- size_t mbclen;
-
- if (shell_input_line == NULL)
- return;
- len = strlen (shell_input_line); /* XXX - shell_input_line_len ? */
- FREE (shell_input_line_property);
- shell_input_line_property = (char *)xmalloc (len + 1);
-
- memset (&prevs, '\0', sizeof (mbstate_t));
- for (i = previ = 0; i < len; i++)
- {
- mbs = prevs;
-
- c = shell_input_line[i];
- if (c == EOF)
- {
- int j;
- for (j = i; j < len; j++)
- shell_input_line_property[j] = 1;
- break;
- }
-
- mbclen = mbrlen (shell_input_line + previ, i - previ + 1, &mbs);
- if (mbclen == 1 || mbclen == (size_t)-1)
- {
- mbclen = 1;
- previ = i + 1;
- }
- else if (mbclen == (size_t)-2)
- mbclen = 0;
- else if (mbclen > 1)
- {
- mbclen = 0;
- previ = i + 1;
- prevs = mbs;
- }
- else
- {
- /* XXX - what to do if mbrlen returns 0? (null wide character) */
- int j;
- for (j = i; j < len; j++)
- shell_input_line_property[j] = 1;
- break;
- }
-
- shell_input_line_property[i] = mbclen;
- }
-}
-#endif /* HANDLE_MULTIBYTE */
diff --git a/print_cmd.c~ b/print_cmd.c~
deleted file mode 100644
index 7524f3dd..00000000
--- a/print_cmd.c~
+++ /dev/null
@@ -1,1307 +0,0 @@
-/* print_command -- A way to make readable commands from a command tree. */
-
-/* Copyright (C) 1989-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 <stdio.h>
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#if defined (PREFER_STDARG)
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
-
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include "shell.h"
-#include "flags.h"
-#include <y.tab.h> /* use <...> so we pick it up from the build directory */
-
-#include "shmbutil.h"
-
-#include "builtins/common.h"
-
-#if !HAVE_DECL_PRINTF
-extern int printf __P((const char *, ...)); /* Yuck. Double yuck. */
-#endif
-
-extern int indirection_level;
-
-static int indentation;
-static int indentation_amount = 4;
-
-#if defined (PREFER_STDARG)
-typedef void PFUNC __P((const char *, ...));
-
-static void cprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
-static void xprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
-#else
-#define PFUNC VFunction
-static void cprintf ();
-static void xprintf ();
-#endif
-
-static void reset_locals __P((void));
-static void newline __P((char *));
-static void indent __P((int));
-static void semicolon __P((void));
-static void the_printed_command_resize __P((int));
-
-static void make_command_string_internal __P((COMMAND *));
-static void _print_word_list __P((WORD_LIST *, char *, PFUNC *));
-static void command_print_word_list __P((WORD_LIST *, char *));
-static void print_case_clauses __P((PATTERN_LIST *));
-static void print_redirection_list __P((REDIRECT *));
-static void print_redirection __P((REDIRECT *));
-
-static void print_for_command __P((FOR_COM *));
-#if defined (ARITH_FOR_COMMAND)
-static void print_arith_for_command __P((ARITH_FOR_COM *));
-#endif
-#if defined (SELECT_COMMAND)
-static void print_select_command __P((SELECT_COM *));
-#endif
-static void print_group_command __P((GROUP_COM *));
-static void print_case_command __P((CASE_COM *));
-static void print_while_command __P((WHILE_COM *));
-static void print_until_command __P((WHILE_COM *));
-static void print_until_or_while __P((WHILE_COM *, char *));
-static void print_if_command __P((IF_COM *));
-#if defined (COND_COMMAND)
-static void print_cond_node __P((COND_COM *));
-#endif
-static void print_function_def __P((FUNCTION_DEF *));
-
-#define PRINTED_COMMAND_INITIAL_SIZE 64
-#define PRINTED_COMMAND_GROW_SIZE 128
-
-char *the_printed_command = (char *)NULL;
-int the_printed_command_size = 0;
-int command_string_index = 0;
-
-/* Non-zero means the stuff being printed is inside of a function def. */
-static int inside_function_def;
-static int skip_this_indent;
-static int was_heredoc;
-
-/* The depth of the group commands that we are currently printing. This
- includes the group command that is a function body. */
-static int group_command_nesting;
-
-/* A buffer to indicate the indirection level (PS4) when set -x is enabled. */
-static char indirection_string[100];
-
-/* Print COMMAND (a command tree) on standard output. */
-void
-print_command (command)
- COMMAND *command;
-{
- command_string_index = 0;
- printf ("%s", make_command_string (command));
-}
-
-/* Make a string which is the printed representation of the command
- tree in COMMAND. We return this string. However, the string is
- not consed, so you have to do that yourself if you want it to
- remain around. */
-char *
-make_command_string (command)
- COMMAND *command;
-{
- command_string_index = was_heredoc = 0;
- make_command_string_internal (command);
- return (the_printed_command);
-}
-
-/* The internal function. This is the real workhorse. */
-static void
-make_command_string_internal (command)
- COMMAND *command;
-{
- if (command == 0)
- cprintf ("");
- else
- {
- if (skip_this_indent)
- skip_this_indent--;
- else
- indent (indentation);
-
- if (command->flags & CMD_TIME_PIPELINE)
- {
- cprintf ("time ");
- if (command->flags & CMD_TIME_POSIX)
- cprintf ("-p ");
- }
-
- if (command->flags & CMD_INVERT_RETURN)
- cprintf ("! ");
-
- switch (command->type)
- {
- case cm_for:
- print_for_command (command->value.For);
- break;
-
-#if defined (ARITH_FOR_COMMAND)
- case cm_arith_for:
- print_arith_for_command (command->value.ArithFor);
- break;
-#endif
-
-#if defined (SELECT_COMMAND)
- case cm_select:
- print_select_command (command->value.Select);
- break;
-#endif
-
- case cm_case:
- print_case_command (command->value.Case);
- break;
-
- case cm_while:
- print_while_command (command->value.While);
- break;
-
- case cm_until:
- print_until_command (command->value.While);
- break;
-
- case cm_if:
- print_if_command (command->value.If);
- break;
-
-#if defined (DPAREN_ARITHMETIC)
- case cm_arith:
- print_arith_command (command->value.Arith->exp);
- break;
-#endif
-
-#if defined (COND_COMMAND)
- case cm_cond:
- print_cond_command (command->value.Cond);
- break;
-#endif
-
- case cm_simple:
- print_simple_command (command->value.Simple);
- break;
-
- case cm_connection:
-
- skip_this_indent++;
- make_command_string_internal (command->value.Connection->first);
-
- switch (command->value.Connection->connector)
- {
- case '&':
- case '|':
- {
- char c = command->value.Connection->connector;
- cprintf (" %c", c);
- if (c != '&' || command->value.Connection->second)
- {
- cprintf (" ");
- skip_this_indent++;
- }
- }
- break;
-
- case AND_AND:
- cprintf (" && ");
- if (command->value.Connection->second)
- skip_this_indent++;
- break;
-
- case OR_OR:
- cprintf (" || ");
- if (command->value.Connection->second)
- skip_this_indent++;
- break;
-
- case ';':
- if (was_heredoc == 0)
- cprintf (";");
- else
- was_heredoc = 0;
-
- if (inside_function_def)
- cprintf ("\n");
- else
- {
- cprintf (" ");
- if (command->value.Connection->second)
- skip_this_indent++;
- }
- break;
-
- default:
- cprintf (_("print_command: bad connector `%d'"),
- command->value.Connection->connector);
- break;
- }
-
- make_command_string_internal (command->value.Connection->second);
- break;
-
- case cm_function_def:
- print_function_def (command->value.Function_def);
- break;
-
- case cm_group:
- print_group_command (command->value.Group);
- break;
-
- case cm_subshell:
- cprintf ("( ");
- skip_this_indent++;
- make_command_string_internal (command->value.Subshell->command);
- cprintf (" )");
- break;
-
- default:
- command_error ("print_command", CMDERR_BADTYPE, command->type, 0);
- break;
- }
-
-
- if (command->redirects)
- {
- cprintf (" ");
- print_redirection_list (command->redirects);
- }
- }
-}
-
-static void
-_print_word_list (list, separator, pfunc)
- WORD_LIST *list;
- char *separator;
- PFUNC *pfunc;
-{
- WORD_LIST *w;
-
- for (w = list; w; w = w->next)
- (*pfunc) ("%s%s", w->word->word, w->next ? separator : "");
-}
-
-void
-print_word_list (list, separator)
- WORD_LIST *list;
- char *separator;
-{
- _print_word_list (list, separator, xprintf);
-}
-
-/* Return a string denoting what our indirection level is. */
-
-char *
-indirection_level_string ()
-{
- register int i, j;
- char *ps4;
- char ps4_firstc[MB_LEN_MAX+1];
- int ps4_firstc_len, ps4_len;
-
- indirection_string[0] = '\0';
- ps4 = get_string_value ("PS4");
-
- if (ps4 == 0 || *ps4 == '\0')
- return (indirection_string);
-
- change_flag ('x', FLAG_OFF);
- ps4 = decode_prompt_string (ps4);
- change_flag ('x', FLAG_ON);
-
- if (ps4 == 0 || *ps4 == '\0')
- return (indirection_string);
-
-#if defined (HANDLE_MULTIBYTE)
- ps4_len = strnlen (ps4, MB_CUR_MAX);
- ps4_firstc_len = MBLEN (ps4, ps4_len);
- if (ps4_firstc_len == 1 || ps4_firstc_len == 0 || MB_INVALIDCH (ps4_firstc_len))
- {
- ps4_firstc[0] = ps4[0];
- ps4_firstc[ps4_firstc_len = 1] = '\0';
- }
- else
- memcpy (ps4_firstc, ps4, ps4_firstc_len);
-#else
- ps4_firstc[0] = ps4[0];
- ps4_firstc[ps4_firstc_len = 1] = '\0';
-#endif
-
- for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < 99; i += ps4_firstc_len, j++)
- {
- if (ps4_firstc_len == 1)
- indirection_string[i] = ps4_firstc[0];
- else
- memcpy (indirection_string+i, ps4_firstc, ps4_firstc_len);
- }
-
- for (j = ps4_firstc_len; *ps4 && ps4[j] && i < 99; i++, j++)
- indirection_string[i] = ps4[j];
-
- indirection_string[i] = '\0';
- free (ps4);
- return (indirection_string);
-}
-
-void
-xtrace_print_assignment (name, value, assign_list, xflags)
- char *name, *value;
- int assign_list, xflags;
-{
- char *nval;
-
- if (xflags)
- fprintf (stderr, "%s", indirection_level_string ());
-
- /* VALUE should not be NULL when this is called. */
- if (*value == '\0' || assign_list)
- nval = value;
- else if (sh_contains_shell_metas (value))
- nval = sh_single_quote (value);
- else if (ansic_shouldquote (value))
- nval = ansic_quote (value, 0, (int *)0);
- else
- nval = value;
-
- if (assign_list)
- fprintf (stderr, "%s=(%s)\n", name, nval);
- else
- fprintf (stderr, "%s=%s\n", name, nval);
-
- if (nval != value)
- FREE (nval);
-
- fflush (stderr);
-}
-
-/* A function to print the words of a simple command when set -x is on. */
-void
-xtrace_print_word_list (list, xtflags)
- WORD_LIST *list;
- int xtflags;
-{
- WORD_LIST *w;
- char *t, *x;
-
- if (xtflags)
- fprintf (stderr, "%s", indirection_level_string ());
-
- for (w = list; w; w = w->next)
- {
- t = w->word->word;
- if (t == 0 || *t == '\0')
- fprintf (stderr, "''%s", w->next ? " " : "");
- else if (sh_contains_shell_metas (t))
- {
- x = sh_single_quote (t);
- fprintf (stderr, "%s%s", x, w->next ? " " : "");
- free (x);
- }
- else if (ansic_shouldquote (t))
- {
- x = ansic_quote (t, 0, (int *)0);
- fprintf (stderr, "%s%s", x, w->next ? " " : "");
- free (x);
- }
- else
- fprintf (stderr, "%s%s", t, w->next ? " " : "");
- }
- fprintf (stderr, "\n");
-}
-
-static void
-command_print_word_list (list, separator)
- WORD_LIST *list;
- char *separator;
-{
- _print_word_list (list, separator, cprintf);
-}
-
-void
-print_for_command_head (for_command)
- FOR_COM *for_command;
-{
- cprintf ("for %s in ", for_command->name->word);
- command_print_word_list (for_command->map_list, " ");
-}
-
-void
-xtrace_print_for_command_head (for_command)
- FOR_COM *for_command;
-{
- fprintf (stderr, "%s", indirection_level_string ());
- fprintf (stderr, "for %s in ", for_command->name->word);
- xtrace_print_word_list (for_command->map_list, 0);
-}
-
-static void
-print_for_command (for_command)
- FOR_COM *for_command;
-{
- print_for_command_head (for_command);
-
- cprintf (";");
- newline ("do\n");
- indentation += indentation_amount;
- make_command_string_internal (for_command->action);
- semicolon ();
- indentation -= indentation_amount;
- newline ("done");
-}
-
-#if defined (ARITH_FOR_COMMAND)
-static void
-print_arith_for_command (arith_for_command)
- ARITH_FOR_COM *arith_for_command;
-{
- cprintf ("for ((");
- command_print_word_list (arith_for_command->init, " ");
- cprintf ("; ");
- command_print_word_list (arith_for_command->test, " ");
- cprintf ("; ");
- command_print_word_list (arith_for_command->step, " ");
- cprintf ("))");
- newline ("do\n");
- indentation += indentation_amount;
- make_command_string_internal (arith_for_command->action);
- semicolon ();
- indentation -= indentation_amount;
- newline ("done");
-}
-#endif /* ARITH_FOR_COMMAND */
-
-#if defined (SELECT_COMMAND)
-void
-print_select_command_head (select_command)
- SELECT_COM *select_command;
-{
- cprintf ("select %s in ", select_command->name->word);
- command_print_word_list (select_command->map_list, " ");
-}
-
-void
-xtrace_print_select_command_head (select_command)
- SELECT_COM *select_command;
-{
- fprintf (stderr, "%s", indirection_level_string ());
- fprintf (stderr, "select %s in ", select_command->name->word);
- xtrace_print_word_list (select_command->map_list, 0);
-}
-
-static void
-print_select_command (select_command)
- SELECT_COM *select_command;
-{
- print_select_command_head (select_command);
-
- cprintf (";");
- newline ("do\n");
- indentation += indentation_amount;
- make_command_string_internal (select_command->action);
- semicolon ();
- indentation -= indentation_amount;
- newline ("done");
-}
-#endif /* SELECT_COMMAND */
-
-static void
-print_group_command (group_command)
- GROUP_COM *group_command;
-{
- group_command_nesting++;
- cprintf ("{ ");
-
- if (inside_function_def == 0)
- skip_this_indent++;
- else
- {
- /* This is a group command { ... } inside of a function
- definition, and should be printed as a multiline group
- command, using the current indentation. */
- cprintf ("\n");
- indentation += indentation_amount;
- }
-
- make_command_string_internal (group_command->command);
-
- if (inside_function_def)
- {
- cprintf ("\n");
- indentation -= indentation_amount;
- indent (indentation);
- }
- else
- {
- semicolon ();
- cprintf (" ");
- }
-
- cprintf ("}");
-
- group_command_nesting--;
-}
-
-void
-print_case_command_head (case_command)
- CASE_COM *case_command;
-{
- cprintf ("case %s in ", case_command->word->word);
-}
-
-void
-xtrace_print_case_command_head (case_command)
- CASE_COM *case_command;
-{
- fprintf (stderr, "%s", indirection_level_string ());
- fprintf (stderr, "case %s in\n", case_command->word->word);
-}
-
-static void
-print_case_command (case_command)
- CASE_COM *case_command;
-{
- print_case_command_head (case_command);
-
- if (case_command->clauses)
- print_case_clauses (case_command->clauses);
- newline ("esac");
-}
-
-static void
-print_case_clauses (clauses)
- PATTERN_LIST *clauses;
-{
- indentation += indentation_amount;
- while (clauses)
- {
- newline ("");
- command_print_word_list (clauses->patterns, " | ");
- cprintf (")\n");
- indentation += indentation_amount;
- make_command_string_internal (clauses->action);
- indentation -= indentation_amount;
- newline (";;");
- clauses = clauses->next;
- }
- indentation -= indentation_amount;
-}
-
-static void
-print_while_command (while_command)
- WHILE_COM *while_command;
-{
- print_until_or_while (while_command, "while");
-}
-
-static void
-print_until_command (while_command)
- WHILE_COM *while_command;
-{
- print_until_or_while (while_command, "until");
-}
-
-static void
-print_until_or_while (while_command, which)
- WHILE_COM *while_command;
- char *which;
-{
- cprintf ("%s ", which);
- skip_this_indent++;
- make_command_string_internal (while_command->test);
- semicolon ();
- cprintf (" do\n"); /* was newline ("do\n"); */
- indentation += indentation_amount;
- make_command_string_internal (while_command->action);
- indentation -= indentation_amount;
- semicolon ();
- newline ("done");
-}
-
-static void
-print_if_command (if_command)
- IF_COM *if_command;
-{
- cprintf ("if ");
- skip_this_indent++;
- make_command_string_internal (if_command->test);
- semicolon ();
- cprintf (" then\n");
- indentation += indentation_amount;
- make_command_string_internal (if_command->true_case);
- indentation -= indentation_amount;
-
- if (if_command->false_case)
- {
- semicolon ();
- newline ("else\n");
- indentation += indentation_amount;
- make_command_string_internal (if_command->false_case);
- indentation -= indentation_amount;
- }
- semicolon ();
- newline ("fi");
-}
-
-#if defined (DPAREN_ARITHMETIC)
-void
-print_arith_command (arith_cmd_list)
- WORD_LIST *arith_cmd_list;
-{
- cprintf ("((");
- command_print_word_list (arith_cmd_list, " ");
- cprintf ("))");
-}
-#endif
-
-#if defined (COND_COMMAND)
-static void
-print_cond_node (cond)
- COND_COM *cond;
-{
- if (cond->flags & CMD_INVERT_RETURN)
- cprintf ("! ");
-
- if (cond->type == COND_EXPR)
- {
- cprintf ("( ");
- print_cond_node (cond->left);
- cprintf (" )");
- }
- else if (cond->type == COND_AND)
- {
- print_cond_node (cond->left);
- cprintf (" && ");
- print_cond_node (cond->right);
- }
- else if (cond->type == COND_OR)
- {
- print_cond_node (cond->left);
- cprintf (" || ");
- print_cond_node (cond->right);
- }
- else if (cond->type == COND_UNARY)
- {
- cprintf ("%s", cond->op->word);
- cprintf (" ");
- print_cond_node (cond->left);
- }
- else if (cond->type == COND_BINARY)
- {
- print_cond_node (cond->left);
- cprintf (" ");
- cprintf ("%s", cond->op->word);
- cprintf (" ");
- print_cond_node (cond->right);
- }
- else if (cond->type == COND_TERM)
- {
- cprintf ("%s", cond->op->word); /* need to add quoting here */
- }
-}
-
-void
-print_cond_command (cond)
- COND_COM *cond;
-{
- cprintf ("[[ ");
- print_cond_node (cond);
- cprintf (" ]]");
-}
-
-#ifdef DEBUG
-void
-debug_print_cond_command (cond)
- COND_COM *cond;
-{
- fprintf (stderr, "DEBUG: ");
- command_string_index = 0;
- print_cond_command (cond);
- fprintf (stderr, "%s\n", the_printed_command);
-}
-#endif
-
-void
-xtrace_print_cond_term (type, invert, op, arg1, arg2)
- int type, invert;
- WORD_DESC *op;
- char *arg1, *arg2;
-{
- command_string_index = 0;
- fprintf (stderr, "%s", indirection_level_string ());
- fprintf (stderr, "[[ ");
- if (invert)
- fprintf (stderr, "! ");
-
- if (type == COND_UNARY)
- {
- fprintf (stderr, "%s ", op->word);
- fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
- }
- else if (type == COND_BINARY)
- {
- fprintf (stderr, "%s", (arg1 && *arg1) ? arg1 : "''");
- fprintf (stderr, " %s ", op->word);
- fprintf (stderr, "%s", (arg2 && *arg2) ? arg2 : "''");
- }
-
- fprintf (stderr, " ]]\n");
-}
-#endif /* COND_COMMAND */
-
-#if defined (DPAREN_ARITHMETIC) || defined (ARITH_FOR_COMMAND)
-/* A function to print the words of an arithmetic command when set -x is on. */
-void
-xtrace_print_arith_cmd (list)
- WORD_LIST *list;
-{
- WORD_LIST *w;
-
- fprintf (stderr, "%s", indirection_level_string ());
- fprintf (stderr, "(( ");
- for (w = list; w; w = w->next)
- fprintf (stderr, "%s%s", w->word->word, w->next ? " " : "");
- fprintf (stderr, " ))\n");
-}
-#endif
-
-void
-print_simple_command (simple_command)
- SIMPLE_COM *simple_command;
-{
- command_print_word_list (simple_command->words, " ");
-
- if (simple_command->redirects)
- {
- cprintf (" ");
- print_redirection_list (simple_command->redirects);
- }
-}
-
-static void
-print_redirection_list (redirects)
- REDIRECT *redirects;
-{
- REDIRECT *heredocs, *hdtail, *newredir;
-
- heredocs = (REDIRECT *)NULL;
- hdtail = heredocs;
-
- was_heredoc = 0;
- while (redirects)
- {
- /* Defer printing the here documents until we've printed the
- rest of the redirections. */
- if (redirects->instruction == r_reading_until || redirects->instruction == r_deblank_reading_until)
- {
- newredir = copy_redirect (redirects);
- newredir->next = (REDIRECT *)NULL;
- if (heredocs)
- {
- hdtail->next = newredir;
- hdtail = newredir;
- }
- else
- hdtail = heredocs = newredir;
- }
- else if (redirects->instruction == r_duplicating_output_word && redirects->redirector == 1)
- {
- /* Temporarily translate it as the execution code does. */
- redirects->instruction = r_err_and_out;
- print_redirection (redirects);
- redirects->instruction = r_duplicating_output_word;
- }
- else
- print_redirection (redirects);
-
- redirects = redirects->next;
- if (redirects)
- cprintf (" ");
- }
-
- /* Now that we've printed all the other redirections (on one line),
- print the here documents. */
- if (heredocs)
- {
- cprintf (" ");
- for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
- {
- print_redirection (hdtail);
- cprintf ("\n");
- }
- dispose_redirects (heredocs);
- was_heredoc = 1;
- }
-}
-
-static void
-print_redirection (redirect)
- REDIRECT *redirect;
-{
- int kill_leading, redirector, redir_fd;
- WORD_DESC *redirectee;
-
- kill_leading = 0;
- redirectee = redirect->redirectee.filename;
- redirector = redirect->redirector;
- redir_fd = redirect->redirectee.dest;
-
- switch (redirect->instruction)
- {
- case r_output_direction:
- if (redirector != 1)
- cprintf ("%d", redirector);
- cprintf (">%s", redirectee->word);
- break;
-
- case r_input_direction:
- if (redirector != 0)
- cprintf ("%d", redirector);
- cprintf ("<%s", redirectee->word);
- break;
-
- case r_inputa_direction: /* Redirection created by the shell. */
- cprintf ("&");
- break;
-
- case r_appending_to:
- if (redirector != 1)
- cprintf ("%d", redirector);
- cprintf (">>%s", redirectee->word);
- break;
-
- case r_deblank_reading_until:
- kill_leading++;
- /* ... */
- case r_reading_until:
- if (redirector != 0)
- cprintf ("%d", redirector);
- /* If the here document delimiter is quoted, single-quote it. */
- if (redirect->redirectee.filename->flags & W_QUOTED)
- {
- char *x;
- x = sh_single_quote (redirect->here_doc_eof);
- cprintf ("<<%s%s\n", kill_leading? "-" : "", x);
- free (x);
- }
- else
- cprintf ("<<%s%s\n", kill_leading? "-" : "", redirect->here_doc_eof);
- cprintf ("%s%s",
- redirect->redirectee.filename->word, redirect->here_doc_eof);
- break;
-
- case r_reading_string:
- if (redirector != 0)
- cprintf ("%d", redirector);
- if (ansic_shouldquote (redirect->redirectee.filename->word))
- {
- char *x;
- x = ansic_quote (redirect->redirectee.filename->word, 0, (int *)0);
- cprintf ("<<< %s", x);
- free (x);
- }
- else
- cprintf ("<<< %s", redirect->redirectee.filename->word);
- break;
-
- case r_duplicating_input:
- cprintf ("%d<&%d", redirector, redir_fd);
- break;
-
- case r_duplicating_output:
- cprintf ("%d>&%d", redirector, redir_fd);
- break;
-
- case r_duplicating_input_word:
- cprintf ("%d<&%s", redirector, redirectee->word);
- break;
-
- case r_duplicating_output_word:
- cprintf ("%d>&%s", redirector, redirectee->word);
- break;
-
- case r_move_input:
- cprintf ("%d<&%d-", redirector, redir_fd);
- break;
-
- case r_move_output:
- cprintf ("%d>&%d-", redirector, redir_fd);
- break;
-
- case r_move_input_word:
- cprintf ("%d<&%s-", redirector, redirectee->word);
- break;
-
- case r_move_output_word:
- cprintf ("%d>&%s-", redirector, redirectee->word);
- break;
-
- case r_close_this:
- cprintf ("%d>&-", redirector);
- break;
-
- case r_err_and_out:
- cprintf (">&%s", redirectee->word);
- break;
-
- case r_input_output:
- if (redirector != 1)
- cprintf ("%d", redirector);
- cprintf ("<>%s", redirectee->word);
- break;
-
- case r_output_force:
- if (redirector != 1)
- cprintf ("%d", redirector);
- cprintf (">|%s", redirectee->word);
- break;
- }
-}
-
-static void
-reset_locals ()
-{
- inside_function_def = 0;
- indentation = 0;
-}
-
-static void
-print_function_def (func)
- FUNCTION_DEF *func;
-{
- COMMAND *cmdcopy;
- REDIRECT *func_redirects;
-
- func_redirects = NULL;
- cprintf ("function %s () \n", func->name->word);
- add_unwind_protect (reset_locals, 0);
-
- indent (indentation);
- cprintf ("{ \n");
-
- inside_function_def++;
- indentation += indentation_amount;
-
- cmdcopy = copy_command (func->command);
- if (cmdcopy->type == cm_group)
- {
- func_redirects = cmdcopy->redirects;
- cmdcopy->redirects = (REDIRECT *)NULL;
- }
- make_command_string_internal (cmdcopy->type == cm_group
- ? cmdcopy->value.Group->command
- : cmdcopy);
-
- remove_unwind_protect ();
- indentation -= indentation_amount;
- inside_function_def--;
-
- if (func_redirects)
- { /* { */
- newline ("} ");
- print_redirection_list (func_redirects);
- cmdcopy->redirects = func_redirects;
- }
- else
- newline ("}");
-
- dispose_command (cmdcopy);
-}
-
-/* Return the string representation of the named function.
- NAME is the name of the function.
- COMMAND is the function body. It should be a GROUP_COM.
- MULTI_LINE is non-zero to pretty-print, or zero for all on one line.
- */
-char *
-named_function_string (name, command, multi_line)
- char *name;
- COMMAND *command;
- int multi_line;
-{
- char *result;
- int old_indent, old_amount;
- COMMAND *cmdcopy;
- REDIRECT *func_redirects;
-
- old_indent = indentation;
- old_amount = indentation_amount;
- command_string_index = was_heredoc = 0;
-
- if (name && *name)
- cprintf ("%s ", name);
-
- cprintf ("() ");
-
- if (multi_line == 0)
- {
- indentation = 1;
- indentation_amount = 0;
- }
- else
- {
- cprintf ("\n");
- indentation += indentation_amount;
- }
-
- inside_function_def++;
-
- cprintf (multi_line ? "{ \n" : "{ ");
-
- cmdcopy = copy_command (command);
- /* Take any redirections specified in the function definition (which should
- apply to the function as a whole) and save them for printing later. */
- func_redirects = (REDIRECT *)NULL;
- if (cmdcopy->type == cm_group)
- {
- func_redirects = cmdcopy->redirects;
- cmdcopy->redirects = (REDIRECT *)NULL;
- }
- make_command_string_internal (cmdcopy->type == cm_group
- ? cmdcopy->value.Group->command
- : cmdcopy);
-
- indentation = old_indent;
- indentation_amount = old_amount;
- inside_function_def--;
-
- if (func_redirects)
- { /* { */
- newline ("} ");
- print_redirection_list (func_redirects);
- cmdcopy->redirects = func_redirects;
- }
- else
- newline ("}");
-
- result = the_printed_command;
-
- if (!multi_line)
- {
-#if 0
- register int i;
- for (i = 0; result[i]; i++)
- if (result[i] == '\n')
- {
- strcpy (result + i, result + i + 1);
- --i;
- }
-#else
- if (result[2] == '\n') /* XXX -- experimental */
- strcpy (result + 2, result + 3);
-#endif
- }
-
- dispose_command (cmdcopy);
-
- return (result);
-}
-
-static void
-newline (string)
- char *string;
-{
- cprintf ("\n");
- indent (indentation);
- if (string && *string)
- cprintf ("%s", string);
-}
-
-static char *indentation_string;
-static int indentation_size;
-
-static void
-indent (amount)
- int amount;
-{
- register int i;
-
- RESIZE_MALLOCED_BUFFER (indentation_string, 0, amount, indentation_size, 16);
-
- for (i = 0; amount > 0; amount--)
- indentation_string[i++] = ' ';
- indentation_string[i] = '\0';
- cprintf (indentation_string);
-}
-
-static void
-semicolon ()
-{
- if (command_string_index > 0 &&
- (the_printed_command[command_string_index - 1] == '&' ||
- the_printed_command[command_string_index - 1] == '\n'))
- return;
- cprintf (";");
-}
-
-/* How to make the string. */
-static void
-#if defined (PREFER_STDARG)
-cprintf (const char *control, ...)
-#else
-cprintf (control, va_alist)
- const char *control;
- va_dcl
-#endif
-{
- register const char *s;
- char char_arg[2], *argp, intbuf[INT_STRLEN_BOUND (int) + 1];
- int digit_arg, arg_len, c;
- va_list args;
-
- SH_VA_START (args, control);
-
- arg_len = strlen (control);
- the_printed_command_resize (arg_len + 1);
-
- char_arg[1] = '\0';
- s = control;
- while (s && *s)
- {
- c = *s++;
- argp = (char *)NULL;
- if (c != '%' || !*s)
- {
- char_arg[0] = c;
- argp = char_arg;
- arg_len = 1;
- }
- else
- {
- c = *s++;
- switch (c)
- {
- case '%':
- char_arg[0] = c;
- argp = char_arg;
- arg_len = 1;
- break;
-
- case 's':
- argp = va_arg (args, char *);
- arg_len = strlen (argp);
- break;
-
- case 'd':
- /* Represent an out-of-range file descriptor with an out-of-range
- integer value. We can do this because the only use of `%d' in
- the calls to cprintf is to output a file descriptor number for
- a redirection. */
- digit_arg = va_arg (args, int);
- if (digit_arg < 0)
- {
- sprintf (intbuf, "%u", (unsigned)-1);
- argp = intbuf;
- }
- else
- argp = inttostr (digit_arg, intbuf, sizeof (intbuf));
- arg_len = strlen (argp);
- break;
-
- case 'c':
- char_arg[0] = va_arg (args, int);
- argp = char_arg;
- arg_len = 1;
- break;
-
- default:
- programming_error (_("cprintf: `%c': invalid format character"), c);
- /*NOTREACHED*/
- }
- }
-
- if (argp && arg_len)
- {
- the_printed_command_resize (arg_len + 1);
- FASTCOPY (argp, the_printed_command + command_string_index, arg_len);
- command_string_index += arg_len;
- }
- }
-
- the_printed_command[command_string_index] = '\0';
-}
-
-/* Ensure that there is enough space to stuff LENGTH characters into
- THE_PRINTED_COMMAND. */
-static void
-the_printed_command_resize (length)
- int length;
-{
- if (the_printed_command == 0)
- {
- the_printed_command_size = (length + PRINTED_COMMAND_INITIAL_SIZE - 1) & ~(PRINTED_COMMAND_INITIAL_SIZE - 1);
- the_printed_command = (char *)xmalloc (the_printed_command_size);
- command_string_index = 0;
- }
- else if ((command_string_index + length) >= the_printed_command_size)
- {
- int new;
- new = command_string_index + length + 1;
-
- /* Round up to the next multiple of PRINTED_COMMAND_GROW_SIZE. */
- new = (new + PRINTED_COMMAND_GROW_SIZE - 1) & ~(PRINTED_COMMAND_GROW_SIZE - 1);
- the_printed_command_size = new;
-
- the_printed_command = (char *)xrealloc (the_printed_command, the_printed_command_size);
- }
-}
-
-#if defined (HAVE_VPRINTF)
-/* ``If vprintf is available, you may assume that vfprintf and vsprintf are
- also available.'' */
-
-static void
-#if defined (PREFER_STDARG)
-xprintf (const char *format, ...)
-#else
-xprintf (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
-
- SH_VA_START (args, format);
-
- vfprintf (stdout, format, args);
- va_end (args);
-}
-
-#else
-
-static void
-xprintf (format, arg1, arg2, arg3, arg4, arg5)
- const char *format;
-{
- printf (format, arg1, arg2, arg3, arg4, arg5);
-}
-
-#endif /* !HAVE_VPRINTF */
diff --git a/shell.c~ b/shell.c~
deleted file mode 100644
index 1a4c0017..00000000
--- a/shell.c~
+++ /dev/null
@@ -1,1793 +0,0 @@
-/* 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|W_NOPROCSUB;
- 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/sig.c~ b/sig.c~
deleted file mode 100644
index 953ca43f..00000000
--- a/sig.c~
+++ /dev/null
@@ -1,570 +0,0 @@
-/* sig.c - interface for shell signal handlers and signal initialization. */
-
-/* Copyright (C) 1994-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"
-
-#if defined (HAVE_UNISTD_H)
-# ifdef _MINIX
-# include <sys/types.h>
-# endif
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <signal.h>
-
-#include "bashintl.h"
-
-#include "shell.h"
-#if defined (JOB_CONTROL)
-#include "jobs.h"
-#endif /* JOB_CONTROL */
-#include "siglist.h"
-#include "sig.h"
-#include "trap.h"
-
-#include "builtins/common.h"
-
-#if defined (READLINE)
-# include "bashline.h"
-#endif
-
-#if defined (HISTORY)
-# include "bashhist.h"
-#endif
-
-extern int last_command_exit_value;
-extern int last_command_exit_signal;
-extern int return_catch_flag;
-extern int loop_level, continuing, breaking;
-extern int parse_and_execute_level, shell_initialized;
-
-/* Non-zero after SIGINT. */
-int interrupt_state;
-
-/* Non-zero after SIGWINCH */
-volatile int sigwinch_received = 0;
-
-/* The environment at the top-level R-E loop. We use this in
- the case of error return. */
-procenv_t top_level;
-
-#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
-/* The signal masks that this shell runs with. */
-sigset_t top_level_mask;
-#endif /* JOB_CONTROL */
-
-/* When non-zero, we throw_to_top_level (). */
-int interrupt_immediately = 0;
-
-#if defined (SIGWINCH)
-static SigHandler *old_winch = (SigHandler *)SIG_DFL;
-#endif
-
-static void initialize_shell_signals __P((void));
-
-void
-initialize_signals (reinit)
- int reinit;
-{
- initialize_shell_signals ();
- initialize_job_signals ();
-#if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
- if (reinit == 0)
- initialize_siglist ();
-#endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
-}
-
-/* A structure describing a signal that terminates the shell if not
- caught. The orig_handler member is present so children can reset
- these signals back to their original handlers. */
-struct termsig {
- int signum;
- SigHandler *orig_handler;
- int orig_flags;
-};
-
-#define NULL_HANDLER (SigHandler *)SIG_DFL
-
-/* The list of signals that would terminate the shell if not caught.
- We catch them, but just so that we can write the history file,
- and so forth. */
-static struct termsig terminating_signals[] = {
-#ifdef SIGHUP
-{ SIGHUP, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGINT
-{ SIGINT, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGILL
-{ SIGILL, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGTRAP
-{ SIGTRAP, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGIOT
-{ SIGIOT, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGDANGER
-{ SIGDANGER, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGEMT
-{ SIGEMT, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGFPE
-{ SIGFPE, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGBUS
-{ SIGBUS, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGSEGV
-{ SIGSEGV, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGSYS
-{ SIGSYS, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGPIPE
-{ SIGPIPE, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGALRM
-{ SIGALRM, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGTERM
-{ SIGTERM, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGXCPU
-{ SIGXCPU, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGXFSZ
-{ SIGXFSZ, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGVTALRM
-{ SIGVTALRM, NULL_HANDLER, 0 },
-#endif
-
-#if 0
-#ifdef SIGPROF
-{ SIGPROF, NULL_HANDLER, 0 },
-#endif
-#endif
-
-#ifdef SIGLOST
-{ SIGLOST, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGUSR1
-{ SIGUSR1, NULL_HANDLER, 0 },
-#endif
-
-#ifdef SIGUSR2
-{ SIGUSR2, NULL_HANDLER, 0 },
-#endif
-};
-
-#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
-
-#define XSIG(x) (terminating_signals[x].signum)
-#define XHANDLER(x) (terminating_signals[x].orig_handler)
-#define XSAFLAGS(x) (terminating_signals[x].orig_flags)
-
-static int termsigs_initialized = 0;
-
-/* Initialize signals that will terminate the shell to do some
- unwind protection. For non-interactive shells, we only call
- this when a trap is defined for EXIT (0). */
-void
-initialize_terminating_signals ()
-{
- register int i;
-#if defined (HAVE_POSIX_SIGNALS)
- struct sigaction act, oact;
-#endif
-
- if (termsigs_initialized)
- return;
-
- /* The following code is to avoid an expensive call to
- set_signal_handler () for each terminating_signals. Fortunately,
- this is possible in Posix. Unfortunately, we have to call signal ()
- on non-Posix systems for each signal in terminating_signals. */
-#if defined (HAVE_POSIX_SIGNALS)
- act.sa_handler = termination_unwind_protect;
- act.sa_flags = 0;
- sigemptyset (&act.sa_mask);
- sigemptyset (&oact.sa_mask);
- for (i = 0; i < TERMSIGS_LENGTH; i++)
- sigaddset (&act.sa_mask, XSIG (i));
- for (i = 0; i < TERMSIGS_LENGTH; i++)
- {
- /* If we've already trapped it, don't do anything. */
- if (signal_is_trapped (XSIG (i)))
- continue;
-
- sigaction (XSIG (i), &act, &oact);
- XHANDLER(i) = oact.sa_handler;
- XSAFLAGS(i) = oact.sa_flags;
- /* Don't do anything with signals that are ignored at shell entry
- if the shell is not interactive. */
- if (!interactive_shell && XHANDLER (i) == SIG_IGN)
- {
- sigaction (XSIG (i), &oact, &act);
- set_signal_ignored (XSIG (i));
- }
-#if defined (SIGPROF) && !defined (_MINIX)
- if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
- sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
-#endif /* SIGPROF && !_MINIX */
- }
-
-#else /* !HAVE_POSIX_SIGNALS */
-
- for (i = 0; i < TERMSIGS_LENGTH; i++)
- {
- /* If we've already trapped it, don't do anything. */
- if (signal_is_trapped (XSIG (i)))
- continue;
-
- XHANDLER(i) = signal (XSIG (i), termination_unwind_protect);
- XSAFLAGS(i) = 0;
- /* Don't do anything with signals that are ignored at shell entry
- if the shell is not interactive. */
- if (!interactive_shell && XHANDLER (i) == SIG_IGN)
- {
- signal (XSIG (i), SIG_IGN);
- set_signal_ignored (XSIG (i));
- }
-#ifdef SIGPROF
- if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
- signal (XSIG (i), XHANDLER (i));
-#endif
- }
-
-#endif /* !HAVE_POSIX_SIGNALS */
-
- termsigs_initialized = 1;
-}
-
-static void
-initialize_shell_signals ()
-{
- if (interactive)
- initialize_terminating_signals ();
-
-#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
- /* All shells use the signal mask they inherit, and pass it along
- to child processes. Children will never block SIGCHLD, though. */
- sigemptyset (&top_level_mask);
- sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
-# if defined (SIGCHLD)
- sigdelset (&top_level_mask, SIGCHLD);
-# endif
-#endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
-
- /* And, some signals that are specifically ignored by the shell. */
- set_signal_handler (SIGQUIT, SIG_IGN);
-
- if (interactive)
- {
- set_signal_handler (SIGINT, sigint_sighandler);
- set_signal_handler (SIGTERM, SIG_IGN);
- set_sigwinch_handler ();
- }
-}
-
-void
-reset_terminating_signals ()
-{
- register int i;
-#if defined (HAVE_POSIX_SIGNALS)
- struct sigaction act;
-#endif
-
- if (termsigs_initialized == 0)
- return;
-
-#if defined (HAVE_POSIX_SIGNALS)
- act.sa_flags = 0;
- sigemptyset (&act.sa_mask);
- for (i = 0; i < TERMSIGS_LENGTH; i++)
- {
- /* Skip a signal if it's trapped or handled specially, because the
- trap code will restore the correct value. */
- if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
- continue;
-
- act.sa_handler = XHANDLER (i);
- act.sa_flags = XSAFLAGS (i);
- sigaction (XSIG (i), &act, (struct sigaction *) NULL);
- }
-#else /* !HAVE_POSIX_SIGNALS */
- for (i = 0; i < TERMSIGS_LENGTH; i++)
- {
- if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
- continue;
-
- signal (XSIG (i), XHANDLER (i));
- }
-#endif /* !HAVE_POSIX_SIGNALS */
-}
-#undef XSIG
-#undef XHANDLER
-
-/* What to do when we've been interrupted, and it is safe to handle it. */
-void
-throw_to_top_level ()
-{
- int print_newline = 0;
-
- if (interrupt_state)
- {
- print_newline = 1;
- DELINTERRUPT;
- }
-
- if (interrupt_state)
- return;
-
- last_command_exit_signal = (last_command_exit_value > 128) ?
- (last_command_exit_value - 128) : 0;
- last_command_exit_value |= 128;
-
- /* Run any traps set on SIGINT. */
- run_interrupt_trap ();
-
- /* Cleanup string parser environment. */
- while (parse_and_execute_level)
- parse_and_execute_cleanup ();
-
-#if defined (JOB_CONTROL)
- give_terminal_to (shell_pgrp, 0);
-#endif /* JOB_CONTROL */
-
-#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
- /* This should not be necessary on systems using sigsetjmp/siglongjmp. */
- sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
-#endif
-
- reset_parser ();
-
-#if defined (READLINE)
- if (interactive)
- bashline_reinitialize ();
-#endif /* READLINE */
-
-#if defined (PROCESS_SUBSTITUTION)
- unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-
- run_unwind_protects ();
- loop_level = continuing = breaking = 0;
- return_catch_flag = 0;
-
- if (interactive && print_newline)
- {
- fflush (stdout);
- fprintf (stderr, "\n");
- fflush (stderr);
- }
-
- /* An interrupted `wait' command in a script does not exit the script. */
- if (interactive || (interactive_shell && !shell_initialized) ||
- (print_newline && signal_is_trapped (SIGINT)))
- jump_to_top_level (DISCARD);
- else
- jump_to_top_level (EXITPROG);
-}
-
-/* This is just here to isolate the longjmp calls. */
-void
-jump_to_top_level (value)
- int value;
-{
- longjmp (top_level, value);
-}
-
-sighandler
-termination_unwind_protect (sig)
- int sig;
-{
- /* I don't believe this condition ever tests true. */
- if (sig == SIGINT && signal_is_trapped (SIGINT))
- run_interrupt_trap ();
-
-#if defined (HISTORY)
- /* This might be unsafe, since it eventually calls functions POSIX says
- not to call from signal handlers. If it's a problem, take this code
- out. */
- if (interactive_shell && sig != SIGABRT)
- maybe_save_shell_history ();
-#endif /* HISTORY */
-
-#if defined (JOB_CONTROL)
- if (interactive && sig == SIGHUP)
- hangup_all_jobs ();
- end_job_control ();
-#endif /* JOB_CONTROL */
-
-#if defined (PROCESS_SUBSTITUTION)
- unlink_fifo_list ();
-#endif /* PROCESS_SUBSTITUTION */
-
- run_exit_trap ();
- set_signal_handler (sig, SIG_DFL);
- kill (getpid (), sig);
-
- SIGRETURN (0);
-}
-
-/* What we really do when SIGINT occurs. */
-sighandler
-sigint_sighandler (sig)
- int sig;
-{
-#if defined (MUST_REINSTALL_SIGHANDLERS)
- signal (sig, sigint_sighandler);
-#endif
-
- /* interrupt_state needs to be set for the stack of interrupts to work
- right. Should it be set unconditionally? */
- if (interrupt_state == 0)
- ADDINTERRUPT;
-
- if (interrupt_immediately)
- {
- interrupt_immediately = 0;
- throw_to_top_level ();
- }
-
- SIGRETURN (0);
-}
-
-#if defined (SIGWINCH)
-sighandler
-sigwinch_sighandler (sig)
- int sig;
-{
-#if defined (MUST_REINSTALL_SIGHANDLERS)
- set_signal_handler (SIGWINCH, sigwinch_sighandler);
-#endif /* MUST_REINSTALL_SIGHANDLERS */
- sigwinch_received = 1;
- SIGRETURN (0);
-}
-#endif /* SIGWINCH */
-
-void
-set_sigwinch_handler ()
-{
-#if defined (SIGWINCH)
- old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
-#endif
-}
-
-void
-unset_sigwinch_handler ()
-{
-#if defined (SIGWINCH)
- set_signal_handler (SIGWINCH, old_winch);
-#endif
-}
-
-/* Signal functions used by the rest of the code. */
-#if !defined (HAVE_POSIX_SIGNALS)
-
-#if defined (JOB_CONTROL)
-/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
-sigprocmask (operation, newset, oldset)
- int operation, *newset, *oldset;
-{
- int old, new;
-
- if (newset)
- new = *newset;
- else
- new = 0;
-
- switch (operation)
- {
- case SIG_BLOCK:
- old = sigblock (new);
- break;
-
- case SIG_SETMASK:
- sigsetmask (new);
- break;
-
- default:
- internal_error (_("sigprocmask: %d: invalid operation"), operation);
- }
-
- if (oldset)
- *oldset = old;
-}
-#endif /* JOB_CONTROL */
-
-#else
-
-#if !defined (SA_INTERRUPT)
-# define SA_INTERRUPT 0
-#endif
-
-#if !defined (SA_RESTART)
-# define SA_RESTART 0
-#endif
-
-SigHandler *
-set_signal_handler (sig, handler)
- int sig;
- SigHandler *handler;
-{
- struct sigaction act, oact;
-
-itrace("set_signal_handler: sig = %d", sig);
- act.sa_handler = handler;
- act.sa_flags = 0;
-#if 0
- if (sig == SIGALRM)
- act.sa_flags |= SA_INTERRUPT; /* XXX */
- else
- act.sa_flags |= SA_RESTART; /* XXX */
-#endif
- sigemptyset (&act.sa_mask);
- sigemptyset (&oact.sa_mask);
- sigaction (sig, &act, &oact);
- return (oact.sa_handler);
-}
-#endif /* HAVE_POSIX_SIGNALS */
diff --git a/subst.c.new b/subst.c.new
deleted file mode 100644
index c0af3775..00000000
--- a/subst.c.new
+++ /dev/null
@@ -1,8103 +0,0 @@
-/* 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 */
-#define EX_BACKQ 0x08 /* experimental */
-
-/* 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, si;
- 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 ((flags & EX_BACKQ) && (c == '\'' || c == '"'))
- {
- si = i + 1;
- i = (c == '\'') ? skip_single_quoted (string, slen, si)
- : skip_double_quoted (string, slen, si);
- continue;
- }
- 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 = (wchar_t *)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;
- /* ${#var} doesn't have any of the other parameter expansions on it. */
- if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
- name = string_extract (string, &t_index, "}", EX_VARNAME);
- else
- 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|EX_BACKQ);
- /* 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.save1 b/subst.c.save1
deleted file mode 100644
index 83c9e213..00000000
--- a/subst.c.save1
+++ /dev/null
@@ -1,8064 +0,0 @@
-/* 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~
deleted file mode 100644
index 4a7d266e..00000000
--- a/subst.c~
+++ /dev/null
@@ -1,8138 +0,0 @@
-/* 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-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 "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 */
-#define EX_COMMAND 0x08 /* extracting a shell script/command */
-
-/* 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;
-
-#if !defined (HAVE_WCSDUP) && defined (HANDLE_MULTIBYTE)
-extern wchar_t *wcsdup __P((const wchar_t *));
-#endif
-
-/* 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((const 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)
-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 int chk_arithsub __P((const char *, 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, "$(", "(", ")", EX_COMMAND); /*)*/
- 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|EX_COMMAND); /* ) */
- 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)
- const 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 = (wchar_t *)xmalloc (sizeof (wchar_t) * (len + 1));
- mbstowcs (wcharlist, charlist, len + 1);
- }
-
- 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, "$(", "(", ")", EX_COMMAND)); /*)*/
-}
-
-/* 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, in_comment;
- 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 = in_comment = 0;
-
- nesting_level = 1;
- i = *sindex;
-
- while (nesting_level)
- {
- c = string[i];
-
- if (c == 0)
- break;
-
- if (in_comment)
- {
- if (c == '\n')
- in_comment = 0;
- ADVANCE_CHAR (string, slen, i);
- continue;
- }
-
- if (pass_character) /* previous char was backslash */
- {
- pass_character = 0;
- ADVANCE_CHAR (string, slen, i);
- continue;
- }
-
- /* Not exactly right yet; should handle shell metacharacters and
- multibyte characters, too. */
- if ((flags & EX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || whitespace (string[i - 1])))
- {
- in_comment = 1;
- 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|EX_COMMAND); /*)*/
- 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|EX_COMMAND); /* ) */
- 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_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 (string[sindex] && spctabnl (string[sindex]) && isifs (string[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 mklocal;
- WORD_LIST *list;
-
- mklocal = flags & ASS_MKLOCAL;
-
- if (mklocal && variable_context)
- {
- list = expand_compound_array_assignment (value, flags);
- v = find_variable (name);
- if (v == 0 || array_p (v) == 0 || v->context != variable_context)
- v = make_local_array_variable (name);
- assign_compound_array_list (v, list, 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;
- 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 (expand && (word->flags & W_COMPASSIGN))
- {
- 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, quoted)
- char *string;
-{
- return (expand_string_if_necessary (string, quoted, 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)
-static wchar_t *
-remove_wpattern (wparam, wstrlen, wpattern, op)
- wchar_t *wparam;
- size_t wstrlen;
- wchar_t *wpattern;
- int op;
-{
- wchar_t wc, *ret;
- int n;
-
- 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;
-#if 0
- int i;
-#endif
-
- /* 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;
-
- temp1 = expand_arith_string (substr, Q_DOUBLE_QUOTES);
- *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);
- temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
- 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, *oname;
- SHELL_VAR *v;
-
- if (value == 0)
- return ((char *)NULL);
-
- oname = this_command_name;
- this_command_name = varname;
-
- vtype = get_var_and_type (varname, value, quoted, &v, &val);
- if (vtype == -1)
- {
- this_command_name = oname;
- return ((char *)NULL);
- }
-
- starsub = vtype & VT_STARSUB;
- vtype &= ~VT_STARSUB;
-
- r = verify_substring_values (val, substr, vtype, &e1, &e2);
- this_command_name = oname;
- 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;
-
- 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;
-}
-
-/* Check for unbalanced parens in S, which is the contents of $(( ... )). If
- any occur, this must be a nested command substitution, so return 0.
- Otherwise, return 1. A valid arithmetic expression must always have a
- ( before a matching ), so any cases where there are more right parens
- means that this must not be an arithmetic expression, though the parser
- will not accept it without a balanced total number of parens. */
-static int
-chk_arithsub (s, len)
- const char *s;
- int len;
-{
- int i, count;
- DECLARE_MBSTATE;
-
- i = count = 0;
- while (i < len)
- {
- if (s[i] == '(')
- count++;
- else if (s[i] == ')')
- {
- count--;
- if (count < 0)
- return 0;
- }
-
- switch (s[i])
- {
- default:
- ADVANCE_CHAR (s, len, i);
- break;
-
- case '\\':
- i++;
- if (s[i])
- ADVANCE_CHAR (s, len, i);
- break;
-
- case '\'':
- i = skip_single_quoted (s, len, ++i);
- break;
-
- case '"':
- i = skip_double_quoted ((char *)s, len, ++i);
- break;
- }
- }
-
- return (count == 0);
-}
-
-/****************************************************************/
-/* */
-/* 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;
- /* ${#var} doesn't have any of the other parameter expansions on it. */
- if (string[t_index] == '#' && legal_variable_starter (string[t_index+1])) /* {{ */
- name = string_extract (string, &t_index, "}", EX_VARNAME);
- else
- 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);
-
- 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. */
- if (tdesc && tdesc->word && (tdesc->flags & W_HASQUOTEDNULL) && QUOTED_NULL (temp))
- {
- 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';
-
- if (chk_arithsub (temp2, t_index) == 0)
- {
- free (temp2);
- goto comsub;
- }
-
- /* Expand variables found inside the expression. */
- temp1 = expand_arith_string (temp2, Q_DOUBLE_QUOTES);
- 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. */
- temp1 = expand_arith_string (temp, Q_DOUBLE_QUOTES);
-
- 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~
deleted file mode 100644
index 33d3f49e..00000000
--- a/subst.h~
+++ /dev/null
@@ -1,260 +0,0 @@
-/* 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~
deleted file mode 100644
index b49bd45d..00000000
--- a/support/Makefile.in~
+++ /dev/null
@@ -1,87 +0,0 @@
-#
-# 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.save b/support/mksignames.c.save
deleted file mode 100644
index 8b96a5a1..00000000
--- a/support/mksignames.c.save
+++ /dev/null
@@ -1,446 +0,0 @@
-/* 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~
deleted file mode 100644
index fc08ff55..00000000
--- a/support/mksignames.c~
+++ /dev/null
@@ -1,110 +0,0 @@
-/* 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~
deleted file mode 100644
index 7a0d8665..00000000
--- a/support/signames.c~
+++ /dev/null
@@ -1,393 +0,0 @@
-/* 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/syntax.h~ b/syntax.h~
deleted file mode 100644
index 8bf15485..00000000
--- a/syntax.h~
+++ /dev/null
@@ -1,102 +0,0 @@
-/* syntax.h -- Syntax definitions for the shell */
-
-/* Copyright (C) 2000 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. */
-
-#ifndef _SYNTAX_H_
-#define _SYNTAX_H_
-
-/* Defines for use by mksyntax.c */
-
-#define slashify_in_quotes "\\`$\"\n"
-#define slashify_in_here_document "\\`$"
-
-#define shell_meta_chars "()<>;&|"
-#define shell_break_chars "()<>;&| \t\n"
-
-#define shell_quote_chars "\"`'"
-
-#if defined (PROCESS_SUBSTITUTION)
-# define shell_exp_chars "$<>"
-#else
-# define shell_exp_chars "$"
-#endif
-
-#if defined (EXTENDED_GLOB)
-# define ext_glob_chars "@*+?!"
-#else
-# define ext_glob_chars ""
-#endif
-#define shell_glob_chars "*?[]^"
-
-/* Defines shared by mksyntax.c and the rest of the shell code. */
-
-/* Values for character flags in syntax tables */
-
-#define CWORD 0x0000 /* nothing special; an ordinary character */
-#define CSHMETA 0x0001 /* shell meta character */
-#define CSHBRK 0x0002 /* shell break character */
-#define CBACKQ 0x0004 /* back quote */
-#define CQUOTE 0x0008 /* shell quote character */
-#define CSPECL 0x0010 /* special character that needs quoting */
-#define CEXP 0x0020 /* shell expansion character */
-#define CBSDQUOTE 0x0040 /* characters escaped by backslash in double quotes */
-#define CBSHDOC 0x0080 /* characters escaped by backslash in here doc */
-#define CGLOB 0x0100 /* globbing characters */
-#define CXGLOB 0x0200 /* extended globbing characters */
-#define CXQUOTE 0x0400 /* cquote + backslash */
-#define CSPECVAR 0x0800 /* single-character shell variable name */
-#define CSUBSTOP 0x1000 /* values of OP for ${word[:]OPstuff} */
-
-/* Defines for use by the rest of the shell. */
-extern int sh_syntaxtab[];
-extern int sh_syntabsiz;
-
-#define shellmeta(c) (sh_syntaxtab[(unsigned char)(c)] & CSHMETA)
-#define shellbreak(c) (sh_syntaxtab[(unsigned char)(c)] & CSHBRK)
-#define shellquote(c) (sh_syntaxtab[(unsigned char)(c)] & CQUOTE)
-
-#define shellxquote(c) (sh_syntaxtab[(unsigned char)(c)] & CXQUOTE)
-
-#define issyntype(c, t) ((sh_syntaxtab[(unsigned char)(c)] & (t)) != 0)
-#define notsyntype(c,t) ((sh_syntaxtab[(unsigned char)(c)] & (t)) == 0)
-
-#if defined (PROCESS_SUBSTITUTION)
-# define shellexp(c) ((c) == '$' || (c) == '<' || (c) == '>')
-#else
-# define shellexp(c) ((c) == '$')
-#endif
-
-#if defined (EXTENDED_GLOB)
-# define PATTERN_CHAR(c) \
- ((c) == '@' || (c) == '*' || (c) == '+' || (c) == '?' || (c) == '!')
-#else
-# define PATTERN_CHAR(c) 0
-#endif
-
-#define GLOB_CHAR(c) \
- ((c) == '*' || (c) == '?' || (c) == '[' || (c) == ']' || (c) == '^')
-
-#define CTLESC '\001'
-#define CTLNUL '\177'
-
-#if !defined (HAVE_ISBLANK) && !defined (isblank)
-# define isblank(x) ((x) == ' ' || (x) == '\t')
-#endif
-
-#endif /* _SYNTAX_H_ */
diff --git a/terminal.c.diff b/terminal.c.diff
deleted file mode 100644
index e3fa8991..00000000
--- a/terminal.c.diff
+++ /dev/null
@@ -1,41 +0,0 @@
-*** ../bash-3.1/lib/readline/terminal.c Sat Nov 12 20:46:54 2005
---- lib/readline/terminal.c Tue Jan 31 10:57:54 2006
-***************
-*** 70,74 ****
- #define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
-
-! int rl_prefer_env_winsize;
-
- /* **************************************************************** */
---- 70,77 ----
- #define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
-
-! /* If the calling application sets this to a non-zero value, readline will
-! use the $LINES and $COLUMNS environment variables to set its idea of the
-! window size before interrogating the kernel. */
-! int rl_prefer_env_winsize = 0;
-
- /* **************************************************************** */
-***************
-*** 123,127 ****
-
- /* Non-zero means the terminal can auto-wrap lines. */
-! int _rl_term_autowrap;
-
- /* Non-zero means that this terminal has a meta key. */
---- 126,130 ----
-
- /* Non-zero means the terminal can auto-wrap lines. */
-! int _rl_term_autowrap = -1;
-
- /* Non-zero means that this terminal has a meta key. */
-***************
-*** 275,278 ****
---- 278,284 ----
- int rows, cols;
- {
-+ if (_rl_term_autowrap == -1)
-+ _rl_init_terminal_io (rl_terminal_name);
-+
- if (rows > 0)
- _rl_screenheight = rows;
diff --git a/test.c.orig b/test.c.orig
deleted file mode 100644
index 4fc0ade0..00000000
--- a/test.c.orig
+++ /dev/null
@@ -1,924 +0,0 @@
-/* GNU test program (ksb and mjb) */
-
-/* Modified to run with the GNU shell Apr 25, 1988 by bfox. */
-
-/* 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. */
-
-/* Define PATTERN_MATCHING to get the csh-like =~ and !~ pattern-matching
- binary operators. */
-/* #define PATTERN_MATCHING */
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include "bashtypes.h"
-
-#if !defined (HAVE_LIMITS_H)
-# include <sys/param.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#if !defined (_POSIX_VERSION) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif /* !_POSIX_VERSION */
-#include "posixstat.h"
-#include "filecntl.h"
-
-#include "bashintl.h"
-
-#include "shell.h"
-#include "pathexp.h"
-#include "test.h"
-#include "builtins/common.h"
-
-#include <glob/strmatch.h>
-
-#if !defined (STRLEN)
-# define STRLEN(s) ((s)[0] ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
-#endif
-
-#if !defined (STREQ)
-# define STREQ(a, b) ((a)[0] == (b)[0] && strcmp (a, b) == 0)
-#endif /* !STREQ */
-
-#if !defined (R_OK)
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#define F_OK 0
-#endif /* R_OK */
-
-#define EQ 0
-#define NE 1
-#define LT 2
-#define GT 3
-#define LE 4
-#define GE 5
-
-#define NT 0
-#define OT 1
-#define EF 2
-
-/* The following few defines control the truth and false output of each stage.
- TRUE and FALSE are what we use to compute the final output value.
- SHELL_BOOLEAN is the form which returns truth or falseness in shell terms.
- Default is TRUE = 1, FALSE = 0, SHELL_BOOLEAN = (!value). */
-#define TRUE 1
-#define FALSE 0
-#define SHELL_BOOLEAN(value) (!(value))
-
-#define TEST_ERREXIT_STATUS 2
-
-static procenv_t test_exit_buf;
-static int test_error_return;
-#define test_exit(val) \
- do { test_error_return = val; longjmp (test_exit_buf, 1); } while (0)
-
-/* We have to use access(2) for machines running AFS, because it's
- not a Unix file system. This may produce incorrect answers for
- non-AFS files. I hate AFS. */
-#if defined (AFS)
-# define EACCESS(path, mode) access(path, mode)
-#else
-# define EACCESS(path, mode) test_eaccess(path, mode)
-#endif /* AFS */
-
-static int pos; /* The offset of the current argument in ARGV. */
-static int argc; /* The number of arguments present in ARGV. */
-static char **argv; /* The argument list. */
-static int noeval;
-
-static void test_syntax_error __P((char *, char *)) __attribute__((__noreturn__));
-static void beyond __P((void)) __attribute__((__noreturn__));
-static void integer_expected_error __P((char *)) __attribute__((__noreturn__));
-
-static int test_stat __P((char *, struct stat *));
-
-static int unary_operator __P((void));
-static int binary_operator __P((void));
-static int two_arguments __P((void));
-static int three_arguments __P((void));
-static int posixtest __P((void));
-
-static int expr __P((void));
-static int term __P((void));
-static int and __P((void));
-static int or __P((void));
-
-static int filecomp __P((char *, char *, int));
-static int arithcomp __P((char *, char *, int, int));
-static int patcomp __P((char *, char *, int));
-
-static void
-test_syntax_error (format, arg)
- char *format, *arg;
-{
- builtin_error (format, arg);
- test_exit (TEST_ERREXIT_STATUS);
-}
-
-/*
- * beyond - call when we're beyond the end of the argument list (an
- * error condition)
- */
-static void
-beyond ()
-{
- test_syntax_error (_("argument expected"), (char *)NULL);
-}
-
-/* Syntax error for when an integer argument was expected, but
- something else was found. */
-static void
-integer_expected_error (pch)
- char *pch;
-{
- test_syntax_error (_("%s: integer expression expected"), pch);
-}
-
-/* A wrapper for stat () which disallows pathnames that are empty strings
- and handles /dev/fd emulation on systems that don't have it. */
-static int
-test_stat (path, finfo)
- char *path;
- struct stat *finfo;
-{
- if (*path == '\0')
- {
- errno = ENOENT;
- return (-1);
- }
- if (path[0] == '/' && path[1] == 'd' && strncmp (path, "/dev/fd/", 8) == 0)
- {
-#if !defined (HAVE_DEV_FD)
- intmax_t fd;
- int r;
-
- if (legal_number (path + 8, &fd) && fd == (int)fd)
- {
- r = fstat ((int)fd, finfo);
- if (r == 0 || errno != EBADF)
- return (r);
- }
- errno = ENOENT;
- return (-1);
-#else
- /* If HAVE_DEV_FD is defined, DEV_FD_PREFIX is defined also, and has a
- trailing slash. Make sure /dev/fd/xx really uses DEV_FD_PREFIX/xx.
- On most systems, with the notable exception of linux, this is
- effectively a no-op. */
- char pbuf[32];
- strcpy (pbuf, DEV_FD_PREFIX);
- strcat (pbuf, path + 8);
- return (stat (pbuf, finfo));
-#endif /* !HAVE_DEV_FD */
- }
-#if !defined (HAVE_DEV_STDIN)
- else if (STREQN (path, "/dev/std", 8))
- {
- if (STREQ (path+8, "in"))
- return (fstat (0, finfo));
- else if (STREQ (path+8, "out"))
- return (fstat (1, finfo));
- else if (STREQ (path+8, "err"))
- return (fstat (2, finfo));
- else
- return (stat (path, finfo));
- }
-#endif /* !HAVE_DEV_STDIN */
- return (stat (path, finfo));
-}
-
-/* Do the same thing access(2) does, but use the effective uid and gid,
- and don't make the mistake of telling root that any file is
- executable. */
-int
-test_eaccess (path, mode)
- char *path;
- int mode;
-{
- struct stat st;
-
- if (test_stat (path, &st) < 0)
- return (-1);
-
- if (current_user.euid == 0)
- {
- /* Root can read or write any file. */
- if (mode != X_OK)
- return (0);
-
- /* Root can execute any file that has any one of the execute
- bits set. */
- if (st.st_mode & S_IXUGO)
- return (0);
- }
-
- if (st.st_uid == current_user.euid) /* owner */
- mode <<= 6;
- else if (group_member (st.st_gid))
- mode <<= 3;
-
- if (st.st_mode & mode)
- return (0);
-
- errno = EACCES;
- return (-1);
-}
-
-/* Increment our position in the argument list. Check that we're not
- past the end of the argument list. This check is supressed if the
- argument is FALSE. Made a macro for efficiency. */
-#define advance(f) do { ++pos; if (f && pos >= argc) beyond (); } while (0)
-#define unary_advance() do { advance (1); ++pos; } while (0)
-
-/*
- * expr:
- * or
- */
-static int
-expr ()
-{
- if (pos >= argc)
- beyond ();
-
- return (FALSE ^ or ()); /* Same with this. */
-}
-
-/*
- * or:
- * and
- * and '-o' or
- */
-static int
-or ()
-{
- int value, v2;
-
- value = and ();
- if (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'o' && !argv[pos][2])
- {
- advance (0);
- v2 = or ();
- return (value || v2);
- }
-
- return (value);
-}
-
-/*
- * and:
- * term
- * term '-a' and
- */
-static int
-and ()
-{
- int value, v2;
-
- value = term ();
- if (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'a' && !argv[pos][2])
- {
- advance (0);
- v2 = and ();
- return (value && v2);
- }
- return (value);
-}
-
-/*
- * term - parse a term and return 1 or 0 depending on whether the term
- * evaluates to true or false, respectively.
- *
- * term ::=
- * '-'('a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'k'|'p'|'r'|'s'|'u'|'w'|'x') filename
- * '-'('G'|'L'|'O'|'S'|'N') filename
- * '-t' [int]
- * '-'('z'|'n') string
- * '-o' option
- * string
- * string ('!='|'='|'==') string
- * <int> '-'(eq|ne|le|lt|ge|gt) <int>
- * file '-'(nt|ot|ef) file
- * '(' <expr> ')'
- * int ::=
- * positive and negative integers
- */
-static int
-term ()
-{
- int value;
-
- if (pos >= argc)
- beyond ();
-
- /* Deal with leading `not's. */
- if (argv[pos][0] == '!' && argv[pos][1] == '\0')
- {
- value = 0;
- while (pos < argc && argv[pos][0] == '!' && argv[pos][1] == '\0')
- {
- advance (1);
- value = 1 - value;
- }
-
- return (value ? !term() : term());
- }
-
- /* A paren-bracketed argument. */
- if (argv[pos][0] == '(' && argv[pos][1] == '\0') /* ) */
- {
- advance (1);
- value = expr ();
- if (argv[pos] == 0) /* ( */
- test_syntax_error (_("`)' expected"), (char *)NULL);
- else if (argv[pos][0] != ')' || argv[pos][1]) /* ( */
- test_syntax_error (_("`)' expected, found %s"), argv[pos]);
- advance (0);
- return (value);
- }
-
- /* are there enough arguments left that this could be dyadic? */
- if ((pos + 3 <= argc) && test_binop (argv[pos + 1]))
- value = binary_operator ();
-
- /* Might be a switch type argument */
- else if (argv[pos][0] == '-' && argv[pos][2] == '\0')
- {
- if (test_unop (argv[pos]))
- value = unary_operator ();
- else
- test_syntax_error (_("%s: unary operator expected"), argv[pos]);
- }
- else
- {
- value = argv[pos][0] != '\0';
- advance (0);
- }
-
- return (value);
-}
-
-static int
-filecomp (s, t, op)
- char *s, *t;
- int op;
-{
- struct stat st1, st2;
- int r1, r2;
-
- if ((r1 = test_stat (s, &st1)) < 0)
- {
- if (op == EF)
- return (FALSE);
- }
- if ((r2 = test_stat (t, &st2)) < 0)
- {
- if (op == EF)
- return (FALSE);
- }
-
- switch (op)
- {
- case OT: return (r1 < r2 || (r2 == 0 && st1.st_mtime < st2.st_mtime));
- case NT: return (r1 > r2 || (r1 == 0 && st1.st_mtime > st2.st_mtime));
- case EF: return ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino));
- }
- return (FALSE);
-}
-
-static int
-arithcomp (s, t, op, flags)
- char *s, *t;
- int op, flags;
-{
- intmax_t l, r;
- int expok;
-
- if (flags & TEST_ARITHEXP)
- {
- l = evalexp (s, &expok);
- if (expok == 0)
- return (FALSE); /* should probably longjmp here */
- r = evalexp (t, &expok);
- if (expok == 0)
- return (FALSE); /* ditto */
- }
- else
- {
- if (legal_number (s, &l) == 0)
- integer_expected_error (s);
- if (legal_number (t, &r) == 0)
- integer_expected_error (t);
- }
-
- switch (op)
- {
- case EQ: return (l == r);
- case NE: return (l != r);
- case LT: return (l < r);
- case GT: return (l > r);
- case LE: return (l <= r);
- case GE: return (l >= r);
- }
-
- return (FALSE);
-}
-
-static int
-patcomp (string, pat, op)
- char *string, *pat;
- int op;
-{
- int m;
-
- m = strmatch (pat, string, FNMATCH_EXTFLAG|FNMATCH_IGNCASE);
- return ((op == EQ) ? (m == 0) : (m != 0));
-}
-
-int
-binary_test (op, arg1, arg2, flags)
- char *op, *arg1, *arg2;
- int flags;
-{
- int patmatch;
-
- patmatch = (flags & TEST_PATMATCH);
-
- if (op[0] == '=' && (op[1] == '\0' || (op[1] == '=' && op[2] == '\0')))
- return (patmatch ? patcomp (arg1, arg2, EQ) : STREQ (arg1, arg2));
-
- else if ((op[0] == '>' || op[0] == '<') && op[1] == '\0')
- return ((op[0] == '>') ? (strcmp (arg1, arg2) > 0) : (strcmp (arg1, arg2) < 0));
-
- else if (op[0] == '!' && op[1] == '=' && op[2] == '\0')
- return (patmatch ? patcomp (arg1, arg2, NE) : (STREQ (arg1, arg2) == 0));
-
- else if (op[2] == 't')
- {
- switch (op[1])
- {
- case 'n': return (filecomp (arg1, arg2, NT)); /* -nt */
- case 'o': return (filecomp (arg1, arg2, OT)); /* -ot */
- case 'l': return (arithcomp (arg1, arg2, LT, flags)); /* -lt */
- case 'g': return (arithcomp (arg1, arg2, GT, flags)); /* -gt */
- }
- }
- else if (op[1] == 'e')
- {
- switch (op[2])
- {
- case 'f': return (filecomp (arg1, arg2, EF)); /* -ef */
- case 'q': return (arithcomp (arg1, arg2, EQ, flags)); /* -eq */
- }
- }
- else if (op[2] == 'e')
- {
- switch (op[1])
- {
- case 'n': return (arithcomp (arg1, arg2, NE, flags)); /* -ne */
- case 'g': return (arithcomp (arg1, arg2, GE, flags)); /* -ge */
- case 'l': return (arithcomp (arg1, arg2, LE, flags)); /* -le */
- }
- }
-
- return (FALSE); /* should never get here */
-}
-
-
-static int
-binary_operator ()
-{
- int value;
- char *w;
-
- w = argv[pos + 1];
- if ((w[0] == '=' && (w[1] == '\0' || (w[1] == '=' && w[2] == '\0'))) || /* =, == */
- ((w[0] == '>' || w[0] == '<') && w[1] == '\0') || /* <, > */
- (w[0] == '!' && w[1] == '=' && w[2] == '\0')) /* != */
- {
- value = binary_test (w, argv[pos], argv[pos + 2], 0);
- pos += 3;
- return (value);
- }
-
-#if defined (PATTERN_MATCHING)
- if ((w[0] == '=' || w[0] == '!') && w[1] == '~' && w[2] == '\0')
- {
- value = patcomp (argv[pos], argv[pos + 2], w[0] == '=' ? EQ : NE);
- pos += 3;
- return (value);
- }
-#endif
-
- if ((w[0] != '-' || w[3] != '\0') || test_binop (w) == 0)
- {
- test_syntax_error (_("%s: binary operator expected"), w);
- /* NOTREACHED */
- return (FALSE);
- }
-
- value = binary_test (w, argv[pos], argv[pos + 2], 0);
- pos += 3;
- return value;
-}
-
-static int
-unary_operator ()
-{
- char *op;
- intmax_t r;
-
- op = argv[pos];
- if (test_unop (op) == 0)
- return (FALSE);
-
- /* the only tricky case is `-t', which may or may not take an argument. */
- if (op[1] == 't')
- {
- advance (0);
- if (pos < argc)
- {
- if (legal_number (argv[pos], &r))
- {
- advance (0);
- return (unary_test (op, argv[pos - 1]));
- }
- else
- return (FALSE);
- }
- else
- return (unary_test (op, "1"));
- }
-
- /* All of the unary operators take an argument, so we first call
- unary_advance (), which checks to make sure that there is an
- argument, and then advances pos right past it. This means that
- pos - 1 is the location of the argument. */
- unary_advance ();
- return (unary_test (op, argv[pos - 1]));
-}
-
-int
-unary_test (op, arg)
- char *op, *arg;
-{
- intmax_t r;
- struct stat stat_buf;
-
- switch (op[1])
- {
- case 'a': /* file exists in the file system? */
- case 'e':
- return (test_stat (arg, &stat_buf) == 0);
-
- case 'r': /* file is readable? */
- return (EACCESS (arg, R_OK) == 0);
-
- case 'w': /* File is writeable? */
- return (EACCESS (arg, W_OK) == 0);
-
- case 'x': /* File is executable? */
- return (EACCESS (arg, X_OK) == 0);
-
- case 'O': /* File is owned by you? */
- return (test_stat (arg, &stat_buf) == 0 &&
- (uid_t) current_user.euid == (uid_t) stat_buf.st_uid);
-
- case 'G': /* File is owned by your group? */
- return (test_stat (arg, &stat_buf) == 0 &&
- (gid_t) current_user.egid == (gid_t) stat_buf.st_gid);
-
- case 'N':
- return (test_stat (arg, &stat_buf) == 0 &&
- stat_buf.st_atime <= stat_buf.st_mtime);
-
- case 'f': /* File is a file? */
- if (test_stat (arg, &stat_buf) < 0)
- return (FALSE);
-
- /* -f is true if the given file exists and is a regular file. */
-#if defined (S_IFMT)
- return (S_ISREG (stat_buf.st_mode) || (stat_buf.st_mode & S_IFMT) == 0);
-#else
- return (S_ISREG (stat_buf.st_mode));
-#endif /* !S_IFMT */
-
- case 'd': /* File is a directory? */
- return (test_stat (arg, &stat_buf) == 0 && (S_ISDIR (stat_buf.st_mode)));
-
- case 's': /* File has something in it? */
- return (test_stat (arg, &stat_buf) == 0 && stat_buf.st_size > (off_t) 0);
-
- case 'S': /* File is a socket? */
-#if !defined (S_ISSOCK)
- return (FALSE);
-#else
- return (test_stat (arg, &stat_buf) == 0 && S_ISSOCK (stat_buf.st_mode));
-#endif /* S_ISSOCK */
-
- case 'c': /* File is character special? */
- return (test_stat (arg, &stat_buf) == 0 && S_ISCHR (stat_buf.st_mode));
-
- case 'b': /* File is block special? */
- return (test_stat (arg, &stat_buf) == 0 && S_ISBLK (stat_buf.st_mode));
-
- case 'p': /* File is a named pipe? */
-#ifndef S_ISFIFO
- return (FALSE);
-#else
- return (test_stat (arg, &stat_buf) == 0 && S_ISFIFO (stat_buf.st_mode));
-#endif /* S_ISFIFO */
-
- case 'L': /* Same as -h */
- case 'h': /* File is a symbolic link? */
-#if !defined (S_ISLNK) || !defined (HAVE_LSTAT)
- return (FALSE);
-#else
- return ((arg[0] != '\0') &&
- (lstat (arg, &stat_buf) == 0) && S_ISLNK (stat_buf.st_mode));
-#endif /* S_IFLNK && HAVE_LSTAT */
-
- case 'u': /* File is setuid? */
- return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISUID) != 0);
-
- case 'g': /* File is setgid? */
- return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISGID) != 0);
-
- case 'k': /* File has sticky bit set? */
-#if !defined (S_ISVTX)
- /* This is not Posix, and is not defined on some Posix systems. */
- return (FALSE);
-#else
- return (test_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISVTX) != 0);
-#endif
-
- case 't': /* File fd is a terminal? */
- if (legal_number (arg, &r) == 0)
- return (FALSE);
- return ((r == (int)r) && isatty ((int)r));
-
- case 'n': /* True if arg has some length. */
- return (arg[0] != '\0');
-
- case 'z': /* True if arg has no length. */
- return (arg[0] == '\0');
-
- case 'o': /* True if option `arg' is set. */
- return (minus_o_option_value (arg) == 1);
- }
-
- /* We can't actually get here, but this shuts up gcc. */
- return (FALSE);
-}
-
-/* Return TRUE if OP is one of the test command's binary operators. */
-int
-test_binop (op)
- char *op;
-{
- if (op[0] == '=' && op[1] == '\0')
- return (1); /* '=' */
- else if ((op[0] == '<' || op[0] == '>') && op[1] == '\0') /* string <, > */
- return (1);
- else if ((op[0] == '=' || op[0] == '!') && op[1] == '=' && op[2] == '\0')
- return (1); /* `==' and `!=' */
-#if defined (PATTERN_MATCHING)
- else if (op[2] == '\0' && op[1] == '~' && (op[0] == '=' || op[0] == '!'))
- return (1);
-#endif
- else if (op[0] != '-' || op[2] == '\0' || op[3] != '\0')
- return (0);
- else
- {
- if (op[2] == 't')
- switch (op[1])
- {
- case 'n': /* -nt */
- case 'o': /* -ot */
- case 'l': /* -lt */
- case 'g': /* -gt */
- return (1);
- default:
- return (0);
- }
- else if (op[1] == 'e')
- switch (op[2])
- {
- case 'q': /* -eq */
- case 'f': /* -ef */
- return (1);
- default:
- return (0);
- }
- else if (op[2] == 'e')
- switch (op[1])
- {
- case 'n': /* -ne */
- case 'g': /* -ge */
- case 'l': /* -le */
- return (1);
- default:
- return (0);
- }
- else
- return (0);
- }
-}
-
-/* Return non-zero if OP is one of the test command's unary operators. */
-int
-test_unop (op)
- char *op;
-{
- if (op[0] != '-')
- return (0);
-
- switch (op[1])
- {
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'k': case 'n':
- case 'o': case 'p': case 'r': case 's': case 't':
- case 'u': case 'w': case 'x': case 'z':
- case 'G': case 'L': case 'O': case 'S': case 'N':
- return (1);
- }
-
- return (0);
-}
-
-static int
-two_arguments ()
-{
- if (argv[pos][0] == '!' && argv[pos][1] == '\0')
- return (argv[pos + 1][0] == '\0');
- else if (argv[pos][0] == '-' && argv[pos][2] == '\0')
- {
- if (test_unop (argv[pos]))
- return (unary_operator ());
- else
- test_syntax_error (_("%s: unary operator expected"), argv[pos]);
- }
- else
- test_syntax_error (_("%s: unary operator expected"), argv[pos]);
-
- return (0);
-}
-
-#define ANDOR(s) (s[0] == '-' && !s[2] && (s[1] == 'a' || s[1] == 'o'))
-
-/* This could be augmented to handle `-t' as equivalent to `-t 1', but
- POSIX requires that `-t' be given an argument. */
-#define ONE_ARG_TEST(s) ((s)[0] != '\0')
-
-static int
-three_arguments ()
-{
- int value;
-
- if (test_binop (argv[pos+1]))
- {
- value = binary_operator ();
- pos = argc;
- }
- else if (ANDOR (argv[pos+1]))
- {
- if (argv[pos+1][1] == 'a')
- value = ONE_ARG_TEST(argv[pos]) && ONE_ARG_TEST(argv[pos+2]);
- else
- value = ONE_ARG_TEST(argv[pos]) || ONE_ARG_TEST(argv[pos+2]);
- pos = argc;
- }
- else if (argv[pos][0] == '!' && argv[pos][1] == '\0')
- {
- advance (1);
- value = !two_arguments ();
- }
- else if (argv[pos][0] == '(' && argv[pos+2][0] == ')')
- {
- value = ONE_ARG_TEST(argv[pos+1]);
- pos = argc;
- }
- else
- test_syntax_error (_("%s: binary operator expected"), argv[pos+1]);
-
- return (value);
-}
-
-/* This is an implementation of a Posix.2 proposal by David Korn. */
-static int
-posixtest ()
-{
- int value;
-
- switch (argc - 1) /* one extra passed in */
- {
- case 0:
- value = FALSE;
- pos = argc;
- break;
-
- case 1:
- value = ONE_ARG_TEST(argv[1]);
- pos = argc;
- break;
-
- case 2:
- value = two_arguments ();
- pos = argc;
- break;
-
- case 3:
- value = three_arguments ();
- break;
-
- case 4:
- if (argv[pos][0] == '!' && argv[pos][1] == '\0')
- {
- advance (1);
- value = !three_arguments ();
- break;
- }
- /* FALLTHROUGH */
- default:
- value = expr ();
- }
-
- return (value);
-}
-
-/*
- * [:
- * '[' expr ']'
- * test:
- * test expr
- */
-int
-test_command (margc, margv)
- int margc;
- char **margv;
-{
- int value;
- int code;
-
- USE_VAR(margc);
-
- code = setjmp (test_exit_buf);
-
- if (code)
- return (test_error_return);
-
- argv = margv;
-
- if (margv[0] && margv[0][0] == '[' && margv[0][1] == '\0')
- {
- --margc;
-
- if (margv[margc] && (margv[margc][0] != ']' || margv[margc][1]))
- test_syntax_error (_("missing `]'"), (char *)NULL);
-
- if (margc < 2)
- test_exit (SHELL_BOOLEAN (FALSE));
- }
-
- argc = margc;
- pos = 1;
-
- if (pos >= argc)
- test_exit (SHELL_BOOLEAN (FALSE));
-
- noeval = 0;
- value = posixtest ();
-
- if (pos != argc)
- test_syntax_error (_("too many arguments"), (char *)NULL);
-
- test_exit (SHELL_BOOLEAN (value));
-}
diff --git a/test.c~ b/test.c~
deleted file mode 100644
index d37a3310..00000000
--- a/test.c~
+++ /dev/null
@@ -1,834 +0,0 @@
-/* GNU test program (ksb and mjb) */
-
-/* Modified to run with the GNU shell Apr 25, 1988 by bfox. */
-
-/* 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. */
-
-/* Define PATTERN_MATCHING to get the csh-like =~ and !~ pattern-matching
- binary operators. */
-/* #define PATTERN_MATCHING */
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <stdio.h>
-
-#include "bashtypes.h"
-
-#if !defined (HAVE_LIMITS_H)
-# include <sys/param.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <errno.h>
-#if !defined (errno)
-extern int errno;
-#endif /* !errno */
-
-#if !defined (_POSIX_VERSION) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif /* !_POSIX_VERSION */
-#include "posixstat.h"
-#include "filecntl.h"
-
-#include "bashintl.h"
-
-#include "shell.h"
-#include "pathexp.h"
-#include "test.h"
-#include "builtins/common.h"
-
-#include <glob/strmatch.h>
-
-#if !defined (STRLEN)
-# define STRLEN(s) ((s)[0] ? ((s)[1] ? ((s)[2] ? strlen(s) : 2) : 1) : 0)
-#endif
-
-#if !defined (STREQ)
-# define STREQ(a, b) ((a)[0] == (b)[0] && strcmp (a, b) == 0)
-#endif /* !STREQ */
-
-#if !defined (R_OK)
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#define F_OK 0
-#endif /* R_OK */
-
-#define EQ 0
-#define NE 1
-#define LT 2
-#define GT 3
-#define LE 4
-#define GE 5
-
-#define NT 0
-#define OT 1
-#define EF 2
-
-/* The following few defines control the truth and false output of each stage.
- TRUE and FALSE are what we use to compute the final output value.
- SHELL_BOOLEAN is the form which returns truth or falseness in shell terms.
- Default is TRUE = 1, FALSE = 0, SHELL_BOOLEAN = (!value). */
-#define TRUE 1
-#define FALSE 0
-#define SHELL_BOOLEAN(value) (!(value))
-
-#define TEST_ERREXIT_STATUS 2
-
-static procenv_t test_exit_buf;
-static int test_error_return;
-#define test_exit(val) \
- do { test_error_return = val; longjmp (test_exit_buf, 1); } while (0)
-
-extern int sh_stat __P((const char *, struct stat *));
-
-/* We have to use access(2) for machines running AFS, because it's
- not a Unix file system. This may produce incorrect answers for
- non-AFS files. I hate AFS. */
-#if defined (AFS)
-# define EACCESS(path, mode) access(path, mode)
-#else
-# define EACCESS(path, mode) sh_eaccess(path, mode)
-#endif /* AFS */
-
-static int pos; /* The offset of the current argument in ARGV. */
-static int argc; /* The number of arguments present in ARGV. */
-static char **argv; /* The argument list. */
-static int noeval;
-
-static void test_syntax_error __P((char *, char *)) __attribute__((__noreturn__));
-static void beyond __P((void)) __attribute__((__noreturn__));
-static void integer_expected_error __P((char *)) __attribute__((__noreturn__));
-
-static int unary_operator __P((void));
-static int binary_operator __P((void));
-static int two_arguments __P((void));
-static int three_arguments __P((void));
-static int posixtest __P((void));
-
-static int expr __P((void));
-static int term __P((void));
-static int and __P((void));
-static int or __P((void));
-
-static int filecomp __P((char *, char *, int));
-static int arithcomp __P((char *, char *, int, int));
-static int patcomp __P((char *, char *, int));
-
-static void
-test_syntax_error (format, arg)
- char *format, *arg;
-{
- builtin_error (format, arg);
- test_exit (TEST_ERREXIT_STATUS);
-}
-
-/*
- * beyond - call when we're beyond the end of the argument list (an
- * error condition)
- */
-static void
-beyond ()
-{
- test_syntax_error (_("argument expected"), (char *)NULL);
-}
-
-/* Syntax error for when an integer argument was expected, but
- something else was found. */
-static void
-integer_expected_error (pch)
- char *pch;
-{
- test_syntax_error (_("%s: integer expression expected"), pch);
-}
-
-/* Increment our position in the argument list. Check that we're not
- past the end of the argument list. This check is supressed if the
- argument is FALSE. Made a macro for efficiency. */
-#define advance(f) do { ++pos; if (f && pos >= argc) beyond (); } while (0)
-#define unary_advance() do { advance (1); ++pos; } while (0)
-
-/*
- * expr:
- * or
- */
-static int
-expr ()
-{
- if (pos >= argc)
- beyond ();
-
- return (FALSE ^ or ()); /* Same with this. */
-}
-
-/*
- * or:
- * and
- * and '-o' or
- */
-static int
-or ()
-{
- int value, v2;
-
- value = and ();
- if (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'o' && !argv[pos][2])
- {
- advance (0);
- v2 = or ();
- return (value || v2);
- }
-
- return (value);
-}
-
-/*
- * and:
- * term
- * term '-a' and
- */
-static int
-and ()
-{
- int value, v2;
-
- value = term ();
- if (pos < argc && argv[pos][0] == '-' && argv[pos][1] == 'a' && !argv[pos][2])
- {
- advance (0);
- v2 = and ();
- return (value && v2);
- }
- return (value);
-}
-
-/*
- * term - parse a term and return 1 or 0 depending on whether the term
- * evaluates to true or false, respectively.
- *
- * term ::=
- * '-'('a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'k'|'p'|'r'|'s'|'u'|'w'|'x') filename
- * '-'('G'|'L'|'O'|'S'|'N') filename
- * '-t' [int]
- * '-'('z'|'n') string
- * '-o' option
- * string
- * string ('!='|'='|'==') string
- * <int> '-'(eq|ne|le|lt|ge|gt) <int>
- * file '-'(nt|ot|ef) file
- * '(' <expr> ')'
- * int ::=
- * positive and negative integers
- */
-static int
-term ()
-{
- int value;
-
- if (pos >= argc)
- beyond ();
-
- /* Deal with leading `not's. */
- if (argv[pos][0] == '!' && argv[pos][1] == '\0')
- {
- value = 0;
- while (pos < argc && argv[pos][0] == '!' && argv[pos][1] == '\0')
- {
- advance (1);
- value = 1 - value;
- }
-
- return (value ? !term() : term());
- }
-
- /* A paren-bracketed argument. */
- if (argv[pos][0] == '(' && argv[pos][1] == '\0') /* ) */
- {
- advance (1);
- value = expr ();
- if (argv[pos] == 0) /* ( */
- test_syntax_error (_("`)' expected"), (char *)NULL);
- else if (argv[pos][0] != ')' || argv[pos][1]) /* ( */
- test_syntax_error (_("`)' expected, found %s"), argv[pos]);
- advance (0);
- return (value);
- }
-
- /* are there enough arguments left that this could be dyadic? */
- if ((pos + 3 <= argc) && test_binop (argv[pos + 1]))
- value = binary_operator ();
-
- /* Might be a switch type argument */
- else if (argv[pos][0] == '-' && argv[pos][2] == '\0')
- {
- if (test_unop (argv[pos]))
- value = unary_operator ();
- else
- test_syntax_error (_("%s: unary operator expected"), argv[pos]);
- }
- else
- {
- value = argv[pos][0] != '\0';
- advance (0);
- }
-
- return (value);
-}
-
-static int
-filecomp (s, t, op)
- char *s, *t;
- int op;
-{
- struct stat st1, st2;
- int r1, r2;
-
- if ((r1 = sh_stat (s, &st1)) < 0)
- {
- if (op == EF)
- return (FALSE);
- }
- if ((r2 = sh_stat (t, &st2)) < 0)
- {
- if (op == EF)
- return (FALSE);
- }
-
- switch (op)
- {
- case OT: return (r1 < r2 || (r2 == 0 && st1.st_mtime < st2.st_mtime));
- case NT: return (r1 > r2 || (r1 == 0 && st1.st_mtime > st2.st_mtime));
- case EF: return ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino));
- }
- return (FALSE);
-}
-
-static int
-arithcomp (s, t, op, flags)
- char *s, *t;
- int op, flags;
-{
- intmax_t l, r;
- int expok;
-
- if (flags & TEST_ARITHEXP)
- {
- l = evalexp (s, &expok);
- if (expok == 0)
- return (FALSE); /* should probably longjmp here */
- r = evalexp (t, &expok);
- if (expok == 0)
- return (FALSE); /* ditto */
- }
- else
- {
- if (legal_number (s, &l) == 0)
- integer_expected_error (s);
- if (legal_number (t, &r) == 0)
- integer_expected_error (t);
- }
-
- switch (op)
- {
- case EQ: return (l == r);
- case NE: return (l != r);
- case LT: return (l < r);
- case GT: return (l > r);
- case LE: return (l <= r);
- case GE: return (l >= r);
- }
-
- return (FALSE);
-}
-
-static int
-patcomp (string, pat, op)
- char *string, *pat;
- int op;
-{
- int m;
-
- m = strmatch (pat, string, FNMATCH_EXTFLAG|FNMATCH_IGNCASE);
- return ((op == EQ) ? (m == 0) : (m != 0));
-}
-
-int
-binary_test (op, arg1, arg2, flags)
- char *op, *arg1, *arg2;
- int flags;
-{
- int patmatch;
-
- patmatch = (flags & TEST_PATMATCH);
-
- if (op[0] == '=' && (op[1] == '\0' || (op[1] == '=' && op[2] == '\0')))
- return (patmatch ? patcomp (arg1, arg2, EQ) : STREQ (arg1, arg2));
-
- else if ((op[0] == '>' || op[0] == '<') && op[1] == '\0')
- return ((op[0] == '>') ? (strcmp (arg1, arg2) > 0) : (strcmp (arg1, arg2) < 0));
-
- else if (op[0] == '!' && op[1] == '=' && op[2] == '\0')
- return (patmatch ? patcomp (arg1, arg2, NE) : (STREQ (arg1, arg2) == 0));
-
- else if (op[2] == 't')
- {
- switch (op[1])
- {
- case 'n': return (filecomp (arg1, arg2, NT)); /* -nt */
- case 'o': return (filecomp (arg1, arg2, OT)); /* -ot */
- case 'l': return (arithcomp (arg1, arg2, LT, flags)); /* -lt */
- case 'g': return (arithcomp (arg1, arg2, GT, flags)); /* -gt */
- }
- }
- else if (op[1] == 'e')
- {
- switch (op[2])
- {
- case 'f': return (filecomp (arg1, arg2, EF)); /* -ef */
- case 'q': return (arithcomp (arg1, arg2, EQ, flags)); /* -eq */
- }
- }
- else if (op[2] == 'e')
- {
- switch (op[1])
- {
- case 'n': return (arithcomp (arg1, arg2, NE, flags)); /* -ne */
- case 'g': return (arithcomp (arg1, arg2, GE, flags)); /* -ge */
- case 'l': return (arithcomp (arg1, arg2, LE, flags)); /* -le */
- }
- }
-
- return (FALSE); /* should never get here */
-}
-
-
-static int
-binary_operator ()
-{
- int value;
- char *w;
-
- w = argv[pos + 1];
- if ((w[0] == '=' && (w[1] == '\0' || (w[1] == '=' && w[2] == '\0'))) || /* =, == */
- ((w[0] == '>' || w[0] == '<') && w[1] == '\0') || /* <, > */
- (w[0] == '!' && w[1] == '=' && w[2] == '\0')) /* != */
- {
- value = binary_test (w, argv[pos], argv[pos + 2], 0);
- pos += 3;
- return (value);
- }
-
-#if defined (PATTERN_MATCHING)
- if ((w[0] == '=' || w[0] == '!') && w[1] == '~' && w[2] == '\0')
- {
- value = patcomp (argv[pos], argv[pos + 2], w[0] == '=' ? EQ : NE);
- pos += 3;
- return (value);
- }
-#endif
-
- if ((w[0] != '-' || w[3] != '\0') || test_binop (w) == 0)
- {
- test_syntax_error (_("%s: binary operator expected"), w);
- /* NOTREACHED */
- return (FALSE);
- }
-
- value = binary_test (w, argv[pos], argv[pos + 2], 0);
- pos += 3;
- return value;
-}
-
-static int
-unary_operator ()
-{
- char *op;
- intmax_t r;
-
- op = argv[pos];
- if (test_unop (op) == 0)
- return (FALSE);
-
- /* the only tricky case is `-t', which may or may not take an argument. */
- if (op[1] == 't')
- {
- advance (0);
- if (pos < argc)
- {
- if (legal_number (argv[pos], &r))
- {
- advance (0);
- return (unary_test (op, argv[pos - 1]));
- }
- else
- return (FALSE);
- }
- else
- return (unary_test (op, "1"));
- }
-
- /* All of the unary operators take an argument, so we first call
- unary_advance (), which checks to make sure that there is an
- argument, and then advances pos right past it. This means that
- pos - 1 is the location of the argument. */
- unary_advance ();
- return (unary_test (op, argv[pos - 1]));
-}
-
-int
-unary_test (op, arg)
- char *op, *arg;
-{
- intmax_t r;
- struct stat stat_buf;
-
- switch (op[1])
- {
- case 'a': /* file exists in the file system? */
- case 'e':
- return (sh_stat (arg, &stat_buf) == 0);
-
- case 'r': /* file is readable? */
- return (EACCESS (arg, R_OK) == 0);
-
- case 'w': /* File is writeable? */
- return (EACCESS (arg, W_OK) == 0);
-
- case 'x': /* File is executable? */
- return (EACCESS (arg, X_OK) == 0);
-
- case 'O': /* File is owned by you? */
- return (sh_stat (arg, &stat_buf) == 0 &&
- (uid_t) current_user.euid == (uid_t) stat_buf.st_uid);
-
- case 'G': /* File is owned by your group? */
- return (sh_stat (arg, &stat_buf) == 0 &&
- (gid_t) current_user.egid == (gid_t) stat_buf.st_gid);
-
- case 'N':
- return (sh_stat (arg, &stat_buf) == 0 &&
- stat_buf.st_atime <= stat_buf.st_mtime);
-
- case 'f': /* File is a file? */
- if (sh_stat (arg, &stat_buf) < 0)
- return (FALSE);
-
- /* -f is true if the given file exists and is a regular file. */
-#if defined (S_IFMT)
- return (S_ISREG (stat_buf.st_mode) || (stat_buf.st_mode & S_IFMT) == 0);
-#else
- return (S_ISREG (stat_buf.st_mode));
-#endif /* !S_IFMT */
-
- case 'd': /* File is a directory? */
- return (sh_stat (arg, &stat_buf) == 0 && (S_ISDIR (stat_buf.st_mode)));
-
- case 's': /* File has something in it? */
- return (sh_stat (arg, &stat_buf) == 0 && stat_buf.st_size > (off_t) 0);
-
- case 'S': /* File is a socket? */
-#if !defined (S_ISSOCK)
- return (FALSE);
-#else
- return (sh_stat (arg, &stat_buf) == 0 && S_ISSOCK (stat_buf.st_mode));
-#endif /* S_ISSOCK */
-
- case 'c': /* File is character special? */
- return (sh_stat (arg, &stat_buf) == 0 && S_ISCHR (stat_buf.st_mode));
-
- case 'b': /* File is block special? */
- return (sh_stat (arg, &stat_buf) == 0 && S_ISBLK (stat_buf.st_mode));
-
- case 'p': /* File is a named pipe? */
-#ifndef S_ISFIFO
- return (FALSE);
-#else
- return (sh_stat (arg, &stat_buf) == 0 && S_ISFIFO (stat_buf.st_mode));
-#endif /* S_ISFIFO */
-
- case 'L': /* Same as -h */
- case 'h': /* File is a symbolic link? */
-#if !defined (S_ISLNK) || !defined (HAVE_LSTAT)
- return (FALSE);
-#else
- return ((arg[0] != '\0') &&
- (lstat (arg, &stat_buf) == 0) && S_ISLNK (stat_buf.st_mode));
-#endif /* S_IFLNK && HAVE_LSTAT */
-
- case 'u': /* File is setuid? */
- return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISUID) != 0);
-
- case 'g': /* File is setgid? */
- return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISGID) != 0);
-
- case 'k': /* File has sticky bit set? */
-#if !defined (S_ISVTX)
- /* This is not Posix, and is not defined on some Posix systems. */
- return (FALSE);
-#else
- return (sh_stat (arg, &stat_buf) == 0 && (stat_buf.st_mode & S_ISVTX) != 0);
-#endif
-
- case 't': /* File fd is a terminal? */
- if (legal_number (arg, &r) == 0)
- return (FALSE);
- return ((r == (int)r) && isatty ((int)r));
-
- case 'n': /* True if arg has some length. */
- return (arg[0] != '\0');
-
- case 'z': /* True if arg has no length. */
- return (arg[0] == '\0');
-
- case 'o': /* True if option `arg' is set. */
- return (minus_o_option_value (arg) == 1);
- }
-
- /* We can't actually get here, but this shuts up gcc. */
- return (FALSE);
-}
-
-/* Return TRUE if OP is one of the test command's binary operators. */
-int
-test_binop (op)
- char *op;
-{
- if (op[0] == '=' && op[1] == '\0')
- return (1); /* '=' */
- else if ((op[0] == '<' || op[0] == '>') && op[1] == '\0') /* string <, > */
- return (1);
- else if ((op[0] == '=' || op[0] == '!') && op[1] == '=' && op[2] == '\0')
- return (1); /* `==' and `!=' */
-#if defined (PATTERN_MATCHING)
- else if (op[2] == '\0' && op[1] == '~' && (op[0] == '=' || op[0] == '!'))
- return (1);
-#endif
- else if (op[0] != '-' || op[2] == '\0' || op[3] != '\0')
- return (0);
- else
- {
- if (op[2] == 't')
- switch (op[1])
- {
- case 'n': /* -nt */
- case 'o': /* -ot */
- case 'l': /* -lt */
- case 'g': /* -gt */
- return (1);
- default:
- return (0);
- }
- else if (op[1] == 'e')
- switch (op[2])
- {
- case 'q': /* -eq */
- case 'f': /* -ef */
- return (1);
- default:
- return (0);
- }
- else if (op[2] == 'e')
- switch (op[1])
- {
- case 'n': /* -ne */
- case 'g': /* -ge */
- case 'l': /* -le */
- return (1);
- default:
- return (0);
- }
- else
- return (0);
- }
-}
-
-/* Return non-zero if OP is one of the test command's unary operators. */
-int
-test_unop (op)
- char *op;
-{
- if (op[0] != '-')
- return (0);
-
- switch (op[1])
- {
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'k': case 'n':
- case 'o': case 'p': case 'r': case 's': case 't':
- case 'u': case 'w': case 'x': case 'z':
- case 'G': case 'L': case 'O': case 'S': case 'N':
- return (1);
- }
-
- return (0);
-}
-
-static int
-two_arguments ()
-{
- if (argv[pos][0] == '!' && argv[pos][1] == '\0')
- return (argv[pos + 1][0] == '\0');
- else if (argv[pos][0] == '-' && argv[pos][2] == '\0')
- {
- if (test_unop (argv[pos]))
- return (unary_operator ());
- else
- test_syntax_error (_("%s: unary operator expected"), argv[pos]);
- }
- else
- test_syntax_error (_("%s: unary operator expected"), argv[pos]);
-
- return (0);
-}
-
-#define ANDOR(s) (s[0] == '-' && !s[2] && (s[1] == 'a' || s[1] == 'o'))
-
-/* This could be augmented to handle `-t' as equivalent to `-t 1', but
- POSIX requires that `-t' be given an argument. */
-#define ONE_ARG_TEST(s) ((s)[0] != '\0')
-
-static int
-three_arguments ()
-{
- int value;
-
- if (test_binop (argv[pos+1]))
- {
- value = binary_operator ();
- pos = argc;
- }
- else if (ANDOR (argv[pos+1]))
- {
- if (argv[pos+1][1] == 'a')
- value = ONE_ARG_TEST(argv[pos]) && ONE_ARG_TEST(argv[pos+2]);
- else
- value = ONE_ARG_TEST(argv[pos]) || ONE_ARG_TEST(argv[pos+2]);
- pos = argc;
- }
- else if (argv[pos][0] == '!' && argv[pos][1] == '\0')
- {
- advance (1);
- value = !two_arguments ();
- }
- else if (argv[pos][0] == '(' && argv[pos+2][0] == ')')
- {
- value = ONE_ARG_TEST(argv[pos+1]);
- pos = argc;
- }
- else
- test_syntax_error (_("%s: binary operator expected"), argv[pos+1]);
-
- return (value);
-}
-
-/* This is an implementation of a Posix.2 proposal by David Korn. */
-static int
-posixtest ()
-{
- int value;
-
- switch (argc - 1) /* one extra passed in */
- {
- case 0:
- value = FALSE;
- pos = argc;
- break;
-
- case 1:
- value = ONE_ARG_TEST(argv[1]);
- pos = argc;
- break;
-
- case 2:
- value = two_arguments ();
- pos = argc;
- break;
-
- case 3:
- value = three_arguments ();
- break;
-
- case 4:
- if (argv[pos][0] == '!' && argv[pos][1] == '\0')
- {
- advance (1);
- value = !three_arguments ();
- break;
- }
- /* FALLTHROUGH */
- default:
- value = expr ();
- }
-
- return (value);
-}
-
-/*
- * [:
- * '[' expr ']'
- * test:
- * test expr
- */
-int
-test_command (margc, margv)
- int margc;
- char **margv;
-{
- int value;
- int code;
-
- USE_VAR(margc);
-
- code = setjmp (test_exit_buf);
-
- if (code)
- return (test_error_return);
-
- argv = margv;
-
- if (margv[0] && margv[0][0] == '[' && margv[0][1] == '\0')
- {
- --margc;
-
- if (margv[margc] && (margv[margc][0] != ']' || margv[margc][1]))
- test_syntax_error (_("missing `]'"), (char *)NULL);
-
- if (margc < 2)
- test_exit (SHELL_BOOLEAN (FALSE));
- }
-
- argc = margc;
- pos = 1;
-
- if (pos >= argc)
- test_exit (SHELL_BOOLEAN (FALSE));
-
- noeval = 0;
- value = posixtest ();
-
- if (pos != argc)
- test_syntax_error (_("too many arguments"), (char *)NULL);
-
- test_exit (SHELL_BOOLEAN (value));
-}
diff --git a/test.h~ b/test.h~
deleted file mode 100644
index 3aef8913..00000000
--- a/test.h~
+++ /dev/null
@@ -1,40 +0,0 @@
-/* test.h -- external interface to the conditional command code. */
-
-/* Copyright (C) 1997 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-1307, USA. */
-
-#ifndef _TEST_H_
-#define _TEST_H_
-
-#include "stdc.h"
-
-/* Values for the flags argument to binary_test */
-#define TEST_PATMATCH 0x01
-#define TEST_ARITHEXP 0x02
-
-extern int test_eaccess __P((char *, int));
-
-extern int test_unop __P((char *));
-extern int test_binop __P((char *));
-
-extern int unary_test __P((char *, char *));
-extern int binary_test __P((char *, char *, char *, int));
-
-extern int test_command __P((int, char **));
-
-#endif /* _TEST_H_ */
diff --git a/tests/RUN-ONE-TEST~ b/tests/RUN-ONE-TEST~
deleted file mode 100755
index 3efcf32d..00000000
--- a/tests/RUN-ONE-TEST~
+++ /dev/null
@@ -1,9 +0,0 @@
-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/array4.sub~ b/tests/array4.sub~
deleted file mode 100644
index f61d7a96..00000000
--- a/tests/array4.sub~
+++ /dev/null
@@ -1,30 +0,0 @@
-# compound assignment parsing problems in bash-3.1-release
-func()
-{
- local -a x=() y=()
-}
-
-a=() b=()
-eval foo=()
-eval foo=() bar=() qux=( "bash" )
-
-foo=( "bash" )
-eval foo=( "bash" )
-eval bar=( "bash" ) bax=( "bash" )
-
-let a=(5 + 3) b=(4 + 7)
-echo $a $b
-
-typeset -i a b
-a=(5+3) b=(4+7)
-echo $a $b
-
-a=(4*3)/2
-echo $a
-
-LNAME=nordholz
-echo ${LNAME}
-echo ${#LNAME}
-
-echo ${#LNAME[$(( 0 ))]}
-echo ${#LNAME[$(( 0+0 ))]}
diff --git a/tests/braces.tests~ b/tests/braces.tests~
deleted file mode 100644
index 3f57829f..00000000
--- a/tests/braces.tests~
+++ /dev/null
@@ -1,70 +0,0 @@
-echo ff{c,b,a}
-echo f{d,e,f}g
-echo {l,n,m}xyz
-echo {abc\,def}
-echo {abc}
-
-echo \{a,b,c,d,e}
-echo {x,y,\{a,b,c}}
-echo {x\,y,\{abc\},trie}
-
-echo /usr/{ucb/{ex,edit},lib/{ex,how_ex}}
-
-echo XXXX\{`echo a b c | tr ' ' ','`\}
-eval echo XXXX\{`echo a b c | tr ' ' ','`\}
-
-echo {}
-echo { }
-echo }
-echo {
-echo abcd{efgh
-
-echo foo {1,2} bar
-echo `zecho foo {1,2} bar`
-echo $(zecho foo {1,2} bar)
-
-var=baz
-varx=vx
-vary=vy
-
-echo foo{bar,${var}.}
-echo foo{bar,${var}}
-
-echo "${var}"{x,y}
-echo $var{x,y}
-echo ${var}{x,y}
-
-unset var varx vary
-
-# new sequence brace operators
-echo {1..10}
-
-# this doesn't work yet
-echo {0..10,braces}
-# but this does
-echo {{0..10},braces}
-echo x{{0..10},braces}y
-
-echo {3..3}
-echo x{3..3}y
-echo {10..1}
-echo {10..1}y
-echo x{10..1}y
-
-echo {a..f}
-echo {f..a}
-
-echo {a..A}
-echo {A..a}
-
-echo {f..f}
-
-# mixes are incorrectly-formed brace expansions
-echo {1..f}
-echo {f..1}
-
-echo 0{1..9} {10..20}
-
-# do negative numbers work?
-echo {-1..-10}
-echo {-20..0}
diff --git a/tests/cprint.right.save1 b/tests/cprint.right.save1
deleted file mode 100644
index 6b711b8c..00000000
--- a/tests/cprint.right.save1
+++ /dev/null
@@ -1,72 +0,0 @@
-tf is a function
-tf ()
-{
- echo this is ${0##*/} >/dev/null;
- echo a | cat - >/dev/null;
- test -f ${0##*/} && echo ${0##*/} is a regular file;
- test -d ${0##*/} || echo ${0##*/} is not a directory;
- echo a;
- echo b;
- echo c;
- echo background >/dev/null & ( exit 1 );
- echo $?;
- {
- echo a
- };
- i=0;
- while (( " i < 3 " )); do
- test -r /dev/fd/$i;
- i=$(( i + 1 ));
- done;
- [[ -r /dev/fd/0 && -w /dev/fd/1 ]] || echo oops >/dev/null;
- for name in $( echo 1 2 3 );
- do
- test -r /dev/fd/$name;
- done;
- if [[ -r /dev/fd/0 && -w /dev/fd/1 ]]; then
- echo ok >/dev/null;
- else
- if (( " 7 > 40 " )); then
- echo oops;
- else
- echo done;
- fi;
- fi >/dev/null;
- case $PATH in
- *$PWD*)
- echo \$PWD in \$PATH
- ;;
- *)
- echo \$PWD not in \$PATH
- ;;
- esac >/dev/null;
- while false; do
- echo z;
- done >/dev/null;
- until true; do
- echo z;
- done >/dev/null;
- echo \&\|'()' \{ echo abcde \; \};
- eval fu\%nc'()' \{ echo abcde \; \};
- type fu\%nc
-}
-tf2 is a function
-tf2 ()
-{
- ( {
- time -p echo a | cat - >/dev/null
- } ) 2>&1
-}
-cprint.tests is a regular file
-cprint.tests is not a directory
-a
-b
-c
-1
-a
-&|() { echo abcde ; }
-fu%nc is a function
-fu%nc ()
-{
- echo abcde
-}
diff --git a/tests/func.right~ b/tests/func.right~
deleted file mode 100644
index e51d92b1..00000000
--- a/tests/func.right~
+++ /dev/null
@@ -1,150 +0,0 @@
-a returns 5
-b returns 4
-c returns 3
-d returns 2
-in e
-e returned 25
-x is 25
-ZZ
-abcde
-defghi
-ZZ
-5
-0
-AVAR
-AVAR
-foo
-foo
-AVAR
-5
-5
-f1
-f1 ()
-{
- ( return 5 );
- status=$?;
- echo $status;
- return $status
-}
-before: try to assign to FUNCNAME
-outside: FUNCNAME =
-before: FUNCNAME = func
-FUNCNAME = func2
-after: FUNCNAME = func
-outside2: FUNCNAME =
-function
-zf is a function
-zf ()
-{
- echo this is zf
-}
-f is a function
-f ()
-{
- echo f-x;
- echo f-y
-} 1>&2
-subshell
-f is a function
-f ()
-{
- echo f-x;
- echo f-y
-} 1>&2
-f2 is a function
-f2 ()
-{
- echo f2-a;
- function f3 ()
- {
- echo f3-a;
- echo f3-b
- } 1>&2;
- f3
-}
-subshell
-f2 is a function
-f2 ()
-{
- echo f2-a;
- function f3 ()
- {
- echo f3-a;
- echo f3-b
- } 1>&2;
- f3
-}
-f4 is a function
-f4 ()
-{
- echo f4-a;
- function f5 ()
- {
- echo f5-a;
- echo f5-b
- } 1>&2;
- f5
-} 2>&1
-subshell
-f4 is a function
-f4 ()
-{
- echo f4-a;
- function f5 ()
- {
- echo f5-a;
- echo f5-b
- } 1>&2;
- f5
-} 2>&1
-testgrp is a function
-testgrp ()
-{
- echo testgrp-a;
- {
- echo tg-x;
- echo tg-y
- } 1>&2;
- echo testgrp-b
-}
-subshell
-testgrp is a function
-testgrp ()
-{
- echo testgrp-a;
- {
- echo tg-x;
- echo tg-y
- } 1>&2;
- echo testgrp-b
-}
-funca is a function
-funca ()
-{
- ( echo func-a )
-}
-funcb is a function
-funcb ()
-{
- ( echo func-b )
-}
-funcc is a function
-funcc ()
-{
- ( echo func-c ) 2>&1
-}
-func-a
-func-b
-func-c
-expect 5 10
-5 10
-expect 20
-20
-expect 5 20
-5 20
-expect 5 30
-5 30
-expect 2 40
-2 40
-expect 5 20
-5 20
diff --git a/tests/func.tests~ b/tests/func.tests~
deleted file mode 100644
index cbbbdb03..00000000
--- a/tests/func.tests~
+++ /dev/null
@@ -1,176 +0,0 @@
-a()
-{
- x=$((x - 1))
- return 5
-}
-
-b()
-{
- x=$((x - 1))
- a
- echo a returns $?
- return 4
-}
-
-c()
-{
- x=$((x - 1))
- b
- echo b returns $?
- return 3
-}
-
-d()
-{
- x=$((x - 1))
- c
- echo c returns $?
- return 2
-}
-
-e()
-{
- d
- echo d returns $?
- echo in e
- x=$((x - 1))
- return $x
-}
-
-f()
-{
- e
- echo e returned $?
- echo x is $x
- return 0
-}
-
-x=30
-f
-
-# make sure unsetting a local variable preserves the `local' attribute
-f1()
-{
- local zz
- zz=abcde
- echo $zz
- unset zz
- zz=defghi
- echo $zz
-}
-
-zz=ZZ
-echo $zz
-f1
-echo $zz
-
-unset -f f1
-f1()
-{
- return 5
-}
-
-( f1 )
-echo $?
-
-unset -f f1
-f1()
-{
- sleep 5
- return 5
-}
-
-f1 &
-wait
-echo $?
-
-unset -f f1
-
-f1()
-{
- echo $AVAR
- printenv AVAR
-}
-
-AVAR=AVAR
-echo $AVAR
-f1
-AVAR=foo f1
-echo $AVAR
-
-unset -f f1
-# make sure subshells can do a `return' if we're executing in a function
-f1()
-{
- ( return 5 )
- status=$?
- echo $status
- return $status
-}
-
-f1
-echo $?
-
-declare -F f1 # should print just the name
-declare -f f1 # should print the definition, too
-
-# no functions should be exported, right?
-declare -xF
-declare -xf
-
-# FUNCNAME tests
-func2()
-{
- echo FUNCNAME = $FUNCNAME
-}
-
-func()
-{
- echo before: FUNCNAME = $FUNCNAME
- func2
- echo after: FUNCNAME = $FUNCNAME
-}
-
-echo before: try to assign to FUNCNAME
-FUCNAME=7
-
-echo outside: FUNCNAME = $FUNCNAME
-func
-echo outside2: FUNCNAME = $FUNCNAME
-
-# test exported functions (and cached exportstr)
-zf()
-{
- echo this is zf
-}
-export -f zf
-
-${THIS_SH} -c 'type -t zf'
-${THIS_SH} -c 'type zf'
-
-${THIS_SH} ./func1.sub
-
-# tests for functions whose bodies are not group commands, with and without
-# attached redirections
-${THIS_SH} ./func2.sub
-
-# test for some posix-specific function behavior
-${THIS_SH} ./func3.sub
-
-unset -f myfunction
-myfunction() {
- echo "bad shell function redirection"
-} >> /dev/null
-
-myfunction
-myfunction | cat
-
-segv()
-{
- echo foo | return 5
-}
-
-segv
-echo $?
-
-exit 0
diff --git a/tests/history.tests.save b/tests/history.tests.save
deleted file mode 100644
index 4a218c30..00000000
--- a/tests/history.tests.save
+++ /dev/null
@@ -1,97 +0,0 @@
-trap 'rm /tmp/newhistory' 0
-
-# bad options
-history -x
-# cannot use -r and -w at the same time
-history -r -w /dev/null
-
-# bad option
-fc -v
-
-# all of these should result in an empty history list
-history -c
-history -r /dev/null
-history -n /dev/null
-history -c
-
-HISTFILE=history.list
-HISTCONTROL=ignoreboth
-HISTIGNORE='&:history*:fc*'
-HISTSIZE=32
-
-shopt -s cmdhist
-set -o history
-
-history
-
-fc -l
-fc -nl
-
-fc -lr
-fc -nlr
-
-history -s "echo line for history"
-history
-
-history -p '!!'
-
-fc -nl
-
-HISTFILE=/tmp/newhistory
-history -a
-echo displaying \$HISTFILE after history -a
-cat $HISTFILE
-
-history
-history -w
-cat $HISTFILE
-
-history -s "echo line 2 for history"
-history
-history -p '!e'
-history -p '!!'
-
-# this should show up as one history entry
-for x in one two three
-do
- :
-done
-history
-
-# just a basic test. a full test suite for history expansion should be
-# created
-set -H
-!!
-!e
-
-unset HISTSIZE
-unset HISTFILE
-
-fc -l 4
-fc -l 4 8
-
-fc -l 502
-fc -l one=two three=four 502
-
-history 4
-
-shopt -so history
-shopt -s expand_aliases
-
-alias r="fc -s"
-
-echo aa ab ac
-
-r a=x
-r x=4 b=8
-
-# this had better fail with `no command found'
-r cc
-
-unalias -a
-alias
-
-set +o history
-
-shopt -q -o history
-echo $?
diff --git a/tests/misc/regress/log.orig b/tests/misc/regress/log.orig
deleted file mode 100644
index c1f1e199..00000000
--- a/tests/misc/regress/log.orig
+++ /dev/null
@@ -1,50 +0,0 @@
-:; ./shx
-
-sh:
-<&$fd ok
-nlbq Mon Aug 3 02:45:00 EDT 1992
-bang geoff
-quote 712824302
-setbq defmsgid=<1992Aug3.024502.6176@host>
-bgwait sleep done... wait 6187
-
-
-bash:
-<&$fd ok
-nlbq Mon Aug 3 02:45:09 EDT 1992
-bang geoff
-quote 712824311
-setbq defmsgid=<1992Aug3.024512.6212@host>
-bgwait sleep done... wait 6223
-
-
-ash:
-<&$fd shx1: 4: Syntax error: Bad fd number
-nlbq Mon Aug 3 02:45:19 EDT 1992
-bang geoff
-quote getdate: `"now"' not a valid date
-
-setbq defmsgid=<1992Aug3.` echo 024521
-bgwait sleep done... wait 6241
-
-
-ksh:
-<&$fd ok
-nlbq ./shx: 6248 Memory fault - core dumped
-bang geoff
-quote getdate: `"now"' not a valid date
-
-setbq defmsgid=<1992Aug3.024530.6257@host>
-bgwait no such job: 6265
-wait 6265
-sleep done...
-
-zsh:
-<&$fd ok
-nlbq Mon Aug 3 02:45:36 EDT 1992
-bang shx3: event not found: /s/ [4]
-quote 712824337
-setbq defmsgid=<..6290@host>
-bgwait shx7: unmatched " [9]
-sleep done...
-:;
diff --git a/tests/misc/regress/shx.orig b/tests/misc/regress/shx.orig
deleted file mode 100644
index 4b3bf2b8..00000000
--- a/tests/misc/regress/shx.orig
+++ /dev/null
@@ -1,10 +0,0 @@
-#! /bin/sh
-for cmd in sh bash ash ksh zsh
-do
- echo
- echo $cmd:
- for demo in shx?
- do
- $cmd $demo
- done
-done
diff --git a/tests/new-exp.tests.save1 b/tests/new-exp.tests.save1
deleted file mode 100644
index e0c2702a..00000000
--- a/tests/new-exp.tests.save1
+++ /dev/null
@@ -1,558 +0,0 @@
-# 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~
deleted file mode 100644
index 2d6d8f90..00000000
--- a/tests/new-exp.tests~
+++ /dev/null
@@ -1,558 +0,0 @@
-# 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/quote.tests~ b/tests/quote.tests~
deleted file mode 100644
index ef465ad0..00000000
--- a/tests/quote.tests~
+++ /dev/null
@@ -1,101 +0,0 @@
-echo "Single Quote"
-echo 'foo
-bar'
-echo 'foo
-bar'
-echo 'foo\
-bar'
-
-echo "Double Quote"
-echo "foo
-bar"
-echo "foo
-bar"
-echo "foo\
-bar"
-
-echo "Backslash Single Quote"
-echo `echo 'foo
-bar'`
-echo `echo 'foo
-bar'`
-echo `echo 'foo\
-bar'`
-
-echo "Backslash Double Quote"
-echo `echo "foo
-bar"`
-echo `echo "foo
-bar"`
-echo `echo "foo\
-bar"`
-
-echo "Double Quote Backslash Single Quote"
-echo "`echo 'foo
-bar'`"
-echo "`echo 'foo
-bar'`"
-echo "`echo 'foo\
-bar'`"
-
-echo "Dollar Paren Single Quote"
-echo $(echo 'foo
-bar')
-echo $(echo 'foo
-bar')
-echo $(echo 'foo\
-bar')
-
-echo "Dollar Paren Double Quote"
-echo $(echo "foo
-bar")
-echo $(echo "foo
-bar")
-echo $(echo "foo\
-bar")
-
-echo "Double Quote Dollar Paren Single Quote"
-echo "$(echo 'foo
-bar')"
-echo "$(echo 'foo
-bar')"
-echo "$(echo 'foo\
-bar')"
-
-# old-style command substitution parsing compatibility tests -- post bash-3.1
-recho 'foo \\
-bar'
-
-recho 'foo \
-bar'
-
-echo `recho sed -e 's/[ :]/\\
-/g'`
-
-echo `recho sed -e 's/[ :]/\
-/g'`
-
-echo `recho 'foo\\
-bar'`
-
-echo `recho 'foo\
-bar'`
-
-echo $(recho 'foo\
-bar')
-
-a=`echo 'a b c' | sed 's/ /\\
-/g' | grep 'b'`
-echo $a
-a=`echo 'a b c' | sed 's/ /\\
-/g'`
-echo "$a"
-
-recho `echo 'a\' b`
-
-recho `echo '\$' bab`
-recho `echo '\$foo' bab`
-
-recho `echo '\`' ab`
-
-recho `echo '\\' ab`
diff --git a/tests/tilde.right~ b/tests/tilde.right~
deleted file mode 100644
index b22dabf1..00000000
--- a/tests/tilde.right~
+++ /dev/null
@@ -1,24 +0,0 @@
-~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~
deleted file mode 100644
index f5f53090..00000000
--- a/tests/tilde.tests~
+++ /dev/null
@@ -1,66 +0,0 @@
-# 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~
deleted file mode 100644
index 64cdbd08..00000000
--- a/trap.c~
+++ /dev/null
@@ -1,984 +0,0 @@
-/* trap.c -- Not the trap command, but useful functions for manipulating
- those objects. The trap command is in builtins/trap.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. */
-
-#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
-
-#define GETORIGSIG(sig) \
- do { \
- original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
- set_signal_handler (sig, original_signals[sig]); \
- if (original_signals[sig] == SIG_IGN) \
- sigmodes[sig] |= SIG_HARD_IGNORE; \
- } while (0)
-
-#define GET_ORIGINAL_SIGNAL(sig) \
- if (sig && sig < NSIG && original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER) \
- GETORIGSIG(sig)
-
-void
-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;
-
- 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)
- GETORIGSIG (SIGCHLD);
- sigmodes[SIGCHLD] |= (SIG_SPECIAL | SIG_NO_TRAP);
-#endif /* SIGCHLD */
-
- GETORIGSIG (SIGINT);
- sigmodes[SIGINT] |= SIG_SPECIAL;
-
-#if defined (__BEOS__)
- /* BeOS sets SIGINT to SIG_IGN! */
- original_signals[SIGINT] = SIG_DFL;
- sigmodes[SIGINT] &= ~SIG_HARD_IGNORE;
-#endif
-
- GETORIGSIG (SIGQUIT);
- sigmodes[SIGQUIT] |= SIG_SPECIAL;
-
- if (interactive)
- {
- GETORIGSIG (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, termsig_sighandler));
-}
-
-/* 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)
- GETORIGSIG (sig);
- if (original_signals[sig] == SIG_IGN)
- 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;
-}
-
-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)
- GETORIGSIG (sig);
-}
-
-/* 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 (function_trace_mode == 0)
- {
- sigmodes[DEBUG_TRAP] &= ~SIG_TRAPPED;
- sigmodes[RETURN_TRAP] &= ~SIG_TRAPPED;
- }
- if (error_trace_mode == 0)
- sigmodes[ERROR_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/unwind_prot.c~ b/unwind_prot.c~
deleted file mode 100644
index 4bb7a78f..00000000
--- a/unwind_prot.c~
+++ /dev/null
@@ -1,320 +0,0 @@
-/* I can't stand it anymore! Please can't we just write the
- whole Unix system in lisp or something? */
-
-/* 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. */
-
-/* **************************************************************** */
-/* */
-/* Unwind Protection Scheme for Bash */
-/* */
-/* **************************************************************** */
-#include "config.h"
-
-#include "bashtypes.h"
-#include "bashansi.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if STDC_HEADERS
-# include <stddef.h>
-#endif
-
-#ifndef offsetof
-# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-
-#include "command.h"
-#include "general.h"
-#include "unwind_prot.h"
-#include "quit.h"
-#include "sig.h"
-
-/* Structure describing a saved variable and the value to restore it to. */
-typedef struct {
- char *variable;
- int size;
- char desired_setting[1]; /* actual size is `size' */
-} SAVED_VAR;
-
-/* If HEAD.CLEANUP is null, then ARG.V contains a tag to throw back to.
- If HEAD.CLEANUP is restore_variable, then SV.V contains the saved
- variable. Otherwise, call HEAD.CLEANUP (ARG.V) to clean up. */
-typedef union uwp {
- struct uwp_head {
- union uwp *next;
- Function *cleanup;
- } head;
- struct {
- struct uwp_head uwp_head;
- char *v;
- } arg;
- struct {
- struct uwp_head uwp_head;
- SAVED_VAR v;
- } sv;
-} UNWIND_ELT;
-
-
-extern int interrupt_immediately;
-
-static void without_interrupts __P((VFunction *, char *, char *));
-static void unwind_frame_discard_internal __P((char *, char *));
-static void unwind_frame_run_internal __P((char *, char *));
-static void add_unwind_protect_internal __P((Function *, char *));
-static void remove_unwind_protect_internal __P((char *, char *));
-static void run_unwind_protects_internal __P((char *, char *));
-static void clear_unwind_protects_internal __P((char *, char *));
-static inline void restore_variable __P((SAVED_VAR *));
-static void unwind_protect_mem_internal __P((char *, char *));
-
-static UNWIND_ELT *unwind_protect_list = (UNWIND_ELT *)NULL;
-
-#define uwpalloc(elt) (elt) = (UNWIND_ELT *)xmalloc (sizeof (UNWIND_ELT))
-#define uwpfree(elt) free(elt)
-
-/* Run a function without interrupts. This relies on the fact that the
- FUNCTION cannot change the value of interrupt_immediately. (I.e., does
- not call QUIT (). */
-static void
-without_interrupts (function, arg1, arg2)
- VFunction *function;
- char *arg1, *arg2;
-{
- int old_interrupt_immediately;
-
- old_interrupt_immediately = interrupt_immediately;
- interrupt_immediately = 0;
-
- (*function)(arg1, arg2);
-
- interrupt_immediately = old_interrupt_immediately;
-}
-
-/* Start the beginning of a region. */
-void
-begin_unwind_frame (tag)
- char *tag;
-{
- add_unwind_protect ((Function *)NULL, tag);
-}
-
-/* Discard the unwind protects back to TAG. */
-void
-discard_unwind_frame (tag)
- char *tag;
-{
- if (unwind_protect_list)
- without_interrupts (unwind_frame_discard_internal, tag, (char *)NULL);
-}
-
-/* Run the unwind protects back to TAG. */
-void
-run_unwind_frame (tag)
- char *tag;
-{
- if (unwind_protect_list)
- without_interrupts (unwind_frame_run_internal, tag, (char *)NULL);
-}
-
-/* Add the function CLEANUP with ARG to the list of unwindable things. */
-void
-add_unwind_protect (cleanup, arg)
- Function *cleanup;
- char *arg;
-{
- without_interrupts (add_unwind_protect_internal, (char *)cleanup, arg);
-}
-
-/* Remove the top unwind protect from the list. */
-void
-remove_unwind_protect ()
-{
- if (unwind_protect_list)
- without_interrupts
- (remove_unwind_protect_internal, (char *)NULL, (char *)NULL);
-}
-
-/* Run the list of cleanup functions in unwind_protect_list. */
-void
-run_unwind_protects ()
-{
- if (unwind_protect_list)
- without_interrupts
- (run_unwind_protects_internal, (char *)NULL, (char *)NULL);
-}
-
-/* Erase the unwind-protect list. If flags is 1, free the elements. */
-void
-clear_unwind_protect_list (flags)
- int flags;
-{
- char *flag;
-
- if (unwind_protect_list)
- {
- flag = flags ? "" : (char *)NULL;
- without_interrupts
- (clear_unwind_protects_internal, flag, (char *)NULL);
- }
-}
-
-/* **************************************************************** */
-/* */
-/* The Actual Functions */
-/* */
-/* **************************************************************** */
-
-static void
-add_unwind_protect_internal (cleanup, arg)
- Function *cleanup;
- char *arg;
-{
- UNWIND_ELT *elt;
-
- uwpalloc (elt);
- elt->head.next = unwind_protect_list;
- elt->head.cleanup = cleanup;
- elt->arg.v = arg;
- unwind_protect_list = elt;
-}
-
-static void
-remove_unwind_protect_internal (ignore1, ignore2)
- char *ignore1, *ignore2;
-{
- UNWIND_ELT *elt;
-
- elt = unwind_protect_list;
- if (elt)
- {
- unwind_protect_list = unwind_protect_list->head.next;
- uwpfree (elt);
- }
-}
-
-static void
-run_unwind_protects_internal (ignore1, ignore2)
- char *ignore1, *ignore2;
-{
- unwind_frame_run_internal ((char *) NULL, (char *) NULL);
-}
-
-static void
-clear_unwind_protects_internal (flag, ignore)
- char *flag, *ignore;
-{
- if (flag)
- {
- while (unwind_protect_list)
- remove_unwind_protect_internal ((char *)NULL, (char *)NULL);
- }
- unwind_protect_list = (UNWIND_ELT *)NULL;
-}
-
-static void
-unwind_frame_discard_internal (tag, ignore)
- char *tag, *ignore;
-{
- UNWIND_ELT *elt;
-
- while (elt = unwind_protect_list)
- {
- unwind_protect_list = unwind_protect_list->head.next;
- if (elt->head.cleanup == 0 && (STREQ (elt->arg.v, tag)))
- {
- uwpfree (elt);
- break;
- }
- else
- uwpfree (elt);
- }
-}
-
-/* Restore the value of a variable, based on the contents of SV.
- sv->desired_setting is a block of memory SIZE bytes long holding the
- value itself. This block of memory is copied back into the variable. */
-static inline void
-restore_variable (sv)
- SAVED_VAR *sv;
-{
- FASTCOPY (sv->desired_setting, sv->variable, sv->size);
-}
-
-static void
-unwind_frame_run_internal (tag, ignore)
- char *tag, *ignore;
-{
- UNWIND_ELT *elt;
-
- while (elt = unwind_protect_list)
- {
- unwind_protect_list = elt->head.next;
-
- /* If tag, then compare. */
- if (!elt->head.cleanup)
- {
- if (tag && STREQ (elt->arg.v, tag))
- {
- uwpfree (elt);
- break;
- }
- }
- else
- {
- if (elt->head.cleanup == (Function *) restore_variable)
- restore_variable (&elt->sv.v);
- else
- (*(elt->head.cleanup)) (elt->arg.v);
- }
-
- uwpfree (elt);
- }
-}
-
-static void
-unwind_protect_mem_internal (var, psize)
- char *var;
- char *psize;
-{
- int size, allocated;
- UNWIND_ELT *elt;
-
- size = *(int *) psize;
- allocated = size + offsetof (UNWIND_ELT, sv.v.desired_setting[0]);
- elt = (UNWIND_ELT *)xmalloc (allocated);
- elt->head.next = unwind_protect_list;
- elt->head.cleanup = (Function *) restore_variable;
- elt->sv.v.variable = var;
- elt->sv.v.size = size;
- FASTCOPY (var, elt->sv.v.desired_setting, size);
- unwind_protect_list = elt;
-}
-
-/* Save the value of a variable so it will be restored when unwind-protects
- are run. VAR is a pointer to the variable. SIZE is the size in
- bytes of VAR. */
-void
-unwind_protect_mem (var, size)
- char *var;
- int size;
-{
- without_interrupts (unwind_protect_mem_internal, var, (char *) &size);
-}
diff --git a/variables.c~ b/variables.c~
deleted file mode 100644
index c2373265..00000000
--- a/variables.c~
+++ /dev/null
@@ -1,4267 +0,0 @@
-/* variables.c -- Functions for hacking shell variables. */
-
-/* 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 "posixstat.h"
-#include "posixtime.h"
-
-#if defined (qnx)
-# if defined (qnx6)
-# include <sy/netmgr.h>
-# else
-# include <sys/vc.h>
-# endif /* !qnx6 */
-#endif /* qnx */
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include "chartypes.h"
-#include <pwd.h>
-#include "bashansi.h"
-#include "bashintl.h"
-
-#include "shell.h"
-#include "flags.h"
-#include "execute_cmd.h"
-#include "findcmd.h"
-#include "mailcheck.h"
-#include "input.h"
-#include "hashcmd.h"
-#include "pathexp.h"
-
-#include "builtins/getopt.h"
-#include "builtins/common.h"
-
-#if defined (READLINE)
-# include "bashline.h"
-# include <readline/readline.h>
-#else
-# include <tilde/tilde.h>
-#endif
-
-#if defined (HISTORY)
-# include "bashhist.h"
-# include <readline/history.h>
-#endif /* HISTORY */
-
-#if defined (PROGRAMMABLE_COMPLETION)
-# include "pcomplete.h"
-#endif
-
-#define TEMPENV_HASH_BUCKETS 4 /* must be power of two */
-
-#define ifsname(s) ((s)[0] == 'I' && (s)[1] == 'F' && (s)[2] == 'S' && (s)[3] == '\0')
-
-extern char **environ;
-
-/* Variables used here and defined in other files. */
-extern int posixly_correct;
-extern int line_number;
-extern int subshell_environment, indirection_level, subshell_level;
-extern int build_version, patch_level;
-extern int expanding_redir;
-extern char *dist_version, *release_status;
-extern char *shell_name;
-extern char *primary_prompt, *secondary_prompt;
-extern char *current_host_name;
-extern sh_builtin_func_t *this_shell_builtin;
-extern SHELL_VAR *this_shell_function;
-extern char *the_printed_command_except_trap;
-extern char *this_command_name;
-extern char *command_execution_string;
-extern time_t shell_start_time;
-
-#if defined (READLINE)
-extern int no_line_editing;
-extern int perform_hostname_completion;
-#endif
-
-/* The list of shell variables that the user has created at the global
- scope, or that came from the environment. */
-VAR_CONTEXT *global_variables = (VAR_CONTEXT *)NULL;
-
-/* The current list of shell variables, including function scopes */
-VAR_CONTEXT *shell_variables = (VAR_CONTEXT *)NULL;
-
-/* The list of shell functions that the user has created, or that came from
- the environment. */
-HASH_TABLE *shell_functions = (HASH_TABLE *)NULL;
-
-#if defined (DEBUGGER)
-/* The table of shell function definitions that the user defined or that
- came from the environment. */
-HASH_TABLE *shell_function_defs = (HASH_TABLE *)NULL;
-#endif
-
-/* The current variable context. This is really a count of how deep into
- executing functions we are. */
-int variable_context = 0;
-
-/* The set of shell assignments which are made only in the environment
- for a single command. */
-HASH_TABLE *temporary_env = (HASH_TABLE *)NULL;
-
-/* Set to non-zero if an assignment error occurs while putting variables
- into the temporary environment. */
-int tempenv_assign_error;
-
-/* Some funky variables which are known about specially. Here is where
- "$*", "$1", and all the cruft is kept. */
-char *dollar_vars[10];
-WORD_LIST *rest_of_args = (WORD_LIST *)NULL;
-
-/* The value of $$. */
-pid_t dollar_dollar_pid;
-
-/* An array which is passed to commands as their environment. It is
- manufactured from the union of the initial environment and the
- shell variables that are marked for export. */
-char **export_env = (char **)NULL;
-static int export_env_index;
-static int export_env_size;
-
-#if defined (READLINE)
-static int winsize_assignment; /* currently assigning to LINES or COLUMNS */
-static int winsize_assigned; /* assigned to LINES or COLUMNS */
-#endif
-
-/* Non-zero means that we have to remake EXPORT_ENV. */
-int array_needs_making = 1;
-
-/* The number of times BASH has been executed. This is set
- by initialize_variables (). */
-int shell_level = 0;
-
-/* Some forward declarations. */
-static void create_variable_tables __P((void));
-
-static void set_machine_vars __P((void));
-static void set_home_var __P((void));
-static void set_shell_var __P((void));
-static char *get_bash_name __P((void));
-static void initialize_shell_level __P((void));
-static void uidset __P((void));
-#if defined (ARRAY_VARS)
-static void make_vers_array __P((void));
-#endif
-
-static SHELL_VAR *null_assign __P((SHELL_VAR *, char *, arrayind_t));
-#if defined (ARRAY_VARS)
-static SHELL_VAR *null_array_assign __P((SHELL_VAR *, char *, arrayind_t));
-#endif
-static SHELL_VAR *get_self __P((SHELL_VAR *));
-
-#if defined (ARRAY_VARS)
-static SHELL_VAR *init_dynamic_array_var __P((char *, sh_var_value_func_t *, sh_var_assign_func_t *, int));
-#endif
-
-static SHELL_VAR *assign_seconds __P((SHELL_VAR *, char *, arrayind_t));
-static SHELL_VAR *get_seconds __P((SHELL_VAR *));
-static SHELL_VAR *init_seconds_var __P((void));
-
-static int brand __P((void));
-static void sbrand __P((unsigned long)); /* set bash random number generator. */
-static SHELL_VAR *assign_random __P((SHELL_VAR *, char *, arrayind_t));
-static SHELL_VAR *get_random __P((SHELL_VAR *));
-
-static SHELL_VAR *assign_lineno __P((SHELL_VAR *, char *, arrayind_t));
-static SHELL_VAR *get_lineno __P((SHELL_VAR *));
-
-static SHELL_VAR *assign_subshell __P((SHELL_VAR *, char *, arrayind_t));
-static SHELL_VAR *get_subshell __P((SHELL_VAR *));
-
-#if defined (HISTORY)
-static SHELL_VAR *get_histcmd __P((SHELL_VAR *));
-#endif
-
-#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
-static SHELL_VAR *assign_dirstack __P((SHELL_VAR *, char *, arrayind_t));
-static SHELL_VAR *get_dirstack __P((SHELL_VAR *));
-#endif
-
-#if defined (ARRAY_VARS)
-static SHELL_VAR *get_groupset __P((SHELL_VAR *));
-#endif
-
-static SHELL_VAR *get_funcname __P((SHELL_VAR *));
-static SHELL_VAR *init_funcname_var __P((void));
-
-static void initialize_dynamic_variables __P((void));
-
-static SHELL_VAR *hash_lookup __P((const char *, HASH_TABLE *));
-static SHELL_VAR *new_shell_variable __P((const char *));
-static SHELL_VAR *make_new_variable __P((const char *, HASH_TABLE *));
-static SHELL_VAR *bind_variable_internal __P((const char *, char *, HASH_TABLE *, int, int));
-
-static void free_variable_hash_data __P((PTR_T));
-
-static VARLIST *vlist_alloc __P((int));
-static VARLIST *vlist_realloc __P((VARLIST *, int));
-static void vlist_add __P((VARLIST *, SHELL_VAR *, int));
-
-static void flatten __P((HASH_TABLE *, sh_var_map_func_t *, VARLIST *, int));
-
-static int qsort_var_comp __P((SHELL_VAR **, SHELL_VAR **));
-
-static SHELL_VAR **vapply __P((sh_var_map_func_t *));
-static SHELL_VAR **fapply __P((sh_var_map_func_t *));
-
-static int visible_var __P((SHELL_VAR *));
-static int visible_and_exported __P((SHELL_VAR *));
-static int local_and_exported __P((SHELL_VAR *));
-static int variable_in_context __P((SHELL_VAR *));
-#if defined (ARRAY_VARS)
-static int visible_array_vars __P((SHELL_VAR *));
-#endif
-
-static SHELL_VAR *bind_tempenv_variable __P((const char *, char *));
-static void push_temp_var __P((PTR_T));
-static void propagate_temp_var __P((PTR_T));
-static void dispose_temporary_env __P((sh_free_func_t *));
-
-static inline char *mk_env_string __P((const char *, const char *));
-static char **make_env_array_from_var_list __P((SHELL_VAR **));
-static char **make_var_export_array __P((VAR_CONTEXT *));
-static char **make_func_export_array __P((void));
-static void add_temp_array_to_env __P((char **, int, int));
-
-static int n_shell_variables __P((void));
-static int set_context __P((SHELL_VAR *));
-
-static void push_func_var __P((PTR_T));
-static void push_exported_var __P((PTR_T));
-
-static inline int find_special_var __P((const char *));
-
-static void
-create_variable_tables ()
-{
- if (shell_variables == 0)
- {
- shell_variables = global_variables = new_var_context ((char *)NULL, 0);
- shell_variables->scope = 0;
- shell_variables->table = hash_create (0);
- }
-
- if (shell_functions == 0)
- shell_functions = hash_create (0);
-
-#if defined (DEBUGGER)
- if (shell_function_defs == 0)
- shell_function_defs = hash_create (0);
-#endif
-}
-
-/* Initialize the shell variables from the current environment.
- If PRIVMODE is nonzero, don't import functions from ENV or
- parse $SHELLOPTS. */
-void
-initialize_shell_variables (env, privmode)
- char **env;
- int privmode;
-{
- char *name, *string, *temp_string;
- int c, char_index, string_index, string_length;
- SHELL_VAR *temp_var;
-
- create_variable_tables ();
-
- for (string_index = 0; string = env[string_index++]; )
- {
- char_index = 0;
- name = string;
- while ((c = *string++) && c != '=')
- ;
- if (string[-1] == '=')
- char_index = string - name - 1;
-
- /* If there are weird things in the environment, like `=xxx' or a
- string without an `=', just skip them. */
- if (char_index == 0)
- continue;
-
- /* ASSERT(name[char_index] == '=') */
- name[char_index] = '\0';
- /* Now, name = env variable name, string = env variable value, and
- char_index == strlen (name) */
-
- /* If exported function, define it now. Don't import functions from
- the environment in privileged mode. */
- if (privmode == 0 && read_but_dont_execute == 0 && STREQN ("() {", string, 4))
- {
- string_length = strlen (string);
- temp_string = (char *)xmalloc (3 + string_length + char_index);
-
- strcpy (temp_string, name);
- temp_string[char_index] = ' ';
- strcpy (temp_string + char_index + 1, string);
-
- parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
-
- /* Ancient backwards compatibility. Old versions of bash exported
- functions like name()=() {...} */
- if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
- name[char_index - 2] = '\0';
-
- if (temp_var = find_function (name))
- {
- VSETATTR (temp_var, (att_exported|att_imported));
- array_needs_making = 1;
- }
- else
- report_error (_("error importing function definition for `%s'"), name);
-
- /* ( */
- if (name[char_index - 1] == ')' && name[char_index - 2] == '\0')
- name[char_index - 2] = '('; /* ) */
- }
-#if defined (ARRAY_VARS)
-# if 0
- /* Array variables may not yet be exported. */
- else if (*string == '(' && string[1] == '[' && string[strlen (string) - 1] == ')')
- {
- string_length = 1;
- temp_string = extract_array_assignment_list (string, &string_length);
- temp_var = assign_array_from_string (name, temp_string);
- FREE (temp_string);
- VSETATTR (temp_var, (att_exported | att_imported));
- array_needs_making = 1;
- }
-# endif
-#endif
- else
- {
- temp_var = bind_variable (name, string, 0);
- VSETATTR (temp_var, (att_exported | att_imported));
- array_needs_making = 1;
- }
-
- name[char_index] = '=';
- /* temp_var can be NULL if it was an exported function with a syntax
- error (a different bug, but it still shouldn't dump core). */
- if (temp_var && function_p (temp_var) == 0) /* XXX not yet */
- {
- CACHE_IMPORTSTR (temp_var, name);
- }
- }
-
- set_pwd ();
-
- /* Set up initial value of $_ */
- temp_var = set_if_not ("_", dollar_vars[0]);
-
- /* Remember this pid. */
- dollar_dollar_pid = getpid ();
-
- /* Now make our own defaults in case the vars that we think are
- important are missing. */
- temp_var = set_if_not ("PATH", DEFAULT_PATH_VALUE);
-#if 0
- set_auto_export (temp_var); /* XXX */
-#endif
-
- temp_var = set_if_not ("TERM", "dumb");
-#if 0
- set_auto_export (temp_var); /* XXX */
-#endif
-
-#if defined (qnx)
- /* set node id -- don't import it from the environment */
- {
- char node_name[22];
-# if defined (qnx6)
- netmgr_ndtostr(ND2S_LOCAL_STR, ND_LOCAL_NODE, node_name, sizeof(node_name));
-# else
- qnx_nidtostr (getnid (), node_name, sizeof (node_name));
-# endif
- temp_var = bind_variable ("NODE", node_name, 0);
- set_auto_export (temp_var);
- }
-#endif
-
- /* set up the prompts. */
- if (interactive_shell)
- {
-#if defined (PROMPT_STRING_DECODE)
- set_if_not ("PS1", primary_prompt);
-#else
- if (current_user.uid == -1)
- get_current_user_info ();
- set_if_not ("PS1", current_user.euid == 0 ? "# " : primary_prompt);
-#endif
- set_if_not ("PS2", secondary_prompt);
- }
- set_if_not ("PS4", "+ ");
-
- /* Don't allow IFS to be imported from the environment. */
- temp_var = bind_variable ("IFS", " \t\n", 0);
- setifs (temp_var);
-
- /* Magic machine types. Pretty convenient. */
- set_machine_vars ();
-
- /* Default MAILCHECK for interactive shells. Defer the creation of a
- default MAILPATH until the startup files are read, because MAIL
- names a mail file if MAILPATH is not set, and we should provide a
- default only if neither is set. */
- if (interactive_shell)
- {
- temp_var = set_if_not ("MAILCHECK", posixly_correct ? "600" : "60");
- VSETATTR (temp_var, att_integer);
- }
-
- /* Do some things with shell level. */
- initialize_shell_level ();
-
- set_ppid ();
-
- /* Initialize the `getopts' stuff. */
- temp_var = bind_variable ("OPTIND", "1", 0);
- VSETATTR (temp_var, att_integer);
- getopts_reset (0);
- bind_variable ("OPTERR", "1", 0);
- sh_opterr = 1;
-
- if (login_shell == 1 && posixly_correct == 0)
- set_home_var ();
-
- /* Get the full pathname to THIS shell, and set the BASH variable
- to it. */
- name = get_bash_name ();
- temp_var = bind_variable ("BASH", name, 0);
- free (name);
-
- /* Make the exported environment variable SHELL be the user's login
- shell. Note that the `tset' command looks at this variable
- to determine what style of commands to output; if it ends in "csh",
- then C-shell commands are output, else Bourne shell commands. */
- set_shell_var ();
-
- /* Make a variable called BASH_VERSION which contains the version info. */
- bind_variable ("BASH_VERSION", shell_version_string (), 0);
-#if defined (ARRAY_VARS)
- make_vers_array ();
-#endif
-
- if (command_execution_string)
- bind_variable ("BASH_EXECUTION_STRING", command_execution_string, 0);
-
- /* Find out if we're supposed to be in Posix.2 mode via an
- environment variable. */
- temp_var = find_variable ("POSIXLY_CORRECT");
- if (!temp_var)
- temp_var = find_variable ("POSIX_PEDANTIC");
- if (temp_var && imported_p (temp_var))
- sv_strict_posix (temp_var->name);
-
-#if defined (HISTORY)
- /* Set history variables to defaults, and then do whatever we would
- do if the variable had just been set. Do this only in the case
- that we are remembering commands on the history list. */
- if (remember_on_history)
- {
- name = bash_tilde_expand (posixly_correct ? "~/.sh_history" : "~/.bash_history", 0);
-
- set_if_not ("HISTFILE", name);
- free (name);
-
-#if 0
- set_if_not ("HISTSIZE", "500");
- sv_histsize ("HISTSIZE");
-#endif
- }
-#endif /* HISTORY */
-
- /* Seed the random number generator. */
- sbrand (dollar_dollar_pid + shell_start_time);
-
- /* Handle some "special" variables that we may have inherited from a
- parent shell. */
- if (interactive_shell)
- {
- temp_var = find_variable ("IGNOREEOF");
- if (!temp_var)
- temp_var = find_variable ("ignoreeof");
- if (temp_var && imported_p (temp_var))
- sv_ignoreeof (temp_var->name);
- }
-
-#if defined (HISTORY)
- if (interactive_shell && remember_on_history)
- {
- sv_history_control ("HISTCONTROL");
- sv_histignore ("HISTIGNORE");
- }
-#endif /* HISTORY */
-
-#if defined (READLINE) && defined (STRICT_POSIX)
- /* POSIXLY_CORRECT will only be 1 here if the shell was compiled
- -DSTRICT_POSIX */
- if (interactive_shell && posixly_correct && no_line_editing == 0)
- rl_prefer_env_winsize = 1;
-#endif /* READLINE && STRICT_POSIX */
-
- /*
- * 24 October 2001
- *
- * I'm tired of the arguing and bug reports. Bash now leaves SSH_CLIENT
- * and SSH2_CLIENT alone. I'm going to rely on the shell_level check in
- * isnetconn() to avoid running the startup files more often than wanted.
- * That will, of course, only work if the user's login shell is bash, so
- * I've made that behavior conditional on SSH_SOURCE_BASHRC being defined
- * in config-top.h.
- */
-#if 0
- temp_var = find_variable ("SSH_CLIENT");
- if (temp_var && imported_p (temp_var))
- {
- VUNSETATTR (temp_var, att_exported);
- array_needs_making = 1;
- }
- temp_var = find_variable ("SSH2_CLIENT");
- if (temp_var && imported_p (temp_var))
- {
- VUNSETATTR (temp_var, att_exported);
- array_needs_making = 1;
- }
-#endif
-
- /* Get the user's real and effective user ids. */
- uidset ();
-
- /* Initialize the dynamic variables, and seed their values. */
- initialize_dynamic_variables ();
-}
-
-/* **************************************************************** */
-/* */
-/* Setting values for special shell variables */
-/* */
-/* **************************************************************** */
-
-static void
-set_machine_vars ()
-{
- SHELL_VAR *temp_var;
-
- temp_var = set_if_not ("HOSTTYPE", HOSTTYPE);
- temp_var = set_if_not ("OSTYPE", OSTYPE);
- temp_var = set_if_not ("MACHTYPE", MACHTYPE);
-
- temp_var = set_if_not ("HOSTNAME", current_host_name);
-}
-
-/* Set $HOME to the information in the password file if we didn't get
- it from the environment. */
-
-/* This function is not static so the tilde and readline libraries can
- use it. */
-char *
-sh_get_home_dir ()
-{
- if (current_user.home_dir == 0)
- get_current_user_info ();
- return current_user.home_dir;
-}
-
-static void
-set_home_var ()
-{
- SHELL_VAR *temp_var;
-
- temp_var = find_variable ("HOME");
- if (temp_var == 0)
- temp_var = bind_variable ("HOME", sh_get_home_dir (), 0);
-#if 0
- VSETATTR (temp_var, att_exported);
-#endif
-}
-
-/* Set $SHELL to the user's login shell if it is not already set. Call
- get_current_user_info if we haven't already fetched the shell. */
-static void
-set_shell_var ()
-{
- SHELL_VAR *temp_var;
-
- temp_var = find_variable ("SHELL");
- if (temp_var == 0)
- {
- if (current_user.shell == 0)
- get_current_user_info ();
- temp_var = bind_variable ("SHELL", current_user.shell, 0);
- }
-#if 0
- VSETATTR (temp_var, att_exported);
-#endif
-}
-
-static char *
-get_bash_name ()
-{
- char *name;
-
- if ((login_shell == 1) && RELPATH(shell_name))
- {
- if (current_user.shell == 0)
- get_current_user_info ();
- name = savestring (current_user.shell);
- }
- else if (ABSPATH(shell_name))
- name = savestring (shell_name);
- else if (shell_name[0] == '.' && shell_name[1] == '/')
- {
- /* Fast path for common case. */
- char *cdir;
- int len;
-
- cdir = get_string_value ("PWD");
- if (cdir)
- {
- len = strlen (cdir);
- name = (char *)xmalloc (len + strlen (shell_name) + 1);
- strcpy (name, cdir);
- strcpy (name + len, shell_name + 1);
- }
- else
- name = savestring (shell_name);
- }
- else
- {
- char *tname;
- int s;
-
- tname = find_user_command (shell_name);
-
- if (tname == 0)
- {
- /* Try the current directory. If there is not an executable
- there, just punt and use the login shell. */
- s = file_status (shell_name);
- if (s & FS_EXECABLE)
- {
- tname = make_absolute (shell_name, get_string_value ("PWD"));
- if (*shell_name == '.')
- {
- name = sh_canonpath (tname, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
- if (name == 0)
- name = tname;
- else
- free (tname);
- }
- else
- name = tname;
- }
- else
- {
- if (current_user.shell == 0)
- get_current_user_info ();
- name = savestring (current_user.shell);
- }
- }
- else
- {
- name = full_pathname (tname);
- free (tname);
- }
- }
-
- return (name);
-}
-
-void
-adjust_shell_level (change)
- int change;
-{
- char new_level[5], *old_SHLVL;
- intmax_t old_level;
- SHELL_VAR *temp_var;
-
- old_SHLVL = get_string_value ("SHLVL");
- if (old_SHLVL == 0 || *old_SHLVL == '\0' || legal_number (old_SHLVL, &old_level) == 0)
- old_level = 0;
-
- shell_level = old_level + change;
- if (shell_level < 0)
- shell_level = 0;
- else if (shell_level > 1000)
- {
- internal_warning (_("shell level (%d) too high, resetting to 1"), shell_level);
- shell_level = 1;
- }
-
- /* We don't need the full generality of itos here. */
- if (shell_level < 10)
- {
- new_level[0] = shell_level + '0';
- new_level[1] = '\0';
- }
- else if (shell_level < 100)
- {
- new_level[0] = (shell_level / 10) + '0';
- new_level[1] = (shell_level % 10) + '0';
- new_level[2] = '\0';
- }
- else if (shell_level < 1000)
- {
- new_level[0] = (shell_level / 100) + '0';
- old_level = shell_level % 100;
- new_level[1] = (old_level / 10) + '0';
- new_level[2] = (old_level % 10) + '0';
- new_level[3] = '\0';
- }
-
- temp_var = bind_variable ("SHLVL", new_level, 0);
- set_auto_export (temp_var);
-}
-
-static void
-initialize_shell_level ()
-{
- adjust_shell_level (1);
-}
-
-/* If we got PWD from the environment, update our idea of the current
- working directory. In any case, make sure that PWD exists before
- checking it. It is possible for getcwd () to fail on shell startup,
- and in that case, PWD would be undefined. If this is an interactive
- login shell, see if $HOME is the current working directory, and if
- that's not the same string as $PWD, set PWD=$HOME. */
-
-void
-set_pwd ()
-{
- SHELL_VAR *temp_var, *home_var;
- char *temp_string, *home_string;
-
- home_var = find_variable ("HOME");
- home_string = home_var ? value_cell (home_var) : (char *)NULL;
-
- temp_var = find_variable ("PWD");
- if (temp_var && imported_p (temp_var) &&
- (temp_string = value_cell (temp_var)) &&
- same_file (temp_string, ".", (struct stat *)NULL, (struct stat *)NULL))
- set_working_directory (temp_string);
- else if (home_string && interactive_shell && login_shell &&
- same_file (home_string, ".", (struct stat *)NULL, (struct stat *)NULL))
- {
- set_working_directory (home_string);
- temp_var = bind_variable ("PWD", home_string, 0);
- set_auto_export (temp_var);
- }
- else
- {
- temp_string = get_working_directory ("shell-init");
- if (temp_string)
- {
- temp_var = bind_variable ("PWD", temp_string, 0);
- set_auto_export (temp_var);
- free (temp_string);
- }
- }
-
- /* According to the Single Unix Specification, v2, $OLDPWD is an
- `environment variable' and therefore should be auto-exported.
- Make a dummy invisible variable for OLDPWD, and mark it as exported. */
- temp_var = bind_variable ("OLDPWD", (char *)NULL, 0);
- VSETATTR (temp_var, (att_exported | att_invisible));
-}
-
-/* Make a variable $PPID, which holds the pid of the shell's parent. */
-void
-set_ppid ()
-{
- char namebuf[INT_STRLEN_BOUND(pid_t) + 1], *name;
- SHELL_VAR *temp_var;
-
- name = inttostr (getppid (), namebuf, sizeof(namebuf));
- temp_var = find_variable ("PPID");
- if (temp_var)
- VUNSETATTR (temp_var, (att_readonly | att_exported));
- temp_var = bind_variable ("PPID", name, 0);
- VSETATTR (temp_var, (att_readonly | att_integer));
-}
-
-static void
-uidset ()
-{
- char buff[INT_STRLEN_BOUND(uid_t) + 1], *b;
- register SHELL_VAR *v;
-
- b = inttostr (current_user.uid, buff, sizeof (buff));
- v = find_variable ("UID");
- if (v == 0)
- {
- v = bind_variable ("UID", b, 0);
- VSETATTR (v, (att_readonly | att_integer));
- }
-
- if (current_user.euid != current_user.uid)
- b = inttostr (current_user.euid, buff, sizeof (buff));
-
- v = find_variable ("EUID");
- if (v == 0)
- {
- v = bind_variable ("EUID", b, 0);
- VSETATTR (v, (att_readonly | att_integer));
- }
-}
-
-#if defined (ARRAY_VARS)
-static void
-make_vers_array ()
-{
- SHELL_VAR *vv;
- ARRAY *av;
- char *s, d[32], b[INT_STRLEN_BOUND(int) + 1];
-
- unbind_variable ("BASH_VERSINFO");
-
- vv = make_new_array_variable ("BASH_VERSINFO");
- av = array_cell (vv);
- strcpy (d, dist_version);
- s = xstrchr (d, '.');
- if (s)
- *s++ = '\0';
- array_insert (av, 0, d);
- array_insert (av, 1, s);
- s = inttostr (patch_level, b, sizeof (b));
- array_insert (av, 2, s);
- s = inttostr (build_version, b, sizeof (b));
- array_insert (av, 3, s);
- array_insert (av, 4, release_status);
- array_insert (av, 5, MACHTYPE);
-
- VSETATTR (vv, att_readonly);
-}
-#endif /* ARRAY_VARS */
-
-/* Set the environment variables $LINES and $COLUMNS in response to
- a window size change. */
-void
-sh_set_lines_and_columns (lines, cols)
- int 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);
-
- v = inttostr (cols, val, sizeof (val));
- bind_variable ("COLUMNS", v, 0);
-}
-
-/* **************************************************************** */
-/* */
-/* Printing variables and values */
-/* */
-/* **************************************************************** */
-
-/* Print LIST (a list of shell variables) to stdout in such a way that
- they can be read back in. */
-void
-print_var_list (list)
- register SHELL_VAR **list;
-{
- register int i;
- register SHELL_VAR *var;
-
- for (i = 0; list && (var = list[i]); i++)
- if (invisible_p (var) == 0)
- print_assignment (var);
-}
-
-/* Print LIST (a list of shell functions) to stdout in such a way that
- they can be read back in. */
-void
-print_func_list (list)
- register SHELL_VAR **list;
-{
- register int i;
- register SHELL_VAR *var;
-
- for (i = 0; list && (var = list[i]); i++)
- {
- printf ("%s ", var->name);
- print_var_function (var);
- printf ("\n");
- }
-}
-
-/* Print the value of a single SHELL_VAR. No newline is
- output, but the variable is printed in such a way that
- it can be read back in. */
-void
-print_assignment (var)
- SHELL_VAR *var;
-{
- if (var_isset (var) == 0)
- return;
-
- if (function_p (var))
- {
- printf ("%s", var->name);
- print_var_function (var);
- printf ("\n");
- }
-#if defined (ARRAY_VARS)
- else if (array_p (var))
- print_array_assignment (var, 0);
-#endif /* ARRAY_VARS */
- else
- {
- printf ("%s=", var->name);
- print_var_value (var, 1);
- printf ("\n");
- }
-}
-
-/* Print the value cell of VAR, a shell variable. Do not print
- the name, nor leading/trailing newline. If QUOTE is non-zero,
- and the value contains shell metacharacters, quote the value
- in such a way that it can be read back in. */
-void
-print_var_value (var, quote)
- SHELL_VAR *var;
- int quote;
-{
- char *t;
-
- if (var_isset (var) == 0)
- return;
-
- if (quote && posixly_correct == 0 && ansic_shouldquote (value_cell (var)))
- {
- t = ansic_quote (value_cell (var), 0, (int *)0);
- printf ("%s", t);
- free (t);
- }
- else if (quote && sh_contains_shell_metas (value_cell (var)))
- {
- t = sh_single_quote (value_cell (var));
- printf ("%s", t);
- free (t);
- }
- else
- printf ("%s", value_cell (var));
-}
-
-/* Print the function cell of VAR, a shell variable. Do not
- print the name, nor leading/trailing newline. */
-void
-print_var_function (var)
- SHELL_VAR *var;
-{
- if (function_p (var) && var_isset (var))
- printf ("%s", named_function_string ((char *)NULL, function_cell(var), 1));
-}
-
-/* **************************************************************** */
-/* */
-/* Dynamic Variables */
-/* */
-/* **************************************************************** */
-
-/* DYNAMIC VARIABLES
-
- These are variables whose values are generated anew each time they are
- referenced. These are implemented using a pair of function pointers
- in the struct variable: assign_func, which is called from bind_variable
- and, if arrays are compiled into the shell, some of the functions in
- arrayfunc.c, and dynamic_value, which is called from find_variable.
-
- assign_func is called from bind_variable_internal, if
- bind_variable_internal discovers that the variable being assigned to
- has such a function. The function is called as
- SHELL_VAR *temp = (*(entry->assign_func)) (entry, value, ind)
- and the (SHELL_VAR *)temp is returned as the value of bind_variable. It
- is usually ENTRY (self). IND is an index for an array variable, and
- unused otherwise.
-
- dynamic_value is called from find_variable_internal to return a `new'
- value for the specified dynamic varible. If this function is NULL,
- the variable is treated as a `normal' shell variable. If it is not,
- however, then this function is called like this:
- tempvar = (*(var->dynamic_value)) (var);
-
- Sometimes `tempvar' will replace the value of `var'. Other times, the
- shell will simply use the string value. Pretty object-oriented, huh?
-
- Be warned, though: if you `unset' a special variable, it loses its
- special meaning, even if you subsequently set it.
-
- The special assignment code would probably have been better put in
- subst.c: do_assignment_internal, in the same style as
- stupidly_hack_special_variables, but I wanted the changes as
- localized as possible. */
-
-#define INIT_DYNAMIC_VAR(var, val, gfunc, afunc) \
- do \
- { \
- v = bind_variable (var, (val), 0); \
- v->dynamic_value = gfunc; \
- v->assign_func = afunc; \
- } \
- while (0)
-
-#define INIT_DYNAMIC_ARRAY_VAR(var, gfunc, afunc) \
- do \
- { \
- v = make_new_array_variable (var); \
- v->dynamic_value = gfunc; \
- v->assign_func = afunc; \
- } \
- while (0)
-
-static SHELL_VAR *
-null_assign (self, value, unused)
- SHELL_VAR *self;
- char *value;
- arrayind_t unused;
-{
- return (self);
-}
-
-#if defined (ARRAY_VARS)
-static SHELL_VAR *
-null_array_assign (self, value, ind)
- SHELL_VAR *self;
- char *value;
- arrayind_t ind;
-{
- return (self);
-}
-#endif
-
-/* Degenerate `dynamic_value' function; just returns what's passed without
- manipulation. */
-static SHELL_VAR *
-get_self (self)
- SHELL_VAR *self;
-{
- return (self);
-}
-
-#if defined (ARRAY_VARS)
-/* A generic dynamic array variable initializer. Intialize array variable
- NAME with dynamic value function GETFUNC and assignment function SETFUNC. */
-static SHELL_VAR *
-init_dynamic_array_var (name, getfunc, setfunc, attrs)
- char *name;
- sh_var_value_func_t *getfunc;
- sh_var_assign_func_t *setfunc;
- int attrs;
-{
- SHELL_VAR *v;
-
- v = find_variable (name);
- if (v)
- return (v);
- INIT_DYNAMIC_ARRAY_VAR (name, getfunc, setfunc);
- if (attrs)
- VSETATTR (v, attrs);
- return v;
-}
-#endif
-
-
-/* The value of $SECONDS. This is the number of seconds since shell
- invocation, or, the number of seconds since the last assignment + the
- value of the last assignment. */
-static intmax_t seconds_value_assigned;
-
-static SHELL_VAR *
-assign_seconds (self, value, unused)
- SHELL_VAR *self;
- char *value;
- arrayind_t unused;
-{
- if (legal_number (value, &seconds_value_assigned) == 0)
- seconds_value_assigned = 0;
- shell_start_time = NOW;
- return (self);
-}
-
-static SHELL_VAR *
-get_seconds (var)
- SHELL_VAR *var;
-{
- time_t time_since_start;
- char *p;
-
- time_since_start = NOW - shell_start_time;
- p = itos(seconds_value_assigned + time_since_start);
-
- FREE (value_cell (var));
-
- VSETATTR (var, att_integer);
- var_setvalue (var, p);
- return (var);
-}
-
-static SHELL_VAR *
-init_seconds_var ()
-{
- SHELL_VAR *v;
-
- v = find_variable ("SECONDS");
- if (v)
- {
- if (legal_number (value_cell(v), &seconds_value_assigned) == 0)
- seconds_value_assigned = 0;
- }
- INIT_DYNAMIC_VAR ("SECONDS", (v ? value_cell (v) : (char *)NULL), get_seconds, assign_seconds);
- return v;
-}
-
-/* The random number seed. You can change this by setting RANDOM. */
-static unsigned long rseed = 1;
-static int last_random_value;
-static int seeded_subshell = 0;
-
-/* A linear congruential random number generator based on the example
- one in the ANSI C standard. This one isn't very good, but a more
- complicated one is overkill. */
-
-/* Returns a pseudo-random number between 0 and 32767. */
-static int
-brand ()
-{
- rseed = rseed * 1103515245 + 12345;
- return ((unsigned int)((rseed >> 16) & 32767)); /* was % 32768 */
-}
-
-/* Set the random number generator seed to SEED. */
-static void
-sbrand (seed)
- unsigned long seed;
-{
- rseed = seed;
- last_random_value = 0;
-}
-
-static SHELL_VAR *
-assign_random (self, value, unused)
- SHELL_VAR *self;
- char *value;
- arrayind_t unused;
-{
- sbrand (strtoul (value, (char **)NULL, 10));
- if (subshell_environment)
- seeded_subshell = 1;
- return (self);
-}
-
-int
-get_random_number ()
-{
- int rv;
-
- /* Reset for command and process substitution. */
- if (subshell_environment && seeded_subshell == 0)
- {
- sbrand (rseed + getpid() + NOW);
- seeded_subshell = 1;
- }
-
- do
- rv = brand ();
- while (rv == last_random_value);
- return rv;
-}
-
-static SHELL_VAR *
-get_random (var)
- SHELL_VAR *var;
-{
- int rv;
- char *p;
-
- rv = get_random_number ();
- last_random_value = rv;
- p = itos (rv);
-
- FREE (value_cell (var));
-
- VSETATTR (var, att_integer);
- var_setvalue (var, p);
- return (var);
-}
-
-static SHELL_VAR *
-assign_lineno (var, value, unused)
- SHELL_VAR *var;
- char *value;
- arrayind_t unused;
-{
- intmax_t new_value;
-
- if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
- new_value = 0;
- line_number = new_value;
- return var;
-}
-
-/* Function which returns the current line number. */
-static SHELL_VAR *
-get_lineno (var)
- SHELL_VAR *var;
-{
- char *p;
- int ln;
-
- ln = executing_line_number ();
- p = itos (ln);
- FREE (value_cell (var));
- var_setvalue (var, p);
- return (var);
-}
-
-static SHELL_VAR *
-assign_subshell (var, value, unused)
- SHELL_VAR *var;
- char *value;
- arrayind_t unused;
-{
- intmax_t new_value;
-
- if (value == 0 || *value == '\0' || legal_number (value, &new_value) == 0)
- new_value = 0;
- subshell_level = new_value;
- return var;
-}
-
-static SHELL_VAR *
-get_subshell (var)
- SHELL_VAR *var;
-{
- char *p;
-
- p = itos (subshell_level);
- FREE (value_cell (var));
- var_setvalue (var, p);
- return (var);
-}
-
-static SHELL_VAR *
-get_bash_command (var)
- SHELL_VAR *var;
-{
- char *p;
-
-
- if (the_printed_command_except_trap)
- p = savestring (the_printed_command_except_trap);
- else
- {
- p = (char *)xmalloc (1);
- p[0] = '\0';
- }
- FREE (value_cell (var));
- var_setvalue (var, p);
- return (var);
-}
-
-#if defined (HISTORY)
-static SHELL_VAR *
-get_histcmd (var)
- SHELL_VAR *var;
-{
- char *p;
-
- p = itos (history_number ());
- FREE (value_cell (var));
- var_setvalue (var, p);
- return (var);
-}
-#endif
-
-#if defined (READLINE)
-/* When this function returns, VAR->value points to malloced memory. */
-static SHELL_VAR *
-get_comp_wordbreaks (var)
- SHELL_VAR *var;
-{
- /* If we don't have anything yet, assign a default value. */
- if (rl_completer_word_break_characters == 0 && bash_readline_initialized == 0)
- enable_hostname_completion (perform_hostname_completion);
-
- var_setvalue (var, rl_completer_word_break_characters);
-
- return (var);
-}
-
-/* When this function returns, rl_completer_word_break_characters points to
- malloced memory. */
-static SHELL_VAR *
-assign_comp_wordbreaks (self, value, unused)
- SHELL_VAR *self;
- char *value;
- arrayind_t unused;
-{
- if (rl_completer_word_break_characters &&
- rl_completer_word_break_characters != rl_basic_word_break_characters)
- free (rl_completer_word_break_characters);
-
- rl_completer_word_break_characters = savestring (value);
- return self;
-}
-#endif /* READLINE */
-
-#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
-static SHELL_VAR *
-assign_dirstack (self, value, ind)
- SHELL_VAR *self;
- char *value;
- arrayind_t ind;
-{
- set_dirstack_element (ind, 1, value);
- return self;
-}
-
-static SHELL_VAR *
-get_dirstack (self)
- SHELL_VAR *self;
-{
- ARRAY *a;
- WORD_LIST *l;
-
- l = get_directory_stack (0);
- a = array_from_word_list (l);
- array_dispose (array_cell (self));
- dispose_words (l);
- var_setarray (self, a);
- return self;
-}
-#endif /* PUSHD AND POPD && ARRAY_VARS */
-
-#if defined (ARRAY_VARS)
-/* We don't want to initialize the group set with a call to getgroups()
- unless we're asked to, but we only want to do it once. */
-static SHELL_VAR *
-get_groupset (self)
- SHELL_VAR *self;
-{
- register int i;
- int ng;
- ARRAY *a;
- static char **group_set = (char **)NULL;
-
- if (group_set == 0)
- {
- group_set = get_group_list (&ng);
- a = array_cell (self);
- for (i = 0; i < ng; i++)
- array_insert (a, i, group_set[i]);
- }
- return (self);
-}
-#endif /* ARRAY_VARS */
-
-/* If ARRAY_VARS is not defined, this just returns the name of any
- currently-executing function. If we have arrays, it's a call stack. */
-static SHELL_VAR *
-get_funcname (self)
- SHELL_VAR *self;
-{
-#if ! defined (ARRAY_VARS)
- char *t;
- if (variable_context && this_shell_function)
- {
- FREE (value_cell (self));
- t = savestring (this_shell_function->name);
- var_setvalue (self, t);
- }
-#endif
- return (self);
-}
-
-void
-make_funcname_visible (on_or_off)
- int on_or_off;
-{
- SHELL_VAR *v;
-
- v = find_variable ("FUNCNAME");
- if (v == 0 || v->dynamic_value == 0)
- return;
-
- if (on_or_off)
- VUNSETATTR (v, att_invisible);
- else
- VSETATTR (v, att_invisible);
-}
-
-static SHELL_VAR *
-init_funcname_var ()
-{
- SHELL_VAR *v;
-
- v = find_variable ("FUNCNAME");
- if (v)
- return v;
-#if defined (ARRAY_VARS)
- INIT_DYNAMIC_ARRAY_VAR ("FUNCNAME", get_funcname, null_array_assign);
-#else
- INIT_DYNAMIC_VAR ("FUNCNAME", (char *)NULL, get_funcname, null_assign);
-#endif
- VSETATTR (v, att_invisible|att_noassign);
- return v;
-}
-
-static void
-initialize_dynamic_variables ()
-{
- SHELL_VAR *v;
-
- v = init_seconds_var ();
-
- INIT_DYNAMIC_VAR ("BASH_COMMAND", (char *)NULL, get_bash_command, (sh_var_assign_func_t *)NULL);
- INIT_DYNAMIC_VAR ("BASH_SUBSHELL", (char *)NULL, get_subshell, assign_subshell);
-
- INIT_DYNAMIC_VAR ("RANDOM", (char *)NULL, get_random, assign_random);
- VSETATTR (v, att_integer);
- INIT_DYNAMIC_VAR ("LINENO", (char *)NULL, get_lineno, assign_lineno);
- VSETATTR (v, att_integer);
-
-#if defined (HISTORY)
- INIT_DYNAMIC_VAR ("HISTCMD", (char *)NULL, get_histcmd, (sh_var_assign_func_t *)NULL);
- VSETATTR (v, att_integer);
-#endif
-
-#if defined (READLINE)
- INIT_DYNAMIC_VAR ("COMP_WORDBREAKS", (char *)NULL, get_comp_wordbreaks, assign_comp_wordbreaks);
-#endif
-
-#if defined (PUSHD_AND_POPD) && defined (ARRAY_VARS)
- v = init_dynamic_array_var ("DIRSTACK", get_dirstack, assign_dirstack, 0);
-#endif /* PUSHD_AND_POPD && ARRAY_VARS */
-
-#if defined (ARRAY_VARS)
- v = init_dynamic_array_var ("GROUPS", get_groupset, null_array_assign, att_noassign);
-
-# if defined (DEBUGGER)
- v = init_dynamic_array_var ("BASH_ARGC", get_self, null_array_assign, att_noassign|att_nounset);
- v = init_dynamic_array_var ("BASH_ARGV", get_self, null_array_assign, att_noassign|att_nounset);
-# endif /* DEBUGGER */
- v = init_dynamic_array_var ("BASH_SOURCE", get_self, null_array_assign, att_noassign|att_nounset);
- v = init_dynamic_array_var ("BASH_LINENO", get_self, null_array_assign, att_noassign|att_nounset);
-#endif
-
- v = init_funcname_var ();
-}
-
-/* **************************************************************** */
-/* */
-/* Retrieving variables and values */
-/* */
-/* **************************************************************** */
-
-/* How to get a pointer to the shell variable or function named NAME.
- HASHED_VARS is a pointer to the hash table containing the list
- of interest (either variables or functions). */
-
-static SHELL_VAR *
-hash_lookup (name, hashed_vars)
- const char *name;
- HASH_TABLE *hashed_vars;
-{
- BUCKET_CONTENTS *bucket;
-
- bucket = hash_search (name, hashed_vars, 0);
- return (bucket ? (SHELL_VAR *)bucket->data : (SHELL_VAR *)NULL);
-}
-
-SHELL_VAR *
-var_lookup (name, vcontext)
- const char *name;
- VAR_CONTEXT *vcontext;
-{
- VAR_CONTEXT *vc;
- SHELL_VAR *v;
-
- v = (SHELL_VAR *)NULL;
- for (vc = vcontext; vc; vc = vc->down)
- if (v = hash_lookup (name, vc->table))
- break;
-
- return v;
-}
-
-/* Look up the variable entry named NAME. If SEARCH_TEMPENV is non-zero,
- then also search the temporarily built list of exported variables.
- The lookup order is:
- temporary_env
- shell_variables list
-*/
-
-SHELL_VAR *
-find_variable_internal (name, force_tempenv)
- const char *name;
- int force_tempenv;
-{
- SHELL_VAR *var;
- int search_tempenv;
-
- var = (SHELL_VAR *)NULL;
-
- /* If explicitly requested, first look in the temporary environment for
- the variable. This allows constructs such as "foo=x eval 'echo $foo'"
- to get the `exported' value of $foo. This happens if we are executing
- a function or builtin, or if we are looking up a variable in a
- "subshell environment". */
- search_tempenv = force_tempenv || (expanding_redir == 0 && subshell_environment);
-
- if (search_tempenv && temporary_env)
- var = hash_lookup (name, temporary_env);
-
- if (var == 0)
- var = var_lookup (name, shell_variables);
-
- if (var == 0)
- return ((SHELL_VAR *)NULL);
-
- return (var->dynamic_value ? (*(var->dynamic_value)) (var) : var);
-}
-
-/* Look up the variable entry named NAME. Returns the entry or NULL. */
-SHELL_VAR *
-find_variable (name)
- const char *name;
-{
- return (find_variable_internal (name, (expanding_redir == 0 && this_shell_builtin != 0)));
-}
-
-/* Look up the function entry whose name matches STRING.
- Returns the entry or NULL. */
-SHELL_VAR *
-find_function (name)
- const char *name;
-{
- return (hash_lookup (name, shell_functions));
-}
-
-/* Find the function definition for the shell function named NAME. Returns
- the entry or NULL. */
-FUNCTION_DEF *
-find_function_def (name)
- const char *name;
-{
- return ((FUNCTION_DEF *)hash_lookup (name, shell_function_defs));
-}
-
-/* Return the value of VAR. VAR is assumed to have been the result of a
- lookup without any subscript, if arrays are compiled into the shell. */
-char *
-get_variable_value (var)
- SHELL_VAR *var;
-{
- if (var == 0)
- return ((char *)NULL);
-#if defined (ARRAY_VARS)
- else if (array_p (var))
- return (array_reference (array_cell (var), 0));
-#endif
- else
- return (value_cell (var));
-}
-
-/* Return the string value of a variable. Return NULL if the variable
- doesn't exist. Don't cons a new string. This is a potential memory
- leak if the variable is found in the temporary environment. Since
- functions and variables have separate name spaces, returns NULL if
- var_name is a shell function only. */
-char *
-get_string_value (var_name)
- const char *var_name;
-{
- SHELL_VAR *var;
-
- var = find_variable (var_name);
- return ((var) ? get_variable_value (var) : (char *)NULL);
-}
-
-/* This is present for use by the tilde and readline libraries. */
-char *
-sh_get_env_value (v)
- const char *v;
-{
- return get_string_value (v);
-}
-
-/* **************************************************************** */
-/* */
-/* Creating and setting variables */
-/* */
-/* **************************************************************** */
-
-/* Set NAME to VALUE if NAME has no value. */
-SHELL_VAR *
-set_if_not (name, value)
- char *name, *value;
-{
- SHELL_VAR *v;
-
- if (shell_variables == 0)
- create_variable_tables ();
-
- v = find_variable (name);
- if (v == 0)
- v = bind_variable_internal (name, value, global_variables->table, HASH_NOSRCH, 0);
- return (v);
-}
-
-/* Create a local variable referenced by NAME. */
-SHELL_VAR *
-make_local_variable (name)
- const char *name;
-{
- SHELL_VAR *new_var, *old_var;
- VAR_CONTEXT *vc;
- int was_tmpvar;
- char *tmp_value;
-
- /* local foo; local foo; is a no-op. */
- old_var = find_variable (name);
- if (old_var && local_p (old_var) && old_var->context == variable_context)
- {
- VUNSETATTR (old_var, att_invisible);
- return (old_var);
- }
-
- was_tmpvar = old_var && tempvar_p (old_var);
- if (was_tmpvar)
- tmp_value = value_cell (old_var);
-
- for (vc = shell_variables; vc; vc = vc->down)
- if (vc_isfuncenv (vc) && vc->scope == variable_context)
- break;
-
- if (vc == 0)
- {
- internal_error (_("make_local_variable: no function context at current scope"));
- return ((SHELL_VAR *)NULL);
- }
- else if (vc->table == 0)
- vc->table = hash_create (TEMPENV_HASH_BUCKETS);
-
- /* Since this is called only from the local/declare/typeset code, we can
- call builtin_error here without worry (of course, it will also work
- for anything that sets this_command_name). Variables with the `noassign'
- attribute may not be made local. The test against old_var's context
- level is to disallow local copies of readonly global variables (since I
- believe that this could be a security hole). Readonly copies of calling
- function local variables are OK. */
- if (old_var && (noassign_p (old_var) ||
- (readonly_p (old_var) && old_var->context == 0)))
- {
- if (readonly_p (old_var))
- sh_readonly (name);
- return ((SHELL_VAR *)NULL);
- }
-
- if (old_var == 0)
- new_var = bind_variable_internal (name, "", vc->table, HASH_NOSRCH, 0);
- else
- {
- new_var = make_new_variable (name, vc->table);
-
- /* If we found this variable in one of the temporary environments,
- inherit its value. Watch to see if this causes problems with
- things like `x=4 local x'. */
- if (was_tmpvar)
- var_setvalue (new_var, savestring (tmp_value));
-
- new_var->attributes = exported_p (old_var) ? att_exported : 0;
- }
-
- vc->flags |= VC_HASLOCAL;
-
- new_var->context = variable_context;
- VSETATTR (new_var, att_local);
-
- if (ifsname (name))
- setifs (new_var);
-
- return (new_var);
-}
-
-#if defined (ARRAY_VARS)
-SHELL_VAR *
-make_local_array_variable (name)
- char *name;
-{
- SHELL_VAR *var;
- ARRAY *array;
-
- var = make_local_variable (name);
- if (var == 0 || array_p (var))
- return var;
-
- array = array_create ();
-
- FREE (value_cell(var));
- var_setarray (var, array);
- VSETATTR (var, att_array);
- return var;
-}
-#endif /* ARRAY_VARS */
-
-/* Create a new shell variable with name NAME. */
-static SHELL_VAR *
-new_shell_variable (name)
- const char *name;
-{
- SHELL_VAR *entry;
-
- entry = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
-
- entry->name = savestring (name);
- var_setvalue (entry, (char *)NULL);
- CLEAR_EXPORTSTR (entry);
-
- entry->dynamic_value = (sh_var_value_func_t *)NULL;
- entry->assign_func = (sh_var_assign_func_t *)NULL;
-
- entry->attributes = 0;
-
- /* Always assume variables are to be made at toplevel!
- make_local_variable has the responsibilty of changing the
- variable context. */
- entry->context = 0;
-
- return (entry);
-}
-
-/* Create a new shell variable with name NAME and add it to the hash table
- TABLE. */
-static SHELL_VAR *
-make_new_variable (name, table)
- const char *name;
- HASH_TABLE *table;
-{
- SHELL_VAR *entry;
- BUCKET_CONTENTS *elt;
-
- entry = new_shell_variable (name);
-
- /* Make sure we have a shell_variables hash table to add to. */
- if (shell_variables == 0)
- create_variable_tables ();
-
- elt = hash_insert (savestring (name), table, HASH_NOSRCH);
- elt->data = (PTR_T)entry;
-
- return entry;
-}
-
-#if defined (ARRAY_VARS)
-SHELL_VAR *
-make_new_array_variable (name)
- char *name;
-{
- SHELL_VAR *entry;
- ARRAY *array;
-
- entry = make_new_variable (name, global_variables->table);
- array = array_create ();
- var_setarray (entry, array);
- VSETATTR (entry, att_array);
- return entry;
-}
-#endif
-
-char *
-make_variable_value (var, value, flags)
- SHELL_VAR *var;
- char *value;
- int flags;
-{
- char *retval, *oval;
- intmax_t lval, rval;
- int expok, olen;
-
- /* If this variable has had its type set to integer (via `declare -i'),
- then do expression evaluation on it and store the result. The
- functions in expr.c (evalexp()) and bind_int_variable() are responsible
- for turning off the integer flag if they don't want further
- evaluation done. */
- if (integer_p (var))
- {
- if (flags & ASS_APPEND)
- {
- oval = value_cell (var);
- lval = evalexp (oval, &expok); /* ksh93 seems to do this */
- if (expok == 0)
- jump_to_top_level (DISCARD);
- }
- rval = evalexp (value, &expok);
- if (expok == 0)
- jump_to_top_level (DISCARD);
- if (flags & ASS_APPEND)
- rval += lval;
- retval = itos (rval);
- }
- else if (value)
- {
- if (flags & ASS_APPEND)
- {
- oval = get_variable_value (var);
- if (oval == 0) /* paranoia */
- oval = "";
- olen = STRLEN (oval);
- retval = (char *)xmalloc (olen + (value ? STRLEN (value) : 0) + 1);
- strcpy (retval, oval);
- if (value)
- strcpy (retval+olen, value);
- }
- else if (*value)
- retval = savestring (value);
- else
- {
- retval = (char *)xmalloc (1);
- retval[0] = '\0';
- }
- }
- else
- retval = (char *)NULL;
-
- return retval;
-}
-
-/* Bind a variable NAME to VALUE in the HASH_TABLE TABLE, which may be the
- temporary environment (but usually is not). */
-static SHELL_VAR *
-bind_variable_internal (name, value, table, hflags, aflags)
- const char *name;
- char *value;
- HASH_TABLE *table;
- int hflags, aflags;
-{
- char *newval;
- SHELL_VAR *entry;
-
- entry = (hflags & HASH_NOSRCH) ? (SHELL_VAR *)NULL : hash_lookup (name, table);
-
- if (entry == 0)
- {
- entry = make_new_variable (name, table);
- var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */
- }
- else if (entry->assign_func) /* array vars have assign functions now */
- {
- INVALIDATE_EXPORTSTR (entry);
- newval = (aflags & ASS_APPEND) ? make_variable_value (entry, value, aflags) : value;
- entry = (*(entry->assign_func)) (entry, newval, -1);
- if (newval != value)
- free (newval);
- return (entry);
- }
- else
- {
- if (readonly_p (entry) || noassign_p (entry))
- {
- if (readonly_p (entry))
- err_readonly (name);
- return (entry);
- }
-
- /* Variables which are bound are visible. */
- VUNSETATTR (entry, att_invisible);
-
- newval = make_variable_value (entry, value, aflags); /* XXX */
-
- /* Invalidate any cached export string */
- INVALIDATE_EXPORTSTR (entry);
-
-#if defined (ARRAY_VARS)
- /* XXX -- this bears looking at again -- XXX */
- /* If an existing array variable x is being assigned to with x=b or
- `read x' or something of that nature, silently convert it to
- x[0]=b or `read x[0]'. */
- if (array_p (entry))
- {
- array_insert (array_cell (entry), 0, newval);
- free (newval);
- }
- else
-#endif
- {
- FREE (value_cell (entry));
- var_setvalue (entry, newval);
- }
- }
-
- if (mark_modified_vars)
- VSETATTR (entry, att_exported);
-
- if (exported_p (entry))
- array_needs_making = 1;
-
- return (entry);
-}
-
-/* Bind a variable NAME to VALUE. This conses up the name
- and value strings. If we have a temporary environment, we bind there
- first, then we bind into shell_variables. */
-
-SHELL_VAR *
-bind_variable (name, value, flags)
- const char *name;
- char *value;
- int flags;
-{
- SHELL_VAR *v;
- VAR_CONTEXT *vc;
-
- if (shell_variables == 0)
- create_variable_tables ();
-
- /* If we have a temporary environment, look there first for the variable,
- and, if found, modify the value there before modifying it in the
- shell_variables table. This allows sourced scripts to modify values
- given to them in a temporary environment while modifying the variable
- value that the caller sees. */
- if (temporary_env)
- bind_tempenv_variable (name, value);
-
- /* XXX -- handle local variables here. */
- for (vc = shell_variables; vc; vc = vc->down)
- {
- if (vc_isfuncenv (vc) || vc_isbltnenv (vc))
- {
- v = hash_lookup (name, vc->table);
- if (v)
- return (bind_variable_internal (name, value, vc->table, 0, flags));
- }
- }
- return (bind_variable_internal (name, value, global_variables->table, 0, flags));
-}
-
-/* Make VAR, a simple shell variable, have value VALUE. Once assigned a
- value, variables are no longer invisible. This is a duplicate of part
- of the internals of bind_variable. If the variable is exported, or
- all modified variables should be exported, mark the variable for export
- and note that the export environment needs to be recreated. */
-SHELL_VAR *
-bind_variable_value (var, value, aflags)
- SHELL_VAR *var;
- char *value;
- int aflags;
-{
- char *t;
-
- VUNSETATTR (var, att_invisible);
-
- if (var->assign_func)
- {
- /* If we're appending, we need the old value, so use
- make_variable_value */
- t = (aflags & ASS_APPEND) ? make_variable_value (var, value, aflags) : value;
- (*(var->assign_func)) (var, t, -1);
- if (t != value && t)
- free (t);
- }
- else
- {
- t = make_variable_value (var, value, aflags);
- FREE (value_cell (var));
- var_setvalue (var, t);
- }
-
- INVALIDATE_EXPORTSTR (var);
-
- if (mark_modified_vars)
- VSETATTR (var, att_exported);
-
- if (exported_p (var))
- array_needs_making = 1;
-
- return (var);
-}
-
-/* Bind/create a shell variable with the name LHS to the RHS.
- This creates or modifies a variable such that it is an integer.
-
- This used to be in expr.c, but it is here so that all of the
- variable binding stuff is localized. Since we don't want any
- recursive evaluation from bind_variable() (possible without this code,
- since bind_variable() calls the evaluator for variables with the integer
- attribute set), we temporarily turn off the integer attribute for each
- variable we set here, then turn it back on after binding as necessary. */
-
-SHELL_VAR *
-bind_int_variable (lhs, rhs)
- char *lhs, *rhs;
-{
- register SHELL_VAR *v;
- int isint, isarr;
-
- isint = isarr = 0;
-#if defined (ARRAY_VARS)
- if (valid_array_reference (lhs))
- {
- isarr = 1;
- v = array_variable_part (lhs, (char **)0, (int *)0);
- }
- else
-#endif
- v = find_variable (lhs);
-
- if (v)
- {
- isint = integer_p (v);
- VUNSETATTR (v, att_integer);
- }
-
-#if defined (ARRAY_VARS)
- if (isarr)
- v = assign_array_element (lhs, rhs, 0);
- else
-#endif
- v = bind_variable (lhs, rhs, 0);
-
- if (isint)
- VSETATTR (v, att_integer);
-
- return (v);
-}
-
-SHELL_VAR *
-bind_var_to_int (var, val)
- char *var;
- intmax_t val;
-{
- char ibuf[INT_STRLEN_BOUND (intmax_t) + 1], *p;
-
- p = fmtulong (val, 10, ibuf, sizeof (ibuf), 0);
- return (bind_int_variable (var, p));
-}
-
-/* Do a function binding to a variable. You pass the name and
- the command to bind to. This conses the name and command. */
-SHELL_VAR *
-bind_function (name, value)
- const char *name;
- COMMAND *value;
-{
- SHELL_VAR *entry;
-
- entry = find_function (name);
- if (entry == 0)
- {
- BUCKET_CONTENTS *elt;
-
- elt = hash_insert (savestring (name), shell_functions, HASH_NOSRCH);
- entry = new_shell_variable (name);
- elt->data = (PTR_T)entry;
- }
- else
- INVALIDATE_EXPORTSTR (entry);
-
- if (var_isset (entry))
- dispose_command (function_cell (entry));
-
- if (value)
- var_setfunc (entry, copy_command (value));
- else
- var_setfunc (entry, 0);
-
- VSETATTR (entry, att_function);
-
- if (mark_modified_vars)
- VSETATTR (entry, att_exported);
-
- VUNSETATTR (entry, att_invisible); /* Just to be sure */
-
- if (exported_p (entry))
- array_needs_making = 1;
-
-#if defined (PROGRAMMABLE_COMPLETION)
- set_itemlist_dirty (&it_functions);
-#endif
-
- return (entry);
-}
-
-/* Bind a function definition, which includes source file and line number
- information in addition to the command, into the FUNCTION_DEF hash table.*/
-void
-bind_function_def (name, value)
- const char *name;
- FUNCTION_DEF *value;
-{
- FUNCTION_DEF *entry;
- BUCKET_CONTENTS *elt;
- COMMAND *cmd;
-
- entry = find_function_def (name);
- if (entry)
- {
- dispose_function_def_contents (entry);
- entry = copy_function_def_contents (value, entry);
- }
- else
- {
- cmd = value->command;
- value->command = 0;
- entry = copy_function_def (value);
- value->command = cmd;
-
- elt = hash_insert (savestring (name), shell_function_defs, HASH_NOSRCH);
- elt->data = (PTR_T *)entry;
- }
-}
-
-/* Add STRING, which is of the form foo=bar, to the temporary environment
- HASH_TABLE (temporary_env). The functions in execute_cmd.c are
- responsible for moving the main temporary env to one of the other
- temporary environments. The expansion code in subst.c calls this. */
-int
-assign_in_env (word)
- WORD_DESC *word;
-{
- int offset;
- char *name, *temp, *value;
- SHELL_VAR *var;
- const char *string;
-
- string = word->word;
-
- offset = assignment (string, 0);
- name = savestring (string);
- value = (char *)NULL;
-
- if (name[offset] == '=')
- {
- name[offset] = 0;
-
- /* ignore the `+' when assigning temporary environment */
- if (name[offset - 1] == '+')
- name[offset - 1] = '\0';
-
- var = find_variable (name);
- if (var && (readonly_p (var) || noassign_p (var)))
- {
- if (readonly_p (var))
- err_readonly (name);
- free (name);
- return (0);
- }
-
- temp = name + offset + 1;
-#if 0
- temp = (xstrchr (temp, '~') != 0) ? bash_tilde_expand (temp, 1) : savestring (temp);
- value = expand_string_unsplit_to_string (temp, 0);
- free (temp);
-#else
- value = expand_assignment_string_to_string (temp, 0);
-#endif
- }
-
- if (temporary_env == 0)
- temporary_env = hash_create (TEMPENV_HASH_BUCKETS);
-
- var = hash_lookup (name, temporary_env);
- if (var == 0)
- var = make_new_variable (name, temporary_env);
- else
- FREE (value_cell (var));
-
- if (value == 0)
- {
- value = (char *)xmalloc (1); /* like do_assignment_internal */
- value[0] = '\0';
- }
-
- var_setvalue (var, value);
- var->attributes |= (att_exported|att_tempvar);
- var->context = variable_context; /* XXX */
-
- INVALIDATE_EXPORTSTR (var);
- var->exportstr = mk_env_string (name, value);
-
- array_needs_making = 1;
-
- if (ifsname (name))
- setifs (var);
-
- if (echo_command_at_execute)
- /* The Korn shell prints the `+ ' in front of assignment statements,
- so we do too. */
- xtrace_print_assignment (name, value, 0, 1);
-
- free (name);
- return 1;
-}
-
-/* **************************************************************** */
-/* */
-/* Copying variables */
-/* */
-/* **************************************************************** */
-
-#ifdef INCLUDE_UNUSED
-/* Copy VAR to a new data structure and return that structure. */
-SHELL_VAR *
-copy_variable (var)
- SHELL_VAR *var;
-{
- SHELL_VAR *copy = (SHELL_VAR *)NULL;
-
- if (var)
- {
- copy = (SHELL_VAR *)xmalloc (sizeof (SHELL_VAR));
-
- copy->attributes = var->attributes;
- copy->name = savestring (var->name);
-
- if (function_p (var))
- var_setfunc (copy, copy_command (function_cell (var)));
-#if defined (ARRAY_VARS)
- else if (array_p (var))
- var_setarray (copy, dup_array (array_cell (var)));
-#endif
- else if (value_cell (var))
- var_setvalue (copy, savestring (value_cell (var)));
- else
- var_setvalue (copy, (char *)NULL);
-
- copy->dynamic_value = var->dynamic_value;
- copy->assign_func = var->assign_func;
-
- copy->exportstr = COPY_EXPORTSTR (var);
-
- copy->context = var->context;
- }
- return (copy);
-}
-#endif
-
-/* **************************************************************** */
-/* */
-/* Deleting and unsetting variables */
-/* */
-/* **************************************************************** */
-
-/* Dispose of the information attached to VAR. */
-void
-dispose_variable (var)
- SHELL_VAR *var;
-{
- if (var == 0)
- return;
-
- if (function_p (var))
- dispose_command (function_cell (var));
-#if defined (ARRAY_VARS)
- else if (array_p (var))
- array_dispose (array_cell (var));
-#endif
- else
- FREE (value_cell (var));
-
- FREE_EXPORTSTR (var);
-
- free (var->name);
-
- if (exported_p (var))
- array_needs_making = 1;
-
- free (var);
-}
-
-/* Unset the shell variable referenced by NAME. */
-int
-unbind_variable (name)
- const char *name;
-{
- return makunbound (name, shell_variables);
-}
-
-/* Unset the shell function named NAME. */
-int
-unbind_func (name)
- const char *name;
-{
- BUCKET_CONTENTS *elt;
- SHELL_VAR *func;
-
- elt = hash_remove (name, shell_functions, 0);
-
- if (elt == 0)
- return -1;
-
-#if defined (PROGRAMMABLE_COMPLETION)
- set_itemlist_dirty (&it_functions);
-#endif
-
- func = (SHELL_VAR *)elt->data;
- if (func)
- {
- if (exported_p (func))
- array_needs_making++;
- dispose_variable (func);
- }
-
- free (elt->key);
- free (elt);
-
- return 0;
-}
-
-int
-unbind_function_def (name)
- const char *name;
-{
- BUCKET_CONTENTS *elt;
- FUNCTION_DEF *funcdef;
-
- elt = hash_remove (name, shell_function_defs, 0);
-
- if (elt == 0)
- return -1;
-
- funcdef = (FUNCTION_DEF *)elt->data;
- if (funcdef)
- dispose_function_def (funcdef);
-
- free (elt->key);
- free (elt);
-
- return 0;
-}
-
-/* Make the variable associated with NAME go away. HASH_LIST is the
- hash table from which this variable should be deleted (either
- shell_variables or shell_functions).
- Returns non-zero if the variable couldn't be found. */
-int
-makunbound (name, vc)
- const char *name;
- VAR_CONTEXT *vc;
-{
- BUCKET_CONTENTS *elt, *new_elt;
- SHELL_VAR *old_var;
- VAR_CONTEXT *v;
- char *t;
-
- for (elt = (BUCKET_CONTENTS *)NULL, v = vc; v; v = v->down)
- if (elt = hash_remove (name, v->table, 0))
- break;
-
- if (elt == 0)
- return (-1);
-
- old_var = (SHELL_VAR *)elt->data;
-
- if (old_var && exported_p (old_var))
- array_needs_making++;
-
- /* If we're unsetting a local variable and we're still executing inside
- the function, just mark the variable as invisible. The function
- eventually called by pop_var_context() will clean it up later. This
- must be done so that if the variable is subsequently assigned a new
- value inside the function, the `local' attribute is still present.
- We also need to add it back into the correct hash table. */
- if (old_var && local_p (old_var) && variable_context == old_var->context)
- {
-#if defined (ARRAY_VARS)
- if (array_p (old_var))
- array_dispose (array_cell (old_var));
- else
-#endif
- FREE (value_cell (old_var));
- /* Reset the attributes. Preserve the export attribute if the variable
- came from a temporary environment. Make sure it stays local, and
- make it invisible. */
- old_var->attributes = (exported_p (old_var) && tempvar_p (old_var)) ? att_exported : 0;
- VSETATTR (old_var, att_local);
- VSETATTR (old_var, att_invisible);
- var_setvalue (old_var, (char *)NULL);
- INVALIDATE_EXPORTSTR (old_var);
-
- new_elt = hash_insert (savestring (old_var->name), v->table, 0);
- new_elt->data = (PTR_T)old_var;
- stupidly_hack_special_variables (old_var->name);
-
- free (elt->key);
- free (elt);
- return (0);
- }
-
- /* Have to save a copy of name here, because it might refer to
- old_var->name. If so, stupidly_hack_special_variables will
- reference freed memory. */
- t = savestring (name);
-
- free (elt->key);
- free (elt);
-
- dispose_variable (old_var);
- stupidly_hack_special_variables (t);
- free (t);
-
- return (0);
-}
-
-/* Get rid of all of the variables in the current context. */
-void
-kill_all_local_variables ()
-{
- VAR_CONTEXT *vc;
-
- for (vc = shell_variables; vc; vc = vc->down)
- if (vc_isfuncenv (vc) && vc->scope == variable_context)
- break;
- if (vc == 0)
- return; /* XXX */
-
- if (vc->table && vc_haslocals (vc))
- {
- delete_all_variables (vc->table);
- hash_dispose (vc->table);
- }
- vc->table = (HASH_TABLE *)NULL;
-}
-
-static void
-free_variable_hash_data (data)
- PTR_T data;
-{
- SHELL_VAR *var;
-
- var = (SHELL_VAR *)data;
- dispose_variable (var);
-}
-
-/* Delete the entire contents of the hash table. */
-void
-delete_all_variables (hashed_vars)
- HASH_TABLE *hashed_vars;
-{
- hash_flush (hashed_vars, free_variable_hash_data);
-}
-
-/* **************************************************************** */
-/* */
-/* Setting variable attributes */
-/* */
-/* **************************************************************** */
-
-#define FIND_OR_MAKE_VARIABLE(name, entry) \
- do \
- { \
- entry = find_variable (name); \
- if (!entry) \
- { \
- entry = bind_variable (name, "", 0); \
- if (!no_invisible_vars) entry->attributes |= att_invisible; \
- } \
- } \
- while (0)
-
-/* Make the variable associated with NAME be readonly.
- If NAME does not exist yet, create it. */
-void
-set_var_read_only (name)
- char *name;
-{
- SHELL_VAR *entry;
-
- FIND_OR_MAKE_VARIABLE (name, entry);
- VSETATTR (entry, att_readonly);
-}
-
-#ifdef INCLUDE_UNUSED
-/* Make the function associated with NAME be readonly.
- If NAME does not exist, we just punt, like auto_export code below. */
-void
-set_func_read_only (name)
- const char *name;
-{
- SHELL_VAR *entry;
-
- entry = find_function (name);
- if (entry)
- VSETATTR (entry, att_readonly);
-}
-
-/* Make the variable associated with NAME be auto-exported.
- If NAME does not exist yet, create it. */
-void
-set_var_auto_export (name)
- char *name;
-{
- SHELL_VAR *entry;
-
- FIND_OR_MAKE_VARIABLE (name, entry);
- set_auto_export (entry);
-}
-
-/* Make the function associated with NAME be auto-exported. */
-void
-set_func_auto_export (name)
- const char *name;
-{
- SHELL_VAR *entry;
-
- entry = find_function (name);
- if (entry)
- set_auto_export (entry);
-}
-#endif
-
-/* **************************************************************** */
-/* */
-/* Creating lists of variables */
-/* */
-/* **************************************************************** */
-
-static VARLIST *
-vlist_alloc (nentries)
- int nentries;
-{
- VARLIST *vlist;
-
- vlist = (VARLIST *)xmalloc (sizeof (VARLIST));
- vlist->list = (SHELL_VAR **)xmalloc ((nentries + 1) * sizeof (SHELL_VAR *));
- vlist->list_size = nentries;
- vlist->list_len = 0;
- vlist->list[0] = (SHELL_VAR *)NULL;
-
- return vlist;
-}
-
-static VARLIST *
-vlist_realloc (vlist, n)
- VARLIST *vlist;
- int n;
-{
- if (vlist == 0)
- return (vlist = vlist_alloc (n));
- if (n > vlist->list_size)
- {
- vlist->list_size = n;
- vlist->list = (SHELL_VAR **)xrealloc (vlist->list, (vlist->list_size + 1) * sizeof (SHELL_VAR *));
- }
- return vlist;
-}
-
-static void
-vlist_add (vlist, var, flags)
- VARLIST *vlist;
- SHELL_VAR *var;
- int flags;
-{
- register int i;
-
- for (i = 0; i < vlist->list_len; i++)
- if (STREQ (var->name, vlist->list[i]->name))
- break;
- if (i < vlist->list_len)
- return;
-
- if (i >= vlist->list_size)
- vlist = vlist_realloc (vlist, vlist->list_size + 16);
-
- vlist->list[vlist->list_len++] = var;
- vlist->list[vlist->list_len] = (SHELL_VAR *)NULL;
-}
-
-/* Map FUNCTION over the variables in VAR_HASH_TABLE. Return an array of the
- variables for which FUNCTION returns a non-zero value. A NULL value
- for FUNCTION means to use all variables. */
-SHELL_VAR **
-map_over (function, vc)
- sh_var_map_func_t *function;
- VAR_CONTEXT *vc;
-{
- VAR_CONTEXT *v;
- VARLIST *vlist;
- SHELL_VAR **ret;
- int nentries;
-
- for (nentries = 0, v = vc; v; v = v->down)
- nentries += HASH_ENTRIES (v->table);
-
- if (nentries == 0)
- return (SHELL_VAR **)NULL;
-
- vlist = vlist_alloc (nentries);
-
- for (v = vc; v; v = v->down)
- flatten (v->table, function, vlist, 0);
-
- ret = vlist->list;
- free (vlist);
- return ret;
-}
-
-SHELL_VAR **
-map_over_funcs (function)
- sh_var_map_func_t *function;
-{
- VARLIST *vlist;
- SHELL_VAR **ret;
-
- if (shell_functions == 0 || HASH_ENTRIES (shell_functions) == 0)
- return ((SHELL_VAR **)NULL);
-
- vlist = vlist_alloc (HASH_ENTRIES (shell_functions));
-
- flatten (shell_functions, function, vlist, 0);
-
- ret = vlist->list;
- free (vlist);
- return ret;
-}
-
-/* Flatten VAR_HASH_TABLE, applying FUNC to each member and adding those
- elements for which FUNC succeeds to VLIST->list. FLAGS is reserved
- for future use. Only unique names are added to VLIST. If FUNC is
- NULL, each variable in VAR_HASH_TABLE is added to VLIST. If VLIST is
- NULL, FUNC is applied to each SHELL_VAR in VAR_HASH_TABLE. If VLIST
- and FUNC are both NULL, nothing happens. */
-static void
-flatten (var_hash_table, func, vlist, flags)
- HASH_TABLE *var_hash_table;
- sh_var_map_func_t *func;
- VARLIST *vlist;
- int flags;
-{
- register int i;
- register BUCKET_CONTENTS *tlist;
- int r;
- SHELL_VAR *var;
-
- if (var_hash_table == 0 || (HASH_ENTRIES (var_hash_table) == 0) || (vlist == 0 && func == 0))
- return;
-
- for (i = 0; i < var_hash_table->nbuckets; i++)
- {
- for (tlist = hash_items (i, var_hash_table); tlist; tlist = tlist->next)
- {
- var = (SHELL_VAR *)tlist->data;
-
- r = func ? (*func) (var) : 1;
- if (r && vlist)
- vlist_add (vlist, var, flags);
- }
- }
-}
-
-void
-sort_variables (array)
- SHELL_VAR **array;
-{
- qsort (array, strvec_len ((char **)array), sizeof (SHELL_VAR *), (QSFUNC *)qsort_var_comp);
-}
-
-static int
-qsort_var_comp (var1, var2)
- SHELL_VAR **var1, **var2;
-{
- int result;
-
- if ((result = (*var1)->name[0] - (*var2)->name[0]) == 0)
- result = strcmp ((*var1)->name, (*var2)->name);
-
- return (result);
-}
-
-/* Apply FUNC to each variable in SHELL_VARIABLES, adding each one for
- which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
-static SHELL_VAR **
-vapply (func)
- sh_var_map_func_t *func;
-{
- SHELL_VAR **list;
-
- list = map_over (func, shell_variables);
- if (list /* && posixly_correct */)
- sort_variables (list);
- return (list);
-}
-
-/* Apply FUNC to each variable in SHELL_FUNCTIONS, adding each one for
- which FUNC succeeds to an array of SHELL_VAR *s. Returns the array. */
-static SHELL_VAR **
-fapply (func)
- sh_var_map_func_t *func;
-{
- SHELL_VAR **list;
-
- list = map_over_funcs (func);
- if (list /* && posixly_correct */)
- sort_variables (list);
- return (list);
-}
-
-/* Create a NULL terminated array of all the shell variables. */
-SHELL_VAR **
-all_shell_variables ()
-{
- return (vapply ((sh_var_map_func_t *)NULL));
-}
-
-/* Create a NULL terminated array of all the shell functions. */
-SHELL_VAR **
-all_shell_functions ()
-{
- return (fapply ((sh_var_map_func_t *)NULL));
-}
-
-static int
-visible_var (var)
- SHELL_VAR *var;
-{
- return (invisible_p (var) == 0);
-}
-
-SHELL_VAR **
-all_visible_functions ()
-{
- return (fapply (visible_var));
-}
-
-SHELL_VAR **
-all_visible_variables ()
-{
- return (vapply (visible_var));
-}
-
-/* Return non-zero if the variable VAR is visible and exported. Array
- variables cannot be exported. */
-static int
-visible_and_exported (var)
- SHELL_VAR *var;
-{
- return (invisible_p (var) == 0 && exported_p (var));
-}
-
-/* Return non-zero if VAR is a local variable in the current context and
- is exported. */
-static int
-local_and_exported (var)
- SHELL_VAR *var;
-{
- return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context && exported_p (var));
-}
-
-SHELL_VAR **
-all_exported_variables ()
-{
- return (vapply (visible_and_exported));
-}
-
-SHELL_VAR **
-local_exported_variables ()
-{
- return (vapply (local_and_exported));
-}
-
-static int
-variable_in_context (var)
- SHELL_VAR *var;
-{
- return (invisible_p (var) == 0 && local_p (var) && var->context == variable_context);
-}
-
-SHELL_VAR **
-all_local_variables ()
-{
- VARLIST *vlist;
- SHELL_VAR **ret;
- VAR_CONTEXT *vc;
-
- vc = shell_variables;
- for (vc = shell_variables; vc; vc = vc->down)
- if (vc_isfuncenv (vc) && vc->scope == variable_context)
- break;
-
- if (vc == 0)
- {
- internal_error (_("all_local_variables: no function context at current scope"));
- return (SHELL_VAR **)NULL;
- }
- if (vc->table == 0 || HASH_ENTRIES (vc->table) == 0 || vc_haslocals (vc) == 0)
- return (SHELL_VAR **)NULL;
-
- vlist = vlist_alloc (HASH_ENTRIES (vc->table));
-
- flatten (vc->table, variable_in_context, vlist, 0);
-
- ret = vlist->list;
- free (vlist);
- if (ret)
- sort_variables (ret);
- return ret;
-}
-
-#if defined (ARRAY_VARS)
-/* Return non-zero if the variable VAR is visible and an array. */
-static int
-visible_array_vars (var)
- SHELL_VAR *var;
-{
- return (invisible_p (var) == 0 && array_p (var));
-}
-
-SHELL_VAR **
-all_array_variables ()
-{
- return (vapply (visible_array_vars));
-}
-#endif /* ARRAY_VARS */
-
-char **
-all_variables_matching_prefix (prefix)
- const char *prefix;
-{
- SHELL_VAR **varlist;
- char **rlist;
- int vind, rind, plen;
-
- plen = STRLEN (prefix);
- varlist = all_visible_variables ();
- for (vind = 0; varlist && varlist[vind]; vind++)
- ;
- if (varlist == 0 || vind == 0)
- return ((char **)NULL);
- rlist = strvec_create (vind + 1);
- for (vind = rind = 0; varlist[vind]; vind++)
- {
- if (plen == 0 || STREQN (prefix, varlist[vind]->name, plen))
- rlist[rind++] = savestring (varlist[vind]->name);
- }
- rlist[rind] = (char *)0;
- free (varlist);
-
- return rlist;
-}
-
-/* **************************************************************** */
-/* */
-/* Managing temporary variable scopes */
-/* */
-/* **************************************************************** */
-
-/* Make variable NAME have VALUE in the temporary environment. */
-static SHELL_VAR *
-bind_tempenv_variable (name, value)
- const char *name;
- char *value;
-{
- SHELL_VAR *var;
-
- var = temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL;
-
- if (var)
- {
- FREE (value_cell (var));
- var_setvalue (var, savestring (value));
- INVALIDATE_EXPORTSTR (var);
- }
-
- return (var);
-}
-
-/* Find a variable in the temporary environment that is named NAME.
- Return the SHELL_VAR *, or NULL if not found. */
-SHELL_VAR *
-find_tempenv_variable (name)
- const char *name;
-{
- return (temporary_env ? hash_lookup (name, temporary_env) : (SHELL_VAR *)NULL);
-}
-
-/* Push the variable described by (SHELL_VAR *)DATA down to the next
- variable context from the temporary environment. */
-static void
-push_temp_var (data)
- PTR_T data;
-{
- SHELL_VAR *var, *v;
- HASH_TABLE *binding_table;
-
- var = (SHELL_VAR *)data;
-
- binding_table = shell_variables->table;
- if (binding_table == 0)
- {
- if (shell_variables == global_variables)
- /* shouldn't happen */
- binding_table = shell_variables->table = global_variables->table = hash_create (0);
- else
- binding_table = shell_variables->table = hash_create (TEMPENV_HASH_BUCKETS);
- }
-
- v = bind_variable_internal (var->name, value_cell (var), binding_table, 0, 0);
-
- /* XXX - should we set the context here? It shouldn't matter because of how
- assign_in_env works, but might want to check. */
- if (binding_table == global_variables->table) /* XXX */
- var->attributes &= ~(att_tempvar|att_propagate);
- else
- {
- var->attributes |= att_propagate;
- if (binding_table == shell_variables->table)
- shell_variables->flags |= VC_HASTMPVAR;
- }
- v->attributes |= var->attributes;
-
- dispose_variable (var);
-}
-
-static void
-propagate_temp_var (data)
- PTR_T data;
-{
- SHELL_VAR *var;
-
- var = (SHELL_VAR *)data;
- if (tempvar_p (var) && (var->attributes & att_propagate))
- push_temp_var (data);
- else
- dispose_variable (var);
-}
-
-/* Free the storage used in the hash table for temporary
- environment variables. PUSHF is a function to be called
- to free each hash table entry. It takes care of pushing variables
- to previous scopes if appropriate. */
-static void
-dispose_temporary_env (pushf)
- sh_free_func_t *pushf;
-{
- hash_flush (temporary_env, pushf);
- hash_dispose (temporary_env);
- temporary_env = (HASH_TABLE *)NULL;
-
- array_needs_making = 1;
-
- sv_ifs ("IFS"); /* XXX here for now */
-}
-
-void
-dispose_used_env_vars ()
-{
- if (temporary_env)
- dispose_temporary_env (propagate_temp_var);
-}
-
-/* Take all of the shell variables in the temporary environment HASH_TABLE
- and make shell variables from them at the current variable context. */
-void
-merge_temporary_env ()
-{
- if (temporary_env)
- dispose_temporary_env (push_temp_var);
-}
-
-/* **************************************************************** */
-/* */
-/* Creating and manipulating the environment */
-/* */
-/* **************************************************************** */
-
-static inline char *
-mk_env_string (name, value)
- const char *name, *value;
-{
- int name_len, value_len;
- char *p;
-
- name_len = strlen (name);
- value_len = STRLEN (value);
- p = (char *)xmalloc (2 + name_len + value_len);
- strcpy (p, name);
- p[name_len] = '=';
- if (value && *value)
- strcpy (p + name_len + 1, value);
- else
- p[name_len + 1] = '\0';
- return (p);
-}
-
-#ifdef DEBUG
-/* Debugging */
-static int
-valid_exportstr (v)
- SHELL_VAR *v;
-{
- char *s;
-
- s = v->exportstr;
- if (legal_variable_starter ((unsigned char)*s) == 0)
- {
- internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
- return (0);
- }
- for (s = v->exportstr + 1; s && *s; s++)
- {
- if (*s == '=')
- break;
- if (legal_variable_char ((unsigned char)*s) == 0)
- {
- internal_error (_("invalid character %d in exportstr for %s"), *s, v->name);
- return (0);
- }
- }
- if (*s != '=')
- {
- internal_error (_("no `=' in exportstr for %s"), v->name);
- return (0);
- }
- return (1);
-}
-#endif
-
-static char **
-make_env_array_from_var_list (vars)
- SHELL_VAR **vars;
-{
- register int i, list_index;
- register SHELL_VAR *var;
- char **list, *value;
-
- list = strvec_create ((1 + strvec_len ((char **)vars)));
-
-#define USE_EXPORTSTR (value == var->exportstr)
-
- for (i = 0, list_index = 0; var = vars[i]; i++)
- {
-#if defined (__CYGWIN__)
- /* We don't use the exportstr stuff on Cygwin at all. */
- INVALIDATE_EXPORTSTR (var);
-#endif
- if (var->exportstr)
- value = var->exportstr;
- else if (function_p (var))
- value = named_function_string ((char *)NULL, function_cell (var), 0);
-#if defined (ARRAY_VARS)
- else if (array_p (var))
-# if 0
- value = array_to_assignment_string (array_cell (var));
-# else
- continue; /* XXX array vars cannot yet be exported */
-# endif
-#endif
- else
- value = value_cell (var);
-
- if (value)
- {
- /* Gee, I'd like to get away with not using savestring() if we're
- using the cached exportstr... */
- list[list_index] = USE_EXPORTSTR ? savestring (value)
- : mk_env_string (var->name, value);
-
- if (USE_EXPORTSTR == 0)
- SAVE_EXPORTSTR (var, list[list_index]);
-
- list_index++;
-#undef USE_EXPORTSTR
-
-#if 0 /* not yet */
-#if defined (ARRAY_VARS)
- if (array_p (var))
- free (value);
-#endif
-#endif
- }
- }
-
- list[list_index] = (char *)NULL;
- return (list);
-}
-
-/* Make an array of assignment statements from the hash table
- HASHED_VARS which contains SHELL_VARs. Only visible, exported
- variables are eligible. */
-static char **
-make_var_export_array (vcxt)
- VAR_CONTEXT *vcxt;
-{
- char **list;
- SHELL_VAR **vars;
-
- vars = map_over (visible_and_exported, vcxt);
-
- if (vars == 0)
- return (char **)NULL;
-
- list = make_env_array_from_var_list (vars);
-
- free (vars);
- return (list);
-}
-
-static char **
-make_func_export_array ()
-{
- char **list;
- SHELL_VAR **vars;
-
- vars = map_over_funcs (visible_and_exported);
- if (vars == 0)
- return (char **)NULL;
-
- list = make_env_array_from_var_list (vars);
-
- free (vars);
- return (list);
-}
-
-/* Add ENVSTR to the end of the exported environment, EXPORT_ENV. */
-#define add_to_export_env(envstr,do_alloc) \
-do \
- { \
- if (export_env_index >= (export_env_size - 1)) \
- { \
- export_env_size += 16; \
- export_env = strvec_resize (export_env, export_env_size); \
- environ = export_env; \
- } \
- export_env[export_env_index++] = (do_alloc) ? savestring (envstr) : envstr; \
- export_env[export_env_index] = (char *)NULL; \
- } while (0)
-
-/* Add ASSIGN to EXPORT_ENV, or supercede a previous assignment in the
- array with the same left-hand side. Return the new EXPORT_ENV. */
-char **
-add_or_supercede_exported_var (assign, do_alloc)
- char *assign;
- int do_alloc;
-{
- register int i;
- int equal_offset;
-
- equal_offset = assignment (assign, 0);
- if (equal_offset == 0)
- return (export_env);
-
- /* If this is a function, then only supersede the function definition.
- We do this by including the `=() {' in the comparison, like
- initialize_shell_variables does. */
- if (assign[equal_offset + 1] == '(' &&
- strncmp (assign + equal_offset + 2, ") {", 3) == 0) /* } */
- equal_offset += 4;
-
- for (i = 0; i < export_env_index; i++)
- {
- if (STREQN (assign, export_env[i], equal_offset + 1))
- {
- free (export_env[i]);
- export_env[i] = do_alloc ? savestring (assign) : assign;
- return (export_env);
- }
- }
- add_to_export_env (assign, do_alloc);
- return (export_env);
-}
-
-static void
-add_temp_array_to_env (temp_array, do_alloc, do_supercede)
- char **temp_array;
- int do_alloc, do_supercede;
-{
- register int i;
-
- if (temp_array == 0)
- return;
-
- for (i = 0; temp_array[i]; i++)
- {
- if (do_supercede)
- export_env = add_or_supercede_exported_var (temp_array[i], do_alloc);
- else
- add_to_export_env (temp_array[i], do_alloc);
- }
-
- free (temp_array);
-}
-
-/* Make the environment array for the command about to be executed, if the
- array needs making. Otherwise, do nothing. If a shell action could
- change the array that commands receive for their environment, then the
- code should `array_needs_making++'.
-
- The order to add to the array is:
- temporary_env
- list of var contexts whose head is shell_variables
- shell_functions
-
- This is the shell variable lookup order. We add only new variable
- names at each step, which allows local variables and variables in
- the temporary environments to shadow variables in the global (or
- any previous) scope.
-*/
-
-static int
-n_shell_variables ()
-{
- VAR_CONTEXT *vc;
- int n;
-
- for (n = 0, vc = shell_variables; vc; vc = vc->down)
- n += HASH_ENTRIES (vc->table);
- return n;
-}
-
-void
-maybe_make_export_env ()
-{
- register char **temp_array;
- int new_size;
- VAR_CONTEXT *tcxt;
-
- if (array_needs_making)
- {
- if (export_env)
- strvec_flush (export_env);
-
- /* Make a guess based on how many shell variables and functions we
- have. Since there will always be array variables, and array
- variables are not (yet) exported, this will always be big enough
- for the exported variables and functions. */
- new_size = n_shell_variables () + HASH_ENTRIES (shell_functions) + 1 +
- HASH_ENTRIES (temporary_env);
- if (new_size > export_env_size)
- {
- export_env_size = new_size;
- export_env = strvec_resize (export_env, export_env_size);
- environ = export_env;
- }
- export_env[export_env_index = 0] = (char *)NULL;
-
- /* Make a dummy variable context from the temporary_env, stick it on
- the front of shell_variables, call make_var_export_array on the
- whole thing to flatten it, and convert the list of SHELL_VAR *s
- to the form needed by the environment. */
- if (temporary_env)
- {
- tcxt = new_var_context ((char *)NULL, 0);
- tcxt->table = temporary_env;
- tcxt->down = shell_variables;
- }
- else
- tcxt = shell_variables;
-
- temp_array = make_var_export_array (tcxt);
- if (temp_array)
- add_temp_array_to_env (temp_array, 0, 0);
-
- if (tcxt != shell_variables)
- free (tcxt);
-
-#if defined (RESTRICTED_SHELL)
- /* Restricted shells may not export shell functions. */
- temp_array = restricted ? (char **)0 : make_func_export_array ();
-#else
- temp_array = make_func_export_array ();
-#endif
- if (temp_array)
- add_temp_array_to_env (temp_array, 0, 0);
-
- array_needs_making = 0;
- }
-}
-
-/* This is an efficiency hack. PWD and OLDPWD are auto-exported, so
- we will need to remake the exported environment every time we
- change directories. `_' is always put into the environment for
- every external command, so without special treatment it will always
- cause the environment to be remade.
-
- If there is no other reason to make the exported environment, we can
- just update the variables in place and mark the exported environment
- as no longer needing a remake. */
-void
-update_export_env_inplace (env_prefix, preflen, value)
- char *env_prefix;
- int preflen;
- char *value;
-{
- char *evar;
-
- evar = (char *)xmalloc (STRLEN (value) + preflen + 1);
- strcpy (evar, env_prefix);
- if (value)
- strcpy (evar + preflen, value);
- export_env = add_or_supercede_exported_var (evar, 0);
-}
-
-/* We always put _ in the environment as the name of this command. */
-void
-put_command_name_into_env (command_name)
- char *command_name;
-{
- update_export_env_inplace ("_=", 2, command_name);
-}
-
-#if 0 /* UNUSED -- it caused too many problems */
-void
-put_gnu_argv_flags_into_env (pid, flags_string)
- intmax_t pid;
- char *flags_string;
-{
- char *dummy, *pbuf;
- int l, fl;
-
- pbuf = itos (pid);
- l = strlen (pbuf);
-
- fl = strlen (flags_string);
-
- dummy = (char *)xmalloc (l + fl + 30);
- dummy[0] = '_';
- strcpy (dummy + 1, pbuf);
- strcpy (dummy + 1 + l, "_GNU_nonoption_argv_flags_");
- dummy[l + 27] = '=';
- strcpy (dummy + l + 28, flags_string);
-
- free (pbuf);
-
- export_env = add_or_supercede_exported_var (dummy, 0);
-}
-#endif
-
-/* **************************************************************** */
-/* */
-/* Managing variable contexts */
-/* */
-/* **************************************************************** */
-
-/* Allocate and return a new variable context with NAME and FLAGS.
- NAME can be NULL. */
-
-VAR_CONTEXT *
-new_var_context (name, flags)
- char *name;
- int flags;
-{
- VAR_CONTEXT *vc;
-
- vc = (VAR_CONTEXT *)xmalloc (sizeof (VAR_CONTEXT));
- vc->name = name ? savestring (name) : (char *)NULL;
- vc->scope = variable_context;
- vc->flags = flags;
-
- vc->up = vc->down = (VAR_CONTEXT *)NULL;
- vc->table = (HASH_TABLE *)NULL;
-
- return vc;
-}
-
-/* Free a variable context and its data, including the hash table. Dispose
- all of the variables. */
-void
-dispose_var_context (vc)
- VAR_CONTEXT *vc;
-{
- FREE (vc->name);
-
- if (vc->table)
- {
- delete_all_variables (vc->table);
- hash_dispose (vc->table);
- }
-
- free (vc);
-}
-
-/* Set VAR's scope level to the current variable context. */
-static int
-set_context (var)
- SHELL_VAR *var;
-{
- return (var->context = variable_context);
-}
-
-/* Make a new variable context with NAME and FLAGS and a HASH_TABLE of
- temporary variables, and push it onto shell_variables. This is
- for shell functions. */
-VAR_CONTEXT *
-push_var_context (name, flags, tempvars)
- char *name;
- int flags;
- HASH_TABLE *tempvars;
-{
- VAR_CONTEXT *vc;
-
- vc = new_var_context (name, flags);
- vc->table = tempvars;
- if (tempvars)
- {
- /* Have to do this because the temp environment was created before
- variable_context was incremented. */
- flatten (tempvars, set_context, (VARLIST *)NULL, 0);
- vc->flags |= VC_HASTMPVAR;
- }
- vc->down = shell_variables;
- shell_variables->up = vc;
-
- return (shell_variables = vc);
-}
-
-static void
-push_func_var (data)
- PTR_T data;
-{
- SHELL_VAR *var, *v;
-
- var = (SHELL_VAR *)data;
-
- if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
- {
- /* XXX - should we set v->context here? */
- v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
- if (shell_variables == global_variables)
- var->attributes &= ~(att_tempvar|att_propagate);
- else
- shell_variables->flags |= VC_HASTMPVAR;
- v->attributes |= var->attributes;
- }
-
- dispose_variable (var);
-}
-
-/* Pop the top context off of VCXT and dispose of it, returning the rest of
- the stack. */
-void
-pop_var_context ()
-{
- VAR_CONTEXT *ret, *vcxt;
-
- vcxt = shell_variables;
- if (vc_isfuncenv (vcxt) == 0)
- {
- internal_error (_("pop_var_context: head of shell_variables not a function context"));
- return;
- }
-
- if (ret = vcxt->down)
- {
- ret->up = (VAR_CONTEXT *)NULL;
- shell_variables = ret;
- if (vcxt->table)
- hash_flush (vcxt->table, push_func_var);
- dispose_var_context (vcxt);
- }
- else
- internal_error (_("pop_var_context: no global_variables context"));
-}
-
-/* Delete the HASH_TABLEs for all variable contexts beginning at VCXT, and
- all of the VAR_CONTEXTs except GLOBAL_VARIABLES. */
-void
-delete_all_contexts (vcxt)
- VAR_CONTEXT *vcxt;
-{
- VAR_CONTEXT *v, *t;
-
- for (v = vcxt; v != global_variables; v = t)
- {
- t = v->down;
- dispose_var_context (v);
- }
-
- delete_all_variables (global_variables->table);
- shell_variables = global_variables;
-}
-
-/* **************************************************************** */
-/* */
-/* Pushing and Popping temporary variable scopes */
-/* */
-/* **************************************************************** */
-
-VAR_CONTEXT *
-push_scope (flags, tmpvars)
- int flags;
- HASH_TABLE *tmpvars;
-{
- return (push_var_context ((char *)NULL, flags, tmpvars));
-}
-
-static void
-push_exported_var (data)
- PTR_T data;
-{
- SHELL_VAR *var, *v;
-
- var = (SHELL_VAR *)data;
-
- /* If a temp var had its export attribute set, or it's marked to be
- propagated, bind it in the previous scope before disposing it. */
- /* XXX - This isn't exactly right, because all tempenv variables have the
- export attribute set. */
-#if 0
- if (exported_p (var) || (var->attributes & att_propagate))
-#else
- if (tempvar_p (var) && exported_p (var) && (var->attributes & att_propagate))
-#endif
- {
- var->attributes &= ~att_tempvar; /* XXX */
- v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
- if (shell_variables == global_variables)
- var->attributes &= ~att_propagate;
- v->attributes |= var->attributes;
- }
-
- dispose_variable (var);
-}
-
-void
-pop_scope (is_special)
- int is_special;
-{
- VAR_CONTEXT *vcxt, *ret;
-
- vcxt = shell_variables;
- if (vc_istempscope (vcxt) == 0)
- {
- internal_error (_("pop_scope: head of shell_variables not a temporary environment scope"));
- return;
- }
-
- ret = vcxt->down;
- if (ret)
- ret->up = (VAR_CONTEXT *)NULL;
-
- shell_variables = ret;
-
- /* Now we can take care of merging variables in VCXT into set of scopes
- whose head is RET (shell_variables). */
- FREE (vcxt->name);
- if (vcxt->table)
- {
- if (is_special)
- hash_flush (vcxt->table, push_func_var);
- else
- hash_flush (vcxt->table, push_exported_var);
- hash_dispose (vcxt->table);
- }
- free (vcxt);
-
- sv_ifs ("IFS"); /* XXX here for now */
-}
-
-/* **************************************************************** */
-/* */
-/* Pushing and Popping function contexts */
-/* */
-/* **************************************************************** */
-
-static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
-static int dollar_arg_stack_slots;
-static int dollar_arg_stack_index;
-
-/* XXX - we might want to consider pushing and popping the `getopts' state
- when we modify the positional parameters. */
-void
-push_context (name, is_subshell, tempvars)
- char *name; /* function name */
- int is_subshell;
- HASH_TABLE *tempvars;
-{
- if (is_subshell == 0)
- push_dollar_vars ();
- variable_context++;
- push_var_context (name, VC_FUNCENV, tempvars);
-}
-
-/* Only called when subshell == 0, so we don't need to check, and can
- unconditionally pop the dollar vars off the stack. */
-void
-pop_context ()
-{
- pop_dollar_vars ();
- variable_context--;
- pop_var_context ();
-
- sv_ifs ("IFS"); /* XXX here for now */
-}
-
-/* Save the existing positional parameters on a stack. */
-void
-push_dollar_vars ()
-{
- if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
- {
- dollar_arg_stack = (WORD_LIST **)
- xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
- * sizeof (WORD_LIST **));
- }
- dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
- dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
-}
-
-/* Restore the positional parameters from our stack. */
-void
-pop_dollar_vars ()
-{
- if (!dollar_arg_stack || dollar_arg_stack_index == 0)
- return;
-
- remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
- dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
- dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
- set_dollar_vars_unchanged ();
-}
-
-void
-dispose_saved_dollar_vars ()
-{
- if (!dollar_arg_stack || dollar_arg_stack_index == 0)
- return;
-
- dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
- dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
-}
-
-/* Manipulate the special BASH_ARGV and BASH_ARGC variables. */
-
-void
-push_args (list)
- WORD_LIST *list;
-{
-#if defined (ARRAY_VARS) && defined (DEBUGGER)
- SHELL_VAR *bash_argv_v, *bash_argc_v;
- ARRAY *bash_argv_a, *bash_argc_a;
- WORD_LIST *l;
- arrayind_t i;
- char *t;
-
- GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
- GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
-
- for (l = list, i = 0; l; l = l->next, i++)
- array_push (bash_argv_a, l->word->word);
-
- t = itos (i);
- array_push (bash_argc_a, t);
- free (t);
-#endif /* ARRAY_VARS && DEBUGGER */
-}
-
-/* Remove arguments from BASH_ARGV array. Pop top element off BASH_ARGC
- array and use that value as the count of elements to remove from
- BASH_ARGV. */
-void
-pop_args ()
-{
-#if defined (ARRAY_VARS) && defined (DEBUGGER)
- SHELL_VAR *bash_argv_v, *bash_argc_v;
- ARRAY *bash_argv_a, *bash_argc_a;
- ARRAY_ELEMENT *ce;
- intmax_t i;
-
- GET_ARRAY_FROM_VAR ("BASH_ARGV", bash_argv_v, bash_argv_a);
- GET_ARRAY_FROM_VAR ("BASH_ARGC", bash_argc_v, bash_argc_a);
-
- ce = array_shift (bash_argc_a, 1, 0);
- if (ce == 0 || legal_number (element_value (ce), &i) == 0)
- i = 0;
-
- for ( ; i > 0; i--)
- array_pop (bash_argv_a);
- array_dispose_element (ce);
-#endif /* ARRAY_VARS && DEBUGGER */
-}
-
-/*************************************************
- * *
- * Functions to manage special variables *
- * *
- *************************************************/
-
-/* Extern declarations for variables this code has to manage. */
-extern int eof_encountered, eof_encountered_limit, ignoreeof;
-
-#if defined (READLINE)
-extern int hostname_list_initialized;
-#endif
-
-/* An alist of name.function for each special variable. Most of the
- functions don't do much, and in fact, this would be faster with a
- switch statement, but by the end of this file, I am sick of switch
- statements. */
-
-#define SET_INT_VAR(name, intvar) intvar = find_variable (name) != 0
-
-/* This table will be sorted with qsort() the first time it's accessed. */
-struct name_and_function {
- char *name;
- sh_sv_func_t *function;
-};
-
-static struct name_and_function special_vars[] = {
-#if defined (READLINE)
-# if defined (STRICT_POSIX)
- { "COLUMNS", sv_winsize },
-# endif
- { "COMP_WORDBREAKS", sv_comp_wordbreaks },
-#endif
-
- { "GLOBIGNORE", sv_globignore },
-
-#if defined (HISTORY)
- { "HISTCONTROL", sv_history_control },
- { "HISTFILESIZE", sv_histsize },
- { "HISTIGNORE", sv_histignore },
- { "HISTSIZE", sv_histsize },
- { "HISTTIMEFORMAT", sv_histtimefmt },
-#endif
-
-#if defined (__CYGWIN__)
- { "HOME", sv_home },
-#endif
-
-#if defined (READLINE)
- { "HOSTFILE", sv_hostfile },
-#endif
-
- { "IFS", sv_ifs },
- { "IGNOREEOF", sv_ignoreeof },
-
- { "LANG", sv_locale },
- { "LC_ALL", sv_locale },
- { "LC_COLLATE", sv_locale },
- { "LC_CTYPE", sv_locale },
- { "LC_MESSAGES", sv_locale },
- { "LC_NUMERIC", sv_locale },
- { "LC_TIME", sv_locale },
-
-#if defined (READLINE) && defined (STRICT_POSIX)
- { "LINES", sv_winsize },
-#endif
-
- { "MAIL", sv_mail },
- { "MAILCHECK", sv_mail },
- { "MAILPATH", sv_mail },
-
- { "OPTERR", sv_opterr },
- { "OPTIND", sv_optind },
-
- { "PATH", sv_path },
- { "POSIXLY_CORRECT", sv_strict_posix },
-
-#if defined (READLINE)
- { "TERM", sv_terminal },
- { "TERMCAP", sv_terminal },
- { "TERMINFO", sv_terminal },
-#endif /* READLINE */
-
- { "TEXTDOMAIN", sv_locale },
- { "TEXTDOMAINDIR", sv_locale },
-
-#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
- { "TZ", sv_tz },
-#endif
-
-#if defined (HISTORY) && defined (BANG_HISTORY)
- { "histchars", sv_histchars },
-#endif /* HISTORY && BANG_HISTORY */
-
- { "ignoreeof", sv_ignoreeof },
-
- { (char *)0, (sh_sv_func_t *)0 }
-};
-
-#define N_SPECIAL_VARS (sizeof (special_vars) / sizeof (special_vars[0]) - 1)
-
-static int
-sv_compare (sv1, sv2)
- struct name_and_function *sv1, *sv2;
-{
- int r;
-
- if ((r = sv1->name[0] - sv2->name[0]) == 0)
- r = strcmp (sv1->name, sv2->name);
- return r;
-}
-
-static inline int
-find_special_var (name)
- const char *name;
-{
- register int i, r;
-
- for (i = 0; special_vars[i].name; i++)
- {
- r = special_vars[i].name[0] - name[0];
- if (r == 0)
- r = strcmp (special_vars[i].name, name);
- if (r == 0)
- return i;
- else if (r > 0)
- /* Can't match any of rest of elements in sorted list. Take this out
- if it causes problems in certain environments. */
- break;
- }
- return -1;
-}
-
-/* The variable in NAME has just had its state changed. Check to see if it
- is one of the special ones where something special happens. */
-void
-stupidly_hack_special_variables (name)
- char *name;
-{
- static int sv_sorted = 0;
- int i;
-
- if (sv_sorted == 0) /* shouldn't need, but it's fairly cheap. */
- {
- qsort (special_vars, N_SPECIAL_VARS, sizeof (special_vars[0]),
- (QSFUNC *)sv_compare);
- sv_sorted = 1;
- }
-
- i = find_special_var (name);
- if (i != -1)
- (*(special_vars[i].function)) (name);
-}
-
-void
-sv_ifs (name)
- char *name;
-{
- SHELL_VAR *v;
-
- v = find_variable ("IFS");
- setifs (v);
-}
-
-/* What to do just after the PATH variable has changed. */
-void
-sv_path (name)
- char *name;
-{
- /* hash -r */
- phash_flush ();
-}
-
-/* What to do just after one of the MAILxxxx variables has changed. NAME
- is the name of the variable. This is called with NAME set to one of
- MAIL, MAILCHECK, or MAILPATH. */
-void
-sv_mail (name)
- char *name;
-{
- /* If the time interval for checking the files has changed, then
- reset the mail timer. Otherwise, one of the pathname vars
- to the users mailbox has changed, so rebuild the array of
- filenames. */
- if (name[4] == 'C') /* if (strcmp (name, "MAILCHECK") == 0) */
- reset_mail_timer ();
- else
- {
- free_mail_files ();
- remember_mail_dates ();
- }
-}
-
-/* What to do when GLOBIGNORE changes. */
-void
-sv_globignore (name)
- char *name;
-{
- setup_glob_ignore (name);
-}
-
-#if defined (READLINE)
-void
-sv_comp_wordbreaks (name)
- char *name;
-{
- SHELL_VAR *sv;
-
- sv = find_variable (name);
- if (sv == 0)
- rl_completer_word_break_characters = (char *)NULL;
-}
-
-/* What to do just after one of the TERMxxx variables has changed.
- If we are an interactive shell, then try to reset the terminal
- information in readline. */
-void
-sv_terminal (name)
- char *name;
-{
- if (interactive_shell && no_line_editing == 0)
- rl_reset_terminal (get_string_value ("TERM"));
-}
-
-void
-sv_hostfile (name)
- char *name;
-{
- SHELL_VAR *v;
-
- v = find_variable (name);
- if (v == 0)
- clear_hostname_list ();
- else
- hostname_list_initialized = 0;
-}
-
-#if defined (STRICT_POSIX)
-/* In strict posix mode, we allow assignments to LINES and COLUMNS (and values
- found in the initial environment) to override the terminal size reported by
- the kernel. */
-void
-sv_winsize (name)
- char *name;
-{
- SHELL_VAR *v;
- intmax_t xd;
- int d;
-
- if (posixly_correct == 0 || interactive_shell == 0 || no_line_editing)
- return;
-
- v = find_variable (name);
- if (v == 0 || var_isnull (v))
- rl_reset_screen_size ();
- else
- {
- if (legal_number (value_cell (v), &xd) == 0)
- return;
- winsize_assignment = winsize_assigned = 1;
- d = xd; /* truncate */
- if (name[0] == 'L') /* LINES */
- rl_set_screen_size (d, -1);
- else /* COLUMNS */
- rl_set_screen_size (-1, d);
- winsize_assignment = 0;
- }
-}
-#endif /* STRICT_POSIX */
-#endif /* READLINE */
-
-/* Update the value of HOME in the export environment so tilde expansion will
- work on cygwin. */
-#if defined (__CYGWIN__)
-sv_home (name)
- char *name;
-{
- array_needs_making = 1;
- maybe_make_export_env ();
-}
-#endif
-
-#if defined (HISTORY)
-/* What to do after the HISTSIZE or HISTFILESIZE variables change.
- If there is a value for this HISTSIZE (and it is numeric), then stifle
- the history. Otherwise, if there is NO value for this variable,
- unstifle the history. If name is HISTFILESIZE, and its value is
- numeric, truncate the history file to hold no more than that many
- lines. */
-void
-sv_histsize (name)
- char *name;
-{
- char *temp;
- intmax_t num;
- int hmax;
-
- temp = get_string_value (name);
-
- if (temp && *temp)
- {
- if (legal_number (temp, &num))
- {
- hmax = num;
- if (name[4] == 'S')
- {
- stifle_history (hmax);
- hmax = where_history ();
- if (history_lines_this_session > hmax)
- history_lines_this_session = hmax;
- }
- else
- {
- history_truncate_file (get_string_value ("HISTFILE"), hmax);
- if (hmax <= history_lines_in_file)
- history_lines_in_file = hmax;
- }
- }
- }
- else if (name[4] == 'S')
- unstifle_history ();
-}
-
-/* What to do after the HISTIGNORE variable changes. */
-void
-sv_histignore (name)
- char *name;
-{
- setup_history_ignore (name);
-}
-
-/* What to do after the HISTCONTROL variable changes. */
-void
-sv_history_control (name)
- char *name;
-{
- char *temp;
- char *val;
- int tptr;
-
- history_control = 0;
- temp = get_string_value (name);
-
- if (temp == 0 || *temp == 0)
- return;
-
- tptr = 0;
- while (val = extract_colon_unit (temp, &tptr))
- {
- if (STREQ (val, "ignorespace"))
- history_control |= HC_IGNSPACE;
- else if (STREQ (val, "ignoredups"))
- history_control |= HC_IGNDUPS;
- else if (STREQ (val, "ignoreboth"))
- history_control |= HC_IGNBOTH;
- else if (STREQ (val, "erasedups"))
- history_control |= HC_ERASEDUPS;
-
- free (val);
- }
-}
-
-#if defined (BANG_HISTORY)
-/* Setting/unsetting of the history expansion character. */
-void
-sv_histchars (name)
- char *name;
-{
- char *temp;
-
- temp = get_string_value (name);
- if (temp)
- {
- history_expansion_char = *temp;
- if (temp[0] && temp[1])
- {
- history_subst_char = temp[1];
- if (temp[2])
- history_comment_char = temp[2];
- }
- }
- else
- {
- history_expansion_char = '!';
- history_subst_char = '^';
- history_comment_char = '#';
- }
-}
-#endif /* BANG_HISTORY */
-
-void
-sv_histtimefmt (name)
- char *name;
-{
- SHELL_VAR *v;
-
- v = find_variable (name);
- history_write_timestamps = (v != 0);
-}
-#endif /* HISTORY */
-
-#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
-void
-sv_tz (name)
- char *name;
-{
- tzset ();
-}
-#endif
-
-/* If the variable exists, then the value of it can be the number
- of times we actually ignore the EOF. The default is small,
- (smaller than csh, anyway). */
-void
-sv_ignoreeof (name)
- char *name;
-{
- SHELL_VAR *tmp_var;
- char *temp;
-
- eof_encountered = 0;
-
- tmp_var = find_variable (name);
- ignoreeof = tmp_var != 0;
- temp = tmp_var ? value_cell (tmp_var) : (char *)NULL;
- if (temp)
- eof_encountered_limit = (*temp && all_digits (temp)) ? atoi (temp) : 10;
- set_shellopts (); /* make sure `ignoreeof' is/is not in $SHELLOPTS */
-}
-
-void
-sv_optind (name)
- char *name;
-{
- char *tt;
- int s;
-
- tt = get_string_value ("OPTIND");
- if (tt && *tt)
- {
- s = atoi (tt);
-
- /* According to POSIX, setting OPTIND=1 resets the internal state
- of getopt (). */
- if (s < 0 || s == 1)
- s = 0;
- }
- else
- s = 0;
- getopts_reset (s);
-}
-
-void
-sv_opterr (name)
- char *name;
-{
- char *tt;
-
- tt = get_string_value ("OPTERR");
- sh_opterr = (tt && *tt) ? atoi (tt) : 1;
-}
-
-void
-sv_strict_posix (name)
- char *name;
-{
- SET_INT_VAR (name, posixly_correct);
- posix_initialize (posixly_correct);
-#if defined (READLINE)
- if (interactive_shell)
- posix_readline_initialize (posixly_correct);
-#endif /* READLINE */
- set_shellopts (); /* make sure `posix' is/is not in $SHELLOPTS */
-}
-
-void
-sv_locale (name)
- char *name;
-{
- char *v;
-
- v = get_string_value (name);
- if (name[0] == 'L' && name[1] == 'A') /* LANG */
- set_lang (name, v);
- else
- set_locale_var (name, v); /* LC_*, TEXTDOMAIN* */
-}
-
-#if defined (ARRAY_VARS)
-void
-set_pipestatus_array (ps, nproc)
- int *ps;
- int nproc;
-{
- SHELL_VAR *v;
- ARRAY *a;
- ARRAY_ELEMENT *ae;
- register int i;
- char *t, tbuf[INT_STRLEN_BOUND(int) + 1];
-
- v = find_variable ("PIPESTATUS");
- if (v == 0)
- v = make_new_array_variable ("PIPESTATUS");
- if (array_p (v) == 0)
- return; /* Do nothing if not an array variable. */
- a = array_cell (v);
-
- if (a == 0 || array_num_elements (a) == 0)
- {
- for (i = 0; i < nproc; i++) /* was ps[i] != -1, not i < nproc */
- {
- t = inttostr (ps[i], tbuf, sizeof (tbuf));
- array_insert (a, i, t);
- }
- return;
- }
-
- /* Fast case */
- if (array_num_elements (a) == nproc && nproc == 1)
- {
- ae = element_forw (a->head);
- free (element_value (ae));
- ae->value = itos (ps[0]);
- }
- else if (array_num_elements (a) <= nproc)
- {
- /* modify in array_num_elements members in place, then add */
- ae = a->head;
- for (i = 0; i < array_num_elements (a); i++)
- {
- ae = element_forw (ae);
- free (element_value (ae));
- ae->value = itos (ps[i]);
- }
- /* add any more */
- for ( ; i < nproc; i++)
- {
- t = inttostr (ps[i], tbuf, sizeof (tbuf));
- array_insert (a, i, t);
- }
- }
- else
- {
- /* deleting elements. it's faster to rebuild the array. */
- array_flush (a);
- for (i = 0; ps[i] != -1; i++)
- {
- t = inttostr (ps[i], tbuf, sizeof (tbuf));
- array_insert (a, i, t);
- }
- }
-}
-#endif
-
-void
-set_pipestatus_from_exit (s)
- int s;
-{
-#if defined (ARRAY_VARS)
- static int v[2] = { 0, -1 };
-
- v[0] = s;
- set_pipestatus_array (v, 1);
-#endif
-}