+++ /dev/null
- 7/27/2004
- ---------
-
-[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/2006
- --------
-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_expansion
- and bash_directory_completion_hook
-
-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 <vapier@gentoo.org>
-
-{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
- ---
-[bash-3.2-beta released]
-
- 9/8
- ---
-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>
-
-builtins/echo.def,doc/{bash.1,bashref.texi}
- - clarify that `echo -e' and echo when the `xpg_echo' shell option is
- enabled require the \0 to precede any octal constant to be expanded.
- Reported by Vasco Pedro <vp@di.uevora.pt>
-
- 9/12
- ----
-builtins/printf.def
- - make sure `%q' format specifier outputs '' for empty string arguments
- Bug reported by Egmont Koblinger <egmont@uhulinux.hu>
-
-make_cmd.c
- - change make_here_document to echo lines in here-doc if set -v has
- been executed. Reported by Eduardo Ochs <eduardoochs@gmail.com>
-
-aclocal.m4
- - change BASH_CHECK_MULTIBYTE:
- o replace check for wctomb with check for wcrtomb
- o add checks for wcscoll, iswctype, iswupper, iswlower,
- towupper, towlower
- o add call to AC_FUNC_MBRTOWC to check for mbrtowc and mbstate_t
- define HAVE_MBSTATE_T manually
- o add checks for wchar_t, wctype_t, wint_t
-
-config.h.in
- - add defines for wcscoll, iswctype, iswupper, iswlower, towupper,
- towlower functions
- - replace define for wctomb with one for wcrtomb
- - add defines for wchar_t, wint_t, wctype_t types
-
-config-bot.h, lib/readline/rlmbutil.h
- - add check for HAVE_LOCALE_H before defining HANDLE_MULTIBYTE
- - add checks for: ISWCTYPE, ISWLOWER, ISWUPPER, TOWLOWER, TOWUPPER
- - add checks for: WCTYPE_T, WCHAR_T, WCTYPE_T
-
- 9/13
- ----
-lib/readline/display.c
- - when displaying prompts longer than the screenwidth in rl_redisplay,
- and looking for the index of the last character whose buffer index
- is <= the screen width to set up the inv_lbreaks array, make sure to
- catch the case where the index == the screen width (an off-by-one
- error occurs otherwise with prompts one character longer than the
- screen width). Bug reported by Alexey Toptygin <alexeyt@freeshell.org>
-
-configure.in
- - change DEBUGGER_START_FILE to start with ${ac_default_prefix}/share,
- like bashdb installs itself. Reported by Nick Brown
- <nickbroon@blueyonder.co.uk>
-
- 9/14
- ----
-lib/readline/display.c
- - make multibyte code that computes the buffer indices of line breaks
- for a multi-line prompt dependent on MB_CUR_MAX, so we don't take
- the function call hit unless we're in a locale that can have
- multibyte characters
-
- 9/19
- ----
-subst.c
- - make dequote_list extern so other parts of the shell can use it
-
-subst.h
- - extern declaration for dequote_list
-
-builtins/read.def
- - call dequote_list before assigning words read to array variable if
- we saw an escape character. Old code left spurious CTLESCs in the
- string after processing backslashes. Bug reported by Daniel Dawson
- <ddawson@icehouse.net>
-
- 9/21
- ----
-[bash-3.2 frozen]
-
- 10/9
- ----
-support/shobj-coonf
- - change -fpic to -fPIC for FreeBSD systems (needed for SPARC at least)
-
- 10/11
- -----
-[bash-3.2 released]
-
- 10/12
- -----
-parse.y
- - change parse_matched_pair to make sure `` command substitution does
- not check for shell comments while parsing. Bug reported against
- bash-3.2 by Greg Schaefer <gschafer@zip.com.au>
-
- 10/14
- -----
-parse.y
- - add new parser_state flag: PST_REGEXP; means we are parsing a
- regular expression following the =~ conditional operator
- - cond_node sets PST_REGEXP after reading the `=~' operator
- - change read_token to call read_token_word immediately if the
- PST_REGEXP bit is set in parser_state
- - change read_token_word to skip over `(' and `|' if PST_REGEXP is
- set, since those characters are legitimate regexp chars (but still
- parse matched pairs of parens)
-
- 10/16
- -----
-builtins/ulimit.def
- - add -e and -r to $SHORT_DOC usage string
-
-po/ru.po
- - fix encoding; Russian text in the file is actually encoded in KOI8-R
-
- 10/23
- -----
-shell.c
- - make sure that the call to move_to_high_fd in open_shell_script
- passes 1 for the `check_new' parameter so open high file descriptors
- don't get closed and reused. Bug reported by Mike Stroyan
- <mike.stroyan@hp.com>
-
-doc/bashref.texi
- - fixes for typos and misspellings sent in by Brian Gough
-
- 10/24
- -----
-support/shobj-conf
- - make netbsd shared library creation like openbsd's until I hear
- differently (called using `gcc -shared')
-
- 10/26
- -----
-subst.c
- - fix bug in parameter_brace_patsub so if the first character of the
- expanded pattern is a `/', it is not taken as a global replacement
- specifier. Bug reported on forums.nekochan.net
-
- 10/27
- -----
-builtins/printf.def
- - if we need an extern declaration for asprintf, make sure we include
- stdarg.h or varargs.h, whichever is appropriate
- - if we do not have asprintf, add an extern declaration using
- stdarg format. This fixes the bugs with %G on IRIX reported by
- Matthew Woehlke <mwoehlke@tibco.com> and Stuart Shelton
- <srcshelton@gmail.com>
-
-
-lib/sh/snprintf.c
- - add note to not call log_10 with 0 argument -- we don't want to do
- what real log10 does (-infinity/raise divide-by-zero exception)
- - make sure numtoa (used by dtoa) takes the precision into account
- when computing the fractional part with an argument of `0.0'
- - make sure `g' and `G' formats don't print radix char if there are
- no characters to be printed after it (change to floating())
- - change callers of log_10 (exponent, 'g' and 'G' cases in
- vsnprintf_internal) to not call it with 0 for argument. This fixes
- the hang reported on IRIX by Matthew Woehlke <mwoehlke@tibco.com>
- and Stuart Shelton <mwoehlke@tibco.com>
-
- 10/28
- -----
-builtins/{caller,pushd}.def
- - changed longdoc strings in loadable builtin section to be single
- strings, as put in the build directory builtins.c file, to aid
- translators
-
- 11/1
- ----
-execute_cmd.c
- - reset subshell_environment to 0 after make_child() call in
- execute_null_command. Fix provided by Roy Marples
- <uberlord@gentoo.org>
-
- 11/7
- ----
-lib/tilde/tilde.c
-lib/readline/{util,undo,callback,input,isearch,kill}.c
- - make sure that memory allocated with xmalloc is freed with xfree
-
- 11/9
- ----
-lib/readline/display.c
- - make sure that _rl_redisplay_after_sigwinch clears the last displayed
- line instead of the current line (instead of assuming that the
- cursor is on the last line). Fixes bug reported by Egmont
- Koblinger <egmont@uhulinux.hu>
-
- 11/10
- -----
-lib/readline/display.c
- - make sure that _rl_col_width is never called with MB_CUR_MAX == 1,
- since it doesn't count invisible characters and they are not
- compensated for. Added a warning in _rl_col_width if called when
- MB_CUR_MAX == 1. Bug reported and solution suggested by Eric
- Blake <ebb9@byu.net>
-
- 11/11
- -----
-lib/readline/display.c
- - make sure _rl_wrapped_line is initialized to inv_lbsize int chars.
- inv_lbsize and vis_lbsize are the same at that point, but it makes
- the intent clearer. Fix from jan.kratochvil@redhat.com.
- - in rl_redisplay, make sure we call memset on _rl_wrapped_line with
- its full initialized size: inv_lbsize*sizeof(int). Fix from
- jan.kratochvil@redhat.com.
- - wrap the invisible and visible line variables and _rl_wrapped_line
- into line_state structures, which can be swapped more efficiently.
- Have to watch the wrapped_line field, since there's now one for
- each struct. Changes from jan.kratochvil@redhat.com.
-
-lib/readline/complete.c
- - in stat_char, check for `//server' on cygwin and return `/', since
- it will always behave as a directory. Fix from Eric Blake
-
-lib/readline/histfile.c
- - Cygwin's mmap() works in recent versions, so don't #undef HAVE_MMAP.
- Recommendation from Eric Blake
-
-lib/readline/rlwinsize.h
- - make sure tcflow() is defined on SCO Unix. Fix from William Bader
-
-aclocal.m4
- - add check for localeconv to AM_INTL_SUBDIR macro
-
-config.h.in
- - add HAVE_LOCALECONV
-
-lib/sh/snprintf.c
- - add check for HAVE_LOCALECONV for GETLOCALEDATA macro
-
-general.[ch]
- - first argument to legal_number is now `const char *'
-
- 11/14
- -----
-lib/readline/{readline,rlprivate}.h
- - move rl_display_prompt declaration from rlprivate.h to readline.h
-
-lib/readline/util.h
- - new function: rl_free(void *mem), for use by users of readline dlls
- on Windows
-
-lib/readline/readline.h
- - new extern declaration for rl_free
-
-lib/readline/doc/rltech.texi
- - document rl_free and rl_display_prompt for use by application writers
-
- 11/15
- -----
-aclocal.m4
- - change tests for /dev/fd and /dev/stdin to use constructs of the form
- (exec test ... ) instead of test ... to avoid bash's /dev/fd and
- /dev/stdin emulation
-
- 11/16
- -----
-jobs.c
- - in delete_job, reset_current was being called before the job slot
- was cleared -- moved after job_slots[job] was set to NULL. Fixes
- bug reported by Dan Jacobson <jidanni@jidanni.org>
-
- 11/19
- -----
-findcmd.c
- - when the checkhash option is set, fix the check for the hashed
- pathname being an existing executable file. Old code required a
- hash table deletion and re-addition. Bug reported by Linda
- Walsh <bash@tlinx.org>
-
- 11/21
- -----
-subst.c
- - in pos_params, handle case of `start' == 0 by making the list of
- positional parameters begin with $0
- - in parameter_brace_substring, increment `len' if start == 0, sicne
- we will be adding $0 to the beginning of the list when we process it
-
-doc/{bash.1,bashref.texi}
- - document new behavior of `0' offset when using substring expansion
- with the positional parameters
-
-support/shobj-conf
- - changes to shared object creation for loadable builtins on Mac OS X
- 10.4 to use libtool instead of ld by specifying -dynamiclib
- argument and changing options to be appropriate for libtool. This
- winds up creating a dynamic shared library instead of an executable
-
- 11/24
- -----
-{jobs,nojobs}.c
- - don't set last_asynchronous_pid to the child's pid in the child
- for asynchronous jobs (for compatibility -- all other posix shells
- seem to do it this way). This means that (echo $! )& echo $! should
- display two different pids. Fix from discussion on the
- austin-group-l list
-
-builtins/mkbuiltins.c
- - change builtins.c file generation so short doc strings are marked for
- gettext and available for subsequent translation. Suggestion by
- Benno Schulenberg <bensberg@justemail.net>
-
-builtins/{bind,cd,hash,inlib,printf,pushd,test,times,ulimit}.def
-lib/malloc/malloc.c
-{shell,subst}.c
- - fix a few strings that were not marked as translatable. Fix from
- Benno Schulenberg <bensberg@justemail.net>
-
-lib/readline/misc.c
- - new function, _rl_revert_all_lines(void). Goes through history,
- reverting all entries to their initial state by undoing any undo
- lists.
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_revert_all_lines
-
-rldefs.h
- - add #undef HAVE_STRCOLL if STRCOLL_BROKEN is defined, prep to move
- from config.h.in. Problem reported by Valerly Ushakov
- <uwe@ptc.spbu.ru>
-
- 11/25
- -----
-lib/readline/readline.c
- - call _rl_revert_all_lines from readline_internal_teardown if the
- variable _rl_revert_all_at_newline is non-zero
- - declare _rl_revert_all_lines initially 0
-
- 11/27
- -----
-doc/{bash.1,bashref.texi}
- - make sure to be explicit that `typeset +r' cannot remove the readonly
- attribute from a variable
-
- 11/28
- -----
-lib/sh/zmapfd.c
- - new file, implements zmapfd(), which takes a file and returns its
- contents in a string
-
-externs.h
- - extern declaration for zmapfd
-
- 11/29
- -----
-builtins/evalfile.c
- - in _evalfile, use zmapfd to read the contents of the file into a
- string, rather than using the size reported by stat and reading that
- many characters, if the file is not a regular file (for things like
- named pipes, stat reports the size as 0)
-
- 12/3
- ----
-lib/sh/snprintf.c
- - make sure number() sets the FL_UNSIGNED flag for %x and %X, so
- fmtulong treats them as unsigned numbers. Fixes bug reported by
- James Botte <James.M.Botte@lowes.com>
-
- 12/13
- -----
-lib/readline/util.c
- - new function, _rl_ttymsg, for internal warning messages -- does
- redisplay after printing message
- - new function, _rl_errmsg, for internal warning/error messages --
- does not do redisplay after printing message
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_ttymsg, _rl_errmsg
-
-lib/readline/{bind,callback,complete,display,rltty}.c
- - use _rl_ttymsg/_rl_errmsg instead of direct writes to stderr
-
-lib/sh/tmpfile.c
- - in get_tmpdir(), make sure that $TMPDIR names a writable directory;
- otherwise skip it. This catches names longer than PATH_MAX, but in
- case it doesn't test that the length does not exceed PATH_MAX. Fixes
- heap overrun bug reported by Eric Blake <ebb9@byu.net>
-
- 12/16
- -----
-builtin/{set,declare,shopt,trap,wait,bind,complete,enable,fc,history,read,setattr}.def
-doc/{bash.1,bashref.texi}
- - improvements and clarifications to the help text associated with
- several builtins, in some cases bringing them into line with the
- man page text. From Benno Schulenberg <bensberg@justemail.net>
-
-doc/{bash.1,bashref.texi}
- - add `E' and `T' to the synopsis of the set builtin.
- From Benno Schulenberg <bensberg@justemail.net>
-
-builtins/{break,exit,fg_bg,hash,jobs,type,ulimit}.def
-builtins/{common,evalfile}.c
-{error,expr,jobs,mksyntax,nojobs,shell,subst,version,siglist}.c
- - add gettextizing marks to untranslated strings
- From Benno Schulenberg <bensberg@justemail.net>
-
- 12/19
- -----
-builtins/common.c
- - change display_signal_list (used by `trap -l' and `kill -l') to use
- five columns instead of 4 to display signal names
-
-builtins/help.def
- - use the true terminal width instead of assuming 80 when displaying
- help topics, leaving two characters of whitespace between horizontal
- descriptions instead of 1
- - change to print in columns with entries sorted down rather than across
- (that is, like `ls' rather than `ls -x'). Change inspired by Benno
- Schulenberg <bensberg@justemail.net>
-
-jobs.h
- - give values to the JOB_STATE enumerations so they can be used as
- bitmasks, too
-
- 12/22
- -----
-doc/{bash.1,bashref.texi}
- - change description of `set' to make it clearer that you can use
- `+' to turn off options
- - clarify in the description of word splitting that sequences of
- IFS whitespace at the beginning or end of the string are ignored
-
- 12/26
- -----
-doc/bashref.texi
- - move `shopt' builtin to its own section; change internal references
- from `Bash Builtins' to the new shopt builtin
- - new section for builtins that modify shell behavior in `Shell
- Builtin Commands'; move set and shopt to new section. Changes
- inspired by Benno Schulenberg <bensberg@justemail.net>
-
-{redir,subst}.c
- - add MT_USETMPDIR flag to calls to sh_mktmpfd and sh_mktmpname. Bug
- reported by Eric Blake <ebb9@byu.net>
-
-{configure,Makefile}.in
- - changes so that the pathname for DEBUGGER_START_FILE is substituted
- into pathnames.h at make time (allowing more flexibility in setting
- `prefix' or `datadir') instead of at configure time. Suggested by
- Nick Brown <nickbroon@blueyonder.co.uk>
-
-shell.c
- - declaration for have_devfd; initialized from HAVE_DEV_FD
- - declaration for check_jobs_at_exit; initialized to 0
- - declaration for autocd; initialized to 0
-
-variables.c
- - new dynamic variable, BASHPID, always set from return value from
- getpid() (changes even when $$ doesn't change). Idea from Bruce
- Korb <bruce.corb@3pardata.com>
-
-builtins/exit.def
- - if check_jobs_at_exit is non-zero, list jobs if there are any stopped
- or running background jobs; don't exit shell if any running jobs
-
-execute_cmd.c
- - in execute_simple_command, if the first word of a simple command is
- a directory name (after looking for builtins, so `.' isn't caught)
- that isn't found in $PATH, and `autocd' is non-zero, prefix a "cd"
- to the command words
-
-builtins/shopt.def
- - new `checkjobs' option, changes value of check_jobs_at_exit
- - new `autocd' option, changes value of autocd
-
-pcomplete.c
- - add COMP_TYPE, set to rl_completion_type, to list of variables set
- by bind_compfunc_variables and unset by unbind_compfunc_variables
-
-doc/{bash.1,bashref.texi}
- - document BASHPID
- - document new shopt `checkjobs' option
- - document new shopt `autocd' option
- - document COMP_TYPE completion variable
-
- 12/29
- -----
-aclocal.m4
- - in BASH_SYS_SIGLIST, check HAVE_DECL_SYS_SIGLIST instead of the
- obsolete and no-longer-supported SYS_SIGLIST_DECLARED
-
- 12/30
- -----
-lib/readline/vi_mode.c
- - add ` (backquote) to the list of vi motion characters
- - in rl_vi_delete_to, rl_vi_change_to, and rl_vi_yank_to, don't delete
- character under the cursor if the motion command moves the cursor
- backward, so add F and T to the commands that don't cause the
- mark to be adjusted
- - add ` to the characters that don't cause the mark to be adjusted
- when used as a motion command, since it's defined to behave that way
- - when a motion character that may adjust the mark moves point
- backward, don't adjust the mark so the character under the cursor
- isn't deleted
-
-lib/readline/complete.c
- - add variable rl_sort_completion_matches; allows application to
- inhibit match list sorting
- - add variable rl_completion_invoking_key; allows applications to
- discover the key that invoked rl_complete or rl_menu_complete
-
-lib/readline/readline.h
- - extern declarations for rl_completion_invoking_key and
- rl_sort_completion_matches
-
-lib/readline/doc/rltech.texi
- - documented rl_completion_invoking_key and rl_sort_completion_matches
-
-pcomplete.c
- - export variable COMP_KEY to completion functions; initialized from
- rl_completion_invoking_key; unset along with rest of completion
- variables
-
-doc/{bash.1,bashref.texi},lib/readline/doc/rluser.texi
- - document COMP_KEY
-
-[many files]
- - changes to make variables and function parameters `const' for better
- text sharing. Changes originally from Andreas Mohr
- <andi@rhlx01.fht-esslingen.de>
-
- 1/4/2007
- --------
-lib/intl/Makefile.in
- - use cmp before copying libgnuintl.h to libintl.h -- maybe save a few
- rebuilds
-
-lib/builtins/Makefile
- - fixes to build LIBINTL_H if necessary, dependency on this for
- mkbuiltins.o prevented `make -j 6' from working correctly
-
- 1/8
- ---
-subst.c
- - new function, fifos_pending(), returns the count of FIFOs in
- fifo_list (process substitution)
-
-subst.h
- - extern declaration for fifos_pending()
-
-execute_cmd.c
- - in execute_simple_command, if CMD_NO_FORK is set before we call
- execute_disk_command, make sure there are no FIFOs in the expanded
- words (from process substitution) and turn off CMD_NO_FORK if there
- are, so they can get unlinked when the command finishes
-
- 1/10
- ----
-subst.c
- - read_comsub now takes a flags parameter and returns appropriate W_*
- flags in it
- - command_substitute now returns a WORD_DESC *, with the string it used
- to return as the `word' and `flags' filled in appropriately
-
-subst.h
- - changed extern declaration for command_substitute
-
-{pcomplete,subst}.c
- - changed callers of command_substitute appropriately
-
-subst.c
- - string_extract_verbatim now takes an additional int flags argument;
- changed callers
-
- 1/11
- ----
-support/texi2html
- - fix problem that caused index links to not be generated if the first
- index node had a name different than the node name
-
-doc/bashref.texi
- - encapsulated all indexes into a single `Indexes' appendix; works
- around bug fixed in texi2html
-
- 1/12
- ----
-subst.c
- - add call to sv_histtimefmt in initialize_variables so HISTTIMEFORMAT
- from the environment is honored. Fix from Ark Submedes (heh)
- <archimerged@gmail.com>
-
-lib/readline/histfile.c
- - make sure that the first character following the history comment
- character at the beginning of a line is a digit before interpreting
- it as a timestamp for the previous line
-
-doc/{bash.1,bashref.texi},lib/readline/doc/hsuser.texi
- - added detail to make it clear exactly how history timestamps are
- saved to and read from the history file
-
-subst.c
- - change quote_escapes to add CTLESC before spaces if IFS is null,
- just in case we have to split on literal spaces later on (e.g., in
- case of unquoted $@). Corresponding changes to dequote_escapes.
- Fixes a couple of problems reported by Brett Stahlman
- <brettstahlman@comcast.net>
-
- 1/14
- ----
-subst.c
- - make same change to read_comsub to add CTLESC before ' ' if $IFS is
- null, since we will split on literal spaces later
-
- 1/15
- ----
-array.c
- - new function, array_quote_escapes (ARRAY *a), calls quote_escapes
- on each element of the array in the same way array_quote calls
- quote_string
- - call array_quote_escapes if match is not quoted in array_patsub
- - array_slice is now used, so remove the #ifdef INCLUDE_UNUSED define
- - change structure of array_subrange to call array_slice to create a
- new array with the desired subset of elements, then call array_quote
- or array_quote_escapes as necessary, like array_patsub. Convert to
- a string by calling array_to_string on the sliced-out array
-
-array.h
- - new extern declaration for array_quote_escapes
-
-subst.c
- - since array_patsub now calls quote_escapes as necessary, callers
- don't need to call it after array_patsub returns. Fixes first bug
- reported by Brett Stahlman <brettstahlman@comcast.net>
- - since array_subrange now calls quote_escapes as necessary, callers
- don't need to call it after array_patsub returns. Same fix as
- for array_patsub
-
- 1/31
- ----
-configure.in
- - add -DSOLARIS to LOCAL_CFLAGS for solaris x
-
-config-bot.h
- - don't #undef HAVE_GETCWD if GETCWD_BROKEN and SOLARIS are both
- defined. Solaris's loopback mount implementation breaks some of the
- file system assumptions the replacement getcwd uses.
-
-builtins/common.c
- - if GETCWD_BROKEN is defined, call getcwd with PATH_MAX for the size
- argument, so it will allocate a buffer for the current working dir
- with that size, instead of one that's `big enough'
-
-config.h.in
- - add #undef PRI_MACROS_BROKEN for AIX 4.3.3
-
-pathexp.h
- - new flag value for quote_string_for_globbing: QGLOB_REGEXP (quoting
- an ERE for matching as a string)
-
-pathexp.c
- - change quote_string_for_globbing to understand QGLOB_REGEXP
-
-execute_cmd.c
- - change execute_cond_node to pass 2 (regexp match), 1 (shell pattern
- match), or 0 (no matching) to cond_expand_word
-
-subst.c
- - change cond_expand_word to translate SPECIAL==2 into passing
- QGLOB_REGEXP to quote_string_for_globbing
-
-locale.c
- - by default, if all else fails, set shell's idea of locale to ""
- instead of its idea of `default_locale' -- the library functions
- behave better with that value
-
- 2/2
- ---
-builtins/printf.def
- - if PRI_MACROS_BROKEN is defined, #undef PRIdMAX (AIX 4.3.3 broken)
-
- 2/3
- ---
-Makefile.in,{builtins,doc}/Makefile.in,lib/*/Makefile.in
- - add assignment for datarootdir as per GNU coding standards
-
-Makefile.in,builtins/Makefile.in,lib/intl/Makefile.in,po/Makefile.in.in
- - use @localedir@ instead of $(datadir)/locale in assignment
-
- 2/13
- ----
-jobs.c
- - fix compact_jobs_list to not return js.j_lastj, since that is in use
- and should not be overwritten. Fix from Len Lattanzi
- <llattanzi@apple.com>
-
- 2/16
- ----
-lib/readline/text.c
- - change rl_forward_char to allow moving to the end of the line when
- using the arrow keys in vi insertion mode, rather than having the
- behavior identical between vi command and insertion modes. Change
- suggested by Hugh Sasse <hgs@dmu.ac.uk>
-
- 2/19
- ----
-CWRU/audit-patch
- - patch from Steve Grubb of RedHat <sgrubb@redhat.com> to make bash
- audit root's behavior by logging commands using his audit
- framework. Enabled if the shell's name is `aubash'.
-
- 3/8
- ---
-jobs.c
- - use WSTATUS (p->status) instead of bare p->status. Fix from
- Jim Brown <jim.brown@rsmas.miami.edu>
-
- 3/9
- ---
-lib/readline/{complete,input,isearch,misc,readline,text,vi_mode}.c
- - make sure cases where rl_read_key returns -1 (usually due to EIO
- because the controlling tty has gone away) are handled correctly.
- Prompted by report from Thomas Loeber <ifp@loeber1.de>
-
- 3/10
- ----
-sig.c
- - new function, top_level_cleanup, callable from contexts where some
- cleanup needs to be performed before a non-fatal call to
- jump_to_top_level
-
-sig.h
- - new extern declaration for top_level_cleanup
-
-builtins/common.c
- - add calls to top_level_cleanup before calls to jump_to_top_level
- in a builtin command context (no_args(), get_numeric_arg()). Fixes
- bug reported by Ian Watson
-
-lib/readline/display.c
- - in _rl_move_cursor_relative, use `new' when comparing against
- the last invisible character in the prompt, since they both denote
- buffer indices when in a multibyte locale, whereas `dpos' is a
- display position
-
- 3/13
- ----
-lib/readline/complete.c
- - set rl_completion_append_character to the default (' ') in
- set_completion_defaults(). Fixes bug reported by David Emerson
- <demerson3x@angelbase.com>
-
- 3/23
- ----
-builtins/evalfile.c
- - make sure read() returns a value >= 0 before using it as an index
- into string[]
- - use a variable of type `ssize_t' for return value from read()
- - only try to read the entire contents of a regular file in one shot
- if the file size is less than SSIZE_MAX. These fix problems
- reported by hooanon05@yahoo.co.jp.
-
-include/typemax.h
- - define SSIZE_MAX as 32767 if it's not defined
-
-lib/readline/display.c
- - in rl_redisplay() and update_line(), if redrawing the prompt because
- it contains invisible characters, make sure we redraw the character
- indicating a modified history line and take it into account when
- computing _rl_last_c_pos
- - in update_line, if deleting characters and redrawing the new text,
- make sure we adjust _rl_last_c_pos by wrap_offset in a multibyte
- locale if the text we're drawing starts before or at the last
- invisible character in the prompt string. Fixes bug reported on
- bug-readline by J Pelkey <pelkeyj@gmail.com>
-
-parse.y
- - when adding at CTLESC character to the current token, do not
- escape it with CTLESC if pass_next_character indicates that the
- CTLESC was escaped by a backslash. Fixes bug reported by
- Paul Bagshaw <paul.bagshaw@orange-ftgroup.com>.
-
- 3/25
- ----
-lib/readline/text.c
- - in rl_forward_char, short-circuit the loop if in emacs mode and
- rl_point == rl_end. Fixes problem with multibyte locales
- reported by Len Lattanzi <llattanzi@apple.com>
-
- 3/29
- ----
-command.h
- - new flag for subshell_environment: SUBSHELL_PROCSUB, for process
- substitution
-
-subst.c
- - add SUBSHELL_PROCSUB to subshell_environment in process_substitute
-
- 3/30
- ----
-doc/Makefile.in
- - fix installation of bash.info to understand that it is in the build
- directory, not the source directory
-
-mailcheck.c
- - new function, init_mail_dates, calls remember_mail_dates only if
- there are no mailboxes in `mailfiles'
- - new function, init_mail_file, initializes a FILEINFO, using the
- last time mail was checked as the mtime and atime (or the time the
- shell was started if last_time_mail_checked is uninitialized)
- - call init_mail_file instead of update_mail_file in add_mail_file,
- called from remember_mail_dates (which is supposed to initialize
- the list of mail files)
- - new convenience functions, alloc_mail_file and dispose_mail_file to
- allocate and free FILEINFO structs
-
-mailcheck.h
- - extern declaration for init_mail_dates
-
-shell.c
- - call init_mail_dates instead of remember_mail_dates
-
- 4/4
- ---
-builtins/read.def
- - changes to print $PS2 when a line is continued with a backslash in
- an interactive shell. This is as POSIX requires
-
- 4/5
- ---
-subst.c
- - make sure quote_escapes is only ever called when the word to be
- escaped is not marked as double-quoted -- cleaner, and allows us
- to make certain assumptions
-
- 4/6
- ---
-subst.c
- - change all EX_* defines to begin with SX_
- - new flag, SX_NOCTLESC, obeyed by string_extract_verbatim, tells it
- to not obey CTLESC quoting
- - change quote_escapes to not quote CTLESC with CTLESC if one of the
- chars in $IFS is CTLESC, since the return value from quote_string
- will be passed to word splitting and filename generation
- - change read_comsub to do the same thing for unquoted command
- substitutions
- - change list_string to pass SX_NOCTLESC if CTLESC is one of the
- chars in $IFS, so it will split on CTLESC instead of using it as a
- quote character
-
- 4/7
- ---
-subst.c
- - slight change to string_extract_verbatim to allow CTLESC to quote
- CTLNUL even if SX_NOCTLESC is set in the flags passed, to protect
- the CTLNULs from future calls to remove_quoted_nulls. Only
- matters when $IFS contains CTLESC
- - changes to cope with $IFS containing CTLNUL in the same way as the
- CTLESC changes
-
-builtins/read.def
- - changes to cope with $IFS containing CTLNUL in the same way as the
- CTLESC changes
-
- 4/16
- ----
-lib/sh/strftime.c
- - a couple of fixes to the `%z' code
-
-eval.c
- - add an fflush after printing the auto-logout message
-
- 4/24
- ----
-subst.c
- - add call to top_level_cleanup in exp_jump_to_top_level to get things
- like unwind-protects and the loop levels cleaned up
-
-{arrayfunc,expr,variables}.c
- - add calls to top_level_cleanup before jump_to_top_level()
-
- 4/27
- ----
-builtins/complete.def
- - make sure the `command' argument to the -C option is printed with
- single quotes, since multi-word commands will require them. Bug
- reported by martin@snowplow.org
-
-execute_cmd.c
- - change execute_builtin_or_function and execute_subshell_builtin_or_function
- to call fflush(stdout) after the builtin or function returns, to
- make sure that all output is flushed before the call returns. It
- matters on cygwin. Fix suggested by Eric Blake <ebb9@byu.net>
-
-redir.c
- - in do_redirection_internal, if the file descriptor being acted upon
- is the same one used by the stdout stream, call fflush(stdout) to
- make sure all output is flushed before changing the underlying fd
- out from underneath stdio. Fix suggested by Eric Blake <ebb9@byu.net>
-
-
- 4/30
- ----
-
-builtins/common.c
- - new function, sh_chkwrite(int), fflushes stdout and checks for error;
- printing an error message and returning a new exit status if there's
- an error on stdout. Takes exit status as argument; returns new exit
- status (EXECUTION_FAILURE if write error)
-
-builtins/common.h
- - new extern declaration for sh_chkwrite
-
-builtins/{alias,cd,complete,echo,fc,history,pushd,shopt,times,trap,type,ulimit,umask}.def
- - change to use sh_chkwrite to report write errors
-
-builtins/fc.def
- - if an error occurs while writing commands from the history to a file
- to be executed, report a write error and return failure without
- attempting to execute any commands
-
- 5/1
- ---
-builtins/{bind,declare,set,setattr}.def
- - change to use sh_chkwrite to report write errors
-
- 5/2
- ---
-lib/readline/input.c
- - fix off-by-one errors in _rl_get_char (pop_index) and rl_stuff_char
- (push_index) that caused the 511th character in the buffer to be
- discarded. Fixes bug reported by Tom Bjorkholm <tom.bjorkholm@ericsson.com>
-
- 5/8
- ---
-subst.c
- - fix parameter_brace_remove_pattern to pass getpattern() newly-allocated
- memory. If word expansions (particularly brace expansions) are
- required, the expansion code will free the string passed to
- expand_word_internal, and we don't want to free unallocated memory
- (patstr++) or have duplicate frees (patstr). Fixes bug reported on
- Red Hat bugzilla
-
- 5/9
- ---
-lib/readline/signals.c
- - fix bug in rl_set_signals that caught SIGINT twice and didn't catch
- SIGTERM. Bug reported by Ed Kwan <ed.kwan@onstor.com>
-
- 5/18
- ----
-jobs.c
- - change compact_jobs_list to return 1 if js.j_lastj == 0 and there is
- a job in jobs[0]; compact_jobs_list should never return an index
- already occupied
- - change reset_job_indices to avoid infinite looping when js.j_firstj
- == 0 or js.j_firstj == js.j_jobslots upon function entry. Fixes
- bug reported by osicka@post.cz
-
- 5/20
- ----
-
-execute_cmd.c
- - new variable, executing_builtin, keeps track of number of "levels"
- of builtins being executed; incremented by execute_builtin; saved
- and restored by execute_simple_command
-
-subst.c
- - new variable, assigning_in_environment, set and unset around calls
- to assign_in_env by the expansion code
-
-variables.c
- - use executing_builtin and assigning_in_environment to decide whether
- or not to look into temporary_env when calling find_variable_internal.
- Fixes problem reported by Kevin Quinn <kevquinn@gentoo.org>
-
- 5/22
- ----
-redir.c
- - change add_undo_redirect to differentiate between file descriptors
- greater than SHELL_FD_BASE (currently 10) used internally to save
- others and then being the targets of user redirection and fds that
- are just the target of user redirections. The former need to have
- an `exec undo' redirect added to undo it in case exec throws away
- redirections; the latter does not. We use the close-on-exec flag
- for this: if it's set, we assume that the file descriptor is being
- used internally to save another. Fixes problem reported by Ian
- Jackson <ian@davenant.greenend.org.uk>
-
-shell.c
- - new function, init_interactive_script(), does interactive initialization
- for a script run with `bash -i script' -- does everything the same
- as init_interactive except set `interactive == 1', which causes the
- shell to read from the standard input, after calling
- init_noninteractive
- - call init_interactive_script if a script is run as `bash -i script'.
- Fixes problem reported by Joseph Michaud <jmichaud@sgi.com>
-
- 5/24
- ----
-builtins/printf.def
- - change vbadd to only call FASTCOPY if the passed buffer length is
- > 1
- - if the `-v' option is supplied and `vbuf' is already non-null from a
- previous `printf -v var' call, set vbuf[0]=0 explicitly instead of
- relying on vbadd to do it -- vbadd may not be called.
- - fix PRETURN macro to set vbuf[0] == 0 if vbuf is not freed. These
- should fix problem reported by Elmar Stellnberger <estellnb@yahoo.de>
-
-lib/readline/display.c
- - fix update_line to deal with the case where col_lendiff > 0 (meaning
- the new string takes up more screen real estate than the old) but
- lendiff < 0 (meaning that it takes fewer bytes to do so). This can
- happen when a multibyte prompt string is replaced with a longer one
- containing only single-byte characters (e.g., when doing a reverse
- i-search). Fixes gentoo bug reported by Peter Volkov
- <torre_cremata@mail.ru>
-
-builtins/read.def
- - make sure we only print $PS2 if the standard input is a terminal
- - new function, read_mbchar, to read a multibyte character so we
- can make sure we read entire multibyte chars when `read -n' is
- used, rather than bytes. Only called when -n is supplied.
- Fixes problem reported by Stanislav Brabec <sbrabec@suse.cz>
-
- 5/25
- ----
-externs.h
- - new #defines for third argument to named_function_string:
- FUNC_MULTILINE (don't suppress newlines) and FUNC_EXTERNAL (convert
- to external display form)
-
-subst.h
- - new extern declaration for remove_quoted_escapes
-
-subst.c
- - remove_quoted_escapes is now global
-
-print_cmd.c
- - in named_function_string, if FUNC_EXTERNAL is in the flags argument,
- call remove_quoted_escapes to convert from internal to external form.
- Fixes bug reported by Bo Andresen <bo.andresen@zlin.dk>
-
-variables.c,builtins/{declare,setattr,type}.def
- - use FUNC_MULTILINE in calls to named_function_string as appropriate
- - add FUNC_EXTERNAL to calls to named_function_string as appropriate
-
- 5/27
- ----
-{make_cmd,variables}.c
- - changes to enable the shell to compile when debugger support is
- configured out (function_def hash table and access functions). Fixes
- bug reported by Horst Wente <horst.wente@acm.org>
-
-builtins/help.def
- - fix bug in `help' two-column printing to avoid referencing
- shell_builtins[num_shell_builtins]
-
-error.c
- - in get_name_for_error, use dollar_vars[0] if the name returned from
- looking in $BASH_SOURCE[0] is the empty string as well as if it's
- null
-
- 5/31
- ----
-arrayfunc.c
- - change array_value_internal to set *RTYPE to 1 if the reference is
- array[*] and 2 if the reference is array[@]
-
-subst.c
- - in parameter_brace_expand_word, set the flags returned by the word
- desc to include W_HASQUOTEDNULL if array_value returns QUOTED_NULL
- for an array reference like x[*] and the word is quoted. Fixes bug
- reported by Christophe Martin <schplurtz@free.fr>
-
- 6/1
- ---
-jobs.c
- - several changes to preserve errno if tcgetpgrp/tcgetattr/tcsetattr
- fail, for subsequent error messages
- - change initialize_job_control to turn off job control if the terminal
- pgrp == -1 or is not equal to shell_pgrp (with an error message)
- - in initialize_job_control, if the shell has been forced interactive
- with -i, make sure stderr is hooked to a tty before using it as
- the controlling terminal. If it's not, try to open /dev/tty and
- assign it to shell_tty. Fixes problems reported by Derek Fawcus
- <dfawcus@cisco.com>
-
- 6/13
- ----
-support/shobj-conf
- - changes to support shared object and shared library creation on AIX
- 5.x and later versions. From Niklas Edmundsson <nikke@acc.umu.se>
-
- 6/17
- ----
-builtins/mkbuiltins.c
- - new array of builtins, posix_builtins, containing builtins listed
- as special to the command search order by POSIX
- - add POSIX_BUILTIN to the builtin flags if the builtin name is one
- that's special to the posix command search order
-
-builtins.h
- - new define, POSIX_BUILTIN, means that a builtin is special to the
- posix command search order
-
- 6/22
- ----
-lib/readline/display.c
- - new macro, WRAP_OFFSET, intended to replace W_OFFSET. Takes prompt
- strings longer than one physical line with invisible characters on
- the second line into account when calculating the number of
- invisible characters on the current screen line
- - use WRAP_OFFSET where appropriate (update_line, _rl_move_cursor_relative)
- - change update_line to deal with adjusting _rl_last_c_pos in a
- multibyte environment when the prompt has invisible chars on the
- second line and redisplay has output the invisible characters
- - change _rl_move_cursor_relative to adjust _rl_last_c_pos in a
- multibyte environment when the prompt has invisible chars on the
- second line and the redisplay draws the invisible character. Fixes
- redisplay bug reported by Andreas Schwab <schwab@suse.de>
-
-
- 7/11
- ----
-
-lib/readline/rltty.c
- - enable flush-output code for systems other than AIX 4.1. Problem
- reported by Jan Kratochvil <jan.kratochvil@redhat.com>
-
- 7/12
- ----
-lib/readline/display.c
- - set prompt_invis_chars_first_line from the portion of the prompt
- following the final newline, instead of from the prefix. Fixes
- bug reported on the Ubuntu bug list by dAniel hAhler
- <ubuntu@thequod.de>
-
- 7/13
- ----
-variables.c
- - use native __QNX__ and __QNXNTO__ cpp defines instead of qnx and
- qnx6, respectively. Patch from Sean Boudreau <seanb@qnx.com>
-
-lib/sh/getcwd.c
- - #undef HAVE_LSTAT on qnx, so it uses stat instead. Patch from
- Sean Boudreau <seanb@qnx.com>
-
- 7/21
- ----
-builtins/common.c
- - change sh_invalidnum to be a little smarter about octal and hex
- numbers and change the message appropriately. Bug originally
- reported on coreutils list by Jürgen Niinre <Jyrgen.Niinre@emt.ee>
-
- 7/26
- ----
-test.c
- - make sure the string passed to test_unop has only a single character
- following the `-'. Fixes bug reported by Michael A. Smith
- <michael@smith-li.com>
-
-parse.y
- - better input validation: make sure a word looks like a conditional
- unary operator (-X) before calling test_unop
-
- 7/28
- ----
-trap.c
- - in trap_handler, if it's called directly from the signal handler
- (e.g., SIGINT sighandler, set by set_sigint_handler), but the
- trap disposition has been reset to the default between the
- assignment and receipt of the signal, check that the signal is
- trapped and issue a warning if the shell was compiled with
- debugging enabled. Fixes bug reported by Fergus Henderson
- <fergus@google.com>
-
- 8/1
- ---
-lib/readline/{util,histexpand}.c
- - fixes for small memory leaks from Michael Snyder <msnyder@sonic.net>
-
- 8/18
- ----
-Makefile.in
- - add dependency on builtins/builtext.h to nojobs.o list. Fixes
- `make -j 5' issue reported by Chris MacGregor <chris@bouncingdog.com>
-
-examples/loadables/Makefile.in
- - add @LDFLAGS@ to SHOBJ_LDFLAGS assignment -- experimental. Suggested
- by Mike Frysinger <vapier@gentoo.org>
-
-examples/loadables/{basename,cut,dirname,finfo,head,ln,logname,mkdir,pathchk,print,printenv,push,realpath,rmdir,sleep,tee,truefalse,tty,uname,unlink,whoami}.c
- - fix up some includes. Fix from Mike Frysinger <vapier@gentoo.org>
-
- 8/21
- ----
-histexpand.c
- - fix another memory leak in history_find_word. Bug report originally
- from Michael Snyder <msnyder@sonic.net>; test case suggested by Jim
- Blandy <jimb@codesourcery.com>
-
- 8/26
- ----
-subst.c
- - change to do_assignment_internal to make an assignment to a variable
- with the `noassign' internal attribute not a variable assignment
- error.
- - fix do_assignment_internal so assignment to a `noassign' variable
- does not cause it to suddenly become visible if it's currently
- invisible
-
- 9/3
- ---
-stringlib.c
- - change strsub to check whether or not temp is non-null before
- trying to null-terminate it. Also make sure temp is allocated
- even if the pattern and replacement strings are empty, and set
- to a copy of string (like ${foo//})
- Bug report from Timo Lindfors <timo.lindfors@iki.fi>
-
- 9/10
- ----
-{config.h,Makefile,configure}.in,aclocal.m4
- - new tests for fpurge and __fpurge
-
-lib/sh/fpurge.c, externs.h
- - new file, fpurge(3) implementation with external decl in externs.h
-
-builtins/common.c
- - add call to fpurge(stdout) to sh_chkwrite
-
-{redir,execute_cmd}.c
- - add call to fpurge(stdout) after fflush(stdout) before changing
- stdout file descriptor and after a builtin or function executes
-
- 9/12
- ----
-expr.c
- - make sure noeval is set to 0 when a longjmp occurs, since it will
- not be reset otherwise, and it can be set to 1 while processing
- a {pre,post}-increment or {pre,post}-decrement token
- - set noeval to 0 at the beginning of evalexp, since it's never
- called recursively
-
- 9/14
- ----
-config-top.h
- - new builder-modifiable define: DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS
- Turning it on will cause errors from EPIPE to not be reported by
- the normal shell write error message mechanism
-
-builtins/common.c
- - if DONT_REPORT_BROKEN_PIPE_WRITE_ERRORS is defined, don't print an
- error message from sh_wrerror if errno == EPIPE. Suggestion from
- Petr Sumbera <petr.sumbera@sun.com>
-
- 9/19
- ----
-{jobs,nojobs}.c,jobs.h
- - add code to retry fork() after EAGAIN, with a progressively longer
- sleep between attempts, up to FORKSLEEP_MAX (16) seconds. Suggested
- by Martin Koeppe <mkoeppe@gmx.de>
-
- 9/21
- ----
-version.c
- - change copyright year to 2007
-
- 9/25
- ----
-pathexp.c
- - change quote_string_for_globbing to add a backslash in front of a
- backslash appearing in the pathname string, since the globbing
- code will interpret backslashes as quoting characters internally.
- Bug reported by <herbert@gondor.apana.org.au> on the debian list
- (443685)
-
- 10/8
- ----
-lib/readline/display.c
- - in update_line, make sure _rl_last_c_pos is > 0 before setting
- cpos_adjusted (or we actually moved the cursor to column 0 in
- _rl_move_cursor_relative). Fixes redisplay bug with prompt with
- only invisible characters reported by dAniel hAhler
- <ubuntu@thequod.de>
-
- 10/10
- -----
-lib/readline/display.c
- - in rl_redisplay, when calculating the new physical cursor position
- in a multibyte locale (`tx'), do not call rl_backspace if tx ends
- up < 0. Rest of fix for bug reported by dAniel hAhler
- <ubuntu@thequod.de>
-
- 10/12
- -----
-lib/sh/getcwd.c
- - fix memory overwrite problem that's possible if buf is NULL and
- passed size is greater than the pathname length. Reported by
- Ian Campbell <ian.campbell@xensource.com>
-
-builtins/ulimit.def
- - change the multiplier for the -c and -f options (`blocks') to 512,
- the traditional value (and the one POSIX specifies). Bug reported
- by Pete Graner <pgraner@redhat.com>
-
-braces.c
- - pass process substitution through unchanged the same as command
- substitution. Prompted by suggestion from Stephane Chazelas
- <stephane_chazelas@yahoo.fr>
-
-lib/readline/input.c
- - in rl_unget_char, fix off-by-one error when resetting pop_index if
- it's < 0. Bug reported by Uwe Doering <gemini@geminix.org>
-
-builtins/type.def
- - change exit status of `type' to not successful if any of the
- requested commands are not found. Reported by Stephane Chazleas
- <stephane_chazelas@yahoo.fr>
-
-pcomplete.c
- - change command_line_to_word_list to use rl_completer_word_break_characters
- instead of the shell metacharacters to split words, so programmable
- completion does the same thing readline does internally. Reported
- by Vasily Tarasov <vtaras@sw.ru>
-
- 10/16
- -----
-bashline.c
- - When completing a command name beginning with a tilde and containing
- escaped specical characters, dequote the filename before prefixing
- it to the matches, so the escapes are not quoted again. Reported
- by neil@s-z.org
-
- 10/17
- -----
-expr.c
- - in readtok(), don't reset lasttp if we've consumed the whitespace
- at the end of the expression string. Fixes error message problem
- reported by <anmaster@tele2.se>
-
- 11/1
- ----
-builtins/printf.def
- - change asciicode() to return intmax_t; add multibyte character
- support instead of assuming ASCII (depending on behavior of system
- multibyte support functions). Fixes bug reported by Rich
- Felker <dalias@aerifal.cx>
-
- 11/5
- ----
-execute_cmd.c
- - if redirections attached to a compound command fail, make sure to
- set last_command_exit_value when returning EXECUTION_FAILURE.
- Fixes bug reported separately by Andreas Schwab <schwab@suse.de>
- and Paul Eggert <eggert@cs.ucla.edu>
-
- 11/9
- ----
-builtins/read.def
- - make sure the return value from get_word_from_string is freed if
- non-null. Fixes memory leak bug reported by Lars Ellenberg
- <lars.ellenberg@linbit.com>
-
- 11/10
- -----
-variables.c
- - use getpid() as value of seeded_subshell to avoid problems with
- random number generator not getting re-seeded correctly when
- subshells are created. Fix from Tomas Janousek <tjanouse@redhat.com>
-
-lib/readline/display.c
- - in update_line(), when outputting characters at the end of the line,
- e.g., when displaying the prompt string, adjust _rl_last_c_pos by
- wrap_offset if the text we're drawing begins before the last
- invisible character in the line. Similar to fix from 5/24. Fixes
- bug reported by Miroslav Lichvar <mlichvar@redhat.com>
-
- 11/14
- -----
-subst.c
- - fix $[ expansion case to deal with extract_arithmetic_subst
- returning NULL (if the `]' is missing) and return the construct
- unchanged in that case. Fixes tab completion bug reported by
- Heikki Hokkanen <hoxu@users.sf.net> (debian bug 451263)
-
-lib/readline/mbutil.c
- - fix _rl_find_next_mbchar_internal to deal with invalid multibyte
- character sequences when finding non-zero-length chars. Fixes
- bug reported by Morita Sho <morita-pub-en-debian@inz.sakura.ne.jp>
-
- 11/15
- -----
-variables.c
- - add new function `seedrand' to seed the bash random number
- generator from more random data. Suggestion from Steve Grubb
- <sgrubb@redhat.com>
- - replace the rng in brand() with a slightly better one from FreeBSD
- (filtered through Mac OS X 10.5). Replacement suggested by
- Steve Grubb <sgrubb@redhat.com>
-
- 11/21
- -----
-configure.in
- - darwin 9 also requires linking against libreadline.a and
- libhistory.a because of Apple's questionable decision to ship a
- libreadline "replacement" that doesn't provide all functions
-
-doc/{bash.1,bashref.texi}
- - slight change to the text describing the effect of set -e when
- in a || or && list
-
- 12/5
- ----
-jobs.c
- - fix raw_job_exit_status to correct mixing of int/WAIT values (need
- to return a WAIT)
- - arrange so that children run as part of command substitutions also
- set the SIGINT handler to wait_sigint_handler, since they effectively
- don't do job control
- - in wait_for, if a child run as part of a command substitution exits
- due to SIGINT, resend the SIGINT to the waiting shell with kill(2).
- This makes sure the exit status propagates
-
-doc/{bash.1,bashref.texi}
- - tighten up the language describing when bash tries to see if its
- stdin is a socket, so it can run the startup files. Suggested by
- Vincent Lefevre <vincent@vinc17.org>
-
-eval.c
- - in the DISCARD case of a longjmp to top_level, make sure
- last_command_exit_value is set to EXECUTION_FAILURE if it's 0,
- but leave existing non-zero values alone
-
-subst.c
- - in command_substitute, don't reset pipeline_pgrp in the child
- process -- this means that second and subsequent children spawned by
- this comsub shell get put into the wrong process group, not the
- shell's. Fix for bug reported by Ingo Molnar <mingo@elte.hu>
-
- 12/6
- ----
-support/shobj-conf
- - make sure the cases for darwin8.x (Mac OS X 10.4.x) are extended to
- darwin9.x (Mac OS X 10.5.x). Fixes problem originally reported
- against readline-5.2 by schneecrash@gmail.com
-
- 12/8
- ----
-subst.c
- - make sure to add the results of (successful) tilde expansion as a
- quoted string, to inhibit pathname expansion and word splitting.
- From recent Austin Group interpretation.
-
-include/shtty.h, lib/sh/shtty.c
- - add ttfd_onechar, ttfd_noecho, ttfd_eightbit, ttfd_nocanon, and
- ttfd_cbreak to set tty attributes associated with a particular
- file descriptor (which is presumed to point to a terminal). Support
- for fix for bug reported by b_bashbug@thebellsplace.com
-
-lib/readline/display.c
- - make sure we only use rl_invis_chars_first_line when the number of
- physical characters exceeds the screen width, since that's the
- only time expand_prompt sets it to a valid value
-
- 12/12
- -----
-builtins/set.def
- - change set_minus_o_option to return EX_USAGE if an invalid option
- name is supplied. All callers can handle it.
- - change set_builtin to return what set_minus_o_option returns if it's
- not EXECUTION_SUCCESS. This allows EX_USAGE errors to abort a
- shell running in posix mode
-
- 12/14
- -----
-builtins/read.def
- - generalize the calls to the tty attribute functions to maintain a
- local copy of the terminal attributes and use the fd supplied as
- the argument to the -u option (default 0). Fix for bug reported
- by b_bashbug@thebellsplace.com
-
-doc/bashref.texi, lib/readline/doc/{history,rlman,rluser,rluserman}.texi
- - Slight changes to conform to the latest FSF documentation standards.
- Patch from Karl Berry <karl@freefriends.org>
-
- 12/20
- -----
-execute_cmd.c
- - after calling clear_unwind_protect_list, make sure we reset
- parse_and_execute_level to 0, since there's nothing left to
- restore it if top_level_cleanup tests it. Fixes bug reported
- by Len Lattanzi <llattanzi@apple.com>
-
- 12/31
- -----
-lib/sh/getcwd.c
- - new function, _path_checkino, checks whether the inode corresponding
- to the path constructed from the first two arguments is the same as
- the inode number passed as the third argument
- - if BROKEN_DIRENT_D_INO is defined, meaning the d_ino/d_fileno
- member of struct dirent doesn't contain valid values, use
- _path_checkino instead of directly comparing against d_fileno.
- Fixes Interix problem reported by Michael Haubenwallner
- <haubi@gentoo.org>
-
- 1/7/2008
- --------
-array.c
- - fix array_subrange to separate elements in returned string with
- first char of $IFS if QUOTED is non-zero, since this indicates
- the caller used ${array[@]:foo}. Fixes bug reported by Lea
- Wiemann <lewiemann@gmail.com>
-
- 1/8
- ---
-subst.c
- - new function returning a string containing the first character of
- $IFS: char *ifs_firstchar(int *)
-
-subst.h
- - extern declaration for ifs_firstchar()
-
-array.c
- - call ifs_firstchar() to get first character of $IFS when needed
- (array_subrange() and array_patsub())
-
- 1/11
- ----
-lib/readline/display.c
- - use sentinel variable set at end of init_line_structures to decide
- whether to call it from rl_redisplay, since early SIGWINCH on
- Mac OS X that hits during this function can cause _rl_wrapped_line
- to be referenced before initialization. Fix for bug reported by
- Len Lattanzi <llattanzi@apple.com>
-
-subst.[ch]
- - skip_to_delim is now compiled into the shell all the time, not just
- when readline is linked in
-
-subst.c
- - use skip_to_delim to find the `/' denoting the end of a pattern
- in pattern substitution, since it knows more shell syntax than
- quoted_strchr and understands multibyte characters. Fixes bug
- reported by Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com>
-
- 1/15
- ----
-subst.c
- - add `flags' argument to skip_to_delim telling it whether or not to
- set no_longjmp_on_fatal_error; set this flag when calling from the
- readline completion code
-
-subst.h
- - update extern declaration for skip_to_delim
-
- 1/17
- ----
-subst.c
- - expand_prompt_string takes a third argument: the initial flags for
- the WORD
-
-subst.h
- - change extern declaration for expand_prompt_string to add third arg
-
-bashline.c
- - pass W_NOCOMSUB as third argment to expand_prompt_string when
- calling from bash_directory_completion_hook, since we don't want
- to do command substitution from the completion code
-
-parse.y
- - change call to expand_prompt_string
-
- 1/18
- ----
-doc/Makefile.in
- - added an `install_builtins' rule to install the builtins.1 man page,
- preprocessing it with sed to force `.so man1/bash.1', which some
- versions of man require. Suggestion from Peter Breitenlohner
- <peb@mppmu.mpg.de>
- - new target `install_everything' that will install normal documentation
- and builtins man page
- - changed uninstall target to remove bash_builtins page from man
- directory
-
-lib/readline/vi_mode.c
- - new function, rl_vi_insert_mode, which calls rl_vi_start_inserting
- to make sure the value of `last command to repeat' is set correctly.
- Fix from Thomas Janousek <tjanouse@redhat.com>
- - add support for redoing inserts made with the `I' command. Fix
- from Thomas Janousek <tjanouse@redhat.com>
- - add support for redoing inserts made with the `A' command
-
-lib/readline/readline.h
- - new extern declaration for rl_vi_insert_mode
-
-lib/readline/{misc,readline,vi_mode,vi_keymap}.c
- - change calls to rl_vi_insertion_mode to rl_vi_insert_mode
-
- 1/19
- ----
-builtins/read.def
- - change timeout behavior when not reading from a tty device to save
- any partial input in the variable list, but still return failure.
- This also causes variables specified as arguments to read to be
- set to null when there is no input available. Fix inspired by
- Brian Craft <bcboy@thecraftstudio.com>
-
- 1/21
- ----
-builtins/fc.def
- - change computation of last_hist to use remember_on_history instead
- of a hard-coded `1'. This keeps fc -l -1 in PROMPT_COMMAND from
- looking too far back
-
- 1/25
- ----
-lib/readline/complete.c
- - fix fnwidth to use string[pos] instead of *string when testing the
- current character for a control character or rubout
-
- 2/2
- ---
-general.c
- - change posix_initialize to turn off source/. searching $PWD when
- the file sourced is not found in $PATH. Fixes bug reported by
- Paolo Bonzini <bonzini@gnu.org> and Eric Blake <ebb9@byu.net>
-
- 2/9
- ---
-builtins/*.def
- - changes to text and formatting suggested by Jan Schampera
- <jan.schampera@web.de>
-
- 2/16
- ----
-bashline.c
- - change command_word_completion_function to use the word completion
- found by readline, which matters only when ignoring case is on
- and the completion found in the file system differs in case from
- the text the user typed (this is what readline does for normal
- filename completion). Fixes issue reported by Jian Wang
- <jwang@a10networks.com.cn>.
-
- 2/18
- ----
-builtins/source.def
- - if the filename passed as an argument contains a `/', don't search
- $PATH. Not sure why it wasn't like this before
-
- 2/21
- ----
-lib/readline/terminal.c
- - change rl_crlf so that the MINT system on ATARI systems adds a
- carriage return before the \n
-
- 2/22
- ----
-doc/{bash.1,bashref.texi}
- - added text to the EXIT STATUS section noting that exit statuses
- fall between 0 and 255, inclusive
-
-support/mkversion.sh
- - output a #define for DEFAULT_COMPAT_LEVEL (${major}${minor}; e.g. 32)
- to version.h
-
-version.c
- - int variable, shell_compatibility_level, set to DEFAULT_COMPAT_LEVEL
- by default
-
-builtins/shopt.def
- - new shopt variable, compat31, sets shell_compatibility_level to 31
- (or back to default if unset)
-
-execute_cmd.c
- - in execute_cond_node, restore bash-3.1 behavior of quoted rhs of
- regexp matches if shell_compatibility_level == 31
-
- 2/28
- ----
-lib/readline/rltty.c
- - set readline_echoing_p = 1 if tcgetattr fails and sets errno to
- EINVAL, as Linux does when the fd is a pipe. Reported by Mike
- Frysinger <vapier@gentoo.org>
-
- 3/6
- ---
-{MANIFEST,Makefile.in},lib/sh/{casemod,uconvert,ufuncs}.c
- - new library sources from bash-4.0-devel tree
-
-lib/sh/spell.c
- - moved cdspell() here from builtins/cd.def, renamed dirspell()
-
-externs.h
- - new declarations for extern functions from new library files
- - new extern declaration for lib/sh/spell.c:dirspell()
-
-builtins/cd.def
- - call extern library function dirspell(); remove static cdspell()
-
-builtins/read.def
- - when read times out, make sure input_string is null-terminated before
- assigning any partial input read to the named variables
-
- 3/10
- ----
-lib/glob/xmbsrtowcs.c
- - cut the number of memory allocations in xdupmbstowcs by not keeping
- track of the indices if the caller hasn't asked for it
-
- 3/17
- ----
-builtins/fc.def
- - make sure the adjustment to i in fc_gethnum uses the same formula
- fc_builtin uses to calculate last_hist
- - make sure that every time fc_gethnum is called, the fc command last
- in the history list has not yet been deleted, since fc_gethnum
- assumes that it has not. Fix from John Haxby <john.haxby@oracle.com>
-
-lib/readline/complete.c
- - new private library function, _rl_reset_completion_state(), used to
- reset any completion state internal to the library when a signal
- is received
- - call _rl_reset_completion_state() before returning from
- rl_complete_internal
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_reset_completion_state
-
-lib/readline/signals.c
- - call _rl_reset_completion_state from rl_signal_handler on SIGINT.
- This fixes one of the problems identified by Mika Fischer
- <mf+ubuntu@zoopnet.de>
-
-pcomplete.c
- - programmable_completions now saves pointer to the compspec it's
- working with in new global variable CURCS
- - new function, pcomp_set_readline_variables, that sets or unsets
- readline variables based on a passed flags value (COPT_FILENAMES,
- etc.)
- - new function, pcomp_set_compspec_options, to set or unset bits in
- the options word of a passed compspec (default CURCS)
- - only call bash_dequote_filename (via rl_filename_dequoting_function)
- from pcomp_filename_completion_function if the readline state
- word indicates word completion is in progress
-
-pcomplete.h
- - new extern declaration for curcs
- - new extern declaration for pcomp_set_readline_variables
- - new extern declaration for pcomp_set_compspec_options
-
-bashline.c
- - fix bash_dequote_filename to implement shell quoting conventions:
- 1. Inhibit backslash stripping within single quotes
- 2. Inhibit backslash stripping within double quotes only if
- the following character is one of the special ones
- - call pcomp_set_readline_variables from attempt_shell_completion
- instead of doing the equivalent inline
-
- 3/18
- ----
-bracecomp.c
- - make sure we sort array of matches in byte order (using strcmp). so
- the brace calculations work correctly even when the locale orders
- characters like aAbBcC...zZ. Fixes bug reported by Torsten Nahm
- <torstennahm@torstennahm.de>
-
- 3/20
- ----
-lib/readline/{rltty,signals}.c
- - move block_sigint and release_sigint from rltty.c to signals.c; add
- _rl_ prefix to make them public to the library; change callers.
- From Jan Kratochvil <jan.kratochvil@redhat.com>
-
-lib/readline/rlprivate.h
- - new extern declarations for _rl_block_sigint and _rl_release_sigint
-
-lib/readline/display.c
- - add calls to _rl_block_sigint and _rl_release_sigint to rl_redisplay,
- since it maniupluates global data structures. Fix from Jan
- Kratochvil <jan.kratochvil@redhat.com>
-
-builtins/printf.def
- - change calls to asprintf and manually adding to vbuf to use calls
- to vsnprintf against vbuf directly -- if the number of characters
- to be written overflows the buffer, realloc the buffer and use
- vsnprintf again. This should reduce the memory used by printf.
- Idea from Yuya Katayama <yuya999@gmail.com>
-
-lib/readline/doc/rltech.texi
- - documented rest of readline's state flags, including RL_STATE_CALLBACK
- - documented rl_save_state and rl_restore_state
-
- 3/27
- ----
-lib/readline/{rlprivate.h,{display,readline,rltty,terminal,text}.c}
- - rename readline_echoing_p to _rl_echoing_p for namespace consistency
-
-lib/readline/{rlprivate.h,{callback,readline,util}.c}
- - rename readline_top_level to _rl_top_level for namespace consistency
-
-builtins/ulimit.def
- - new -b (socket buffer size) and -T (number of threads) options
-
-array.c
- - fix bug in calculation of the array element assignment string length:
- use length of `is' instead of `indstr'. Reported as ubuntu bug
- #202885 by John McCabe-Dansted
-
-builtins/setattr.def
- - new function, show_all_var_attributes, displays attributes and
- values for all shell variables (or shell functions) in a reusable
- format
-
-builtins/common.h
- - new extern declaration for show_all_var_attributes
-
-builtins/declare.def
- - change `declare -p' to print out all variable attributes and values,
- and `declare -fp' to print out all function attributes and
- definitions. Inspired by request from John Love-Jensen
- <eljay@adobe.com>
-
-doc/{bash.1,bashref.texi}
- - document new -b and -T options to ulimit
- - tighten up language describing AND and OR lists
- - add description of new behavior of `declare -p'
-
- 3/28
- ----
-pcomplete.c
- - rename curcs -> pcomp_curcs
- - new global completion variable, pcomp_curcmd, the current command
- name being completed
-
-builtins/complete.def
- - new builtin, compopt, allows completion options for command names
- supplied as arguments or the current completion being executed to
- be modified. Suggested by Mika Fischer <mf+ubuntu@zoopnet.de>
-
- 3/30
- ----
-doc/{bash.1,bashref.texi},lib/readline/doc/rluser.texi
- - document new compopt builtin
-
- 4/5
- ---
-support/shobj-conf
- - change solaris10 stanza to use -fPIC to fix 64-bit sparc_v9/solaris10
- compilations. Fix from Fabian Groffen <grobian@gentoo.org>
-
-builtins/read.def
- - added `-i text' option, inserts `text' into line if using readline.
- Suggested by many, used some ideas from Kevin Pulo <kevin@pulo.com.au>
-
-doc/{bash.1,bashref.texi}
- - document new `-i text' option to read builtin
-
- 4/7
- ---
-lib/readline/bind.c
- - new settable variable, `history-size', sets the max number of
- entries in the history list
-
-doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
- - document new `history-size' settable readline variable
-
- 4/8
- ---
-builtins/complete.def
- - change build_actions calling sequence to take a struct with `other'
- (non-action) flag arguments (-p, -r)
- - add support for `-E' option to build_actions and complete builtin --
- modifies or displays (internal) `_EmptycmD_' completion spec
-
-bashline.c
- - change attempt_shell_completion to try programmable completion on an
- `empty' command line and return the results
-
-doc/bash.1,lib/readline/doc/rluser.texi
- - documented new `-E' option to `complete'
-
- 4/9
- ---
-bashhist.c
- - new variable, `enable_history_list', used to reflect setting of
- `-o history' option
- - change bash_history_{enable,disable,reinit} to set enable_history_list
- as well as remember_on_history
-
-builtins/set.def
- - use `enable_history_list' instead of `remember_on_history' to keep
- value of `-o history' option
-
-builtins/evalstring.c
- - instead of unwind-protecting remember_on_history, use a function to
- restore it to the value of `enable_history_list' after
- parse_and_execute runs the commands in the string. This allows
- history to be turned off in a startup file, for instance. Problem
- reported by Dan Jacobson <jidanni@jidanni.org>
-
- 4/11
- ----
-bashline.c
- - limited support for completing command words with globbing characters
- (only a single match completed on TAB, absolute or relative
- pathnames supported, no $PATH searching, some support for displaying
- possible matches, can be used with menu completion).
- Suggested by Harald Koenig <h.koenig@science-computing.de>
-
-print_cmd.c
- - change redirection printing to output r_err_and_out as `&>file',
- since the man page says that's the preferred form
-
- 4/12
- ----
-builtins/*.def
- - change long doc so the first line is a short description
- - add `Exit Status:' section to each longdoc describing exit values
-
-builtins/help.def
- - new `-d' option to print short description of each utility
- - new `-m' option to print description of each builtin in a
- pseudo-manpage format (inspired by ksh93)
-
-doc/{bash.1,bashref.texi}
- - document new `-d' and `-m' options to `help'
-
-builtins/mapfile.def
- - new builtin, `mapfile', imported from bash-4.0-devel branch
-
-tests/{mapfile.{data,right,tests},run-mapfile}
- - tests for `mapfile' builtin
-
-doc/{bash.1,bashref.texi}
- - added description of `mapfile' builtin
-
-MANIFEST,Makefile.in,builtins/Makefile.in
- - added entries for mapfile source files
-
-arrayfunc.[ch]
- - new function, bind_array_element, to support mapfile builtin
-
- 4/20
- ----
-expr.c
- - fix operator precendence in expcond(): term after the `:' is
- a conditional-expression, not a logical-OR-expression (using C
- terminology). Bug reported by <archimerged@gmail.com>
-
- 4/22
- ----
-bashintl.h
- - new P_ define for using ngettext to decide on plural forms
- (currently unused)
-
- 4/25
- ----
-execute_cmd.c
- - in execute_disk_command, if the command is not found, search for
- a shell function named `command_not_found_handle' and call it
- with the words in the command as arguments. Inspired by Debian
- feature.
-
-doc/{bash.1,bashref.texi}
- - document new command_not_found_handle behavior in COMMAND EXECUTION
- section
-
-configure.in
- - change default version to bash-4.0-devel
-
- 4/28
- ----
-variables.c
- - change push_func_var and push_exported_var to call
- stupidly_hack_special_variables if the temporary variable is going
- to be disposed. This undoes any internal changes caused by a local
- variable assignment in the environment or in a shell function. Bug
- reported by Morita Sho <morita-pub-en-debian@inz.sakura.ne.jp> in
- http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=478096
-
- 5/3
- ---
-builtins/fc.def
- - fixed a problem caused by change of 1/21 to use remember_on_history,
- since it's turned off by parse_and_execute(), but can cause the
- last command in history to be deleted and leave last_hist pointing
- beyond the end of the history list. edit_and_execute_command can
- do this.
-
-bashline.c
- - new define, RL_BOOLEAN_VAR_VALUE, to take a readline boolean variable
- and get its value as 0 or 1 (consider making readline global)
- - put tty back into canonical mode before calling parse_and_execute in
- edit_and_execute_command and then back into raw mode after it
- returns. Fixes problem identified by <koersen@gmail.com>.
-
- 5/4
- ---
-lib/glob/glob.c
- - code to support `globstar' option: GX_GLOBSTAR and two internal
- flags. Changes to skipname, glob_vector, mbskipname, glob_filename.
- New function finddirs().
-
-lib/glob/glob.h
- - new defines to support globstar code
-
-builtins/shopt.def
- - new shell option, `globstar', enables special handling of `**' in
- glob patterns -- matches all directories recursively
-
-pathexp.h
- - extern declaration for glob_star
-
-pathexp.c
- - break inline code out of quote_globbing_chars into a separate
- function to decide whether a character is a globbing char:
- glob_char_p
- - change shell_glob_filename to call glob_filename with the
- GX_GLOBSTAR flag if glob_star is set
-
-doc/{bash.1,bashref.texi}
- - document new `globstar' shell option
-
-arrayfunc.c
- - new function, broken out of quote_array_assignment_chars:
- quote_assign; extended from old code to make sure that globbing
- chars and chars in $IFS are quoted when displaying assignment
- statements, especially in compound array assignments
-
- 5/5
- ---
-bashline.c
- - new variable, dircomplete_spelling, controls spelling correction
- of directory names when doing filename completion
- - change bash_directory_completion_hook to incorporate spelling
- correction if initial canonicalization of directory name fails
-
-builtins/shopt.def
- - new shell option, `dirspell', enables and disables spelling
- correction of directory names during word completion
-
-builtins/read.def
- - support for fractional timeout values (ival.uval); uses uconvert
- and falarm/setitimer
-
-config.h.in
- - new `HAVE_SETITIMER' define
-
-configure.in
- - look for setitimer(2), define HAVE_SETITIMER if found
-
-doc/{bash.1,bashref.texi}
- - document new `dirspell' shopt option
- - document new fractional values to `read -t timeout'
-
- 5/6
- ---
-assoc.[ch]
- - new files, basic support for associative array implementation
-
-general.h
- - new extern declarations for sh_openpipe, sh_closepipe, trim_pathname
-
-general.c
- - new functions: sh_openpipe to create a pipe and move the file
- descriptors to a high range; sh_closepipe, to close pipe fds and
- clean up, and trim_pathname, to replace portions of a pathname
- with `...' (for prompting)
-
-jobs.c
- - don't set last_asynchronous_pid in child shell (messes up $!, among
- other things)
-
-parse.y,parser.h
- - moved definitions of parser flags to parser.h
-
-array.c
- - imported array_modcase (case-changing operations on arrays) from
- 4.0-devel branch
-
-array.h
- - new extern declaration for array_modcase
-
-lib/readline/complete.c
- - new variable, rl_menu_completion_entry_function, generator for
- rl_menu_complete
- - new menu completion `browsing' implementation, with several
- improvements over the old code. Inspired by Sami Pietila
- <sami.pietila@gmail.com>
-
-lib/readline/readline.h
- - extern declaration for rl_menu_completion_entry_function
-
- 5/8
- ---
-lib/readline/complete.c
- - add support for a third argument to fnprint and print_filename,
- which supports replacing a specified portion of the pathnames
- printed when displaying possible completions with a `...' (or
- `___', if the prefix would be confused with a portion of the
- filename)
- - new variable, _rl_completion_prefix_display_length, sets the
- number of characters in a common prefix to be replaced with an
- ellipsis when displaying possible completions
- - add support to _rl_display_match_list to find the length of the
- common prefix of all items being displayed, and passing that
- value to print_filename for possible replacement with an ellipsis
- if that length is longer than _rl_completion_prefix_display_length
-
-lib/readline/bind.c
- - add support for retrieving value of history-size variable to
- _rl_get_string_variable_value
- - new bindable variable, completion-prefix-display-length. When
- displaying possible completions, matches with a common prefix
- longer than this value have the common prefix replaced with an
- ellipsis
- - support for retrieving value of completion-prefix-display-length
- variable to _rl_get_string_variable_value
- - new bindable variable, revert-all-at-newline: if enabled, causes
- all changes in history lines to be undone before readline returns
- after processing a newline
-
-doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
- - document new `completion-prefix-display-length' variable
- - document new `revert-all-at-newline' variable
-
-execute_cmd.c
- - change execute_builtin to not inherit the `-e' flag into commands
- executed by the `command' or `source/.' builtins if we are supposed
- to be ignoring the return value. This is like `eval'. Fixes bug
- reported by Hiroshi Fujishima <hirobo@tonteki.org>
-
- 5/10
- ----
-variables.c
- - when reading the initial environment, don't create variables with
- names that are not valid shell identifiers. Fixes bug reported by
- Stephane Chazleas <stephane_chazelas@yahoo.fr>
-
- 5/13
- ----
-subst.c
- - fix string_quote_removal to gracefully handle the case where a
- backslash is the final character in the string (leaves the backslash
- in place). Fixes bug reported by Ian Robertson
- <iroberts@u.washington.edu>
-
- 5/16
- ----
-support/checkbashisms
- - Perl script that purports to check for bash-specific features in a
- shell script. Lifted from Debian via ubuntu
-
- 5/20
- ----
-lib/readline/display.c
- - in update_line, when deciding whether or not to adjust _rl_last_c_pos
- in a multibyte environment after printing the last line of a multiline
- prompt with invisible characters on the first and last lines, use
- the number of inivisible chars on the first line in the calculation
- deciding whether or not we're past the last invisible character and
- need to adjust the cursor position. Old code used the number of
- invisible chars on the last prompt line. Fixes bug reported by
- stuff@slinkp.com.
- - in update_line, when fixing _rl_last_c_pos after drawing the first
- line of the prompt, use the number of invisible chars on the first
- line as the offset, instead of the total number of invisible chars
- - use prompt_multibyte_characters, the number of multibyte chars in
- the prompt string, to short-circuit some relatively expensive
- multibyte text processing in rl_redisplay
-
- 5/21
- ----
-variables.c
- - new function, reinit_special_variables(), a hook for special
- vars that need their hook functions called when they're unset as
- a result of the shell reinitializing itself to run a script
-
-shell.c
- - shell_reinitialize now calls reinit_special_variables
- - shell_reinitialize now calls bashline_reset
-
-variables.h
- - new extern declaration for reinit_special_variables
-
-bashline.c
- - new function, bashline_reset(), called when the shell reinitializes
- in shell_reinitialize. Right now, just resets
- bash_readline_initialized to 0.
-
-bashline.h
- - new extern declaration for bashline_reset()
-
- 5/23
- ----
-bashhist.c
- - new function, bash_clear_history, clears the history and resets any
- associated internal bash state
-
-bashhist.h
- - extern declaration for bash_clear_history
-
-builtins/history.def
- - call bash_clear_history instead of clear_history for `history -c'.
- Fixes part of problem reported by Scott McDermott
- <scott.m.mcdermott@gmail.com>
- - decrement history_lines_this_session in delete_histent, called for
- `history -d'
-
-builtins/history.def,bashhist.[ch]
- - move delete_histent() to bashhist.c; rename to bash_delete_histent
- - move delete_last_history() to bashhist.c; rename to
- bash_delete_last_history()
-
- 5/25
- ----
-braces.c
- - add another parameter to mkseq(), the number of digits to put into
- each member of a numeric sequence (width), changes to determine
- any zero-padding go into expand_seqterm
- - changes to expand_seqterm to allow user-specified increments
-
-bashline.[ch],shell.c,sig.c
- - switched names of bashline_reinitialize and bashline_reset to better
- reflect their functions
- - when searching $PATH for directories to use for command completion,
- make sure to free `current_path' before going out of scope
- - new bindable function `dabbrev-expand', which is more or less
- menu completion using dynamic history completion as the generator
- - changes to bash_execute_unix_command to set variables for the
- executed command like programmable completion: READLINE_LINE
- (rl_line_buffer) and READLINE_POINT (rl_point)
- - change to bash_execute_unix_command to allow the executed command
- to change the readline line buffer by modifying the value of
- READLINE_LINE and to change rl_point by modifying the value of
- READLINE_POINT
-
-common.h
- - new SEVAL_ defines for later parse_string changes from 4.0-devel
- branch
-
-command.h
- - new defines for new &>> r_append_err_and_out redirection
-
-builtins/evalstring.c
- - new function, parse_string, parses a command from a passed string
- and returns the number of characters consumed. For satisfying
- Posix rules when parsing command substitutions, from bash-4.0-devel
- branch
- - split out common prolog code from parse_string and
- parse_and_execute into a separate function called from both
-
-parse.y
- - small changes to add symbols needed for parse_string
- - parser change to add `|&' as synonym for `2>&1 |'; translation is
- performed at parse time so |& never shows up in output of
- print_command, for instance. Picked up from zsh, merged in from
- bash-4.0-devel branch
-
-parse.y,{redir,copy_cmd,dispose_cmd,make_cmd,print_cmd}.c
- - implement new &>> r_append_err_and_out (like >>foo 2>&1); merged
- in from bash-4.0-devel branch
-
-doc/{bash.1,bashref.texi},lib/readline/doc/rluser.texi
- - document new optional increment in brace expansion
- - document new zero-padded fixed-width integer brace expansion
- - document new `dabbrev-expand' bindable readline command
- - document new effects of `bind -x' setting and reading the values of
- READLINE_LINE and READLINE_POINT
- - document new |& synonym for `2>&1 |' pipeline operator
-
- 5/26
- ----
-parse.y - recognize new ;& and ;;& case action list terminator tokens and
- implement them in the grammar, setting CASEPAT_FALLTHROUGH and
- CASEPAT_TESTNEXT flags as appropriate
-
-print_cmd.c
- - print new ;& and ;;& case clause action list terminators as
- appropriate
-
-execute_cmd.c
- - implement new case clause action list terminators:
- ;& - fall through to actions associated with next pattern list
- ;;& - fall through to tests in next pattern list
-
-doc/{bash.1,bashref.texi}
- - document new ;& and ;;& case clause action list terminators
-
- 5/28
- ----
-jobs.c
- - change waitchld so it treats SIGCHLD like SIGINT if `wait' is being
- executed, and allows wait to jump out before running any trap set
- on SIGCHLD. Fixes debian bug #483016 reported by Miroslav Rudisin
- <miero@atrey.karlin.mff.cuni.cz>
- - run_sigchld_trap is no longer static, so the trap code in trap.c
- can call it
- - change run_sigchld_trap to call set_impossible_sigchld_trap instead
- of just using a call to restore_default_signal
-
-jobs.h
- - new extern declaration for run_sigchld_trap
-
-trap.c
- - fix run_pending_traps to run a SIGCHLD trap if the trap handler isn't
- set to IMPOSSIBLE_TRAP_HANDLER
- - in trap_handler, don't reset the SIGCHLD trap handler to trap_handler
- if MUST_REINSTALL_SIGHANDLERS is defined
- - new function, set_impossible_sigchld_handler, sets the trap string
- associated with SIGCHLD to IMPOSSIBLE_TRAP_HANDLER; used as a sentinel
- by run_sigchld_trap and maybe_set_sigchld_handler
- - change maybe_set_sigchld_handler to set the SIGCHLD trap string only
- if the current value is IMPOSSIBLE_TRAP_HANDLER. This ensures that
- any traps on SIGCHLD set in a SIGCHLD handler will persist. Fixes
- debian bug #483016 reported by Miroslav Rudisin
- <miero@atrey.karlin.mff.cuni.cz>
-
-trap.h
- - new extern declaration for set_impossible_sigchld_trap
-
- 5/31
- ----
-parse.y
- - new function: parse_comsub(), parses $(...) by parsing command
- between parens and making sure the next token is `)'. From
- the bash-4.0-devel branch
- - new function: xparse_dolparen, helper function for parsing
- command substitutions in $(...). Called from subst.c to extract
- a command substitution during word expansion. From bash-4.0-devel
- branch
- - new function: rewind_input_stream(). Rewinds bash_input.location.string
- back to where it was before the shell parsed a $() command
- substitution. From bash-4.0-devel branch
- - changes to parse_matched_pair to combine most of the flag variables
- (was_dollar, in_comment, and so on) into a local flags word
-
- 6/2
- ---
-parse.y
- - call trim_pathname, which retains only the last $PROMPT_DIRTRIM
- directories and replaces the intervening characters with `...',
- when expanding \w and \W
-
-doc/{bash.1,bashref.texi}
- - document the effect of setting PROMPT_DIRTRIM
-
- 6/3
- ---
-builtins/ulimit.def
- - make the multiplier (block size) for -c and -f 512 bytes only if in
- Posix mode and 1024 bytes otherwise (as in previous versions). Uses
- POSIXBLK and BLOCK_SIZE defines to parameterize size based on value
- of posixly_correct
-
-doc/bashref.texi
- - document this addition to posix mode
-
-builtins/common.c
- - change get_numeric_arg to have a calling sequence and return value
- more closely mimicking general.c:legal_number(), with the addition
- of a flags word
- - add extra value for `fatal' argument to get_numeric_arg to force it
- to return failure to the caller rather than longjmping
-
-builtins/common.h
- - change prototype declaration for get_numeric_arg
-
-builtins/{break,shift}.def
- - change calls to get_numeric_arg to deal with new semantics and calling
- sequence
-
-builtins/history.def
- - display_history now returns an int
- - change calling sequence for get_numeric_arg in display_history
- - display_history now returns failure to the caller if get_numeric_arg
- detects an invalid number, rather than jumping back to the top level
- - use value returned by display_history as return status of history
- builtin, filtered through sh_chkwrite
- - history no longer aborts compound commands on invalid arguments.
- fixes problem reported by Chu Li <chul@cn.fujitsu.com>
-
-{braces,subst}.c
- - extract_command_subst now takes a third flags argument; passed flags
- are ORd into flags passed to other functions; changed callers
-
-subst.h
- - move SX_* defines here from subst.c so parse.y:xparse_dolparen can
- see them and behave appropriately
- - extract_command_subst now takes a third flags argument; change
- prototype
-
-subst.c
- - change extract_command_subst to call xparse_dolparen when extracting
- a $() construct
- - change calls to extract_delimited_string to extract_command_subst
- as appropriate
- - if command_substitute returns a NULL word desc, don't call
- dispose_word_desc on it
-
-parse.y
- - change xparse_dolparen to use the SX_* flags now in subst.h
-
- 6/16
- ----
-subst.c
- - in quote_list, set W_HASQUOTEDNULL flag in the word if quote_string
- turns "" into CTLNUL
- - in dequote_list, turn off W_HASQUOTEDNULL flag in the word if
- dequote_string turns CTLNUL into ""
- - new function, string_list_pos_params, encapsulates everything
- needed to turn the positional parameters or an array indexed with
- '@' or '*' into a string, including taking care of quoting and
- using the first char of $IFS, when used in another expansion like
- pattern removal or pattern substitution
- - change list_remove_pattern, pos_params, pos_params_pat_subst to
- call string_list_pos_params. Fixes problems reported by
- Stephane Chazelas <stephane_chazelas@yahoo.fr>
-
- 6/22
- ----
-variables.h
- - include assoc.h for associative arrays
- - defines for case-modifying expansions and associative array variables
- - sh_var_assign_func_t functions now take an extra char * parameter
-
- 6/25
- ----
-variables.c
- - change declarations and definitions of sh_var_assign_func_t functions
- to add the extra char * parameter: null_assign, null_array_assign,
- assign_seconds, assign_random, assign_lineno, assign_subshell,
- assign_dirstack
- - change calls to var->assign_func to add extra char * argument
- - broke part of body of dispose_variable out into a new function,
- dispose_variable_value, which knows how to free all kinds of shell
- variable data
- - changes to deal with variables with the internal `nofree' attribute
-
-arrayfunc.c
- - change calls to var->assign_func to add extra char * argument
- - bind_array_var_internal now takes an extra `char *key' argument
- - additions for associative array implementation; from bash-4.0-devel
- tree
-
-arrayfunc.[ch],subst.c
- - expand_compound_array_assignment now takes the variable as the first
- argument (SHELL_VAR *); changed function definition and callers
-
-builtins/set.def
- - changes to handle associative arrays in `unset'
-
-{execute_cmd,command}.h
- - definitions for coproc implementation; from bash-4.0-devel tree
-
-variables.c
- - new functions for associative arrays: make_new_assoc_variable,
- make_local_assoc_variable
-
- 6/26
- ----
-variables.c
- - more infrastructure for associative arrays; from bash-4.0-devel tree
- - infrastructure for handling assignments to variables with
- case-modifying attributes; from bash-4.0-devel tree
-
-config.h.in
- - add #defines controlling case-modifying variable attributes and word
- expansions
-
-configure.in
- - add enable options for case-modifying variable attributes and word
- expansions (--enable-casemod-attributes and --enable-casemod-expansions,
- respectively); from bash-4.0-devel tree
-
-execute_cmd.c
- - add code to fix_assignment_words to handle assignment statements to
- "assignment builtins" that seem to be associative arrays. Imperfect
-
-subst.c
- - array_remove_pattern now takes a SHELL_VAR * as its first argument
- instead of an ARRAY *; from the bash-4.0-devel tree
- - changes to array_length_reference for associative arrays; from the
- bash-4.0-devel tree
- - changes to get_var_and_type for associative arrays; from the
- bash-4.0-devel tree
- - changes to parameter_brace_substring for associative arrays; from the
- bash-4.0-devel tree
- - changes to param_expand for associative arrays; from the
- bash-4.0-devel tree
-
-builtins/declare.def
- - changes for associative arrays: new `-A' option, changes to make
- local and global associative array variables; from the bash-4.0-devel
- tree
-
- 6/27
- ----
-execute_cmd.c
- - in execute_command_internal, when short-circuiting execution
- because `breaking' or `continuing' is non-zero, preserve the exit
- status by returning `last_command_exit_value' instead of an
- unconditional EXECUTION_SUCCESS. Fixes bug reported by Roman
- Rakus <rrakus@redhat.com>
-
- 6/28
- ----
-variables.c
- - fix get_var_and_type to appropriately handle references like
- ${varname[0]}, where `varname' is a scalar variable
-
-make_cmd.[ch],parse.y
- - make_here_document now takes a second argument: the current line
- number; changed caller (gather_here_documents)
-
-builtins/setattr.def
- - added support for associative arrays and the `-A' variable attribute
- option; from the bash-4.0-devel tree
-
-subst.c
- - change code that transforms `declare -A xxx=(yyy)' to perform the
- internal `declare -A xxx' before doing the variable assignment,
- because associative arrays have to be declared before being assigned
- to as such; uses new function make_internal_declare
-
- 6/30
- ----
-subst.[ch]
- - dequote_escapes is now external; add declaration in subst.h
- - remove_quoted_nulls is now external; add declaration in subst.h
-
-array.[ch]
- - new functions for completeness: array_dequote, array_dequote_escapes,
- array_remove_quoted_nulls
- - array_subrange now calls array_remove_quoted_nulls for "${array[*]}".
- Fixes bug reported by Vitor De Araujo <ux386@yahoo.com.br>
- - array_patsub now calls array_remove_quoted_nulls for "${array[*]}"
- - array_modcase now calls array_remove_quoted_nulls for "${array[*]}"
- - array_patsub now handles the mflags&MATCH_QUOTED case appropriately
- (that implies "${array[@]}")
-
-subst.c
- - new functions for case-modifying word expansion suppport:
- pos_params_casemod, parameter_brace_casemod; from bash-4.0-devel branch
-
-assoc.c
- - new functions for completeness: assoc_remove_quoted_nulls
- - assoc_patsub now calls assoc_remove_quoted_nulls for "${assoc[*]}"
- - assoc_modcase now calls assoc_remove_quoted_nulls for "${array[*]}"
- - assoc_patsub now handles the mflags&MATCH_QUOTED case appropriately
- (that implies "${assoc[@]}")
-
- 7/1
- ---
-assoc.[ch]
- - new function, assoc_subrange: takes a hash table, converts it to a
- word list, and performs the subrange and indexing on that list
- - new functions for completeness: assoc_dequote, assoc_dequote_escapes
-
-subst.c
- - verify_substring_values now takes the variable SHELL_VAR * as its
- new first argument; changed callers
- - change verify_substring_values to handle associative arrays using the
- number of elements as the upper bound
- - brought in code to do case-modifying word expansions from
- bash-4.0-devel branch, conditional on CASEMOD_EXPANSIONS
-
-input.c
- - if the read(2) in getc_with_restart returns -1/EAGAIN, turn off
- non-blocking mode on the file descriptor and try again. Fixes
- problem reported by Glynn Clements <glynn@clements.plus.com>
-
- 7/2
- ---
-doc/{bash.1,bashref.texi}
- - documented new case-modifying word expansions
-
-make_cmd.c
- - change make_here_document to display a warning message including the
- start line of a here document if it ends up delimited by EOF.
- Addresses issue raised by Richard Neill <rn214@hermes.cam.ac.uk>
-
-subst.c
- - in do_assignment_internal, make sure the `invisible' attribute is
- unset before returning success
-
- 7/3
- ---
-config-top.h
- - add `CASEMOD_CAPCASE' define to include or exclude the ~[~] word
- expansion and the `capcase' variable attribute (declare -c)
-
-builtins/declare.def
- - add support for manipulating the case-modifying attributes (new
- declare -clu); from bash-4.0-devel branch
-
-builtins/setattr.def
- - add support for reporting case-modifying attributes (-clu attributes);
- from bash-4.0-devel branch
-
-doc/{bash.1,bashref.texi}
- - specify that the read builtin timing out results in a return value
- greater than 128
- - document new `-l' and `-u' options to declare/typeset/local. Leave
- `-c' undocumented for now
-
- 7/4
- ---
-make_cmd.[ch]
- - make_coproc_command: construct a coproc; from bash-4.0-devel tree
-
-dispose_cmd.c
- - dispose coproc command; from bash-4.0-devel tree
-
-copy_cmd.c
- - copy a coproc command; from bash-4.0-devel tree
-
-print_cmd.c
- - print a coproc command; from bash-4.0-devel tree
-
-shell.c
- - dispoe the current coproc on shell exit; from bash-4.0-devel tree
-
-redir.c
- - when closing redirects as part of user redirections, check whether
- or not active coprocess fds are being closed and close the coproc
- if so; from bash-4.0-devel tree
-
-config.h.in
- - add define for COPROCESS_SUPPORT to include coprocesses
-
-configure.in
- - add support for configuring coprocesses into and out of the build
-
-jobs.c
- - in waitchld, check whether or not a coproc processs has exited;
- from the bash-4.0-devel tree
-
- 7/5
- ---
-doc/bashref.texi
- - document new --enable-coprocesses option that includes coprocess
- support
-
-execute_cmd.c
- - add functions for coprocess support, including execute_coproc and
- code to call it when command->type == cm_coproc; from
- bash-4.0-devel tree
-
-lib/sh/fdprintf.c
- - new library function fdprintf(int fd, const char *format, ...);
- printf to a file descriptor
-
-{configure,config.h}.in
- - support for detecting fdprintf and compiling in replacement
-
-Makefile.in,lib/sh/Makefile.in
- - add rules to include fdprintf.o
-
-doc/{bash.1,bashref.texi}
- - documented coprocesses and `coproc' reserved word
-
- 7/7
- ---
-subst.c
- - fix array_length_reference to use MB_STRLEN instead of STRLEN, so
- multibyte characters in array values are computed correctly. Fixes
- bug reported by Wang Xin <wxinee@gmail.com>
-
- 7/10
- ----
-jobs.c
- - new function, maybe_give_terminal_to (old, new, flags), sets the
- terminal pgrp to NEW if and only if it's currently set to OLD
- - call maybe_give_terminal_to when the parent sets the terminal pgrp
- to the pipeline pgrp in stop_pipeline, so we don't give the
- terminal to the new job's pgrp unless it's currently owned by the
- shell. Fixes race condition described by Joe Peterson
- <joe@skyrush.com>, where parent bash may change tty pgrp after a
- grandchild (interactive bash child of su) has changed it to
- something else. The call to maybe_give_terminal_to makes explicit
- a previously-implicit assumption
-
-aclocal.m4
- - remove dependency on writable /tmp by creating directories in
- build directory
-
-shell.c
- - make changes to how bash sets no_line_editing and running_under_emacs
- to deal with various emacs terminal emulators; use better check
- for `eterm', since bash sends $PWD to eterm with control sequences
- that confuse other programs. Problem reported by Micah Cowan
- <micah@cowan.name>
-
-
- 7/12
- ----
-print_cmd.c
- - break code that prints here-documents into two functions:
- print_heredoc_header, which prints the operator and delimiter, and
- print_heredoc_body, which prints the body text and closing delimiter
- - change print_redirection to call print_heredoc_{header,body}
- - sentinel variable, printing_connection, used when printing a command
- of type `connection' (|, &&, ||, etc.)
- - change print_redirection_list to save any here documents it finds
- while printing a connection and save them in `deferred_heredocs'
- - new function, print_deferred_heredocs, called from print_redirection
- in the cm_connection case, calls print_heredoc_header for all the
- here documents, then prints the operator (|, &&, ||, etc.), then
- the here-document body. This preserves syntactic correctness; the
- old code printed the control operator after the body of the here
- document. Fixes bug reported by <buport@figpost.com>
-
- 7/16
- ----
-locale.c
- - in set_locale_var, print a warning message if setlocale() fails any
- time it's called -- required some code restructuring
-
- 7/19
- ----
-support/shobj-conf
- - support for mingw32, contributed by Carlo Bramix
- <carlo.bramix@libero.it>
-
- 7/23
- ----
-execute_cmd.c
- - added support (currently unused) to manage a list of coprocs
-
- 7/25
- ----
-bashline.c
- - add extern declarations for literal_history and force_append_history
-
-builtins/shopt.def
- - include "bashhist.h" instead of having extern declarations for the
- appropriate history variables
-
-parser.h
- - new parser_state value: PST_HEREDOC, set when reading body of here-
- document in parse.y:read_secondary_line
-
-parse.y
- - set PST_HEREDOC bit in parser_state when reading a secondary line
- for the body of a here-document
- - change read_secondary_line to save lines in the body of a here-
- document in the shell history list if remember_on_history is
- set. Fixes bug reported by Gene Golub <gene_golub@hotmail.com>
-
- 8/4
- ---
-configure.in
- - changed to 4.0-alpha
-
-lib/readline/readline.h
- - changed constants to reflect readline-6.0 version
-
- 8/11
- ----
-lib/readline/signals.c
- - make sure we don't use SIGWINCH without checking whether or not it's
- defined. Fix from Pedro Alves <pedro@codesourcery.com>
-
- 8/12
- ----
-
-COPYING
- - updated to GPLv3; edits in every file with a copyright or license
- declaration to update to gpl3
-
-version.c
- - update extended version info to latest gnu standard
-
- 8/17
- ----
-subst.c
- - change exp_jump_to_top_level to only call top_level_cleanup if
- parse_and_execute_level is 0. If it's not, the longjmp to
- parse_and_execute will run the unwind-protect stack. Fixes bug
- most recently reported by Roman Rakus <rrakus@redhat.com>
-
- 8/18
- ----
-support/config.{guess,sub}
- - updated to newer versions from autoconf-2.62 distribution
-
- 8/20
- ----
-subst.c
- - fixed parameter_brace_substring to differentiate between indexed and
- associative arrays when computing second offset, instead of
- assuming indexed array
-
- 8/21
- ----
-support/xcase.c
- - simple program to convert input from lower to uppercase and vice
- versa. Now used by coproc test suite, since `tr -u' is not
- portable.
-
- 8/22
- ----
-doc/bash.1
- - fixed description of the bindable edit-and-execute commands to note
- they check $VISUAL first, instead of $FCEDIT. Fixed bug reported
- by
-
-[bash-4.0-alpha frozen]
-
- 8/28
- ----
-[bash-4.0-alpha released]
-
- 9/1
- ---
-builtins/evalstring.c
- - fixed typo in parse_string (ostring used uninitialized). Bug
- reported by Andreas Schwab <schwab@suse.de>
-
-subst.c
- - fix return value of parameter_brace_expand to set the
- W_HASQUOTEDNULL flag in the returned WORD_DESC * if the return value
- from parameter_brace_remove_pattern is a quoted null string. Fixes
- bug reported by Andreas Schwab <schwab@suse.de>
- - set the W_HASQUOTEDNULL flag in the return value from
- parameter_brace_expand if the return value from parameter_brace_patsub
- is a quoted null string
-
- 9/6
- ---
-builtins/read.def
- - change read -t 0 to return success if there is input available to be
- read -- allows scripts to poll for input. Uses input_avail libsh
- function
-
- 9/9
- ---
-externs.h
- - fix extern fpurge declaration -- use HAVE_DECL_FPURGE instead of
- NEED_FPURGE_DECL, since the former is set by `configure'
-
-jobs.h
- - add extern declaration for close_pgrp_pipe
- - add a new job state JNONE (-1) to the enum
-
-jobs.c
- - include execute_cmd.h for extern declarations for coproc functions
-
-subst.c
- - include builtins/builtext.h for extern declarations for functions
- implementing builtins (e.g., declare_builtin)
-
-arrayfunc.c
- - include "pathexp.h" for extern declaration for glob_char_p
-
-braces.c
- - add extern declaration for `asprintf'
-
-lib/readline/rlprivate.h
- - add extern declarations for _rl_trace, _rl_tropen
-
-lib/sh/zgetline.c
- - add extern declarations for zread, zreadc
-
-lib/sh/mktime.c
- - include "bashansi.h" for string function declarations
-
-builtins/common.h
- - add extern declaration for parse_string
-
-trap.c
- - include jobs.h for extern declaration for run_sigchld_trap
-
-general.c
- - fix call to strtoimax in legal_number; if ep == string when function
- returns, the number was not converted, even if errno is not set.
- Fix from Paul Jarc <prj@case.edu>
-
- 9/11
- ----
-[prayers for the victims of 9/11/2001]
-
-builtins/return.def
- - call no_options, as Posix requires. This also has the effect of
- disallowing negative return values unless they're prefixed by `--'
-
- 9/13
- ----
-builtins/bind.def
- - add an error message when bind is used without line editing active,
- instead of just returning an error status
-
-variables.c
- - make sure make_local_variable never creates visible variables with
- a value, whether or not a variable with the same name existed in a
- previous context. This is consistent with ksh93. Fix from
- <neil@s-z.org>
-
- 9/16
- ----
-execute_cmd.c
- - add call to CHECK_TERMSIG in shell_execve after the call to execve
- returns. Recommended by Roman Rakus <rrakus@redhat.com>
- - add QUIT check in execute_connection after executing first command
- in a `&' connection
-
- 9/22
- ----
-execute_cmd.c
- - new semaphore variable, executing_list, incremented every time a
- list (command1;command2 or command1 || command2 or command1 &&
- command2) is executed; used as sentinel for rest of shell
-
-sig.c,builtins/evalstring.c
- - set executing_list to 0 when throwing execution back to top level;
- make sure to unwind-protect it in appropriate places
-
-jobs.c
- - if a pipeline is killed by SIGINT while executing a list (when
- executing_list is non-zero), make sure the shell acts as if an
- interrupt occurred. The behavior is dependent on the shell
- compatibility level being > 32 (bash-4.0 and above)
-
- 9/23
- ----
-redir.c
- - don't bother reporting an error with a file descriptor, even if
- the errno is EBADF, if the redirection error (e.g., NOCLOBBER)
- can't have anything to do with the fd. Fixes bug reported by
- "David A. Harding" <dave@dtrt.org>, debian bug #499633.
-
- 9/24
- ----
-builtins/declare.def
- - make `declare [option] var' (and the `typeset' equivalent) create
- invisible variables, instead of assigning the null string to a
- visible variable. Fixes bug reported by Bernd Eggink <monoped@sudrala.de>
-
- 9/25
- ----
-builtins/common.[ch]
- - new function, builtin_warning(), like builtin_error but for warning
- messages
-
-builtins/bind.def
- - experimental: print a warning, but go on, if line editing not active
- when bind is invoked. Suggested by Rocky Bernstein
- <rocky.bernstein@gmail.com>
-
- 10/3
- ----
-test.c
- - use same_file instead of directly comparing st_dev and st_ino when
- comparing files in filecomp(). From mingw32 patches submitted
- by Hector Chu <hkcc2@cantab.net>
-
- 10/4
- ----
-
-redir.c
- - in redirection_error(), use `error' instead of errno when comparing
- against EBADF. From mingw32 patches submitted by Hector Chu
- <hkcc2@cantab.net>
-
-shell.c
- - in unset_bash_input(), reset bash_input.type to st_none after
- closing the default buffered fd. From mingw32 patches submitted
- by Hector Chu <hkcc2@cantab.net>
-
-builtins/cd.def
- - ignore CDPATH when in privileged mode. Suggested by Paul Jarc
- <prj@po.cwru.edu>
-
-variables.c
- - change sv_globignore to only act if privileged mode is not enabled.
- Suggested by Paul Jarc <prj@po.cwru.edu>
-
-doc/bash.1,bashref.texi
- - document new treatment of CDPATH and GLOBIGNORE when privileged
- mode is enabled
-
-builtins/read.def
- - change prompt printing to occur after terminal is set to no-echo
- mode. Based on suggestion from Stephane Chazelas
- <stephane_chazelas@yahoo.fr>
-
-lib/readline/signals.c
- - new variables to keep track of special characters corresponding to
- SIGINT, SIGQUIT, and SIGTSTP
- - new variable to keep track of whether tty is echoing control
- characters corresponding to SIGINT, SIGQUIT, and SIGTSTP
- - new function, _rl_echo_signal_char(int sig) to display the tty
- special char generating SIGINT, SIGQUIT, or SIGTSTP. Based on
- idea and code from Joe Peterson <joe@skyrush.com>
- - call rl_echo_signal_char in rl_signal_handler: if the terminal
- settings indicate it, readline will echo characters that generate
- keyboard signals
-
-lib/readline/rltty.c
- - set _rl_intr_char, _rl_quit_char, and _rl_susp_char to special
- characters that generate signals from keyboard
- - set _rl_echoctl if ECHOCTL tty flag is set
-
-lib/readline/rlprivate.h
- - extern declarations for _rl_intr_char, _rl_quit_char, and
- _rl_susp_char
- - extern declaration for _rl_echoctl
-
-lib/readline/readline.h
- - extern declaration for rl_echo_signal_char()
-
-lib/readline/doc/rltech.texi
- - document rl_echo_signal_handler(): available for applications
- that install their own signal handlers
-
- 10/5
- ----
-execute_cmd.c
- - fix errexit logic to not cause the shell to exit when a command in
- a pipeline fails. Fixes bug reported by Marcin Owsiany
- <marcin@owsiany.pl>
-
- 10/14
- -----
-builtins/evalstring.c
- - don't short-circuit execution in parse_and_execute if we want to
- run an exit trap. Fixes bug reported by Steffen Kiess
- <s-kiess@web.de>
-
- 10/18
- -----
-parse.y
- - fix error production to only call YYACCEPT if the shell is currently
- interactive and not in parse_and_execute (so parser errors in
- things like eval will correctly set $?). Fixes bug reported by
- marco-oweber@gmx.de
-
-execute_cmd.c
- - make sure variable name errors in execute_for_command and non-
- identifier function names in execute_intern_function set the
- return status to EX_BADUSAGE (2), not EX_USAGE (258)
-
-parser.h
- - new parser state, PST_REPARSE
-
-parse.y
- - turn PST_REPARSE on in parse_string_to_word_list
- - in parse_matched_pair, if parsing a single-quoted string and
- PST_REPARSE is set, don't requote CTLESC or CTLNUL. Fixes bug with
- compound array assignment using $'\x7f' reported by Antonio Macchi
- <antonio_macchi@alice.it>
-
- 10/23
- -----
-configure.in
- - define LOCAL_LDFLAGS as `-z interpose' on Solaris 8, 9, and 10 to
- allow the bash malloc to interpose the libc malloc when called by
- library functions pre-bound to the libc malloc. Suggested by
- Serge Dussud <Serge.Dussud@Sun.COM>
-
- 10/26
- -----
-doc/bash.1
- - add single-sentence descriptions to rest of parameter expansions.
- Suggested by Ken Irving <fnkci@uaf.edu>
-
- 10/27
- -----
-subst.c
- - rearrange code in skip_to_delims to allow quote characters and other
- shell expansion characters to be delimiters
- - add new flags value for inverting search: skip to the next character
- NOT in the set of delimiters passed as an argument
-
-subst.h
- - define for new SD_INVERT flag value for skip_to_delims
-
- 10/28
- -----
-bashline.c
- - new bindable functions: shell-forward-word and shell-backward-word.
- Like forward-word and backward-word, but understand shell quoting
- and use shell metacharacters and whitespace as delimiters.
- Suggested by Andre Majorel <amajorel@teaser.fr>
- - new bindable functions: shell-kill-word and shell-backward-kill-word.
- Like kill-word and backward-kill-word, but understand shell quoting
- and use shell metacharacters and whitespace as delimiters.
- Suggested by Andre Majorel <amajorel@teaser.fr>
-
-doc/bash.1,lib/readline/doc/rluser.texi
- - documented shell-forward-word and shell-backward-word
- - documented shell-kill-word and shell-backward-kill-word
-
- 11/1
- ----
-redir.c
- - add extra argument to add_undo_redirect: fdbase. FD used to save
- a file descriptor must be > fdbase if fdbase >= SHELL_FD_BASE. A
- value of -1 for fdbase means to just use SHELL_FD_BASE. Fixes bug
- with 0<&10 reported by Clark Jian Wang <dearvoid@gmail.com>
-
- 11/5
- ----
-unwind_prot.c
- - new function: have_unwind_protects(); returns 1 if unwind_protect_list
- is not empty
-
-unwind_prot.h
- - extern declaration for have_unwind_protects
-
-builtins/evalstring.c
- - in parse_and_execute_cleanup, make sure that we don't call
- run_unwind_frame and expect it to decrement parse_and_execute_level
- if there's no unwind_protect_list, since there's a while loop in
- throw_to_top_level that calls parse_and_execute_cleanup as long as
- parse_and_execute_level is non-zero
-
- 11/9
- ----
-variables.c
- - fix the assign function for COMP_WORDBREAKS to allocate new memory
- to store as the variable's value, to avoid freeing memory twice
- if the variable is unset after rl_completer_word_break_characters
- is freed and reallocated. Fix from Mike Stroyan <mike@stroyan.net
-
- 11/11
- -----
-bashline.c
- - new function to reset the value of rl_completer_word_break_characters
- while honoring setting of `hostcomplete': reset_completer_word_break_chars.
-
-bashline.h
- - new extern declaration for reset_completer_word_break_chars.
-
-variables.c
- - call reset_completer_word_break_chars in sv_comp_wordbreaks when the
- variable is unset
-
-[bash-4.0-beta frozen]
-
- 11/16
- -----
-subst.c
- - call set_pipestatus_from_exit in exp_jump_to_top_level so that
- failed expansions that set $? will set $PIPESTATUS. Fixes bug
- reported by Eric Blake <ebb9@byu.net>
-
- 11/20
- -----
-general.c
- - new 'file_exists(fn)' primitive; just calls stat(2)
-
-general.h
- - new extern declaration for file_exists
-
-bashline.c
- - add `~' to rl_filename_quote_characters so make_quoted_replacement
- will call bash_quote_filename for words containing `~'. Then
- bash_quote_filename can make choices based on that
- - change quote_word_break_chars to backslash-quote the tilde in a
- filename with a leading tilde that exists in the current directory,
- since we want to inhibit tilde expansion in this case
-
-execute_cmd.c
- - call file_isdir from shell_execve instead of stat(2) directly
-
-bashhist.c
- - use file_exists and file_isdir primitives instead of calling stat
-
- 11/21
- -----
-redir.c
- - When undoing saving of non-standard file descriptors (>=3) using
- file descriptors >= SHELL_FD_BASE, we set the saving fd to be
- close-on-exec and use a flag (RX_SAVCLEXEC) to decide how to set
- close-on-exec when the fd is restored. Set flag in add_undo_redirect,
- check in do_redirection_internal. Fixes problem reported by Andreas
- Schwab <schwab@suse.de>
-
- 11/26
- -----
-subst.c
- - fix param_expand to have expansions of $@ and $* exit the shell if
- there are no positional parameters and `set -u' is enabled. Fixes
- bug reported by Dan Jacobson <jidanni@jidanni.org>
-
- 11/27
- -----
-lib/readline/display.c
- - fix update_line to not call space_to_eol if current cursor position
- (_rl_last_c_pos) indicates that we're already at end of line.
- Partial fix for bug reported by Mike Frysinger <vapier@gentoo.org>
- - in update_line, don't call insert_some_chars if that will start
- before the last invisible character in the prompt string and not
- draw the entire prompt string. More of the partial fix for bug
- reported by Mike Frysinger <vapier@gentoo.org>
- - fix update_line to adjust _rl_last_c_pos by wrap_offset when adding
- characters beginning before the last invisible character in the
- prompt. New code is same as previously existed in a different code
- path. Rest of fix for bug from Mike Frysinger <vapier@gentoo.org>
- - fix assignment of newline breaks (inv_lbreaks) to correctly account
- for prompts longer than two screen lines containing invisible
- characters. The assumption is that part of the invisible characters
- are on the first line (prompt_invis_chars_first_line) and the
- remainder are on the last (wrap_offset - prompt_invis_chars_first_line).
- Fix is in rl_redisplay. part of fix for bug reported by
- "Wesley J. Landaker" <wjl@icecavern.net> in
- http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=265182
- [TENTATIVE]
- - fix _rl_move_cursor_relative to correctly offset `dpos' by `woff'
- when there are invisible characters on lines after the second by
- using (_rl_screenwidth*_rl_last_v_pos) when seeing whether or not
- we just wrote some invisible characters. Rest of fix for bug
- reported in http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=265182
- [TENTATIVE]
-
- 12/11
- -----
-sig.c
- - reset the execution context before running the exit trap in
- termsig_handler
-
-general.c
- - set and unset terminate_immediately like interrupt_immediately in
- bash_tilde_expand
-
-builtins/read.def
- - change terminate_immediately to a counter instead of a flag, as
- interrupt_immediately is used
-
-lib/readline/display.c
- - slight change to fix from 11/27 to deal with prompts longer than a
- screen line where the invisible characters all appear after the
- line wrap. Fixes bug reported by Andreas Schwab <schwab@suse.de>
-
-builtins/{echo,printf}.def
- - increment terminate_immediately at entry; decrement before returning.
- Fix for bug reported by Ralf.Wildenhues@gmx.de
-
- 12/16
- -----
-subst.c
- - fix off-by-one error in /dev/fd version of add_fifo_list; make
- sure we add to totfds when it is == fd, not just when fd > totfds.
- Fixes bug reported by marciso@gmail.com
-
-[bash-4.0-beta2 frozen]
-
- 12/29
- -----
-doc/{bash.1,bashref.texi}
- - document more clearly that when not in Posix mode, command
- substitution does not inherit the -e option. From bug report from
- Freddy Vulto <fvulto@gmail.com>
-
-{execute_cmd,sig,builtins/evalstring}.c
- - sentinel variable to keep track of whether or not we're supposed to
- ignore the failure status of a command executed in a command
- substitution even if the `-e' option is set: comsub_ignore_return
- - increment and decrement comsub_ignore_return in execute_simple_command
- before calling expand_words
- - in parse_and_execute, if comsub_ignore_return is non-zero and the
- SUBSHELL_COMSUB bit is set in subshell_environment, enable the
- CMD_IGNORE_RETURN flag in every command executed from the passed
- string. Fixes problem reported by Freddy Vulto <fvulto@gmail.com>
- - make sure to reset comsub_ignore_return every time we throw to the
- top level, like executing_list flag
-
- 1/2/2009
- --------
-parse.y
- - fix to rewind_input_stream to handle case of $(...) command
- substitution followed by a quoted literal newline. Report and fix
- from Andreas Schwab <schwab@suse.de>
-
- 1/7
- ---
-
-subst.c
- - fix match_wpattern and match_upattern to prefix a `*' to the
- pattern even if it starts with a `*(' (if extglob is enabled)
- before checking whether or not it can match anywhere in the
- string. Fixes bug reported by os@sernet.de.
-
-[bash-4.0-rc1 frozen]
-
- 1/9
- ---
-locale.c
- - since setlocale() doesn't set errno to anything meaningful,
- don't include the strerror() result in the error message if
- it fails
- - make sure the error messages printed when setlocale fails are
- localizable
-
- 1/11
- ----
-lib/readline/histexpand.c
- - make sure that every time history_no_expand_chars is tested, we
- also call the history_inhibit_expansion_function if it's set.
- Fixes bug reported by Yang Zhang <yanghatespam@gmail.com>
-
- 1/12
- ----
-trap.c
- - make sure to call parse_and_execute with the SEVAL_RESETLINE bit
- set in the flags so it will reset the line number when running
- the trap commands. Partial fix for bug reported by
- peter360@fastmail.us
-
- 1/14
- ----
-builtins/reserved.def
- - document `coproc' so it can be used with `help' builtin. Pointed
- out by Pierre Gaston <pgas@freeshell.org>
-
-lib/sh/casemod.c
- - added two new flags: CASE_UPFIRST and CASE_LOWFIRST to casemod
- the first character of the passed string and pass the rest
- through unchanged. Fixes bug reported by Jan Schampera
- <jan.schampera@web.de>
-
-externs.h
- - new defines for CASE_UPFIRST and CASE_LOWFIRST
-
-subst.c
- - use CASE_UPFIRST for ^ and CASE_LOWFIRST for , casemod operators
-
-builtins/mapfile.def
- - call zreset() before calling first zgetline(), to clean out any
- remaining data in local buffer used by zreadc. Fixes bug
- reported by Pierre Gaston <pierre.gaston@gmail.com>
-
- 1/15
- ----
-lib/sh/zread.c
- - renamed zreadintr to zreadretry -- not perfect, but better
- - new functions: zreadintr, which just calls read so it can be
- interruptible, and zreadcintr, which is like zreadc but uses
- zreadintr to fill the buffer
-
-lib/sh/zgetline.c
- - in zgetline, when zread/zreadc return <= 0, make sure line is
- non-null before assigning to line[nr]
-
-builtins/mapfile.def
- - return an error right away if the supplied array variable name
- refers to a readonly or noassign array
- - set interrupt_immediately so calls to zgetline can be
- interrupted. Fixes bug reported by Pierre Gaston
- <pierre.gaston@gmail.com>
- - if interactive, pass the SEVAL_INTERACT and SEVAL_NOHIST flags
- to parse_and_execute when calling callbacks. Fixes bug reported
- by Pierre Gaston <pierre.gaston@gmail.com>
- - add `readarray' as a synonym for mapfile
-
-doc/{bash.1,bashref.texi}
- - document behavior of mapfile builtin adding index of array element
- to be assigned as additional argument to callback string. Reported
- by Pierre Gaston <pierre.gaston@gmail.com>
- - document readarray as synonym for mapfile
-
-builtins/common.c
- - new error function, sh_ttyerror(set), prints an error message having
- to do with setting or getting terminal attributes
-
-builtins/read.def
- - print error message if read fails to set terminal attributes
-
- 1/16
- ----
-execute_cmd.c
- - new function, coproc_reap, calls coproc_dispose if sh_coproc is
- marked as COPROC_DEAD
- - new function, cpl_reap, disposes coprocs marked as COPROC_DEAD
- from coproc list
- - change coproc_pidchk to just mark the coproc as dead instead of
- calling coproc_dispose, so we don't call unsafe functions from
- a signal handler. Fixes bug reported by Andreas Schwab
- <schwab@suse.de>
-
-execute_cmd.h
- - new extern declaration for coproc_reap
-
-command.h
- - new flags for c_flags member of a struct coproc
-
-{jobs,nojobs}.c
- - add call to coproc_reap in cleanup_dead_jobs, which will do the
- right queueing or blocking of SIGCHLD
-
-trap.c
- - modify change from 1/12 to not reset the line number when running
- the DEBUG and RETURN traps
-
- 1/18
- ----
-lib/sh/casemod.c
- - change default operations to work on entire passed string instead
- of breaking into words at non-alpha-numerics. Use new
- CASE_USEWORDS flag to enable by-word behavior. Fixes bug reported
- by Jan Schampera <jan.schampera@web.de>
-
-builtins/printf.def
- - in vbprintf, bracket each call to vsnprintf (which uses the args
- passed to vbprintf) with SH_VA_START and va_end, so we can
- reninitialize the argument list for each call. This is actually
- what the C standard requires. Fixes bug that caused printf -b
- to `ignore' first % format specifier if it came first in the
- string. Reported by David Leverton <levertond@googlemail.com>
-
-builtins/mapfile.def
- - start the line count at 1, since it doesn't get incremented before
- (or after) reading the first line, so things like
- `mapfile -n 5 -c 1 -C 'echo foo' array < file' work right and call
- the callback after the first line is read. Fixes bug reported by
- Pierre Gaston <pierre.gaston@gmail.com>
-
- 1/22
- ----
-lib/readline/complete.c
- - set _rl_interrupt_immediately non-zero before reading from the file
- system or calling an application-defined completion function
-
-lib/readline/signals.c
- - renamed rl_signal_handler to _rl_handle_signal; new version of
- rl_signal_handler that just calls _rl_handle_signal (for now)
- - new function _rl_signal_handler that calls _rl_handle_signal without
- any checking
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_signal_handler
- - new define, RL_CHECK_SIGNALS, checks whether or not _rl_caught_signal
- is set and calls _rl_signal_handler if so
-
-lib/readline/{bind,input,readline}.c
- - add RL_CHECK_SIGNALS in appropriate places
-
-lib/readline/signals.c
- - change rl_signal_handler to set a flag and return rather than
- run through the entire signal handling process. If
- _rl_interrupt_immediately is set, call the signal handling code
- right away instead of setting the flag. Initial fix for crash
- bug reported by Roman Rakus <rrakus@redhat.com>
-
-aclocal.m4
- - new macro, BASH_TYPE_SIG_ATOMIC_T, tests for sig_atomic_t in
- <signal.h>, defines as int if not defined
-
-configure.in
- - call BASH_TYPE_SIG_ATOMIC_T
- - call AC_C_VOLATILE
-
-config.h.in
- - empty define for sig_atomic_t
- - empty define for volatile
-
- 1/27
- ----
-subst.c
- - audit calls to add_character and change to add_ifs_character (which
- quotes characters in $IFS). Affects primarily `:', `=', and `~'.
- Fixes bug reported by Jan Schampera <jan.schampera@web.de>; fix
- suggested by Stephane Chazelas <stephane_chazelas@yahoo.fr>
-
- 2/1
- ---
-configure.in
- - call AC_C_RESTRICT
-
-config.h.in
- - add empty defintion for `restrict'
-
-pcomplete.c
- - use unwind_protects around call to execute_shell_function in
- gen_shell_function_matches to prevent data corruption if
- throw_to_top_level is called. Bug report and fix from
- werner@suse.de.
-
-execute_cmd.c
- - don't clamp CPU usage at 100% in print_formatted_time. Bug reported
- by Linda Walsh <bash@tlinx.org>
-
- 2/5
- ---
-locale.c
- - in set_locale_var, set errno to 0 before calling setlocale(), and
- print strerror (errno) if setlocale fails and errno ends up non-zero
-
- 2/6
- ---
-configure.in
- - backed out of solaris change from 10/23/2008 (adding `-z interpose'
- to LDFLAGS) due to solaris updates to fix a linker problem.
- Updatted by Serge Dussud <Serge.Dussud@Sun.COM>
-
- 2/12
- ----
-execute_cmd.c
- - change execute_connection so failure of a pipeline will cause the
- shell to exit if -e is on. From discussion on austin-group
- mailing list
- - change execute_command_internal so failure of a user-specified
- subshell will cause the shell to exit if -e is on. From discussion
- on austin-group mailing list
-
- 2/13
- ----
-doc/{bash.1,bashref.texi}
- - clarified description of set -e option to accurately reflect current
- implementation
-
- 2/19
- ----
-print_cmd.c
- - fix print_deferred_heredocs to not print a space if the separator
- string is null
- - change print_deferred_heredocs to set `was_heredoc' after printing
- something
- - change connection printing code to only print the `;' separator
- if we haven't just printed a here-document
- - change connection printing code to print any deferred here
- documents after the rhs of the connection. Fixes bug reported by
- Bo Andresen <bo.andresen@zlin.dk>
-
-[bash-4.0 frozen]
-
- 2/20
- ----
-
-[bash-4.0 released]
-
- 2/22
- ----
-
-parse.y
- - fix parse_comsub to not test a character for being a possible shell
- metacharacter if LEX_PASSNEXT flag is set. Fixes bug reported by
- Mike Frysinger <vapier@gentoo.org>
-
-pcomplete.c
- - add call to save_parser_state (accidentally dropped from patch) to
- gen_shell_function_matches. Fixes bug with bash_completion and
- file/directory completion reported by phil@Arcturus.universe
-
-Makefile.in
- - fix assignment to LDFLAGS_FOR_BUILD to match those in subdir
- Makefiles. Fixes bug reported by Mike Frysinger <vapier@gentoo.org>
-
-builtins/mapfile.def
- - make sure the callback quantum (-c option argument) is > 0. Fixes
- bug reported by Stephane Chazleas <stephane_chazelas@yahoo.fr>
-
- 2/23
- ----
-parse.y
- - fix save_token_state and restore_token_state to save and restore
- current_token. Fixes bug reported by Bernd Eggink
- <monoped@sudrala.de>
-
-builtins/exit.def
- - check jobs[i] before checking whether or not it's running when
- the checkjobs option is set and we're looking for running jobs
- at exit. Fixes bug reported by Mike Frysinger <vapier@gentoo.org>
-
- 2/24
- ----
-siglist.c
- - include bashintl.h for definition of _. Fixes bug reported by
- Greg Wooledge <wooledg@eeg.ccf.org>
-
- 2/25
- ----
-subst.c
- - new function, skip_matched_pair. Similar to skip_to_delim and
- the extract_XXX family
- - move skipsubscript here from arrayfunc.c; re-implement in terms of
- skip_matched_pair. Fixes bugs reported by <anmaster@tele2.se>
-
-arrayfunc.c
- - remove skipsubscript; moved to subst.c
-
-parse.y
- - change reset_parser to set current_token to '\n'. Rest of fix for
- bug reported by Bernd Eggink <monoped@sudrala.de>; earlier fix on
- 2/23
-
- 2/26
- ----
-builtins/declare.def
- - when given something like array[x]=y (which sets making_array_special
- to 1), don't convert an associative array to an indexed array (line
- 493). Part of fix for bug reported by Pierre Gaston
- <pierre.gaston@gmail.com>
- - if offset == 0, indicating that we do not have a valid assignment,
- make sure any `name' containing a `[' is a valid array reference
- before trying to go on. Not doing this leads to creating crazy
- variables like `name[foo[bar]=bax'. Rest of fix for bug reported
- by Pierre Gaston <pierre.gaston@gmail.com>
-
-assoc.c
- - change assoc_to_assign to single-quote the array keys if `quoted' is
- non-zero. Makes things easier to read with weird characters in the
- key
-
-parse.y
- - fix parse_comsub to not set LEX_HEREDELIM when it sees "<<<". Fixes
- bug reported by Mike Frysinger <vapier@gentoo.org>
-
- 2/27
- ----
-parse.y
- - fix report_syntax_error to set last_command_exit_value to
- EX_BADUSAGE (2) instead of EX_USAGE (258), since there's nothing
- that will translate that to something < 128 before reading the
- next command. Partial fix for bug reported by Mike Frysinger
- <vapier@gentoo.org>
-
-sig.c
- - fix sigint_sighandler to set last_command_exit_value to sig+128
- before calling throw_to_top_level. Rest of fix for bug reported
- by Mike Frysinger <vapier@gentoo.org>
-
-jobs.c
- - if fork() fails, set last_command_exit_value to 126 before calling
- throw_to_top_level
-
-execute_cmd.c
- - defer calling unlink_fifo_list in parent branch of
- execute_disk_command if we're executing in a shell function
- - change execute_function to call unlink_fifo_list before returning
- if it's the top-level function
-
- 3/2
- ---
-builtins/read.def
- - if read times out, make sure we remove the top element from the
- unwind-protect stack (the free of input_string) and run the rest,
- to reset the tty and readline and alarm states. Then we jump to
- assigning the variables to any partial input. Fixes bug reported
- by Christopher F. A. Johnson <cfajohnson@gmail.com>
-
- 3/3
- ---
-parse.y
- - break comment checking code into a common COMMENT_BEGIN define so
- we can use it in multiple places in parse_comsub
- - in parse_comsub, don't alter the LEX_RESWDOK flag if we read a
- `#' and we're checking comments, even though `#' isn't a `shell break'
- character. Fixes bug reported by Mike Frysinger <vapier@gentoo.org>
-
-braces.c
- - in expand_seqterm, decrease the total length of the rhs by the length
- of any (optional) increment, so we don't end up with unwanted zero
- padding because the rhs length is wrong. Fixes bug reported by
- Carl Albing <albing@comcast.net>
-
- 3/4
- ---
-doc/{bash.1,bashref.texi}
- - changes to clean up some of the language describing the effects of
- terminal process groups on the ability to read from and write to
- the terminal
-
- 3/5
- ---
-support/shobj-conf
- - add host_vendor to string tested in switch to handle things like
- gentoo/freebsd
- - beginning with version 7, FreeBSD no longer has /usr/bin/objformat
- or a.out binaries and libraries. It's always ELF. Fix from
- Timothy Redaelli <drizzt@gentoo.org>
-
-parse.y
- - in parse_comsub, allow comments if we are ready to read a
- reserved word (tflags & LEX_RESWDOK), haven't read anything from
- one yet (lex_rwlen == 0) and the current character is a '#'
-
- 3/6
- ---
-parse.y
- - new lex flag for parse_comsub: LEX_INWORD. Turn it off when
- we see a shell break character; turn it on or keep it on when
- not a break character. Keep track of word length (reset to 0
- when we turn on LEX_INWORD when it was off).
- - don't use COMMENT_BEGIN in parse_comsub any more; test
- whether or not LEX_INWORD is set and lex_wlen == 0 in addition
- to tests for LEX_RESWDOK and lex_rwlen. Comments are valid
- when at the start of a word
- - move LEX_PASSNEXT code to the top of parse_comsub, so the rest
- of the function doesn't have to check for the flag at different
- places
-
- 3/7
- ---
-parse.y
- - in parse_comsub, when looking for a reserved word (LEX_RESWDOK
- non-zero), and in a case statement, we can see either an esac
- or a pattern list. We handle an esac separately. We should
- turn off LEX_RESWDOK if we see anything but a newline, since
- we'll be reading a pattern list. Other part of fix for bug
- reported by Mike Frysinger <vapier@gentoo.org> (rest of fix
- on 3/3)
-
- 3/10
- ----
-{.,lib/readline}/doc/fdl.texi
- - updated to FDL version 1.3
-
- 3/11
- ----
-parse.y
- - when using the |& construct with a simple command preceding it, add
- the implicit redirection to the simple command's redirection list,
- since the redirections associated with the command struct are never
- executed. Fixes bug reported by Matt Zyzik <Matt@ice.filescope.com>
-
- 3/14
- ----
-execute_cmd.c
- - in execute_case_command, if ;& is used with no following pattern
- list, make sure we don't reference a NULL pointer. Bug report and
- fix from Clark Jian Wang <dearvoid@gmail.com>
-
-parse.y
- - make parser_state global, so other files can use it
- - command_word_acceptable now returns non-zero if PST_REDIRLIST bit
- set in parser_state, so we accept assignment statements and
- perform alias expansion. Fix for bug reported by Vincent
- Lefevre <vincent@vinc17.org> (2/24/2009)
-
-parser.h
- - add PST_REDIRLIST flag, notes that parser is currently parsing a
- redirection list preceding a simple command
-
-make_cmd.c
- - make_simple_command now turns on PST_REDIRLIST in parser_state when
- creating a new simple command
- - make_simple_command turns off PST_REDIRLIST in parser_state if it
- adds a non-redirection to the command it's building
- - clean_simple_command turns off PST_REDIRLIST to make sure it's off
-
-subst.c
- - new flag for param_expand: PF_IGNUNBOUND, means to not exit if the
- variable is unbound even if `set -u' is enabled
- - change param_expand to not call err_unboundvar if the `pflags'
- argument has the PF_IGNUNBOUND bit set
- - parameter_brace_expand_word now takes an extra `pflags' argument to
- pass down to param_expand; changed callers
- - changed call to parameter_brace_expand_word in parameter_brace_expand
- to add PF_IGNUNBOUND flag so ${@:-foo} doesn't cause the shell to
- exit (but ${@} does) when there are no positional parameters. Fixes
- Debian bug 519165 from Dan Jacobson <jidanni@jidanni.org>
-
-parse.y
- - add code to parse_comsub to allow here-documents within command
- substitutions to be delimited by the closing right paren, with the
- usual warning about here documents delimited by EOF on execution.
- Fixes regression from bash-3.2 noted in Red Hat bugzilla 485664 by
- Ralf Corsepius
-
- 3/15
- ----
-subst.c
- - string_list_dollar_at now checks for Q_PATQUOTE, which getpattern()
- uses to denote Q_DOUBLE_QUOTES (?). Fixes a=abcd echo "${a#$*}"
- when IFS= and args are `a b' as noted by Stephane Chazleas
- <stephane_chazelas@yahoo.fr>
- - param_expand now checks for Q_PATQUOTE and treats it identically
- to Q_DOUBLE_QUOTES when expanding $*
- - expand_word_unsplit now sets W_NOSPLIT in the flags of the word it
- passes to expand_word_internal if $IFS is NULL
- - expand_word_leave_quoted now sets expand_no_split_dollar_star and
- the W_NOSPLIT bit in the word flags before calling
- expand_word_internal if $IFS is NULL, just like expand_word_unsplit.
- It is now virtually identical to expand_word_unsplit. Rest of fix for
- problems reported by Stephane Chazleas <stephane_chazelas@yahoo.fr>
-
- 3/20
- ----
-trap.c
- - in _run_trap_internal, don't pass SEVAL_RESETLINE as flag to
- parse_and_execute if running the ERR trap (further modification
- of change from 1/12)
-
-execute_cmd.c
- - in execute_simple_command, set line_number to line_number_for_err_trap
- before calling run_error_trap. Part of fix for bug reported by
- Brian J. Murrell <brian@interlinx.bc.ca>
- - change other places calling run_error_trap() to set and use
- line_number_for_err_trap
-
- 3/21
- ----
-builtins/fc.def
- - Even though command substitution through parse_and_execute turns
- off remember_on_history, command substitution in a shell when
- set -o history has been enabled (interactive or not) should use it
- in the last_hist calculation as if it were on. Same calculation
- in fc_gethnum and fc_builtin. Fixes bug reported by
- Ian Kelling <smallnow@gmail.com>
-
-sig.c
- - change termsig_sighandler to terminate immediately if it gets called
- twice with the same signal before termsig_handler gets called. This
- fixes the `looping on SIGSEGV' phenomenon reported by Linux users.
-
-parse.y
- - in read_secondary_line, don't try to add NULL lines to the history
- list. Report and patch from Lubomir Rintel <lkundrak@v3.sk>
-
- 3/22
- ----
-sig.c
- - Augment change from 3/21 with explicit check for signals we *don't*
- want this to happen for. Patch from Lubomir Rintel <lkundrak@v3.sk>
-
- 3/28
- ----
-array.c
- - in array_reference, return NULL immediately if the desired index
- is larger than the maximum
- - add cache of last array referenced and last array element referenced;
- use in array_reference to optimize case of sequential access;
- invalidated where necessary in other functions
- - array_rshift needs to set max_index to 0 if the array was empty
- before shifting in the new element 0
- - array_shift needs to use element_index(a->head->prev) to set the
- max_index, not a simple decrement, to deal with sparse arrays
-
- 4/1
- ---
-bashline.c
- - in bash_dequote_filename, return right away after copying the
- backslash if the last character in the string to be expanded
- is a backslash. The old code copied an extra NUL and overwrote
- the bounds checking. Fixes bug reported by Shawn Starr
- https://bugzilla.redhat.com/show_bug.cgi?id=488649
-
- 4/3
- ---
-subst.c
- - in pat_subst.c, make sure to copy one character from the input
- string in the case of a null pattern match, since we substitute
- on the null match and then increment past the current character.
- Not doing this means that each character of the original string
- is replaced because of the null matches. Fixes debian bug
- reported bhy Louis-David Mitterrand <ldm@apartia.fr>
- http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=522160
-
-lib/sh/winsize.c
- - incorporate contents of readline/rlwinsize.h to get all the various
- system dependencies right when trying to find TIOCGWINSZ. Fixes
- bug reported by Dan Price <dp@eng.sun.com>
-
- 4/6
- ---
-doc/{bash.1,bashref.texi}
- - fix description of conditional `>' and `<' to remove statement that
- the comparison pays attention to the current locale -- it has
- always used strcmp
-
-lib/glob/glob.c
- - fixed a bug in glob_filename that caused glob_dir_to_array to be
- called to prepend a (globbed) directory name onto the results from
- glob_vector, which, if we were globbing `**', glob_vector has
- already done. Effect is to have the directory name(s) on there
- twice. Fixes "dir*/**" bug reported by Matt Zyzik
- <Matt@ice.filescope.com>
-
- 4/8
- ---
-doc/{bash.1,bashref.texi}
- - fix short syntax summary of for command to reflect full bash
- syntax (which is a superset of Posix syntax). Fixes bug reported
- by Reuben Thomas <rrt@sc3d.org>
-
- 4/10
- ----
-{expr,subst}.c
- - make sure last_command_exit_value is set to EXECUTION_FAILURE
- before calling err_unboundvar, in case set -e is enabled and
- the shell exits from there. Fixes bug reported by Freddy
- Vulto <fvulto@gmail.com> and Piotr Zielinski
- <piotr.zielinski@gmail.com>
-
- 4/11
- ----
-jobs.c
- - in restore_pipeline, don't call discard_pipeline with a NULL
- argument
-
-trap.c
- - in run_debug_trap, make sure to save and restore the pipeline,
- pipeline_pgrp, and state of the pipeline around running the debug
- trap, then remove any job created by running the debug trap from
- the jobs table when it completes. Fixes for two bugs reported
- by lex@upc.ua
-
- 4/12
- ----
-lib/readline/signals.c
- - new functions to block and release SIGWINCH like the SIGINT blocking
- and releasing functions
-
-lib/readline/rlprivate.h
- - new extern declarations for _rl_block_sigwinch and _rl_release_sigwinch
-
-lib/readline/display.c
- - block SIGWINCH during redisplay like SIGINT. Should fix bug reported
- by Nicolai Lissner <nlissne@linux01.org>
-
- 4/13
- ----
-lib/readline/readline.h
- - new readline state variable: RL_STATE_REDISPLAYING
-
-lib/readline/display.c
- - in rl_redisplay, don't block SIGWINCH during redisplay; just set
- the REDISPLAYING state
-
-lib/readline/terminal.c
- - in rl_resize_terminal, don't call rl_redisplay_after_sigwinch() if
- we're already in the middle of redisplay (RL_STATE_REDISPLAYING).
- Fix for bug reported by Nicolai Lissner <nlissne@linux01.org>
-
- 4/15
- ----
-parse.y
- - fix parse_comsub to add check for \n when seeing whether the current
- character can change to a state where a reserved word is legal,
- since it is not a shell meta character. Fixes bug reported by
- Bernd Eggink <monoped@sudrala.de>.
-
- 4/17
- ----
-jobs.c
- - new functions to save and restore the pgrp_pipe (since there's only
- one): save_pgrp_pipe and restore_pgrp_pipe
-
-trap.c
- - run_debug_trap now saves and restores the pgrp_pipe before and
- after calling the debug trap
- - run_debug_trap now makes sure the terminal is owned by the pipeline
- pgrp after the debug trap runs. Rest of fix for bug reported by
- Oleksly Melnyk <o.melnyk@upc.ua> (lex@upc.ca)
-
- 4/19
- ----
-include/posixselect.h
- - new include file, encapsulates select(2) includes and defines for
- bash and readline. Inspired by patch from Mike Frysinger
- <vapier@gentoo.org>
-
-lib/sh/input_avail.c
- - include "posixselect.h"
-
-lib/readline/{input,parens}.c
- - include "posixselect.h" instead of using inline includes
- - use new USEC_TO_TIMEVAL define to make sure that values for timeouts
- greater than one second are handled properly
-
-lib/sh/fpurge.c
- - updated implementation, taken from gnulib
-
- 4/21
- ----
-lib/glob/glob.c
- - in finddirs, don't try to free a return value of glob_error_return
- from glob_vector. Bug and fix from werner@suse.de
-
-lib/readline/signals.c
- - in rl_echo_signal_char, check that SIGQUIT and SIGTSTP are defined
- before trying to use them. Bug report and fix from Volker Grabsch
- <vog@notjusthosting.com>
-
- 4/24
- ----
-aclocal.m4
- - add conditional inclusion of <stdint.h> to BASH_CHECK_TYPE
-
-bashtypes.h,lib/sh/strto[iu]max.c
- - include <stdint.h> if present for any existing declaration of
- intmax_t and uintmax_t. Fixes Interix problem reported by
- Markus Duft <mduft@gentoo.org>
-
-lib/sh/strindex.c,externs.h,builtins/common.h
- - renamed strindex to strcasestr to agree with other implementations
- (e.g., BSD, MacOS X, gnulib); changed callers
-
-lib/sh/{strindex.c,Makefile.in},Makefile.in
- - renamed strindex.c to strcasestr.c
-
-configure.in
- - add strcasestr to call to AC_REPLACE_FUNCS, take advantage of
- existing libc implementations
-
-config.h.in
- - add define for HAVE_STRCASESTR
-
-lib/sh/mbscmp.c
- - fix mbscmp to return correct values when the strings do not contain
- valid multibyte characters. Ideas from gnulib
-
-xstrchr.c
- - only compare current character against C if mblength == 1
-
-{shell,variables}.c
- - changed some xstrchr calls back to strchr when the arguments cannot
- contain multibyte characters
-
-lib/sh/{xstrchr.c,Makefile.in},Makefile.in
- - renamed xstrchr to mbschr; renamed file to mbschr.c
-
-aclocal.m4
- - change BASH_CHECK_MULTIBYTE to use AC_REPLACE_FUNCS(mbschr)
-
-externs.h
- - extern declarations for mbscmp and mbschr, conditional on the usual
- HAVE_MBSCMP and HAVE_MBSCHR defines
-
-general.h,{alias,arrayfunc,bashline,general,execute_cmd,subst}.c
- - changed calls to xstrchr to mbschr
-
-doc/bash.1
- - use `pathname expansion' consistently, not `filename expansion' or
- `filename generation'
-
-doc/bashref.texi
- - use the phrase `filename expansion' consistently (since this is
- what the Gnu people prefer) instead of `pathname expansion' or
- `filename generation'
-
-aclocal.m4,config.h.in
- - check for mbscasecmp in BASH_CHECK_MULTIBYTE, define HAVE_MBSCASECMP
- if found
-
-lib/sh/{mbscasecmp.c,Makefile.in}
- - new file, case-insensitive multibyte string comparison
-
-externs.h
- - extern declaration for mbscasecmp
-
- 4/25
- ----
-lib/readline/display.c
- - in _rl_move_cursor_relative, don't adjust dpos by woff if it's
- already less than woff (don't want it less than 0)
- - in _rl_move_cursor_relative, short-circuit right away if the cursor
- is at columns 0 and `new' is 0 (doesn't matter if it's a multibyte
- locale or not, or whether there are invisible chars in the prompt)
- - in _rl_move_cursor_relative, go ahead and adjust dpos if
- prompt_physical_chars >= _rl_screenwidth (previous check was just > )
- Fixes bug reported by Andreas Schwab <schwab@linux-m68k.org>
-
- 4/28
- ----
-lib/glob/glob.c
- - in glob_vector, don't add an empty pathname ("") if we're adding the
- currect directory to the dirlist and GX_NULLDIR is set -- we can just
- ignore it, since the passed directory name (".") was created by
- the caller. Fixes bug reported by Matt Zyzik <matt.zyzik@nyu.edu>
-
- 5/5
- ---
-subst.c
- - make expansion of $@ and $* when set -u is in effect and there are
- no positional parameters be a non-fatal error. This is the
- consensus of the austin group, though it is not historical practice.
- Message from Geoff Clare <20090505091501.GA10097@squonk.masqnet> of
- 5 May 2009 and http://austingroupbugs.net/view.php?id=155
-
-
- 5/20
- ----
-lib/glob/glob.c
- - tentative fix to glob_filename to compensate for glob_vector putting
- null pathname at front of result vector when dflags&GX_NULLDIR.
- Current fix manually removes empty string element from front of
- result vector; a better fix would be to use a flag so glob_vector
- doesn't add it at all. Augments patch from 4/28, which appears to
- have broken some things. Fixes bug reported by Matt Zyzik
- <matt.zyzik@nyu.edu>
-
- 5/22
- ----
-
-lib/glob/glob.c
- - better fix for glob_filename; supersedes patch of 5/20. Now the
- code does not set GX_ADDCURDIR if directory_len == 0 and the
- function has not been called recursively ((flags & GX_ALLDIRS) == 0).
- Better fix for bug reported by Matt Zyzik <matt.zyzik@nyu.edu>
-
-Makefile.in
- - fix build race condition that occurs in some makes caused by
- libreadline.a and libhistory.a containing some of the same files
- (e.g., xmalloc.o) and conflicting when trying to build both at
- the same time. Reported by Mike Frysinger <vapier@gentoo.org>
-
- 5/25
- ----
-lib/readline/vi_mode.c
- - fix _rl_vi_initialize_line so that the loop counter is not
- unsigned (it doesn't matter, but it eliminates a compiler warning).
- Bug reported by Dave Caroline <dave.thearchivist@gmail.com>
-
- 5/26
- ----
-doc/{bash.1,bashref.texi}
- - add text to the description of array variables making it clear
- that an array variable is not considered set until a subscript
- has been assigned a value
-
- 5/29
- ----
-lib/readline/text.c
- - fix rl_change_case to handle case where mbrtowc doesn't find a
- valid multibyte character
-
-lib/readline/vi_mode.c
- - fix _rl_vi_change_mbchar_case to handle case where mbrtowc doesn't
- find a valid multibyte character
-
-lib/sh/casemod.c
- - fix sh_modcase to handle case where mbrtowc doesn't find a valid
- multibyte character
-
-lib/readline/mbutil.c
- - fix _rl_find_next_mbchar_internal to not call mbrtowc at the end of
- the string, since implementations return different values -- just
- break the loop immediately
-
-lib/readline/display.c
- - fix rl_redisplay to make same sort of cursor position adjustments
- based on multibyte locale and _rl_last_c_pos when performing
- horizontal scrolling rather than line wrapping. Probably still
- more to do. Fixes bug reported by jim@jim.sh
-
- 6/5
- ---
-doc/{bash.1,bashref.texi}
- - added some more explanation of the inheritance of the ERR trap at
- the suggestion of Thomas Pospisek <tpo@sourcepole.ch>
-
-findcmd.c
- - use eaccess(2) if available in file_status to take other file
- access mechanisms such as ACLs into account. Patch supplied
- by werner@suse.de
-
- 6/12
- ----
-xmalloc.c
- - also calculate lowest brk() value the first time xmalloc/xrealloc
- (and their sh_ counterparts) are called
- - error messages consolidated into a single function (allocerr/
- sh_allocerr) to avoid string duplication
-
- 6/16
- ----
-variables.c
- - changes to allow variables.c to be compiled if ALIAS is not defined.
- Bug and fix from John Gatewood Ham <uraphalinuxserver@gmail.com>
-
-lib/sh/getcwd.c
- - fix so systems defining BROKEN_DIRENT_D_INO have the necessary
- defines. Fix from Jay Krell <jay.krell@cornell.edu>
-
-configure.in
- - add -D_ALL_SOURCE to interix CFLAGS for struct timezone definition.
- Bug and fix from John Gatewood Ham <uraphalinuxserver@gmail.com>
-
- 6/29
- ----
-variables.c
- - change initialize_shell_variables to add environment variables with
- invalid names to the variables hash table, but marking them as
- invisible and imported
- - new function, export_environment_candidate. Used when creating the
- export environment for commands to include variables with invalid
- names inherited from the initial environment. Apparently this
- behavior is widespread
- - change make_var_export_array to use export_environment_candidate
- rather than visible_and_exported to test variables for inclusion
- in the export environment
-
- 7/1
- ---
-builtins/read.def
- - fix a memory leak where the number of fields is not the same as
- the number of variables passed to `read'. Bug report from
- werner@suse.de
-
-builtins/command.def
- - move section of code that sets PATH from -p option before the
- verbose-handling section, so command -v and command -V honor
- the PATH set by command -p. Bug report and fix from
- ohki@gssm.otsuka.tsukuba.ac.jp
-
- 7/9
- ---
-subst.c
- - change brace_expand_word_list to defer brace expansion on compound
- array assignments that are arguments to builtins like `declare',
- deferring the expansion until the assignment statement is processed.
- Fixes inconsistency reported by agriffis@n01se.net
-
- 7/16
- ----
-bashline.c
- - fix bash_execute_unix_command to set rl_point correctly based on
- READLINE_POINT. The old method of using save_point will not
- work because maybe_make_readline_line will change rl_point. Bug
- reported by Henning Bekel <h.bekel@googlemail.com>
-
-trap.c
- - fix _run_trap_internal and run_pending_traps to save and restore
- value of subst_assign_varlist so the dispose_words on it doesn't
- leave dangling pointers after the trap handler runs. Fixes bug
- reported by Marc Herbert <marc.herbert@gmail.com>
-
- 7/22
- ----
-subst.c
- - fix off-by-one error in pos_params when computing positional
- parameters beginning with index 0. Bug and fix from Isaac Good
- <isaacgood@gmail.com>
-
- 7/24
- ----
-lib/readline/display.c
- - add code to _rl_move_cursor_relative and _rl_col_width to short-
- circuit a few special cases: prompt string and prompt string plus
- line contents, both starting from 0. Saves a bunch of calls to
- multibyte character functions using already-computed information.
- As a side effect, fixes bug reported by Lasse Karkkainen
- <tronic+8qug@trn.iki.fi>
-
-subst.c
- - fixed a problem in split_at_delims that could leave *cwp set to -1
- if the line ends in IFS whitespace and SENTINEL is one of those
- whitespace characters. Fixes problem with setting COMP_CWORD for
- programmable completion reported by Ville Skytta <ville.skytta@iki.fi>
-
-bashline.c
- - change bash_execute_unix_command to clear the current line (if the
- terminal supplies the "ce" attribute) instead of moving to a new
- line. Inspired by report from Henning Bekel <h.bekel@googlemail.com>
-
-builtins/printf.def
- - changes to allow printf -v var to assign to array indices, the way
- the read builtin can. Suggested by Christopher F. A. Johnson
- <cfajohnson@gmail.com>
-
-lib/readline/complete.c
- - fix rl_old_menu_complete and rl_menu_complete to appropriately set
- and unset RL_STATE_COMPLETING while generating the list of matches.
- Fixes debian bug #538013 reported by Jerome Reybert
- <jreybert@gmail.com>
-
- 7/25
- ----
-execute_cmd.c
- - change execute_builtin to temporarily turn off and restore the ERR
- trap for the eval/source/command builtins in the same way as we
- temporarily disable and restore the setting of the -e option.
- Fixes bug reported by Henning Garus <henning.garus@googlemail.com>
-
- 7/27
- ----
-shell.c
- - add fflush(stdout) and fflush(stderr) to exit_shell before closing
- any file descriptors at exit time (e.g., coproc pipes)
-
- 7/30
- ----
-lib/readline/complete.c
- - new function rl_backward_menu_complete, just passes negative count
- argument to rl_menu_complete
- - change rl_menu_complete to act appropriately if rl_last_command is
- rl_backward_menu_complete, so we can cycle forward and backward
- through the list of completions
-
-lib/readline/doc/{readline.3,rluser.texi},doc/bash.1
- - document new "menu-complete-backward" bindable readline function.
- Suggested by Jason Spiro <jasonspiro04@gmail.com>
-
-lib/readline/vi_keymap.c
- - add binding of C-n to menu-complete and C-p to menu-complete-backward
- in vi-insert keymap, as suggested by Jason Spiro
- <jasonspiro04@gmail.com>
-
-pcomplete.c
- - fixed a bug in programmable_completions: the options it returned from
- the compspec it found were set before generating the completions,
- which meant that any changes made by "compopt" were overridden and
- only in effect for the duration of the executing shell function
- rather than the entire completion. Fixes bug reported by Ville
- Skytta <ville.skytta@iki.fi>
-
- 7/31
- ----
-lib/readline/keymaps.c
- - fixed memory leak in rl_discard_keymap by freeing storage associated
- with hierarchical keymaps
- - new convenience function, rl_free_keymap, that calls rl_discard_keymap
- and frees the keymap passed as an argument
-
-lib/readline/util.c
- - new bindable keymap function, _rl_null_function, to be used internally
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_null_function
-
-lib/readline/bind.c
- - fix rl_generic_bind in the case where we are trying to override a
- keymap with a null function (e.g., when trying to unbind it). We
- can't use a NULL function pointer in ANYOTHERKEY since that's
- indistinguishable from the keymap not having been overridden at all.
- We use _rl_null_function instead, which simply does nothing. We
- could add an rl_ding to it later. Fixes problem with hitting ESC
- repeatedly while in vi command mode reported by James Rowell
- <jrjimmy801-misc1@yahoo.com>
-
-builtins/bind.def
- - call rl_bind_keyseq instead of rl_set_key for -r option
-
-lib/readline/readline.c
- - Set vi_movement_keymap[ESC] to _rl_null_function after binding the
- arrow keys in bind_arrow_keys() to allow vi-mode users to hit ESC
- multiple times in vi command mode while still allowing the arrow
- keys to work
-
- 8/2
- ---
-bashline.c
- - fix clear_hostname_list by setting hostname_list_initialized to 0
- after freeing all list members. Fixes bug reported by Freddy
- Vulto <fvulto@gmail.com>
-
-lib/readline/display.c
- - in update_line, if we copy data from one line to another because we
- are wrapping a multibyte character from, say, the first line to the
- second, we need to update OMAX and the line indices to account for
- the moved data. Bug report and fix from Martin Hamrle
- <martin.hamrle@gmail.com>
-
- 8/3
- ---
-pcomplete.h
- - defines for EMPTYCMD ("_EmptycmD_") and DEFAULTCMD ("_DefaultCmD_")
-
-builtins/complete.def
- - change compopt_builtin to make -E work on the "empty" command
- completion
- - fix print_compitem and print_compopts to replace EMPTYCMD with -E
- - added -D (default) option to complete/compgen/compopt. No supporting
- code yet
-
-doc/bash.1,lib/readline/doc/rluser.texi
- - document new -D, -E options to compopt
- - document new -D option to complete/compgen
-
-shell.h
- - new define, EX_WEXPCOMSUB, value of 125
- - new define, EX_RETRYFAIL, value of 124 (for programmable completion)
-
-subst.c
- - use EX_WEXPCOMSUB instead of literal 125 as exit status when a shell
- invoked to run wordexp(3) with the -n option supplied attempts a
- command substitution
-
-pcomplete.c
- - new define, PCOMP_RETRYFAIL, used to indicate a "failure, retry with
- next completion" status to the programmable completion code
-
- 8/4
- ---
-pcomplete.c
- - changed gen_shell_function_matches to take an extra parameter
- indicating whether the specified shell function was not found or
- returned the special "fail/retry" status, and, if it was either,
- to not bother returning any matches list
- - changed gen_compspec_completions to take an extra parameter to pass
- through the "found" status from gen_shell_function_completions
- - new function gen_progcomp_completions to take care of searching for
- and evaluating a compspec for a particular word, saving its status,
- and returning to its caller (programmable_completions) whether or
- not to retry completion. This function also checks whether a
- retry changed the compspec associated with a command and short-
- circuits the retry if it has not
- - changed programmable_completions to try default completion (if set)
- if a specific completion was not found for a command
- - changed programmable_completions to implement "fail/retry" semantics
- for a shell function that returns 124 and changes the compspec
- associated with the command. All based on proposal and changes from
- Behdad Esfahbod (Red Hat bugzilla 475229)
-
-doc/bash.1,lib/readline/doc/rluser.texi
- - documented new dynamic programmable completion functionality
-
- 8/5
- ---
-stringlib.c
- - first argument to substring() is now `const char *'
-
-externs.h
- - changed extern declaration for substring()
-
-subst.c
- - skipsubscript now takes a third FLAGS argument, passes to
- skip_matched_pair
- - skip_matched_pair now interprets flags&1 to mean not to parse
- matched pairs of quotes, backquotes, or shell word expansion
- constructs
-
-{subst,general,expr}.c
- - changed skipsubscript() callers
-
-assoc.c
- - changed assoc_to_assign to double-quote the key if it contains any
- shell metacharacters
-
-arrayfunc.c
- - use skipsubscript in quote_assign rather than quote any glob
- characters in the subscript of an array assignment
- - in assign_compound_array_list, call skipsubscript with a flags
- argument of 1 if assigning an associative array to avoid trying
- to re-parse quoted strings
-
-redir.c
- - set expanding_redir before expanding body of here documents and
- here strings to avoid looking for variables in temporary env
-
- 8/7
- ---
-lib/readline/readline.c
- - in _rl_dispatch_callback, return value of -3 means that we have
- added to a key sequence, but there are previous matches in the
- sequence. Don't call _rl_subseq_result if we get a -3 from a
- previous context in the chain; just go back up the chain. Report
- and fix from <freehaha@gmail.com>
-
-bashline.c
- - fixes to history_completion_generator and bash_dabbrev_expand to
- make dabbrev-expand inhibit suppressing of appending space char
- to matches. Have to do it with the generator too because
- rl_menu_complete turns off suppressing the appended space in
- set_completion_defaults(). Suggestion from Dan Nicolaescu
- <dann@ics.uci.edu>
- - suppress completion match sorting in bash_dabbrev_expand by
- setting rl_sort_completion_matches = 0. Suggestion from Dan
- Nicolaescu <dann@ics.uci.edu>
- - don't qsort history match list in build_history_completion_array
- if dabbrev_expand_active == 1
- - start the loop in build_history_completion_array that gathers words
- from history for possible completions from the end of the list
- rather than the beginning. It doesn't matter where you start if
- the results are sorted, and dabbrev-expand is supposed to offer
- the most recent completions first
-
- 8/12
- ----
-execute_cmd.c
- - change to execute_command_internal to make [[ ... ]] conditional
- command subject to settings of `set -e' and the ERR trap
-
- 8/14
- ----
-execute_cmd.c
- - change to execute_command_internal to make (( ... )) arithmetic
- command subject to settings of `set -e' and the ERR trap
-
-lib/readline/text.c
- - new bindable function, rl_skip_csi_sequence, reads the characters
- that make up a control sequence as defined by ECMA-48. Sequences
- are introduced by the Control Sequence Indicator (CSI) and
- contain a defined set of characters. Insert, End, Page Up and so
- on are CSI sequences. Report and code from Andy Koppe
- <andy.koppe@gmail.com>
-
-lib/readline/readline.h
- - extern declaration for rl_skip_csi_sequence
-
-lib/readline/funmap.c
- - new bindable command "skip-csi-sequence", runs rl_skip_csi_sequence
-
-doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
- - documented new bindable command "skip-csi-sequence", unbound by
- default
-
-builtins/evalfile.c
- - fix _evalfile to remove embedded null bytes from the file read
- into the string. Report and proposed fix from Roman Rakus
- <rrakus@redhat.com>
-
-{configure,config.h}.in
- - check for syslog(3), define HAVE_SYSLOG
- - check for syslog.h, define HAVE_SYSLOG_H
-
-config-top.h
- - new define SYSLOG_HISTORY, disabled by default
-
-config-bot.h
- - if HAVE_SYSLOG or HAVE_SYSLOG_H are not defined, undef SYSLOG_HISTORY
-
-bashhist.c
- - if SYSLOG_HISTORY is defined, call bash_syslog_history with the
- line added to the history in bash_add_history.
- - new function, bash_syslog_history(line), sends line to syslog at
- user.info. The line is truncated to send no more than 600
- (SYSLOG_MAXLEN) bytes to syslog. Feature requested by many, and
- required by some national laws
-
-sig.c
- - in termsig_handler, resend SIGHUP to children if subshell_environment
- indicates we're a shell performing command or process substitution
-
-jobs.c
- - add CHECK_TERMSIG calls to wait_for in addition to the ones in
- waitchld()
-
-builtins/shopt.def
- - new functions set_bashopts, parse_bashopts, and initialize_bashopts
- to manage new environment variable $BASHOPTS, like $SHELLOPTS but
- for shopt options
- - change toggle_shopts to call set_bashopts after setting options, so
- $BASHOPTS reflects new values
-
-shell.c
- - call initialize_bashopts after calling initialize_shell_options at
- shell startup
-
-configure.in
- - new configure `enable' option --enable-exended-glob-default, to
- set the initial default value of the `extglob' shell option
-
-config.h
- - new define, EXTGLOB_DEFAULT, controlled by the `extended-glob-default'
- configure option
-
-pathexp.c
- - initialize extended_glob variable to EXTGLOB_DEFAULT
-
-doc/{bash.1,bashref.texi}
- - document new $BASHOPTS variable and its behavior
-
-doc/bashref.texi
- - document new --enable-extended-glob-default configure option
-
- 8/16
- ----
-print_cmd.c
- - new variables: xtrace_fd and xtrace_fp, the file descriptor and
- FILE * to which we send `set -x' tracing output. If fd == -1
- then fp == STDERR, the default mode
- - new function xtrace_init, sets xtrace_fd == -1 and xtrace_fp = stderr
- - new function xtrace_set (fd, fp), sets xtrace_fd and xtrace_fp
- to the arguments
- - new function xtrace_reset, handles closing old xtrace fd/fp and
- moving them back to -1/stderr
- - new function xtrace_fdchck, calls xtrace_reset if the fd passed as
- an argument is xtrace_fd
- - change xtrace functions to fprintf to xtrace_fp instead of stderr
-
-shell.c
- - call xtrace_init() very early in main()
-
-variables.c
- - new special variable, BASH_XTRACEFD, holds file descriptor used for
- set -x trace output. Inspired by suggestion from Bruce Korb
- <bruce.korb@gmail.com>
-
-doc/{bash.1,bashref.texi}
- - added description of new BASH_XTRACEFD variable
-
-redir.c
- - add calls to xtrace_fdchk to the redirections that close file
- descriptors, so we notice if we close BASH_XTRACEFD and compensate
- accordingly (same places that call coproc_fdchk())
-
- 8/18
- ----
-lib/readline/text.c
- - change to _rl_replace_text to add error checks: start must be <=
- end, and we don't call rl_insert_text if passed the empty string
-
-config.h.in
- - add define for HAVE_ICONV, already found by intl autoconf macros
- - add define for HAVE_LOCALE_CHARSET
-
-aclocal.m4
- - add check for locale_charset() to BASH_CHECK_MULTIBYTE
-
-lib/sh/fnxform.c
- - new file with two public function: fnx_tofs and fnx_fromfs.
- Primarily intended for use on MacOS X, they use iconv to convert
- between whatever the current locale encoding is and "UTF-8-MAC",
- a special encoding on OS X in which all characters are
- decomposed unicode, as the HFS+ filesystem stores them. These
- functions return a pointer to a local buffer, allocated once and
- resized as necessary, to avoid too many allocations; callers
- should not free the return value, since it may be the string
- passed
-
-Makefile.in
- - make sure LIBICONV is set by autoconf (@LIBICONV@) and added to
- list of link libraries
-
-externs.h
- - new extern declarations for fnx_fromfs and fnx_tofs
-
-lib/glob/glob.c
- - convert the filename read using readdir() in glob_vector() using
- fnx_fromfs and use that value in the call to strmatch. This
- ensures that we're using the precomposed Unicode value of the
- filename rather than the native decomposed form. Original bug
- report from Len Lattanzi <llatanzi@apple.com>; fix inspired by
- Guillaume Outters <guillaume.outters@free.fr>
-
- 8/19
- ----
-lib/readline/complete.c
- - new completion hook: rl_filename_rewrite_hook, can rewrite or modify
- filenames read from the filesystem before they are compared to the
- word to be completed
-
-lib/readline/readline.h
- - extern declaration for rl_filename_rewrite_hook
-
-lib/readline/doc/rltech.texi
- - document rl_filename_rewrite_hook
-
-bashline.c
- - new function, bash_filename_rewrite_hook, assigned to
- rl_filename_rewrite_hook. Calls fnx_fromfs to convert from
- filesystem format to "input" format. This makes completing
- filenames with accented characters work on Mac OS X
-
- 8/20
- ----
-lib/readline/bind.c
- - new bindable variable "skip-completed-text", bound to
- _rl_skip_completed_text. If enabled, it means to note when
- completing before the end of a word and skipping over characters
- after rl_point that match in both the completion to be inserted
- and the word being completed. It means that completing
- `Makefile' with the cursor after the `e' results in `Makefile'
- instead of `Makefilefile'. Inspired by an idea from Jared
- Yanovich <phierunner@comcast.net> from back in 2004
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_skip_completed_text
-
-lib/readline/complete.c
- - implement semantics of _rl_skip_completed_text in insert_match:
- skip characters in `replacement' that match chars in rl_line_buffer
- from the start of the word to be completed
-
- 8/21
- ----
-error.c
- - change parser_error to set last_command_exit_value to 2 before
- calling exit_shell (if set -e is enabled), so any exit or ERR
- trap gets the right value of $?. Suggestion from Stefano
- Lattarini <stefano.lattarini@gmail.com>
-
-braces.c
- - fix expand_seqterm so that a non-zero-prefixed term that's longer
- than a zero-prefixed term determines the length of each term
- in the brace-expanded sequence. This means that things like
- {01..100} will have three digits in all the elements of the
- expanded list. Fixes bug reported by Jeff Haemer
- <jeffrey.haemer@gmail.com>
-
- 8/24
- ----
-{arrayfunc,variables}.c
- - when inserting a value into an associative array using syntax like
- T=v where T is an already-declared associative array using key "0",
- make sure the key is in newly-allocated memory so it can be freed
- when the variable is unset. Fixes bug reported as redhat 518644
- by Jon Fairbairn
-
- 8/26
- ----
-lib/readline/funmap.c
- - add "old-menu-complete" binding for rl_old_menu_complete
-
-lib/readline/readline.h
- - add extern declaration for rl_old_menu_complete
-
-subst.c
- - fix memory leak when processing ${!prefix@}. Need to dispose all
- words in the word list created from all matching variable. Fixes
- bug reported by muszi@muszi.kite.hu.
-
- 8/29
- ----
-execute_cmd.c
- - add fflush(stdout) and fflush(stderr) to child coproc code before
- calling exit after execute_in_subshell
-
- 8/31
- ----
-lib/readline/{{bind,readline}.c,rlprivate.h}
- - new bindable variable, "echo-control-characters", enabled by default.
- This controls whether or not readline honors the tty ECHOCTL bit
- and displays characters corresponding to keyboard-generated signals.
- Controlled by _rl_echo_control_chars variable, declared in readline.c
-
-lib/readline/signals.c
- - if _rl_echo_control_chars == 0, don't go through _rl_echo_signal_char
-
-
-lib/readline/doc/{readline.3,rluser.texi}
- - document "echo-control-characters" bindable variable
-
- 9/1
- ---
-lib/readline/histexpand.c
- - hist_string_extract_single_quoted now takes an additional argument:
- a flags word. The only defined value (flags & 1) allows backslash
- to quote the single quote. This is to inhibit history expansion
- inside $'...' containing an escaped single quote.
- - change history_expand to call hist_string_extract_single_quoted
- with flags == 1 if it sees $'. Fixes bug reported by Sean
- Donner <sean.donner@gmail.com>
-
- 9/2
- ---
-builtins/printf.def
- - add a call to sh_wrerror if ferror() succeeds in the PRETURN macro,
- to print an error message in the case that the final fflush fails
- (for instance, because it attempts to write data that didn't have a
- trailing newline). Fixes bug reported by Stefano Lattarini
- <stefano.lattarini@gmail.com>
-
- 9/7
- ---
-arrayfunc.c
- - some fixes to assign_compound_array_list to avoid null pointer
- dereferences pointed out by clang/scan-build
-
-lib/glob/glob.c
- - fixes to udequote_pathname and wdequote_pathname to avoid possible
- null pointer dereferences pointed out by clang/scan-build
-
-lib/readline/undo.c
- - fix to _rl_copy_undo_list (function unused) to avoid deref of
- uninitialized pointer pointed out by clang/scan-build
-
-general.c
- - fix string_to_rlimtype so it works if passed a null pointer (though
- it never is)
-
-builtins/mapfile.def
- - fix to mapfile() to avoid possible null pointer dereference pointed
- out by clang/scan-build
-
-variables.c
- - fix to valid_exportstr to avoid possible null pointer dereferences
- pointed out by clang/scan-build
-
-bashline.c
- - fix to bash_execute_unix_command to avoid possible null pointer
- dereference if READLINE_LINE or READLINE_POINT is not bound
-
- 9/11
- ----
-[Prayers for the victimes of 9/11/2001]
-
-command.h
- - add `rflags' member to struct redirect to hold private flags and
- state information
- - change redirector to a REDIRECTEE instead of int to prepare for
- possible future changes
-
-{copy_cmd,dispose_cmd,make_cmd,print_cmd,redir}.c
- - changes resulting from type change of `redirector' member of struct
- redirect: change x->redirector to x->redirector.dest and add code
- where appropriate to deal with x->redirector.filename
-
-make_cmd.h
- - change extern declaration for make_redirection
-
-make_cmd.c
- - first argument of make_redirection is now a `REDIRECTEE' to prepare
- for possible future changes. First arg is now assigned directly to
- redirector member instead of assigning int to redirector.dest
-
-{make_cmd,redir}.c,parse.y
- - changes resulting from type change of first argument to
- make_redirection from int to REDIRECTEE. In general, changes are
- using REDIRECTEE sd and assigning old argument to sd.dest, then
- passing sd to make_redirection
-
-make_cmd.[ch],parse.y
- - add fourth argument to make_redirection: flags. Sets initial value
- of `rflags' member of struct redirect
- - changed all callers of make_redirection to add fourth argument of 0
-
- 9/15
- ----
-parse.y
- - change read_token_word to return REDIR_WORD for tokens of the form
- {var} where `var' is a valid shell identifier and the character
- following the } is a `<' or `>'
- - add REDIR_WORD versions of all input and output file redirections
- and here documents
-
-print_cmd.c
- - change input and output file redirection direction and here
- document cases of print_redirection to print a varname
- specification of the form {var} when appropriate. Still need
- to fix rest of cases
-
-redir.c
- - implement REDIR_VARASSIGN semantics for file input and output
- redirections and here documents
-
- 9/16
- ----
-parse.y
- - added REDIR_WORD versions of remaining redirection constructs except
- for err_and_out ones
-
-redir.c
- - handle REDIR_VARASSIGN semantics for rest of redirection constructs
- - accommodate REDIR_VARASSIGN when translating redirections
- - new function, redir_varvalue, does variable lookup for {v} when
- redirection needs the value (e.g., r_close_this)
-
-print_cmd.c
- - fix rest of cases to print {varname} when REDIR_VARASSIGN is set in
- redirect->rflags
-
-doc/{bash.1,bashref.texi}
- - document new {varname} REDIR_VARASSIGN form of redirections
-
-tests/vredir.{right,tests},vredir[1-5].sub
- - tests for new {varname} REDIR_VARASSIGN form of redirections
-
- 9/18
- ----
-subst.c
- - new flags argument to split_at_delims: these flags are ORd with
- SD_NOJMP and passed to skip_to_delim
- - change skip_to_delim to honor new SD_NOQUOTEDELIM flag by not
- checking whether or not single and double quotes are delimiters
- if it's set in passed flags until after skipping quoted strings.
-
-subst.h
- - change extern declaration for split_at_delims
- - new define for SD_NOQUOTEDELIM flag
-
-pcomplete.c
- - pass SD_NOQUOTEDELIM in flags argument to split_at_delims so single
- and double quotes, even though they're in
- rl_completer_word_break_characters, don't act as word delimiters
- for programmable completion. Fixes bug reported by Freddy
- Vulto <fvulto@gmail.com>
-
-lib/glob/glob.c
- - in glob_filename, after recursively scanning a directory specified
- with `**', turn off GX_ALLDIRS|GX_ADDCURDIR before calling
- glob_vector on the rest of the pathname, since it may not apply to
- the rest of the pattern. Turned back on if the filename makes it
- appropriate. Fixes bug reported by Anders Kaseorg <andersk@mit.edu>
-
-redir.c
- - change execute_null_command to fork a child to execute if any of
- the commands redirections have the REDIR_VARASSIGN flag set, since
- those commands are not supposed to have side effects
-
-test.c
- - < and > binary operators will obey the locale by using strcoll if
- the TEST_LOCALE flag is passed to binary_test
-
-test.h
- - new define for TEST_LOCALE
-
-execute_cmd.c
- - execute_cond_node sets TEST_LOCALE so [[ str1 < str2 ]] (and >)
- obey the locale. Fixes bug/incompatibility reported by Greg
- Wooledge <wooledg@eeg.ccf.org>
-
-doc/{bash.1,bashref.texi}
- - documented [[ command new locale-sensitive treatment of < and >
-
- 9/24
- ----
-configure.in
- - add "darwin10" cases like darwin8 and darwin9 to handle linking with
- included readline and history libraries
-
- 9/26
- ----
-lib/readline/display.c
- - modify change of 7/24 to use prompt_physical_chars instead of
- prompt_visible_length to account for visible multibyte characters in
- the line (usually in the prompt). Fixes debian bug #547264
- reported by Pietro Battiston <toobaz@email.it>
- - add flags argument to _rl_col_width; changed callers. flags > 0
- means that it's ok to use the already-computed prompt information;
- flags == 0 means that we're expanding the prompt and we should not
- short-circuit
-
-parse.y
- - in decode_prompt_string, when expanding \w and \W on Mac OS X,
- use fnx_fromfs to convert from "filesystem" form to "input" form.
- This makes $PWD with multibyte characters work in the prompt
- string on Mac OS X
-
-lib/sh/fnxform.c
- - in fnx_fromfs and fnx_tofs, use templen instead of outlen as last
- argument in calls to iconv, since outlen is used to keep track of
- the size of the buffer, and iconv potentially modifies its
- `outbytesleft' argument
-
- 9/29
- ----
-subst.c
- - make skip_to_delim understand how to skip over process substitution
- constructs the way it skips $(...) command substitution
-
- 9/30
- ----
-lib/readline/terminal.c
- - don't set the `terminal has meta key' flag if the `MT' capability is
- available; that means something completely different
-
- 10/1
- ----
-builtins/help.def
- - make sure width is at least 7, since we pass `width/2 - 3' to strncpy
- as the length argument. Terminal widths <= 6 are converted to 80.
- Fixes bug reported by Chris Hall <c@pobox.co.uk>
-
-configure.in
- - changed version to 4.1-alpha
-
-subst.h
- - new flag for skip_to_delim: SD_NOSKIPCMD, which means to not skip
- over embedded command and process substitutions, but rather to look
- for delimiters within them
-
-subst.c
- - implement semantics of SD_NOSKIPCMD in skip_to_delim
-
-bashline.c
- - call skip_to_delim with SD_NOSKIPCMD from find_cmd_start, so
- programmable completion can use the completion defined for `b' for
- command lines like "a $(b c". Fixes inconsistency/bug reported by
- Freddy Vulto <fvulto@gmail.com>
-
-parser.h
- - replace unused PST_CMDTOKEN parser state value with PST_EXTPAT,
- means currently parsing an extended glob pattern (extglob)
-
-parse.y
- - fix cond_node() so that extended_glob is set before parsing the
- rhs of the `==' or `!=' operators. For ksh93 compatibility.
- - reset extended_glob to global value (saved in parse_cond_command())
- in reset_parser()
-
- 10/5
- ----
-jobs.c
- - change waitchld() to only interrupt the wait builtin when the shell
- receives SIGCHLD in Posix mode. It's a posix requirement, but
- makes easy things hard to do, like run a SIGCHLD trap for every
- exiting child. Change prompted by question from Alex Efros
- <powerman@powerman.name>
-
-doc/bashref.texi
- - document new posix mode behavior about SIGCHLD arriving while the
- wait builtin is executing when a trap on SIGCHLD has been set
-
- 10/6
- ----
-lib/readline/histexpand.c
- - fix hist_expand to keep from stopping history expansion after the
- first multibyte character (a `break' instead of a `continue').
- Fixes debian bug (#549933) reported by Nikolaus Schulz
- <microschulz@web.de>
-
- 10/8
- ----
-builtins/read.def
- - implement new `-N nchars' option: read exactly NCHARS characters,
- ignoring any delimiter, and don't split the result on $IFS.
- Feature requested by Richard Stallman <rms@gnu.org>
-
-doc/{bash.1,bashref.texi}
- - document new `read -N' option
-
- 10/9
- ----
-lib/readline/bind.c
- - new bindable variable, "enable-meta-key", controls whether or not
- readline enables any meta modifier key the terminal claims to
- support. Suggested by Werner Fink <werner@suse.de>
-
-lib/readline/doc/{readline.3,rluser.texi},doc/bash.1
- - document new readline "enable-meta-key" bindable variable
-
- 10/10
- -----
-trap.c
- - new function, free_trap_string(), does what it says and turns off
- SIG_TRAPPED flag without changing signal disposition
-
-[bash-4.1-alpha frozen]
-
- 10/16
- -----
-builtins/mapfile.def
- - return an error if the variable passed is not an indexed array.
- Fixes bug reported by Nick Hobson <nick.hobson@yahoo.com>
- - change help text to make it clear that an indexed array is required
-
-doc/{bash.1,bashref.texi}
- - changed description of mapfile to note that the array variable
- argument must be an indexed array, and mapfile will return an
- error if it is not
-
-subst.c
- - change expand_string_unsplit and expand_string_leave_quoted to
- add the (previously unused) W_NOSPLIT2 flag to the created word
- - change expand_word_internal to understand W_NOSPLIT2 to mean that
- we're not going to split on $IFS, so we should not quote any
- characters in IFS that we add to the result string. Fixes bug
- reported by Enrique Perez-Terron <enrio@online.no>
- - change cond_expand_word similarly. Fixes rest of bug reported by
- Enrique Perez-Terron <enrio@online.no>
-
-parse.y
- - save and restore value of last_command_subst_pid around call to
- expand_prompt_string in decode_prompt_string. Fixes bug that causes
- $? to be set wrong when using a construct like false || A=3 when
- set -x is enabled and $PS4 contains a command substitution. Reported
- by Jeff Haemer <jeffrey.haemer@gmail.com>
-
- 10/17
- -----
-execute_cmd.c
- - in execute_in_subshell, make sure we set setjmp(return_catch) before
- running the command, in case the command or its word expansion
- calls jump_to_top_level. Fixes bug reported by Nils Bernhard
- <nils.bernhard@yahoo.de>
-
-subst.c
- - new PF_NOSPLIT2 flag for param_expand
- - parameter_brace_expand takes a new `pflags' argument, before the
- `output' parameters; passes to param_expand as necessary
- - change parameter_brace_expand to call parameter_brace_expand_word
- with the PF_NOSPLIT2 flag if the pflags argument to
- parameter_brace_expand has it set
-
-parse.y
- - change report_syntax_error to set last_command_exit_value to
- EX_BADSYNTAX if parse_and_execute_level is > 0, indicating a
- syntax error while we're executing a dot script, eval string,
- trap command, etc.
-
-builtins/evalstring.c
- - in parse_and_execute, if parse_command() returns non-zero,
- indicating a parse error, print a warning message if the conditions
- would require a posix-mode shell to abort (parse error in a `.'
- script or eval string)
-
- 10/19
- -----
-builtins/evalfile.c
- - even if the `check binary' flag is not passed to _evalfile, return an
- error after reading 128 null characters if called by `source', on
- the assumption that it's probably a binary file. [This will be in
- bash-4.1-beta]
-
- 10/24
- -----
-[bash-4.1-alpha released]
-
-bashline.c
- - don't call command_substitution_completion_function if we're
- completing a substring delimited by a single quote. Fixes bug
- reported by bash-bugs@atu.cjb.net
-
-lib/readline/complete.c
- - make sure _rl_skip_completed_text defaults to 0, as the
- documentation states (incorrect in bash-4.1-alpha)
- - in insert_match, skip over a close quote in the replacement text if
- the character at point when completion is invoked is a single
- quote. Fixes complaint from bash-bugs@atu.cjb.net
-
- 10/26
- -----
-shell.c
- - in main, make sure "$EMACS" is non-null before calling strstr on its
- value. Fixes Red Hat bug 530911 submitted by Mitchell Berger
-
-builtins/mapfile.def
- - don't save callback commands in shell history. Suggested by
- Jan Schampera <jan.schampera@web.de>
-
-mailcheck.c
- - in file_mod_date_changed, make sure the modification time is later
- than the saved modification date, not just that it's not equal.
- Fix from Evgeniy Dushistov <dushistov@mail.ru>
- - in file_access_date_changed, make sure the access time is later
- than the saved access time, not just that it's not equal
-
- 10/27
- -----
-builtins/shopt.def
- - added new `compat40' compatibility variable, with associated changes
- to shell_compatibility_level(), since the default compatibility level
- is now 41
-
-test.c
- - make the < and > operators to [[ use strcoll() only if the shell
- compatibility level is greater than 40 (it is 41 by default in
- bash-4.1)
-
- 10/28
- -----
-support/shobj-conf
- - decrease the default version of FreeBSD that creates shared libraries
- to 4.x. Advice from Peter Jeremy <peterjeremy@acm.org>
-
- 11/2
- ----
-parse.y
- - change parse_comsub to free `heredelim' and set it to 0 whenever the
- comsub scanner finds the end of a here document. Really need to
- implement a stack of here doc delimiters like in the parser (can we
- use redir_stack here, too?)
- - fix parse_comsub to not attempt to read another here doc delimiter
- after seeing a shell break character (that is not newline) if we
- already have one. Fixes Debian bash bug #553485, submitted by
- Samuel Hym <samuel.hym@gmail.com>
-
- 11/3
- ----
-variables.c
- - fix bind_variable_internal to call a variable's dynamic 'set function'
- with the right arguments depending on whether it's an associative
- array, an indexed array, or a scalar. Fixes Ubuntu bug #471504
- https://bugs.launchpad.net/ubuntu/+source/bash/+bug/471504 reported
- by AJ Slater <aj.slater@gmail.com>
-
-[bash-4.1-beta frozen]
-
- 11/11
- -----
-builtins/printf.def
- - in getintmax(), in the case of a conversion error, return the partial
- value accumulated so far, which is suppose to be what
- strtoimax/strtoll/strtol returns
-
- 11/17
- -----
-[bash-4.1-beta released]
-
- 11/18
- -----
-builtins/{common.h,shopt.def},shell.c
- - changed shopt variable "set functions" to take the option name as
- the first argument; changed function prototypes and callers
-
-builtins/shopt.def
- - change set_compatibility_level() to turn off other compatNN options
- when one is set -- enforce mutual exclusivity. Fixes problem noted
- by Jan Schampera <jan.schampera@web.de>
-
- 11/19
- -----
-lib/readline/rltty.c
- - make sure prepare_terminal_settings() tests for the presence of
- ECHOCTL before using it. Fixes bug reported by Joachim Schmitz
- <schmitz@hp.com>
-
-config-top.h
- - new WORDEXP_OPTION define (off by default)
-
-shell.c
- - don't include the --wordexp option or the supporting function
- (run_wordexp) if WORDEXP_OPTION is not defined. Suggested by
- Aharon Robbins <arnold@skeeve.com>
-
-execute_cmd.c
- - in execute_cond_node, turn on comsub_ignore_return if the flags
- indicate we're ignoring the return value before calling
- cond_expand_word. Fixes bug reported by Anirban Sinha
- <asinha@zeugmasystems.com>
-
- 11/20
- -----
-lib/sh/snprintf.c,builtins/printf.def
- - change check for HAVE_ASPRINTF and HAVE_SNPRINTF to check if value
- is 1 or 0 rather than whether they are defined or not. This allows
- a value of 0 to enable function replacement
-
-configure.in,aclocal.m4
- - new autoconf macro, BASH_FUNC_SNPRINTF, checks for snprintf present
- and working as C99 specifies with a zero length argument. Idea
- from Greg Wooledge <wooledg@eeg.ccf.org>
- - new macro BASH_FUNC_VSNPRINTF, does same thing for vsnprintf
-
- 11/25
- -----
-subst.c
- - in command_substitute, only tell parse_and_execute to reset the line
- number in an interactive shell if sourcelevel == 0 -- we'll use the
- line numbers from the sourced file
-
-execute_cmd.c
- - in execute_simple_command, only subtract function_line_number from
- line_number if sourcelevel == 0. If sourcing, we'll use the line
- numbers from the sourced file. Fixes bug reported by Hugo
- Mildenberger <Hugo.Mildenberger@namir.de>
-
-builtins/declare.def
- - in declare_internal, call bind_assoc_variable instead of
- bind_array_variable in the case of declare -A foo=bar. Fixes bug
- reported by Bernd Eggink <monoped@sudrala.de>.
-
- 11/27
- -----
-lib/readline/util.c
- - change declaration for _rl_walphabetic to use prototype, assuming
- that any system with multibyte characters has a compiler that can
- handle prototypes. Fix for AIX compilation problem reported by
- Nick Hillman <nick_hillman@neverbox.com>
-
- 11/28
- -----
-execute_cmd.c
- - make funcnest file-scope static and unwind-protect its value in
- execute_function, so it can be used as a real measure of function
- call nesting
-
-general.c
- - fix off-by-one error in trim_pathname that caused it to short-circuit
- when PROMPT_DIRTRIM == number of directories - 1. Fixes bug
- reported by Dennis Williamson <dennistwilliamson@gmail.com>
-
- 11/29
- -----
-jobs.c
- - when fork() returns -1/EAGAIN, call waitchld(-1, 0) so the shell can
- reap any dead jobs before trying fork again. Currently disabled
- until bash-4.2 development starts
-
-lib/readline/complete.c
- - when incrementing _rl_interrupt_immediately, make sure it's greater
- than 0 before decrementing it. In practice, not a problem, but
- the right way to do it. Suggested by Jan Kratochvil
- <jan.kratochvil@redhat.com>
-
-lib/readline/signals.c
- - make sure rl_signal_handler doesn't set rl_caught_signal if
- _rl_interrupt_immediately is set, so RL_CHECK_SIGNALS doesn't
- cause it to be processed twice. Suggested by Jan Kratochvil
- <jan.kratochvil@redhat.com>
- - if the callback interface is being used, use the code path that
- immediately handles signals. This restores the readline-5.2
- behavior. Fixes GDB readline bug reported by Jan Kratochvil
- <jan.kratochvil@redhat.com>
-
- 12/18
- -----
-[bash-4.1-rc1 released]
-
- 12/22
- -----
-config-top.h
- - don't have SYSLOG_HISTORY enabled by default
-
-lib/sh/Makefile.in
- - add explicit dependency on pathnames.h for parallel make support
-
-externs.h
- - add extern declaration for xtrace_fdchk
-
-lib/sh/snprintf.c
- - add local prototype declarations for isinf, isnan if we are providing
- local definitions
-
-lib/sh/fnxform.c
- - add extern declaration for get_locale_var if HAVE_LOCALE_CHARSET not
- defined
-
-execute_cmd.c
- - define NEED_FPURGE_DECL so we pick up any extern declaration for
- fpurge (e.g., if the system doesn't provide it)
-
-builtins/shopt.def
- - correct prototype and declaration for set_shellopts_after_change so
- it's the correct type for shopt_set_func_t
- - add new function shopt_enable_hostname_completion that is the correct
- type for shopt_set_func_t; just calls enable_hostname_completion and
- returns its result
-
- 12/26
- -----
-doc/{bash.1,bashref.texi}
- - add \E and \" escape sequences to ANSI-C quoting description.
- Suggested by Aharon Robbins <arnold@skeeve.com>
-
- 12/29
- -----
-doc/bash.1
- - make sure shell and environment variable names are always in
- `small caps' bold. Suggested by Aharon Robbins <arnold@skeeve.com>
-
- 12/30
- -----
-{execute_cmd.c,parse.y,Makefile}
- - changes for building minimal configuration from Matthias Klose
- <doko@debian.org>
-
-[bash-4.1 frozen]
-
- 12/31
- -----
-[bash-4.1 released]
-
- 1/5/2010
- --------
-doc/bashref.texi
- - document compat32 and compat40 shopt options. Omission pointed out
- by Dilyan Palauzov <Dilyan.Palauzov@aegee.org>
-
- 1/6
- ---
-lib/readline/complete.c
- - use `convfn' (converted filename) instead of entry->d_name (filename
- read from file system) when adding partial or full completions to
- the command line. Bug and fix from Guillaume Outters
- <guillaume.outters@free.fr>
-
- 1/7
- ---
-builtins/printf.def
- - fix prototype in extern declaration for vsnprintf. Fix for bug
- reported by Yann Rouillard <yann@pleiades.fr.eu.org>
-
- 1/9
- ---
-parse.y
- - fix shell_getc to handle alias expansions containing quoted
- newlines. Problems in bash-4.1 with aliases containing quoted
- newlines in the middle of and at the end of their expansion.
- Fix for bug reported by Jonathan Claggett
- <jonathan@claggett.org>
- - change mk_alexpansion to not append a space to an alias
- expansion ending with a newline. Works with shell_getc
-
- 1/11
- ----
-lib/glob/Makefile.in
- - add dependencies on shell.h and pathnames.h. From Mike Frysinger
- <vapier@gentoo.org>
-
- 1/15
- ----
-doc/{bash.1,{bashref,version}.texi},lib/readine/doc/rluser.texi
- - some typo fixes from Aharon Robbins <arnold@skeeve.com>
- - added descriptions of ENV, COPROC, and MAPFILE variables
- - added descriptions of READLINE_LINE and READLINE_POINT
-
- 1/21
- ----
-arrayfunc.c
- - free `akey', the word-expanded index into the assoc array to avoid
- mem leak in array_value_internal
- - free index into assoc array in unbind_array_element
- - change array_value_internal to take an additional argument: an
- arrayind_t *. If not null, an index to an indexed array is
- returned there. If not an indexed array or subscript is @ or
- *, the value is unchanged
-
- 1/22
- ----
-builtins/ulimit.def
- - include <ulimit.h> if we found it during configure and we don't
- have resources. Fixes omission reported by Joachim Schmitz
- <jojo@schmitz-digital.de>
-
-{configure,config.h}.in
- - check for <ulimit.h>, define HAVE_ULIMIT_H if found
-
-lib/sh/oslib.c
- - include <signal.h> for extern declaration for kill(2) if
- HAVE_KILLPG not defined
-
-jobs.c
- - if HAVE_KILLPG is not defined, add an extern prototype decl for
- killpg()
-
- 1/24
- ----
-print_cmd.c
- - when printing here-string redirections, don't quote the string. The
- original quotes, if any, are still in place and don't need to be
- requoted. Fixes bug reported by Arfrever Frehtes Taifersar Arahesis
- <arfrever.fta@gmail.com>
-
-subst.c
- - fix array_length_reference to return 0 for variables that have not
- been assigned a value. Fixes bug reported by Mart Frauenlab
- <mart.frauenlob@chello.at>, but is not backwards compatible
-
-arrayfunc.[ch]
- - change array_value to take a new arrayind_t *indp parameter like
- get_array_value; changed extern prototype declaration
-
-subst.c
- - changed callers of array_value to add extra parameter
-
-expr.c
- - change expr_streval to set a new `lvalue' parameter with information
- about the string being evaluated: string, value, array index (if
- any), variable evaluated (if set).
- - saving and restoring current context now saves and restores the
- current `lvalue'
- - new function expr_bind_array_element, binds an array element with an
- already-computed index to a specified value
- - anywhere we set the current token to a string (STR), save and set
- the current lvalue
- - change calls to expr_bind_variable to check whether or not the
- current lvalue indicates an indexed array was evaluated, and, if so,
- call expr_bind_array_element using the already-computed index
- (curlval.ind). Fixes problems with dynamic variables (e.g., RANDOM)
- in array indices with {pre,post}-{inc,dec}rement and op=
- operators reported by <dennis@netstrata.com>
-
- 1/25
- ----
-expr.c
- - fix subexpr() to initialize curlval and lastlval when resetting all
- of the rest of the expression-parsing variables
-
- 1/26
- ----
-builtins/setattr.def
- - in show_var_attributes, if the variable is not set (value == 0),
- don't print `name=""', just print `name'. Pointed out by
- Mart Frauenlab <mart.frauenlob@chello.at>
-
-arrayfunc.c
- - fix array_keys to return NULL if the variable is not set or
- invisible. Pointed out by Mart Frauenlab <mart.frauenlob@chello.at>
- - change array_value_internal to return NULL for variable which has
- not been set
-
- 1/30
- ----
-bashline.c
- - in command_word_completion_function, don't call glob_pattern_p
- on hint -- use the already-computed `globpat'. At this point,
- hint might contain an already-dequoted globbing character, but
- glob_matches will be NULL. Fixes bug reported by
- coyote@wariat.org.pl
-
- 2/5
- ---
-builtins/exec.def
- - set extern variable "exec_argv0" to the argument to -a
-
-shell.c
- - if exec_argv0 is set, set dollar_vars[0] to it and set it to NULL,
- assuming it was set by `exec -a'. `exec -a foo' now sets $0 to
- foo in an executable shell script without a leading `#!' (fixes
- longstanding bug)
-
- 2/8
- ---
-variables.c
- - in push_func_var, if a variable is in a special builtin's temporary
- environment and needs to be propagated because we're in Posix mode,
- or we just need to propagate a variable, and we are executing in a
- function without any local variables (so the function-local variable
- context has no variable hash table), make sure we create a hash
- table so we have a place to save the variable to be propagated.
- Fixes bug reported by Crestez Dan Leonard <cdleonard@gmail.com>.
-
- 2/18
- ----
-builtins/hash.def
- - change add_hashed_command to remove the command being looked up from
- the hash table before trying to add it. That way, if it's not found,
- there won't be anything remaining in the hash table
-
- 2/26
- ----
-trap.[ch]
- - move IMPOSSIBLE_TRAP_HANDLER define to trap.h so other parts of the
- shell can use it
-
-parse.y
- - change yy_readline_get to use IMPOSSIBLE_TRAP_HANDER instead of NULL
- as a sentinel value for the SIGINT signal handler
- - make sure yy_readline_get resets interrupt_immediately to 0 after
- calling readline() using the same criteria it used to set it to 1
- before the call -- make the code symmetric. Suggested by Werner
- Fink <werner@suse.de>
-
-builtins/read.def
- - move assignment to `retval' before decrement of interrupt_immediately
- and terminate_immediately and call to discard_unwind_frame
- - move assign_vars label before decrement of interrupt_immediately and
- terminate_immediately so those variables get reset appropriately
- if read -t times out
-
-subst.h
- - new define for Q_DOLBRACE, indicates double-quoted ${...}
-
-subst.c
- - in parameter_brace_expand, before calling parameter_brace_expand_rhs,
- add Q_DOLBRACE to `quoted' if we're within double quotes.
- - in expand_word_internal, if the Q_DOLBRACE flag is set, remove a
- backslash escaping a }. Result of a Posix discussion on the
- austin-group list
-
- 2/27
- ----
-variables.c
- - new functions to save and restore the PIPESTATUS variable's internal
- array: save_pipestatus_array and restore_pipestatus_array
-
-variables.h
- - new extern declarations for save_pipestatus_array and
- restore_pipestatus_array
-
-trap.c
- - in run_pending_traps, _run_trap_internal, and run_exit_trap, save
- and restore $PIPESTATUS while traps are running. Fixes bug
- reported by Florian Bruhin <me@the-compiler.org>
-
-parse.y
- - use save_pipestatus_array and restore_pipestatus_array in
- save_parser_state and restore_parser_state, respectively, replacing
- inline code
-
-lib/readline/histfile.c
- - fix callers of history_filename to be prepared to cope with it
- returning NULL
- - change history_filename to return NULL if $HOME is not set, rather
- than trying to write the history file in the current directory.
- This is the default directory, used only if the application does
- not specify a history filename. Changed due to long-ago (unsent)
- bug report from OpenBSD
-
-{Makefile,config.h,configure}.in,externs.h,lib/sh/{dprintf.c,Makefile.in}
- - change fdprintf to dprintf, which is the Posix standard interface,
- look for it with configure, replace it if not available
-
- 2/28
- ----
-command.h
- - add new subshell flag, SUBSHELL_RESETTRAP. Indicates to the trap
- builtin that the shell is executing a command substitution and
- should free the trap strings we left unfreed by reset_signal_handlers()
-
-trap.c
- - free_trap_string() and free_trap_strings() are now compiled in
-
-builtins/trap.def
- - if changing a signal disposition and the SUBSHELL_RESETTRAP flag is
- set in subshell_environment, free the trap strings left unfreed by
- reset_signal_handlers
-
-subst.c
- - in command_substitute, set the SUBSHELL_RESETTRAP flag. This change
- is for Austin Group Posix interpretation 53
- (http://austingroupbugs.net/view.php?id=53)
-
- 3/7
- ---
-lib/sh/{Makefile.in,strchrnul.c},Makefile.in
- - implementation of strchrnul, from gnulib
-
-configure.in,config.h.in
- - look for strchrnul and compile in version in lib/sh/strchrnul.c if
- not available
- - look for mbsnrtowcs and define HAVE_MBSNRTOWCS if available
-
-lib/sh/xmbsrtowcs.c
- - new function, xdupmbstowcs2, fast version of xdupmbstowcs used when
- mbsnrtowcs is available and the indices are not required. Called
- from xdupmbstowcs as required. Initial patch from
- <0xe2.0x9a.0x9b@gmail.com>
-
- 3/22
- ----
-print_cmd.c
- - call print_deferred_heredocs virtually every time a recursive call
- to make_command_string_internal is made so here documents get
- printed correctly when they are attached to commands inside compound
- commands such as for and while. Fixes bug reported by Mike
- Frysinger <vapier@gentoo.org>
-
- 3/25
- ----
-builtins/printf.def
- - fix have_precision case in PF macro to call printf with precision
- instead of fieldwidth argument. Fixes bug reported by Rob Robason
- <rob@robason.net>
-
- 3/26
- ----
-trap.[ch]
- - new function, signal_is_hard_ignored, returns true if the shell
- inherited SIG_IGN as a signal's disposition
- - new function, set_original_signal (sig, handler), provides interface
- for rest of shell to set original_signals[sig] = handler
-
-execute_cmd.c
- - execute_disk_command needs to call reset_terminating_signals in the
- child process before resetting traps with restore_original_signals
-
-builtins/trap.def
- - call initialize_terminating_signals before calling display_traps for
- trap -p or trap without any other arguments. Possible future use
-
-lib/readline/complete.c
- - rl_filename_completion_function needs to call
- rl_filename_dequoting_function with `dirname' (which has already
- been tilde-expanded) instead of `users_dirname', because it calls
- opendir with `dirname'. Fixes bug reported by Stefan H. Holek
- <stefan@jarn.com>
-
- 3/27
- ----
-sig.c
- - experimental change to set_signal_handler: when setting the SIGCHLD
- handler, set the SA_RESTART flag so that interruptible system calls
- get restarted after a child dies. Fixes bug reported by Tomas
- Trnka <tomastrnka@gmx.com>, but needs further evaluation
-
-lib/sh/eaccess.c
- - eaccess(2) apparently does only half the job: it does not check that
- the permission bits on a file actually allow, for instance, execution.
- Need to augment with a call to sh_stataccess if eaccess returns
- success on FreeBSD. Fixes FreeBSD problem reported by Johan Hattne
- <johan.hattne@utsouthwestern.edu>
-
- 3/28
- ----
-parse.y,bashline.c,externs.h
- - history_delimiting_chars now takes a const char * as an argument:
- the line being added to the history. Changed callers
-
-parse.y
- - bash_add_history should not add a semicolon separator if the current
- history entry already ends in a newline. It can introduce syntax
- errors (e.g., when it results in a null command before a close brace).
- Fixes bug reported by Andreas Schwab <schwab@linux-m68k.org>
-
-parse.y
- - history_delimiting_chars needs to return a newline instead of a
- semicolon if it thinks the current line starts a here document
- (if it contains `<<'). Also keeps track of the fact with a new
- static variable, LAST_WAS_HEREDOC, so it can return the right
- sequence of newlines later for the here-document body. Fixes bug
- reported by Andreas Schwab <schwab@linux-m68k.org>
-
- 3/29
- ----
-lib/sh/eaccess.c
- - if the system has faccessat, sh_eaccess will now use it in
- preference to all other options
-
- 3/30
- ----
-subst.h
- - new string_extract and extract_dollar_brace_string flag value:
- SX_POSIXEXP, set if the shell is expanding one of the new Posix
- pattern removal word expansions
-
-parser.h
- - new definitions for "word expansion state", shared between parse.y
- and subst.c
-
-subst.c
- - include parser.h
-
- 4/9
- ---
-builtins/declare.def
- - make sure declare_internal calls bind_assoc_variable with newly-
- allocated memory for the key argument when using an implicit key
- of "0". Bug report and fix from Andreas Schwab
- <schwab@linux-m68k.org>
-
- 4/14
- ----
-lib/readline/input.c
- - restructure the rl_event_hook loop in rl_read_key to call the
- event hook after rl_gather_tyi() returns and rl_get_char has
- a chance to collect the input. Previous behavior was to call
- the event hook before attempting to read input. Problem
- reported by Anant Shankar <anantshankar17@gmail.com>
-
- 4/15
- ----
-builtins/fc.def
- - fc_builtin needs to check whether the calculation of last_hist
- leaves hlist[last_hist] == 0, and keep decrementing it until it
- leaves a non-null history entry or goes < 0. Currently only
- does this if saved_command_line_count > 0, indicating we're
- trying to edit a multi-line command. Fixes bug reported by
- Roman Rakus <rrakus@redhat.com>
-
- 4/17
- ----
-subst.c
- - new process substitution helper functions:
- unlink_fifo - closes a single FD or FIFO
- num_fifos - returns number of open FDs or active FIFOs
- copy_fifo_list - returns a bitmap of open FDs or active FIFOs
- by index into appropriate list (dev_fd_list or fifo_list)
- close_new_fifos - take a bitmap saved by copy_fifo_list and
- call unlink_fifo on any FD or FIFO open at the time of the
- call that is not marked as active in list
-
-execute_cmd.c
- - execute_builtin_or_function: use new framework to close process
- substitution FDs or FIFOs created by a shell builtin or shell
- function. Fixes bug reported by Charles Duffy <charles@dyfis.net>
-
-doc/{bash.1,bashref.texi}
- - document 'C and "C constants for printf builtin
-
- 4/22
- ----
-lib/readline/complete.c
- - new function to return screenwidth for use when displaying possible
- matches: complete_get_screenwidth; changed uses of _rl_screenwidth
- to use complete_get_screenwidth().
- - change complete_get_screenwidth to query (readline-private)
- _rl_completion_colums, $COLUMNS, then _rl_screenwidth in that order
- - change rl_display_match_list to deal with limit < 0 (which implies
- that cols == 0) when _rl_screenwidth > 0
-
-lib/readline/bind.c
- - new bindable variable: completion-display-width, controls the
- number of columns used when displaying completions with new
- sv_compwidth function to call when value is set or unset
-
-lib/readline/doc/{readline.3,rltech.texi}
- - documented completion-display-width variable
-
- 4/23
- ----
-execute_cmd.c
- - change execute_in_subshell to reset trap handlers without freeing
- the trap strings and set SUBSHELL_RESETTRAP. In line with Austin
- Group interp #53 (trap in a subshell).
- - ditto for execute_simple_command where it can be determined that
- the shell is going to run a builtin or function in a subshell
-
-trap.c
- - new function, get_all_original_signals, retrieves the original
- signal disposition for all signals
-
-trap.h
- - extern declaration for get_all_original_signals
-
-builtins/trap.def
- - change showtrap to display signals that are "hard ignored" as
- trap commands to ignore them, even though that trap command would
- be a no-op. Partial fix for feature request from Siddhesh
- Poyarekar <siddhesh.poyarekar@gmail.com>
- - change trap_builtin to call get_all_original_signals before displaying
- traps. This will show inherited ignored signals. Rest of feature
- request from Siddhesh Poyarekar <siddhesh.poyarekar@gmail.com>
-
-lib/readline/histexpand.c
- - fix history_tokenize_word so that it understands $(...) and the
- <(...) and >(...) expansions as a single word
- - change history_tokenize_word so that it understands extended shell
- globbing patterns as a single word. Code is very similar to
- $(...) code above. Bug reported by Rajeev V. Pillai
- <rajeevvp@gmail.com>
-
- 4/24
- ----
-lib/readline/vi_mode.c
- - add checks to rl_vi_char_search to make sure we've already done a
- search if the command is `;' or `,', and return immediately if we
- have not. Fixes bug reported by Eric Ho <ericmho@shaw.ca>
-
-lib/readline/text.c
- - make sure `dir' is in the valid range before searching in
- _rl_char_search_internal. Range checks in the code depend on it
- being non-zero
-
- 5/3
- ---
-lib/readline/complete.c
- - in rl_complete_internal, if show-all-if-ambiguous or
- show-all-if-unmodified are set (what_to_do == '!' or '@',
- respectively), and the common match prefix is shorter than the
- text being completed, inhibit inserting the match.
- The guess is that replacing text with a shorter match will not
- be wanted
-
- 5/20
- ----
-lib/sh/unicode.c
- - new file, with unicode character conversion-related code. Will be
- used to implement \u and \U escapes where appropriate, and for
- other unicode-related functions in the future
-
- 5/21
- ----
-builtins/printf.def
- - add code to handle \u and \U escapes in format strings and arguments
- processed by the %b format specifier
-
-lib/sh/strtrans.c
- - add code to handle \u and \U escapes as unicode characters, works for
- both `echo -e' and $'...'
-
-doc/{bash.1,bashref.texi}
- - document new \u and \U escape sequences for $'...' and echo (printf
- defers to the system's man page or Posix)
-
- 5/24
- ----
-execute_cmd.c
- - change execute_disk_command to return a status, instead of just
- leaving it in `last_command_exit_value', since the parent's return
- value is sometimes used (e.g., when a restricted shell refuses to
- run a command with a `/'). Fixes bug reported by David Pitt
- <David.Pitt@anz.com>
-
- 5/25
- ----
-bashline.c
- - change bash completion functions to save and restore the value of
- rl_ignore_some_completions_function, and set it to the bash default
- of filename_completion_ignore where appropriate. Fixes bug
- reported by Henning Bekel <h.bekel@googlemail.com>
-
-variables.c
- - new convenience function: find_global_variable (name). Looks for
- NAME in the global variables table, skipping any local and
- temporary environment variables
-
-builtins/declare.def
- - add new -g option to declare/typeset/local, forces variables to be
- created or modified at the global scope when executing inside a
- shell function. Requested by many, most recently by
- konsolebox@gmail.com
-
- 5/27
- ----
-test.c
- - added new `-v var' unary test operator; returns TRUE if var is set
- (i.e., has been assigned a value). Works in both test builtin and
- [[ conditional command
-
-doc/{bash.1,bashref.texi}
- - documented new `-v var' unary conditional operator
-
-tests/test.tests
- - added tests for new -v var operator
-
-builtins/kill.def
- - change kill builtin so -PID (pgrp specification) following a
- -s sig or -n sig option is not interpreted as a signal specification.
- Fixes bug reported by Roman Rakus <rrakus@redhat.com>
-
-builtins/evalstring.c
- - in parse_and_execute, if parse_command() returns non-zero,
- indicating a parse error, exit the shell if the conditions require
- a posix-mode non-interactive shell to abort (parse error in a `.'
- script or eval string). Bash-4.1 only printed a warning. This is
- from Austin Group interp 114
-
-doc/bashref.texi
- - add note to the posix mode section of the texinfo manual noting
- the changed behavior for `.' and `eval'
-
-parse.y
- - change time_command_acceptable to allow TIME token to appear after
- BANG token (to allow `! time foo', which is supposed to be valid)
- - change pipeline_command production to allow multiple instances of
- `!' (which toggle inverting the return status) and `time' (which
- have no effect)
-
-execute_cmd.c
- - In posix mode, `time' without a following pipeline prints the
- elapsed user, system, and real time for the shell and its
- children since the shell was invoked.
- It's like `times' but obeys the setting of TIMEFORMAT. A future
- revision of Posix will require this
-
-doc/{bashref.texi,bash.1}
- - document new posix mode use of `time'
-
-parse.y
- - add production to pipeline_command that permits `!' by itself to
- be equivalent to `false' (and, with the changes above, permits
- `! !' to be roughly equivalent to `true'). A future revision of
- Posix will require this
-
- 5/28
- ----
-parse.y
- - fix \W prompt expansion to use memmove instead of strcpy, since the
- source and target strings overlap (though you think it wouldn't
- matter, since the overlapping regions are never touched at the same
- time). Fixes bug reported by Stéphane Jourdoi
- <sjourdois@gmail.com>
-
-parse.y
- - Posix interp 217 states that $(( must be parsed first as an
- arithmetic expansion, so avoid attempting to parse it as a nested
- command substitution. Fixes bug reported by several, most recently
- <jwm@horde.net>
-
-subst.c
- - change extract_delimited_string to process nested $( as a possible
- command substitution, but only if already parsing an arithmetic
- expansion. Rest of fix for Posix interp 217
- - change parameter_brace_expand_rhs to make the := expansion operator
- perform quote removal and both assign the result to the variable and
- return it as the result of the expansion, rather than assign the
- value after quote removal but return the value before quote removal.
- Posix interp 221
- - introduce new internal quoting flag: Q_DOLBRACE. Denotes a double-
- quoted ${...} expansion. In this case, Posix interp 221 requires
- that a backslash quoting an embedded `}' be removed, even though it's
- not one of the characters marked as special inside double quotes.
- Set in parameter_brace_expand, used by expand_word_internal.
-
-parse.y
- - introduce new parsing state, P_DOLBRACE, set when parsing a ${...}
- expansion
- - set a "dolbrace operator state" in parse_matched_pair to decide
- whether the lexer is reading the param, op, or word in
- ${paramOPword}. Will be used to decide whether or not to treat
- single quotes specially in a double-quoted "${...}
-
- 5/29
- ----
-parse.y
- - change parse_matched_pair so that a single quote appearing in a
- double-quoted ${...} expansion is not special unless the expansion
- operator is `#[#]' or `%[%]'. Posix interp 221
-
-subst.c
- - change string_extract_double_quoted so that a single quote appearing
- in a double-quoted ${...} expansion is not special unless the
- expansion operator is `#[#]' or `%[%]'. Posix interp 221
-
-doc/bashref.texi
- - document posix-mode effects of Posix interp 221
- - add section describing GNU parallel as requested by Stallman
-
-lib/readline/complete.c
- - broke code that compares filenames read from the file system (and
- possibly converted) to words being completed out into a separate
- function: complete_fncmp
- - augment complete_fncmp to treat hyphen and underscore as equivalent
- when comparing filenames if _rl_completion_case_map is set
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_completion_case_map
-
-lib/readline/util.c
- - change _rl_strnicmp to return the difference between the characters,
- like strcasecmp, and not modify the pointers it is passed
- - change _rl_stricmp to not modify the pointers it is passed
-
-lib/readline/bind.c
- - new bindable variable, "completion-case-map", toggles value of
- _rl_completion_case_map
-
-lib/readline/doc/{rluser.texi,readline.3}
- - document new bindable readline variable "completion-case-map"
-
-execute_cmd.c
- - change execute_function to reset funcnest and jump back to top level
- if funcnest exceeds funcnest_max
- - use funcnest_max as a max function nesting level, if set to numeric
- value greater than 0 (defaults to 0, so inactive)
-
-variables.c
- - new variable FUNCNEST, controls funcnest_max value if set to numeric
- value > 0
-sig.c
- - reset funcnest to 0 when throw_to_top_level occurs
-
-doc/{bash.1,bashref.texi}
- - document FUNCNEST variable and its effect on function execution
-
-lib/readline/funmap.c
- - add new bindable command names to avoid case-insensitive matching
- problems between, for instance, vi-fword and vi-fWord:
-
- vi-forward-word
- vi-forward-bigword
- vi-backward-word
- vi-backward-bigword
- vi-end-word
- vi-end-bigword
-
- Suggested in a different form in 2006 (!) by Servatius Brandt
- <servatius.brandt@arcor.de>
-
-builtins/mapfile.def
- - run_callback now takes a new third argument: curline, the line
- currently being read and about to be assigned
- - the callback function/command now takes an additional argument:
- the line to be assigned to the array index. Feature suggested by
- Dennis Williamson <dennistwilliamson@gmail.com>
-
-doc/{bash.1,bashref.texi}
- - document new additional `line' argument to mapfile callback
-
- 5/30
- ----
-builtins/printf.def
- - add new %(fmt)T format specifier, where FMT is a strftime format.
- Argument is number of seconds since the epoch, with -1 meaning
- current time (roughly date +%s) and -2 meaning shell start time
- (roughly $SECONDS, unless it's been assigned a value or unset).
- Fieldwidth and precision are preserved, strftime result is printed
- as with %[-][[fieldwidth][.[precision]]]s
-
-doc/{bash.1,bashref.texi}
- - document new %(datefmt)T printf format specifier and special
- arguments
-
-builtins/hash.def
- - don't permit programs with slashes to be entered into the hash table
- at all, even with the -p option. Inconsistency pointed out by
- Jan Schampera <jan.schampera@web.de>
-
-builtins/shopt.def
- - add `compat41' option in preparation for bash-4.2
-
- 6/6
- ---
-lib/readline/vi_mode.c
- - finish restructuring rl_vi_domove and the functions that call it so
- it works in callback mode, including numeric arguments. Requested
- a long time ago by Bob Rossi
-
-lib/readline/callback.c
- - arrange to call appropriate callback when readline state indicates
- RL_STATE_VIMOTION, so vi motion commands like `cw' and `d2w' are
- handled in callback mode
-
-lib/sh/wcswidth.c
- - replacement wcswidth implementation
-
-aclocal.m4
- - add REPLACE_FUNCS(wcswidth) to BASH_CHECK_MULTIBYTE
-
-execute_cmd.c
- - fix select_query and print_index_and_element to compute correct
- display width of select list elements in presence of multibyte
- characters. Bug reported by Bernd Eggink <monoped@sudrala.de>
-
-builtins/cd.def
- - add posix-mandated -e option; currently ignored in most circumstances
-
-doc/{bash.1,bashref.texi}
- - document new `cd -e' option
-
- 6/12
- ----
-arrayfunc.c
- - change array_value_internal to treat negative subscripts to indexed
- arrays, offset from array_max_index(x) + 1, so foo[-1] is the last
- element of $foo
-
-subst.c
- - Change verify_substring_values to allow negative length specifications
- when using string variables or array members. Negative lengths
- mean to return characters from OFFSET until (${#var} - N) for
- {var:offset:-N}. Feature requested by Richard Neill
- <rn214@hermes.cam.ac.uk>
-
-doc/{bash.1,bashref.texi}
- - document new behavior of negative subscripts to indexed arrays
- - document new behavior of negative LENGTH in substring expansion
-
-configure.in
- - change version to bash-4.2-devel
-
-variables.c
- - make sure initialize_shell_variables calls sv_xtracefd if
- BASH_XTRACEFD is inherited in the shell environment. Fixes but
- reported by <jsunx1@bellsouth.net>
-
- 6/13
- ----
-lib/readline/complete.c
- - change get_y_or_n to always return 1 when in callback mode, so we
- don't do a blocking read. Have to wait until readline-7.0 to add
- a state so we can use callbacks, since that will change public
- interface
-
- 6/17
- ----
-subst.c
- - fix memory leak in parameter_brace_expand: when performing pattern
- removal with parameter_brace_remove_pattern, make sure `name' is
- freed. Fixes bug reported by oyvindh@dhampir.no
-
- 6/23
- ----
-{parse.y,subst.c}
- - make the ${param//pat/rep}, ${param^pat}, and ${param,pat} expansions
- require single quotes and double quotes to match when within double
- quotes. This way every expansion except the Posix ones behaves as
- bash has always behaved
-
-subst.c
- - change remove_upattern and remove_wpattern to return their first
- argument if nothing matches, change callers to allocate memory
- appropriately
- - change remove_pattern to short-circuit and return copy of PARAM
- if remove_wpattern returns its first argument (indicating no match)
- rather than convert back to multibyte string, allocating new memory
- twice and calling wcsrtombs
-
- 6/24
- ----
-execute_cmd.c
- - add missing initializers for sh_coproc to eliminate a compiler
- warning. Patch from Werner Fink <werner@suse.de>
-
- 6/27
- ----
-parse.y
- - add `TIMEIGN' token to handle `time -p -- ...'. Pointed out by
- Laszlo Ersek <lacos@caesar.elte.hu> on austin-group list
-
- 6/28
- ----
-jobs.c
- - treat a shell with (subshell_environment&SUBSHELL_PIPE) != 0 like
- a command substitution in wait_for and act like we received a
- SIGINT if a job we're waiting for dies of SIGINT. Fixes bug
- reported by Ilya Basin <basinilya@gmail.com>
-
- 7/2
- ---
-jobs.c
- - if fork() fails in make_child, try to reap some dead children before
- retrying
-
-execute_cmd.c
- - change execute_pipeline to run the last command of a non-asynchronous
- pipeline in the current shell environment if the `lastpipe' shell
- option is enabled and job control is not active. Code from
- Werner Fink <werner@suse.de>
-
-parse.y
- - Posix says (issue 267) that time is not recognized as a keyword
- if the next token begins with a `-'
-
-doc/{bash.1,bashref.texi}
- - changed the descriptions of BASH_SOURCE, BASH_LINENO, and FUNCNAME
- as proposed in Ubuntu bug 591677.
- - document new `lastpipe' shell option that runs last command of a
- pipeline in the current shell environment
- - document new posix-mode behavior with `time -p'
-
- 7/5
- ---
-aclocal.m4
- - new autoconf test WEXITSTATUS_OFFSET, bit offset in status word
- returned by wait() of the process's exit status
-
-jobs.[ch]
- - change stop_pipeline to return the actual index of the job just
- created and added to the jobs table, instead of the current job
- - job_exit_status and job_exit_signal are now global functions, with
- extern declarations in jobs.h
- - append_process: new utility function for use by the lastpipe code,
- takes info, creates a PROCESS from them, and adds it to the end of
- the passed job id's pipeline. lastpipe code uses it to add a dummy
- process for the last command in the pipeline
- - freeze_jobs_list: new utility function so rest of shell can freeze
- the jobs list. Used by the lastpipe code
-
-execute_cmd.c
- - changes to lastpipe code to make `pipefail' option, $PIPESTATUS, and
- $? work correctly. Uses append_process and job_exit_status
-
- 7/10
- ----
-subst.c
- - when performing pattern substitution word expansions, a `&' in the
- replacement string is replaced by the text matched by the pattern.
- The `&' can be quoted with a backslash to inhibit the expansion.
- CURRENTLY DISABLED
-
- 7/13
- ----
-pcomplib.[ch]
- - new member for struct compspec: lcommand. for future use
-
- 7/15
- ----
-parse.y
- - fix problem in parse_comsub where extra space was added to here-doc
- delimiter if the first word in the comsub contained a `/'. Fixes
- bug reported by Alex Khesin <alexk@google.com>
-
- 7/20
- ----
-parse.y
- - change reserved_word_acceptable to return success if the last two
- tokens read were `function WORD'. Allows function definitions like
- function good [[ -x foo ]];. Fixes bug reported by Linda Walsh
- <bash@tlinx.org>
-
-doc/{bash.1,bashref.texi}
- - change function definition meta-syntax to make it clearer, rather
- than let the text note the optional portions
-
- 7/24
- ----
-bashhist.c
- - change bash_history_inhibit_expansion() to suppress history expansion
- for $! parameter expansion. Fixes debian bug #589745 submitted by
- Frank Heckenbach <f.heckenbach@fh-soft.de>
-
-lib/readline/terminal.c
- - change rl_resize_terminal to always fetch the new terminal size and
- only force the redisplay if _rl_echoing_p is non-zero. Fixes bug
- reported by Balazs Kezes <rlblaster@gmail.com>
-
- 7/25
- ----
-lib/readline/xfree.c
- - new file, contains definition of xfree moved from xmalloc.c
-
- 7/28
- ----
-variables.c
- - check suspect return values from bind_variable before trying to use
- the returned SHELL_VAR *. Changes to: initialize_shell_variables,
- bind_int_variable, FIND_OR_MAKE_VARIABLE. Fixes bug reported by
- Roman Rakus <rrakus@redhat.com>
-
- 7/31
- ----
-lib/readline/rltty.c
- - fix rl_prep_terminal and rl_deprep_terminal to use fileno(stdout)
- if rl_instream is NULL. Fixes bug reported by Otto Allmendinger
- otto.allmendinger@googlemail.com
-
- 8/2
- ---
-lib/sh/casemod.c
- - if the passed string is NULL or empty, return it immediately. Fixes
- bug reported by Dennis Williamson <dennistwilliamson@gmail.com>
-
-subst.c
- - fix pat_subst to cope with the passed string being NULL
-
-arrayfunc.h
- - added flag values for array_value_internal and its callers; converted
- array_value_internal `allow_all' parameter into a general flags word
- - get_array_value now takes a flags value
- - changed array_value internal to use *indp as an index to use if the
- AV_USEIND flag is set, rather than recomputing it
-
-subst.c
- - get_var_and_type takes two new parameters: a flags word and an index
- that represents an already-computed index for an array reference
- (just indexed arrays so far). Index is used and passed to array_value
- if flags includes AV_USEIND
- - parameter_brace_expand_word takes a new argument: the already-
- computed index; returns W_ARRAYIND if word expanded is being used
- as an array index
- - changed parameter_brace_casemod, parameter_brace_patsub,
- parameter_brace_substring, parameter_brace_remove_pattern to take new
- flags and index arguments from parameter_brace_expand_word. They
- pass the new parameters along to get_var_and_type to use an
- already-computed array index if necessary. Fixes bug where array
- indexes are computed twice reported by Andrew Benton
- <b3nton@gmail.com>
-
-doc/bash.1,lib/readline/doc/{history.3,hsuser.texi}
- - modified description of history event designators to clarify that
- all non-absolute event designators are relative to the current
- position in the history list. Question raised by Frank
- Heckenbach <f.heckenbach@fh-soft.de> as debian bash bug 590012
-
- 8/5
- ---
-subst.c
- - remove code that does not add a quoted null when the input string
- is partially quoted; subsequent word splitting may require it.
- Fixes bug reported by Eric Blake <eblake@redhat.com>
-
- 8/12
- ----
-lib/glob/gmisc.c
- - move match_pattern_wchar and match_pattern_char to new file in
- glob library
- - new functions: wmatchlen(pat, max) and umatchlen(pat, max), computes
- number of characters PAT will match. Returns the number of chars
- that will be matched or -1 if the match length is indeterminate
- (i.e., contains a `*')
-
-subst.c
- - use umatchlen/wmatchlen in match_upattern/match_wpattern to bound
- the number of match attempts in large strings to (usually) one,
- depending on match length. Fixes performance problems with
- pattern substitution in large strings noted by Yi Yan
- <yiyan97@hotmail.com>. Can be applied to remove_[uw]pattern also
-
- 8/13
- ----
-bashhist.c
- - in maybe_append_history, change check for history_lines_this_session
- so that we append the lines to the file if it's equal to the value
- returned by where_history(). This means that without this change,
- the history won't be appended if all the lines in the history list
- were added in the current session since the last time the history
- file was read or written. Fixes bug reported by Bruce Korb
- <bruce.korb@gmail.com>
-
-shell.h,parse.y
- - add prompt_string_pointer to the parser_state struct saved and
- restored by {save,restore}_parser_state. Fixes both bugs exposed
- by bash_completion and completion of open backquotes reported by
- Egmont Koblinger <egmont@gmail.com>
-
-subst.h
- - new flag for skip_to_delim: SD_EXTGLOB. Skip extended globbing
- patterns while looking for ending delimiter
-
-subst.c
- - when passed the SD_EXTGLOB flag, skip_to_delim skips over extended
- globbing patterns (when extended_glob is set) while looking for a
- character in the delimiter set
-
-pathexp.c
- - split_ignorespec: new function to replace calls to extract_colon_unit
- in setup_ignore_patterns. uses skip_to_delim with the SD_EXTGLOB
- flag to skip over extended globbing patterns in variables like
- HISTIGNORE and GLOBIGNORE. Fixes bug reported by Dimitar DIMITROV
- <mitkofr@yahoo.fr> and Greg Wooledge <wooledg@eeg.ccf.org>
-
- 8/28
- ----
-lib/readline/rlprivate.h
- - add members to search_cxt to save _rl_keymap
- - new flag for isearch context: SF_CHGKMAP, set if we changed the
- keymap while reading a character for the search string that
- translated to a command
-
-lib/readline/isearch.c
- - save current readline keymap in cxt->keymap and cxt->okeymap
- in _rl_scxt_alloc
- - in _rl_isearch_dispatch, only check for cxt->lastc as a member of
- cxt->search_terminators if it's > 0 (i.e., not an isearch opcode)
-
- 9/3
- ---
-support/signames.c
- - add Solaris SIGJVM1 and SIGJVM2. Update from Stefan Teleman
- <stefan.teleman@oracle.com>
-
-shell.c
- - instead of closing all fds 3-20 at shell startup, just set them to
- be close-on-exec. Report from Rainer Mülle <raimue@macports.org>
-
-lib/readline/isearch.c
- - in _rl_isearch_dispatch, if the current character maps to ISKMAP,
- move to the indicated keymap (using cxt->keymap) and go on to
- read another character. Fixes problem reported by Davor
- Cubranic <cubranic@stat.ubc.ca>
- - in _rl_isearch_dispatch, after translating key to possible opcode,
- restore _rl_keymap from cxt->okeymap if necessary
- - in _rl_isearch_dispatch, use key sequences that map to default
- functions that ^G, ^W, and ^Y map to as equivalent to those chars
-
-lib/readline/complete.c
- - new variable, _rl_menu_complete_prefix_first, zero by default
- - change menu_complete to display common prefix (matches[0]) first
- before cycling through rest of match list if
- _rl_menu_complete_prefix_first is non-zero. Suggested by Sami
- Pietila <sami.pietila@gmail.com>
-
-lib/readline/bind.c
- - new bindable readline variable, "menu-complete-display-prefix",
- controls setting of _rl_menu_complete_prefix_first
-
-doc/{bash.1,bashref.texi},lib/readline/doc/{readline.3,rluser.texi}
- - added description of menu-complete-display-prefix bindable
- readline variable
-
- 9/17
- ----
-configure.in
- - remove AM_PATH_LISPDIR call since we don't use that bash debugger
- any more. Suggested by Mike Frysinger <vapier@gentoo.org>
-
- 10/6
- ----
-findcmd.c
- - change executable_file to set errno to EISDIR if the passed name
- is a directory
-
-builtins/exec.def
- - change exec_builtin to report appropriate error message if the
- file argument is a directory. Noted by Eric Blake <eblake@redhat.com>
- in a message to austin-group
-
-builtins/source.def
- - change source_builtin to make sure the shell exits if the file is
- not found when in a non-interactive shell running in posix mode
- and source_searches_cwd == 0 (as posix mode makes it by default).
- Pointed out in http://thread.gmane.org/gmane.comp.shells.dash/291/focus=392
- by Jilles Tjoelker <jilles@stack.nl>
-
-execute_cmd.c
- - set executing_command_builtin in execute_builtin if the builtin is
- command_builtin. Unwind-protected in execute_function_or_builtin
- (like executing_builtin variable). Available for rest of shell
-
-builtins/{source.def,evalfile.c}
- - make sure that non-interactive posix mode shells exit if the file
- argument to `.' is not found only if they are not being executed
- by the command builtin (executing_command_builtin == 0). This is
- how `command' can cancel effects of special builtin exit properties
- in the case of `dot file not found'
-
- 10/13
- -----
-lib/sh/strtrans.c
- - pass \c through unchanged if not escaping for `echo -e' and they are
- the final two characters in the string
-
- 10/15
- -----
-subst.c
- - extract_dollar_brace_string: fix problem with single quotes
- in unquoted ${...} for Posix compliance
-
- 10/16
- -----
-builtins/exec.def
- - catch return value from shell_execve; don't print duplicate error
- message if return value is EX_NOTFOUND. Make sure exit status
- from exec is 127 if command is not found
-
-execute_cmd.c
- - fix typo (`saved_redirects' should be `saved redirects') in
- execute_function_or_builtin `command exec' case. Typo caused
- too much of the unwind-protect stack to be discarded
- - in same execute_function_or_builtin case, don't discard the
- `saved redirects' frame unconditionally; only discard it if
- saved_redirects is non-null in the `command exec' case. Fixes
- sh -c 'command exec; exit 1' hanging bug uncovered by FreeBSD
- sh test cases
-
- 10/18
- -----
-subst.c
- - when in posix mode, shell should not exit if a variable assignment
- error (e.g., assigning to readonly variable) occurs preceding a
- command that is not a special builtin. Fixes bug uncovered by
- FreeBSD sh test cases
- - when in posix mode, the ${!?} and ${!#} expansions are not indirect
- expansions, but posix word expansions involving the `!' variable
-
-parse.y
- - fix parse_comsub so that it does not skip backslash-newline when
- parsing a comment
-
- 10/19
- -----
-subst.c
- - fix parameter_brace_expand so that an attempt to use the % or #
- expansions on an unset variable with -u set will cause a non-
- interactive shell to abort. Posix change
- - fix parameter_brace_expand so that an attempt to use pattern
- substitution or case modification expansions on an unset variable
- with -u set will cause and unbound variable error and make a
- non-interactive shell abort
- - change parameter_brace_expand_length to return INTMAX_MIN if a
- positional parameter is unset and -u is set
- - if parameter_brace_expand_length returns INTMAX_MIN when -u is set,
- treat it as an unbound variable error and make a non-interactive
- shell abort. Posix change
- - change parameter_brace_expand_length to return INTMAX_MIN if an
- implicit reference to array[0] is made ${#array} and array[0] is
- not set when -u is set
-
- 10/20
- -----
-builtins/cd.def
- - Posix 2008 says that if no matching directories are found in $CDPATH,
- use the directory name passed as an operand and go on. Posix change
-
-doc/bashref.texi
- - change Posix mode section with latest additions and removals
-
- 11/4
- ----
-lib/readline/complete.c
- - fix rl_menu_complete and rl_old_menu_complete to keep incrementing
- match_list_index by match_list_size as long as it's < 0. Fixes
- bug reported by jeenuv@gmail.com
-
-braces.c
- - make mkseq() take intmax_t arguments for sequence start and end
- and make sure it's passed intmax_t values. Fixes bug reported by
- Pete Gregory <pg@bushlitt.org>
-
-sig.c
- - if termsig_handler is called when terminate_immediately == 1,
- assume we're being called as a signal handler and set
- history_lines_this_session to 0 to inhibit history file being
- written on shell exit. Fixes long-standing bug most recently
- observed by Andreas Schwab <schwab@linux-m68k.org>
-
- 11/5
- ----
-redir.c
- - add_undo_close_redirect now returns int, 0 on success, non-zero on
- failure. Currently always succeeds
- - new macro REDIRECTION_ERROR to make do_redirection_internal return
- value of errno
- - change do_redirection_internal to call REDIRECTION_ERROR after
- saving file descriptor and make do_redirection_internal return error
- if add_undo_redirect or add_undo_close redirect fails. This makes
- failure to save a file descriptor a redirection error and the shell
- behaves appropriately. Fixes bug reported by Eric Blake
- <eblake@redhat.com>
-
-bashline.c
- - modify bash_forward_shellword to correctly handle quoted strings,
- especially if point is in a quoted string when function is invoked.
- Fixes bug reported by Daniel Colascione <dan.colascione@gmail.com>
-
-configure.in
- - change version to 4.2-alpha
-
- 11/7
- ----
-lib/readline/text.c
- - in rl_insert, if we're not in the multibyte code path, don't try to
- optimize and insert all of the available typeahead input if we're
- reading input from a macro. Fixes bug reported by Andre Majorel
- <aym-ung@teaser.fr>
-
-lib/readline/text.c
- - break out multibyte guts of rl_forward_char into a separate function
- _rl_forward_char_internal that does nothing but calculate the new
- value of point
- - change rl_forward_char to call _rl_forward_char_internal instead of
- having equivalent code inline
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_forward_char_internal
-
-lib/readline/vi_mode.c
- - change _rl_vi_append_forward to call _rl_forward_char_internal to
- set rl_point, instead of calling rl_forward_char. When at the end
- of the line, rl_forward_char will ring the bell. Fixes debian
- bash bug 601042, reported by Alan J. Greenberger <alanjg@ptd.net>
-
- 11/14
- -----
-subst.c
- - fix match_upattern to use correct test to immediately break out of
- loop (when potential match length is greater than number of chars
- remaining in the string) in MATCH_ANY case
-
- 11/15
- -----
-subst.c
- - include "typemax.h" to make sure we have a definition of INTMAX_MIN
-
- 11/16
- -----
-lib/sh/unicode.c
- - make sure `localconv' isn't declared on machines without iconv
- - add stub_charset for systems that don't have locale_charset: looks
- up LC_CTYPE, returns everything after last `.', "UTF-8" if the
- value is exactly "UTF-8", and "ASCII" otherwise
-
- 11/20
- -----
-lib/readline/vi_mode.c
- - in rl_domove_motion_callback, make sure to use m->key instead of
- key, which is not initialized and should not be used. Bug report
- from Andreas Schwab <schwab@linux-m68k.org>
- - in rl_vi_domove, make assignment to `m' explicit instead of
- relying on evaluation order semantics, since the C standard leaves
- them unspecified. Bug report from Andreas Schwab
- <schwab@linux-m68k.org>
-
- 11/21
- -----
-lib/sh/shquote.c
- - sh_single_quote and sh_double_quote now take a const char *
- argument. Fixes problem pointed out by Joachim Schmitz
- <jojo@schmitz-digital.de>
-
-externs.h
- - change extern declarations for sh_single_quote and sh_double_quote
-
-lib/sh/strchrnul.c
- - make sure that return value is cast to (char *) if we're using a
- part of the passed (const char *) argument. Fixes problem pointed
- out by Joachim Schmitz <jojo@schmitz-digital.de>
-
-lib/glob/gmisc.c
- - fix a typo that mixed up defines for LPAREN and RPAREN. Bug and
- fix from Andreas Schwab <schwab@linux-m68k.org>
- - use WLPAREN and WRPAREN in multibyte character environments
- - fixed typos using L'cc' in a non-wide-char environment
-
-lib/readline/complete.c
- - fix rl_filename_completion_function to dequote users_dirname if
- there is a filename dequoting function (as well as dirname), since
- users_dirname gets tacked back onto the beginning of the possible
- completions and then requoted. Bug reported by Andreas Schwab
- <schwab@linux-m68k.org>
-
- 11/22
- -----
-lib/readline/parens.c
- - the `blink-matching-paren' variable should default to off
-
- 11/23
- -----
-subst.h
- - add extern declaration for close_new_fifos()
-
-lib/sh/fnxform.c
- - fix curencoding to return the character past the `.', not a string
- beginning with `.'
-
-lib/sh/unicode.c
- - fix stub_charset to do the same cut-off at `@' as curencoding().
- These two functions should be combined
-
-builtins/printf.def
- - document new %(datefmt)T modifier in help text
-
- 11/24
- -----
-parse.y
- - fix `W' case in decode_prompt_string: memmove was copying one too
- few bytes and missed the closing NUL. Bug report from Tim Mooney
- <Tim.Mooney@ndsu.edu>
-
- 11/26
- -----
-subst.c
- - in expand_word_internal, don't add quoted nulls to partially-
- quoted strings if the word will not be subjected to word splitting
- later (which will remove the quoted null). Fixes bug reported by
- Rocky Bernstein <rocky.bernstein@gmail.com>
-
- 11/28
- -----
-subst.c
- - change multibyte case of match_pattern to revert to match_upattern
- if neither the pattern nor the string has any multibyte characters
-
-alias.c
- - fix tests of backslash-escaped characters in skipquotes, skipws,
- rd_token to check for backslash at EOS and not go past the end.
- Fixes debian bug 603696 reported by Tim Small <tim@buttersideup.com>
-
-include/shmbchar.h
- - new file, mbchar.h from gnulib minus the <stdbool.h> include
-
-lib/sh/shmbchar.c
- - new file, mbchar.c from gnulib with additions
- - moved mbstrlen from subst.c to here, changed initialization of mbs
- - change mbstrlen to use is_basic to avoid calls to mbrlen for ASCII
- chars; code hints from gnulib
- - don't copy mbs and mbsbak if we're not calling mbrlen
-
- 11/29
- -----
-lib/glob/smatch.c
- - change xstrmatch to use internal_strmatch() if the pattern and
- string don't have any multibyte characters
-
- 11/30
- -----
-include/shmbutil.h
- - change ADVANCE_CHAR and ADVANCE_CHAR_P macros to use is_basic and
- only call mbrlen and copy state and state_bak if is_basic returns
- false (non-ASCII). Called all over the place.
- - change rest of macros except BACKUP_CHAR and BACKUP_CHAR_P in the
- same way
-
- 12/2
- ----
-subst.c
- - audit all calls to string_list and make sure caller can handle a
- NULL return value. Fixes bug reported by David Rochberg
- <rochberg@google.com>
-
-general.h
- - change sh_wassign_func_t to take an additional argument: an int
- flags word
-
-subst.c
- - change do_word_assignment to take an additional argument to match
- wassign_func_t; change callers
- - change call to (*assign_func) in expand_word_list_internal to match
- new wassign_func_t prototype
- - (*assign_func) passes 1 as additional arg if the simple command is
- a builtin or function, in which case the assignment to the
- temporary env should take effect
-
-variables.c
- - change assign_in_env to take an additional argument to match
- wassign_func_t; change callers
- - move call to sv_ifs from dispose_temporary_env to
- dispose_used_env_vars; we don't need to do it if called from
- merge_temporary_env
-
- 12/3
- ----
-variables.c
- - change dispose_temporary_env to maintain a list (tempvar_list) of
- variables that need to be handled specially. If a variable that
- gets freed by push_temp_var or propagate_temp_var is one of the
- variables that the shell handles specially (IFS, LANG, etc.), it's
- stored on the list. For each variable in this list,
- dispose_temp_var calls stupidly_hack_special_variables.
- - assign_in_env calls stupidly_hack_special_variables if flags arg
- is non-zero, so variable assignments affect current shell
- execution environment if a builtin or function is being executed.
- Fixes bug reported by Bruno Haible <bruno@clisp.org>
-
- 12/5
- ----
-subst.c
- - use mbsmbchar on both string and pattern in match_pattern instead
- of strlen and mbstrlen; only go through the strings once
-
- 12/6
- ----
-lib/readline/kill.c
- - in rl_yank_last_arg, only switch directions if the `count'
- argument is < 0, not < 1. This makes explicit count arguments of
- 0 work as expected. Fixes bug reported by Dennis Williamson
- <dennistwilliamson@gmail.com>
-
-doc/bash.1,lib/readline/doc/{readline.3,rluser.texi}
- - fix documentation for yank-last-arg to make it clear how the count
- argument is set and how second and subsequent calls treat any
- numeric argument
-
-doc/{bash.1,bashref.texi}
- - slight changes to the description of test
- - change \(bv to `|'; it seems that many `internationalized' versions
- of groff don't render that as a vertical bar. Fixes Debian bug
- 603805
-
- 12/10
- -----
-configure.in
- - changed release status to 4.2-beta
-
- 12/14
- -----
-[bash-4.2-beta frozen]
-
- 12/18
- -----
-redir.c
- - change REDIRECTION_ERROR macro to accept a third argument: an
- additional file descriptor to close before returning and error (pass
- -1 to do nothing)
- - change calls to REDIRECTION_ERROR to close appropriate file
- descriptors. Fixes bug reported by Andreas Schwab
- <schwab@linux-m68k.org>
- - make sure to close any file descriptors opened for REDIR_VARASSIGN
- before returning an error
-
- 12/19
- -----
-expr.c
- - move processing of unary `-' and `+' to exp1 from exp0 to avoid
- precedence problems. Fixes bug reported by <12bric@gmail.com>
-
- 12/22
- -----
-lib/sh/fpurge.c
- - updated version from gnulib, inlined gnulib stdio-impl.h
-
- 12/24
- -----
-doc/bash.1
- - change the description of while and until to use `list-1' and
- `list-2', similar to the Posix description. Suggested by
- Jeff Haemer <jeffrey.haemer@gmail.com>
-
- 12/27
- -----
-execute_cmd.c
- - slight changes to execute_command_internal and how it captures the
- exit status of (command) and shell control structures with pipes to
- avoid multiple variable assignments to last_command_exit_value
- - change to execute_simple_command so that parent branches of shells
- forked to execute commands in pipelines don't change $? to 0
- (if (pipe_out != NO_PIPE) result = last_command_exit_value). Fixes
- bug reported by Damien Nadà <dnade.ext@orange-ftgroup.com>
-
- 12/28
- -----
-configure.in
- - changed version to bash-4.2-rc1
-
- 1/2/2011
- --------
-lib/readline/complete.c
- - fix rl_filename_completion_function to dequote and save users_dirname
- before calling any function to transform the directory name passed
- to opendir(). Fix from Andreas Schwab <schwab@linux-m68k.org>
-
-lib/readline/doc/
- - make sure to note that rl_directory_completion_hook cannot modify
- the directory name argument if it returns 0
-
-bashline.c
- - make sure that bash_directory_completion_hook consistently returns
- non-zero whenever it modifies its directory name argument
-
-lib/readline/terminal.c
- - don't bother with the declarations (extern or not) for PC, BS, and
- UP if NCURSES_VERSION is defined, since ncurses defines local
- versions of those symbols in the library. Fixes bug most recently
- reported by Kevin Scott <kscott@eznet.net> against Mac OS X
-
-include/filecntl.h
- - make sure O_TEXT and O_BINARY are defined to avoid Windows-specific
- (or cygwin-specific) code. This and the following changes from
- Eric Blake <eblake@redhat.com> for current cygwin systems
-
-input.h
- - add a B_TEXT flag to note when the underlying file descriptor is
- opened in O_TEXT mode
-
-lib/sh/tmpfile.c
- - make sure temporary files are opened in binary mode (O_BINARY) on
- systems where it matters
-
-input.c
- - make sure to set the B_TEXT flag if the file descriptor has O_TEXT
- in its flags (returned by fcntl)
- - change b_fill_buffer to compensate for lseek() and read() returning
- different offsets on files opened in O_TEXT mode
- - cygwin now is able to lseek on files and set the unbuffered and text
- flags appropriately, so can use the general test for a seekable fd
- - now that cygwin uses O_TEXT or O_BINARY appropriately, we no longer
- have to manually translate \r\n to \n
-
-redir.c
- - remove the Cygwin-1.1 code from here_document_to_fd; cygwin is now
- up to version 1.7 and can unlink an open file descriptor
- - make sure temporary files used for here documents are opened in
- binary mode (O_BINARY) on systems where it matters
-
-execute_cmd.c,parse.y
- - make sure error messages use all printable characters in filenames
- and strings
-
-{builtins/evalfile,shell,subst}.c
- - remove cygwin-specific calls to setmode to force file descriptors
- into text mode, since we're using text or binary mode according to
- the mode of the mount point
-
-execute_cmd.c
- - when creating pipes and making them stdin and stdout, make sure to
- tell stdio that the mode of the underlying file descriptor may have
- changed from text to binary
-
-subst.c
- - when creating pipes for command substitution, make sure to
- tell stdio that the mode of the underlying file descriptor may have
- changed from text to binary
-
- 1/3
- ---
-doc/{bash.1,bashref.texi}
- - changes to the readonly documentation suggested by Jan Schampera
- <jan.schampera@web.de>
-
- 1/4
- ---
-builtins/read.def
- - change bind_read_variable to consistently return NULL if there is some
- kind of variable assignment error (e.g., assigning to a readonly or
- noassign var)
- - change read builtin to only call stupidly_hack_special_variables if
- bind_read_variable returns non-NULL
- - change read_builtin to return EXECUTION_FAILURE if there is an
- assignment error (e.g., assigning to a readonly or noassign var).
- Fixes bug reported by Jan Schampera <jan.schampera@web.de>
-
- 1/5
- ---
-builtins/{help.def,common.c}
- - change uses of a builtin's `short_doc' member to go through gettext
- for possible translation before being displayed. Suggestion from
- <goeran@uddeborg.se>
-
- 1/6
- ---
-shell.h
- - new exit status define: EX_MISCERROR (2)
-
-builtins/getopts.def
- - change getopts_bind_variable to return error if an attempt is made
- to assign to a variable with the `noassign' attribute
- - change getopts_bind_variable to return EX_MISCERROR if attempt is
- made to assign to readonly or noassign variable
-
-builtins/cd.def
- - change setpwd to return an int and return failure when PWD is
- readonly; success otherwise
- - change bindpwd to return failure if setpwd returns EXECUTION_FAILURE.
- Inspired by message from Eric Blake <eblake@redhat.com>
- - change pwd builtin to return failure if PWD is readonly (and setpwd
- returns EXECUTION_FAILURE)
-
- 1/8
- ---
-lib/sh/eaccess.c
- - on FreeBSD and Solaris, check the result of access(2) with mode X_OK
- for root by checking sh_stataccess(). Same code as was added to
- check result of eaccess(). Fixes Solaris 11 problem reported by
- <cloyce@headgear.org>
-
- 1/10
- ----
-builtins/set.def
- - add description of `--' to help text
-
-[bash-4.2-rc1 released]
-
- 1/14
- ----
-lib/readline/readline.h
- - fix/update description of rl_directory_rewrite_hook
-
-lib/readline/complete.c
- - if there are no directory rewrite or completion hooks, set dirname
- to a duplicate copy of users_dirname instead of calling the
- dequoting function again
-
-bashline.c
- - use rl_directory_rewrite_hook instead of rl_directory_completion_hook
- to avoid changing the directory name the user typed, other than
- dequoting it. Fixes bug introduced by changes to directory
- completion hook, pointed out first by William Bader
- <william.bader@gmail.com>
-
- 1/16
- ----
-lib/sh/strftime.c
- - portability and other (int->long) updates from Aharon Robbins
- <arnold@skeeve.com>
-
-configure.in
- - change release level to rc2
-
- 1/17
- ----
-execute_cmd.c
- - short-circuit select builtin if read_builtin returns anything but
- EXECUTION_SUCCESS, not just EXECUTION_FAILURE. Fixes bug reported
- by Pierre Gaston <pierre.gaston@gmail.com>
-
- 1/19
- ----
-execute_cmd.c
- - change execute_simple_command to save and restore the values of
- executing_builtin and executing_command_builtin before discarding
- the unwind-protect frame. Bug and fix from Werner Fink
- <werner@suse.de>
-
- 1/24
- ----
-variables.c
- - change brand to set rseed to a known, constant value if it's 0,
- so the sequence is known. Fixes issue reported by Olivier
- Mehani <shtrom@ssji.net>
-
- 2/2
- ---
-braces.c
- - make sure to pass an `int' argument to asprintf in mkseq. Fixes
- bug reported by Mike Frysinger <vapier@gentoo.org>
-
- 2/5
- ---
-lib/glob/gmisc.c
- - fix wmatchlen and umatchlen to initialize all state variables. Fix
- from Andreas Schwab <schwab@linux-m68k.org>
-
-jobs.c
- - change wait_for to call restore_sigint_handler right after exiting
- the wait loop, instead of right before function returns. Reduces
- the window for a SIGINT to be lost because a child does not exit
- due to SIGINT
-
- 2/7
- ---
-configure.in
- - changed release status to `release'
-
- 2/9
- ---
-execute_cmd.c
- - make sure some variables are declared as volatile if necessary. Bug
- report and fix from Eric Blake <eblake@redhat.com>
-
-[bash-4.2 frozen]
-
- 2/11
- ----
-print_cmd.c
- - in indirection_level_string, change to simpler test of result of
- MBLEN (< 0 instead of MB_INVALIDCH)
-
- 2/14
- ----
-[bash-4.2 released]
-
- 2/15
- ----
-lib/glob/gmisc.c
- - fix wmatchlen and umatchlen to avoid going past the end of the
- string on an incomplete bracket expression that ends with a
- NUL. Partial fix for bug reported by Clark Wang <dearvoid@gmail.com>
-
- 2/16
- ----
-subst.h
- - new string extract flag value: SX_WORD. Used when calling
- extract_dollar_brace_string to skip over the word in
- ${param op word} from parameter_brace_expand
-
-subst.c
- - change parameter_brace_expand to add SX_WORD to flags passed to
- extract_dollar_brace_string
- - change parameter_brace_expand to use SX_POSIXEXP for all non-posix
- word expansion operators that treat single quotes as special, not
- just % and #
- - change extract_dollar_brace_string to initialize dolbrace_state to
- DOLBRACE_WORD if SX_WORD flag supplied and we shouldn't use
- DOLBRACE_QUOTE. Fixes bug reported by Juergen Daubert <jue@jue.li>
-
-doc/{bash.1,bashref.texi}
- - document the exact expansions here strings undergo
-
- 2/17
- ----
-lib/readline/vi_mode.c
- - make sure that `dd', `cc', and `yy' call vidomove_dispatch from
- rl_domove_read_callback. Fixes bug reported by Clark Wang
- <dearvoid@gmail.com>
-
-lib/readline/callback.c
- - make sure _rl_internal_char_cleanup is called after the
- vi-motion callbacks (rl_vi_domove_callback) in rl_callback_read_char.
- Companion to above fix
-
-doc/{bash.1,bashref.texi}
- - make sure that the text describing the rhs of the == and =~
- operators to [[ states that only the quoted portion of the pattern
- is matched as a string
-
- 2/18
- ----
-lib/glob/gmisc.c
- - better fix for umatchlen/wmatchlen: keep track of the number of
- characters in a bracket expression as the value to increase
- matchlen by if the bracket expression is not well-formed. Fixes
- bug reported by Clark Wang <dearvoid@gmail.com>
-
-subst.c
- - change expand_string_for_rhs so that it sets the W_NOSPLIT2 flag
- in the word flags. We will not perform word splitting or quote
- removal on the result, so we do not want to add quoted nulls if
- we see "" or ''. Fixes bug reported by Mike Frysinger
- <vapier@gentoo.org>
-
- 2/19
- ----
-variables.c
- - new function, int chkexport(name), checks whether variable NAME is
- exported and remakes the export environment if necessary. Returns
- 1 if NAME is exported and 0 if not
- - call chkexport(name) to get tzset to look at the right variable in
- the environment when modifying TZ in sv_tz. Don't call tzset if
- chkexport doesn't indicate that the variable is exported
-
-variables.h
- - new extern declaration for chkexport
-
-
-{parse.y,builtins/printf.def}
- - call sv_tz before calling localtime() when formatting time strings
- in prompt strings or using printf. Fixes bug reported by
- Dennis Williamson <dennistwilliamson@gmail.com>
-
-execute_cmd.c
- - modify fix of 2/9 to add casts when those variables are passed to
- functions; some compilers throw errors instead of warnings. Report
- and fix from Joachim Schmitz <jojo@schmitz-digital.de>
-
-support/shobj-conf
- - add a stanza for nsk on the Tandem from Joachim Schmitz
- <jojo@schmitz-digital.de>
-
-{shell,lib/readline/shell}.c
- - Tandem systems should use getpwnam (getlogin()); for some reason
- they don't do well with using getuid(). Fix from Joachim Schmitz
- <jojo@schmitz-digital.de>
-
- 3/1
- ---
-variables.c
- - make sure that the return value from find_variable is non-null
- before trying to use it in chkexport. Fixes bug reported by
- Evangelos Foutras <foutrelis@gmail.com>
-
- 3/3
- ---
-parse.y
- - when adding $$ to the current token buffer in read_token_word(),
- don't xmalloc a buffer for two characters and then strcpy it, just
- copy the characters directly into the token buffer. Fix from
- Michael Whitten <mfwitten@gmail.com>
-
-execute_cmd.c
- - fix expand_word_unsplit to add the W_NOSPLIT2 flag to the word to
- be expanded, so "" doesn't add CTLNUL. Similar to fix of 2/18 to
- expand_string_for_rhs. Fixes bug reported by Nathanael D. Noblet
- <nathanael@gnat.ca> and Matthias Klose <doko@debian.org>
-
-parse.y
- - fix extended_glob case of read_token_word to allocate an extra
- space in the buffer for the next character read after the extended
- glob specification if it's a CTLESC or CTLNUL. Report and fix from
- Michael Witten <mfwitten@gmail.com>
- - fix shell expansions case of read_token_word to allocate an extra
- space in the buffer for the next character read after the shell
- expansion if it's a CTLESC or CTLNUL. Report and fix from
- Michael Witten <mfwitten@gmail.com>
- - TENTATIVE: fix read_token_word to reduce the amount of buffer space
- required to hold the translated and double-quoted value of $"..."
- strings. Report and fix from Michael Witten <mfwitten@gmail.com>
- - change code around got_character and got_escaped_character labels to
- make sure that we call RESIZE_MALLOCED_BUFFER before adding the
- CTLESC before a CTLESC or CTLNUL, and before adding the character if
- we're not adding a CTLESC. Report and fix from
- Michael Witten <mfwitten@gmail.com>
-
-subst.c
- - new param flags value, PF_ASSIGNRHS, mirrors W_ASSIGNRHS, noting that
- parameter expansion is on rhs of assignment statement. That inhibits
- word splitting
- - change param_expand to call string_list_dollar_at with quoted == 1
- if PF_ASSIGNRHS is set, so it will quote IFS characters in the
- positional parameter before separating them with the first char of
- $IFS. This keeps the rhs from being split inappropriately. Fixes
- bug reported by Andres Perera <andres.p@zoho.com>
-
- 3/4
- ---
-lib/readline/bind.c
- - add a missing free of `names' in rl_function_dumper. Bug report
- and fix from Michael Snyder <msnyder@vmware.com>
-
- 3/5
- ---
-lib/readline/rltty.c
- - change rl_deprep_terminal so it uses fileno (stdin) for the tty fd
- if rl_instream is not set, like rl_prep_terminal
-
- 3/6
- ---
-lib/readline/display.c
- - fix rl_message to use a dynamically-allocated buffer instead of a
- fixed-size buffer of 128 chars for the `local message prompt'. Bug
- report and fix from Micah Cowan <micah@cowan.name>
-
- 3/7
- ---
-jobs.c
- - add sentinel to wait_sigint_handler so it only sets wait_sigint_received
- if waiting_for_child is non-zero; otherwise, it restores the old
- SIGINT handler and sends itself the SIGINT
- - set waiting_for_child around the calls to waitchld that use it to
- synchronously wait for a process
- - change logic that decides whether or not the child process blocked
- or handled SIGINT based on whether or not waitpid returns -1/EINTR
- and the shell receives a SIGINT and the child does not exit. If
- the child later exits due to SIGINT, cancel the assumoption that it
- was handled
- - instead of testing whether or not the child exited due to SIGINT
- when deciding whether the shell should act on a SIGINT it received
- while waiting, test whether or not we think the child caught
- SIGINT. If it did, we let it go (unless the shell has it trapped);
- if it did not catch it, the shell acts on the SIGINT. Fix from
- Linus Torvalds <torvalds@linux-foundation.org>, bug report originally
- from Oleg Nesterov <oleg@redhat.com>
-
- 3/8
- ---
-shell.c
- - initialize no_line_editing to 1 if READLINE is not defined -- we
- can't have line editing without readline
-
- 3/12
- ----
-lib/readline/signals.c
- - add SIGHUP to the set of signals readline handles
-
-lib/readline/doc/rltech.texi
- - document that SIGHUP is now part of the set of signals readline
- handles
-
-lib/readline/input.c
- - if _rl_caught_signal indicates that read() was interrupted by a
- SIGHUP or SIGTERM, return READERR or EOF as appropriate
- - call rl_event_hook, if it's set, if call to read in rl_getc
- returns -1/EINTR. If rl_event_hook doesn't do anything, this
- continues the loop as before. This handles the other fatal
- signals
-
-execute_cmd.c
- - add a couple of QUIT; calls to execute_disk_command and
- execute_simple_command to improve responsiveness to interrupts
- and fatal signals
-
-input.c
- - rearrange getc_with_restart so that the return values from read()
- are handled right
-
-parse.y
- - don't need to set terminate_immediately in yy_stream_get, since
- getc_with_restart checks for terminating signals itself
- - since readline returns READERR on SIGHUP or SIGTERM, don't need
- to set terminate_immediately. Still doesn't handle other
- signals well -- will have to check that some more
-
-bashline.c
- - new function, bash_event_hook, for rl_event_hook. Just checks for
- terminating signals and acts on them using CHECK_TERMSIG.
- - set rl_event_hook to bash_event_hook
-
-builtins/read.def
- - take out setting terminate_immediately; add calls to CHECK_TERMSIG
- after read calls
-
-doc/{bash.1,bashref.texi}
- - move the text describing the effect of negative subscripts used to
- reference indexed array elements to the paragraphs describing
- ${parameter[subscript]}, since that's where they are implemented.
- Pointed out by Christopher F. A. Johnson <cfajohnson@gmail.com>
-
-arrayfunc.[ch],subst.c
- - array_expand_index now takes a new first argument: a SHELL_VAR *
- of the array variable being subscripted. Can be used later to fully
- implement negative subscripts
-
- 3/14
- ----
-lib/glob/glob.c
- - fix mbskipname to not turn the directory entry name into a wide char
- string if the conversion of the pattern to a wide char string fails
- - fix mbskipname to call skipname if either the pattern or the filename
- can't be converted into a wide-char string
-
-lib/glob/xmbsrtowcs.c
- - fix xdupmbstowcs2 to handle return value of 0 from mbsnrtowcs and
- short-circuit with failure in that case. Fixes bug reported by
- Roman Rakus <rrakus@redhat.com>
-
- 3/15
- ----
-bashline.c
- - new variable, bash_filename_quote_characters to store the value
- assigned to rl_filename_quote_characters so it can be restored
- if changed.
- - change bashline_reset and attempt_shell_completion to restore
- rl_filename_quote_characters if not set to default
-
- 3/22
- ----
-lib/glob/glob.c
- - wdequote_pathname falls back to udequote_pathname if xdupmbstowcs
- fails to convert the pathname to a wide-character string
-
-lib/glob/xmbsrtowcs.c
- - xdupmbstowcs2: change to fix problem with leading '\\' (results in
- nms == 0, which causes it to short-circuit with failure right
- away). Fixes bug pointed out by Werner Fink <werner@suse.de>
- - xdupmbstowcs2: compensate for mbsnrtowcs returning 0 by taking the
- next single-byte character and going on
- - xdupmbstowcs2: change memory allocation to increase by WSBUF_INC
- bytes; try to avoid calls to realloc (even if they don't actually
- result in more memory being allocated)
-
- 3/24
- ----
-doc/{bash.1,bashref.texi}
- - slightly modify BASH_SUBSHELL description based on complaint from
- Sam Liddicott <sam@liddicott.com>
-
- 3/25
- ----
-trap.c
- - change free_trap_strings to not call free_trap_string for signals
- that are being ignored, like reset_or_restore_signal_handlers.
- Fixes bug reported by Satoshi Takahashi <blue3waters@gmail.com>
-
- 3/26
- ----
-lib/readline/rltypedefs.h
- - remove old Function/VFunction/CPFunction/CPPFunction typedefs as
- suggested by Tom Tromey <tromey@redhat.com>
-
-lib/readline/rlstdc.h
- - move defines for USE_VARARGS/PREFER_STDARG/PREFER_VARARGS from
- config.h.in to here because declaration of rl_message in
- readline.h uses the defines. This makes it hard for another packages
- to use after the header files are installed, since config.h is not
- one of the installed files. Suggested by Tom Tromey
- <tromey@redhat.com>
-
- 3/27
- ----
-print_cmd.c
- - change indirection_string from a static buffer to a dynamic one
- managed by indirection_level_string(), so we don't end up truncating
- PS4. Suggested by Dennis Williamson <dennistwilliamson@gmail.com>
-
-lib/readline/shell.c
- - change sh_set_lines_and_columns to use static buffers instead of
- allocating the buffers to pass to setenv/putenv
-
-lib/readline/terminal.c
- - change _rl_get_screen_size to not call sh_set_lines_and_columns if
- ignore_env == 0
- - _rl_sigwinch_resize_terminal: new function to just retrieve terminal
- size, ignoring environment
-
-lib/readline/rlprivate.h
- - new external declaration for _rl_sigwinch_resize_terminal() (currently
- unused)
-
-lib/readline/signals.c
- - rl_sigwinch_handler: set _rl_caught_signal to SIGWINCH
- - rl_sigwinch_handler: don't immediately call rl_resize_terminal; just
- leave _rl_caught_signal set for RL_CHECK_SIGNALS to handle
- - _rl_signal_handler: call rl_resize_terminal if sig == SIGWINCH.
- Should fix hang when sending multiple repeated SIGWINCH reported by
- Henning Bekel <h.bekel@googlemail.com>
-
- 3/29
- ----
-lib/sh/snprintf.c
- - include math.h for any defines for isinf/isnan
- - use code from gnulib documentation to implement isinf/isnan if they
- are not defined
-
-configure.in
- - don't check for isinf or isnan; c99 says they're macros anyway
-
-config.h.in
- - remove defines for ISINF_IN_LIBC and ISNAN_IN_LIBC, no longer used
- by snprintf.c
-
- 4/2
- ---
-braces.c
- - brace_gobbler: fix to understand double-quoted command substitution,
- since the shell understands unquoted comsubs. Fixes bug reported
- by Michael Whitten <mfwitten@gmail.com>
-
-lib/readline/display.c
- - include <pc.h> on MDOS
- - get and set screen size using DJGPP-specific calls on MSDOS
- - move cursor up clear screen using DJGPP-specific calls
- - don't call tputs on DJGPP; there is no good terminfo support
-
-lib/readline/terminal.c
- - include <pc.h> on MDOS
- - get and set screen size using DJGPP-specific calls on MSDOS
- - use DJGPP-specific initialization on MSDOS, zeroing all the
- _rl_term_* variables
- - don't call tputs on DJGPP; there is no good terminfo support
- DJGPP support from Eli Zaretskii <eliz@gnu.org>
-
- 4/6
- ---
-
-config-top.h
- - change DEFAULT_PATH_VALUE to something more useful and modern
-
- 4/8
- ---
-tests/printf2.sub
- - make sure LC_ALL and LC_CTYPE are set so LANG assignment takes effect.
- Reported by Cedric Arbogast <arbogast.cedric@gmail.com>
-
- 4/11
- ----
-include/chartypes.h
- - fix a couple of dicey defines (though ones that don't cause any
- compiler warnings) in IN_CTYPE_DOMAIN
-
-doc/{bashref.texi,bash.1}
- - add note referring to duplicating file descriptors in sections
- describing redirecting stdout and stderr and appending to stdout
- and stderr. Suggested by Matthew Dinger <mdinger.bugzilla@gmail.com>
-
-pcomplete.c
- - it_init_helptopics: new function to support completing on help topics,
- not just builtins
- - it_helptopics: new programmable completion list of help topics
- - build list of helptopic completions in gen_action_completions on
- demand
-
-pcomplete.h
- - new extern declaration for it_helptopics
-
-builtins/complete.def
- - the `helptopic' action now maps to CA_HELPTOPIC intead of CA_BUILTIN,
- since there are more help topics than just builtins. Suggested by
- Clark Wang <dearvoid@gmail.com>
-
- 4/12
- ----
-print_cmd.c
- - fix print_arith_for_command to add a call to PRINT_DEFERRED_HEREDOCS
- before ending the body of the command, so heredocs get attached to
- the right command instead of to the loop. From gentoo bug 363371
- http://bugs.gentoo.org/show_bug.cgi?id=363371
-
-execute_cmd.c
- - change coproc_pidchk to unset the appropriate shell variables when
- the (currently single) known coproc pid terminates
- - cleanup and new functions to fully support multiple coprocesses when
- and if I decide to go there
-
- 4/13
- ----
-print_cmd.c
- - fix print_group_command to add a call to PRINT_DEFERRED_HEREDOCS
- after call to make_command_string_internal before printing closing
- `}'
- - fix make_command_string_internal to add a call to
- PRINT_DEFERRED_HEREDOCS after recursive call to
- make_command_string_internal in case cm_subshell before printing
- closing `)'
-
- 4/14
- ----
-print_cmd.c
- - change overlapping strcpy in named_function_string to memmove
-
-sig.h
- - UNBLOCK_SIGNAL: convenience define, same as UNBLOCK_CHILD, just
- restores an old signal mask
-
-trap.c
- - set_signal: instead of setting the signal handler to SIG_IGN while
- installing the new trap handler, block the signal and unblock it
- after the new handler is installed. Fixes bug reported by Roman
- Rakus <rrakus@redhat.com>
-
- 4/15
- ----
-doc/{bash.1,bashref.texi}
- - make it clear that enabling monitor mode means that all jobs run in
- separate process groups
-
- 4/18
- ----
-builtins/fc.def
- - update fix of 4/15/2010 to not take saved_command_line_count into
- account when stepping down the history list to make sure that
- last_hist indexes something that is valid. Fixes bug reported by
- <piuma@piumalab.org>
-
- 4/19
- ----
-builtins/fc.def
- - fc_gethnum: make sure the calculation to decide the last history
- entry is exactly the same as fc_builtin. Fixes bug uncovered by
- fix of 4/18 to stop seg fault
-
- 4/22
- ----
-lib/readline/terminal.c
- - change _rl_enable_meta_key to set a flag indicating that it sent the
- enable-meta sequence
- - _rl_disable_meta_key: new function to turn off meta mode after we
- turned it on with _rl_enable_meta_key
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_disable_meta_key
-
-configure.in
- - if not cross-compiling, set CFLAGS_FOR_BUILD from any CFLAGS inherited
- from the environment. Fixes HP/UX build problem reported by
- "Daniel Richard G." <skunk@iSKUNK.ORG>
-
- 4/26
- ----
-config-top.h
- - define MULTIPLE_COPROCS to 0 so the code is still disabled but easy
- to enable via configure option or editing this file
-
- 4/29
- ----
-lib/sh/eaccess.c
- - freebsd provides faccessat, with the same misfeature as their eaccess
- and access implementations (X_OK returns true for uid==0 regardless
- of the actual file permissions), so reorganize code to check the
- file permissions as with eaccess. Report and fix from Johan Hattne
- <johan.hattne@utsouthwestern.edu>
-
- 5/2
- ---
-doc/{bash.1,bashref.texi}
- - add forward reference to `Pattern Matching' from `Pathname
- Expansion', suggested by Greg Wooledge <wooledg@eeg.ccf.org>
-
- 5/5
- ---
-pcomplib.c
- - the bash_completion project now distributes over 200 completions
- for various programs, with no end in sight, so increase the value
- of COMPLETE_HASH_BUCKETS from 32 to 128
-
-pathexp.c
- - quote_string_for_globbing: make sure CTLESC quoting CTLESC is
- translated into \<CTLESC> even if the flags include QGLOB_REGEXP.
- We don't want to process the second CTLESC as a quote character.
- Fixes bug reported by Shawn Bohrer <sbohrer@rgmadvisors.com>
-
- 5/6
- ---
-builtins/printf.def
- - change PRETURN to not call fflush if ferror(stdout) is true
- - if a call to one of the stdio functions or printstr leaves
- ferror(stdout) true, and PRETURN is going to be called, let PRETURN
- print the error message rather than doubling up the messages. Fixes
- problem reported by Roman Rakus <rrakus@redhat.com>
-
- 5/9
- ---
-doc/{bash.1,bashref.texi}
- - add note to the effect that lists inside compound command can be
- terminated by newlines as well as semicolons. Suggested by
- Roman Byshko <rbyshko@gmail.com>
-
- 5/10
- ----
-subst.c
- - remove_quoted_nulls: fix problem that caused it to skip over the
- character after a CTLNUL, which had the effect of skipping every
- other of a series of CTLNULs. Fixes bug reported by
- Marten Wikstrom <marten.wikstrom@keystream.se>
-
- 5/11
- ----
-subst.c
- - extract_process_subst: add SX_COMMAND flag to call to
- extract_delimited_string, since we're expanding the same sort of
- command as command substitution. Fixes bug reported in Ubuntu
- bug 779848
-
- 5/12
- ----
-configure.in
- - set the prefer_shared and prefer_static variables appropriately
- depending on the value of $opt_static_link
-
-aclocal.m4
- - AC_LIB_LINKFLAGS_BODY: change to not prefer shared versions of the
- libraries it's searching for if the prefer_shared variable is "no".
- Fixes problem reported by Cedric Arbogast <arbogast.cedric@gmail.com>
-
- 5/13
- ----
-lib/readline/readline.c
- - _rl_internal_teardown: add call to _rl_disable_meta_key to make the
- meta key active only for the duration of the call to readline()
- - _rl_internal_setup: move call to _rl_enable_meta_key here from
- readline_initialize_everything so the meta key is active only for
- the duration of the call to readline(). Suggestion from Miroslav
- Lichvar <mlichvar@redhat.com>
-
-builtins/help.def
- - help_builtin: change strncmp to strcmp so that `help read' no longer
- matches `readonly'. Suggested by Clark Wang <dearvoid@gmail.com>
-
-config.h.in
- - add define for GLIBC21, checked using jm_GLIBC21 as part of the tests
- for libintl
-
-lib/malloc/malloc.c
- - internal_free: don't use the cached value of memtop when deciding
- whether or not to adjust the break and give memory back to the kernel
- when using the GNU C library, since glibc uses sbrk for its own
- internal purposes. From Debian bug 614815, reported by Samuel
- Thibault <samuel.thibault@gnu.org>
-
-aclocal.m4
- - BASH_STRUCT_WEXITSTATUS_OFFSET: change AC_RUN_IFELSE to AC_TRY_RUN
- to avoid warning about not using AC_LANG_SOURCE
-
- 5/14
- ----
-bashline.[ch]
- - two new functions, bashline_set_event_hook and bashline_reset_event_hook,
- to set rl_event_hook to bash_event_hook and back to NULL, respectively
- - don't set rl_event_hook unconditionally
-
-sig.c
- - termsig_sighandler: if the shell is currently interactive and
- readline is active, call bashline_set_event_hook to cause
- termsig_handler to be called via bash_event_hook when the shell
- returns from the signal handler
-
- 5/15
- ----
-lib/readline/display.c
- - _rl_col_width: Mac OS X has a bug in wcwidth: it does not return 0
- for UTF-8 combining characters. Added workaround dependent on
- MACOSX. Fixes problem pointed out by Thomas De Contes
- <d.l.tDecontes@free.fr>
-
- 5/16
- ----
-lib/readline/rlmbutil.h
- - WCWIDTH: wrapper for wcwidth that returns 0 for Unicode combining
- characters on systems where wcwidth is broken (e.g., Mac OS X).
-
-lib/readline/{complete,display,mbutil}.c
- - use WCWIDTH instead of wcwidth
-
- 5/17
- ----
-lib/readline/display.c
- - update_line: after computing ofd and nfd, see whether the next
- character in ofd is a zero-width combining character. If it is,
- back ofd and nfd up one, so the base characters no longer compare
- as equivalent. Fixes problem reported by Keith Winstein
- <keithw@mit.edu>
-
-lib/readline/nls.c
- - _rl_utf8locale: new flag variable, set to non-zero if the current
- locale is UTF-8
- - utf8locale(): new function, returns 1 if the passed lspec (or the
- current locale) indicates that the locale is UTF-8. Called from
- _rl_init_eightbit
-
-lib/readline/rlprivate.h
- - extern declaration for _rl_utf8locale
-
-locale.c
- - locale_utf8locale: new flag variable, set to non-zero if the current
- locale is UTF-8 (currently unused)
- - locale_isutf8(): new function, returns 1 if the passed lspec (or the
- current locale) indicates that the locale is UTF-8. Should be called
- whenever the locale or LC_CTYPE value is modified
-
-aclocal.m4
- - BASH_WCWIDTH_BROKEN: new test for whether or not wcwidth returns
- zero-width characters like unicode combining characters as having
- display length 1; define WCWIDTH_BROKEN in this case
-
-config.h.in
- - WCWIDTH_BROKEN: new define
-
-lib/readline/rlmbutil.h
- - change WCWIDTH macro to use _rl_utf8locale and the full range of
- Unicode combining characters (U+0300-U+036F)
-
- 5/19
- ----
-lib/readline/rlprivate.h
- - _rl_search_context: new member, prevc, will hold character read
- prior to lastc
-
-lib/readline/isearch.c
- - _rl_isearch_dispatch: if the character causes us to index into
- another keymap, save that character in cxt->prevc
- - _rl_isearch_dispatch: if we index into another keymap, but don't
- find a function that's special to i-search, and the character that
- caused us to index into that keymap would have terminated the
- search, push back cxt->prevc and cxt->lastc to make it appear as
- if `prevc' terminated the search, and execute lastc as a command.
- We have to push prevc back so we index into the same keymap before
- we read lastc. Fixes bug report from Davor Cubranic
- <cubranic@stat.ubc.ca>
-
- 5/20
- ----
-expr.c
- - expr_bind_variable: pay attention to the return value from
- bind_variable and check whether or not we should error out due to
- a readonly or noassign variable. Fixes bug reported by Eric
- Blake <eblake@redhat.com>
-
- 5/26
- ----
-
-lib/readline/search.c
- - include histlib.h for ANCHORED_SEARCH defines
- - rl_history_search_flags: new variable, holds ANCHORED_SEARCH flag for
- the duration of a history search
- - rl_history_search_reinit: takes a new flags variable, defines whether
- or not the search is anchored; assigned to rl_history_search_flags
- - rl_history_serarch_reinit: if ANCHORED_SEARCH flag passed, add ^ to
- beginning of search string; otherwise search string is unmodified
- - rl_history_search_internal: set rl_point appropriately based on
- whether or not rl_history_search_flags includes ANCHORED_SEARCH
- - rl_history_substr_search_forward: new function, for non-anchored
- substring search forward through history for string of characters
- preceding rl_point
- - rl_history_substr_search_backward: new function, for non-anchored
- substring search backward through history for string of characters
- preceding rl_point. Original code from Niraj Kulkarni
- <kulkarniniraj14@gmail.com>
-
-lib/readline/readline.h
- - extern declarations for rl_history_substr_search_{for,back}ward
-
-lib/readline/funmap.c
- - history-substring-search-forward: new bindable command, invokes
- rl_history_substr_search_forward
- - history-substring-search-backward: new bindable command, invokes
- rl_history_substr_search_backward
-
-lib/readline/doc/{rluser.texi,readline.3}
- - document history-substring-search-forward and
- history-substring-search-backward
-
- 5/27
- ----
-{nojobs,jobs}.c
- - add support for DONT_REPORT_SIGTERM so that the shell doesn't print
- a message when a job exits due to SIGTERM since that's the default
- signal sent by the kill builtin. Suggested by Marc Herbert
- <mark.herbert@gmail.com>
-
-config-top.h
- - DONT_REPORT_SIGTERM: new user-modifiable setting. Commented out
- by default
-
- 5/28
- ----
-lib/readline/bind.c
- - _rl_skip_to_delim: skip to a closing double quote or other delimiter,
- allowing backslash to quote any character, including the delimiter
- - rl_parse_and_bind: call _rl_skip_to_delim instead of using inline
- code
- - rl_parse_and_bind: allow quoted strings as the values of string
- variables. Variable values without double quotes have trailing
- whitespace removed (which still allows embedded whitespace, for
- better or worse). Fixes problem with string variables not matching
- in `set' command if values happen to have trailing spaces or tabs
- (debian bash bug #602762), but introduces slight incompatibility.
-
- 5/29
- ----
-doc/{bash.1,bashref.texi}
- - clarify unset description to specify that without options, a
- variable, then a shell function if there is no variable by that
- name, is unset. Fixes discrepancy reported by Mu Qiao
- <qiaomuf@gentoo.org>
-
- 6/4
- ----
-doc/{bash.1,bashref.texi}
- - clarify description of LINES and COLUMNS (and checkwinsize shopt
- option) to make it clear that only interactive shells set a
- handler for SIGWINCH and update LINES and COLUMNS. Original
- report submitted by Jonathan Nieder <jrnieder@gmail.com>
-
-arrayfunc.c
- - expand_compound_array_assignment: defer expansion of words between
- parens when performing compound assignmnt to an associative array
- variable
- - assign_compound_array_list: perform the same expansions when doing
- a compound array assignment to an associative array variable as
- when doing a straight array index assignment. The idea is that
- foo=( [ind1]=bar [ind2]=quux)
- is the same as
- foo[ind1]=bar ; foo[ind2]=quux
-
- This fixes problems with double-expansion and quote removal being
- performed on the array indices
-
- 6/13
- ----
-doc/{bash.1,bashref.texi}
- - Add a little text to make it clear that the locale determines how
- range expressions in glob patterns are handled.
-
-
- 6/21
- ----
-builtins/read.def
- - display a message and return error status if -a is used with an
- existing associative array. Fixes bug reported by Curtis Doty
- <curtis@greenkey.net>
-
- 6/24
- ----
-{jobs,nojobs}.c
- - non-interactive shells now react to the setting of checkwinsize
- and set LINES and COLUMNS after a foreground job exits. From a
- suggestion by Leslie Rhorer <lrhorer@satx.rr.com>
-
-doc/{bash.1,bashref.texi}
- - checkwinsize: remove language saying that only interactive shells
- check the window size after each command
-
-lib/readline/histfile.c
- - history_backupfile: new file, creates a backup history file name
- given a filename (appending `-')
- - history_do_write: when overwriting the history file, back it up
- before writing. Restore backup file on a write error. Suggested
- by chkno@chkno.net
-
-bashline.c
- - find_cmd_name: two new arguments, return the start and end of the
- actual text string used to find the command name, without taking
- whitespace into account
- - attempt_shell_completion: small changes to make sure that completion
- attempted at the beginning of a non-empty line does not find a
- programmable completion, even if the command name starts at point
- - attempt_shell_completion: small change to make sure that completion
- does not find a progcomp when in whitespace before the command
- name
- - attempt_shell_completion: small change to make sure that completion
- does not find a progcomp when point is at the first character of a
- command name, even when there is leading whitespace (similar to
- above). Fixes problems noted by Ville Skytta <ville.skytta@iki.fi>
-
-subst.c
- - brace_expand_word_list: since the individual strings in the strvec
- returned by brace_expand are already allocated, don't copy them to
- newly-allocated memory when building the WORD_LIST, just use them
- intact
-
-locale.c
- - locale_mb_cur_max: cache value of MB_CUR_MAX when we set or change
- the locale to avoid a function call every time we need to read it
-
-shell.h
- - new struct to save shell_input_line and associated variables:
- shell_input_line_state_t
- - add members of sh_parser_state_t to save and restore token and the
- size of the token buffer
-
-parse.y
- - {save,restore}_input_line_state: new functions to save and restore
- shell_input_line and associated variables
- - {save,restore}_parser_state: add code to save and restore the token
- and token buffer size
- - xparse_dolparen: call save_ and restore_input_line_state to avoid
- problems with overwriting shell_input_line when we recursively
- call the parser to parse a command substitution. Fixes bug
- reported by Rui Santos <rsantos@grupopie.com>
-
-include/shmbutil.h
- - use locale_mb_cur_max instead of MB_CUR_MAX in ADVANCE_CHAR and
- similar macros
-
-lib/glob/smatch.c
- - rangecmp,rangecmp_wc: change to take an additional argument, which
- forces the use of strcoll/wscoll when non-zero. If it's 0, a new
- variable `glob_asciirange' controls whether or not we use strcoll/
- wscoll. If it's non-zero, we use straight C-locale-like ordering.
- Suggested by Aharon Robbins <arnold@skeeve.com>
-
- 6/30
- ----
-execute_cmd.c
- - execute_pipeline: make sure the lastpipe code is protected by
- #ifdef JOB_CONTROL. Fixes problem reported by Thomas Cort
- <tcort@minix3.org>
-
- 7/2
- ---
-lib/readline/complete.c
- - EXPERIMENTAL: remove setting of _rl_interrupt_immediately around
- completion functions that touch the file system. Idea from Jan
- Kratochvil <jan.ktratochvil@redhat.com> and the GDB development
- team
-
-lib/readline/signals.c
- - rl_signal_handler: if we're in callback mode, don't interrupt
- immediately on a SIGWINCH
-
- 7/3
- ---
-bashline.c
- - set_directory_hook: and its siblings are a new set of functions to
- set, save, and restore the appropriate directory completion hook
- - change callers to use {set,save,restore}_directory_hook instead of
- manipulating rl_directory_rewrite_hook directly
- - dircomplete_expand: new variable, defaults to 0, if non-zero causes
- directory names to be word-expanded during word and filename
- completion
- - change {set,save,restore}_directory_hook to look at dircomplete_expand
- and change rl_directory_completion_hook or rl_directory_rewrite_hook
- appropriately
-
-bashline.h
- - extern declaration for set_directory_hook so shopt code can use it
-
- 7/6
- ---
-builtins/shopt.def
- - globasciiranges: new settable shopt option, makes glob ranges act
- as if in the C locale (so b no longer comes between A and B).
- Suggested by Aharon Robbins <arnold@skeeve.com>
-
- 7/7
- ---
-doc/{bash.1,bashref.texi}
- - document new `globasciiranges' shopt option
-
- 7/8
- ---
-builtins/shopt.def
- - direxpand: new settable option, makes filename completion expand
- variables in directory names like bash-4.1 did.
- - shopt_set_complete_direxpand: new function, does the work for the
- above by calling set_directory_hook
-
-doc/{bash.1,bashref.texi}
- - document new `direxpand' shopt option
-
- 7/15
- ----
-lib/readline/isearch.c
- - _rl_isearch_dispatch: when adding character to search string, use
- cxt->lastc (which we use in the switch statement) instead of c,
- since lastc can be modified earlier in the function
-
- 7/18
- ----
-lib/readline/rlprivate.h
- - _rl_search_context: add another member to save previous value of
- (multibyte) lastc: pmb is to mb as prevc is to lastc
-
-lib/readline/isearch.c:
- - _rl_isearch_dispatch: if a key sequence indexes into a new keymap,
- but doesn't find any bound function (k[ind].function == 0) or is
- bound to self-insert (k[ind].function == rl_insert), back up and
- insert the previous character (the one that caused the index into a
- new keymap) and arrange things so the current character is the next
- one read, so both of them end up in the search string. Fixes bug
- reported by Clark Wang <dearvoid@gmail.com>
- - _rl_isearch_dispatch: a couple of efficiency improvements when adding
- characters to the isearch string
-
- 7/24
- ----
-lib/readline/isearch.c
- - _rl_isearch_dispatch: save and restore cxt->mb and cxt->pmb
- appropriately when in a multibyte locale
-
-doc/{bash.1,bashref.texi}
- - correct description of {x}>file (and other redirection operators
- that allocate a file descriptor) to note the the fd range is
- greater than or equal to 10. Fixes problem reported by
- Christian Ullrich
-
-lib/readline/signals.c
- - rl_signal_handler: don't interrupt immediately if in callback mode
-
-lib/readline/callback.c
- - rl_callback_read_char: install signal handlers only when readline
- has control in callback mode, so readline's signal handlers aren't
- called when the application is active (e.g., between the calls to
- rl_callback_handler_install and rl_callback_read_char). If the
- readline signal handlers only set a flag, which the application
- doesn't know about, the signals will effectively be ignored until
- the next time the application calls into the readline callback
- interface. Fixes problem of calling unsafe functions from signal
- handlers when in callback mode reported by Jan Kratochvil
- <jan.kratochvil@redhat.com>
-
-execute_cmd.c
- - fix_assignment_words: when in Posix mode, the `command' builtin
- doesn't change whether or not the command name it protects is an
- assignment builtin. One or more instances of `command'
- preceding `export', for instance, doesn't make `export' treat its
- assignment statement arguments differently. Posix interpretation
- #351
-
-doc/{bash.1,bashref.texi}
- - document new Posix-mode behavior of `command' when preceding builtins
- that take assignment statements as arguments
-
-builtins/printf.def
- - printstr: if fieldwidth or precision are < 0 or > INT_MAX when
- supplied explicitly (since we take care of the `-' separately),
- clamp at INT_MAX like when using getint(). Fixes issue reported
- by Ralph Coredroy <ralph@inputplus.co.uk>
-
- 7/25
- ----
-lib/readline/chardefs.h
- - isxdigit: don't define if compiling with c++; declared as a c++
- template function. Fixes bug reported by Miroslav Lichvar
- <mlichvar@redhat.com>
-
-builtins/printf.def
- - getint: if garglist == 0, return whatever getintmax returns (0).
- Fixes bug reported by Ralph Coredroy <ralph@inputplus.co.uk>
-
- 7/28
- ----
-doc/{bash.1,bashref.texi}
- - minor changes to the descriptions of the cd and pushd builtins
-
-lib/sh/zread.c
- - zsyncfd: change variable holding return value from lseek to
- off_t. Bug report and fix from Gregory Margo <gmargo@pacbell.net>
-
- 8/1
- ---
-expr.c
- - don't check for division by 0 when in a context where no evaluation
- is taking place. Fixes bug reported by dnade.ext@orange-ftgroup.com
-
- 8/6
- ---
-execute_cmd.c
- - execute_command_internal: the parent branch of the subshell code
- (where the child calls execute_in_subshell) should not close all
- open FIFOs with unlink_fifo_list if it's part of a shell function
- that's still executing. Fixes bug reported by Maarten Billemont
- <lhunath@lyndir.com>
-
- 8/9
- ---
-builtins/common.c
- - get_exitstat: return EX_BADUSAGE (2) on a non-numeric argument
-
-builtins/return.def
- - return_builtin: just call get_exitstat to get the return status,
- let it handle proper parsing and handling of arguments. Fixes
- issue most recently raised by Linda Walsh <bash@tlinx.org>.
- Reverses change from 9/11/2008 (see above)
-
- 8/16
- ----
-doc/{bash.1,bashref.texi}
- - clean up `set -e' language to make it clearer that any failure of
- a compound command will cause the shell to exit, not just subshells
- and brace commands
-
- 8/17
- ----
-configure.in
- - make the various XXX_FOR_BUILD variables `precious' to autoconf to
- avoid stale data
- - change how CC_FOR_BUILD is initialized when cross-compiling and not,
- but do not change behavior
- - initialize CFLAGS_FOR_BUILD to -g when cross-compiling
- - initialize LIBS_FOR_BUILD to $(LIBS) when not cross-compiling, empty
- when cross-compiling
- - create AUTO_CFLAGS variable to hold basic CFLAGS defaults; used when
- CFLAGS not inherited from environment (like effect of old
- auto_cflags variable)
- - substitute LIBS_FOR_BUILD into output Makefiles
- [changes inspired by bug report from Nathan Phillip Brink
- <ohnobinki@ohnopublishing.net> -- gentoo bug 378941]
-
-builtins/Makefile.in
- - substitute LIBS_FOR_BUILD from configure, not strictly initialized
- to $(LIBS)
-
- 8/27
- ----
-doc/{bash.1,bashref.texi}
- - minor changes to the here string description to clarify the
- expansions performed on the word
-
-support/shobj-conf
- - handle compilation on Lion (Mac OS X 10.7/darwin11) with changes
- to darwin stanzas. Fixes readline bug reported by Vincent
- Sheffer <vince.sheffer@apisphere.com>
-
-lib/sh/strtrans.c
- - ansic_wshouldquote: check a string with multi-byte characters for
- characters that needs to be backslash-octal escaped for $'...'
- - ansic_shouldquote: if is_basic fails for one character, let
- ansic_wshouldquote examine the rest of the string and return what
- it returns. From a patch sent by Roman Rakus <rrakus@redhat.com>
-
- 8/30
- ----
-lib/sh/strtrans.c
- - ansic_quote: changes to quote (or not) multibyte characters. New
- code converts them to wide characters and uses iswprint to check
- valid wide chars. From a patch sent by Roman Rakus
- <rrakus@redhat.com>
-
- 9/7
- ---
-lib/sh/shquote.c
- - sh_backslash_quote: change to be table-driven so we can use a
- different table if we want to
- - sh_backslash_quote: takes a second char table[256] argument;
-
-externs.h
- - sh_backslash_quote: add second argument to function prototype
-
-bashline.c,braces.c,parse.y,builtins/printf.def
- - change callers of sh_backslash_quote to add second argument
-
-bashline.c
- - filename_bstab: table of characters to pass to sh_backslash_quote;
- characters with value 1 will be backslash-quoted
- - set_filename_bstab: turn on characters in filename backslash-quote
- table according to passed string argument
- - call set_filename_bstab every time rl_filename_quote_characters is
- assigned a value
- - bash_quote_filename: call sh_backslash_quote with filename_bstab
- as second argument. This allows other characters in filenames to
- be quoted without quoting, for instance, a dollar sign in a shell
- variable reference
-
- 9/8
- ---
-bashline.c
- - complete_fullquote: new variable, controls table passed to
- sh_backslash_quote. If non-zero (the default), the standard set
- of shell metacharacters -- as in bash versions up to and including
- bash-4.2 -- gets backslash-quoted by the completion code. If zero,
- sh_backslash_quote gets the table with the characters in the
- variable reference removed, which means they are removed from the
- set of characters to be quoted in filenames
-
- 9/10
- ----
-bashline.c
- - bash_filename_stat_hook: new function, designed to expand variable
- references in filenames before readline passes them to stat(2)
- to determine whether or not they are a directory
-
- 9/15
- ----
-builtins/declare.def
- - if assign_array_element fails due to a bad (or empty) subscript, mark
- it as an assignment error and don't attempt any further processing
- of that declaration. Fixes segfault bug reported by Diego Augusto
- Molina <diegoaugustomolina@gmail.com>
-
- 9/19
- ----
-expr.c
- - exppower: replace the simple exponentiation algorithm with an
- implementation of exponentiation by squaring. Inspired by report
- from Nicolas ARGYROU <nargy@yahoo.com>
-
-bashline.c
- - bash_quote_filename: check for rtext being non-null before
- dereferencing it
- - set_saved_history: operate_and_get_next assumes that the previous
- line was added to the history, even when the history is stifled and
- at the max number of entries. If it wasn't, make sure the history
- number is incremented properly. Partial fix for bug reported by
- gregrwm <backuppc-users@whitleymott.net>
-
-doc/{bash.1,bashref.texi},lib/readline/doc/{hsuser,rluser}.texi
- - minor editorial changes inspired by suggestions from
- Roger Zauner <rogerx.oss@gmail.com>
-
- 9/20
- ----
-lib/intl/localealias.c
- - read_alias_file: close resource leak (fp) when returning on error
-
- 9/22
- ----
-execute_command.c
- - execute_intern_function: implement Posix interpretation 383 by making
- it an error to define a function with the same name as a special
- builtin when in Posix mode.
- http://austingroupbugs.net/view.php?id=383#c692
-
- 9/25
- ----
-doc/{bash.1,bashref.texi}
- - formatting and some content changes from Benno Schulenberg
- <bensberg@justemail.net>
- - document new posix-mode behavior from interp 383 change of 9/22
-
- 9/30
- ----
-execute_cmd.c
- - shell_execve: add strerror to error message about executable file
- that shell can't execute as a shell script. From suggestion by
- daysleeper <daysleeper@centrum.cz>
-
- 10/1
- ----
-bashhist.c
- - maybe_add_history: act as if literal_history is set when parser_state
- includes PST_HEREDOC, so we save the bodies of here-documents just
- as they were entered. Fixes bug reported by Jonathan Wakely
- <bugs@kayari.org>
- - bash_add_history: make sure that the second and subsequent lines of
- a here document don't have extra newlines or other delimiting
- chars added, since they have the trailing newline preserved, when
- `lithist' is set and history_delimiting_chars isn't called
-
-execute_cmd.c
- - execute_command_internal: avoid fd exhaustion caused by using
- process substitution in loops inside shell functions by using
- copy_fifo_list and close_new_fifos (). Fixes debian bash bug
- 642504
-
-lib/readline/complete.c
- - new variable, rl_filename_stat_hook, used by append_to_match. If
- filename completion is desired, and rl_filename_stat_hook points
- to a function, call that function to expand the filename in an
- application-specific way before calling stat.
-
-bashline.c
- - bash_default_completion: if variable completion returns a single
- match, use bash_filename_stat_hook and file_isdir to determine
- whether or not the variable name expands to a directory. If it
- does, set the filename_append_character to `/'. This is not
- perfect, so we will see how it works out. Adds functionality
- requested by Peter Toft <pto@linuxbog.dk> and Patrick Pfeifer
- <patrick@pfeifer.de>
- - rl_filename_stat_hook: assigned bash_filename_stat_hook, so things
- like $HOME/Downloads (after completion) have a slash appended.
- In general, this causes the stat hook to be called whenever
- filename completion is appended. Adds functionality requested by
- Patrick Pfeifer <patrick@pfeifer.de>
-
-lib/readline/readline.h
- - new extern declaration for rl_filename_stat_hook
-
-lib/readline/doc/rltech.texi
- - rl_directory_rewrite_hook: now documented
- - rl_filename_stat_hook: document
-
-pcomplete.c
- - gen_action_completions: in the CA_DIRECTORY case, turn off
- rl_filename_completion_desired if it was off before we called
- rl_filename_completion_function and we didn't get any matches.
- Having it on causes readline to quote the matches as if they
- were filenames. Adds functionality requested by many,
- including Clark Wang <dearvoid@gmail.com>
-
-assoc.[ch]
- - assoc_replace: new function, takes the same arguments as
- assoc_insert, but returns the old data instead of freeing it
- - assoc_insert: if the object returned by hash_insert doesn't have
- the same value for its key as the key passed as an argument, we
- are overwriting an existing value. In this case, we can free the
- key. Fixes bug reported by David Parks <davidparks21@yahoo.com>
-
- 10/5
- ----
-print_cmd.c
- - indirection_level_string: small change to only re-enable `x'
- option after calling decode_prompt_string if it was on before. In
- normal mode, it will be, but John Reiser <jreiser@bitwagon.com>
- has a novel use for that code in conjunction with a pre-loaded
- shared library that traces system call usage in shell scripts
-
- 10/10
- -----
-Makefile.in
- - Fix from Mike Frysinger <vapier@gentoo.org> to avoid trying to
- build y.tab.c and y.tab.h with two separate runs of yacc if
- parse.y changes. Problem with parallel makes
- - Fix from Mike Frysinger <vapier@gentoo.org> to avoid subdirectory
- builds each trying to make version.h (and all its dependencies)
-
-lib/sh/Makefile.in
- - remove some dependencies on version.h where it doesn't make sense
-
-variables.c
- - initialize_shell_variables: while reading the environment, a shell
- running in posix mode now checks for SHELLOPTS being readonly (it
- gets set early on in main()) before trying to assign to it. It
- saves an error message and the variable gets parsed as it should.
- Fixes bug reported by Len Giambrone <Len.Giambrone@intersystems.com>
-
- 10/14
- -----
-doc/{bash.1,bashref.texi}
- - add to the "duplicating file descriptors" description that >&word
- doesn't redirect stdout and stderr if word expands to `-'
- - add to the "appending standard output and standard error"
- description a note that >&word, where word is a number or `-',
- causes other redirection operators to apply for sh and Posix
- compatibility reasons. Suggested by Greg Wooledge
- <wooledg@eeg.ccf.org>
-
- 10/15
- -----
-pcomplete.c
- - change pcomp_filename_completion_function to only run the filename
- dequoting function in the cases (as best as it can figure) where
- readline won't do it via rl_filename_completion_function. Based
- on reports from <lolilolicon@gmail.com>
-
- 10/19
- -----
-bashline.c
- - attempt_shell_completion: add call to set_directory_hook() to make
- sure the rewrite functions are correct. It's cheap and doesn't
- hurt
- - command_word_completion_function: if completing a command name that
- starts with `.' or `..', temporarily suppress the effects of the
- `direxpand' option and restore the correct value after calling
- rl_filename_completion_function. If it's enabled, the directory
- name will be rewritten and no longer match `./' or `../'. Fixes
- problem reported by Michael Kalisz <michael@kalisz.homelinux.net>
-
- 10/22
- -----
-builtins/history.def
- - push_history: make sure remember_on_history is enabled before we
- try to delete the last history entry -- the `history -s' command
- might not have been saved. Fixes bug reported by
- lester@vmw-les.eng.vmware.com
-
-lib/readline/complete.c
- - rl_callback_read_char: add calls to a macro CALLBACK_READ_RETURN
- instead of straight return; add same call at end of function.
- Placeholder for future work in deinstalling signal handlers when
- readline is not active
-
- 10/25
- -----
-expr.c
- - exp2: catch arithmetic overflow when val1 == INTMAX_MIN and val2 == -1
- for DIV and MOD and avoid SIGFPE. Bug report and pointer to fix
- from Jaak Ristioja <jaak.ristioja@cyber.ee>
- - expassign: same changes for arithmetic overflow for DIV and MOD
-
- 10/28
- -----
-subst.c
- - parameter_brace_expand: allow pattern substitution when there is an
- expansion of the form ${var/} as a no-op: replacing nothing with
- nothing
- - parameter_brace_patsub: don't need to check for PATSUB being NULL;
- it never is
-
-flags.c
- - if STRICT_POSIX is defined, initialize history_expansion to 0, since
- history expansion (and its treatment of ! within double quotes) is
- not a conforming posix environment. From austin-group issue 500
-
-lib/readline/histexpand.c
- - history_expand: when processing a string within double quotes
- (DQUOTE == 1), make the closing double quote inhibit history
- expansion, as if the word were outside double quotes. In effect,
- we assume that the double quote is followed by a character in
- history_no_expand_chars. tcsh and csh seem to do this. This
- answers a persistent complaint about history expansion
-
- 10/29
- -----
-make_cmd.c
- - make_arith_for_command: use skip_to_delim to find the next `;'
- when breaking the string between the double parens into three
- separate components instead of a simple character loop. Fixes
- bug reported by Dan Douglas <ormaaj@gmail.com>
-
- 11/2
- ----
-Makefile.in
- - make libbuiltins.a depend on builtext.h to serialize its creation
- and avoid conflict between multiple invocations of mkbuiltins.
- Fix from Mike Frysinger <vapier@gentoo.org>
-
- 11/5
- ----
-findcmd.c
- - user_command_matches: if stat(".", ...) returns -1, set st_dev
- and st_ino fields in dotinfo to 0 to avoid same_file matches
- - find_user_command_in_path: check stat(2) return the same way
-
-lib/glob/glob.c
- - glob_vector: don't call strlen(pat) without checking pat == 0
- - glob_dir_to_array: make sure to free `result' and all allocated
- members before returning error due to malloc failure
- - glob_vector: make sure to free `nextname' and `npat' on errors
- (mostly when setting lose = 1)
- - glob_vector: if flags & GX_MATCHDIRS but not GX_ALLDIRS, make
- sure we free `subdir'
- - glob_filename: when expanding ** (GX_ALLDIRS), make sure we
- free temp_results (return value from glob_vector)
-
-lib/glob/xmbsrtowcs.c
- - xdupmbstowcs: fix call to realloc to use sizeof (char *) instead
- of sizeof (char **) when assigning idxtmp
-
-execute_cmd.c
- - print_index_and_element: return 0 right away if L == 0
- - is_dirname: fix memory leak by freeing `temp'
- - time_command: don't try to deref NULL `command' when assigning
- to `posix_time'
- - shell_execve: null-terminate `sample' after READ_SAMPLE_BUF so it's
- terminated for functions that expect that
-
-builtins/read.def
- - read_builtin: don't call bind_read_variable with a potentially-null
- string
-
-pcomplete.c
- - gen_command_matches: don't call dispose_word_desc with a NULL arg
- - gen_compspec_completions: fix memory leak by freeing `ret' before
- calling gen_action_completions (tcs, ...). happens when
- performing directory completion as default and no completions
- have been generated
- - gen_progcomp_completions: make sure to set foundp to 0 whenever
- returning NULL
- - it_init_aliases: fix memory leak by freeing alias_list before
- returning
-
-bashline.c
- - command_word_completion_function: don't call restore_tilde with a
- NULL directory_part argument
- - bash_directory_expansion: bugfix: don't throw away results of
- rl_directory_rewrite_hook if it's set and returns non-zero
- - bind_keyseq_to_unix_command: free `kseq' before returning error
-
-arrayfunc.c
- - assign_array_element_internal: make sure `akey' is freed if non-null
- before returning error
- - assign_compound_array_list: free `akey' before returning error
- - array_value_internal: free `akey' before returning error
- - unbind_array_element: free `akey' before returning error
-
-subst.c
- - array_length_reference: free `akey' before returning error in case
- of expand_assignment_string_to_string error
- - array_length_reference: free `akey' after call to assoc_reference
- - skip_to_delim: if skipping process and command substitution, free
- return value from extract_process_subst
- - parameter_brace_substring: free `val' (vtype == VT_VARIABLE) before
- returning if verify_substring_values fails
- - parameter_brace_expand: remove two duplicate lines that allocate
- ret in parameter_brace_substring case
- - parameter_brace_expand: convert `free (name); name = xmalloc (...)'
- to use `xrealloc (name, ...)'
- - parameter_brace_expand: free `name' before returning when handling
- ${!PREFIX*} expansion
- - split_at_delims: fix memory leak by freeing `d2' before returning
-
-redir.c
- - redirection_error: free `filename' if the redirection operator is
- REDIR_VARASSIGN by assigning allocname
-
-eval.c
- - send_pwd_to_eterm: fix memory leak by freeing value returned by
- get_working_directory()
-
-builtins/cd.def
- - change_to_directory: fix memory leak by freeing return value from
- resetpwd()
- - cd_builtin: fix memory leak by freeing value returned by dirspell()
- - cd_builtin: fix memory leak by freeing `directory' if appropriate
- before overwriting with return value from resetpwd()
-
-builtins/type.def
- - describe_command: free `full_path' before overwriting it with return
- value from sh_makepath
-
-builtins/complete.def
- - compgen_builtin: fix memory leak by calling strlist_dispose (sl)
- before overwriting sl with return value from completions_to_stringlist
-
-builtins/hash.def
- - list_hashed_filename_targets: fix memory leak by freeing `target'
-
-make_cmd.c
- - make_arith_for_command: free `init', `test', and `step' before
- returning error on parse error
-
-jobs.c
- - initialize_job_control: don't call move_to_high_fd if shell_tty == -1
-
-general.c
- - check_dev_tty: don't call close with an fd < 0
- - legal_number: deal with NULL `string' argument, return invalid
-
-lib/sh/fmtulong.c
- - fmtulong: if the `base' argument is invalid, make sure we index
- buf by `len-1' at maximum
-
-print_cmd.c
- - print_deferred_heredocs: don't try to dereference a NULL `cstring'
- - cprintf: make sure to call va_end (args)
-
-variables.c
- - push_dollar_vars: fix call to xrealloc to use sizeof (WORD_LIST *)
- instead of sizeof (WORD_LIST **)
-
-lib/sh/zmapfd.c
- - zmapfd: if read returns error, free result and return -1 immediately
- instead of trying to reallocate it
-
- 11/6
- ----
-execute_cmd.c
- - cpl_reap: rewrote to avoid using pointer after freeing it; now builds
- new coproc list on the fly while traversing the old one and sets the
- right values for coproc_list when done
-
- 11/12
- -----
-builtins/set.def
- - if neither -f nor -v supplied, don't allow a readonly function to
- be implicitly unset. Fixes bug reported by Jens Schmidt
- <jens.schmidt35@arcor.de>
-
-lib/readline/callback.c
- - change CALLBACK_READ_RETURN to clear signal handlers before returning
- from rl_callback_read_char so readline's signal handlers aren't
- installed when readline doesn't have control. Idea from Jan
- Kratochvil <jan.ktratochvil@redhat.com> and the GDB development
- team
-
-pcomplete.h
- - COPT_NOQUOTE: new complete/compgen option value
-
-builtins/complete.def
- - noquote: new complete/compgen option; will be used to disable
- filename completion quoting
-
-pcomplete.c
- - pcomp_set_readline_variables: pay attention to COPT_NOQUOTE; turns
- of rl_filename_quoting_desired if set; turns it on if unset (value
- is inverted, since default is on)
-
-doc/bash.1,lib/readline/doc/rluser.texi
- - document new -o noquote option to complete/compgen/compopt
-
-pathexp.c
- - quote_string_for_globbing: if QGLOB_REGEXP, make sure characters
- between brackets in an ERE bracket expression are not inappropriately
- quoted with backslashes. This is a pretty substantial change,
- should be stressed when opening bash up for alpha and beta tests.
- Fixes bug pointed out by Stephane Chazleas
- <stephane_chazelas@yahoo.fr>
-
-doc/{bash.1,bashref.texi}
- - document that regexp matches can be inconsistent when quoting
- characters in bracket expressions, since usual quoting characters
- lose their meaning within brackets
- - note that regular expression matching when the pattern is stored
- in a shell variable which is quoted for expansion causes string
- matching
-
-redir.h
- - RX_SAVEFD: new flag value; notes that a redirection denotes an
- fd used to save another even if it's not >= SHELL_FD_BASE
-
-redir.c
- - do_redirection_internal: when deciding whether or not to reset the
- close-on-exec flag on a restored file descriptor, trust the value
- of redirect->flags & RX_SAVCLEXEC even if the fd is < SHELL_FD_BASE
- if the RX_SAVEFD flag is set
- - add_undo_redirect: set the RX_SAVEFD flag if the file descriptor
- limit is such that the shell can't duplicate to a file descriptor
- >= 10. Fixes a limitation that tripped a coreutils test reported
- by Paul Eggert <eggert@cs.ucla.edu>
-
- 11/19
- -----
-doc/{bash.1,bashref.texi},lib/readline/doc/hsuser.texi
- - make it clear that bash runs HISTFILESIZE=$HISTSIZE after reading
- the startup files
- - make it clear that bash runs HISTSIZE=500 after reading the
- startup files
- - make it clear that setting HISTSIZE=0 causes commands to not be
- saved in the history list
- - make it clear that setting HISTFILESIZE=0 causes the history file
- to be truncated to zero size
-
-variables.c
- - sv_histsize: change so setting HISTSIZE to a value less than 0
- causes the history to be `unstifled'
- - sv_histsize: change so setting HISTFILESIZE to a value less than 0
- results in no file truncation
- - make it clear that numeric values less than 0 for HISTFILESIZE or
- HISTSIZE inhibit the usual functions
-
- 11/23
- -----
-parse.y
- - save_input_line_state: add missing `return ls' at the end, since the
- function is supposed to return its argument. Pointed out by
- Andreas Schwab <schwab@linux-m68k.org>
-
-builtins/read.def
- - skip over NUL bytes in input, as most modern shells seem to. Bug
- report by Matthew Story <matt@tablethotels.com>
-
-lib/readline/vi_mode.c
- - rl_vi_replace: set _rl_vi_last_key_before_insert to invoking key
-
- 11/25
- -----
-builtins/read.def
- - read_builtin: if xrealloc returns same pointer as first argument,
- don't bother with the remove_unwind_protect/add_unwind_protect pair
- - read_builtin: set a flag (`reading') around calls to zread/zreadc
- and readline()
- - sigalrm: change to set flag (`sigalrm_seen') and only longjmp if
- currently in read(2) (reading != 0)
- - CHECK_ALRM: new macro, checks sigalrm_seen and longjmps if non-zero,
- behavior of old SIGALRM catching function
- - read_builtin: call CHECK_ALRM in appropriate places while reading
- line of input. Fixes bug reported by Pierre Gaston
- <pierre.gaston@gmail.com>
-
-lib/readline/vi_mode.c
- - rl_vi_replace: initialize characters before printing characters in
- vi_replace_keymap to their default values in vi_insertion_keymap,
- since we're supposed to be in insert mode replacing characters
- - rl_vi_replace: call rl_vi_start_inserting to set last command to
- `R' for undo
- - rl_vi_replace: set _rl_vi_last_key_before_insert to `R' for future
- use by _rl_vi_done_inserting
- - vi_save_insert_buffer: new function, broke out code that copies text
- into vi_insert_buffer from _rl_vi_save_insert
- - _rl_vi_save_replace: new function, saves text modified by
- rl_vi_replace (using current point and vi_replace_count to figure
- it out) to vi_replace_buffer
- - _rl_vi_save_insert: call vi_save_insert_buffer
- - _rl_vi_done_inserting: if _rl_vi_last_key_before_insert == 'R', call
- _rl_vi_save_replace to save text modified in replace mode (uses
- vi_save_insert_buffer)
- - _rl_vi_replace_insert: new function, replaces the number of chars
- in vi_insert_buffer after rl_point with contents ov vi_insert_buffer
- - rl_vi_redo: call _rl_vi_replace_insert if last command == 'R' and
- there's something in vi_insert_buffer. Fixes bug with `.' not
- redoing the most recent `R' command, reported by Geoff Clare
- <g.clare@opengroup.org> in readline area on savannah
-
- 11/26
- -----
-lib/readline/rlprivate.h
- - RL_SIG_RECEIVED(): evaluate to non-zero if there is a pending signal
- to be handled
- - RL_SIGINT_RECEIVED(): evaluate to non-zero if there is a pending
- SIGINT to be handled
-
-lib/readline/complete.c
- - remove all mention of _rl_interrupt_immediately
- - rl_completion_matches: check RL_SIG_RECEIVED after each call to
- the entry function, call RL_CHECK_SIGNALS if true to handle the
- signal
- - rl_completion_matches: if RL_SIG_RECEIVED evaluates to true, free
- and zero out the match_list this function allocated
- - rl_completion_matches: if the completion entry function is
- rl_filename_completion_function, free the contents of match_list,
- because that function does not keep state and will not free the
- entries; avoids possible memory leak pointed out by
- Garrett Cooper <yanegomi@gmail.com>
- - gen_completion_matches: if RL_SIG_RECEIVED evalutes to true after
- calling rl_attempted_completion_function, free the returned match
- list and handle the signal with RL_CHECK_SIGNALS; avoids
- possible memory leak pointed out by Garrett Cooper
- <yanegomi@gmail.com>
- - gen_completion_matches: if RL_SIG_RECEIVED evaluates to true after
- calling rl_completion_matches, free the returned match list and
- handle the signal with RL_CHECK_SIGNALS
-
-lib/readline/util.c
- - rl_settracefp: new utility function to set the tracing FILE *
-
-lib/readline/signals.c
- - _rl_sigcleanup: pointer to a function that will be called with the
- signal and a void * argument from _rl_handle_signal
- - _rl_sigcleanarg: void * that the rest of the code can set to have
- passed to the signal cleanup function
- - _rl_handle_signal: if _rl_sigcleanup set, call as
- (*_rl_sigcleanup) (sig, _rl_sigcleanarg)
-
-lib/readline/rlprivate.h
- - extern declarations for _rl_sigcleanup and _rl_sigcleanarg
-
-lib/readline/complete.c
- - _rl_complete_sigcleanup: signal cleanup function for completion code;
- calls _rl_free_match_list on _rl_sigcleanarg if signal == SIGINT
- - rl_complete_internal: before calling display_matches if what_to_do
- == `?', set _rl_sigcleanup to _rl_complete_sigcleanup so the match
- list gets freed on SIGINT; avoids possible memory leak pointed out
- by Garrett Cooper <yanegomi@gmail.com>
- - rl_complete_internal: in default switch case, call _rl_free_match_list
- before returning to avoid memory leak
-
-doc/bashref.texi
- - start at a set of examples for the =~ regular expression matching
- operator, touching on keeping the pattern in a shell variable and
- quoting portions of the pattern to remove their special meaning
-
- 12/1
- ----
-lib/glob/gmisc.c
- - extglob_pattern: new function, returns 1 if pattern passed as an
- argument looks like an extended globbing pattern
-
-lib/glob/glob.c
- - skipname: return 0 immediately if extglob_pattern returns non-zero,
- let the extended globbing code do the right thing with skipping
- names beginning with a `.'
- - mbskipname: return 0 immediately if extglob_pattern returns non-zero,
- let the extended globbing code do the right thing with skipping
- names beginning with a `.'. Fixes bug reported by Yongzhi Pan
- <panyongzhi@gmail.com>
-
- 12/2
- ----
-lib/glob/smatch.c
- - patscan, patscan_wc: no longer static so other parts of the glob
- library can use them, renamed to glob_patscan, glob_patscan_wc
-
-lib/glob/glob.c
- - extern declarations for glob_patscan, glob_patscan_wc
- - wchkname: new function, does skipname on wchar_t pattern and dname,
- old body of mbskipname after converting to wide chars
- - extglob_skipname: new function, checks all subpatterns in an extglob
- pattern to determine whether or not a filename should be skipped.
- Calls skipname for each subpattern. Dname is only skipped if all
- subpatterns indicate it should be. Better fix for bug reported by
- Yongzhi Pan <panyongzhi@gmail.com>
- - wextglob_skipname: wide-char version of extglob_skipname, calls
- wchkname instead of calling back into mbskipname for each
- subpattern to avoid problems with char/wchar_t mismatch
- - skipname: call extglob_skipname if extglob_pattern returns non-zero
- - mbskipname: call wextglob_skipname if extglob_pattern returns non-zero
- - mbskipname: short-circuit immediately if no multibyte chars in
- pattern or filename
-
-execute_cmd.c
- - execute_cond_node: added parens to patmatch assignment statement to
- make intent clearer
-
- 12/3
- ----
-configure.in,config.h.in
- - check for imaxdiv, define HAVE_IMAXDIV if present
-
-expr.c
- - expassign, exp2: use imaxdiv if available. Doesn't help with checks
- for overflow from 10/25
-
- 12/6
- ----
-lib/readline/complete.c
- - compute_lcd_of_matches: if we're ignoring case in the matches, only
- use what the user typed as the lcd if it matches the first match
- (after sorting) up to the length of what was typed (if what the
- user typed is longer than the shortest of the possible matches, use
- the shortest common length of the matches instead). If it doesn't
- match, use the first of the list of matches, as if case were not
- being ignored. Fixes bug reported by Clark Wang
- <dearvoid@gmail.com>
-
- 12/7
- ----
-builtins/cd.def
- - cd_builtin: add code to return error in case cd has more than one
- non-option argument, conditional on CD_COMPLAINS define (which is
- not defined anywhere)
-
-doc/{bash.1,bashref.texi}
- - note that additional arguments to cd following the directory name
- are ignored. Suggested by Vaclav Hanzl <hanzl@noel.feld.cvut.cz>
-
- 12/10
- -----
-lib/readline/input.c
- - rl_read_key: don't need to increment key sequence length here; doing
- it leads to an off-by-one error
-
-lib/readline/macro.c
- - rl_end_kbd_macro: after off-by-one error with rl_key_sequence_length
- fixed, can decrement current_macro_index by rl_key_sequence_length
- (length of key sequence that closes keyboard macro)
-
-lib/readline/readline.c
- - _rl_dispatch_subseq: fix extra increment of rl_key_sequence_length
- when ESC maps to a new keymap and we're converting meta characters
- to ESC+key
- - _rl_dispatch_subseq: better increment of rl_key_sequence_length
- before we dispatch to a function in the ISFUNC case (where the
- second increment above should have happened)
- - rl_executing_keyseq: the full key sequence that ended up executing
- a readline command. Available to the calling application, maintained
- by _rl_dispatch_subseq, indexed by rl_key_sequence_length
- - rl_executing_key: the key that was bound to the currently-executing
- readline command. Same as the `key' argument to the function
-
-lib/readline/readline.h
- - rl_executing_keyseq: extern declaration
- - rl_executing_key: extern declaration
- - rl_key_sequence_length: declaration moved here from rlprivate.h,
- now part of public interface
-
-lib/readline/rlprivate.h
- - new extern declaration for _rl_executing_keyseq_size, buffer size
- for rl_executing_keyseq
-
-lib/readline/doc/rltech.texi
- - documented new variables: rl_executing_key, rl_executing_keyseq,
- rl_key_sequence_length
-
- 12/13
- -----
-bashline.c
- - bash_execute_unix_command: replace ad-hoc code that searches
- cmd_xmap for correct command with call to rl_function_of_keyseq
- using rl_executing_keyseq; now supports key sequences longer
- than two characters. Fixes bug reported by Michael Kazior
- <kazikcz@gmail.com>
-
- 12/15
- -----
-make_cmd.c
- - make_function_def: don't null out source_file before calling
- make_command so it can be used later on when the function definition
- is executed
-
-execute_cmd.c
- - execute_intern_function: second argument is now FUNCTION_DEF *
- instead of COMMAND *
- - execute_command_internal: call execute_intern_function with the
- new second argument (the entire FUNCTION_DEF instead of just the
- command member)
- - execute_intern_function: if DEBUGGER is defined, call
- bind_function_def before calling bind_function, just like
- make_function_def does (might be able to take out the call in
- make_function_def depending on what the debugger does with it).
- Fixes bug reported by <dethrophes@motd005>
-
-expr.c
- - more minor changes to cases of INTMAX_MIN % -1 and INTMAX_MIN / 1;
- fix typos and logic errors
-
- 12/16
- -----
-bashline.c
- - find_cmd_start: change flags to remove SD_NOSKIPCMD so it skips over
- command substitutions and doesn't treat them as command separators
- - attempt_shell_completion: instead of taking first return from
- find_cmd_name as command name to use for programmable completion,
- use loop to skip over assignment statements. Fixes problem reported
- by Raphael Droz <raphael.droz+floss@gmail.com>
- - attempt_shell_completion: if we don't find a command name but the
- command line is non-empty, assume the other words are all assignment
- statements and flag that point is in a command position so we can
- do command name completion
- - attempt_shell_completion: if the word being completed is the first
- word following a series of assignment statements, and the
- command line is non-empty, flag that point is in a command position
- so we can do command name completion
-
-lib/readline/history.c
- - history_get_time: atol -> strtol
-
- 12/18
- -----
-parse.y
- - parser_in_command_position: external interface to the
- command_token_position macro for use by other parts of the shell,
- like the completion mechanism
-
-externs.h
- - extern declaration for parser_in_command_position
-
- 12/19
- -----
-
-builtins/read.def
- - read_builtin: make sure all calls to bind_read_variable are passed
- a non-null string. Fixes bug reported by Dan Douglas
- <ormaaj@gmail.com>
-
-bashline.c
- - attempt_shell_completion: mark that we're in a command position if
- we're at the start of the line and the parser is ready to accept
- a reserved word or command name. Feature most recently suggested
- by Peng Yu <pengyu.ut@gmail.com>
-
- 12/21
- -----
-lib/readline/bind.c
- - _rl_escchar: return the character that would be backslash-escaped
- to denote the control character passed as an argument ('\n' -> 'n')
- - _rl_isescape: return 1 if character passed is one that has a
- backslash escape
- - _rl_untranslate_macro_value: new second argument: use_escapes, if
- non-zero translate to backslash escapes where possible instead of
- using straight \C-x for control character `x'. Change callers
- - _rl_untranslate_macro_value: now global
-
-lib/readline/rlprivate.h
- - _rl_untranslate_macro_value: extern declaration
-
-lib/readline/{macro.c,readline.h}
- - rl_print_last_kbd_macro: new bindable function, inspired by patch
- from Mitchel Humpherys
-
-lib/readline/funmap.c
- - print-last-kbd-macro: new bindable command, bound to
- rl_print_last_kbd_macro
-
-lib/readline/doc/{rluser.texi,readline.3},doc/bash.1
- - print-last-kbd-macro: document.
-
-lib/readline/text.c
- - _rl_insert_next: if we're defining a macro, make sure the key gets
- added to the macro text (should really audit calls to rl_read_key()
- and make sure the right thing is happening for all of them)
-
-bashline.[ch]
- - print_unix_command_map: new function, prints all bound commands in
- cmd_xmap using rl_macro_dumper in a reusable format
-
-builtins/bind.def
- - new -X option: print all keysequences bound to Unix commands using
- print_unix_command_map. Feature suggested by Dennis Williamson
- (2/2011)
-
-doc/{bash.1,bashref.texi}
- - document new `bind -X' option
-
- 12/24
- -----
-
-doc/{bash.1,bashref.texi}
- - add a couple of sentences to the description of the case modification
- operators making it clearer that each character of parameter is
- tested against the pattern, and that the pattern should only attempt
- to match a single character. Suggested by Bill Gradwohl
- <bill@ycc.com>
-
- 12/28
- -----
-shell.c
- - init_noninteractive: instead of calling set_job_control(0) to
- unconditionally turn off job control, turn on job control if
- forced_interactive or jobs_m_flag is set
- - shell_initialize: call initialize_job_control with jobs_m_flag as
- argument so `bash -m script' enables job control while running the
- script
-
-jobs.c
- - initialize_job_control: if the `force' argument is non-zero, turn on
- job control even if the shell is not currently interactive
- (interactive == 0)
-
- 12/29
- -----
-
-flags.h
- - new extern declaration for jobs_m_flag
-
-builtins/{cd,set}.def,doc/{bash.1,bashref.texi}
- - added text clarifying the descriptions of cd -L and -P, suggested by
- Padraig Brady <p@draigbrady.com>
- - slight change to the description of `set -P' about resolving symbolic
- links
-
-lib/readline/doc/rluser.texi
- - Added an example to the programmable completion section: _comp_cd,
- a completion function for cd, with additional verbiage. Text
- includes a reference to the bash_completion project
-
- 1/1/2012
- --------
-jobs.c
- - set_job_status_and_cleanup: note that a job is stopped due to
- SIGTSTP (any_tstped) if job_control is set; there's no need to
- test interactive
-
- 1/5
- ---
-quit.h
- - LASTSIG(): new macro, expands to signal number of last terminating
- signal received (terminating_signal or SIGINT)
-
-trap.c
- - first_pending_trap: returns lowest signal number with a trap pending
- - trapped_signal_received: set to the last trapped signal the shell
- received in trap_handler(); reset to 0 in run_pending_traps
-
-builtins/read.def
- - read_builtin: changes to posix-mode (posixly_correct != 0) to make
- `read' interruptible by a trapped signal. After the trap runs,
- read returns 128+sig and does not assign the partially-read line
- to the named variable(s). From an austin-group discussion started
- by David Korn
-
- 1/11
- ----
-doc/{bash.1,bashref.texi}
- - slight changes to the descriptions of the compat32 and compat40 shell
- options to clarify their meaning
-
- 1/12
- ----
-lib/readline/{colors.[ch],parse-colors.[ch]}
- - new files, part of color infrastructure support
-
-Makefile.in,lib/readline/Makefile.in
- - arrange to have colors.o and parse-colors.o added to readline
- library
-
-{configure,config.h}.in
- - check for stdbool.h, define HAVE_STDBOOL_H if found
-
- 1/14
- ----
-lib/readline/bind.c
- - colored_stats: new bindable variable, enables using colors to
- indicate file type when listing completions
-
-lib/readline/complete.c
- - _rl_colored_stats: new variable, controlled by colored-stats bindable
- variable
- - colored_stat_start, colored_stat_end: new functions to set and reset
- the terminal color appropriately depending on the type of the
- filename to be printed
- - print_filename: changes to print colors if `colored-stats' variable
- set. Changes contributed by Raphael Droz
- <raphael.droz+floss@gmail.com>
-
-lib/readline/readline.c
- - rl_initialize_everything: add call to _rl_parse_colors to parse
- color values out of $LS_COLORS. May have to add to rl_initialize
- to make more dynamic if LS_COLORS changes (which doesn't happen
- very often, if at all)
-
-lib/readline/rlprivate.h
- - _rl_colored_stats: new extern declaration
-
-lib/readline/doc/{readline.3,rluser.texi},doc/bash.1
- - colored-stats: document new bindable readline variable
-
-lib/readline/colors.c
- - _rl_print_color_indicator: call rl_filename_stat_hook before calling
- lstat/stat so we can get color indicators for stuff like
- $HOME/Applications
-
-lib/readline/complete.c
- - stat_char: call rl_filename_stat_hook before calling lstat/stat
-
-findcmd.[ch],execute_cmd.c
- - search_for_command: now takes a second `flags' argument; changed
- header function prototype and callers
- - search_for_command: if (flags & 1), put the command found in $PATH
- into the command hash table (previous default behavior)
-
-execute_cmd.c
- - is_dirname: call search_for_command with flags argument of 0 so it
- doesn't try to put something in the command hash table
-
-bashline.c
- - bash_command_name_stat_hook: a hook function for readline's
- filename_stat_hook that does $PATH searching the same way that
- execute_cmd.c:execute_disk_command() does it, and rewrites the
- passed filename if found. Does not put names into command hash
- table. This allows command name completion to take advantage
- of `visible-stats' and `colored-stats' settings.
- - executable_completion: new function, calls the directory completion
- hook to expand the filename before calling executable_file or
- executable_or_directory; change command_word_completion_function to
- call executable_completion. This allows $HOME/bin/[TAB] to do
- command completion and display alternatives
-
- 1/17
- ----
-pcomplete.c
- - gen_command_matches: now takes a new second argument: the command
- name as deciphered by the programmable completion code and used
- to look up the compspec; changed callers (gen_compspec_completions)
- - gen_shell_function_matches: now takes a new second argument: the
- command that originally caused the completion function to be
- invoked; changed callers (gen_compspec_completions))
- - build_arg_list: now takes a new second argument: the command name
- corresponding to the current compspec; changed callers
- (gen_command_matches, gen_shell_function_matches)
- - build_arg_list: now uses `cmd' argument to create $1 passed to
- invoked command or shell function
- - gen_compspec_completions: if we skipped a null command at the
- beginning of the line (e.g., for completing `>'), add a new word for
- it at the beginning of the word list and increment nw and cw
- appropriately. This is all a partial fix for the shortcoming
- pointed out by Sung Pae <sungpae@gmail.com>
-
- 1/18
- ----
-
-{configure,config.h}.in
- - new check: check for AUDIT_USER_TTY defined in <linux/audit.h>,
- define HAVE_DECL_AUDIT_USER_TTY if both are found
-
-lib/readline/rlconf.h
- - ENABLE_TTY_AUDIT_SUPPORT: new define, allows use of the Linux kernel
- tty auditing system if it's available and enabled
-
-lib/readline/util.c
- - _rl_audit_tty: new function, send a string to the kernel tty audit
- system
-
-lib/readline/rlprivate.h
- - _rl_audit_tty: new extern declaration
-
-lib/readline/readline.c
- - readline: call _rl_audit_tty with line to be returned before returning
- it if the Linux tty audit system is available and it's been enabled
- in rlconf.h Original patch from Miroslav Trmac; recent request
- from Miroslav Lichvar <mlichvar@redhat.com>
-
- 1/21
- ----
-
-lib/readline/readline.c:
- - _rl_dispatch_subseq: add an inter-character timeout for multi-char
- key sequences. Suggested by <rogerx.oss@gmail.com>. Still needs
- work to make a user-settable variable
-
-parse.y
- - shell_getc: make code that uses the pop_alias dependent on ALIAS
- define
-
-variables.h
- - sv_tz: extern define should only depend on HAVE_TZSET
-
-expr.c
- - expr_streval: if ARRAY_VARS is not defined, set lvalue->ind to -1;
- move assignment to `ind' inside define
- - expr_bind_array_element: declaration and uses need to be #ifdef
- ARRAY_VARS
-
-arrayfunc.h
- - AV_ALLOWALL, AV_QUOTED, AV_USEIND: define to 0 if ARRAY_VARS not
- defined; used in subst.c unconditionally
-
-sig.h
- - make the signal blocking functions not dependent on JOB_CONTROL
-
-sig.c
- - sigprocmask: make the replacement definition not dependent on
- JOB_CONTROL
-
-trap.c
- - use BLOCK_SIGNAL/UNBLOCK_SIGNAL instead of code dependent on
- HAVE_POSIX_SIGNALS and BSD signals
-
- 1/24
- ----
-
-print_cmd.c
- - print_redirection_list: change the conditions under which
- r_duplicating_output_word is mapped to r_err_and_out to more or
- less match those used in redir.c. Fixes bug pointed out by
- Dan Douglas <ormaaj@gmail.com>
-
-
- 1/29
- ----
-lib/readline/signals.c
- - _rl_block_sigwinch,_rl_release_sigwinch: don't compile in bodies
- unless SIGWINCH is defined. Fixes bug reported by Pierre Muller
- <pierre.muller@ics-cnrs.unistra.fr>
-
-doc/{bash.1,bashref.texi}
- - small modifications to the introduction to the REDIRECTION section
- to describe how redirections can modify file handles
- - small modification to the section describing base#n to make it
- clearer that n can be denoted using non-numerics. From a posting
- by Linda Walsh <bash@tlinx.org>
-
- 2/2
- ---
-builtins/printf.def
- - printf_builtin: make sure vbuf is intialized and non-null when -v
- is supplied, since other parts of the code assume that it's not
- null (e.g., bind_printf_variable()). Fixes bug reported by Jim
- Avera <james_avera@yahoo.com>
-
- 2/4
- ---
-lib/readline/undo.c
- - _rl_free_undo_list: new function, old body of rl_free_undo_list,
- frees undo entries in UNDO_LIST * passed as argument
- - rl_free_undo_list: call _rl_free_undo_list
-
-lib/readline/rlprivate.h
- - _rl_free_undo_list: new extern declaration
- - _rl_keyseq_timeout: new extern declaration (see below)
-
-lib/readline/misc.c
- - rl_clear_history: new function. Clears the history list and frees
- all associated data similar to history.c:clear_history(), but
- takes rl_undo_list into account and frees and UNDO_LISTs saved as
- `data' members of a history list entry
-
-lib/readline/doc/rltech.texi
- - rl_clear_history: documented
-
-lib/readline/readline.c
- - _rl_keyseq_timeout: new variable to hold intra-key timeout value
- from 1/21 fix; specified in milliseconds. Default value is 500
- - _rl_dispatch_subseq: change to use _rl_keyseq_timeout as intra-key
- timeout if it's greater than 0; no timeout if <= 0
- - _rl_dispatch_subseq: don't check for queued keyboard input if we have
- pushed or pending input, or if we're reading input from a macro
-
-lib/readline/bind.c
- - keyseq-timeout: new bindable variable, shadows _rl_keyseq_timeout
- - string_varlist: add keyseq-timeout
- - sv_seqtimeout: new function to modify value of _rl_keyseq_timeout;
- clamps negative values at 0 for now
- - _rl_get_string_variable_value: return value for keyseq-timeout
-
-doc/bash.1,lib/readline/doc/{rluser.texi,readline.3}
- - keyseq-timeout: documented
-
-lib/readline/isearch.c
- - _rl_isearch_dispatch: modification to fix from 7/18 to not use
- cxt->keymap and cxt->okeymap, since by the time this code is
- executed, they are equal. Use `f' to check for rl_insert or
- unbound func
- - _rl_isearch_dispatch: if we're switching keymaps, not in
- callback mode, and don't have pending or pushed input, use
- _rl_input_queued to resolve a potentially ambiguous key sequence.
- Suggested by Roger Zauner <rogerx.oss@gmail.com>
- - _rl_isearch_dispatch: if we have changed keymaps and resolved to
- an editing function (not self-insert), make sure we stuff the
- right characters back onto the input after changing the keymap
- back so the right editing function is executed after the search
- is terminated. Rest of fix for bug reported by Roger Zauner
- <rogerx.oss@gmail.com>
-
- 2/5
- ---
-builtins/gen-helpfiles.c
- - new file: reads struct builtin and writes the long docs to files
- in the `helpdirs' subdirectory. The filename is given in the
- previously-unused `handle' member of the struct builtin. Links
- with `tmpbuiltins.o', which is created by Makefile to have the
- right long documentation. When not cross-compiling, gets the
- right #defines based on configuration options from config.h instead
- of trying to parse conditional parts of def files. Fixes
- shortcoming pointed out by Andreas Schwab <schwab@linux-m68k.org>
-
-builtins/Makefile.in
- - tmpbuiltins.c: new generated file, created to enable creation of
- separate helpfiles based on correct #defines instead of trying to
- parse conditional parts of def files
- - gen-helpfiles: new program to generate helpfiles, links with
- tmpbuiltins.o
- - HELPFILES_TARGET: new target, substituted by configure to `helpdoc'
- if separate helpfiles requested
- - targets: new target, libbuiltins.a and $(HELPFILES_TARGET)
- - CREATED_OBJECTS: new variable, holds created object files for
- make clean; changed make clean to remove created objects
- - helpdoc: changed to call gen-helpfiles instead of mkbuiltins
-
-Makefile.in
- - when building libbuiltins.a, recursively call make with `targets'
- argument to make sure separate helpfiles get built
-
-configure.in
- - substitute `helpdoc' as value of HELPFILES_TARGET if
- --enable-separate-helpfiles supplied as configure argument
-
-builtins/mkbuiltins.c
- - `-nofunctions': new argument, causes mkbuiltins to not write value
- for function implementing a particular builtin to struct builtin
- and to write document file name to `handle' member of struct builtin
- - no longer writes separate helpfiles; that is left to gen-helpfiles
-
- 2/8
- ---
-subst.c
- - make sure last_command_exit_value is set to a non-zero value before
- any calls to report_error, since `-e' set will short-circuit
- report_error. Fixes bug reported by Ewan Mellor
- <Ewan.Mellor@eu.citrix.com>
-
-variables.c
- - make_local_array_variable: added second argument; if non-zero,
- function will return an existing local associative array variable
- instead of insisting on an indexed array
-
-variable.h,subst.c
- - make_local_array_variable: changed prototype and caller
-
-builtins/declare.def
- - declare_internal: add second arg to call to make_local_array_variable;
- making_array_special, which indicates we're processing an
- assignment like declare a[b]=c. Fixes seg fault resulting from
- a being an already-declared local associative array variable in a
- function. Ubuntu bash bug 928900.
-
- 2/14
- ----
-
-execute_cmd.c
- - execute_command_internal: if redirections into or out of a loop fail,
- don't try to free ofifo_list unless saved_fifo is non-zero. It's
- only valid if saved_fifo is set
-
- 2/15
- ----
-{arrayfunc,braces,variables}.c
- - last_command_exit_value: make sure it's set before any calls to
- report_error, since -e will cause that to exit the shell
-
-builtins/common.c
- - get_job_by_name: call internal_error instead of report_error so this
- doesn't exit the shell
-
- 2/18
- ----
-builtins/evalstring.c
- - parse_and_execute: make sure the file descriptor to be redirected to
- is 1 before calling cat_file. One fix for bug reported by Dan Douglas
- <ormaaj@gmail.com>
-
-parse.y
- - read_token_word: don't return NUMBER if a string of all digits
- resolves to a number that overflows the bounds of an intmax_t.
- Other fix for bug reported by Dan Douglas <ormaaj@gmail.com>
-
- 2/19
- ----
-lib/sh/strtrans.c
- - ansicstr: use 0x7f as the boundary for characters that translate
- directly from ASCII to unicode (\u and \U escapes) instead of
- UCHAR_MAX, since everything >= 0x80 requires more than one byte.
- Bug and fix from John Kearney <dethrophes@web.de>
-
-builtins/printf.def
- - tescape: ditto for printf \u and \U escape sequences
-
- 2/20
- ----
-lib/sh/unicode.c
- - u32toutf8: fix to handle encodings up to six bytes long correctly
- (though technically UTF-8 only has characters up to 4 bytes long).
- Report and fix from John Kearney <dethrophes@web.de>
- - u32toutf8: first argument is now an unsigned 32-bit quantity,
- changed callers (u32cconv) to pass c instead of wc
- - u32reset: new function, resets local static state to uninitialized
- (locale information, currently)
-
-locale.c
- - call u32reset whenever LC_CTYPE/LC_ALL/LANG is changed to reset the
- cached locale information used by u32cconv. From a report from
- John Kearney <dethrophes@web.de>
-
- 2/21
- ----
-doc/{bash,builtins}.1
- - minor changes from Bjarni Ingi Gislason <bjarniig@rhi.hi.is>
-
-lib/sh/unicode.c
- - u32cconv: only assume you can directly call wctomb on the passed
- value if __STDC_ISO_10646__ is defined and the value is <=
- 0x7fffffff
- - stub_charset: return locale as default instead of "ASCII", let
- rest of code decide what to do with it
-
-lib/readline/parens.c
- - _rl_enable_paren_matching: make paren matching work in vi insert
- mode. Bug report from <derflob@derflob.de>
-
- 2/22
- ----
-lib/sh/shquote.c
- - sh_backslash_quote: quote tilde in places where it would be
- expanded. From a report from John Kearney <dethrophes@web.de>
-
- 2/23
- ----
-execute_cmd.c
- - execute_pipeline: wrap the discard_unwind_frame call in #ifdef
- JOB_CONTROL, since the frame is only created if JOB_CONTROL is
- defined. Bug and fix from Doug Kehn <rdkehn@yahoo.com>
-
- 2/25
- ----
-error.c
- - report_error: make sure last_command_exit_value is non-zero before
- we call exit_shell, since the exit trap may reference it. Call
- exit_shell with last_command_exit_value to allow exit statuses
- other than 1
-
-unicode.c
- - stub_charset: use local static buffer to hold charset, don't change
- value returned by get_locale_var. Based on idea and code from
- John Kearney <dethrophes@web.de>
- - u32toutf16: function to convert unsigned 32-bit value (unicode) to
- UTF-16. From John Kearney <dethrophes@web.de>
- - u32cconv: call u32toutf16 if __STDC_ISO_10646__ defined and wchar_t
- is two bytes, send result to wcstombs, return if not encoding error.
- From John Kearney <dethrophes@web.de>
-
-
+++ /dev/null
-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.
+++ /dev/null
-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);
-}
+++ /dev/null
-/* 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 */
+++ /dev/null
-#
-# Master distribution manifest for bash
-#
-#
-# Filename type
-#
-CWRU d
-CWRU/misc d
-builtins d
-cross-build d
-doc d
-examples 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/tilde d
-po d
-support d
-tests d
-tests/misc d
-ABOUT-NLS f
-ChangeLog s CWRU/changelog
-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 755
-Makefile.in f
-config-top.h f
-config-bot.h f
-config.h.in f
-aclocal.m4 f
-array.c f
-arrayfunc.c f
-assoc.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
-assoc.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/mapfile.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/posixselect.h f
-include/posixstat.h f
-include/posixtime.h f
-include/posixwait.h f
-include/shmbchar.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/gmisc.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/xfree.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/colors.c f
-lib/readline/parse-colors.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/posixselect.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/colors.h f
-lib/readline/parse-colors.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/casemod.c f
-lib/sh/clktck.c f
-lib/sh/clock.c f
-lib/sh/dprintf.c f
-lib/sh/eaccess.c f
-lib/sh/fmtullong.c f
-lib/sh/fmtulong.c f
-lib/sh/fmtumax.c f
-lib/sh/fnxform.c f
-lib/sh/fpurge.c f
-lib/sh/getcwd.c f
-lib/sh/getenv.c f
-lib/sh/inet_aton.c f
-lib/sh/input_avail.c f
-lib/sh/itos.c f
-lib/sh/mailstat.c f
-lib/sh/makepath.c f
-lib/sh/mbscasecmp.c f
-lib/sh/mbschr.c f
-lib/sh/mbscmp.c f
-lib/sh/memset.c f
-lib/sh/mktime.c f
-lib/sh/netconn.c f
-lib/sh/netopen.c f
-lib/sh/oslib.c f
-lib/sh/pathcanon.c f
-lib/sh/pathphys.c f
-lib/sh/rename.c f
-lib/sh/setlinebuf.c f
-lib/sh/shmatch.c f
-lib/sh/shmbchar.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/strcasestr.c f
-lib/sh/strchrnul.c f
-lib/sh/strerror.c f
-lib/sh/strftime.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/uconvert.c f
-lib/sh/ufuncs.c f
-lib/sh/unicode.c f
-lib/sh/vprint.c f
-lib/sh/wcsdup.c f
-lib/sh/wcswidth.c f
-lib/sh/winsize.c f
-lib/sh/zcatfd.c f
-lib/sh/zgetline.c f
-lib/sh/zmapfd.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/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/README f
-po/Rules-builtins f
-po/Rules-quot f
-po/bash.pot f
-po/boldquot.sed f
-po/en@boldquot.gmo f
-po/en@boldquot.header f
-po/en@boldquot.po f
-po/en@quot.gmo f
-po/en@quot.header f
-po/en@quot.po f
-po/af.gmo f
-po/af.po f
-po/bg.gmo f
-po/bg.po f
-po/ca.gmo f
-po/ca.po f
-po/cs.gmo f
-po/cs.po f
-po/da.gmo f
-po/da.po f
-po/de.gmo f
-po/de.po f
-po/eo.gmo f
-po/eo.po f
-po/es.gmo f
-po/es.po f
-po/et.gmo f
-po/et.po f
-po/fi.gmo f
-po/fi.po f
-po/fr.gmo f
-po/fr.po f
-po/ga.gmo f
-po/ga.po f
-po/hu.gmo f
-po/hu.po f
-po/id.gmo f
-po/id.po f
-po/ja.gmo f
-po/ja.po f
-po/lt.gmo f
-po/lt.po f
-po/nl.gmo f
-po/nl.po f
-po/pl.gmo f
-po/pl.po f
-po/pt_BR.gmo f
-po/pt_BR.po f
-po/ro.gmo f
-po/ro.po f
-po/ru.gmo f
-po/ru.po f
-po/sk.gmo f
-po/sk.po f
-po/sl.gmo f
-po/sl.po f
-po/sv.gmo f
-po/sv.po f
-po/tr.gmo f
-po/tr.po f
-po/uk.gmo f
-po/uk.po f
-po/vi.gmo f
-po/vi.po f
-po/zh_CN.gmo f
-po/zh_CN.po f
-po/zh_TW.gmo f
-po/zh_TW.po 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/checkbashisms f 755
-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/xcase.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/obashdb/PERMISSION f
-examples/obashdb/README f
-examples/obashdb/bashdb f
-examples/obashdb/bashdb.el f
-examples/complete/bash_completion f
-examples/complete/cdfunc 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/mypid.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/bash-hexdump.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/timeout2 f
-examples/scripts/timeout3 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/COPYRIGHT f
-tests/alias.tests f
-tests/alias1.sub 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/arith3.sub f
-tests/arith4.sub f
-tests/arith5.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/array5.sub f
-tests/array6.sub f
-tests/array7.sub f
-tests/array8.sub f
-tests/array9.sub f
-tests/array10.sub f
-tests/array11.sub f
-tests/array12.sub f
-tests/array-at-star f
-tests/array2.right f
-tests/assoc.tests f
-tests/assoc.right f
-tests/assoc1.sub f
-tests/assoc2.sub f
-tests/assoc3.sub f
-tests/assoc4.sub f
-tests/assoc5.sub f
-tests/assoc6.sub 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/builtins3.sub f
-tests/source1.sub f
-tests/source2.sub f
-tests/source3.sub f
-tests/source4.sub f
-tests/source5.sub f
-tests/source6.sub f
-tests/case.tests f
-tests/case.right f
-tests/casemod.tests f
-tests/casemod.right f
-tests/comsub.tests f
-tests/comsub.right f
-tests/comsub1.sub f
-tests/comsub-eof.tests f
-tests/comsub-eof0.sub f
-tests/comsub-eof1.sub f
-tests/comsub-eof2.sub f
-tests/comsub-eof3.sub f
-tests/comsub-eof4.sub f
-tests/comsub-eof5.sub f
-tests/comsub-eof.right f
-tests/comsub-posix.tests f
-tests/comsub-posix.right f
-tests/comsub-posix1.sub f
-tests/comsub-posix2.sub f
-tests/comsub-posix3.sub f
-tests/cond.tests f
-tests/cond.right f
-tests/cond-regexp1.sub f
-tests/cond-regexp2.sub f
-tests/coproc.tests f
-tests/coproc.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/dbg-support3.sub f
-tests/dollar-at-star f
-tests/dollar-at1.sub f
-tests/dollar-at2.sub f
-tests/dollar-at3.sub f
-tests/dollar-at4.sub f
-tests/dollar-star1.sub f
-tests/dollar-star2.sub f
-tests/dollar-star3.sub f
-tests/dollar-star4.sub f
-tests/dollar-star5.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/errors1.sub 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/exec8.sub f
-tests/exec9.sub f
-tests/exp.tests f
-tests/exp.right f
-tests/exp1.sub f
-tests/exp2.sub f
-tests/exp3.sub f
-tests/exp4.sub f
-tests/exp5.sub f
-tests/exp6.sub f
-tests/extglob.tests f
-tests/extglob.right f
-tests/extglob1.sub 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/func4.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.tests f
-tests/glob1.sub f
-tests/glob.right f
-tests/globstar.tests f
-tests/globstar.right f
-tests/globstar1.sub f
-tests/heredoc.tests f
-tests/heredoc.right f
-tests/heredoc1.sub f
-tests/heredoc2.sub f
-tests/heredoc3.sub 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/history1.sub f
-tests/history2.sub f
-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/intl1.sub f
-tests/intl2.sub 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/lastpipe.right f
-tests/lastpipe.tests f
-tests/lastpipe1.sub f
-tests/mapfile.data f
-tests/mapfile.right f
-tests/mapfile.tests f
-tests/mapfile1.sub 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-exp6.sub f
-tests/new-exp7.sub f
-tests/new-exp8.sub f
-tests/new-exp.right f
-tests/nquote.tests f
-tests/nquote.right f
-tests/nquote1.sub 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/nquote5.tests f
-tests/nquote5.right f
-tests/posix2.tests f
-tests/posix2.right f
-tests/posixexp.tests f
-tests/posixexp.right f
-tests/posixexp1.sub f
-tests/posixexp2.sub f
-tests/posixexp2.tests f
-tests/posixexp2.right f
-tests/posixpat.tests f
-tests/posixpat.right f
-tests/posixpipe.tests f
-tests/posixpipe.right f
-tests/prec.right f
-tests/precedence f
-tests/printf.tests f
-tests/printf.right f
-tests/printf1.sub f
-tests/printf2.sub f
-tests/printf3.sub 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/read6.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/redir8.sub f
-tests/redir9.sub f
-tests/redir10.sub f
-tests/rhs-exp.tests f
-tests/rhs-exp.right f
-tests/rhs-exp1.sub 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-assoc f
-tests/run-braces f
-tests/run-builtins f
-tests/run-case f
-tests/run-casemod f
-tests/run-comsub f
-tests/run-comsub-eof f
-tests/run-comsub-posix f
-tests/run-cond f
-tests/run-coproc 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-globstar 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-lastpipe f
-tests/run-mapfile 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-nquote5 f
-tests/run-posix2 f
-tests/run-posixexp f
-tests/run-posixexp2 f
-tests/run-posixpat f
-tests/run-posixpipe 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/run-vredir f
-tests/set-e.tests f
-tests/set-e1.sub f
-tests/set-e2.sub f
-tests/set-e.right f
-tests/set-x.tests f
-tests/set-x1.sub 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/trap3.sub f
-tests/type.tests f
-tests/type.right f
-tests/type1.sub f
-tests/type2.sub f
-tests/type3.sub f
-tests/type4.sub 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/vredir.tests f
-tests/vredir.right f
-tests/vredir1.sub f
-tests/vredir2.sub f
-tests/vredir3.sub f
-tests/vredir4.sub f
-tests/vredir5.sub f
-tests/vredir6.sub 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
+++ /dev/null
-# Makefile for bash-4.2, version 4.6
-#
-# Copyright (C) 1996-2011 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
-
-# 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@
-
-datarootdir = @datarootdir@
-
-bindir = @bindir@
-libdir = @libdir@
-infodir = @infodir@
-includedir = @includedir@
-datadir = @datadir@
-localedir = @localedir@
-
-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@
-
-DEBUGGER_START_FILE = @DEBUGGER_START_FILE@
-
-#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_FOR_BUILD@ $(LOCAL_LDFLAGS) $(CFLAGS_FOR_BUILD)
-
-INCLUDES = -I. @RL_INCLUDE@ -I$(srcdir) -I$(BASHINCDIR) -I$(LIBSRC) $(INTL_INC)
-
-# Maybe add: -Wextra
-GCC_LINT_FLAGS = -O -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}/strchrnul.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}/strcasestr.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}/mbschr.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 \
- ${SH_LIBSRC}/zmapfd.c ${SH_LIBSRC}/fpurge.c \
- ${SH_LIBSRC}/zgetline.c ${SH_LIBSRC}/mbscmp.c \
- ${SH_LIBSRC}/casemod.c ${SH_LIBSRC}/uconvert.c \
- ${SH_LIBSRC}/ufuncs.c ${SH_LIBSRC}/dprintf.c \
- ${SH_LIBSRC}/input_avail.c ${SH_LIBSRC}/mbscasecmp.c \
- ${SH_LIBSRC}/fnxform.c ${SH_LIBSRC}/unicode.c \
- ${SH_LIBSRC}/wcswidth.c ${SH_LIBSRC}/shmbchar.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)/colors.h $(RL_LIBSRC)/parse-colors.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)/colors.c $(RL_LIBSRC)/parse-colors.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 \
- $(RL_LIBDIR)/colors.o $(RL_LIBDIR)/parse-colors.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)/gmisc.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 \
- $(GLOB_LIBDIR)/gmisc.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@
-
-# libiconv
-LIBICONV = @LIBICONV@
-
-# 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 = $(GLOB_LIB) $(SHLIB_LIB) $(READLINE_LIB) $(HISTORY_LIB) $(TERMCAP_LIB) \
- $(TILDE_LIB) $(MALLOC_LIB) $(INTL_LIB) $(LIBICONV) $(LOCAL_LIBS)
-
-LIBDEP = $(GLOB_DEP) $(SHLIB_DEP) $(INTL_DEP) $(READLINE_DEP) $(HISTORY_DEP) $(TERMCAP_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 assoc.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 assoc.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 assoc.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 \
- $(DEFSRC)/mapfile.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 $(DEFDIR)/mapfile.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) xcase$(EXEEXT)
-CREATED_SUPPORT = signames.h recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) \
- tests/recho$(EXEEXT) tests/zecho$(EXEEXT) \
- tests/printenv$(EXEEXT) xcase$(EXEEXT) tests/xcase$(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 config.status.lineno
-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 patchlevel.h
- $(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.h 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: 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
-
-y.tab.h: y.tab.c
- @true
-
-
-# Subdirs will often times want version.h, so they'll change back up to
-# the top level and try to create it. This causes parallel build issues
-# so just force top level sanity before we descend.
-$(LIBDEP): .build
-#$(LIBDEP): version.h
-
-$(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) $(READLINE_DEP)
- @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_DEP}
-
-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 $(DEFDIR)/builtext.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
-
-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
-
-pathnames.h: Makefile $(srcdir)/pathnames.h.in
- @sed -e 's|@DEBUGGER_START_FILE\@|${DEBUGGER_START_FILE}|g' $(srcdir)/pathnames.h.in > pathnames.tmp
- @if test -f $@; then \
- cmp -s pathnames.tmp $@ || mv pathnames.tmp $@; \
- else \
- mv pathnames.tmp $@; \
- fi
- @${RM} pathnames.tmp
-
-# 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}
-
-xcase$(EXEEXT): $(SUPPORT_SRC)xcase.c
- @$(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(SUPPORT_SRC)xcase.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
-bashhist.o: config-top.h
-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 pathnames.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
-input.o: quit.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 parser.h
-make_cmd.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.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 ${BASHINCDIR}/shmbchar.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 bashline.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 parser.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 ${BASHINCDIR}/shmbchar.h
-subst.o: ${DEFDIR}/builtext.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 jobs.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 assoc.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: execute_cmd.h 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
-nojobs.o: $(DEFDIR)/builtext.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 pathexp.h
-arrayfunc.o: $(DEFSRC)/common.h
-arrayfunc.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
-assoc.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
-assoc.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
-assoc.o: command.h ${BASHINCDIR}/stdc.h error.h
-assoc.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
-assoc.o: assoc.h hashlib.h
-assoc.o: quit.h ${BASHINCDIR}/maxpath.h unwind_prot.h dispose_cmd.h
-assoc.o: make_cmd.h subst.h sig.h pathnames.h externs.h
-assoc.o: $(DEFSRC)/common.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 ${BASHINCDIR}/shmbchar.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
-bashline.o: ${BASHINCDIR}/shmbutil.h ${BASHINCDIR}/shmbchar.h
-bracecomp.o: config.h bashansi.h ${BASHINCDIR}/ansi_stdlib.h
-bracecomp.o: shell.h syntax.h config.h bashjmp.h ${BASHINCDIR}/posixjmp.h
-bracecomp.o: command.h ${BASHINCDIR}/stdc.h error.h
-bracecomp.o: general.h xmalloc.h bashtypes.h variables.h arrayfunc.h conftypes.h
-bracecomp.o: array.h hashlib.h alias.h builtins.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
-
-# 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
-y.tab.o: 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 pathnames.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 pathnames.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 pathnames.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/break.o: pathnames.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/builtin.o: pathnames.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 pathnames.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 pathnames.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 pathnames.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 pathnames.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/echo.o: pathnames.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 pathnames.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/eval.o: pathnames.h
-builtins/exec.o: bashtypes.h pathnames.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/exec.o: pathnames.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/exit.o: pathnames.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 pathnames.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/fg_bg.o: pathnames.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/getopts.o: pathnames.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/hash.o: pathnames.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 pathnames.h
-builtins/history.o: bashtypes.h pathnames.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/inlib.o: pathnames.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/jobs.o: pathnames.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/kill.o: pathnames.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/let.o: pathnames.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 pathnames.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/read.o: pathnames.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/return.o: pathnames.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/set.o: pathnames.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/setattr.o: pathnames.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/shift.o: pathnames.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 pathnames.h
-builtins/shopt.o: bashhist.h bashline.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/source.o: pathnames.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/suspend.o: pathnames.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 pathnames.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/times.o: pathnames.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/trap.o: pathnames.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/type.o: pathnames.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/ulimit.o: pathnames.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 pathnames.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 pathnames.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 pathnames.h
-builtins/complete.o: pcomplete.h
-builtins/complete.o: ${DEFSRC}/common.h ${DEFSRC}/bashgetopt.h
-builtins/mapfile.o: command.h config.h ${BASHINCDIR}/memalloc.h error.h general.h xmalloc.h ${BASHINCDIR}/maxpath.h
-builtins/mapfile.o: quit.h dispose_cmd.h make_cmd.h subst.h externs.h ${BASHINCDIR}/stdc.h
-builtins/mapfile.o: shell.h syntax.h bashjmp.h ${BASHINCDIR}/posixjmp.h sig.h unwind_prot.h variables.h arrayfunc.h conftypes.h
-builtins/mapfile.o: pathnames.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/mapfile.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-builtins/mkbuiltins.o: ${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/mapfile.o: $(DEFSRC)/mapfile.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
+++ /dev/null
-# This Makefile for building libbuiltins.a is in -*- text -*- for Emacs.
-#
-# Copyright (C) 1996-2009 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
-
-PACKAGE = @PACKAGE_NAME@
-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
-PACKAGE_NAME = @PACKAGE_NAME@
-PACKAGE_STRING = @PACKAGE_STRING@
-PACKAGE_VERSION = @PACKAGE_VERSION@
-
-#
-SHELL = @MAKE_SHELL@
-RANLIB = @RANLIB@
-CC = @CC@
-CC_FOR_BUILD = @CC_FOR_BUILD@
-AR = @AR@
-ARFLAGS = @ARFLAGS@
-RM = rm -f
-CP = cp
-
-EXEEXT = @EXEEXT@
-
-prefix = @prefix@
-
-srcdir = @srcdir@
-VPATH = .:@srcdir@
-topdir = @top_srcdir@
-
-datarootdir = @datarootdir@
-
-includedir = @includedir@
-datadir = @datadir@
-localedir = @localedir@
-
-# Support an alternate destination root directory for package building
-DESTDIR =
-
-INSTALL = @INSTALL@
-INSTALL_DATA = @INSTALL_DATA@
-BUILD_DIR = @BUILD_DIR@
-
-LIBBUILD = ${BUILD_DIR}/lib
-
-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}
-DEFS = @DEFS@
-LOCAL_DEFS = @LOCAL_DEFS@
-
-LIBS = @LIBS@
-LDFLAGS = @LDFLAGS@ $(LOCAL_LDFLAGS) $(CFLAGS)
-LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ $(LOCAL_LDFLAGS) $(CFLAGS_FOR_BUILD)
-LOCAL_LDFLAGS = @LOCAL_LDFLAGS@
-LIBS_FOR_BUILD = @LIBS_FOR_BUILD@
-#LIBS_FOR_BUILD = $(LIBS)
-
-BASHINCDIR = ${topdir}/include
-
-RL_INCLUDEDIR = @RL_INCLUDEDIR@
-
-INTL_LIBSRC = ${topdir}/lib/intl
-INTL_BUILDDIR = ${LIBBUILD}/intl
-INTL_LIBDIR = ${INTL_BUILDDIR}
-INTL_LIBRARY = ${INTL_BUILDDIR}/libintl.a
-INTL_INC = @INTL_INC@
-INTL_DEP = @INTL_DEP@
-LIBINTL_H = @LIBINTL_H@
-
-HELPDIR = @HELPDIR@
-MKDIRS = ${topdir}/support/mkdirs
-
-HELPFILES_TARGET = @HELPFILES_TARGET@
-
-INCLUDES = -I. -I.. @RL_INCLUDE@ -I$(topdir) -I$(BASHINCDIR) -I$(topdir)/lib -I$(srcdir) ${INTL_INC}
-
-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)
-
-GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
- -Wcast-align -Wstrict-prototypes -Wconversion \
- -Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
-
-MKBUILTINS = mkbuiltins$(EXEEXT)
-DIRECTDEFINE = -D $(srcdir)
-HELPDIRDEFINE = @HELPDIRDEFINE@
-HELPSTRINGS = @HELPSTRINGS@
-
-# xxx this is bad style
-RL_LIBSRC = $(topdir)/lib/readline
-
-.SUFFIXES:
-.SUFFIXES: .def .c .o
-# How to make a .o file from a .def file.
-.def.o:
- $(RM) $@
- ./$(MKBUILTINS) $(DIRECTDEFINE) $<
- $(CC) -c $(CCFLAGS) $*.c || ( $(RM) $*.c ; exit 1 )
- $(RM) $*.c
-
-# How to make a .c file from a .def file.
-.def.c:
- $(RM) $@
- ./$(MKBUILTINS) $(DIRECTDEFINE) $<
-
-# default rule for making a .o file from a .c file
-.c.o:
- $(RM) $@
- $(CC) -c $(CCFLAGS) $<
-
-DEFSRC = $(srcdir)/alias.def $(srcdir)/bind.def $(srcdir)/break.def \
- $(srcdir)/builtin.def $(srcdir)/caller.def \
- $(srcdir)/cd.def $(srcdir)/colon.def \
- $(srcdir)/command.def $(srcdir)/declare.def $(srcdir)/echo.def \
- $(srcdir)/enable.def $(srcdir)/eval.def $(srcdir)/getopts.def \
- $(srcdir)/exec.def $(srcdir)/exit.def $(srcdir)/fc.def \
- $(srcdir)/fg_bg.def $(srcdir)/hash.def $(srcdir)/help.def \
- $(srcdir)/history.def $(srcdir)/jobs.def $(srcdir)/kill.def \
- $(srcdir)/let.def $(srcdir)/read.def $(srcdir)/return.def \
- $(srcdir)/set.def $(srcdir)/setattr.def $(srcdir)/shift.def \
- $(srcdir)/source.def $(srcdir)/suspend.def $(srcdir)/test.def \
- $(srcdir)/times.def $(srcdir)/trap.def $(srcdir)/type.def \
- $(srcdir)/ulimit.def $(srcdir)/umask.def $(srcdir)/wait.def \
- $(srcdir)/reserved.def $(srcdir)/pushd.def $(srcdir)/shopt.def \
- $(srcdir)/printf.def $(srcdir)/complete.def $(srcdir)/mapfile.def
-
-STATIC_SOURCE = common.c evalstring.c evalfile.c getopt.c bashgetopt.c \
- getopt.h
-
-OFILES = builtins.o \
- alias.o bind.o break.o builtin.o caller.o cd.o colon.o command.o \
- common.o declare.o echo.o enable.o eval.o evalfile.o \
- evalstring.o exec.o exit.o fc.o fg_bg.o hash.o help.o history.o \
- jobs.o kill.o let.o mapfile.o \
- pushd.o read.o return.o set.o setattr.o shift.o source.o \
- suspend.o test.o times.o trap.o type.o ulimit.o umask.o \
- wait.o getopts.o shopt.o printf.o getopt.o bashgetopt.o complete.o
-
-CREATED_FILES = builtext.h builtins.c psize.aux pipesize.h tmpbuiltins.c \
- tmpbuiltins.h
-CREATED_OBJECTS = tmpbuiltins.o gen-helpfiles.o mkbuiltins.o
-
-all: $(MKBUILTINS) libbuiltins.a $(HELPFILES_TARGET)
-
-libbuiltins.a: $(MKBUILTINS) $(OFILES) builtins.o
- $(RM) $@
- $(AR) $(ARFLAGS) $@ $(OFILES)
- -$(RANLIB) $@
-
-tmpbuiltins.c: $(MKBUILTINS) $(DEFSRC)
- ./$(MKBUILTINS) -externfile tmpbuiltins.h -structfile $@ \
- -noproduction -nofunctions \
- $(DIRECTDEFINE) $(HELPSTRINGS) $(DEFSRC)
-
-tmpbuiltins.h: tmpbuiltins.c
-
-gen-helpfiles.o: ../config.h
-gen-helpfiles.o: gen-helpfiles.c
- $(RM) $@
- $(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $<
-
-gen-helpfiles: tmpbuiltins.o gen-helpfiles.o
- $(CC_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $@ gen-helpfiles.o tmpbuiltins.o $(LIBS_FOR_BUILD)
-
-builtext.h builtins.c: $(MKBUILTINS) $(DEFSRC)
- @-if test -f builtins.c; then mv -f builtins.c old-builtins.c; fi
- @-if test -f builtext.h; then mv -f builtext.h old-builtext.h; fi
- ./$(MKBUILTINS) -externfile builtext.h -structfile builtins.c \
- -noproduction $(DIRECTDEFINE) $(HELPDIRDEFINE) $(HELPSTRINGS) $(DEFSRC)
- @-if cmp -s old-builtext.h builtext.h 2>/dev/null; then \
- mv old-builtext.h builtext.h; \
- else \
- $(RM) old-builtext.h; \
- fi
- @-if cmp -s old-builtins.c builtins.c 2>/dev/null; then \
- mv old-builtins.c builtins.c; \
- else \
- $(RM) old-builtins.c; \
- fi
-
-helpdoc: gen-helpfiles
- ./gen-helpfiles ${HELPDIRDEFINE}
-
-install-help:
- @-if test -n "${HELPDIR}" && test -d helpfiles ; then \
- test -d $(DESTDIR)${HELPDIR} || ${SHELL} ${MKDIRS} $(DESTDIR)$(HELPDIR) ;\
- ( for f in helpfiles/*; do \
- echo installing $$f; \
- ${INSTALL_DATA} $$f $(DESTDIR)$(HELPDIR); \
- done; ) ; \
- fi
-
-install: @HELPINSTALL@
-
-mkbuiltins.o: ../config.h
-mkbuiltins.o: mkbuiltins.c
- $(RM) $@
- $(CC_FOR_BUILD) -c $(CCFLAGS_FOR_BUILD) $<
-
-mkbuiltins$(EXEEXT): mkbuiltins.o
- $(CC_FOR_BUILD) $(LDFLAGS_FOR_BUILD) -o $(MKBUILTINS) mkbuiltins.o $(LIBS_FOR_BUILD)
-
-# rules for deficient makes, like SunOS
-mkbuiltins.o: mkbuiltins.c
-builtins.o: builtins.c
-common.o: common.c
-bashgetopt.o: bashgetopt.c
-getopt.o: getopt.c
-evalstring.o: evalstring.c
-evalfile.o: evalfile.c
-
-tmpbuiltins.o: tmpbuiltins.c
-gen-helpfiles.o: gen-helpfiles.c
-
-ulimit.o: pipesize.h
-
-pipesize.h: psize.aux
- $(SHELL) $(srcdir)/psize.sh > $@
-
-psize.aux: psize.c
- $(CC_FOR_BUILD) $(CCFLAGS_FOR_BUILD) -o $@ $(srcdir)/psize.c
-
-documentation: builtins.texi
-
-builtins.texi: $(MKBUILTINS)
- ./$(MKBUILTINS) -documentonly $(DEFSRC)
-
-clean:
- $(RM) $(OFILES) $(CREATED_FILES) libbuiltins.a
- $(RM) $(MKBUILTINS) gen-helpfiles $(CREATED_OBJECTS)
- -test -d helpfiles && $(RM) -r helpfiles
-
-mostlyclean:
- $(RM) $(OFILES) libbuiltins.a
-
-distclean maintainer-clean: clean
- $(RM) Makefile
-
-$(OFILES): $(MKBUILTINS) ../config.h
-
-../version.h: ../config.h ../Makefile Makefile
- -( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} version.h )
-
-# maintainer special - for now
-po: builtins.c
- xgettext -L C -o $(topdir)/po/builtins.pot --keyword='N_' builtins.c 2>/dev/null
-
-${LIBINTL_H}:
- @echo making $@ in ${INTL_BUILDDIR}
- @(cd ${INTL_BUILDDIR} && \
- $(MAKE) $(MFLAGS) libintl.h) || exit 1
-
-# dependencies
-
-alias.o: alias.def
-bind.o: bind.def
-break.o: break.def
-builtin.o: builtin.def
-caller.o: caller.def
-cd.o: cd.def
-colon.o: colon.def
-command.o: command.def
-declare.o: declare.def
-echo.o: echo.def
-enable.o: enable.def
-eval.o: eval.def
-exec.o: exec.def
-exit.o: exit.def
-fc.o: fc.def
-fg_bg.o: fg_bg.def
-hash.o: hash.def
-help.o: help.def
-history.o: history.def
-jobs.o: jobs.def
-kill.o: kill.def
-let.o: let.def
-mapfile.o: mapfile.def
-printf.o: printf.def
-pushd.o: pushd.def
-read.o: read.def
-return.o: return.def
-set.o: set.def
-setattr.o: setattr.def
-shift.o: shift.def
-shopt.o: shopt.def
-source.o: source.def
-suspend.o: suspend.def
-test.o: test.def
-times.o: times.def
-trap.o: trap.def
-type.o: type.def
-ulimit.o: ulimit.def
-umask.o: umask.def
-wait.o: wait.def
-getopts.o: getopts.def
-reserved.o: reserved.def
-complete.o: complete.def
-
-# C files
-bashgetopt.o: ../config.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
-bashgetopt.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/bashjmp.h
-bashgetopt.o: $(topdir)/command.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/error.h
-bashgetopt.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/quit.h $(BASHINCDIR)/maxpath.h
-bashgetopt.o: $(topdir)/unwind_prot.h $(topdir)/dispose_cmd.h
-bashgetopt.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/sig.h
-bashgetopt.o: ../pathnames.h $(topdir)/externs.h $(srcdir)/common.h
-bashgetopt.o: $(BASHINCDIR)/chartypes.h
-common.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
-common.o: $(topdir)/shell.h $(topdir)/syntax.h ../config.h $(topdir)/bashjmp.h $(BASHINCDIR)/posixjmp.h
-common.o: $(topdir)/sig.h $(topdir)/command.h
-common.o: $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/stdc.h $(BASHINCDIR)/memalloc.h
-common.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/input.h
-common.o: $(topdir)/siglist.h $(topdir)/bashhist.h $(topdir)/quit.h
-common.o: $(topdir)/unwind_prot.h $(BASHINCDIR)/maxpath.h $(topdir)/jobs.h
-common.o: $(topdir)/builtins.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-common.o: $(topdir)/subst.h $(topdir)/execute_cmd.h $(topdir)/error.h
-common.o: $(topdir)/externs.h ../pathnames.h ./builtext.h
-common.o: $(BASHINCDIR)/chartypes.h
-evalfile.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h ${BASHINCDIR}/filecntl.h
-evalfile.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
-evalfile.o: $(topdir)/shell.h $(topdir)/syntax.h ../config.h $(topdir)/bashjmp.h
-evalfile.o: $(topdir)/command.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/error.h
-evalfile.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/quit.h $(BASHINCDIR)/maxpath.h
-evalfile.o: $(topdir)/unwind_prot.h $(topdir)/dispose_cmd.h
-evalfile.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/sig.h
-evalfile.o: ../pathnames.h $(topdir)/externs.h
-evalfile.o: $(topdir)/jobs.h $(topdir)/builtins.h $(topdir)/flags.h
-evalfile.o: $(topdir)/input.h $(topdir)/execute_cmd.h
-evalfile.o: $(topdir)/bashhist.h $(srcdir)/common.h
-evalstring.o: ../config.h $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
-evalstring.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/bashjmp.h $(BASHINCDIR)/posixjmp.h
-evalstring.o: $(topdir)/sig.h $(topdir)/command.h $(topdir)/siglist.h
-evalstring.o: $(BASHINCDIR)/memalloc.h $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/input.h
-evalstring.o: $(topdir)/quit.h $(topdir)/unwind_prot.h
-evalstring.o: $(BASHINCDIR)/maxpath.h $(topdir)/jobs.h $(topdir)/builtins.h
-evalstring.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-evalstring.o: $(topdir)/externs.h $(topdir)/jobs.h $(topdir)/builtins.h
-evalstring.o: $(topdir)/flags.h $(topdir)/input.h $(topdir)/execute_cmd.h
-evalstring.o: $(topdir)/bashhist.h $(srcdir)/common.h
-evalstring.o: $(topdir)/trap.h $(topdir)/redir.h ../pathnames.h
-#evalstring.o: $(topdir)/y.tab.h
-getopt.o: ../config.h $(BASHINCDIR)/memalloc.h
-getopt.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/bashjmp.h $(topdir)/command.h
-getopt.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/error.h $(topdir)/variables.h $(topdir)/conftypes.h
-getopt.o: $(topdir)/quit.h $(BASHINCDIR)/maxpath.h $(topdir)/unwind_prot.h
-getopt.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-getopt.o: $(topdir)/sig.h ../pathnames.h $(topdir)/externs.h
-getopt.o: $(srcdir)/getopt.h
-mkbuiltins.o: ../config.h $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h
-mkbuiltins.o: ${BASHINCDIR}/filecntl.h
-mkbuiltins.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h
-
-# def files
-alias.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-alias.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h
-alias.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-alias.o: $(topdir)/subst.h $(topdir)/externs.h $(srcdir)/common.h
-alias.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-alias.o: ../pathnames.h
-bind.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
-bind.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-bind.o: $(topdir)/subst.h $(topdir)/externs.h $(srcdir)/bashgetopt.h
-bind.o: $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h $(topdir)/bashline.h
-bind.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-bind.o: ../pathnames.h
-break.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-break.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-break.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-break.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-break.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-break.o: ../pathnames.h
-builtin.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-builtin.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/externs.h
-builtin.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h
-builtin.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-builtin.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-builtin.o: $(srcdir)/bashgetopt.h ../pathnames.h
-caller.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
-caller.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/quit.h $(topdir)/dispose_cmd.h
-caller.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/externs.h
-caller.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-caller.o: $(srcdir)/common.h $(BASHINCDIR)/maxpath.h ./builtext.h
-caller.o: ${BASHINCDIR}/chartypes.h $(topdir)/bashtypes.h ../pathnames.h
-cd.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
-cd.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/quit.h $(topdir)/dispose_cmd.h
-cd.o: $(topdir)/make_cmd.h $(topdir)/subst.h $(topdir)/externs.h
-cd.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-cd.o: $(srcdir)/common.h $(BASHINCDIR)/maxpath.h ../pathnames.h
-command.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-command.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/externs.h
-command.o: $(topdir)/quit.h $(srcdir)/bashgetopt.h $(BASHINCDIR)/maxpath.h
-command.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-command.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-command.o: ../pathnames.h
-declare.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-declare.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-declare.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-declare.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-declare.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-declare.o: $(topdir)/arrayfunc.h $(srcdir)/bashgetopt.h
-declare.o: ./builtext.h ../pathnames.h
-echo.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
-echo.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
-echo.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-echo.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-echo.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
-enable.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-enable.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-enable.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-enable.o: $(topdir)/subst.h $(topdir)/externs.h
-enable.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-enable.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
-enable.o: $(topdir)/pcomplete.h
-eval.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-eval.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-eval.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-eval.o: $(topdir)/subst.h $(topdir)/externs.h
-eval.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-eval.o: $(BASHINCDIR)/maxpath.h ../pathnames.h
-exec.o: $(topdir)/bashtypes.h
-exec.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-exec.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-exec.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-exec.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/flags.h
-exec.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-exec.o: $(srcdir)/common.h $(topdir)/execute_cmd.h $(BASHINCDIR)/maxpath.h
-exec.o: $(topdir)/findcmd.h $(topdir)/jobs.h ../pathnames.h
-exit.o: $(topdir)/bashtypes.h
-exit.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-exit.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-exit.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-exit.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/jobs.h
-exit.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-exit.o: $(BASHINCDIR)/maxpath.h ./builtext.h ../pathnames.h
-fc.o: $(topdir)/bashtypes.h $(BASHINCDIR)/posixstat.h
-fc.o: $(topdir)/builtins.h $(topdir)/command.h $(srcdir)/bashgetopt.h
-fc.o: $(topdir)/bashhist.h
-fc.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
-fc.o: $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h
-fc.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-fc.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/shell.h $(topdir)/syntax.h
-fc.o: $(topdir)/flags.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-fc.o: $(topdir)/bashansi.h $(BASHINCDIR)/ansi_stdlib.h $(BASHINCDIR)/chartypes.h
-fc.o: ../pathnames.h
-fg_bg.o: $(topdir)/bashtypes.h $(srcdir)/bashgetopt.h
-fg_bg.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-fg_bg.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-fg_bg.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-fg_bg.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-fg_bg.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-fg_bg.o: $(topdir)/jobs.h ../pathnames.h
-getopts.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-getopts.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-getopts.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-getopts.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-getopts.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-getopts.o: ../pathnames.h
-hash.o: $(topdir)/builtins.h $(topdir)/command.h $(topdir)/quit.h
-hash.o: $(topdir)/findcmd.h $(topdir)/hashlib.h
-hash.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-hash.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-hash.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-hash.o: $(srcdir)/common.h $(BASHINCDIR)/maxpath.h ../pathnames.h
-help.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-help.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-help.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-help.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-help.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-help.o: ${srcdir}/common.h ../pathnames.h
-history.o: $(topdir)/bashtypes.h
-history.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-history.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-history.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-history.o: $(topdir)/subst.h $(topdir)/externs.h
-history.o: ${BASHINCDIR}/filecntl.h $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h
-history.o: $(topdir)/variables.h $(topdir)/conftypes.h $(topdir)/bashhist.h $(BASHINCDIR)/maxpath.h
-history.o: ../pathnames.h
-inlib.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-inlib.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-inlib.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-inlib.o: $(BASHINCDIR)/maxpath.h $(topdir)/subst.h $(topdir)/externs.h
-inlib.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h ../pathnames.h
-jobs.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
-jobs.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/quit.h $(srcdir)/bashgetopt.h
-jobs.o: $(BASHINCDIR)/maxpath.h $(topdir)/externs.h $(topdir)/jobs.h
-jobs.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-jobs.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-jobs.o: ../pathnames.h
-kill.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/error.h
-kill.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
-kill.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-kill.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/trap.h $(topdir)/unwind_prot.h
-kill.o: $(topdir)/variables.h $(topdir)/conftypes.h $(BASHINCDIR)/maxpath.h
-kill.o: $(topdir)/jobs.h ../pathnames.h
-let.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-let.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-let.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-let.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-let.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-let.o: ../pathnames.h
-printf.o: ../config.h $(BASHINCDIR)/memalloc.h $(topdir)/bashjmp.h
-printf.o: $(topdir)/command.h $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-printf.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-printf.o: $(topdir)/subst.h $(topdir)/externs.h $(topdir)/sig.h
-printf.o: ../pathnames.h $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h
-printf.o: $(topdir)/variables.h $(topdir)/conftypes.h $(BASHINCDIR)/stdc.h $(srcdir)/bashgetopt.h
-printf.o: $(topdir)/bashtypes.h ${srcdir}/common.h $(BASHINCDIR)/chartypes.h
-printf.o: ../pathnames.h
-pushd.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-pushd.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-pushd.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-pushd.o: $(topdir)/subst.h $(topdir)/externs.h
-pushd.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-pushd.o: $(BASHINCDIR)/maxpath.h $(srcdir)/common.h ./builtext.h
-pushd.o: ../pathnames.h
-read.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-read.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-read.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-read.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-read.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-read.o: $(BASHINCDIR)/shtty.h
-read.o: $(topdir)/arrayfunc.h ../pathnames.h
-return.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-return.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-return.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-return.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-return.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-return.o: ../pathnames.h
-set.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-set.o: $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/subst.h $(topdir)/externs.h
-set.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-set.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-set.o: $(BASHINCDIR)/maxpath.h $(topdir)/error.h
-set.o: $(topdir)/arrayfunc.h ../pathnames.h
-setattr.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-setattr.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(BASHINCDIR)/maxpath.h
-setattr.o: $(topdir)/quit.h $(srcdir)/common.h $(srcdir)/bashgetopt.h
-setattr.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-setattr.o: $(topdir)/externs.h
-setattr.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-setattr.o: $(topdir)/arrayfunc.h ../pathnames.h
-shift.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-shift.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-shift.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-shift.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-shift.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-shift.o: ../pathnames.h
-shopt.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-shopt.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-shopt.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-shopt.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-shopt.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-shopt.o: $(srcdir)/common.h $(srcdir)/bashgetopt.h ../pathnames.h
-shopt.o: $(topdir)/bashhist.h $(topdir)/bashline.h
-source.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-source.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/findcmd.h
-source.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-source.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-source.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-source.o: $(srcdir)/bashgetopt.h $(topdir)/flags.h $(topdir)/trap.h
-source.o: ../pathnames.h
-suspend.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-suspend.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-suspend.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-suspend.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-suspend.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-suspend.o: $(topdir)/jobs.h ../pathnames.h
-test.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-test.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-test.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-test.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-test.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-test.o: $(topdir)/test.h ../pathnames.h
-times.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-times.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-times.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-times.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-times.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-times.o: $(BASHINCDIR)/posixtime.h ../pathnames.h
-trap.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-trap.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h $(topdir)/externs.h
-trap.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h
-trap.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-trap.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-trap.o: $(topdir)/findcmd.h ../pathnames.h
-type.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-type.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-type.o: $(topdir)/quit.h $(srcdir)/common.h $(BASHINCDIR)/maxpath.h
-type.o: $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h $(topdir)/subst.h
-type.o: $(topdir)/externs.h $(topdir)/hashcmd.h ../pathnames.h
-type.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-ulimit.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-ulimit.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-ulimit.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-ulimit.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-ulimit.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-ulimit.o: ../pathnames.h
-umask.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-umask.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-umask.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-umask.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-umask.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-umask.o: $(BASHINCDIR)/chartypes.h ../pathnames.h
-wait.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-wait.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-wait.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-wait.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-wait.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/unwind_prot.h $(topdir)/variables.h $(topdir)/conftypes.h
-wait.o: $(topdir)/jobs.h
-wait.o: $(BASHINCDIR)/chartypes.h ../pathnames.h
-
-complete.o: ../config.h ../pathnames.h
-complete.o: ${topdir}/shell.h $(topdir)/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h ${topdir}/sig.h
-complete.o: ${topdir}/unwind_prot.h ${topdir}/variables.h
-complete.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
-complete.o: ${topdir}/builtins.h
-complete.o: ${topdir}/pcomplete.h
-complete.o: ${srcdir}/common.h ${srcdir}/bashgetopt.h
-mapfile.o: $(topdir)/command.h ../config.h $(BASHINCDIR)/memalloc.h
-mapfile.o: $(topdir)/error.h $(topdir)/general.h $(topdir)/xmalloc.h
-mapfile.o: $(topdir)/quit.h $(topdir)/dispose_cmd.h $(topdir)/make_cmd.h
-mapfile.o: $(topdir)/subst.h $(topdir)/externs.h $(BASHINCDIR)/maxpath.h
-mapfile.o: $(topdir)/shell.h $(topdir)/syntax.h $(topdir)/variables.h $(topdir)/conftypes.h
-mapfile.o: $(topdir)/arrayfunc.h ../pathnames.h
-
-#bind.o: $(RL_LIBSRC)chardefs.h $(RL_LIBSRC)readline.h $(RL_LIBSRC)keymaps.h
-
-# libintl dependencies
-bind.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-break.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-caller.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-cd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-common.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-complete.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-declare.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-enable.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-evalfile.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-exec.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-exit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-fc.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-fg_bg.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-getopt.c: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-hash.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-help.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-history.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-inlib.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-jobs.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-kill.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-let.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-mapfile.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-mkbuiltins.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-printf.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-pushd.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-read.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-return.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-set.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-setattr.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-shift.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-shopt.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-source.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-suspend.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-type.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-ulimit.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
-umask.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
+++ /dev/null
-/* evalstring.c - evaluate a string as one or more shell commands. */
-
-/* Copyright (C) 1996-2010 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#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"
-#include "../bashintl.h"
-
-#include <y.tab.h>
-
-#if defined (HISTORY)
-# include "../bashhist.h"
-#endif
-
-#include "common.h"
-#include "builtext.h"
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-#define IS_BUILTIN(s) (builtin_address_internal(s, 0) != (struct builtin *)NULL)
-
-extern int indirection_level, subshell_environment;
-extern int line_number;
-extern int current_token, shell_eof_token;
-extern int last_command_exit_value;
-extern int running_trap;
-extern int loop_level;
-extern int executing_list;
-extern int comsub_ignore_return;
-extern int posixly_correct;
-extern sh_builtin_func_t *this_shell_builtin;
-
-int parse_and_execute_level = 0;
-
-static int cat_file __P((REDIRECT *));
-
-#define PE_TAG "parse_and_execute top"
-#define PS_TAG "parse_string top"
-
-#if defined (HISTORY)
-static void
-set_history_remembering ()
-{
- remember_on_history = enable_history_list;
-}
-#endif
-
-/* 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 ();
- }
-
- if (have_unwind_protects ())
- run_unwind_frame (PE_TAG);
- else
- parse_and_execute_level = 0; /* XXX */
-}
-
-static void
-parse_prologue (string, flags, tag)
- char *string;
- int flags;
- char *tag;
-{
- char *orig_string;
- int x;
-
- orig_string = string;
- /* Unwind protect this invocation of parse_and_execute (). */
- begin_unwind_frame (tag);
- 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);
- unwind_protect_int (executing_list);
- unwind_protect_int (comsub_ignore_return);
- if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
- unwind_protect_int (interactive);
-
-#if defined (HISTORY)
- if (parse_and_execute_level == 0)
- add_unwind_protect (set_history_remembering, (char *)NULL);
- else
- 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 ();
-
- if (flags & (SEVAL_NONINT|SEVAL_INTERACT))
- interactive = (flags & SEVAL_NONINT) ? 0 : 1;
-
-#if defined (HISTORY)
- if (flags & SEVAL_NOHIST)
- bash_history_disable ();
-#endif /* HISTORY */
-}
-
-/* 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, lreset;
- volatile int should_jump_to_top_level, last_result;
- COMMAND *volatile command;
-
- parse_prologue (string, flags, PE_TAG);
-
- parse_and_execute_level++;
-
- lreset = flags & SEVAL_RESETLINE;
-
- /* 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++;
-
- 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 ((flags & SEVAL_PARSEONLY) || (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 ((subshell_environment & SUBSHELL_COMSUB) && comsub_ignore_return)
- command->flags |= CMD_IGNORE_RETURN;
-
-#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're not going to run the exit trap 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 &&
- signal_is_trapped (EXIT_TRAP) == 0 &&
- command->redirects == 0 && command->value.Simple->redirects == 0 &&
- ((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 &&
- command->value.Simple->redirects->redirector.dest == 1)
- {
- 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;
-
- if (interactive_shell == 0 && this_shell_builtin &&
- (this_shell_builtin == source_builtin || this_shell_builtin == eval_builtin) &&
- last_command_exit_value == EX_BADSYNTAX && posixly_correct)
- {
- should_jump_to_top_level = 1;
- code = ERREXIT;
- last_command_exit_value = EX_BADUSAGE;
- }
-
- /* Since we are shell compatible, syntax errors in a script
- abort the execution of the script. Right? */
- break;
- }
- }
-
- out:
-
- run_unwind_frame (PE_TAG);
-
- 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);
-}
-
-/* Parse a command contained in STRING according to FLAGS and return the
- number of characters consumed from the string. If non-NULL, set *ENDP
- to the position in the string where the parse ended. Used to validate
- command substitutions during parsing to obey Posix rules about finding
- the end of the command and balancing parens. */
-int
-parse_string (string, from_file, flags, endp)
- char *string;
- const char *from_file;
- int flags;
- char **endp;
-{
- int code, nc;
- volatile int should_jump_to_top_level;
- COMMAND *volatile command, *oglobal;
- char *ostring;
-
- parse_prologue (string, flags, PS_TAG);
-
- /* 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 (0);
-
- code = should_jump_to_top_level = 0;
- oglobal = global_command;
- ostring = string;
-
- with_input_from_string (string, from_file);
- while (*(bash_input.location.string))
- {
- command = (COMMAND *)NULL;
-
-#if 0
- if (interrupt_state)
- break;
-#endif
-
- /* Provide a location for functions which `longjmp (top_level)' to
- jump to. */
- code = setjmp (top_level);
-
- if (code)
- {
-#if defined (DEBUG)
-itrace("parse_string: longjmp executed: code = %d", code);
-#endif
- should_jump_to_top_level = 0;
- switch (code)
- {
- case FORCE_EOF:
- case ERREXIT:
- case EXITPROG:
- case DISCARD: /* XXX */
- if (command)
- dispose_command (command);
- /* Remember to call longjmp (top_level) after the old
- value for it is restored. */
- should_jump_to_top_level = 1;
- goto out;
-
- default:
- command_error ("parse_string", CMDERR_BADJUMP, code, 0);
- break;
- }
- }
-
- if (parse_command () == 0)
- {
- dispose_command (global_command);
- global_command = (COMMAND *)NULL;
- }
- else
- {
- if ((flags & SEVAL_NOLONGJMP) == 0)
- {
- should_jump_to_top_level = 1;
- code = DISCARD;
- }
- else
- reset_parser (); /* XXX - sets token_to_read */
- break;
- }
-
- if (current_token == yacc_EOF || current_token == shell_eof_token)
- break;
- }
-
- out:
-
- global_command = oglobal;
- nc = bash_input.location.string - ostring;
- if (endp)
- *endp = bash_input.location.string;
-
- run_unwind_frame (PS_TAG);
-
- if (should_jump_to_top_level)
- jump_to_top_level (code);
-
- return (nc);
-}
-
-/* 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);
-}
+++ /dev/null
-/* gen-helpfiles - create files containing builtin help text */
-
-/* Copyright (C) 2012 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#if !defined (CROSS_COMPILING)
-# 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"
-
-#include "../builtins.h"
-#include "tmpbuiltins.h"
-
-#ifndef errno
-extern int errno;
-#endif
-
-#if !defined (__STDC__) && !defined (strcpy)
-extern char *strcpy ();
-#endif /* !__STDC__ && !strcpy */
-
-#define whitespace(c) (((c) == ' ') || ((c) == '\t'))
-
-/* Flag values that builtins can have. */
-#define BUILTIN_FLAG_SPECIAL 0x01
-#define BUILTIN_FLAG_ASSIGNMENT 0x02
-#define BUILTIN_FLAG_POSIX_BUILTIN 0x04
-
-#define BASE_INDENT 4
-
-/* 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;
-
-/* Forward declarations. */
-
-int write_helpfiles ();
-
-/* 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;
-
- while (arg_index < argc && argv[arg_index][0] == '-')
- {
- char *arg = argv[arg_index++];
-
- if (strcmp (arg, "-noproduction") == 0)
- ;
- else if (strcmp (arg, "-H") == 0)
- 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);
- }
- }
-
- write_helpfiles(shell_builtins);
-
- exit (0);
-}
-
-/* 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)
- FILE *stream;
- char *documentation;
- int indentation;
-{
- if (stream == 0)
- return;
-
- if (documentation)
- fprintf (stream, "%*s%s\n", indentation, " ", documentation);
-}
-
-int
-write_helpfiles (builtins)
- struct builtin *builtins;
-{
- char *helpfile, *bname, *fname;
- FILE *helpfp;
- int i, hdlen;
- struct builtin b;
-
- 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 < num_shell_builtins; i++)
- {
- b = builtins[i];
-
- fname = (char *)b.handle;
- helpfile = (char *)malloc (hdlen + strlen (fname) + 1);
- if (helpfile == 0)
- {
- fprintf (stderr, "gen-helpfiles: cannot allocate memory\n");
- exit (1);
- }
- sprintf (helpfile, "helpfiles/%s", fname);
-
- helpfp = fopen (helpfile, "w");
- if (helpfp == 0)
- {
- fprintf (stderr, "write_helpfiles: cannot open %s\n", helpfile);
- free (helpfile);
- continue;
- }
-
- write_documentation (helpfp, b.long_doc[0], 4);
-
- fflush (helpfp);
- fclose (helpfp);
- free (helpfile);
- }
- return 0;
-}
+++ /dev/null
-/* mkbuiltins.c - Create builtins.c, builtext.h, and builtdoc.c from
- a single source file called builtins.def. */
-
-/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#if !defined (CROSS_COMPILING)
-# 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 BUILTIN_FLAG_POSIX_BUILTIN 0x04
-
-#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 not add functions (xxx_builtin) to the members of the
- produced `struct builtin []' */
-int inhibit_functions = 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
-};
-
-/* The builtin commands that are special to the POSIX search order. */
-char *posix_builtins[] =
-{
- "alias", "bg", "cd", "command", "false", "fc", "fg", "getopts", "jobs",
- "kill", "newgrp", "pwd", "read", "true", "umask", "unalias", "wait",
- (char *)NULL
-};
-
-/* Forward declarations. */
-static int is_special_builtin ();
-static int is_assignment_builtin ();
-static int is_posix_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)
-
-\f
-/* 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, "-nofunctions") == 0)
- inhibit_functions = 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);
- free (buffer);
- 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 (i < file_size && buffer[i] != '\n')
- 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;
- if (is_posix_builtin (name))
- new->flags |= BUILTIN_FLAG_POSIX_BUILTIN;
-
- 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-2012 Free Software Foundation, Inc.",
- "",
- " This file is part of GNU Bash, the Bourne Again SHell.",
- "",
- " Bash is free software: you can redistribute it and/or modify",
- " it under the terms of the GNU General Public License as published by",
- " the Free Software Foundation, either version 3 of the License, or",
- " (at your option) any later version.",
- "",
- " Bash is distributed in the hope that it will be useful,",
- " but WITHOUT ANY WARRANTY; without even the implied warranty of",
- " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
- " GNU General Public License for more details.",
- "",
- " You should have received a copy of the GNU General Public License",
- " along with Bash. If not, see <http://www.gnu.org/licenses/>.",
- "*/",
- "",
- "/* 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, (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 && inhibit_functions == 0)
- fprintf (structfile, "%s, ", builtin->function);
- else
- fprintf (structfile, "(sh_builtin_func_t *)0x0, ");
-
- fprintf (structfile, "%s%s%s%s, %s_doc,\n",
- "BUILTIN_ENABLED | STATIC_BUILTIN",
- (builtin->flags & BUILTIN_FLAG_SPECIAL) ? " | SPECIAL_BUILTIN" : "",
- (builtin->flags & BUILTIN_FLAG_ASSIGNMENT) ? " | ASSIGNMENT_BUILTIN" : "",
- (builtin->flags & BUILTIN_FLAG_POSIX_BUILTIN) ? " | POSIX_BUILTIN" : "",
- document_name (builtin));
-
- if (inhibit_functions)
- fprintf
- (structfile, " N_(\"%s\"), \"%s\" },\n",
- builtin->shortdoc ? builtin->shortdoc : builtin->name,
- document_name (builtin));
- else
- fprintf
- (structfile, " N_(\"%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);
-
- }
-}
-
-void
-write_dummy_declarations (stream, builtins)
- FILE *stream;
- ARRAY *builtins;
-{
- register int i;
- BUILTIN_DESC *builtin;
-
- for (i = 0; structfile_header[i]; i++)
- fprintf (stream, "%s\n", structfile_header[i]);
-
- for (i = 0; i < builtins->sindex; i++)
- {
- builtin = (BUILTIN_DESC *)builtins->array[i];
-
- /* How to guarantee that no builtin is written more than once? */
- fprintf (stream, "int %s () { return (0); }\n", builtin->function);
- }
-}
-
-/* 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, filename_p;
-
- if (stream == 0)
- 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)
- {
- if (documentation && documentation[0] && documentation[0][0])
- fprintf (stream, "N_(\"");
- else
- 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 = 0, texinfo = (flags & TEXINFO); documentation && (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);
- continue;
- }
-
- /* prefix with N_( for gettext */
- if (string_array && single_longdoc_strings == 0)
- {
- if (filename_p == 0)
- {
- if (line[0])
- fprintf (stream, " N_(\"");
- else
- 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));
-}
-
-static int
-is_posix_builtin (name)
- char *name;
-{
- return (_find_in_table (name, posix_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 */
+++ /dev/null
-This file is printf.def, from which is created printf.c.
-It implements the builtin "printf" in Bash.
-
-Copyright (C) 1997-2010 Free Software Foundation, Inc.
-
-This file is part of GNU Bash, the Bourne Again SHell.
-
-Bash is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-Bash is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Bash. If not, see <http://www.gnu.org/licenses/>.
-
-$PRODUCES printf.c
-
-$BUILTIN printf
-$FUNCTION printf_builtin
-$SHORT_DOC printf [-v var] format [arguments]
-Formats and prints ARGUMENTS under control of the FORMAT.
-
-Options:
- -v var assign the output to shell variable VAR rather than
- display it on the standard output
-
-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 format specifications described in printf(1),
-printf interprets:
-
- %b expand backslash escape sequences in the corresponding argument
- %q quote the argument in a way that can be reused as shell input
- %(fmt)T output the date-time string resulting from using FMT as a format
- string for strftime(3)
-
-Exit Status:
-Returns success unless an invalid option is given or a write or assignment
-error occurs.
-$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
-
-#if defined (PREFER_STDARG)
-# include <stdarg.h>
-#else
-# include <varargs.h>
-#endif
-
-#include <stdio.h>
-#include <chartypes.h>
-
-#ifdef HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-
-#include "posixtime.h"
-#include "../bashansi.h"
-#include "../bashintl.h"
-
-#define NEED_STRFTIME_DECL
-
-#include "../shell.h"
-#include "shmbutil.h"
-#include "stdc.h"
-#include "bashgetopt.h"
-#include "common.h"
-
-#if defined (PRI_MACROS_BROKEN)
-# undef PRIdMAX
-#endif
-
-#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 { \
- int nw; \
- clearerr (stdout); \
- if (have_fieldwidth && have_precision) \
- nw = vflag ? vbprintf (f, fieldwidth, precision, func) : printf (f, fieldwidth, precision, func); \
- else if (have_fieldwidth) \
- nw = vflag ? vbprintf (f, fieldwidth, func) : printf (f, fieldwidth, func); \
- else if (have_precision) \
- nw = vflag ? vbprintf (f, precision, func) : printf (f, precision, func); \
- else \
- nw = vflag ? vbprintf (f, func) : printf (f, func); \
- tw += nw; \
- if (ferror (stdout)) \
- { \
- sh_wrerror (); \
- clearerr (stdout); \
- return (EXECUTION_FAILURE); \
- } \
- } while (0)
-
-/* We free the buffer used by mklong() if it's `too big'. */
-#define PRETURN(value) \
- do \
- { \
- if (vflag) \
- { \
- bind_printf_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; \
- } \
- else if (vbuf) \
- vbuf[0] = 0; \
- terminate_immediately--; \
- if (ferror (stdout) == 0) \
- fflush (stdout); \
- if (ferror (stdout)) \
- { \
- sh_wrerror (); \
- clearerr (stdout); \
- return (EXECUTION_FAILURE); \
- } \
- return (value); \
- } \
- while (0)
-
-#define SKIP1 "#'-+ 0"
-#define LENMODS "hjlLtz"
-
-extern time_t shell_start_time;
-
-#if !HAVE_ASPRINTF
-extern int asprintf __P((char **, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
-#endif
-
-#if !HAVE_VSNPRINTF
-extern int vsnprintf __P((char *, size_t, const char *, va_list)) __attribute__((__format__ (printf, 3, 0)));
-#endif
-
-static void printf_erange __P((char *));
-static int printstr __P((char *, char *, int, int, int));
-static int tescape __P((char *, char *, int *, int *));
-static char *bexpand __P((char *, int, int *, int *));
-static char *vbadd __P((char *, int));
-static int vbprintf __P((const char *, ...)) __attribute__((__format__ (printf, 1, 2)));
-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));
-static SHELL_VAR *bind_printf_variable __P((char *, char *, int));
-
-#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 intmax_t 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;
-#if defined (HANDLE_MULTIBYTE)
- char mbch[25]; /* 25 > MB_LEN_MAX, plus can handle 4-byte UTF-8 and large Unicode characters*/
- int mbind, mblen;
-#endif
-
- conversion_error = 0;
- retval = EXECUTION_SUCCESS;
-
- vflag = 0;
-
- reset_internal_getopt ();
- while ((ch = internal_getopt (list, "v:")) != -1)
- {
- switch (ch)
- {
- case 'v':
- vname = list_optarg;
-#if defined (ARRAY_VARS)
- if (legal_identifier (vname) || valid_array_reference (vname))
-#else
- if (legal_identifier (vname))
-#endif
- {
- vflag = 1;
- if (vbsize == 0)
- vbuf = xmalloc (vbsize = 16);
- vblen = 0;
- if (vbuf)
- vbuf[0] = 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);
-
- terminate_immediately++;
-
- /* 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. */
-#if defined (HANDLE_MULTIBYTE)
- /* Accommodate possible use of \u or \U, which can result in
- multibyte characters */
- memset (mbch, '\0', sizeof (mbch));
- fmt += tescape (fmt, mbch, &mblen, (int *)NULL);
- for (mbind = 0; mbind < mblen; mbind++)
- PC (mbch[mbind]);
-#else
- fmt += tescape (fmt, &nextch, (int *)NULL, (int *)NULL);
- PC (nextch);
-#endif
- 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 '(':
- {
- char *timefmt, timebuf[128], *t;
- int n;
- intmax_t arg;
- time_t secs;
- struct tm *tm;
-
- modstart[1] = nextch; /* restore char after left paren */
- timefmt = xmalloc (strlen (fmt) + 3);
- fmt++; /* skip over left paren */
- for (t = timefmt, n = 1; *fmt; )
- {
- if (*fmt == '(')
- n++;
- else if (*fmt == ')')
- n--;
- if (n == 0)
- break;
- *t++ = *fmt++;
- }
- *t = '\0';
- if (*++fmt != 'T')
- {
- builtin_warning (_("`%c': invalid time format specification"), *fmt);
- fmt = start;
- free (timefmt);
- PC (*fmt);
- continue;
- }
- if (timefmt[0] == '\0')
- {
- timefmt[0] = '%';
- timefmt[1] = 'X'; /* locale-specific current time - should we use `+'? */
- timefmt[2] = '\0';
- }
- /* argument is seconds since the epoch with special -1 and -2 */
- arg = getintmax ();
- if (arg == -1)
- secs = NOW; /* roughly date +%s */
- else if (arg == -2)
- secs = shell_start_time; /* roughly $SECONDS */
- else
- secs = arg;
-#if defined (HAVE_TZSET)
- sv_tz ("TZ"); /* XXX -- just make sure */
-#endif
- tm = localtime (&secs);
- n = strftime (timebuf, sizeof (timebuf), timefmt, tm);
- free (timefmt);
- if (n == 0)
- timebuf[0] = '\0';
- else
- timebuf[sizeof(timebuf) - 1] = '\0';
- /* convert to %s format that preserves fieldwidth and precision */
- modstart[0] = 's';
- modstart[1] = '\0';
- n = printstr (start, timebuf, strlen (timebuf), fieldwidth, precision); /* XXX - %s for now */
- if (n < 0)
- {
- if (ferror (stdout) == 0)
- {
- sh_wrerror ();
- clearerr (stdout);
- }
- PRETURN (EXECUTION_FAILURE);
- }
- 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)
- {
- if (ferror (stdout) == 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 (p && *p == 0) /* XXX - getstr never returns null */
- xp = savestring ("''");
- else if (ansic_shouldquote (p))
- xp = ansic_quote (p, 0, (int *)0);
- else
- xp = sh_backslash_quote (p, 0);
- 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))
- {
- /* PRETURN will print error message. */
- 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 */
- intmax_t mfw, mpr;
-
- if (string == 0 || len == 0)
- return 0;
-
-#if 0
- s = fmt;
-#endif
- if (*fmt == '%')
- fmt++;
-
- ljust = fw = 0;
- pr = -1;
- mfw = 0;
- mpr = -1;
-
- /* skip flags */
- while (strchr (SKIP1, *fmt))
- {
- if (*fmt == '-')
- ljust = 1;
- fmt++;
- }
-
- /* get fieldwidth, if present. rely on caller to clamp fieldwidth at INT_MAX */
- if (*fmt == '*')
- {
- fmt++;
- fw = fieldwidth;
- if (fw < 0)
- {
- fw = -fw;
- ljust = 1;
- }
- }
- else if (DIGIT (*fmt))
- {
- mfw = *fmt++ - '0';
- while (DIGIT (*fmt))
- mfw = (mfw * 10) + (*fmt++ - '0');
- /* Error if fieldwidth > INT_MAX here? */
- fw = (mfw < 0 || mfw > INT_MAX) ? INT_MAX : mfw;
- }
-
- /* get precision, if present */
- if (*fmt == '.')
- {
- fmt++;
- if (*fmt == '*')
- {
- fmt++;
- pr = precision;
- }
- else if (DIGIT (*fmt))
- {
- mpr = *fmt++ - '0';
- while (DIGIT (*fmt))
- mpr = (mpr * 10) + (*fmt++ - '0');
- /* Error if precision > INT_MAX here? */
- pr = (mpr < 0 || mpr > INT_MAX) ? INT_MAX : mpr;
- }
- }
-
-#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, lenp, sawc)
- char *estart;
- char *cp;
- int *lenp, *sawc;
-{
- register char *p;
- int temp, c, evalue;
- unsigned long uvalue;
-
- p = estart;
- if (lenp)
- *lenp = 1;
-
- 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 \xNN, where each N is a
- hex digit. */
- case 'x':
- for (temp = 2, evalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
- evalue = (evalue * 16) + HEXVALUE (*p);
- if (p == estart + 1)
- {
- builtin_error (_("missing hex digit for \\x"));
- *cp = '\\';
- return 0;
- }
- *cp = evalue & 0xFF;
- break;
-
-#if defined (HANDLE_MULTIBYTE)
- case 'u':
- case 'U':
- temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
- for (uvalue = 0; ISXDIGIT ((unsigned char)*p) && temp--; p++)
- uvalue = (uvalue * 16) + HEXVALUE (*p);
- if (p == estart + 1)
- {
- builtin_error (_("missing unicode digit for \\%c"), c);
- *cp = '\\';
- return 0;
- }
- if (uvalue <= UCHAR_MAX)
- *cp = uvalue;
- else
- {
- temp = u32cconv (uvalue, cp);
- cp[temp] = '\0';
- if (lenp)
- *lenp = temp;
- }
- break;
-#endif
-
- 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 defined (HANDLE_MULTIBYTE)
- char mbch[25];
- int mbind, mblen;
-#endif
-
- if (string == 0 || len == 0)
- {
- 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;
-#if defined (HANDLE_MULTIBYTE)
- memset (mbch, '\0', sizeof (mbch));
- s += tescape (s, mbch, &mblen, &temp);
-#else
- s += tescape (s, &c, (int *)NULL, &temp);
-#endif
- if (temp)
- {
- if (sawc)
- *sawc = 1;
- break;
- }
-
-#if defined (HANDLE_MULTIBYTE)
- for (mbind = 0; mbind < mblen; mbind++)
- *r++ = mbch[mbind];
-#else
- *r++ = c;
-#endif
- }
-
- *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 if (blen > 1)
- {
- 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, (int)strlen (vbuf));
-#endif
-
- return vbuf;
-}
-
-static int
-#if defined (PREFER_STDARG)
-vbprintf (const char *format, ...)
-#else
-vbprintf (format, va_alist)
- const char *format;
- va_dcl
-#endif
-{
- va_list args;
- size_t nlen;
- int blen;
-
- SH_VA_START (args, format);
- blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
- va_end (args);
-
- nlen = vblen + blen + 1;
- if (nlen >= vbsize)
- {
- vbsize = ((nlen + 63) >> 6) << 6;
- vbuf = (char *)xrealloc (vbuf, vbsize);
- SH_VA_START (args, format);
- blen = vsnprintf (vbuf + vblen, vbsize - vblen, format, args);
- va_end (args);
- }
-
- vblen += blen;
- vbuf[vblen] = '\0';
-
-#ifdef DEBUG
- if (strlen (vbuf) != vblen)
- internal_error ("printf:vbadd: vblen (%d) != strlen (vbuf) (%d)", vblen, (int)strlen (vbuf));
-#endif
-
- return (blen);
-}
-
-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 (garglist == 0)
- return ret;
-
- 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. */
-#if 0
- ret = 0; /* return partially-converted value from strtoimax */
-#endif
- 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 intmax_t
-asciicode ()
-{
- register intmax_t ch;
-#if defined (HANDLE_MULTIBYTE)
- wchar_t wc;
- size_t mblength, slen;
-#endif
- DECLARE_MBSTATE;
-
-#if defined (HANDLE_MULTIBYTE)
- slen = strlen (garglist->word->word+1);
- mblength = MBLEN (garglist->word->word+1, slen);
- if (mblength > 1)
- {
- mblength = mbtowc (&wc, garglist->word->word+1, slen);
- ch = wc; /* XXX */
- }
- else
-#endif
- ch = (unsigned char)garglist->word->word[1];
-
- garglist = garglist->next;
- return (ch);
-}
-
-static SHELL_VAR *
-bind_printf_variable (name, value, flags)
- char *name;
- char *value;
- int flags;
-{
-#if defined (ARRAY_VARS)
- if (valid_array_reference (name) == 0)
- return (bind_variable (name, value, flags));
- else
- return (assign_array_element (name, value, flags));
-#else /* !ARRAY_VARS */
- return bind_variable (name, value, flags);
-#endif /* !ARRAY_VARS */
-}
+++ /dev/null
-dnl
-dnl Configure script for bash-4.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-2012 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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
-
-AC_REVISION([for Bash 4.2, version 4.045])dnl
-
-define(bashvers, 4.2)
-define(relstatus, maint)
-
-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*|maint*) 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
-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='${datadir}/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_coproc=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
-opt_casemod_attrs=yes
-opt_casemod_expansions=yes
-opt_extglob_default=no
-
-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 opt_coproc=no
- opt_casemod_attrs=no opt_casemod_expansions=no opt_extglob_default=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(casemod-attributes, AC_HELP_STRING([--enable-casemod-attributes], [include case-modifying variable attributes]), opt_casemod_attrs=$enableval)
-AC_ARG_ENABLE(casemod-expansions, AC_HELP_STRING([--enable-casemod-expansions], [include case-modifying word expansions]), opt_casemod_expansions=$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 extended regular expression matching in conditional commands]), opt_cond_regexp=$enableval)
-AC_ARG_ENABLE(coprocesses, AC_HELP_STRING([--enable-coprocesses], [enable coprocess support and the coproc reserved word]), opt_coproc=$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(extended-glob-default, AC_HELP_STRING([--enable-extended-glob-default], [force extended pattern matching to be enabled by default]), opt_extglob_default=$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 So-called `precious' variables
-AC_ARG_VAR([CC_FOR_BUILD], [C compiler used when compiling binaries used only at build time])
-AC_ARG_VAR([CFLAGS_FOR_BUILD], [Compliation options (CFLAGS) used when compiling binaries used only at build time])
-AC_ARG_VAR([LDFLAGS_FOR_BUILD], [Linker options (LDFLAGS) used when compiling binaries used only at build time])
-AC_ARG_VAR([CPPFLAGS_FOR_BUILD], [C preprocessor options (CPPFLAGS) used when compiling binaries used only at build time])
-
-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_extglob_default = yes; then
-AC_DEFINE(EXTGLOB_DEFAULT, 1)
-else
-AC_DEFINE(EXTGLOB_DEFAULT, 0)
-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_coproc = yes; then
-AC_DEFINE(COPROCESS_SUPPORT)
-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_casemod_attrs = yes; then
-AC_DEFINE(CASEMOD_ATTRS)
-fi
-if test $opt_casemod_expansions = yes; then
-AC_DEFINE(CASEMOD_EXPANSIONS)
-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)
-
-dnl END changes for cross-building
-
-dnl We want these before the checks, so the checks can modify their values.
-if test -z "$CFLAGS"; then
- AUTO_CFLAGS="-g ${GCC+-O2}"
- AUTO_LDFLAGS="-g ${GCC+-O2}"
-else
- AUTO_CFLAGS= AUTO_LDFLAGS=
-fi
-
-dnl default values
-CFLAGS=${CFLAGS-"$AUTO_CFLAGS"}
-# LDFLAGS=${LDFLAGS="$AUTO_LDFLAGS"} # XXX
-
-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
-
-prefer_shared=yes
-prefer_static=no
-
-if test "$opt_static_link" = yes; then
- prefer_static=yes
- prefer_shared=no
- # 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
-
-# set the appropriate make variables for building the "build tools"
-
-if test "X$cross_compiling" = "Xno"; then
- CC_FOR_BUILD=${CC_FOR_BUILD-'$(CC)'}
- CPPFLAGS_FOR_BUILD=${CPPFLAGS_FOR_BUILD-"$CPPFLAGS"} # XXX - should it be '$(CPPFLAGS)'
- LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-'$(LDFLAGS)'}
- # CFLAGS set above to default value if not passed in environment
- CFLAGS_FOR_BUILD=${CFLAGS-'$(CFLAGS)'}
- LIBS_FOR_BUILD=${LIBS_FOR_BUILD-'$(LIBS)'}
-else
- CC_FOR_BUILD=${CC_FOR_BUILD-"gcc"}
- CPPFLAGS_FOR_BUILD=${CPPFLAGS_FOR_BUILD-""}
- LDFLAGS_FOR_BUILD=${LDFLAGS_FOR_BUILD-""}
- CFLAGS_FOR_BUILD=${CFLAGS_FOR_BUILD="-g"}
- LIBS_FOR_BUILD=${LIBS_FOR_BUILD-""}
-fi
-
-AC_SUBST(CFLAGS)
-AC_SUBST(CPPFLAGS)
-AC_SUBST(LDFLAGS)
-AC_SUBST(STATIC_LD)
-
-AC_SUBST(CC_FOR_BUILD)
-AC_SUBST(CFLAGS_FOR_BUILD)
-AC_SUBST(CPPFLAGS_FOR_BUILD)
-AC_SUBST(LDFLAGS_FOR_BUILD)
-AC_SUBST(LIBS_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
- darwin[[89]]*|darwin10*) 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
- darwin[[89]]*|darwin10*) 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
-AC_C_VOLATILE
-AC_C_RESTRICT
-
-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 \
- stdbool.h stddef.h stdint.h netdb.h pwd.h grp.h strings.h \
- regex.h syslog.h ulimit.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))
-
-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 \
- setitimer tcgetpgrp uname ulimit waitpid)
-AC_REPLACE_FUNCS(rename)
-
-dnl checks for c library functions
-AC_CHECK_FUNCS(bcopy bzero confstr faccessat fnmatch \
- getaddrinfo gethostbyname getservbyname getservent inet_aton \
- imaxdiv memmove pathconf putenv raise regcomp regexec \
- setenv setlinebuf setlocale setvbuf siginterrupt strchr \
- sysconf syslog tcgetattr times ttyname tzset unsetenv)
-
-AC_CHECK_FUNCS(vasprintf asprintf)
-AC_CHECK_FUNCS(isascii isblank isgraph isprint isspace isxdigit)
-AC_CHECK_FUNCS(getpwent getpwnam getpwuid)
-AC_REPLACE_FUNCS(getcwd memset)
-AC_REPLACE_FUNCS(strcasecmp strcasestr strerror strftime strnlen strpbrk strstr)
-AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax)
-AC_REPLACE_FUNCS(dprintf)
-AC_REPLACE_FUNCS(strchrnul)
-
-AC_CHECK_DECLS([AUDIT_USER_TTY],,, [[#include <linux/audit.h>]])
-
-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 HAVE_DECL_SYS_SIGLIST
-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
-BASH_TYPE_SIG_ATOMIC_T
-
-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
-
-AC_CHECK_SIZEOF(intmax_t, 8)
-
-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
-
-BASH_STRUCT_WEXITSTATUS_OFFSET
-
-dnl presence and behavior of C library functions
-BASH_FUNC_STRSIGNAL
-BASH_FUNC_OPENDIR_CHECK
-BASH_FUNC_ULIMIT_MAXFDS
-BASH_FUNC_FPURGE
-BASH_FUNC_GETENV
-if test "$ac_cv_func_getcwd" = "yes"; then
-BASH_FUNC_GETCWD
-fi
-BASH_FUNC_POSIX_SETJMP
-BASH_FUNC_STRCOLL
-BASH_FUNC_SNPRINTF
-BASH_FUNC_VSNPRINTF
-
-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 or ld 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 -DSOLARIS" ;;
-solaris2.8*) LOCAL_CFLAGS=-DSOLARIS ;;
-solaris2.9*) LOCAL_CFLAGS=-DSOLARIS ;;
-solaris2.10*) LOCAL_CFLAGS=-DSOLARIS ;;
-solaris2*) LOCAL_CFLAGS=-DSOLARIS ;;
-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 -D_ALL_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
-
-if test -z "$localedir"; then
- localedir='${datarootdir}/locale'
-fi
-if test -z "$datarootdir"; then
- datarootdir='${prefix}/share'
-fi
-
-AC_SUBST(PROFILE_FLAGS)
-
-AC_SUBST(incdir)
-AC_SUBST(BUILD_DIR)
-
-# Some versions of autoconf don't substitute these automatically
-AC_SUBST(datarootdir)
-AC_SUBST(localedir)
-
-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],
-[
-# Makefile uses this timestamp file to record whether config.h is up to date.
-echo timestamp > stamp-h
-])
+++ /dev/null
-# 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
+++ /dev/null
-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.
+++ /dev/null
-.\"
-.\" MAN PAGE COMMENTS to
-.\"
-.\" Chet Ramey
-.\" Case Western Reserve University
-.\" chet@po.cwru.edu
-.\"
-.\" Last Change: Sun Jan 29 21:16:46 EST 2012
-.\"
-.\" bash_builtins, strip all but Built-Ins section
-.if \n(zZ=1 .ig zZ
-.if \n(zY=1 .ig zY
-.TH BASH 1 "2012 January 29" "GNU Bash 4.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\a\\*(]X\au-3p \{\\*(]X
-.br\}
-.el \\*(]X\h\a|\\n()Iu+\\n()Ru\a\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]
-[command_string | file]
-.SH COPYRIGHT
-.if n Bash is Copyright (C) 1989-2012 by the Free Software Foundation, Inc.
-.if t Bash is Copyright \(co 1989-2012 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
-All of the single-character shell options documented in the
-description of the \fBset\fR builtin command can be used as options
-when the shell is invoked.
-In addition, \fBbash\fR
-interprets the following options when it is invoked:
-.PP
-.PD 0
-.TP 10
-.B \-c
-If the
-.B \-c
-option is present, then commands are read from the first non-option argument
-.IR command_string .
-If there are arguments after the
-.IR command_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).
-.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 filenames 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 filename.
-.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 with its standard input
-connected to a network connection, as when executed by the remote shell
-daemon, usually \fIrshd\fP, or the secure shell daemon \fIsshd\fP.
-If
-.B bash
-determines it is being run in this fashion, 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
-.BR SHELLOPTS ,
-.SM
-.BR BASHOPTS ,
-.SM
-.BR CDPATH ,
-and
-.SM
-.B GLOBIGNORE
-variables, if they appear in the environment, are 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|| & && ; ;; ( ) | |& <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
-one of the control operators
-.B |
-or \fB|&\fP.
-The format for a pipeline is:
-.RS
-.PP
-[\fBtime\fP [\fB\-p\fP]] [ ! ] \fIcommand\fP [ [\fB|\fP\(bv\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).
-If \fB|&\fP is used, \fIcommand\fP's standard output and standard error
-are connected to
-\fIcommand2\fP's standard input through the pipe;
-it is shorthand for \fB2>&1 |\fP.
-This implicit redirection of the standard error is
-performed after any redirections specified by the command.
-.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.
-When the shell is in \fIposix mode\fP, it does not recognize
-\fBtime\fP as a reserved word if the next token begins with a `-'.
-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
-When the shell is in \fIposix mode\fP, \fBtime\fP
-may be followed by a newline. In this case, the shell displays the
-total user and system time consumed by the shell and its children.
-The
-.SM
-.B TIMEFORMAT
-variable may be used to specify the format of
-the time information.
-.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 || ,
-and optionally terminated by one of
-.BR ; ,
-.BR & ,
-or
-.BR <newline> .
-.PP
-Of these list operators,
-.B &&
-and
-.B ||
-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
-AND and OR lists are sequences of one of more pipelines separated by the
-\fB&&\fP and \fB||\fP control operators, respectively.
-AND and OR lists are executed with left associativity.
-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||\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.
-In most cases a \fIlist\fP in a command's description may be separated from
-the rest of the command by one or more newlines, and may be followed by a
-newline in place of a semicolon.
-.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 or another
-shell metacharacter.
-.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 used with \fB[[\fP, the \fB<\fP and \fB>\fP operators sort
-lexicographically using the current locale.
-.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 the quoted portion
-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.
-Any part of the pattern may be quoted to force the quoted portion
-to be matched as a string.
-Bracket expressions in regular expressions must be treated carefully,
-since normal quoting characters lose their meanings between brackets.
-If the pattern is stored in a shell variable, quoting the variable
-expansion forces the entire pattern to be matched as a string.
-Substrings matched by parenthesized subexpressions within the regular
-expression are saved in the array variable
-.SM
-.BR BASH_REMATCH .
-The element of
-.SM
-.B BASH_REMATCH
-with index 0 is the portion of the string
-matching the entire regular expression.
-The element of
-.SM
-.B BASH_REMATCH
-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
-\fIexpression1\fP \fB||\fP \fIexpression2\fP
-True if either
-.I expression1
-or
-.I expression2
-is true.
-.PD
-.LP
-The \fB&&\fP and \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
-.SM
-.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
-.SM
-.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.
-If the \fB;;\fP operator is used, no subsequent matches are attempted after
-the first pattern match.
-Using \fB;&\fP in place of \fB;;\fP causes execution to continue with
-the \fIlist\fP associated with the next set of patterns.
-Using \fB;;&\fP in place of \fB;;\fP causes the shell to test the next
-pattern list in the statement, if any, and execute any associated \fIlist\fP
-on a successful match.
-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-1\fP; \fBdo\fP \fIlist-2\fP; \fBdone\fP
-.PD 0
-.TP
-\fBuntil\fP \fIlist-1\fP; \fBdo\fP \fIlist-2\fP; \fBdone\fP
-.PD
-The \fBwhile\fP command continuously executes the list
-\fIlist-2\fP as long as the last command in the list \fIlist-1\fP returns
-an exit status of zero. The \fBuntil\fP command is identical
-to the \fBwhile\fP command, except that the test is negated;
-.I list-2
-is executed as long as the last command in
-.I list-1
-returns a non-zero exit status.
-The exit status of the \fBwhile\fP and \fBuntil\fP commands
-is the exit status
-of the last command executed in \fIlist-2\fP, or zero if
-none was executed.
-.SS Coprocesses
-.PP
-A \fIcoprocess\fP is a shell command preceded by the \fBcoproc\fP reserved
-word.
-A coprocess is executed asynchronously in a subshell, as if the command
-had been terminated with the \fB&\fP control operator, with a two-way pipe
-established between the executing shell and the coprocess.
-.PP
-The format for a coprocess is:
-.RS
-.PP
-\fBcoproc\fP [\fINAME\fP] \fIcommand\fP [\fIredirections\fP]
-.RE
-.PP
-This creates a coprocess named \fINAME\fP.
-If \fINAME\fP is not supplied, the default name is \fBCOPROC\fP.
-\fINAME\fP must not be supplied if \fIcommand\fP is a \fIsimple
-command\fP (see above); otherwise, it is interpreted as the first word
-of the simple command.
-When the coprocess is executed, the shell creates an array variable (see
-.B Arrays
-below) named \fINAME\fP in the context of the executing shell.
-The standard output of
-.I command
-is connected via a pipe to a file descriptor in the executing shell,
-and that file descriptor is assigned to \fINAME\fP[0].
-The standard input of
-.I command
-is connected via a pipe to a file descriptor in the executing shell,
-and that file descriptor is assigned to \fINAME\fP[1].
-This pipe is established before any redirections specified by the
-command (see
-.SM
-.B REDIRECTION
-below).
-The file descriptors can be utilized as arguments to shell commands
-and redirections using standard word expansions.
-The process ID of the shell spawned to execute the coprocess is
-available as the value of the variable \fINAME\fP_PID.
-The \fBwait\fP
-builtin command may be used to wait for the coprocess to terminate.
-.PP
-The return status of a coprocess is the exit status of \fIcommand\fP.
-.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
-\fIname\fP () \fIcompound\-command\fP [\fIredirection\fP]
-.PD 0
-.TP
-\fBfunction\fP \fIname\fP [()] \fIcompound\-command\fP [\fIredirection\fP]
-.PD
-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.
-When in \fIposix mode\fP, \fIname\fP may not be the name of one of the
-POSIX \fIspecial builtins\fP.
-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
-.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\(dq
-double 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 \eu\fIHHHH\fP
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-\fIHHHH\fP (one to four hex digits)
-.TP
-.B \eU\fIHHHHHHHH\fP
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-\fIHHHHHHHH\fP (one to eight 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\(dq\fIstring\fP\(dq)
-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.
-When in \fIposix mode\fP, these builtins may appear in a command after
-one or more instances of the \fBcommand\fP builtin and retain these
-assignment statement properties.
-.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 \fIinteger\fP 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
-(for indexed arrays) or added as additional key\-value pairs in an
-associative array.
-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 exit 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 filename 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 filename used to invoke this instance of
-.BR bash .
-.TP
-.B BASHOPTS
-A colon-separated list of enabled shell options. Each word in
-the list is a valid argument for the
-.B \-s
-option to the
-.B shopt
-builtin command (see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below). The options appearing in
-.SM
-.B BASHOPTS
-are those reported as
-.I on
-by \fBshopt\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 BASHPID
-Expands to the process ID of the current \fBbash\fP process.
-This differs from \fB$$\fP under certain circumstances, such as subshells
-that do not require \fBbash\fP to be re-initialized.
-.TP
-.B BASH_ALIASES
-An associative array variable whose members correspond to the internal
-list of aliases as maintained by the \fBalias\fP builtin.
-Elements added to this array appear in the alias list; unsetting array
-elements cause aliases to be removed from the alias list.
-.TP
-.B BASH_ARGC
-An array variable whose values are the number of parameters in each
-frame of the current \fBbash\fP 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
-.SM
-.BR BASH_ARGC .
-The shell sets
-.SM
-.B BASH_ARGC
-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 \fBbash\fP
-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
-.SM
-.BR BASH_ARGV .
-The shell sets
-.SM
-.B BASH_ARGV
-only when in extended debugging mode
-(see the description of the
-.B extdebug
-option to the
-.B shopt
-builtin below)
-.TP
-.B BASH_CMDS
-An associative array variable whose members correspond to the internal
-hash table of commands as maintained by the \fBhash\fP builtin.
-Elements added to this array appear in the hash table; unsetting array
-elements cause commands to be removed from the hash table.
-.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
-where each corresponding member of
-.SM
-.B FUNCNAME
-was invoked.
-\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP is the line number in the source
-file (\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP) where
-\fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP was called
-(or \fB${BASH_LINENO[\fP\fI$i-1\fP\fB]}\fP if referenced within another
-shell function).
-Use
-.SM
-.B LINENO
-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
-where the corresponding shell function names in the
-.SM
-.B FUNCNAME
-array variable are defined.
-The shell function
-\fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP is defined in the file
-\fB${BASH_SOURCE[\fP\fI$i\fP\fB]}\fP and called from
-\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP.
-.TP
-.B BASH_SUBSHELL
-Incremented by one within each subshell or subshell environment when
-the shell begins executing in that environment.
-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
-.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
-.SM
-.BR MACHTYPE .
-.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_KEY
-The key (or final key of a key sequence) used to invoke the current
-completion function.
-.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_TYPE
-Set to an integer value corresponding to the type of completion attempted
-that caused a completion function to be called:
-\fITAB\fP, for normal completion,
-\fI?\fP, for listing completions after successive tabs,
-\fI!\fP, for listing alternatives on partial word completion,
-\fI@\fP, to list completions if the word is not unmodified,
-or
-\fI%\fP, for menu completion.
-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 \fBreadline\fP 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.
-The line is split into words as \fBreadline\fP would split it, using
-.SM
-.B COMP_WORDBREAKS
-as described above.
-This variable is available only in shell functions invoked by the
-programmable completion facilities (see \fBProgrammable Completion\fP
-below).
-.TP
-.B COPROC
-An array variable (see \fBArrays\fP below) created to hold the file descriptors
-for output from and input to an unnamed coprocess (see \fBCoprocesses\fP
-above).
-.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 (the one with the highest index) is
-.if t \f(CW"main"\fP.
-.if n "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.
-.if t .sp 0.5
-.if n .sp 1
-This variable can be used with \fBBASH_LINENO\fP and \fBBASH_SOURCE\fP.
-Each element of \fBFUNCNAME\fP has corresponding elements in
-\fBBASH_LINENO\fP and \fBBASH_SOURCE\fP to describe the call stack.
-For instance, \fB${FUNCNAME[\fP\fI$i\fP\fB]}\fP was called from the file
-\fB${BASH_SOURCE[\fP\fI$i+1\fP\fB]}\fP at line number
-\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP.
-The \fBcaller\fP builtin displays the current call stack using this
-information.
-.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 MAPFILE
-An array variable (see \fBArrays\fP below) created to hold the text
-read by the \fBmapfile\fP builtin when no variable name is supplied.
-.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 READLINE_LINE
-The contents of the
-.B readline
-line buffer, for use with
-.if t \f(CWbind -x\fP
-.if n "bind -x"
-(see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-.TP
-.B READLINE_POINT
-The position of the insertion point in the
-.B readline
-line buffer, for use with
-.if t \f(CWbind -x\fP
-.if n "bind -x"
-(see
-.SM
-.B "SHELL BUILTIN COMMANDS"
-below).
-.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 filename.
-.SM
-.B PATH
-is not used to search for the resultant filename.
-.TP
-.B BASH_XTRACEFD
-If set to an integer corresponding to a valid file descriptor, \fBbash\fP
-will write the trace output generated when
-.if t \f(CWset -x\fP
-.if n \fIset -x\fP
-is enabled to that file descriptor.
-The file descriptor is closed when
-.SM
-.B BASH_XTRACEFD
-is unset or assigned a new value.
-Unsetting
-.SM
-.B BASH_XTRACEFD
-or assigning it the empty string causes the
-trace output to be sent to the standard error.
-Note that setting
-.SM
-.B BASH_XTRACEFD
-to 2 (the standard error file
-descriptor) and then unsetting it will result in the standard error
-being closed.
-.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 compound command to determine the terminal width
-when printing selection lists. Automatically set in an interactive shell
-upon receipt of a
-.SM
-.BR 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).
-Each array element contains one possible completion.
-.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 ENV
-Similar to
-.SM
-.BR BASH_ENV ;
-used when the shell is invoked in POSIX mode.
-.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 FUNCNEST
-If set to a numeric value greater than 0, defines a maximum function
-nesting level. Function invocations that exceed this nesting level
-will cause the current command to abort.
-.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
-.SM
-.B 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
-.SM
-.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
-.SM
-.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 by removing the oldest entries.
-The history file is also truncated to this size after
-writing it when an interactive shell exits.
-If the value is 0, the history file is truncated to zero size.
-Non-numeric values and numeric values less than zero inhibit truncation.
-The shell sets the default value to the value of \fBHISTSIZE\fP
-after reading any startup files.
-.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
-.SM
-.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
-.SM
-.BR HISTIGNORE .
-.TP
-.B HISTSIZE
-The number of commands to remember in the command history (see
-.SM
-.B HISTORY
-below).
-If the value is 0, commands are not saved in the history list.
-Numeric values less than zero result in every command being saved
-on the history list (there is no limit).
-The shell sets the default value to 500 after reading any startup files.
-.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.
-This uses the history comment character to distinguish timestamps from
-other history lines.
-.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, or does not name a readable file,
-\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
-.SM
-.B LANG
-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 compound command to determine the column length
-for printing selection lists. Automatically set by an interactive shell
-upon receipt of a
-.SM
-.BR SIGWINCH .
-.TP
-.B MAIL
-If this parameter is set to a file or directory name and the
-.SM
-.B MAILPATH
-variable is not set,
-.B bash
-informs the user of the arrival of mail in the specified file or
-Maildir-format directory.
-.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 filenames to be checked for mail.
-The message to be printed when mail arrives in a particular file
-may be specified by separating the filename 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
-.SM
-.B PATH
-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/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin\fP.
-.if n ``/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin''.
-.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 PROMPT_DIRTRIM
-If set to a number greater than zero, the value is used as the number of
-trailing directory components to retain when expanding the \fB\ew\fP and
-\fB\eW\fP prompt string escapes (see
-.SM
-.B PROMPTING
-below). Characters removed are replaced with an ellipsis.
-.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
-.SM
-.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
-.SM
-.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.
-.PD 0
-.TP
-.B TMOUT
-If set to a value greater than zero,
-.SM
-.B TMOUT
-is treated as the
-default timeout for the \fBread\fP builtin.
-The \fBselect\fP command terminates if input does not arrive
-after
-.SM
-.B TMOUT
-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 indexed and associative array variables.
-Any variable may be used as an indexed 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.
-Indexed arrays are referenced using integers (including arithmetic
-expressions) and are zero-based; associative arrays are referenced
-using arbitrary strings.
-.PP
-An indexed 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.
-To explicitly declare an indexed 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.
-.PP
-Associative arrays are created using
-.BR "declare \-A \fIname\fP" .
-.PP
-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.
-Indexed array assignments do not require anything but \fIstring\fP.
-When assigning to indexed arrays, if the optional brackets and subscript
-are supplied, that index is assigned to;
-otherwise the index of the element assigned is the last index assigned
-to by the statement plus one. Indexing starts at zero.
-.PP
-When assigning to an associative array, the subscript is required.
-.PP
-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 the array with a subscript of 0.
-If the
-.I subscript
-used to reference an element of an indexed array
-evaluates to a number less than zero, it is used as
-an offset from one greater than the array's maximum index (so a subcript
-of -1 refers to the last element of the array).
-.PP
-An array variable is considered set if a subscript has been assigned a
-value. The null string is a valid value.
-.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 pathname
-expansion.
-\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 indexed array and a
-.B \-A
-option to specify an associative array.
-If both options are supplied,
-.B \-A
-takes precedence.
-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\fIincr\fP\fB]}\fP,
-where \fIx\fP and \fIy\fP are either integers or single characters,
-and \fIincr\fP, an optional increment, is an integer.
-When integers are supplied, the expression expands to each number between
-\fIx\fP and \fIy\fP, inclusive.
-Supplied integers may be prefixed with \fI0\fP to force each term to have the
-same width. When either \fIx\fP or \fPy\fP begins with a zero, the shell
-attempts to force all generated terms to contain the same number of digits,
-zero-padding where necessary.
-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.
-When the increment is supplied, it is used as the difference between
-each term. The default increment is 1 or -1 as appropriate.
-.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 filenames 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 (\fB!\fP),
-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 ${\fB!\fP\fIprefix\fP\fB*\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.
-.PP
-When not performing substring expansion, using the forms documented below,
-\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).
-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 \fIlength\fP evaluates to a number less than zero, and \fIparameter\fP
-is not \fB@\fP and not an indexed or associative array, it is interpreted
-as an offset from the end of the value of \fIparameter\fP rather than
-a number of characters, and the expansion is the characters between the
-two offsets.
-If \fIparameter\fP is \fB@\fP, the result is \fIlength\fP positional
-parameters beginning at \fIoffset\fP.
-If \fIparameter\fP is an indexed array name subscripted 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.
-Substring expansion applied to an associative array produces undefined
-results.
-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 by default.
-If \fIoffset\fP is 0, and the positional parameters are used, \fB$0\fP is
-prefixed to the list.
-.TP
-${\fB!\fP\fIprefix\fP\fB*\fP}
-.PD 0
-.TP
-${\fB!\fP\fIprefix\fP\fB@\fP}
-.PD
-\fBNames matching prefix\fP.
-Expands to the names of variables whose names begin with \fIprefix\fP,
-separated by the first character of the
-.SM
-.B IFS
-special variable.
-When \fI@\fP is used and the expansion appears within double quotes, each
-variable name expands to a separate word.
-.TP
-${\fB!\fP\fIname\fP[\fI@\fP]}
-.PD 0
-.TP
-${\fB!\fP\fIname\fP[\fI*\fP]}
-.PD
-\fBList of array keys\fP.
-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}
-\fBParameter length\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
-\fBRemove matching prefix pattern\fP.
-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
-\fBRemove matching suffix pattern\fP.
-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}
-\fBPattern substitution\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 \fIpattern\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.
-.TP
-${\fIparameter\fP\fB^\fP\fIpattern\fP}
-.PD 0
-.TP
-${\fIparameter\fP\fB^^\fP\fIpattern\fP}
-.TP
-${\fIparameter\fP\fB,\fP\fIpattern\fP}
-.TP
-${\fIparameter\fP\fB,,\fP\fIpattern\fP}
-.PD
-\fBCase modification\fP.
-This expansion modifies the case of alphabetic characters in \fIparameter\fP.
-The \fIpattern\fP is expanded to produce a pattern just as in
-pathname expansion.
-Each character in the expanded value of \fIparameter\fP is tested against
-\fIpattern\fP, and, if it matches the pattern, its case is converted.
-The pattern should not attempt to match more than one character.
-The \fB^\fP operator converts lowercase letters matching \fIpattern\fP
-to uppercase; the \fB,\fP operator converts matching uppercase letters
-to lowercase.
-The \fB^^\fP and \fB,,\fP expansions convert each matched character in the
-expanded value; the \fB^\fP and \fB,\fP expansions match and convert only
-the first character in the expanded value.
-If \fIpattern\fP is omitted, it is treated like a \fB?\fP, which matches
-every character.
-If
-.I parameter
-is
-.B @
-or
-.BR * ,
-the case modification 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 case modification 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:
-.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
-sequences of
-.BR <space> ,
-.BR <tab> ,
-and
-.B <newline>
-at the beginning and end of the results of the previous
-expansions are ignored, and
-any sequence of
-.SM
-.B IFS
-characters not at the beginning or end 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
-filenames matching the pattern
-(see
-.SM
-.B "Pattern Matching"
-below).
-If no matching filenames are found,
-and the shell option
-.B nullglob
-is not enabled, 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 filenames matching a
-.IR pattern .
-If
-.SM
-.B GLOBIGNORE
-is set, each matching filename that also matches one of the patterns in
-.SM
-.B GLOBIGNORE
-is removed from the list of matches.
-The filenames
-.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 filenames beginning with a
-.B ``.''
-will match.
-To get the old behavior of ignoring filenames 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
-.RS
-.TP
-.B *
-Matches any string, including the null string.
-When the \fBglobstar\fP shell option is enabled, and \fB*\fP is used in
-a pathname expansion context, two adjacent \fB*\fPs used as a single
-pattern will match all files and zero or more directories and
-subdirectories.
-If followed by a \fB/\fP, two adjacent \fB*\fPs will match only directories
-and subdirectories.
-.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 values of the
-.SM
-.B LC_COLLATE
-or
-.SM
-.B LC_ALL
-shell variables, if set.
-To obtain the traditional interpretation of range expressions, where
-.B [a\-d]
-is equivalent to
-.BR [abcd] ,
-set value of the
-.B LC_ALL
-shell variable to
-.BR C ,
-or enable the
-.B globasciiranges
-shell option.
-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
-.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 allows commands' file handles to be
-duplicated, opened, closed,
-made to refer to different files,
-and can change the files the command reads from and writes to.
-Redirection may also be used to modify file handles in 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
-Each redirection that may be preceded by a file descriptor number
-may instead be preceded by a word of the form {\fIvarname\fP}.
-In this case, for each redirection operator except
->&- and <&-, the shell will allocate a file descriptor greater
-than or equal to 10 and assign it to \fIvarname\fP.
-If >&- or <&- is preceded
-by {\fIvarname\fP}, the value of \fIvarname\fP defines the file
-descriptor to close.
-.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 and variable 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 from the 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
-This construct 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
-.IR word .
-.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
-.PP
-When using the second form, \fIword\fP may not expand to a number or
-\fB\-\fP. If it does, other redirection operators apply
-(see \fBDuplicating File Descriptors\fP below) for compatibility
-reasons.
-.SS Appending Standard Output and Standard Error
-.PP
-This construct allows both the
-standard output (file descriptor 1) and
-the standard error output (file descriptor 2)
-to be appended to the file whose name is the
-expansion of
-.IR word .
-.PP
-The format for appending standard output and standard error is:
-.RS
-.PP
-\fB&>>\fP\fIword\fP
-.RE
-.PP
-This is semantically equivalent to
-.RS
-.PP
-\fB>>\fP\fIword\fP 2\fB>&\fP1
-.RE
-.PP
-(see \fBDuplicating File Descriptors\fP below).
-.SS Here Documents
-.PP
-This type of redirection instructs the shell to read input from the
-current source until a line containing only
-.I delimiter
-(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 and variable 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 undergoes
-brace expansion, tilde expansion, parameter and variable expansion,
-command substitution, arithmetic expansion, and quote removal.
-Pathname expansion word splitting are not performed.
-The result is supplied as a single string 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.
-If
-.I word
-evaluates to
-.BR \- ,
-file descriptor
-.I n
-is closed.
-As a special case, if \fIn\fP is omitted, and \fIword\fP does not
-expand to one or more digits or \fB\-\fP, 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 \fB0\fP
-is unchanged.
-The first element of the
-.SM
-.B FUNCNAME
-variable is set to the name of the function while the function
-is executing.
-.PP
-All other aspects of the shell execution
-environment are identical between a function and its caller
-with these exceptions: 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),
-and the
-.SM
-.B ERR
-trap is not inherited unless the \fB\-o errtrace\fP shell option has
-been enabled.
-.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
-The \fBFUNCNEST\fP variable, if set to a numeric value greater
-than 0, defines a maximum function nesting level. Function
-invocations that exceed the limit cause the entire command to
-abort.
-.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.
-The \fBFUNCNEST\fP variable may be used to limit the depth of the
-function call stack and restrict the number of function invocations.
-By default, 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 \fIinteger\fP 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 the optional \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.
-When specifying \fIn\fP,
-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.
-.if t .sp 0.5
-.if n .sp 1
-When used with \fB[[\fP, the \fB<\fP and \fB>\fP operators sort
-lexicographically using the current locale.
-The \fBtest\fP command sorts using ASCII ordering.
-.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 \-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 \-N \fIfile\fP
-True if \fIfile\fP exists and has been modified since it was last read.
-.TP
-.B \-O \fIfile\fP
-True if \fIfile\fP exists and is owned by the effective user id.
-.TP
-.B \-S \fIfile\fP
-True if \fIfile\fP exists and is a socket.
-.TP
-\fIfile1\fP \fB\-ef\fP \fIfile2\fP
-True if \fIfile1\fP and \fIfile2\fP refer to the same device and
-inode numbers.
-.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
-.B \-o \fIoptname\fP
-True if the 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 \-v \fIvarname\fP
-True if the shell variable
-.I varname
-is set (has been assigned a value).
-.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
-.PD 0
-.TP
-\fIstring1\fP \fB=\fP \fIstring2\fP
-.PD
-True if the strings are equal. \fB=\fP should be used
-with the \fBtest\fP command for POSIX conformance.
-.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.
-.TP
-\fIstring1\fP \fB>\fP \fIstring2\fP
-True if \fIstring1\fP sorts after \fIstring2\fP lexicographically.
-.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 searches for a defined shell
-function named \fBcommand_not_found_handle\fP.
-If that function exists, it is invoked with the original command and
-the original command's arguments as its arguments, and the function's
-exit status becomes the exit status of the shell.
-If that function is not defined, 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:
-.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
-.SM
-.B PPID
-.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.
-.if n .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
-Subshells spawned to execute command substitutions inherit the value of
-the \fB\-e\fP option from the parent shell. When not in \fIposix\fP mode,
-\fBbash\fP clears the \fB\-e\fP option in such subshells.
-.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 filename of the command and passed to that
-command in its environment.
-.SH "EXIT STATUS"
-.PP
-The exit status of an executed command is the value returned by the
-\fIwaitpid\fP system call or equivalent function. Exit statuses
-fall between 0 and 255, though, as explained below, the shell may
-use values above 125 specially. Exit statuses from shell builtins and
-compound commands are also limited to this range. Under certain
-circumstances, the shell will use special values to indicate specific
-failure modes.
-.PP
-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 operating system kernel'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, if the
-user so specifies with \f(CWstty tostop\fP, write to the
-terminal.
-Background processes which attempt to read from (write to when
-\f(CWstty tostop\fP is in effect) the
-terminal are sent a
-.SM
-.B SIGTTIN (SIGTTOU)
-signal by the kernel's 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 specification (\fIjobspec\fP). 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 %\- .
-If there is only a single job, \fB%+\fP and \fB%\-\fP can both be used
-to refer to that job.
-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 (or, if the \fBcheckjobs\fP shell option has
-been enabled using the \fBshopt\fP builtin, running), the shell prints a
-warning message, and, if the \fBcheckjobs\fP option is enabled, lists the
-jobs and their statuses.
-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 any 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
-.SM
-.B $HOME
-abbreviated with a tilde
-(uses the value of the
-.SM
-.B PROMPT_DIRTRIM
-variable)
-.TP
-.B \eW
-the basename of the current working directory, with
-.SM
-.B $HOME
-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.
-Line editing is also used when using the \fB\-e\fP option to the
-\fBread\fP builtin.
-By default, the line editing commands are similar to those of Emacs.
-A vi-style line editing interface is also available.
-Line editing can be enabled at any time using the
-.B \-o emacs
-or
-.B \-o vi
-options to the
-.B set
-builtin (see
-.SM
-.B SHELL BUILTIN COMMANDS
-below).
-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.
-.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 colored\-stats (Off)
-If set to \fBOn\fP, readline displays possible completions using different
-colors to indicate their file type.
-The color definitions are taken from the value of the \fBLS_COLORS\fP
-environment variable.
-.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\-prefix\-display\-length (0)
-The length in characters of the common prefix of a list of possible
-completions that is displayed without modification. When set to a
-value greater than zero, common prefixes longer than this value are
-replaced with an ellipsis when displaying possible completions.
-.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 echo\-control\-characters (On)
-When set to \fBOn\fP, on operating systems that indicate they support it,
-readline echoes a character corresponding to a signal generated from the
-keyboard.
-.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 enable\-meta\-key (On)
-When set to \fBOn\fP, readline will try to enable any meta modifier
-key the terminal claims to support when it is called. On many terminals,
-the meta key is used to send eight-bit characters.
-.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 history\-size (0)
-Set the maximum number of history entries saved in the history list. If
-set to zero, the number of entries in the history list is not limited.
-.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 keyseq\-timeout (500)
-Specifies the duration \fIreadline\fP will wait for a character when reading an
-ambiguous key sequence (one that can form a complete key sequence using
-the input read so far, or can take additional input to complete a longer
-key sequence).
-If no input is received within the timeout, \fIreadline\fP will use the shorter
-but complete key sequence.
-The value is specified in milliseconds, so a value of 1000 means that
-\fIreadline\fP will wait one second for additional input.
-If this variable is set to a value less than or equal to zero, or to a
-non-numeric value, \fIreadline\fP will wait until another key is pressed to
-decide which key sequence to complete.
-.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.
-If set to \fBOff\fP, the leading `.' must be
-supplied by the user in the filename to be completed.
-.TP
-.B menu\-complete\-display\-prefix (Off)
-If set to \fBOn\fP, menu completion displays the common prefix of the
-list of possible completions (which may be empty) before cycling through
-the list.
-.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 revert\-all\-at\-newline (Off)
-If set to \fBOn\fP, readline will undo all changes to history lines
-before returning when \fBaccept\-line\fP is executed. By default,
-history lines may be modified and retain individual undo lists across
-calls to \fBreadline\fP.
-.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 skip\-completed\-text (Off)
-If set to \fBOn\fP, this alters the default completion behavior when
-inserting a single match into the line. It's only active when
-performing completion in the middle of a word. If enabled, readline
-does not insert characters from the completion that match characters
-after point in the word being completed, so portions of the word
-following the cursor are not duplicated.
-.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 \fBbash\fP:
-.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 shell\-forward\-word
-Move forward to the end of the next word.
-Words are delimited by non-quoted shell metacharacters.
-.TP
-.B shell\-backward\-word
-Move back to the start of the current or previous word.
-Words are delimited by non-quoted shell metacharacters.
-.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 a numeric argument, behave exactly like \fByank\-nth\-arg\fP.
-Successive calls to \fByank\-last\-arg\fP move back through the history
-list, inserting the last word (or the word specified by the argument to
-the first call) of each line in turn.
-Any numeric argument supplied to these successive calls determines
-the direction to move through the history. A negative argument switches
-the direction through the history (back or forward).
-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 $VISUAL ,
-.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 shell\-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 \fBshell\-forward\-word\fP.
-.TP
-.B shell\-backward\-kill\-word (M\-Rubout)
-Kill the word behind point.
-Word boundaries are the same as those used by \fBshell\-backward\-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 menu\-complete\-backward
-Identical to \fBmenu\-complete\fP, but moves backward through the list
-of possible completions, as if \fBmenu\-complete\fP had been given a
-negative argument. This command 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 dabbrev\-expand
-Attempt menu 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.
-.B print\-last\-kbd\-macro ()
-Print the last keyboard macro defined in a format suitable for the
-\fIinputrc\fP file.
-.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 skip\-csi\-sequence
-Read enough characters to consume a multi-key sequence such as those
-defined for keys like Home and End. Such sequences begin with a
-Control Sequence Indicator (CSI), usually ESC\-[. If this sequence is
-bound to "\e[", keys producing such sequences will have no effect
-unless explicitly bound to a readline command, instead of inserting
-stray characters into the editing buffer. This is unbound by default,
-but usually bound to ESC\-[.
-.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 filenames 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 filenames 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 the command word is the empty string (completion attempted at the
-beginning of an empty line), any compspec defined with
-the \fB\-E\fP option to \fBcomplete\fP is used.
-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.
-If those searches do not result in a compspec, any compspec defined with
-the \fB\-D\fP option to \fBcomplete\fP is used as the default.
-.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 pathname 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
-.BR COMP_LINE ,
-.SM
-.BR COMP_POINT ,
-.SM
-.BR COMP_KEY ,
-and
-.SM
-.B COMP_TYPE
-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 (\fB$1\fP) is the name of the command whose arguments are
-being completed,
-the second argument (\fB$2\fP) is the word being completed,
-and the third argument (\fB$3\fP) 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, one per array element.
-.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.
-.PP
-There is some support for dynamically modifying completions. This is
-most useful when used in combination with a default completion specified
-with \fBcomplete -D\fP.
-It's possible for shell functions executed as completion
-handlers to indicate that completion should be retried by returning an
-exit status of 124. If a shell function returns 124, and changes
-the compspec associated with the command on which completion is being
-attempted (supplied as the first argument when the function is executed),
-programmable completion restarts from the beginning, with an
-attempt to find a new compspec for that command. This allows a set of
-completions to be built dynamically as completion is attempted, rather than
-being loaded all at once.
-.PP
-For instance, assuming that there is a library of compspecs, each kept in a
-file corresponding to the name of the command, the following default
-completion function would load completions dynamically:
-.PP
-\f(CW_completion_loader()
-.br
-{
-.br
- . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
-.br
-}
-.br
-complete -D -F _completion_loader
-.br
-\fP
-.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
-.SM
-.B HISTSIZE
-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 .
-If \fBHISTFILESIZE\fP is unset, or set to null, a non-numeric value,
-or a numeric value less than zero, the history file is not truncated.
-When the history file is read,
-lines beginning with the history comment character followed immediately
-by a digit are interpreted as timestamps for the preceding history line.
-These timestamps are optionally displayed depending on the value of the
-.SM
-.B HISTTIMEFORMAT
-variable.
-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.
-If the
-.SM
-.B HISTTIMEFORMAT
-variable is set, time stamps are written to the history file, marked
-with the history comment character, so
-they may be preserved across shell sessions.
-This uses the history comment character to distinguish timestamps from
-other history lines.
-After saving the history, the history file is truncated
-to contain no more than
-.SM
-.B HISTFILESIZE
-lines. If
-.SM
-.B HISTFILESIZE
-is unset, or set to null, a non-numeric value,
-or a numeric value less than zero, the history file is not truncated.
-.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 below), 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" ).
-The shell uses
-the history comment character to mark history timestamps when
-writing the history file.
-.SS Event Designators
-.PP
-An event designator is a reference to a command line entry in the
-history list.
-Unless the reference is absolute, events are relative to the current
-position 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 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 preceding the current position in the
-history list starting with
-.IR string .
-.TP
-.B !?\fIstring\fR\fB[?]\fR
-Refer to the most recent command preceding the current position in the
-history list 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 previous 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 filename component, leaving only the head.
-.TP
-.B t
-Remove all leading filename 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.
-The \fB:\fP, \fBtrue\fP, \fBfalse\fP, and \fBtest\fP builtins
-do not accept options and do not treat \fB\-\-\fP specially.
-The \fBexit\fP, \fBlogout\fP, \fBbreak\fP, \fBcontinue\fP, \fBlet\fP,
-and \fBshift\fP builtins accept and process arguments beginning with
-\fB\-\fP without requiring \fB\-\-\fP.
-Other builtins that accept arguments but are not specified as accepting
-options interpret arguments beginning with \fB\-\fP as invalid options and
-require \fB\-\-\fP to prevent this interpretation.
-.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, filenames 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
-.I jobspec
-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\-lpsvPSVX\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 \-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 \-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 \-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.
-When \fIshell\-command\fP is executed, the shell sets the
-.SM
-.B READLINE_LINE
-variable to the contents of the \fBreadline\fP line buffer and the
-.SM
-.B READLINE_POINT
-variable to the current location of the insertion point.
-If the executed command changes the value of
-.SM
-.B READLINE_LINE
-or
-.SM
-.BR READLINE_POINT ,
-those new values will be reflected in the editing state.
-.TP
-.B \-X
-List all key sequences bound to shell commands and the associated commands
-in a format that can be reused as input.
-.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 \fIn\fP is not greater than or equal to 1.
-.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
-\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
-\fBcd\fP [\fB\-L\fP|[\fB\-P\fP [\fB\-e\fP]]] [\fIdir\fP]
-Change the current directory to \fIdir\fP.
-if \fIdir\fP is not supplied, the value of the
-.SM
-.B HOME
-shell variable is the default.
-Any additional arguments following \fIdir\fP are ignored.
-The variable
-.SM
-.B CDPATH
-defines the search path for the directory containing
-.IR dir :
-each directory name in
-.SM
-.B CDPATH
-is searched for \fIdir\fP.
-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 causes \fBcd\fP to use the physical directory structure
-by resolving symbolic links while traversing \fIdir\fP and
-before processing instances of \fI..\fP in \fIdir\fP (see also the
-.B \-P
-option to the
-.B set
-builtin command); the
-.B \-L
-option forces symbolic links to be followed by resolving the link
-after processing instances of \fI..\fP in \fIdir\fP.
-If \fI..\fP appears in \fIdir\fP, it is processed by removing the
-immediately previous pathname component from \fIdir\fP, back to a slash
-or the beginning of \fIdir\fP.
-If the
-.B \-e
-option is supplied with
-.BR \-P ,
-and the current working directory cannot be successfully determined
-after a successful directory change, \fBcd\fP will return an unsuccessful
-status.
-An argument of
-.B \-
-is converted to
-.SM
-.B $OLDPWD
-before the directory change is attempted.
-If a non-empty directory name from
-.SM
-.B CDPATH
-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
-\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
-.SM
-.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 filename
-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\-DE\fP] [\fB\-A\fP \fIaction\fP] [\fB\-G\fP \fIglobpat\fP] [\fB\-W\fP \fIwordlist\fP] [\fB\-F\fP \fIfunction\fP] [\fB\-C\fP \fIcommand\fP]
-.br
-[\fB\-X\fP \fIfilterpat\fP] [\fB\-P\fP \fIprefix\fP] [\fB\-S\fP \fIsuffix\fP] \fIname\fP [\fIname ...\fP]
-.PD 0
-.TP
-\fBcomplete\fP \fB\-pr\fP [\fB\-DE\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.
-The \fB\-D\fP option indicates that the remaining options and actions should
-apply to the ``default'' command completion; that is, completion attempted
-on a command for which no completion has previously been defined.
-The \fB\-E\fP option indicates that the remaining options and actions should
-apply to ``empty'' command completion; that is, completion attempted on a
-blank line.
-.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,
-quoting special characters, or suppressing trailing spaces).
-Intended to be used with shell functions.
-.TP 8
-.B noquote
-Tell readline not to quote the completed words if they are filenames
-(quoting filenames is the default).
-.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\-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 the function is executed,
-the first argument (\fB$1\fP) is the name of the command whose arguments are
-being completed,
-the second argument (\fB$2\fP) is the word being completed,
-and the third argument (\fB$3\fP) is the word preceding the word being
-completed on the current command line.
-When it finishes, the possible completions are retrieved from the value
-of the
-.SM
-.B COMPREPLY
-array variable.
-.TP 8
-\fB\-G\fP \fIglobpat\fP
-The pathname expansion pattern \fIglobpat\fP is expanded to generate
-the possible completions.
-.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.
-.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\-X\fP \fIfilterpat\fP
-\fIfilterpat\fP is a pattern as used for pathname 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.
-.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
-\fBcompopt\fP [\fB\-o\fP \fIoption\fP] [\fB\-DE\fP] [\fB+o\fP \fIoption\fP] [\fIname\fP]
-Modify completion options for each \fIname\fP according to the
-\fIoption\fPs, or for the
-currently-executing completion if no \fIname\fPs are supplied.
-If no \fIoption\fPs are given, display the completion options for each
-\fIname\fP or the current completion.
-The possible values of \fIoption\fP are those valid for the \fBcomplete\fP
-builtin described above.
-The \fB\-D\fP option indicates that the remaining options should
-apply to the ``default'' command completion; that is, completion attempted
-on a command for which no completion has previously been defined.
-The \fB\-E\fP option indicates that the remaining options should
-apply to ``empty'' command completion; that is, completion attempted on a
-blank line.
-.sp 1
-The return value is true unless an invalid option is supplied, an attempt
-is made to modify the options for a \fIname\fP for which no completion
-specification exists, or an output error occurs.
-.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 \fIn\fP is not greater than or equal to 1.
-.TP
-\fBdeclare\fP [\fB\-aAfFgilrtux\fP] [\fB\-p\fP] [\fIname\fP[=\fIvalue\fP] ...]
-.PD 0
-.TP
-\fBtypeset\fP [\fB\-aAfFgilrtux\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 with \fIname\fP arguments, additional options are ignored.
-When
-.B \-p
-is supplied without \fIname\fP arguments, it will display the attributes
-and values of all variables having the attributes specified by the
-additional options.
-If no other options are supplied with \fB\-p\fP, \fBdeclare\fP will display
-the attributes and values of all shell variables. The \fB\-f\fP option
-will restrict the display to shell functions.
-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
-.B \-g
-option forces variables to be created or modified at the global scope,
-even when \fBdeclare\fP is executed in a shell function.
-It is ignored in all other cases.
-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 indexed array variable (see
-.B Arrays
-above).
-.TP
-.B \-A
-Each \fIname\fP is an associative 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"
-above) is performed when the variable is assigned a value.
-.TP
-.B \-l
-When the variable is assigned a value, all upper-case characters are
-converted to lower-case.
-The upper-case attribute is disabled.
-.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 \-u
-When the variable is assigned a value, all lower-case characters are
-converted to upper-case.
-The lower-case attribute is disabled.
-.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 exceptions that \fB+a\fP
-may not be used to destroy an array variable and \fB+r\fP will not
-remove the readonly attribute.
-When used in a function,
-.B declare
-and
-.B typeset
-make each
-\fIname\fP local, as with the
-.B local
-command,
-unless the \fB\-g\fP option is supplied.
-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
-.B \-c
-Clears the directory stack by deleting all of the entries.
-.TP
-.B \-l
-Produces a listing using full pathnames;
-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.
-.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.
-.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, remove each
-.I jobspec
-from the table of active jobs.
-If
-.I jobspec
-is not present, and neither \fB\-a\fP nor \fB\-r\fP is supplied,
-the shell's notion of the \fIcurrent job\fP is used.
-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 0 unless a write error occurs.
-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 further output
-.TP
-.B \ee
-.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 \ex\fIHH\fP
-the eight-bit character whose value is the hexadecimal value \fIHH\fP
-(one or two hex digits)
-.TP
-.B \eu\fIHHHH\fP
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-\fIHHHH\fP (one to four hex digits)
-.TP
-.B \eU\fIHHHHHHHH\fP
-the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value
-\fIHHHHHHHH\fP (one to eight hex digits)
-.PD
-.RE
-.TP
-\fBenable\fP [\fB\-a\fP] [\fB\-dnps\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 argument 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
-.B execfail
-shell option
-is enabled. In that 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 names of all exported variables 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\-lnr\fP] [\fIfirst\fP] [\fIlast\fP]
-.PD 0
-.TP
-\fBfc\fP \fB\-s\fP [\fIpat\fP=\fIrep\fP] [\fIcmd\fP]
-.PD
-The first form selects a range of commands from
-.I first
-to
-.I last
-from the history list and displays or edits and re-executes them.
-.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.
-\fICommand\fP is intepreted the same as \fIfirst\fP above.
-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.
-.SM
-.B OPTIND
-is set to the index of the first non-option argument,
-and \fIname\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]
-Each time \fBhash\fP is invoked,
-the full pathname of the command
-.I name
-is determined by searching
-the directories in
-.B $PATH
-and remembered. Any previously-remembered pathname is discarded.
-If the
-.B \-p
-option is supplied, no path search is performed, and
-.I filename
-is used as the full filename 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\-dms\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.
-.RS
-.PD 0
-.TP
-.B \-d
-Display a short description of each \fIpattern\fP
-.TP
-.B \-m
-Display the description of each \fIpattern\fP in a manpage-like format
-.TP
-.B \-s
-Display only a short usage synopsis for each \fIpattern\fP
-.PD
-.PP
-The return status is 0 unless no command matches
-.IR pattern .
-.RE
-.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
-.SM
-.B HISTTIMEFORMAT
-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 append them to the current history list.
-.TP
-.B \-w
-Write the current history list 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
-.SM
-.B HISTTIMEFORMAT
-variable is set, the time stamp information
-associated with each history entry is written to the history file,
-marked with the history comment character.
-When the history file is read, lines beginning with the history
-comment character followed immediately by a digit are interpreted
-as timestamps for the previous history line.
-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 \-n
-Display information only about jobs that have changed status since
-the user was last notified of their status.
-.TP
-.B \-p
-List only the process ID of the job's process group
-leader.
-.TP
-.B \-r
-Display only running jobs.
-.TP
-.B \-s
-Display only 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
-.B "ARITHMETIC EVALUATION"
-above).
-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
-\fBmapfile\fP [\fB\-n\fP \fIcount\fP] [\fB\-O\fP \fIorigin\fP] [\fB\-s\fP \fIcount\fP] [\fB\-t\fP] [\fB\-u\fP \fIfd\fP] [\fB\-C\fP \fIcallback\fP] [\fB\-c\fP \fIquantum\fP] [\fIarray\fP]
-.PD 0
-.TP
-\fBreadarray\fP [\fB\-n\fP \fIcount\fP] [\fB\-O\fP \fIorigin\fP] [\fB\-s\fP \fIcount\fP] [\fB\-t\fP] [\fB\-u\fP \fIfd\fP] [\fB\-C\fP \fIcallback\fP] [\fB\-c\fP \fIquantum\fP] [\fIarray\fP]
-.PD
-Read lines from the standard input into the indexed array variable
-.IR array ,
-or from file descriptor
-.IR fd
-if the
-.B \-u
-option is supplied.
-The variable
-.SM
-.B MAPFILE
-is the default \fIarray\fP.
-Options, if supplied, have the following meanings:
-.RS
-.PD 0
-.TP
-.B \-n
-Copy at most
-.I count
-lines. If \fIcount\fP is 0, all lines are copied.
-.TP
-.B \-O
-Begin assigning to
-.I array
-at index
-.IR origin .
-The default index is 0.
-.TP
-.B \-s
-Discard the first \fIcount\fP lines read.
-.TP
-.B \-t
-Remove a trailing newline from each line read.
-.TP
-.B \-u
-Read lines from file descriptor \fIfd\fP instead of the standard input.
-.TP
-.B \-C
-Evaluate
-.I callback
-each time \fIquantum\fP lines are read. The \fB\-c\fP option specifies
-.IR quantum .
-.TP
-.B \-c
-Specify the number of lines read between each call to
-.IR callback .
-.PD
-.PP
-If
-.B \-C
-is specified without
-.BR \-c ,
-the default quantum is 5000.
-When \fIcallback\fP is evaluated, it is supplied the index of the next
-array element to be assigned and the line to be assigned to that element
-as additional arguments.
-\fIcallback\fP is evaluated after the line is read but before the
-array element is assigned.
-.PP
-If not supplied with an explicit origin, \fBmapfile\fP will clear \fIarray\fP
-before assigning to it.
-.PP
-\fBmapfile\fP returns successfully unless an invalid option or option
-argument is supplied, \fIarray\fP is invalid or unassignable, or if
-\fIarray\fP is not an indexed array.
-.RE
-.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
-.B \-n
-Suppresses the normal change of directory when removing directories
-from the stack, so that only the stack is manipulated.
-.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.
-.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 \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 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) format specifications,
-\fBprintf\fP interprets the following extensions:
-.RS
-.PD 0
-.TP
-.B %b
-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).
-.TP
-.B %q
-causes \fBprintf\fP to output the corresponding
-\fIargument\fP in a format that can be reused as shell input.
-.TP
-.B %(\fIdatefmt\fP)T
-causes \fBprintf\fP to output the date-time string resulting from using
-\fIdatefmt\fP as a format string for \fIstrftime\fP(3). The corresponding
-\fIargument\fP is an integer representing the number of seconds since the
-epoch. Two special argument values may be used: -1 represents the current
-time, and -2 represents the time the shell was invoked.
-.PD
-.PP
-Arguments to non-string format specifiers are treated as C constants,
-except that a leading plus or minus sign is allowed, and if the leading
-character is a single or double quote, the value is the ASCII value of
-the following character.
-.PP
-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.
-.RE
-.TP
-\fBpushd\fP [\fB\-n\fP] [+\fIn\fP] [\-\fIn\fP]
-.PD 0
-.TP
-\fBpushd\fP [\fB\-n\fP] [\fIdir\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
-.B \-n
-Suppresses the normal change of directory when adding directories
-to the stack, so that only the stack is manipulated.
-.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
-.I dir
-Adds
-.I dir
-to the directory stack at the top, making it the
-new current working directory as if it had been supplied as the argument
-to the \fBcd\fP builtin.
-.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\-a\fP \fIaname\fP] [\fB\-d\fP \fIdelim\fP] [\fB\-i\fP \fItext\fP] [\fB\-n\fP \fInchars\fP] [\fB\-N\fP \fInchars\fP] [\fB\-p\fP \fIprompt\fP] [\fB\-t\fP \fItimeout\fP] [\fB\-u\fP \fIfd\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.
-Readline uses the current (or default, if line editing was not previously
-active) editing settings.
-.TP
-.B \-i \fItext\fP
-If
-.B readline
-is being used to read the line, \fItext\fP is placed into the editing
-buffer before editing begins.
-.TP
-.B \-n \fInchars\fP
-\fBread\fP returns after reading \fInchars\fP characters rather than
-waiting for a complete line of input, but honor a delimiter if fewer
-than \fInchars\fP characters are read before the delimiter.
-.TP
-.B \-N \fInchars\fP
-\fBread\fP returns after reading exactly \fInchars\fP characters rather
-than waiting for a complete line of input, unless EOF is encountered or
-\fBread\fP times out.
-Delimiter characters encountered in the input are
-not treated specially and do not cause \fBread\fP to return until
-\fInchars\fP characters are read.
-.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.
-\fItimeout\fP may be a decimal number with a fractional portion following
-the decimal point.
-This option is only effective if \fBread\fP is reading input from a
-terminal, pipe, or other special file; it has no effect when reading
-from regular files.
-If \fItimeout\fP is 0, \fBread\fP returns immediately, without trying to
-read any data. The exit statis is 0 if input is available on
-the specified file descriptor, non-zero otherwise.
-The exit status is greater than 128 if the timeout is exceeded.
-.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 (in which case the return code is greater than 128),
-a variable assignment error (such as assigning to a readonly variable) occurs,
-or an invalid file descriptor is supplied as the argument to \fB\-u\fP.
-.RE
-.TP
-\fBreadonly\fP [\fB\-aAf\fP] [\fB\-p\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 indexed arrays; the
-.B \-A
-option restricts the variables to associative arrays.
-If both options are supplied,
-.B \-A
-takes precedence.
-If no
-.I name
-arguments are given, or if the
-.B \-p
-option is supplied, a list of all readonly names is printed.
-The other options may be used to restrict the output to a subset of
-the set of readonly names.
-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 stop executing and return the value specified by
-.I n
-to its caller.
-If
-.I n
-is omitted, the return status is that of the last command
-executed in the function body. If
-.B return
-is 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 \fIn\fP is supplied, the return value is its least significant
-8 bits.
-The return status is non-zero if
-.B return
-is supplied a non-numeric argument, or
-is used outside a
-function and not during execution of a script by \fB.\fP\^ or \fBsource\fP.
-Any command associated with the \fBRETURN\fP trap is executed
-before execution resumes after the function or script.
-.TP
-\fBset\fP [\fB\-\-abefhkmnptuvxBCEHPT\fP] [\fB\-o\fP \fIoption\-name\fP] [\fIarg\fP ...]
-.PD 0
-.TP
-\fBset\fP [\fB+abefhkmnptuvxBCEHPT\fP] [\fB+o\fP \fIoption\-name\fP] [\fIarg\fP ...]
-.PD
-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 option processing 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
-\fIpipeline\fP (which may consist of a single \fIsimple command\fP),
-a \fIlist\fP,
-or a \fIcompound 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 following the
-.B if
-or
-.B elif
-reserved words, part of any command executed in a
-.B &&
-or
-.B ||
-list except the command following the final \fB&&\fP or \fB||\fP,
-any command in a pipeline but the last,
-or if the command's return value is
-being inverted with
-.BR ! .
-If a compound command other than a subshell
-returns a non-zero status because a command failed
-while \fB\-e\fP was being ignored, the shell does not exit.
-A trap on \fBERR\fP, if set, is executed before the shell exits.
-This option applies to the shell environment and each subshell environment
-separately (see
-.SM
-.B "COMMAND EXECUTION ENVIRONMENT"
-above), and may cause
-subshells to exit before executing all the commands in the subshell.
-.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).
-All processes run in a separate process group.
-When a background job completes, the shell prints a line
-containing its exit status.
-.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.
-This also affects the editing interface used for \fBread \-e\fP.
-.TP 8
-.B errexit
-Same as
-.BR \-e .
-.TP 8
-.B errtrace
-Same as
-.BR \-E .
-.TP 8
-.B functrace
-Same as
-.BR \-T .
-.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 .
-.TP 8
-.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.
-This also affects the editing interface used for \fBread \-e\fP.
-.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
-.BR SHELLOPTS ,
-.SM
-.BR BASHOPTS ,
-.SM
-.BR CDPATH ,
-and
-.SM
-.B GLOBIGNORE
-variables, if they appear in the environment, are 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 and parameters other than the special
-parameters "@" and "*" as an error when performing
-parameter expansion. If expansion is attempted on an
-unset variable or parameter, 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 resolve 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,
-.B shopt
-shows only 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 autocd
-If set, a command name that is the name of a directory is executed as if
-it were the argument to the \fBcd\fP command.
-This option is only used by interactive shells.
-.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 filename 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 checkjobs
-If set, \fBbash\fP lists the status of any stopped and running jobs before
-exiting an interactive shell. If any jobs are running, this causes
-the exit to be deferred until a second exit is attempted without an
-intervening command (see
-.SM
-.B "JOB CONTROL"
-above). The shell always
-postpones exiting if any jobs are stopped.
-.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 compat31
-If set,
-.B bash
-changes its behavior to that of version 3.1 with respect to quoted
-arguments to the \fB[[\fP conditional command's \fB=~\fP operator
-and locale-specific string comparison when using the \fB[[\fP
-conditional command's \fB<\fP and \fB>\fP operators.
-Bash versions prior to bash-4.1 use ASCII collation and
-.IR strcmp (3);
-bash-4.1 and later use the current locale's collation sequence and
-.IR strcoll (3).
-.TP 8
-.B compat32
-If set,
-.B bash
-changes its behavior to that of version 3.2 with respect to
-locale-specific string comparison when using the \fB[[\fP
-conditional command's \fB<\fP and \fB>\fP operators (see previous item).
-.TP 8
-.B compat40
-If set,
-.B bash
-changes its behavior to that of version 4.0 with respect to locale-specific
-string comparison when using the \fB[[\fP
-conditional command's \fB<\fP and \fB>\fP operators (see description of
-\fBcompat31\fP)
-and the effect of interrupting a command list.
-Bash versions 4.0 and later interrupt the list as if the shell received the
-interrupt; previous versions continue with the next command in the list.
-.TP 8
-.B compat41
-If set,
-.BR bash ,
-when in posix mode, treats a single quote in a double-quoted
-parameter expansion as a special character. The single quotes must match
-(an even number) and the characters between the single quotes are considered
-quoted. This is the behavior of posix mode through version 4.1.
-The default bash behavior remains as in previous versions.
-.TP 8
-.B complete_fullquote
-If set,
-.B bash
-quotes all shell metacharacters in filenames and directory names when
-performing completion.
-If not set,
-.B bash
-removes metacharacters such as the dollar sign from the set of
-characters that will be quoted in completed filenames
-when these metacharacters appear in shell variable references in words to be
-completed.
-This means that dollar signs in variable names that expand to directories
-will not be quoted;
-however, any dollar signs appearing in filenames will not be quoted, either.
-This is active only when bash is using backslashes to quote completed
-filenames.
-This variable is set by default, which is the default bash behavior in
-versions through 4.2.
-.TP 8
-.B direxpand
-If set,
-.B bash
-replaces directory names with the results of word expansion when performing
-filename completion. This changes the contents of the readline editing
-buffer.
-If not set,
-.B bash
-attempts to preserve what the user typed.
-.TP 8
-.B dirspell
-If set,
-.B bash
-attempts spelling correction on directory names during word completion
-if the directory name initially supplied does not exist.
-.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.
-.SM
-.B BASH_ARGC
-and
-.SM
-.B BASH_ARGV
-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
-\fBERR\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
-.SM
-.B FIGNORE
-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
-.SM
-.BR FIGNORE .
-This option is enabled by default.
-.TP 8
-.B globasciiranges
-If set, range expressions used in pattern matching (see
-.SM
-.B Pattern Matching
-above) behave as if in the traditional C locale when performing
-comparisons. That is, the current locale's collating sequence
-is not taken into account, so
-.B b
-will not collate between
-.B A
-and
-.BR B ,
-and upper-case and lower-case ASCII characters will collate together.
-.TP 8
-.B globstar
-If set, the pattern \fB**\fP used in a pathname expansion context will
-match all files and zero or more directories and subdirectories.
-If the pattern is followed by a \fB/\fP, only directories and
-subdirectories match.
-.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
-.SM
-.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 lastpipe
-If set, and job control is not active, the shell runs the last command of
-a pipeline not executed in the background in the current shell environment.
-.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
-.SM
-.B PATH
-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
-.PD
-.TP
-\fBsuspend\fP [\fB\-f\fP]
-Suspend the execution of this shell until it receives a
-.SM
-.B SIGCONT
-signal. A login shell cannot be suspended; the
-.B \-f
-option can be used to override this and force the suspension.
-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 (true) or 1 (false) 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.
-The evaluation depends on the number of arguments; see below.
-Operator precedence is used when there are five or more arguments.
-.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
-The following conditions are applied in the order listed.
-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.
-The \fB\-a\fP and \fB\-o\fP operators are considered binary operators
-when there are three arguments.
-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.
-.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.
-.if t .sp 0.5
-.if n .sp 1
-.LP
-When used with \fBtest\fP or \fB[\fP, the \fB<\fP and \fB>\fP operators
-sort lexicographically using ASCII ordering.
-.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
-.SM
-.B SIG
-prefix is optional.
-.if t .sp 0.5
-.if n .sp 1
-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 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.
-.if t .sp 0.5
-.if n .sp 1
-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 command executed in a
-.B &&
-or
-.B ||
-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 t .sp 0.5
-.if n .sp 1
-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 subshell or subshell environment when one 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, which is 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 all of the arguments are found, false if
-any are not found.
-.TP
-\fBulimit\fP [\fB\-HSTabcdefilmnpqrstuvx\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 by a non-root user 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 \-b
-The maximum socket buffer size
-.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 (many systems do not honor this limit)
-.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 and, on
-some systems, to its children
-.TP
-.B \-x
-The maximum number of file locks
-.TP
-.B \-T
-The maximum number of threads
-.PD
-.PP
-If
-.I limit
-is given, and the
-.B \-a
-option is not used,
-\fIlimit\fP is the new value of the specified resource.
-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
-.BR \-T ,
-.BR \-b ,
-.BR \-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 the
-.B \-v
-option is given, each
-.I name
-refers to a shell variable, and that variable is removed.
-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.
-If no options are supplied, each \fIname\fP refers to a variable; if
-there is no variable by that name, any function with that name is
-unset.
-Each unset variable or function is removed from the environment
-passed to subsequent commands.
-If any of
-.SM
-.BR COMP_WORDBREAKS ,
-.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
-.SM
-.BR SHELL ,
-.SM
-.BR PATH ,
-.SM
-.BR ENV ,
-or
-.SM
-.B BASH_ENV
-.IP \(bu
-specifying command names containing
-.B /
-.IP \(bu
-specifying a filename 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
-.SM
-.B SHELLOPTS
-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.ramey@case.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/gnu/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.ramey@case.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
-Array variables may not (yet) be exported.
-.PP
-There may be only one active coprocess at a time.
-.zZ
-.zY
+++ /dev/null
-/* error.c -- Functions for handling errors. */
-
-/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#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 last_command_exit_value;
-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 const char * const 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
-
-const char * const 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 || *name == '\0') /* XXX - was just 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;
-
- error_prolog (1);
- fprintf (stderr, _("warning: "));
-
- 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 (last_command_exit_value = 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 const char * const 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);
-}
+++ /dev/null
-#
-# Simple makefile for the sample loadable builtins
-#
-# Copyright (C) 1996 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.
-
-# Include some boilerplate Gnu makefile definitions.
-prefix = @prefix@
-
-exec_prefix = @exec_prefix@
-bindir = @bindir@
-libdir = @libdir@
-infodir = @infodir@
-includedir = @includedir@
-
-topdir = @top_srcdir@
-BUILD_DIR = @BUILD_DIR@
-srcdir = @srcdir@
-VPATH = .:@srcdir@
-
-@SET_MAKE@
-CC = @CC@
-RM = rm -f
-
-SHELL = @MAKE_SHELL@
-
-host_os = @host_os@
-host_cpu = @host_cpu@
-host_vendor = @host_vendor@
-
-CFLAGS = @CFLAGS@
-LOCAL_CFLAGS = @LOCAL_CFLAGS@
-DEFS = @DEFS@
-LOCAL_DEFS = @LOCAL_DEFS@
-
-CPPFLAGS = @CPPFLAGS@
-
-BASHINCDIR = ${topdir}/include
-
-LIBBUILD = ${BUILD_DIR}/lib
-
-INTL_LIBSRC = ${topdir}/lib/intl
-INTL_BUILDDIR = ${LIBBUILD}/intl
-INTL_INC = @INTL_INC@
-LIBINTL_H = @LIBINTL_H@
-
-CCFLAGS = $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) $(CFLAGS)
-
-#
-# These values are generated for configure by ${topdir}/support/shobj-conf.
-# If your system is not supported by that script, but includes facilities for
-# dynamic loading of shared objects, please update the script and send the
-# changes to bash-maintainers@gnu.org.
-#
-SHOBJ_CC = @SHOBJ_CC@
-SHOBJ_CFLAGS = @SHOBJ_CFLAGS@
-SHOBJ_LD = @SHOBJ_LD@
-SHOBJ_LDFLAGS = @SHOBJ_LDFLAGS@
-SHOBJ_XLDFLAGS = @SHOBJ_XLDFLAGS@
-SHOBJ_LIBS = @SHOBJ_LIBS@
-SHOBJ_STATUS = @SHOBJ_STATUS@
-
-INC = -I. -I.. -I$(topdir) -I$(topdir)/lib -I$(topdir)/builtins \
- -I$(BASHINCDIR) -I$(BUILD_DIR) -I$(LIBBUILD) \
- -I$(BUILD_DIR)/builtins $(INTL_INC)
-
-.c.o:
- $(SHOBJ_CC) $(SHOBJ_CFLAGS) $(CCFLAGS) $(INC) -c -o $@ $<
-
-
-ALLPROG = print truefalse sleep pushd finfo logname basename dirname \
- tty pathchk tee head mkdir rmdir printenv id whoami \
- uname sync push ln unlink cut realpath getconf strftime
-OTHERPROG = necho hello cat
-
-all: $(SHOBJ_STATUS)
-
-supported: $(ALLPROG)
-others: $(OTHERPROG)
-
-unsupported:
- @echo "Your system (${host_os}) is not supported by the"
- @echo "${topdir}/support/shobj-conf script."
- @echo "If your operating system provides facilities for dynamic"
- @echo "loading of shared objects using the dlopen(3) interface,"
- @echo "please update the script and re-run configure.
- @echo "Please send the changes you made to bash-maintainers@gnu.org"
- @echo "for inclusion in future bash releases."
-
-everything: supported others
-
-print: print.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ print.o $(SHOBJ_LIBS)
-
-necho: necho.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ necho.o $(SHOBJ_LIBS)
-
-getconf: getconf.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ getconf.o $(SHOBJ_LIBS)
-
-hello: hello.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ hello.o $(SHOBJ_LIBS)
-
-truefalse: truefalse.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ truefalse.o $(SHOBJ_LIBS)
-
-sleep: sleep.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sleep.o $(SHOBJ_LIBS)
-
-finfo: finfo.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ finfo.o $(SHOBJ_LIBS)
-
-cat: cat.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cat.o $(SHOBJ_LIBS)
-
-logname: logname.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ logname.o $(SHOBJ_LIBS)
-
-basename: basename.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ basename.o $(SHOBJ_LIBS)
-
-dirname: dirname.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ dirname.o $(SHOBJ_LIBS)
-
-tty: tty.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tty.o $(SHOBJ_LIBS)
-
-pathchk: pathchk.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pathchk.o $(SHOBJ_LIBS)
-
-tee: tee.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ tee.o $(SHOBJ_LIBS)
-
-mkdir: mkdir.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ mkdir.o $(SHOBJ_LIBS)
-
-rmdir: rmdir.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ rmdir.o $(SHOBJ_LIBS)
-
-head: head.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ head.o $(SHOBJ_LIBS)
-
-printenv: printenv.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ printenv.o $(SHOBJ_LIBS)
-
-id: id.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ id.o $(SHOBJ_LIBS)
-
-whoami: whoami.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ whoami.o $(SHOBJ_LIBS)
-
-uname: uname.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ uname.o $(SHOBJ_LIBS)
-
-sync: sync.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ sync.o $(SHOBJ_LIBS)
-
-push: push.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ push.o $(SHOBJ_LIBS)
-
-ln: ln.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ ln.o $(SHOBJ_LIBS)
-
-unlink: unlink.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ unlink.o $(SHOBJ_LIBS)
-
-cut: cut.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ cut.o $(SHOBJ_LIBS)
-
-realpath: realpath.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ realpath.o $(SHOBJ_LIBS)
-
-strftime: strftime.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ strftime.o $(SHOBJ_LIBS)
-
-# pushd is a special case. We use the same source that the builtin version
-# uses, with special compilation options.
-#
-pushd.c: ${topdir}/builtins/pushd.def
- $(RM) $@
- ${BUILD_DIR}/builtins/mkbuiltins -D ${topdir}/builtins ${topdir}/builtins/pushd.def
-
-pushd.o: pushd.c
- $(RM) $@
- $(SHOBJ_CC) -DHAVE_CONFIG_H -DPUSHD_AND_POPD -DLOADABLE_BUILTIN $(SHOBJ_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(INC) -c -o $@ $<
-
-pushd: pushd.o
- $(SHOBJ_LD) $(SHOBJ_LDFLAGS) $(SHOBJ_XLDFLAGS) -o $@ pushd.o $(SHOBJ_LIBS)
-
-clean:
- $(RM) $(ALLPROG) $(OTHERPROG) *.o
- -( cd perl && ${MAKE} ${MFLAGS} $@ )
-
-mostlyclean: clean
- -( cd perl && ${MAKE} ${MFLAGS} $@ )
-
-distclean maintainer-clean: clean
- $(RM) Makefile pushd.c
- -( cd perl && ${MAKE} ${MFLAGS} $@ )
-
-print.o: print.c
-truefalse.o: truefalse.c
-sleep.o: sleep.c
-finfo.o: finfo.c
-logname.o: logname.c
-basename.o: basename.c
-dirname.o: dirname.c
-tty.o: tty.c
-pathchk.o: pathchk.c
-tee.o: tee.c
-head.o: head.c
-rmdir.o: rmdir.c
-necho.o: necho.c
-getconf.o: getconf.c
-hello.o: hello.c
-cat.o: cat.c
-printenv.o: printenv.c
-id.o: id.c
-whoami.o: whoami.c
-uname.o: uname.c
-sync.o: sync.c
-push.o: push.c
-mkdir.o: mkdir.c
-realpath.o: realpath.c
-strftime.o: strftime.c
+++ /dev/null
-#!/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
+++ /dev/null
-/* execute_cmd.c -- Execute a COMMAND structure. */
-
-/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#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
-
-#define NEED_FPURGE_DECL
-
-#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 dollar_dollar_pid;
-extern int posixly_correct;
-extern int expand_aliases;
-extern int autocd;
-extern int breaking, continuing, loop_level;
-extern int parse_and_execute_level, running_trap, sourcelevel;
-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;
-extern time_t shell_start_time;
-#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 displen __P((const char *));
-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 int 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 *));
-#if defined (COPROCESS_SUPPORT)
-static int execute_coproc __P((COMMAND *, int, int, struct fd_bitmap *));
-#endif
-
-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 *, FUNCTION_DEF *));
-
-/* 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;
-
-/* 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;
-
-/* When greater than zero, value is the `level' of builtins we are
- currently executing (e.g. `eval echo a' would have it set to 2). */
-int executing_builtin = 0;
-
-/* Non-zero if we are executing a command list (a;b;c, etc.) */
-int executing_list = 0;
-
-/* Non-zero if failing commands in a command substitution should not exit the
- shell even if -e is set. Used to pass the CMD_IGNORE_RETURN flag down to
- commands run in command substitutions by parse_and_execute. */
-int comsub_ignore_return = 0;
-
-/* 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;
-
-int executing_command_builtin = 0;
-
-struct stat SB; /* used for debugging */
-
-static int special_builtin_failed;
-
-static COMMAND *currently_executing_command;
-
-/* The line number that the currently executing function starts on. */
-static int function_line_number;
-
-/* 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;
-
-/* A sort of function nesting level counter */
-int funcnest = 0;
-int funcnest_max = 0; /* XXX - bash-4.2 */
-
-int lastpipe_opt = 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, user_subshell, invert, ignore_return, was_error_trap;
- REDIRECT *my_undo_list, *exec_undo_list;
- volatile int last_pid;
- volatile int save_line_number;
-#if defined (PROCESS_SUBSTITUTION)
- volatile int ofifo, nfifo, osize, saved_fifo;
- volatile char *ofifo_list;
-#endif
-
-#if 0
- if (command == 0 || breaking || continuing || read_but_dont_execute)
- return (EXECUTION_SUCCESS);
-#else
- if (breaking || continuing)
- return (last_command_exit_value);
- if (command == 0 || read_but_dont_execute)
- return (EXECUTION_SUCCESS);
-#endif
-
- 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 defined (COPROCESS_SUPPORT)
- if (command->type == cm_coproc)
- return (execute_coproc (command, pipe_in, pipe_out, fds_to_close));
-#endif
-
- user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0);
-
- 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. */
- line_number_for_err_trap = line_number;
- 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)
- if (variable_context == 0) /* wait until shell function completes */
- 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)
- {
- was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
- invert = (command->flags & CMD_INVERT_RETURN) != 0;
- ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
- exec_result = wait_for (paren_pid);
-
- /* If we have to, invert the return value. */
- if (invert)
- exec_result = ((exec_result == EXECUTION_SUCCESS)
- ? EXECUTION_FAILURE
- : EXECUTION_SUCCESS);
-
- last_command_exit_value = exec_result;
- if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
- {
- save_line_number = line_number;
- line_number = line_number_for_err_trap;
- run_error_trap ();
- line_number = save_line_number;
- }
-
- if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
- {
- run_pending_traps ();
- jump_to_top_level (ERREXIT);
- }
-
- return (last_command_exit_value);
- }
- 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);
-
-#if defined (PROCESS_SUBSTITUTION)
- if (variable_context != 0)
- {
- ofifo = num_fifos ();
- ofifo_list = copy_fifo_list (&osize);
- saved_fifo = 1;
- }
- else
- saved_fifo = 0;
-#endif
-
- /* 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 ();
-#if defined (PROCESS_SUBSTITUTION)
- if (saved_fifo)
- free (ofifo_list);
-#endif
- return (last_command_exit_value = EXECUTION_FAILURE);
- }
-
- if (redirection_undo_list)
- {
- /* XXX - why copy here? */
- 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)
- {
- /* XXX - why copy here? */
- 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);
- }
- }
-
- /* 2009/02/13 -- pipeline failure is processed elsewhere. This handles
- only the failure of a simple command. */
- if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
- line_number = line_number_for_err_trap;
- run_error_trap ();
- line_number = save_line_number;
- }
-
- if (ignore_return == 0 && invert == 0 &&
- ((posixly_correct && interactive == 0 && special_builtin_failed) ||
- (exit_immediately_on_error && pipe_in == NO_PIPE && pipe_out == NO_PIPE && 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:
- was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
- if (ignore_return)
- command->value.Arith->flags |= CMD_IGNORE_RETURN;
- line_number_for_err_trap = save_line_number = line_number;
- exec_result = execute_arith_command (command->value.Arith);
- line_number = save_line_number;
-
- if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
- save_line_number = line_number;
- line_number = line_number_for_err_trap;
- run_error_trap ();
- line_number = save_line_number;
- }
-
- if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
- run_pending_traps ();
- jump_to_top_level (ERREXIT);
- }
-
- break;
-#endif
-
-#if defined (COND_COMMAND)
- case cm_cond:
- was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
- if (ignore_return)
- command->value.Cond->flags |= CMD_IGNORE_RETURN;
-
- line_number_for_err_trap = save_line_number = line_number;
- exec_result = execute_cond_command (command->value.Cond);
- line_number = save_line_number;
-
- if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
- save_line_number = line_number;
- line_number = line_number_for_err_trap;
- run_error_trap ();
- line_number = save_line_number;
- }
-
- if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
- run_pending_traps ();
- jump_to_top_level (ERREXIT);
- }
-
- break;
-#endif
-
- case cm_function_def:
- exec_result = execute_intern_function (command->value.Function_def->name,
- command->value.Function_def);
- 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");
-
-#if defined (PROCESS_SUBSTITUTION)
- if (saved_fifo)
- {
- nfifo = num_fifos ();
- if (nfifo > ofifo)
- close_new_fifos (ofifo_list, osize);
- free (ofifo_list);
- }
-#endif
-
- /* 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 const 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 0
- /* clamp CPU usage at 100% */
- if (cpu > 10000)
- cpu = 10000;
-#endif
- 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, nullcmd;
- 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 && (command->flags & CMD_TIME_POSIX);
-
- nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
- if (posixly_correct && nullcmd)
- {
-#if defined (HAVE_GETRUSAGE)
- selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = kidsb.ru_stime.tv_sec = 0;
- selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec = kidsb.ru_stime.tv_usec = 0;
- before.tv_sec = shell_start_time;
- before.tv_usec = 0;
-#else
- before.tms_utime = before.tms_stime = before.tms_cutime = before.tms_cstime = 0;
- tbefore = shell_start_time;
-#endif
- }
-
- 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)
- {
- if (posixly_correct && nullcmd)
- time_format = "user\t%2lU\nsys\t%2lS";
- else
- 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, user_coproc;
- int result;
- volatile COMMAND *tcom;
-
- USE_VAR(user_subshell);
- USE_VAR(user_coproc);
- 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);
- user_coproc = command->type == cm_coproc;
-
- 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;
- if (user_coproc)
- subshell_environment |= SUBSHELL_COPROC;
- }
-
- reset_terminating_signals (); /* in sig.c */
- /* Cancel traps, in trap.c. */
- /* Reset the signal handlers in the child, but don't free the
- trap strings. Set a flag noting that we have to free the
- trap strings if we run trap to change a signal disposition. */
- reset_signal_handlers ();
- subshell_environment |= SUBSHELL_RESETTRAP;
-
- /* 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 defined (COPROCESS_SUPPORT)
- coproc_closeall ();
-#endif
-
- /* 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;
- }
-
- if (command->type == cm_subshell)
- tcom = command->value.Subshell->command;
- else if (user_coproc)
- tcom = command->value.Coproc->command;
- else
- tcom = 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 || user_coproc) && (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;
-
- result = setjmp (top_level);
-
- /* 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 we're going to exit the shell, we don't want to invert the return
- status. */
- if (result == EXITPROG)
- invert = 0, return_code = last_command_exit_value;
- else if (result)
- return_code = EXECUTION_FAILURE;
- else if (function_value)
- return_code = return_catch_value;
- else
- return_code = execute_command_internal ((COMMAND *)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 */
-}
-
-#if defined (COPROCESS_SUPPORT)
-#define COPROC_MAX 16
-
-typedef struct cpelement
- {
- struct cpelement *next;
- struct coproc *coproc;
- }
-cpelement_t;
-
-typedef struct cplist
- {
- struct cpelement *head;
- struct cpelement *tail;
- int ncoproc;
- }
-cplist_t;
-
-static struct cpelement *cpe_alloc __P((struct coproc *));
-static void cpe_dispose __P((struct cpelement *));
-static struct cpelement *cpl_add __P((struct coproc *));
-static struct cpelement *cpl_delete __P((pid_t));
-static void cpl_reap __P((void));
-static void cpl_flush __P((void));
-static void cpl_closeall __P((void));
-static struct cpelement *cpl_search __P((pid_t));
-static struct cpelement *cpl_searchbyname __P((const char *));
-static void cpl_prune __P((void));
-
-static void coproc_free __P((struct coproc *));
-
-/* Will go away when there is fully-implemented support for multiple coprocs. */
-Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0, 0, 0 };
-
-cplist_t coproc_list = {0, 0, 0};
-
-/* Functions to manage the list of coprocs */
-
-static struct cpelement *
-cpe_alloc (cp)
- Coproc *cp;
-{
- struct cpelement *cpe;
-
- cpe = (struct cpelement *)xmalloc (sizeof (struct cpelement));
- cpe->coproc = cp;
- cpe->next = (struct cpelement *)0;
- return cpe;
-}
-
-static void
-cpe_dispose (cpe)
- struct cpelement *cpe;
-{
- free (cpe);
-}
-
-static struct cpelement *
-cpl_add (cp)
- Coproc *cp;
-{
- struct cpelement *cpe;
-
- cpe = cpe_alloc (cp);
-
- if (coproc_list.head == 0)
- {
- coproc_list.head = coproc_list.tail = cpe;
- coproc_list.ncoproc = 0; /* just to make sure */
- }
- else
- {
- coproc_list.tail->next = cpe;
- coproc_list.tail = cpe;
- }
- coproc_list.ncoproc++;
-
- return cpe;
-}
-
-static struct cpelement *
-cpl_delete (pid)
- pid_t pid;
-{
- struct cpelement *prev, *p;
-
- for (prev = p = coproc_list.head; p; prev = p, p = p->next)
- if (p->coproc->c_pid == pid)
- {
- prev->next = p->next; /* remove from list */
- break;
- }
-
- if (p == 0)
- return 0; /* not found */
-
-#if defined (DEBUG)
- itrace("cpl_delete: deleting %d", pid);
-#endif
-
- /* Housekeeping in the border cases. */
- if (p == coproc_list.head)
- coproc_list.head = coproc_list.head->next;
- else if (p == coproc_list.tail)
- coproc_list.tail = prev;
-
- coproc_list.ncoproc--;
- if (coproc_list.ncoproc == 0)
- coproc_list.head = coproc_list.tail = 0;
- else if (coproc_list.ncoproc == 1)
- coproc_list.tail = coproc_list.head; /* just to make sure */
-
- return (p);
-}
-
-static void
-cpl_reap ()
-{
- struct cpelement *p, *next, *nh, *nt;
-
- /* Build a new list by removing dead coprocs and fix up the coproc_list
- pointers when done. */
- nh = nt = next = (struct cpelement *)0;
- for (p = coproc_list.head; p; p = next)
- {
- next = p->next;
- if (p->coproc->c_flags & COPROC_DEAD)
- {
- coproc_list.ncoproc--; /* keep running count, fix up pointers later */
-
-#if defined (DEBUG)
- itrace("cpl_reap: deleting %d", p->coproc->c_pid);
-#endif
-
- coproc_dispose (p->coproc);
- cpe_dispose (p);
- }
- else if (nh == 0)
- nh = nt = p;
- else
- {
- nt->next = p;
- nt = nt->next;
- }
- }
-
- if (coproc_list.ncoproc == 0)
- coproc_list.head = coproc_list.tail = 0;
- else
- {
- if (nt)
- nt->next = 0;
- coproc_list.head = nh;
- coproc_list.tail = nt;
- if (coproc_list.ncoproc == 1)
- coproc_list.tail = coproc_list.head; /* just to make sure */
- }
-}
-
-/* Clear out the list of saved statuses */
-static void
-cpl_flush ()
-{
- struct cpelement *cpe, *p;
-
- for (cpe = coproc_list.head; cpe; )
- {
- p = cpe;
- cpe = cpe->next;
-
- coproc_dispose (p->coproc);
- cpe_dispose (p);
- }
-
- coproc_list.head = coproc_list.tail = 0;
- coproc_list.ncoproc = 0;
-}
-
-static void
-cpl_closeall ()
-{
- struct cpelement *cpe;
-
- for (cpe = coproc_list.head; cpe; cpe = cpe->next)
- coproc_close (cpe->coproc);
-}
-
-static void
-cpl_fdchk (fd)
- int fd;
-{
- struct cpelement *cpe;
-
- for (cpe = coproc_list.head; cpe; cpe = cpe->next)
- coproc_checkfd (cpe->coproc, fd);
-}
-
-/* Search for PID in the list of coprocs; return the cpelement struct if
- found. If not found, return NULL. */
-static struct cpelement *
-cpl_search (pid)
- pid_t pid;
-{
- struct cpelement *cpe;
-
- for (cpe = coproc_list.head ; cpe; cpe = cpe->next)
- if (cpe->coproc->c_pid == pid)
- return cpe;
- return (struct cpelement *)NULL;
-}
-
-/* Search for the coproc named NAME in the list of coprocs; return the
- cpelement struct if found. If not found, return NULL. */
-static struct cpelement *
-cpl_searchbyname (name)
- const char *name;
-{
- struct cpelement *cp;
-
- for (cp = coproc_list.head ; cp; cp = cp->next)
- if (STREQ (cp->coproc->c_name, name))
- return cp;
- return (struct cpelement *)NULL;
-}
-
-#if 0
-static void
-cpl_prune ()
-{
- struct cpelement *cp;
-
- while (coproc_list.head && coproc_list.ncoproc > COPROC_MAX)
- {
- cp = coproc_list.head;
- coproc_list.head = coproc_list.head->next;
- coproc_dispose (cp->coproc);
- cpe_dispose (cp);
- coproc_list.ncoproc--;
- }
-}
-#endif
-
-/* These currently use a single global "shell coproc" but are written in a
- way to not preclude additional coprocs later (using the list management
- package above). */
-
-struct coproc *
-getcoprocbypid (pid)
- pid_t pid;
-{
-#if MULTIPLE_COPROCS
- struct cpelement *p;
-
- p = cpl_search (pid);
- return (p ? p->coproc : 0);
-#else
- return (pid == sh_coproc.c_pid ? &sh_coproc : 0);
-#endif
-}
-
-struct coproc *
-getcoprocbyname (name)
- const char *name;
-{
-#if MULTIPLE_COPROCS
- struct cpelement *p;
-
- p = cpl_searchbyname (name);
- return (p ? p->coproc : 0);
-#else
- return ((sh_coproc.c_name && STREQ (sh_coproc.c_name, name)) ? &sh_coproc : 0);
-#endif
-}
-
-void
-coproc_init (cp)
- struct coproc *cp;
-{
- cp->c_name = 0;
- cp->c_pid = NO_PID;
- cp->c_rfd = cp->c_wfd = -1;
- cp->c_rsave = cp->c_wsave = -1;
- cp->c_flags = cp->c_status = 0;
-}
-
-struct coproc *
-coproc_alloc (name, pid)
- char *name;
- pid_t pid;
-{
- struct coproc *cp;
-
-#if MULTIPLE_COPROCS
- cp = (struct coproc *)xmalloc (sizeof (struct coproc));
-#else
- cp = &sh_coproc;
-#endif
- coproc_init (cp);
-
- cp->c_name = savestring (name);
- cp->c_pid = pid;
-
-#if MULTIPLE_COPROCS
- cpl_add (cp);
-#endif
-
- return (cp);
-}
-
-static void
-coproc_free (cp)
- struct coproc *cp;
-{
- free (cp);
-}
-
-void
-coproc_dispose (cp)
- struct coproc *cp;
-{
- if (cp == 0)
- return;
-
- coproc_unsetvars (cp);
- FREE (cp->c_name);
- coproc_close (cp);
-#if MULTIPLE_COPROCS
- coproc_free (cp);
-#else
- coproc_init (cp);
-#endif
-}
-
-/* Placeholder for now. Will require changes for multiple coprocs */
-void
-coproc_flush ()
-{
-#if MULTIPLE_COPROCS
- cpl_flush ();
-#else
- coproc_dispose (&sh_coproc);
-#endif
-}
-
-void
-coproc_close (cp)
- struct coproc *cp;
-{
- if (cp->c_rfd >= 0)
- {
- close (cp->c_rfd);
- cp->c_rfd = -1;
- }
- if (cp->c_wfd >= 0)
- {
- close (cp->c_wfd);
- cp->c_wfd = -1;
- }
- cp->c_rsave = cp->c_wsave = -1;
-}
-
-void
-coproc_closeall ()
-{
-#if MULTIPLE_COPROCS
- cpl_closeall ();
-#else
- coproc_close (&sh_coproc); /* XXX - will require changes for multiple coprocs */
-#endif
-}
-
-void
-coproc_reap ()
-{
-#if MULTIPLE_COPROCS
- cpl_reap ();
-#else
- struct coproc *cp;
-
- cp = &sh_coproc; /* XXX - will require changes for multiple coprocs */
- if (cp && (cp->c_flags & COPROC_DEAD))
- coproc_dispose (cp);
-#endif
-}
-
-void
-coproc_rclose (cp, fd)
- struct coproc *cp;
- int fd;
-{
- if (cp->c_rfd >= 0 && cp->c_rfd == fd)
- {
- close (cp->c_rfd);
- cp->c_rfd = -1;
- }
-}
-
-void
-coproc_wclose (cp, fd)
- struct coproc *cp;
- int fd;
-{
- if (cp->c_wfd >= 0 && cp->c_wfd == fd)
- {
- close (cp->c_wfd);
- cp->c_wfd = -1;
- }
-}
-
-void
-coproc_checkfd (cp, fd)
- struct coproc *cp;
- int fd;
-{
- int update;
-
- update = 0;
- if (cp->c_rfd >= 0 && cp->c_rfd == fd)
- update = cp->c_rfd = -1;
- if (cp->c_wfd >= 0 && cp->c_wfd == fd)
- update = cp->c_wfd = -1;
- if (update)
- coproc_setvars (cp);
-}
-
-void
-coproc_fdchk (fd)
- int fd;
-{
-#if MULTIPLE_COPROCS
- cpl_fdchk (fd);
-#else
- coproc_checkfd (&sh_coproc, fd);
-#endif
-}
-
-void
-coproc_fdclose (cp, fd)
- struct coproc *cp;
- int fd;
-{
- coproc_rclose (cp, fd);
- coproc_wclose (cp, fd);
- coproc_setvars (cp);
-}
-
-void
-coproc_fdsave (cp)
- struct coproc *cp;
-{
- cp->c_rsave = cp->c_rfd;
- cp->c_wsave = cp->c_wfd;
-}
-
-void
-coproc_fdrestore (cp)
- struct coproc *cp;
-{
- cp->c_rfd = cp->c_rsave;
- cp->c_wfd = cp->c_wsave;
-}
-
-void
-coproc_pidchk (pid, status)
- pid_t pid;
-{
- struct coproc *cp;
-
-#if MULTIPLE_COPROCS
- struct cpelement *cpe;
-
- cpe = cpl_delete (pid);
- cp = cpe ? cpe->coproc : 0;
-#else
- cp = getcoprocbypid (pid);
-#endif
- if (cp)
- {
-#if 0
- itrace("coproc_pidchk: pid %d has died", pid);
-#endif
- cp->c_status = status;
- cp->c_flags |= COPROC_DEAD;
- cp->c_flags &= ~COPROC_RUNNING;
-#if MULTIPLE_COPROCS
- coproc_dispose (cp);
-#else
- coproc_unsetvars (cp);
-#endif
- }
-}
-
-void
-coproc_setvars (cp)
- struct coproc *cp;
-{
- SHELL_VAR *v;
- char *namevar, *t;
- int l;
-#if defined (ARRAY_VARS)
- arrayind_t ind;
-#endif
-
- if (cp->c_name == 0)
- return;
-
- l = strlen (cp->c_name);
- namevar = xmalloc (l + 16);
-
-#if defined (ARRAY_VARS)
- v = find_variable (cp->c_name);
- if (v == 0)
- v = make_new_array_variable (cp->c_name);
- if (array_p (v) == 0)
- v = convert_var_to_array (v);
-
- t = itos (cp->c_rfd);
- ind = 0;
- v = bind_array_variable (cp->c_name, ind, t, 0);
- free (t);
-
- t = itos (cp->c_wfd);
- ind = 1;
- bind_array_variable (cp->c_name, ind, t, 0);
- free (t);
-#else
- sprintf (namevar, "%s_READ", cp->c_name);
- t = itos (cp->c_rfd);
- bind_variable (namevar, t, 0);
- free (t);
- sprintf (namevar, "%s_WRITE", cp->c_name);
- t = itos (cp->c_wfd);
- bind_variable (namevar, t, 0);
- free (t);
-#endif
-
- sprintf (namevar, "%s_PID", cp->c_name);
- t = itos (cp->c_pid);
- bind_variable (namevar, t, 0);
- free (t);
-
- free (namevar);
-}
-
-void
-coproc_unsetvars (cp)
- struct coproc *cp;
-{
- int l;
- char *namevar;
-
- if (cp->c_name == 0)
- return;
-
- l = strlen (cp->c_name);
- namevar = xmalloc (l + 16);
-
- sprintf (namevar, "%s_PID", cp->c_name);
- unbind_variable (namevar);
-
-#if defined (ARRAY_VARS)
- unbind_variable (cp->c_name);
-#else
- sprintf (namevar, "%s_READ", cp->c_name);
- unbind_variable (namevar);
- sprintf (namevar, "%s_WRITE", cp->c_name);
- unbind_variable (namevar);
-#endif
-
- free (namevar);
-}
-
-static int
-execute_coproc (command, pipe_in, pipe_out, fds_to_close)
- COMMAND *command;
- int pipe_in, pipe_out;
- struct fd_bitmap *fds_to_close;
-{
- int rpipe[2], wpipe[2], estat;
- pid_t coproc_pid;
- Coproc *cp;
- char *tcmd;
-
- /* XXX -- can be removed after changes to handle multiple coprocs */
-#if !MULTIPLE_COPROCS
- if (sh_coproc.c_pid != NO_PID)
- internal_warning ("execute_coproc: coproc [%d:%s] still exists", sh_coproc.c_pid, sh_coproc.c_name);
- coproc_init (&sh_coproc);
-#endif
-
- command_string_index = 0;
- tcmd = make_command_string (command);
-
- sh_openpipe ((int *)&rpipe); /* 0 = parent read, 1 = child write */
- sh_openpipe ((int *)&wpipe); /* 0 = child read, 1 = parent write */
-
- coproc_pid = make_child (savestring (tcmd), 1);
- if (coproc_pid == 0)
- {
- close (rpipe[0]);
- close (wpipe[1]);
-
- estat = execute_in_subshell (command, 1, wpipe[0], rpipe[1], fds_to_close);
-
- fflush (stdout);
- fflush (stderr);
-
- exit (estat);
- }
-
- close (rpipe[1]);
- close (wpipe[0]);
-
- cp = coproc_alloc (command->value.Coproc->name, coproc_pid);
- cp->c_rfd = rpipe[0];
- cp->c_wfd = wpipe[1];
-
- SET_CLOSE_ON_EXEC (cp->c_rfd);
- SET_CLOSE_ON_EXEC (cp->c_wfd);
-
- coproc_setvars (cp);
-
-#if 0
- itrace ("execute_coproc: [%d] %s", coproc_pid, the_printed_command);
-#endif
-
- close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
- unlink_fifo_list ();
-#endif
- stop_pipeline (1, (COMMAND *)NULL);
- DESCRIBE_PID (coproc_pid);
- run_pending_traps ();
-
- return (EXECUTION_SUCCESS);
-}
-#endif
-
-static void
-restore_stdin (s)
- int s;
-{
- dup2 (s, 0);
- close (s);
-}
-
-/* Catch-all cleanup function for lastpipe code for unwind-protects */
-static void
-lastpipe_cleanup (s)
- int s;
-{
- unfreeze_jobs_list ();
-}
-
-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;
- int lstdin, lastpipe_flag, lastpipe_jid;
- COMMAND *cmd;
- struct fd_bitmap *fd_bitmap;
- pid_t lastpid;
-
-#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;
- }
-
- lastpid = last_made_pid;
-
- /* Now execute the rightmost command in the pipeline. */
- if (ignore_return && cmd)
- cmd->flags |= CMD_IGNORE_RETURN;
-
-#if defined (JOB_CONTROL)
- lastpipe_flag = 0;
- begin_unwind_frame ("lastpipe-exec");
- lstdin = -1;
- /* If the `lastpipe' option is set with shopt, and job control is not
- enabled, execute the last element of non-async pipelines in the
- current shell environment. */
- if (lastpipe_opt && job_control == 0 && asynchronous == 0 && pipe_out == NO_PIPE && prev > 0)
- {
- lstdin = move_to_high_fd (0, 0, 255);
- if (lstdin > 0)
- {
- do_piping (prev, pipe_out);
- prev = NO_PIPE;
- add_unwind_protect (restore_stdin, lstdin);
- lastpipe_flag = 1;
- freeze_jobs_list ();
- lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL); /* XXX */
- add_unwind_protect (lastpipe_cleanup, lastpipe_jid);
- }
- if (cmd)
- cmd->flags |= CMD_LASTPIPE;
- }
- if (prev >= 0)
- add_unwind_protect (close, prev);
-#endif
-
- exec_result = execute_command_internal (cmd, asynchronous, prev, pipe_out, fds_to_close);
-
-#if defined (JOB_CONTROL)
- if (lstdin > 0)
- restore_stdin (lstdin);
-#endif
-
- if (prev >= 0)
- close (prev);
-
-#if defined (JOB_CONTROL)
- UNBLOCK_CHILD (oset);
-#endif
-
- QUIT;
-
- if (lastpipe_flag)
- {
-#if defined (JOB_CONTROL)
- append_process (savestring (the_printed_command), dollar_dollar_pid, exec_result, lastpipe_jid);
-#endif
- lstdin = wait_for (lastpid);
-#if defined (JOB_CONTROL)
- exec_result = job_exit_status (lastpipe_jid);
-#endif
- unfreeze_jobs_list ();
- }
-
- discard_unwind_frame ("lastpipe-exec");
-
- 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;
-{
- COMMAND *tc, *second;
- int ignore_return, exec_result, was_error_trap, invert;
- volatile int save_line_number;
-
- 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);
-
- 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);
- QUIT;
-
- 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;
- }
- executing_list++;
- 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);
- executing_list--;
- break;
-
- case '|':
- was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0;
- invert = (command->flags & CMD_INVERT_RETURN) != 0;
- ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
-
- line_number_for_err_trap = line_number;
- exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);
-
- if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
- save_line_number = line_number;
- line_number = line_number_for_err_trap;
- run_error_trap ();
- line_number = save_line_number;
- }
-
- if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
- {
- last_command_exit_value = exec_result;
- run_pending_traps ();
- jump_to_top_level (ERREXIT);
- }
-
- 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. */
-
- executing_list++;
- 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);
- }
- executing_list--;
- 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_BADUSAGE;
- 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 0
- if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
-#else
- if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-#endif
- {
- 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
-displen (s)
- const char *s;
-{
-#if defined (HANDLE_MULTIBYTE)
- wchar_t *wcstr;
- size_t wclen, slen;
-
- wcstr = 0;
- slen = mbstowcs (wcstr, s, 0);
- if (slen == -1)
- slen = 0;
- wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1));
- mbstowcs (wcstr, s, slen + 1);
- wclen = wcswidth (wcstr, slen);
- free (wcstr);
- return ((int)wclen);
-#else
- return (STRLEN (s));
-#endif
-}
-
-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)
- ;
- if (l == 0) /* don't think this can happen */
- return (0);
- fprintf (stderr, "%*d%s%s", len, ind, RP_SPACE, l->word->word);
- return (displen (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;
-
-#if 0
- t = get_string_value ("LINES");
- LINES = (t && *t) ? atoi (t) : 24;
-#endif
- 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 = displen (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_SUCCESS)
- {
- 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); /* XXX - can't be null? */
- }
-}
-
-/* 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 0
- if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
-#else
- if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-#endif
- {
- 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 0
- if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
-#else
- if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-#endif
- {
- 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)
- {
- do
- {
- if (clauses->action && ignore_return)
- clauses->action->flags |= CMD_IGNORE_RETURN;
- retval = execute_command (clauses->action);
- }
- while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next));
- if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0)
- EXIT_CASE ();
- else
- break;
- }
-
- 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 * const nullstr = "";
-
-/* XXX - can COND ever be NULL when this is called? */
-static int
-execute_cond_node (cond)
- COND_COM *cond;
-{
- int result, invert, patmatch, rmatch, mflags, ignore;
- char *arg1, *arg2;
-
- invert = (cond->flags & CMD_INVERT_RETURN);
- ignore = (cond->flags & CMD_IGNORE_RETURN);
- if (ignore)
- {
- if (cond->left)
- cond->left->flags |= CMD_IGNORE_RETURN;
- if (cond->right)
- cond->right->flags |= CMD_IGNORE_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)
- {
- if (ignore)
- comsub_ignore_return++;
- arg1 = cond_expand_word (cond->left->op, 0);
- if (ignore)
- comsub_ignore_return--;
- 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
-
- if (ignore)
- comsub_ignore_return++;
- arg1 = cond_expand_word (cond->left->op, 0);
- if (ignore)
- comsub_ignore_return--;
- if (arg1 == 0)
- arg1 = nullstr;
- if (ignore)
- comsub_ignore_return++;
- arg2 = cond_expand_word (cond->right->op,
- (rmatch && shell_compatibility_level > 31) ? 2 : (patmatch ? 1 : 0));
- if (ignore)
- comsub_ignore_return--;
- 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|TEST_LOCALE)
- ? 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;
- int forcefork;
- REDIRECT *rd;
-
- for (forcefork = 0, rd = redirects; rd; rd = rd->next)
- forcefork += rd->rflags & REDIR_VARASSIGN;
-
- if (forcefork || 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 defined (COPROCESS_SUPPORT)
- coproc_closeall ();
-#endif
-
- subshell_environment = 0;
- 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, *wcmd;
- struct builtin *b;
- int assoc;
-
- if (words == 0)
- return;
-
- b = 0;
- assoc = 0;
-
- wcmd = words;
- for (w = words; w; w = w->next)
- if (w->word->flags & W_ASSIGNMENT)
- {
- if (b == 0)
- {
- /* Posix (post-2008) says that `command' doesn't change whether
- or not the builtin it shadows is a `declaration command', even
- though it removes other special builtin properties. In Posix
- mode, we skip over one or more instances of `command' and
- deal with the next word as the assignment builtin. */
- while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command"))
- wcmd = wcmd->next;
- b = builtin_address_internal (wcmd->word->word, 0);
- if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
- return;
- else if (b && (b->flags & ASSIGNMENT_BUILTIN))
- wcmd->word->flags |= W_ASSNBLTIN;
- }
- w->word->flags |= (W_NOSPLIT|W_NOGLOB|W_TILDEEXP|W_ASSIGNARG);
-#if defined (ARRAY_VARS)
- if (assoc)
- w->word->flags |= W_ASSIGNASSOC;
-#endif
- }
-#if defined (ARRAY_VARS)
- /* Note that we saw an associative array option to a builtin that takes
- assignment statements. This is a bit of a kludge. */
- else if (w->word->word[0] == '-' && strchr (w->word->word, 'A'))
- {
- if (b == 0)
- {
- while (posixly_correct && wcmd && wcmd->word && wcmd->word->word && STREQ (wcmd->word->word, "command"))
- wcmd = wcmd->next;
- b = builtin_address_internal (wcmd->word->word, 0);
- if (b == 0 || (b->flags & ASSIGNMENT_BUILTIN) == 0)
- return;
- else if (b && (b->flags & ASSIGNMENT_BUILTIN))
- wcmd->word->flags |= W_ASSNBLTIN;
- }
- if (wcmd->word->flags & W_ASSNBLTIN)
- assoc = 1;
- }
-#endif
-}
-
-/* Return 1 if the file found by searching $PATH for PATHNAME, defaulting
- to PATHNAME, is a directory. Used by the autocd code below. */
-static int
-is_dirname (pathname)
- char *pathname;
-{
- char *temp;
- int ret;
-
- temp = search_for_command (pathname, 0);
- ret = (temp ? file_isdir (temp) : file_isdir (pathname));
- free (temp);
- return ret;
-}
-
-/* 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;
- volatile int old_builtin, old_command_builtin;
-
- result = EXECUTION_SUCCESS;
- special_builtin_failed = builtin_is_special = 0;
- command_line = (char *)0;
-
- QUIT;
-
- /* If we're in a function, update the line number information. */
- if (variable_context && interactive_shell && sourcelevel == 0)
- line_number -= function_line_number;
-
- /* Remember what this command line looks like at invocation. */
- command_string_index = 0;
- print_simple_command (simple_command);
-
-#if 0
- if (signal_in_progress (DEBUG_TRAP) == 0 && (this_command_name == 0 || (STREQ (this_command_name, "trap") == 0)))
-#else
- if (signal_in_progress (DEBUG_TRAP) == 0 && running_trap == 0)
-#endif
- {
- 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;
-#if defined (COPROCESS_SUPPORT)
- coproc_closeall ();
-#endif
-
- last_asynchronous_pid = old_last_async_pid;
- }
- else
- {
- /* Don't let simple commands that aren't the last command in a
- pipeline change $? for the rest of the pipeline (or at all). */
- if (pipe_out != NO_PIPE)
- result = last_command_exit_value;
- 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);
- /* Pass the ignore return flag down to command substitutions */
- if (simple_command->flags & CMD_IGNORE_RETURN) /* XXX */
- comsub_ignore_return++;
- words = expand_words (simple_command->words);
- if (simple_command->flags & CMD_IGNORE_RETURN)
- comsub_ignore_return--;
- 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 */
-
-run_builtin:
- /* 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 (builtin)
- {
- old_builtin = executing_builtin;
- old_command_builtin = executing_command_builtin;
- unwind_protect_int (executing_builtin); /* modified in execute_builtin */
- unwind_protect_int (executing_command_builtin); /* ditto */
- }
- if (already_forked)
- {
- /* reset_terminating_signals (); */ /* XXX */
- /* Reset the signal handlers in the child, but don't free the
- trap strings. Set a flag noting that we have to free the
- trap strings if we run trap to change a signal disposition. */
- reset_signal_handlers ();
- subshell_environment |= SUBSHELL_RESETTRAP;
-
- 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 (autocd && interactive && words->word && is_dirname (words->word->word))
- {
- words = make_word_list (make_word ("cd"), words);
- xtrace_print_word_list (words, 0);
- goto run_builtin;
- }
-
- if (command_line == 0)
- command_line = savestring (the_printed_command_except_trap);
-
-#if defined (PROCESS_SUBSTITUTION)
- if ((subshell_environment & SUBSHELL_COMSUB) && (simple_command->flags & CMD_NO_FORK) && fifos_pending() > 0)
- simple_command->flags &= ~CMD_NO_FORK;
-#endif
-
- result = 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);
- if (builtin)
- {
- executing_builtin = old_builtin;
- executing_command_builtin = old_command_builtin;
- }
- 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;
- char *error_trap;
-
- error_trap = 0;
- 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 and disable
- the ERR trap, then restore them when the command completes. This is
- also a problem (as below) for the command and source/. builtins. */
- if (subshell == 0 && (flags & CMD_IGNORE_RETURN) &&
- (builtin == eval_builtin || builtin == command_builtin || builtin == source_builtin))
- {
- begin_unwind_frame ("eval_builtin");
- unwind_protect_int (exit_immediately_on_error);
- error_trap = TRAP_STRING (ERROR_TRAP);
- if (error_trap)
- {
- error_trap = savestring (error_trap);
- add_unwind_protect (xfree, error_trap);
- add_unwind_protect (set_error_trap, error_trap);
- restore_default_signal (ERROR_TRAP);
- }
- 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);
- }
-
- executing_builtin++;
- executing_command_builtin |= builtin == command_builtin;
- 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;
- if (error_trap)
- {
- set_error_trap (error_trap);
- xfree (error_trap);
- }
- 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;
- volatile ARRAY *bash_source_a;
- volatile ARRAY *bash_lineno_a;
-#endif
- FUNCTION_DEF *shell_fn;
- char *sfile, *t;
-
- USE_VAR(fc);
-
- if (funcnest_max > 0 && funcnest >= funcnest_max)
- {
- internal_error (_("%s: maximum function nesting level exceeded (%d)"), var->name, funcnest);
- funcnest = 0; /* XXX - should we reset it somewhere else? */
- jump_to_top_level (DISCARD);
- }
-
-#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);
- unwind_protect_int (funcnest);
- }
- 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 ((ARRAY *)funcname_a, this_shell_function->name);
-
- array_push ((ARRAY *)bash_source_a, sfile);
- t = itos (executing_line_number ());
- array_push ((ARRAY *)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");
-
-#if defined (ARRAY_VARS)
- /* These two variables cannot be unset, and cannot be affected by the
- function. */
- array_pop ((ARRAY *)bash_source_a);
- array_pop ((ARRAY *)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);
-#if defined (PROCESS_SUBSTITUTION)
- unlink_fifo_list ();
-#endif
- }
-
- 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);
- fflush (stdout);
- if (r == EX_USAGE)
- r = EX_BADUSAGE;
- exit (r);
- }
- }
- else
- {
- r = execute_function (var, words, flags, fds_to_close, async, 1);
- fflush (stdout);
- exit (r);
- }
-}
-
-/* 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;
-#if defined (PROCESS_SUBSTITUTION)
- int ofifo, nfifo, osize;
- char *ofifo_list;
-#endif
-
-
-#if defined (PROCESS_SUBSTITUTION)
- ofifo = num_fifos ();
- ofifo_list = copy_fifo_list (&osize);
-#endif
-
- if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
- {
- cleanup_redirects (redirection_undo_list);
- redirection_undo_list = (REDIRECT *)NULL;
- dispose_exec_redirects ();
-#if defined (PROCESS_SUBSTITUTION)
- free (ofifo_list);
-#endif
- return (EX_REDIRFAIL); /* was EXECUTION_FAILURE */
- }
-
- 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. */
- fflush (stdout);
- fpurge (stdout);
- 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)
- {
- int discard;
-
- discard = 0;
- if (saved_undo_list)
- {
- dispose_redirects (saved_undo_list);
- discard = 1;
- }
- redirection_undo_list = exec_redirection_undo_list;
- saved_undo_list = exec_redirection_undo_list = (REDIRECT *)NULL;
- if (discard)
- 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;
- }
-
-#if defined (PROCESS_SUBSTITUTION)
- /* Close any FIFOs created by this builtin or function. */
- nfifo = num_fifos ();
- if (nfifo > ofifo)
- close_new_fifos (ofifo_list, osize);
- free (ofifo_list);
-#endif
-
- 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(). */
-
-/* Name of a shell function to call when a command name is not found. */
-#ifndef NOTFOUND_HOOK
-# define NOTFOUND_HOOK "command_not_found_handle"
-#endif
-
-static int
-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, result;
- pid_t pid;
- SHELL_VAR *hookf;
- WORD_LIST *wl;
-
- nofork = (cmdflags & CMD_NO_FORK); /* Don't fork, just exec, if no pipes */
- pathname = words->word->word;
-
- result = EXECUTION_SUCCESS;
-#if defined (RESTRICTED_SHELL)
- command = (char *)NULL;
- if (restricted && mbschr (pathname, '/'))
- {
- internal_error (_("%s: restricted: cannot specify `/' in command names"),
- pathname);
- result = 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, 1);
-
- 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
-
- reset_terminating_signals (); /* XXX */
- /* 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)
- {
-itrace("not found");
- hookf = find_function (NOTFOUND_HOOK);
- if (hookf == 0)
- {
- /* Make sure filenames are displayed using printable characters */
- if (ansic_shouldquote (pathname))
- pathname = ansic_quote (pathname, 0, NULL);
- internal_error (_("%s: command not found"), pathname);
- exit (EX_NOTFOUND); /* Posix.2 says the exit status is 127 */
- }
-
- wl = make_word_list (make_word (NOTFOUND_HOOK), words);
- exit (execute_shell_function (hookf, wl));
- }
-
- /* 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:
- QUIT;
-
- /* Make sure that the pipes are closed in the parent. */
- close_pipes (pipe_in, pipe_out);
-#if defined (PROCESS_SUBSTITUTION) && defined (HAVE_DEV_FD)
- if (variable_context == 0)
- unlink_fifo_list ();
-#endif
- FREE (command);
- return (result);
- }
-}
-
-/* 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);
- /* XXX -- are there other things we should be resetting here? */
- parse_and_execute_level = 0; /* nothing left to restore it */
-
- /* We're no longer inside a shell function. */
- variable_context = return_catch_flag = funcnest = 0;
-
- executing_list = 0; /* XXX */
-
- /* 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;
-{
- 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() */
- CHECK_TERMSIG;
- 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 (file_isdir (command))
-#if defined (EISDIR)
- internal_error (_("%s: %s"), command, strerror (EISDIR));
-#else
- internal_error (_("%s: is a directory"), command);
-#endif
- 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);
- sample[sample_len - 1] = '\0';
- 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: %s"), command, strerror (i));
- 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, funcdef)
- WORD_DESC *name;
- FUNCTION_DEF *funcdef;
-{
- SHELL_VAR *var;
-
- if (check_identifier (name, posixly_correct) == 0)
- {
- if (posixly_correct && interactive_shell == 0)
- {
- last_command_exit_value = EX_BADUSAGE;
- jump_to_top_level (ERREXIT);
- }
- return (EXECUTION_FAILURE);
- }
-
- /* Posix interpretation 383 */
- if (posixly_correct && find_special_builtin (name->word))
- {
- internal_error (_("`%s': is a special builtin"), name->word);
- last_command_exit_value = EX_BADUSAGE;
- jump_to_top_level (ERREXIT);
- }
-
- 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);
- }
-
-#if defined (DEBUGGER)
- bind_function_def (name->word, funcdef);
-#endif
-
- bind_function (name->word, funcdef->command);
- 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);
-#ifdef __CYGWIN__
- /* Let stdio know the fd may have changed from text to binary mode. */
- freopen (NULL, "r", stdin);
-#endif /* __CYGWIN__ */
- }
- 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);
- }
-#ifdef __CYGWIN__
- /* Let stdio know the fd may have changed from text to binary mode, and
- make sure to preserve stdout line buffering. */
- freopen (NULL, "w", stdout);
- sh_setlinebuf (stdout);
-#endif /* __CYGWIN__ */
- }
-}
+++ /dev/null
-/* externs.h -- extern function declarations which do not appear in their
- own header file. */
-
-/* Copyright (C) 1993-2010 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/* 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. */
-#define FUNC_MULTILINE 0x01
-#define FUNC_EXTERNAL 0x02
-
-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 void xtrace_init __P((void));
-#ifdef NEED_XTRACE_SET_DECL
-extern void xtrace_set __P((int, FILE *));
-#endif
-extern void xtrace_fdchk __P((int));
-extern void xtrace_reset __P((void));
-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 char *xparse_dolparen __P((char *, char *, int *, int));
-extern void reset_parser __P((void));
-extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
-
-extern int parser_in_command_position __P((void));
-
-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((const char *));
-#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((const 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/casemod.c */
-extern char *sh_modcase __P((const char *, char *, int));
-
-/* Defines for flags argument to sh_modcase. These need to agree with what's
- in lib/sh/casemode.c */
-#define CASE_LOWER 0x0001
-#define CASE_UPPER 0x0002
-#define CASE_CAPITALIZE 0x0004
-#define CASE_UNCAP 0x0008
-#define CASE_TOGGLE 0x0010
-#define CASE_TOGGLEALL 0x0020
-#define CASE_UPFIRST 0x0040
-#define CASE_LOWFIRST 0x0080
-
-#define CASE_USEWORDS 0x1000
-
-/* 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/dprintf.c */
-#if !defined (HAVE_DPRINTF)
-extern void dprintf __P((int, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
-#endif
-
-/* 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/fnxform.c */
-extern char *fnx_fromfs __P((char *, size_t));
-extern char *fnx_tofs __P((char *, size_t));
-
-/* Declarations for functions defined in lib/sh/fpurge.c */
-
-#if defined NEED_FPURGE_DECL
-#if !HAVE_DECL_FPURGE
-
-#if HAVE_FPURGE
-# define fpurge _bash_fpurge
-#endif
-extern int fpurge __P((FILE *stream));
-
-#endif /* HAVE_DECL_FPURGE */
-#endif /* NEED_FPURGE_DECL */
-
-/* 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/input_avail.c */
-extern int input_avail __P((int));
-
-/* 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
-#define MP_IGNDOT 0x08
-
-extern char *sh_makepath __P((const char *, const char *, int));
-
-/* declarations for functions defined in lib/sh/mbscasecmp.c */
-#if !defined (HAVE_MBSCASECMP)
-extern char *mbscasecmp __P((const char *, const char *));
-#endif
-
-/* declarations for functions defined in lib/sh/mbschr.c */
-#if !defined (HAVE_MBSCHR)
-extern char *mbschr __P((const char *, int));
-#endif
-
-/* declarations for functions defined in lib/sh/mbscmp.c */
-#if !defined (HAVE_MBSCMP)
-extern char *mbscmp __P((const char *, const char *));
-#endif
-
-/* 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/shmbchar.c */
-extern size_t mbstrlen __P((const char *));
-extern char *mbsmbchar __P((const char *));
-
-/* declarations for functions defined in lib/sh/shquote.c */
-extern char *sh_single_quote __P((const char *));
-extern char *sh_double_quote __P((const 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 *, const 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 *));
-extern char *dirspell __P((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/strcasestr.c */
-#if ! HAVE_STRCASESTR
-extern char *strcasestr __P((const char *, const char *));
-#endif
-
-/* declarations for functions defined in lib/sh/strchrnul.c */
-#if ! HAVE_STRCHRNUL
-extern char *strchrnul __P((const char *, int));
-#endif
-
-/* declarations for functions defined in lib/sh/strerror.c */
-#if !defined (HAVE_STRERROR) && !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 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/uconvert.c */
-extern int uconvert __P((char *, long *, long *));
-
-/* declarations for functions defined in lib/sh/ufuncs.c */
-extern unsigned int falarm __P((unsigned int, unsigned int));
-extern unsigned int fsleep __P((unsigned int, unsigned int));
-
-/* declarations for functions defined in lib/sh/unicode.c */
-extern int u32cconv __P((unsigned long, 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/zcatfd.c */
-extern int zcatfd __P((int, int, char *));
-
-/* declarations for functions defined in lib/sh/zgetline.c */
-extern ssize_t zgetline __P((int, char **, size_t *, int));
-
-/* declarations for functions defined in lib/sh/zmapfd.c */
-extern int zmapfd __P((int, char **, char *));
-
-/* declarations for functions defined in lib/sh/zread.c */
-extern ssize_t zread __P((int, char *, size_t));
-extern ssize_t zreadretry __P((int, char *, size_t));
-extern ssize_t zreadintr __P((int, char *, size_t));
-extern ssize_t zreadc __P((int, char *));
-extern ssize_t zreadcintr __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));
-
-/* declarations for functions defined in lib/glob/gmisc.c */
-extern int match_pattern_char __P((char *, char *));
-extern int umatchlen __P((char *, size_t));
-
-#if defined (HANDLE_MULTIBYTE)
-extern int match_pattern_wchar __P((wchar_t *, wchar_t *));
-extern int wmatchlen __P((wchar_t *, size_t));
-#endif
-
-#endif /* _EXTERNS_H_ */
+++ /dev/null
-/* bind.c -- key binding and startup file support for the readline library. */
-
-/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library (Readline), a library
- for reading lines of text with interactive input and history editing.
-
- Readline is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Readline is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define READLINE_LIBRARY
-
-#if defined (__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 int _rl_skip_to_delim PARAMS((char *, int, int));
-
-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 int find_string_var PARAMS((const char *));
-
-static char *_rl_get_string_variable_value PARAMS((const char *));
-static int substring_member_of_array PARAMS((const char *, const char * const *));
-
-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, ¯o_keys_len))
- {
- xfree (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)
- xfree (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))
- {
- xfree (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)
- {
- xfree (keys);
- 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)
- xfree ((char *)map[ic].function);
- else if (map[ic].type == ISKMAP)
- {
- map = FUNCTION_TO_KEYMAP (map, ic);
- ic = ANYOTHERKEY;
- /* If we're trying to override a keymap with a null function
- (e.g., trying to unbind it), we can't use a null pointer
- here because that's indistinguishable from having not been
- overridden. We use a special bindable function that does
- nothing. */
- if (type == ISFUNC && data == 0)
- data = (char *)_rl_null_function;
- }
-
- map[ic].function = KEYMAP_TO_FUNCTION (data);
- map[ic].type = type;
- }
-
- rl_binding_keymap = map;
- }
- xfree (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);
-}
-
-static int
-_rl_isescape (c)
- int c;
-{
- switch (c)
- {
- case '\007':
- case '\b':
- case '\f':
- case '\n':
- case '\r':
- case TAB:
- case 0x0b: return (1);
- default: return (0);
- }
-}
-
-static int
-_rl_escchar (c)
- int c;
-{
- switch (c)
- {
- case '\007': return ('a');
- case '\b': return ('b');
- case '\f': return ('f');
- case '\n': return ('n');
- case '\r': return ('r');
- case TAB: return ('t');
- case 0x0b: return ('v');
- default: return (c);
- }
-}
-
-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;
-}
-
-char *
-_rl_untranslate_macro_value (seq, use_escapes)
- char *seq;
- int use_escapes;
-{
- 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++ = '\\';
- if (use_escapes && _rl_isescape (c))
- c = _rl_escchar (c);
- else
- {
- *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)
- {
- xfree (buffer);
- return ((char *)NULL);
- }
-
- RL_CHECK_SIGNALS ();
-
- 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);
- xfree (openname);
-
- RL_CHECK_SIGNALS ();
- 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++;
- }
-
- xfree (buffer);
- currently_reading_init_file = 0;
- return (0);
-}
-
-static void
-_rl_init_file_error (msg)
- const char *msg;
-{
- if (currently_reading_init_file)
- _rl_errmsg ("%s: line %d: %s\n", current_readline_init_file,
- current_readline_init_lineno, msg);
- else
- _rl_errmsg ("%s", msg);
-}
-
-/* **************************************************************** */
-/* */
-/* Parser Directives */
-/* */
-/* **************************************************************** */
-
-typedef int _rl_parser_func_t PARAMS((char *));
-
-/* Things that mean `Control'. */
-const char * const _rl_possible_control_prefixes[] = {
- "Control-", "C-", "CTRL-", (const char *)NULL
-};
-
-const char * const _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);
- xfree (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 const struct {
- const char * const 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);
-}
-
-/* Start at STRING[START] and look for DELIM. Return I where STRING[I] ==
- DELIM or STRING[I] == 0. DELIM is usually a double quote. */
-static int
-_rl_skip_to_delim (string, start, delim)
- char *string;
- int start, delim;
-{
- int i, c, passc;
-
- for (i = start,passc = 0; c = string[i]; i++)
- {
- if (passc)
- {
- passc = 0;
- if (c == 0)
- break;
- continue;
- }
-
- if (c == '\\')
- {
- passc = 1;
- continue;
- }
-
- if (c == delim)
- break;
- }
-
- return i;
-}
-
-/* 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 == 0 || *string == 0 || *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 == '"')
- {
- i = _rl_skip_to_delim (string, 1, '"');
-
- /* 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;
- }
- else
- i++; /* skip past closing double quote */
- }
-
- /* 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;
- int s;
-
- 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) == 0) value++;
- if (*value)
- *value++ = '\0';
- while (*value && whitespace (*value)) value++;
-
- /* Strip trailing whitespace from values of boolean variables. */
- if (find_boolean_var (var) >= 0)
- {
- /* remove trailing whitespace */
-remove_trailing:
- e = value + strlen (value) - 1;
- while (e >= value && whitespace (*e))
- e--;
- e++; /* skip back to whitespace or EOS */
-
- if (*e && e >= value)
- *e = '\0';
- }
- else if ((i = find_string_var (var)) >= 0)
- {
- /* Allow quoted strings in variable values */
- if (*value == '"')
- {
- i = _rl_skip_to_delim (value, 1, *value);
- value[i] = '\0';
- }
- else
- goto remove_trailing;
- }
-
- 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 == '"')
- {
- i = _rl_skip_to_delim (string, i+1, *funname);
- if (string[i])
- i++;
- }
-
- /* Advance to the end of the string. */
- for (; string[i] && whitespace (string[i]) == 0; 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));
-
- xfree (seq);
- return 0;
- }
-
- /* Get the actual character we want to deal with. */
- kname = strrchr (string, '-');
- if (kname == 0)
- 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 const struct {
- const char * const 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 },
-#if defined (COLOR_SUPPORT)
- { "colored-stats", &_rl_colored_stats, 0 },
-#endif
- { "completion-ignore-case", &_rl_completion_case_fold, 0 },
- { "completion-map-case", &_rl_completion_case_map, 0 },
- { "convert-meta", &_rl_convert_meta_chars_to_ascii, 0 },
- { "disable-completion", &rl_inhibit_completion, 0 },
- { "echo-control-characters", &_rl_echo_control_chars, 0 },
- { "enable-keypad", &_rl_enable_keypad, 0 },
- { "enable-meta-key", &_rl_enable_meta, 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 },
- { "menu-complete-display-prefix", &_rl_menu_complete_prefix_first, 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 },
- { "revert-all-at-newline", &_rl_revert_all_at_newline, 0 },
- { "show-all-if-ambiguous", &_rl_complete_show_all, 0 },
- { "show-all-if-unmodified", &_rl_complete_show_unmodified, 0 },
- { "skip-completed-text", &_rl_skip_completed_text, 0 },
-#if defined (VISIBLE_STATS)
- { "visible-stats", &rl_visible_stats, 0 },
-#endif /* VISIBLE_STATS */
- { (char *)NULL, (int *)NULL, 0 }
-};
-
-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_dispprefix PARAMS((const char *));
-static int sv_compquery PARAMS((const char *));
-static int sv_compwidth PARAMS((const char *));
-static int sv_editmode PARAMS((const char *));
-static int sv_histsize PARAMS((const char *));
-static int sv_isrchterm PARAMS((const char *));
-static int sv_keymap PARAMS((const char *));
-static int sv_seqtimeout PARAMS((const char *));
-
-static const struct {
- const char * const 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-display-width", V_INT, sv_compwidth },
- { "completion-prefix-display-length", V_INT, sv_dispprefix },
- { "completion-query-items", V_INT, sv_compquery },
- { "editing-mode", V_STRING, sv_editmode },
- { "history-size", V_INT, sv_histsize },
- { "isearch-terminators", V_STRING, sv_isrchterm },
- { "keymap", V_STRING, sv_keymap },
- { "keyseq-timeout", V_INT, sv_seqtimeout },
- { (char *)NULL, 0, (_rl_sv_func_t *)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;
-
- /* 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_dispprefix (value)
- const char *value;
-{
- int nval = 0;
-
- if (value && *value)
- {
- nval = atoi (value);
- if (nval < 0)
- nval = 0;
- }
- _rl_completion_prefix_display_length = nval;
- return 0;
-}
-
-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_compwidth (value)
- const char *value;
-{
- int nval = -1;
-
- if (value && *value)
- nval = atoi (value);
-
- _rl_completion_columns = nval;
- return 0;
-}
-
-static int
-sv_histsize (value)
- const char *value;
-{
- int nval;
-
- nval = 500;
- if (value && *value)
- {
- nval = atoi (value);
- if (nval < 0)
- return 1;
- }
- stifle_history (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_seqtimeout (value)
- const char *value;
-{
- int nval;
-
- nval = 0;
- if (value && *value)
- {
- nval = atoi (value);
- if (nval < 0)
- nval = 0;
- }
- _rl_keyseq_timeout = nval;
- return 0;
-}
-
-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';
-
- xfree (v);
- return 0;
-}
-
-/* Return the character which matches NAME.
- For example, `Space' returns ' '. */
-
-typedef struct {
- const char * const name;
- int value;
-} assoc_list;
-
-static const 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 const struct {
- const char * const 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]);
-
- xfree (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]);
- xfree (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;
- }
-
- xfree (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);
- xfree (invokers[j]);
- }
-
- xfree (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++)
- xfree (invokers[j]);
-
- xfree (invokers);
- }
- }
- }
-
- xfree (names);
-}
-
-/* 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, 0);
-
- 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 : "");
- xfree (keyname);
- xfree (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);
- xfree (keyname);
- keyname = out;
- }
- }
-
- _rl_macro_dumper_internal (print_readably, FUNCTION_TO_KEYMAP (map, key), keyname);
- xfree (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-display-width") == 0)
- {
- sprintf (numbuf, "%d", _rl_completion_columns);
- return (numbuf);
- }
- else if (_rl_stricmp (name, "completion-prefix-display-length") == 0)
- {
- sprintf (numbuf, "%d", _rl_completion_prefix_display_length);
- return (numbuf);
- }
- 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, "history-size") == 0)
- {
- sprintf (numbuf, "%d", history_is_stifled() ? history_max_entries : 0);
- return (numbuf);
- }
- else if (_rl_stricmp (name, "isearch-terminators") == 0)
- {
- if (_rl_isearch_terminators == 0)
- return 0;
- ret = _rl_untranslate_macro_value (_rl_isearch_terminators, 0);
- if (ret)
- {
- strncpy (numbuf, ret, sizeof (numbuf) - 1);
- xfree (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)
- const char *string;
- const char * const *array;
-{
- while (*array)
- {
- if (_rl_strindex (string, *array))
- return (1);
- array++;
- }
- return (0);
-}
+++ /dev/null
-/* complete.c -- filename completion for readline. */
-
-/* Copyright (C) 1987-2011 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library (Readline), a library
- for reading lines of text with interactive input and history editing.
-
- Readline is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Readline is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <fcntl.h>
-#if defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-
-#include <signal.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 <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 _rl_complete_sigcleanup PARAMS((int, void *));
-
-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 *, int));
-static int print_filename PARAMS((char *, char *, int));
-
-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 int complete_fncmp PARAMS((const char *, int, const char *, int));
-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 int complete_get_screenwidth PARAMS((void));
-
-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 = 0;
-#endif
-
-/* Non-zero means that `-' and `_' are equivalent when comparing filenames
- for completion. */
-int _rl_completion_case_map = 0;
-
-/* If zero, don't match hidden files (filenames beginning with a `.' on
- Unix) when doing filename completion. */
-int _rl_match_hidden_files = 1;
-
-/* Length in characters of a common prefix replaced with an ellipsis (`...')
- when displaying completion matches. Matches whose printable portion has
- more than this number of displaying characters in common will have the common
- display prefix replaced with an ellipsis. */
-int _rl_completion_prefix_display_length = 0;
-
-/* The readline-private number of screen columns to use when displaying
- matches. If < 0 or > _rl_screenwidth, it is ignored. */
-int _rl_completion_columns = -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, when completing in the middle of a word, don't insert
- characters from the match that match characters following point in
- the word. This means, for instance, completing when the cursor is
- after the `e' in `Makefile' won't result in `Makefilefile'. */
-int _rl_skip_completed_text = 0;
-
-/* If non-zero, menu completion displays the common prefix first in the
- cycle of possible completions instead of the last. */
-int _rl_menu_complete_prefix_first = 0;
-
-/* 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;
-
-rl_icppfunc_t *rl_filename_stat_hook = (rl_icppfunc_t *)NULL;
-
-/* If non-zero, this is the address of a function to call when reading
- directory entries from the filesystem for completion and comparing
- them to the partial word to be completed. The function should
- either return its first argument (if no conversion takes place) or
- newly-allocated memory. This can, for instance, convert filenames
- between character sets for comparison against what's typed at the
- keyboard. The returned value is what is added to the list of
- matches. The second argument is the length of the filename to be
- converted. */
-rl_dequote_func_t *rl_filename_rewrite_hook = (rl_dequote_func_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 generator function for rl_menu_complete (). NULL means to use
- *rl_completion_entry_function (see above). */
-rl_compentry_func_t *rl_menu_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;
-
-/* Set to the last key used to invoke one of the completion functions */
-int rl_completion_invoking_key;
-
-/* If non-zero, sort the completion matches. On by default. */
-int rl_sort_completion_matches = 1;
-
-/* Variables local to this file. */
-
-/* Local variable states what happened during the last completion attempt. */
-static int completion_changed_buffer;
-
-/* The result of the query to the user about displaying completion matches */
-static int completion_y_or_n;
-
-/*************************************/
-/* */
-/* 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;
-{
- rl_completion_invoking_key = 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;
-{
- rl_completion_invoking_key = invoking_key;
- return (rl_complete_internal ('?'));
-}
-
-int
-rl_insert_completions (ignore, invoking_key)
- int ignore, invoking_key;
-{
- rl_completion_invoking_key = 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 */
-/* */
-/************************************/
-
-/* Reset readline state on a signal or other event. */
-void
-_rl_reset_completion_state ()
-{
- rl_completion_found_quote = 0;
- rl_completion_quote_character = 0;
-}
-
-static void
-_rl_complete_sigcleanup (sig, ptr)
- int sig;
- void *ptr;
-{
- if (sig == SIGINT) /* XXX - for now */
- _rl_free_match_list ((char **)ptr);
-}
-
-/* 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;
- rl_completion_append_character = ' ';
-
- /* 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 now, disable pager in callback mode, until we later convert to state
- driven functions. Have to wait until next major version to add new
- state definition, since it will change value of RL_STATE_DONE. */
-#if defined (READLINE_CALLBACKS)
- if (RL_ISSTATE (RL_STATE_CALLBACK))
- return 1;
-#endif
-
- 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 || c < 0)
- _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;
-
- /* Short-circuit a //server on cygwin, since that will always behave as
- a directory. */
-#if __CYGWIN__
- if (filename[0] == '/' && filename[1] == '/' && strchr (filename+2, '/') == 0)
- return '/';
-#endif
-
-#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[pos]) || string[pos] == 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;
-}
-
-#define ELLIPSIS_LEN 3
-
-static int
-fnprint (to_print, prefix_bytes)
- const char *to_print;
- int prefix_bytes;
-{
- int printed_len, w;
- const char *s;
-#if defined (HANDLE_MULTIBYTE)
- mbstate_t ps;
- const char *end;
- size_t tlen;
- int width;
- wchar_t wc;
-
- end = to_print + strlen (to_print) + 1;
- memset (&ps, 0, sizeof (mbstate_t));
-#endif
-
- printed_len = 0;
-
- /* Don't print only the ellipsis if the common prefix is one of the
- possible completions */
- if (to_print[prefix_bytes] == '\0')
- prefix_bytes = 0;
-
- if (prefix_bytes)
- {
- char ellipsis;
-
- ellipsis = (to_print[prefix_bytes] == '.') ? '_' : '.';
- for (w = 0; w < ELLIPSIS_LEN; w++)
- putc (ellipsis, rl_outstream);
- printed_len = ELLIPSIS_LEN;
- }
-
- s = to_print + prefix_bytes;
- 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, prefix_bytes)
- char *to_print, *full_pathname;
- int prefix_bytes;
-{
- int printed_len, extension_char, slen, tlen;
- char *s, c, *new_full_pathname, *dn;
-
- extension_char = 0;
- printed_len = fnprint (to_print, prefix_bytes);
-
-#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 = '/';
-
- xfree (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 = '/';
- }
-
- xfree (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 (RL_SIG_RECEIVED())
- {
- _rl_free_match_list (matches);
- matches = 0;
- RL_CHECK_SIGNALS ();
- }
-
- if (matches || rl_attempted_completion_over)
- {
- rl_attempted_completion_over = 0;
- return (matches);
- }
- }
-
- /* XXX -- filename dequoting moved into rl_filename_completion_function */
-
- /* rl_completion_matches will check for signals as well to avoid a long
- delay while reading a directory. */
- matches = rl_completion_matches (text, our_func);
- if (RL_SIG_RECEIVED())
- {
- _rl_free_match_list (matches);
- matches = 0;
- RL_CHECK_SIGNALS ();
- }
- 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 && rl_sort_completion_matches)
- 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)
- {
- xfree (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)
- xfree (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)
- {
- xfree (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;
- 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);
- xfree (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);
-}
-
-static int
-complete_get_screenwidth ()
-{
- int cols;
- char *envcols;
-
- cols = _rl_completion_columns;
- if (cols >= 0 && cols <= _rl_screenwidth)
- return cols;
- envcols = getenv ("COLUMNS");
- if (envcols && *envcols)
- cols = atoi (envcols);
- if (cols >= 0 && cols <= _rl_screenwidth)
- return cols;
- return _rl_screenwidth;
-}
-
-/* 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, cols;
- int i, j, k, l, common_length, sind;
- char *temp, *t;
-
- /* Find the length of the prefix common to all items: length as displayed
- characters (common_length) and as a byte index into the matches (sind) */
- common_length = sind = 0;
- if (_rl_completion_prefix_display_length > 0)
- {
- t = printable_part (matches[0]);
- temp = strrchr (t, '/');
- common_length = temp ? fnwidth (temp) : fnwidth (t);
- sind = temp ? strlen (temp) : strlen (t);
-
- if (common_length > _rl_completion_prefix_display_length && common_length > ELLIPSIS_LEN)
- max -= common_length - ELLIPSIS_LEN;
- else
- common_length = sind = 0;
- }
-
- /* How many items of MAX length can we fit in the screen window? */
- cols = complete_get_screenwidth ();
- max += 2;
- limit = cols / max;
- if (limit != 1 && (limit * max == cols))
- limit--;
-
- /* If cols == 0, limit will end up -1 */
- if (cols < _rl_screenwidth && limit < 0)
- limit = 1;
-
- /* Avoid a possible floating exception. If max > cols,
- 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 && rl_sort_completion_matches)
- 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], sind);
-
- 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], sind);
- /* 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], 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 ((completion_y_or_n = 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, *r;
- char oqc;
- int end, rlen;
-
- oqc = qc ? *qc : '\0';
- replacement = make_quoted_replacement (match, mtype, qc);
-
- /* Now insert the match. */
- if (replacement)
- {
- rlen = strlen (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--;
- end = rl_point - 1;
- /* Don't double a closing quote character */
- if (qc && *qc && end && rl_line_buffer[rl_point] == *qc && replacement[rlen - 1] == *qc)
- end++;
- if (_rl_skip_completed_text)
- {
- r = replacement;
- while (start < rl_end && *r && rl_line_buffer[start] == *r)
- {
- start++;
- r++;
- }
- if (start <= end || *r)
- _rl_replace_text (r, start, end);
- rl_point = start + strlen (r);
- }
- else
- _rl_replace_text (replacement, start, end);
- if (replacement != match)
- xfree (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);
- if (rl_filename_stat_hook)
- (*rl_filename_stat_hook) (&filename);
- 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) && path_isdir (filename))
- ;
-#endif
- else
- {
- if (rl_point == rl_end && temp_string_index)
- rl_insert_text (temp_string);
- }
- xfree (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])
- xfree (rp);
- }
- }
- else
- {
- rp = make_quoted_replacement (matches[0], SINGLE_MATCH, qc);
- rl_insert_text (rp);
- rl_insert_text (" ");
- if (rp != matches[0])
- xfree (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++)
- xfree (matches[i]);
- xfree (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;
-#if 1
- int tlen, mlen;
-#endif
-
- 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;
- if (what_to_do == '!' || what_to_do == '@')
- tlen = strlen (text);
- xfree (text);
-
- if (matches == 0)
- {
- rl_ding ();
- FREE (saved_line_buffer);
- completion_changed_buffer = 0;
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- _rl_reset_completion_state ();
- 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);
- _rl_reset_completion_state ();
- return (0);
- }
-
- switch (what_to_do)
- {
- case TAB:
- case '!':
- case '@':
- /* Insert the first match with proper quoting. */
- if (what_to_do == TAB)
- {
- if (*matches[0])
- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
- }
- else if (*matches[0] && matches[1] == 0)
- /* should we perform the check only if there are multiple matches? */
- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
- else if (*matches[0]) /* what_to_do != TAB && multiple matches */
- {
- mlen = *matches[0] ? strlen (matches[0]) : 0;
- if (mlen >= tlen)
- insert_match (matches[0], start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_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, "e_char);
- break;
-
- case '?':
- if (rl_completion_display_matches_hook == 0)
- {
- _rl_sigcleanup = _rl_complete_sigcleanup;
- _rl_sigcleanarg = matches;
- }
- display_matches (matches);
- _rl_sigcleanup = 0;
- _rl_sigcleanarg = 0;
- break;
-
- default:
- _rl_ttymsg ("bad value %d for what_to_do in rl_complete", what_to_do);
- rl_ding ();
- FREE (saved_line_buffer);
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- _rl_free_match_list (matches);
- _rl_reset_completion_state ();
- 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;
- xfree (saved_line_buffer);
- }
-
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- _rl_reset_completion_state ();
- 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;
-{
- register int i;
-
- /* 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 (RL_SIG_RECEIVED ())
- {
- /* Start at 1 because we don't set matches[0] in this function.
- Only free the list members if we're building match list from
- rl_filename_completion_function, since we know that doesn't
- free the strings it returns. */
- if (entry_function == rl_filename_completion_function)
- {
- for (i = 1; match_list[i]; i++)
- xfree (match_list[i]);
- }
- xfree (match_list);
- match_list = 0;
- match_list_size = 0;
- RL_CHECK_SIGNALS ();
- }
-
- 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. */
- {
- xfree (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 */
-}
-
-/* Return non-zero if CONVFN matches FILENAME up to the length of FILENAME
- (FILENAME_LEN). If _rl_completion_case_fold is set, compare without
- regard to the alphabetic case of characters. CONVFN is the possibly-
- converted directory entry; FILENAME is what the user typed. */
-static int
-complete_fncmp (convfn, convlen, filename, filename_len)
- const char *convfn;
- int convlen;
- const char *filename;
- int filename_len;
-{
- register char *s1, *s2;
- int d, len;
-
- /* Otherwise, if these match up to the length of filename, then
- it is a match. */
- if (_rl_completion_case_fold && _rl_completion_case_map)
- {
- /* Case-insensitive comparison treating _ and - as equivalent */
- if (filename_len == 0)
- return 1;
- if (convlen < filename_len)
- return 0;
- s1 = (char *)convfn;
- s2 = (char *)filename;
- len = filename_len;
- do
- {
- d = _rl_to_lower (*s1) - _rl_to_lower (*s2);
- /* *s1 == [-_] && *s2 == [-_] */
- if ((*s1 == '-' || *s1 == '_') && (*s2 == '-' || *s2 == '_'))
- d = 0;
- if (d != 0)
- return 0;
- s1++; s2++; /* already checked convlen >= filename_len */
- }
- while (--len != 0);
- return 1;
- }
- else if (_rl_completion_case_fold)
- {
- if ((_rl_to_lower (convfn[0]) == _rl_to_lower (filename[0])) &&
- (convlen >= filename_len) &&
- (_rl_strnicmp (filename, convfn, filename_len) == 0))
- return 1;
- }
- else
- {
- if ((convfn[0] == filename[0]) &&
- (convlen >= filename_len) &&
- (strncmp (filename, convfn, filename_len) == 0))
- return 1;
- }
- return 0;
-}
-
-/* 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, *dentry, *convfn;
- int dirlen, dentlen, convlen;
- 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, dequoting
- it if necessary. */
- if (rl_completion_found_quote && rl_filename_dequoting_function)
- users_dirname = (*rl_filename_dequoting_function) (dirname, rl_completion_quote_character);
- else
- users_dirname = savestring (dirname);
-
- if (*dirname == '~')
- {
- temp = tilde_expand (dirname);
- xfree (dirname);
- dirname = temp;
- }
-
- /* We have saved the possibly-dequoted version of the directory name
- the user typed. Now transform the directory name we're going to
- pass to opendir(2). The directory rewrite hook modifies only the
- directory name; the directory completion hook modifies both the
- directory name passed to opendir(2) and the version the user
- typed. Both the directory completion and rewrite hooks should perform
- any necessary dequoting. The hook functions return 1 if they modify
- the directory name argument. If either hook returns 0, it should
- not modify the directory name pointer passed as an argument. */
- if (rl_directory_rewrite_hook)
- (*rl_directory_rewrite_hook) (&dirname);
- else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&dirname))
- {
- xfree (users_dirname);
- users_dirname = savestring (dirname);
- }
- else if (rl_completion_found_quote && rl_filename_dequoting_function)
- {
- /* delete single and double quotes */
- xfree (dirname);
- dirname = savestring (users_dirname);
- }
- directory = opendir (dirname);
-
- /* Now dequote a non-null filename. FILENAME will not be NULL, but may
- be empty. */
- if (*filename && rl_completion_found_quote && rl_filename_dequoting_function)
- {
- /* delete single and double quotes */
- temp = (*rl_filename_dequoting_function) (filename, rl_completion_quote_character);
- xfree (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)))
- {
- convfn = dentry = entry->d_name;
- convlen = dentlen = D_NAMLEN (entry);
-
- if (rl_filename_rewrite_hook)
- {
- convfn = (*rl_filename_rewrite_hook) (dentry, dentlen);
- convlen = (convfn == dentry) ? dentlen : strlen (convfn);
- }
-
- /* 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 (convfn))
- continue;
-
- if (convfn[0] != '.' ||
- (convfn[1] && (convfn[1] != '.' || convfn[2])))
- break;
- }
- else
- {
- if (complete_fncmp (convfn, convlen, filename, filename_len))
- break;
- }
- }
-
- if (entry == 0)
- {
- if (directory)
- {
- closedir (directory);
- directory = (DIR *)NULL;
- }
- if (dirname)
- {
- xfree (dirname);
- dirname = (char *)NULL;
- }
- if (filename)
- {
- xfree (filename);
- filename = (char *)NULL;
- }
- if (users_dirname)
- {
- xfree (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, convfn);
- }
- else
- temp = savestring (convfn);
-
- if (convfn != dentry)
- xfree (convfn);
-
- return (temp);
- }
-}
-
-/* An initial implementation of a menu completion function a la tcsh. The
- first time (if the last readline command was not rl_old_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_old_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_old_menu_complete (count, invoking_key)
- int count, invoking_key;
-{
- 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_old_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;
-
- rl_completion_invoking_key = invoking_key;
-
- RL_SETSTATE(RL_STATE_COMPLETING);
-
- /* Only the completion entry function can change these. */
- set_completion_defaults ('%');
-
- our_func = rl_menu_completion_entry_function;
- if (our_func == 0)
- 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;
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return (0);
- }
-
- RL_UNSETSTATE(RL_STATE_COMPLETING);
-
- 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. */
-
- if (match_list_size > 1 && _rl_complete_show_all)
- display_matches (matches);
- }
-
- /* 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)
- {
- while (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, "e_char);
- }
- else
- {
- insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char);
- append_to_match (matches[match_list_index], delimiter, quote_char,
- strcmp (orig_text, matches[match_list_index]));
- }
-
- completion_changed_buffer = 1;
- return (0);
-}
-
-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 nontrivial_lcd = 0;
- static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */
- static int orig_start, orig_end;
- static char quote_char;
- static int delimiter, cstate;
-
- /* The first time through, we generate the list of matches and set things
- up to insert them. */
- if ((rl_last_func != rl_menu_complete && rl_last_func != rl_backward_menu_complete) || full_completion)
- {
- /* 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;
-
- full_completion = 0;
-
- RL_SETSTATE(RL_STATE_COMPLETING);
-
- /* Only the completion entry function can change these. */
- set_completion_defaults ('%');
-
- our_func = rl_menu_completion_entry_function;
- if (our_func == 0)
- 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);
-
- nontrivial_lcd = matches && strcmp (orig_text, matches[0]) != 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. */
- 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;
- RL_UNSETSTATE(RL_STATE_COMPLETING);
- return (0);
- }
-
- RL_UNSETSTATE(RL_STATE_COMPLETING);
-
- for (match_list_size = 0; matches[match_list_size]; match_list_size++)
- ;
-
- if (match_list_size == 0)
- {
- rl_ding ();
- FREE (matches);
- matches = (char **)0;
- match_list_index = 0;
- completion_changed_buffer = 0;
- return (0);
- }
-
- /* matches[0] is lcd if match_list_size > 1, but the circular buffer
- code below should take care of it. */
- if (*matches[0])
- {
- insert_match (matches[0], orig_start, matches[1] ? MULT_MATCH : SINGLE_MATCH, "e_char);
- orig_end = orig_start + strlen (matches[0]);
- completion_changed_buffer = STREQ (orig_text, matches[0]) == 0;
- }
-
- if (match_list_size > 1 && _rl_complete_show_all)
- {
- display_matches (matches);
- /* If there are so many matches that the user has to be asked
- whether or not he wants to see the matches, menu completion
- is unwieldy. */
- if (rl_completion_query_items > 0 && match_list_size >= rl_completion_query_items)
- {
- rl_ding ();
- FREE (matches);
- matches = (char **)0;
- full_completion = 1;
- return (0);
- }
- }
- else if (match_list_size <= 1)
- {
- append_to_match (matches[0], delimiter, quote_char, nontrivial_lcd);
- full_completion = 1;
- return (0);
- }
- else if (_rl_menu_complete_prefix_first && match_list_size > 1)
- {
- rl_ding ();
- return (0);
- }
- }
-
- /* 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)
- {
- while (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 (matches[0], orig_start, MULT_MATCH, "e_char);
- }
- else
- {
- insert_match (matches[match_list_index], orig_start, SINGLE_MATCH, "e_char);
- append_to_match (matches[match_list_index], delimiter, quote_char,
- strcmp (orig_text, matches[match_list_index]));
- }
-
- completion_changed_buffer = 1;
- return (0);
-}
-
-int
-rl_backward_menu_complete (count, key)
- int count, key;
-{
- /* Positive arguments to backward-menu-complete translate into negative
- arguments for menu-complete, and vice versa. */
- return (rl_menu_complete (-count, key));
-}
+++ /dev/null
-# 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
+++ /dev/null
-.\"
-.\" MAN PAGE COMMENTS to
-.\"
-.\" Chet Ramey
-.\" Information Network Services
-.\" Case Western Reserve University
-.\" chet@ins.CWRU.Edu
-.\"
-.\" Last Change: Sat Aug 28 18:56:32 EDT 2010
-.\"
-.TH READLINE 3 "2010 August 28" "GNU Readline 6.2"
-.\"
-.\" 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
-readline \- get a line from a user with editing
-.SH SYNOPSIS
-.LP
-.nf
-.ft B
-#include <stdio.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-.ft
-.fi
-.LP
-.nf
-\fIchar *\fP
-.br
-\fBreadline\fP (\fIconst char *prompt\fP);
-.fi
-.SH COPYRIGHT
-.if n Readline is Copyright (C) 1989\-2011 Free Software Foundation, Inc.
-.if t Readline is Copyright \(co 1989\-2011 Free Software Foundation, Inc.
-.SH DESCRIPTION
-.LP
-.B readline
-will read a line from the terminal
-and return it, using
-.B prompt
-as a prompt. If
-.B prompt
-is \fBNULL\fP or the empty string, no prompt is issued.
-The line returned is allocated with
-.IR malloc (3);
-the caller must free it when finished. The line returned
-has the final newline removed, so only the text of the line
-remains.
-.LP
-.B readline
-offers editing capabilities while the user is entering the
-line.
-By default, the line editing commands
-are similar to those of emacs.
-A vi\-style line editing interface is also available.
-.LP
-This manual page describes only the most basic use of \fBreadline\fP.
-Much more functionality is available; see
-\fIThe GNU Readline Library\fP and \fIThe GNU History Library\fP
-for additional information.
-.SH RETURN VALUE
-.LP
-.B readline
-returns the text of the line read. A blank line
-returns the empty string. If
-.B EOF
-is encountered while reading a line, and the line is empty,
-.B NULL
-is returned. If an
-.B EOF
-is read with a non\-empty line, it is
-treated as a newline.
-.SH NOTATION
-.LP
-An 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.
-.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.
-.SH INITIALIZATION FILE
-.LP
-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
-.B INPUTRC
-environment variable. If that variable is unset, the default is
-.IR ~/.inputrc .
-If that file does not exist or cannot be read, the ultimate default is
-.IR /etc/inputrc .
-When a program which uses the readline library starts up, the
-init file is read, and the key bindings and variables are set.
-There are only a few basic constructs allowed in the
-readline init 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.
-Each program using this library may add its own commands
-and bindings.
-.PP
-For example, placing
-.RS
-.PP
-M\-Control\-u: universal\-argument
-.RE
-or
-.RS
-C\-Meta\-u: universal\-argument
-.RE
-.sp
-into the
-.I inputrc
-would make M\-C\-u execute the readline command
-.IR universal\-argument .
-.PP
-The following symbolic character names are recognized while
-processing key bindings:
-.IR DEL ,
-.IR ESC ,
-.IR ESCAPE ,
-.IR LFD ,
-.IR NEWLINE ,
-.IR RET ,
-.IR RETURN ,
-.IR RUBOUT ,
-.IR SPACE ,
-.IR SPC ,
-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).
-.PP
-.SS 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.
-The name and key sequence are separated by a colon. There can be no
-whitespace between the name and the colon.
-.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 available when specifying
-key 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 ", a double quote
-.TP
-.B \e'
-literal ', a single quote
-.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 should
-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. Other programs using this library provide
-similar mechanisms. The
-.I inputrc
-file may be edited and re-read if a program does not provide
-any other means to incorporate new bindings.
-.SS 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 colored\-stats (Off)
-If set to \fBOn\fP, readline displays possible completions using different
-colors to indicate their file type.
-The color definitions are taken from the value of the \fBLS_COLORS\fP
-environment variable.
-.TP
-.B comment\-begin (``#'')
-The string that is inserted in \fBvi\fP mode when the
-.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\-display\-width (-1)
-The number of screen columns used to display possible matches
-when performing completion.
-The value is ignored if it is less than 0 or greater than the terminal
-screen width.
-A value of 0 will cause matches to be displayed one per line.
-The default value is -1.
-.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\-map\-case (Off)
-If set to \fBOn\fP, and \fBcompletion\-ignore\-case\fP is enabled, readline
-treats hyphens (\fI\-\fP) and underscores (\fI_\fP) as equivalent when
-performing case\-insensitive filename matching and completion.
-.TP
-.B completion\-prefix\-display\-length (0)
-The length in characters of the common prefix of a list of possible
-completions that is displayed without modification. When set to a
-value greater than zero, common prefixes longer than this value are
-replaced with an ellipsis when displaying possible completions.
-.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. A negative value causes readline to never ask.
-.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 it with 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 echo\-control\-characters (On)
-When set to \fBOn\fP, on operating systems that indicate they support it,
-readline echoes a character corresponding to a signal generated from the
-keyboard.
-.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 enable\-meta\-key (On)
-When set to \fBOn\fP, readline will try to enable any meta modifier
-key the terminal claims to support when it is called. On many terminals,
-the meta key is used to send eight-bit characters.
-.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 history\-size (0)
-Set the maximum number of history entries saved in the history list. If
-set to zero, the number of entries in the history list is not limited.
-.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 clear the eighth bit in 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 legal keymap names is
-\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. 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.
-If set to \fBOff\fP, the leading `.' must be
-supplied by the user in the filename to be completed.
-.TP
-.B menu\-complete\-display\-prefix (Off)
-If set to \fBOn\fP, menu completion displays the common prefix of the
-list of possible completions (which may be empty) before cycling through
-the list.
-.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 revert\-all\-at\-newline (Off)
-If set to \fBOn\fP, readline will undo all changes to history lines
-before returning when \fBaccept\-line\fP is executed. By default,
-history lines may be modified and retain individual undo lists across
-calls to \fBreadline\fP.
-.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 skip\-completed\-text (Off)
-If set to \fBOn\fP, this alters the default completion behavior when
-inserting a single match into the line. It's only active when
-performing completion in the middle of a word. If enabled, readline
-does not insert characters from the completion that match characters
-after point in the word being completed, so portions of the word
-following the cursor are not duplicated.
-.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 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 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 \fBbash\fP:
-.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
-.SH SEARCHING
-.PP
-Readline provides commands for searching through the command history
-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.
-To search backward in the history for a particular string, type
-\fBC\-r\fP. Typing \fBC\-s\fP searches forward through the history.
-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 \fIEscape\fP and
-\fBC\-J\fP characters will terminate an incremental search.
-\fBC\-G\fP 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 \fBC\-s\fP or
-\fBC\-r\fP as appropriate.
-This will search backward or forward in the history for the next
-line 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 newline will terminate the search and accept
-the line, thereby executing the command from the history list.
-A movement command will terminate the search, make the last line found
-the current line, and begin editing.
-.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.
-.SH EDITING COMMANDS
-.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.
-.PP
-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, it may be added to the history list for future recall with
-\fBadd_history()\fP.
-If the line is a modified history line, the history line is restored 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\-backward
-Search backward through the history for the string of characters
-between the start of the current line and the current cursor
-position (the \fIpoint\fP).
-The search string must match at the beginning of a history line.
-This is a non-incremental search.
-.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.
-The search string must match at the beginning of a history line.
-This is a non-incremental search.
-.TP
-.B history\-substring\-search\-backward
-Search backward through the history for the string of characters
-between the start of the current line and the current cursor
-position (the \fIpoint\fP).
-The search string may match anywhere in a history line.
-This is a non-incremental search.
-.TP
-.B history\-substring\-search\-forward
-Search forward through the history for the string of characters
-between the start of the current line and the point.
-The search string may match anywhere in a history line.
-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 a numeric argument, behave exactly like \fByank\-nth\-arg\fP.
-Successive calls to \fByank\-last\-arg\fP move back through the history
-list, inserting the last word (or the word specified by the argument to
-the first call) of each line in turn.
-Any numeric argument supplied to these successive calls determines
-the direction to move through the history. A negative argument switches
-the direction through the history (back or forward).
-The history expansion facilities are used to extract the last argument,
-as if the "!$" history expansion had been specified.
-.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 that you type to the line verbatim. This is
-how to insert characters like \fBC\-q\fP, for example.
-.TP
-.B tab\-insert (M-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 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 between the point and \fImark\fP (saved cursor position).
-This text is referred to as the \fIregion\fP.
-.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.
-The actual completion performed is application-specific.
-.BR Bash ,
-for instance, 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.
-.BR Gdb ,
-on the other hand,
-allows completion of program functions and variables, and
-only attempts filename completion under certain circumstances.
-.TP
-.B possible\-completions (M\-?)
-List the possible completions of the text before point.
-When displaying completions, readline sets the number of columns used
-for display to the value of \fBcompletion-display-width\fP, the value of
-the environment variable
-.SM
-.BR COLUMNS ,
-or the screen width, in that order.
-.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 menu\-complete\-backward
-Identical to \fBmenu\-complete\fP, but moves backward through the list
-of possible completions, as if \fBmenu\-complete\fP had been given a
-negative argument. This command 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.
-.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.
-.B print\-last\-kbd\-macro ()
-Print the last keyboard macro defined in a format suitable for the
-\fIinputrc\fP file.
-.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 skip\-csi\-sequence
-Read enough characters to consume a multi-key sequence such as those
-defined for keys like Home and End. Such sequences begin with a
-Control Sequence Indicator (CSI), usually ESC\-[. If this sequence is
-bound to "\e[", keys producing such sequences will have no effect
-unless explicitly bound to a readline command, instead of inserting
-stray characters into the editing buffer. This is unbound by default,
-but usually bound to ESC\-[.
-.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
-.B comment\-begin
-makes 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 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 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 emacs\-editing\-mode (C\-e)
-When in
-.B vi
-command mode, this causes a switch to
-.B emacs
-editing mode.
-.TP
-.B vi\-editing\-mode (M\-C\-j)
-When in
-.B emacs
-editing mode, this causes a switch to
-.B vi
-editing mode.
-.PD
-.SH DEFAULT KEY BINDINGS
-.LP
-The following is a list of the default emacs and vi bindings.
-Characters with the eighth bit set are written as M\-<character>, and
-are referred to as
-.I metafied
-characters.
-The printable ASCII characters not mentioned in the list of emacs
-standard bindings are bound to the
-.B self\-insert
-function, which just inserts the given character into the input line.
-In vi insertion mode, all characters not specifically mentioned are
-bound to
-.BR self\-insert .
-Characters assigned to signal generation by
-.IR stty (1)
-or the terminal driver, such as C-Z or C-C,
-retain that function.
-Upper and lower case metafied characters are bound to the same function in
-the emacs mode meta keymap.
-The remaining characters are unbound, which causes readline
-to ring the bell (subject to the setting of the
-.B bell\-style
-variable).
-.SS Emacs Mode
-.RS +.6i
-.nf
-.ta 2.5i
-.sp
-Emacs Standard bindings
-.sp
-"C-@" set-mark
-"C-A" beginning-of-line
-"C-B" backward-char
-"C-D" delete-char
-"C-E" end-of-line
-"C-F" forward-char
-"C-G" abort
-"C-H" backward-delete-char
-"C-I" complete
-"C-J" accept-line
-"C-K" kill-line
-"C-L" clear-screen
-"C-M" accept-line
-"C-N" next-history
-"C-P" previous-history
-"C-Q" quoted-insert
-"C-R" reverse-search-history
-"C-S" forward-search-history
-"C-T" transpose-chars
-"C-U" unix-line-discard
-"C-V" quoted-insert
-"C-W" unix-word-rubout
-"C-Y" yank
-"C-]" character-search
-"C-_" undo
-"\^ " to "/" self-insert
-"0" to "9" self-insert
-":" to "~" self-insert
-"C-?" backward-delete-char
-.PP
-Emacs Meta bindings
-.sp
-"M-C-G" abort
-"M-C-H" backward-kill-word
-"M-C-I" tab-insert
-"M-C-J" vi-editing-mode
-"M-C-M" vi-editing-mode
-"M-C-R" revert-line
-"M-C-Y" yank-nth-arg
-"M-C-[" complete
-"M-C-]" character-search-backward
-"M-space" set-mark
-"M-#" insert-comment
-"M-&" tilde-expand
-"M-*" insert-completions
-"M--" digit-argument
-"M-." yank-last-arg
-"M-0" digit-argument
-"M-1" digit-argument
-"M-2" digit-argument
-"M-3" digit-argument
-"M-4" digit-argument
-"M-5" digit-argument
-"M-6" digit-argument
-"M-7" digit-argument
-"M-8" digit-argument
-"M-9" digit-argument
-"M-<" beginning-of-history
-"M-=" possible-completions
-"M->" end-of-history
-"M-?" possible-completions
-"M-B" backward-word
-"M-C" capitalize-word
-"M-D" kill-word
-"M-F" forward-word
-"M-L" downcase-word
-"M-N" non-incremental-forward-search-history
-"M-P" non-incremental-reverse-search-history
-"M-R" revert-line
-"M-T" transpose-words
-"M-U" upcase-word
-"M-Y" yank-pop
-"M-\e" delete-horizontal-space
-"M-~" tilde-expand
-"M-C-?" backward-kill-word
-"M-_" yank-last-arg
-.PP
-Emacs Control-X bindings
-.sp
-"C-XC-G" abort
-"C-XC-R" re-read-init-file
-"C-XC-U" undo
-"C-XC-X" exchange-point-and-mark
-"C-X(" start-kbd-macro
-"C-X)" end-kbd-macro
-"C-XE" call-last-kbd-macro
-"C-XC-?" backward-kill-line
-.sp
-.RE
-.SS VI Mode bindings
-.RS +.6i
-.nf
-.ta 2.5i
-.sp
-.PP
-VI Insert Mode functions
-.sp
-"C-D" vi-eof-maybe
-"C-H" backward-delete-char
-"C-I" complete
-"C-J" accept-line
-"C-M" accept-line
-"C-R" reverse-search-history
-"C-S" forward-search-history
-"C-T" transpose-chars
-"C-U" unix-line-discard
-"C-V" quoted-insert
-"C-W" unix-word-rubout
-"C-Y" yank
-"C-[" vi-movement-mode
-"C-_" undo
-"\^ " to "~" self-insert
-"C-?" backward-delete-char
-.PP
-VI Command Mode functions
-.sp
-"C-D" vi-eof-maybe
-"C-E" emacs-editing-mode
-"C-G" abort
-"C-H" backward-char
-"C-J" accept-line
-"C-K" kill-line
-"C-L" clear-screen
-"C-M" accept-line
-"C-N" next-history
-"C-P" previous-history
-"C-Q" quoted-insert
-"C-R" reverse-search-history
-"C-S" forward-search-history
-"C-T" transpose-chars
-"C-U" unix-line-discard
-"C-V" quoted-insert
-"C-W" unix-word-rubout
-"C-Y" yank
-"C-_" vi-undo
-"\^ " forward-char
-"#" insert-comment
-"$" end-of-line
-"%" vi-match
-"&" vi-tilde-expand
-"*" vi-complete
-"+" next-history
-"," vi-char-search
-"-" previous-history
-"." vi-redo
-"/" vi-search
-"0" beginning-of-line
-"1" to "9" vi-arg-digit
-";" vi-char-search
-"=" vi-complete
-"?" vi-search
-"A" vi-append-eol
-"B" vi-prev-word
-"C" vi-change-to
-"D" vi-delete-to
-"E" vi-end-word
-"F" vi-char-search
-"G" vi-fetch-history
-"I" vi-insert-beg
-"N" vi-search-again
-"P" vi-put
-"R" vi-replace
-"S" vi-subst
-"T" vi-char-search
-"U" revert-line
-"W" vi-next-word
-"X" backward-delete-char
-"Y" vi-yank-to
-"\e" vi-complete
-"^" vi-first-print
-"_" vi-yank-arg
-"`" vi-goto-mark
-"a" vi-append-mode
-"b" vi-prev-word
-"c" vi-change-to
-"d" vi-delete-to
-"e" vi-end-word
-"f" vi-char-search
-"h" backward-char
-"i" vi-insertion-mode
-"j" next-history
-"k" prev-history
-"l" forward-char
-"m" vi-set-mark
-"n" vi-search-again
-"p" vi-put
-"r" vi-change-char
-"s" vi-subst
-"t" vi-char-search
-"u" vi-undo
-"w" vi-next-word
-"x" vi-delete
-"y" vi-yank-to
-"|" vi-column
-"~" vi-change-case
-.RE
-.SH "SEE ALSO"
-.PD 0
-.TP
-\fIThe Gnu Readline Library\fP, Brian Fox and Chet Ramey
-.TP
-\fIThe Gnu History Library\fP, Brian Fox and Chet Ramey
-.TP
-\fIbash\fP(1)
-.PD
-.SH FILES
-.PD 0
-.TP
-.FN ~/.inputrc
-Individual \fBreadline\fP initialization file
-.PD
-.SH AUTHORS
-Brian Fox, Free Software Foundation
-.br
-bfox@gnu.org
-.PP
-Chet Ramey, Case Western Reserve University
-.br
-chet@ins.CWRU.Edu
-.SH BUG REPORTS
-If you find a bug in
-.B readline,
-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 the
-.B readline
-library that you have.
-.PP
-Once you have determined that a bug actually exists, mail a
-bug report to \fIbug\-readline\fP@\fIgnu.org\fP.
-If you have a fix, you are welcome to mail that
-as well! Suggestions and `philosophical' bug reports may be mailed
-to \fPbug-readline\fP@\fIgnu.org\fP or posted to the Usenet
-newsgroup
-.BR gnu.bash.bug .
-.PP
-Comments and bug reports concerning
-this manual page should be directed to
-.IR chet@ins.CWRU.Edu .
-.SH BUGS
-.PP
-It's too big and too slow.
+++ /dev/null
-@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.)
-
-@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--2011 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 {char *} rl_display_prompt
-The string displayed as the prompt. This is usually identical to
-@var{rl_prompt}, but may be changed temporarily by functions that
-use the prompt string as a message area, such as incremental search.
-@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_executing_key
-The key that caused the dispatch to the currently-executing Readline function.
-@end deftypevar
-
-@deftypevar {char *} rl_executing_keyseq
-The full key sequence that caused the dispatch to the currently-executing
-Readline function.
-@end deftypevar
-
-@deftypevar int rl_key_sequence_length
-The number of characters in @var{rl_executing_keyseq}.
-@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_INPUTPENDING
-Readline has input pending due to a call to @code{rl_execute_next()}.
-@item RL_STATE_TTYCSAVED
-Readline has saved the values of the terminal's special characters.
-@item RL_STATE_CALLBACK
-Readline is currently using the alternate (callback) interface
-(@pxref{Alternate Interface}).
-@item RL_STATE_VIMOTION
-Readline is reading the argument to a vi-mode "motion" command.
-@item RL_STATE_MULTIKEY
-Readline is reading a multiple-keystroke command.
-@item RL_STATE_VICMDONCE
-Readline has entered vi command (movement) mode at least one time during
-the current call to @code{readline()}.
-@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_free_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 the data in @var{keymap}.
-The caller should free @var{keymap}.
-@end deftypefun
-
-@deftypefun void rl_free_keymap (Keymap keymap)
-Free all storage associated with @var{keymap}. This calls
-@code{rl_discard_keymap} to free subordindate keymaps and macros.
-@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 free the array, but not the pointers, using @code{free} or
-@code{rl_free} when you are done.
-@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 int rl_save_state (struct readline_state *sp)
-Save a snapshot of Readline's internal state to @var{sp}.
-The contents of the @var{readline_state} structure are documented
-in @file{readline.h}.
-The caller is responsible for allocating the structure.
-@end deftypefun
-
-@deftypefun int rl_restore_state (struct readline_state *sp)
-Restore Readline's internal state to that stored in @var{sp}, which must
-have been saved by a call to @code{rl_save_state}.
-The contents of the @var{readline_state} structure are documented
-in @file{readline.h}.
-The caller is responsible for freeing the structure.
-@end deftypefun
-
-@deftypefun void rl_free (void *mem)
-Deallocate the memory pointed to by @var{mem}. @var{mem} must have been
-allocated by @code{malloc}.
-@end deftypefun
-
-@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 void 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}).
-When displaying completions, this function sets the number of columns used
-for display to the value of @code{completion-display-width}, the value of
-the environment variable @env{COLUMNS}, or the screen width, in that order.
-@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{SIGHUP},
-@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{SIGHUP}, @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_echo_signal_char (int sig)
-If an application wishes to install its own signal handlers, but still
-have readline display characters that generate signals, calling this
-function with @var{sig} set to @code{SIGINT}, @code{SIGQUIT}, or
-@code{SIGTSTP} will display the character generating that signal.
-@end deftypefun
-
-@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{SIGHUP}, @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 could be used to expand symbolic links or shell variables in pathnames.
-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 used as part of the completion, replacing
-the directory portion of the pathname the user typed.
-At the least, even if no other expansion is performed, this function should
-remove any quote characters from the directory name, because its result will
-be passed directly to @code{opendir()}.
-
-The directory completion hook returns an integer that should be non-zero if
-the function modifies its directory argument.
-The function should not modify the directory argument if it returns 0.
-@end deftypevar
-
-@deftypevar {rl_icppfunc_t *} rl_directory_rewrite_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 @code{rl_directory_completion_hook},
-it only modifies the directory name used in @code{opendir}, not what is
-displayed when the possible completions are printed or inserted. It is
-called before rl_directory_completion_hook.
-At the least, even if no other expansion is performed, this function should
-remove any quote characters from the directory name, because its result will
-be passed directly to @code{opendir()}.
-
-The directory rewrite hook returns an integer that should be non-zero if
-the function modfies its directory argument.
-The function should not modify the directory argument if it returns 0.
-@end deftypevar
-
-@deftypevar {rl_icppfunc_t *} rl_filename_stat_hook
-If non-zero, this is the address of a function for the completer to
-call before deciding which character to append to a completed name.
-This function modifies its filename name argument, and the modified value
-is passed to @code{stat()} to determine the file's type and characteristics.
-This function does not need to remove quote characters from the filename.
-
-The stat hook returns an integer that should be non-zero if
-the function modfies its directory argument.
-The function should not modify the directory argument if it returns 0.
-@end deftypevar
-
-@deftypevar {rl_dequote_func_t *} rl_filename_rewrite_hook
-If non-zero, this is the address of a function called when reading
-directory entries from the filesystem for completion and comparing
-them to the partial word to be completed. The function should
-perform any necesary application or system-specific conversion on
-the filename, such as converting between character sets or converting
-from a filesystem format to a character input format.
-The function takes two arguments: @var{fname}, the filename to be converted,
-and @var{fnlen}, its length in bytes.
-It must either return its first argument (if no conversion takes place)
-or the converted filename in newly-allocated memory. The converted
-form is used to compare against the word to be completed, and, if it
-matches, is added to the list of matches. Readline will free the
-allocated string.
-@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_sort_completion_matches
-If an application sets this variable to 0, Readline will not sort the
-list of completions (which implies that it cannot remove any duplicate
-completions). The default value is 1, which means that Readline will
-sort the completions and, depending on the value of
-@code{rl_ignore_completion_duplicates}, will attempt to remove duplicate
-matches.
-@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_completion_invoking_key
-Set to the final character in the key sequence that invoked one of the
-completion functions that call @code{rl_complete_internal()}. This is
-set to the appropriate value before any application-specific completion
-function is called.
-@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. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#ifdef HAVE_SYS_FILE_H
-# include <sys/file.h>
-#endif
-#include <sys/stat.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <errno.h>
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else /* !HAVE_STRING_H */
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-#endif
-
-#include <time.h>
-
-#include <readline/readline.h>
-#include <readline/history.h>
-
-extern char *xmalloc PARAMS((size_t));
-
-/* The names of functions that actually do the manipulation. */
-int com_list PARAMS((char *));
-int com_view PARAMS((char *));
-int com_rename PARAMS((char *));
-int com_stat PARAMS((char *));
-int com_pwd PARAMS((char *));
-int com_delete PARAMS((char *));
-int com_help PARAMS((char *));
-int com_cd PARAMS((char *));
-int com_quit PARAMS((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 global means the user is done using this program. */
-int done;
-
-char *
-dupstr (s)
- char *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 PARAMS((const char *, int));
-char **fileman_completion PARAMS((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. Return the 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;
-
-#if defined (__MSDOS__)
- /* more.com doesn't grok slashes in pathnames */
- sprintf (syscom, "less %s", arg);
-#else
- sprintf (syscom, "more %s", arg);
-#endif
- 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. Write it yourself.\n",
- caller);
-@}
-
-/* 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
+++ /dev/null
-@comment %**start of header (This is for running Texinfo on a region.)
-@setfilename rluser.info
-@comment %**end of header (This is for running Texinfo on a region.)
-
-@ignore
-This file documents the end user interface to the GNU command line
-editing features. It is to be an appendix to manuals for programs which
-use these features. There is a document entitled "readline.texinfo"
-which contains both end-user and programmer documentation for the
-GNU Readline Library.
-
-Copyright (C) 1988--2011 Free Software Foundation, Inc.
-
-Authored by Brian Fox and Chet Ramey.
-
-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).
-
-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.
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided also that the
-GNU Copyright statement is available to the distributee, and 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.
-@end ignore
-
-@comment If you are including this manual as an appendix, then set the
-@comment variable readline-appendix.
-
-@ifclear BashFeatures
-@defcodeindex bt
-@end ifclear
-
-@node Command Line Editing
-@chapter Command Line Editing
-
-This chapter describes the basic features of the @sc{gnu}
-command line editing interface.
-@ifset BashFeatures
-Command line editing is provided by the Readline library, which is
-used by several different programs, including Bash.
-Command line editing is enabled by default when using an interactive shell,
-unless the @option{--noediting} option is supplied at shell invocation.
-Line editing is also used when using the @option{-e} option to the
-@code{read} builtin command (@pxref{Bash Builtins}).
-By default, the line editing commands are similar to those of Emacs.
-A vi-style line editing interface is also available.
-Line editing can be enabled at any time using the @option{-o emacs} or
-@option{-o vi} options to the @code{set} builtin command
-(@pxref{The Set Builtin}), or disabled using the @option{+o emacs} or
-@option{+o vi} options to @code{set}.
-@end ifset
-
-@menu
-* Introduction and Notation:: Notation used in this text.
-* Readline Interaction:: The minimum set of commands for editing a line.
-* Readline Init File:: Customizing Readline from a user's view.
-* Bindable Readline Commands:: A description of most of the Readline commands
- available for binding
-* Readline vi Mode:: A short description of how to make Readline
- behave like the vi editor.
-@ifset BashFeatures
-* Programmable Completion:: How to specify the possible completions for
- a specific command.
-* Programmable Completion Builtins:: Builtin commands to specify how to
- complete arguments for a particular command.
-* A Programmable Completion Example:: An example shell function for
- generating possible completions.
-@end ifset
-@end menu
-
-@node Introduction and Notation
-@section Introduction to Line Editing
-
-The following paragraphs describe the notation used to represent
-keystrokes.
-
-The text @kbd{C-k} is read as `Control-K' and describes the character
-produced when the @key{k} key is pressed while the Control key
-is depressed.
-
-The text @kbd{M-k} is read as `Meta-K' and describes the character
-produced when the Meta key (if you have one) is depressed, and the @key{k}
-key is pressed.
-The Meta key is labeled @key{ALT} on many keyboards.
-On keyboards with two keys labeled @key{ALT} (usually to either side of
-the space bar), the @key{ALT} on the left side is generally set to
-work as a Meta key.
-The @key{ALT} key on the right may also be configured to work as a
-Meta key or may be configured as some other modifier, such as a
-Compose key for typing accented characters.
-
-If you do not have a Meta or @key{ALT} key, or another key working as
-a Meta key, the identical keystroke can be generated by typing @key{ESC}
-@emph{first}, and then typing @key{k}.
-Either process is known as @dfn{metafying} the @key{k} key.
-
-The text @kbd{M-C-k} is read as `Meta-Control-k' and describes the
-character produced by @dfn{metafying} @kbd{C-k}.
-
-In addition, several keys have their own names. Specifically,
-@key{DEL}, @key{ESC}, @key{LFD}, @key{SPC}, @key{RET}, and @key{TAB} all
-stand for themselves when seen in this text, or in an init file
-(@pxref{Readline Init File}).
-If your keyboard lacks a @key{LFD} key, typing @key{C-j} will
-produce the desired character.
-The @key{RET} key may be labeled @key{Return} or @key{Enter} on
-some keyboards.
-
-@node Readline Interaction
-@section Readline Interaction
-@cindex interaction, readline
-
-Often during an interactive session you type in a long line of text,
-only to notice that the first word on the line is misspelled. The
-Readline library gives you a set of commands for manipulating the text
-as you type it in, allowing you to just fix your typo, and not forcing
-you to retype the majority of the line. Using these editing commands,
-you move the cursor to the place that needs correction, and delete or
-insert the text of the corrections. Then, when you are satisfied with
-the line, you simply press @key{RET}. You do not have to be at the
-end of the line to press @key{RET}; the entire line is accepted
-regardless of the location of the cursor within the line.
-
-@menu
-* Readline Bare Essentials:: The least you need to know about Readline.
-* Readline Movement Commands:: Moving about the input line.
-* Readline Killing Commands:: How to delete text, and how to get it back!
-* Readline Arguments:: Giving numeric arguments to commands.
-* Searching:: Searching through previous lines.
-@end menu
-
-@node Readline Bare Essentials
-@subsection Readline Bare Essentials
-@cindex notation, readline
-@cindex command editing
-@cindex editing command lines
-
-In order to enter characters into the line, simply type them. The typed
-character appears where the cursor was, and then the cursor moves one
-space to the right. If you mistype a character, you can use your
-erase character to back up and delete the mistyped character.
-
-Sometimes you may mistype a character, and
-not notice the error until you have typed several other characters. In
-that case, you can type @kbd{C-b} to move the cursor to the left, and then
-correct your mistake. Afterwards, you can move the cursor to the right
-with @kbd{C-f}.
-
-When you add text in the middle of a line, you will notice that characters
-to the right of the cursor are `pushed over' to make room for the text
-that you have inserted. Likewise, when you delete text behind the cursor,
-characters to the right of the cursor are `pulled back' to fill in the
-blank space created by the removal of the text. A list of the bare
-essentials for editing the text of an input line follows.
-
-@table @asis
-@item @kbd{C-b}
-Move back one character.
-@item @kbd{C-f}
-Move forward one character.
-@item @key{DEL} or @key{Backspace}
-Delete the character to the left of the cursor.
-@item @kbd{C-d}
-Delete the character underneath the cursor.
-@item @w{Printing characters}
-Insert the character into the line at the cursor.
-@item @kbd{C-_} or @kbd{C-x C-u}
-Undo the last editing command. You can undo all the way back to an
-empty line.
-@end table
-
-@noindent
-(Depending on your configuration, the @key{Backspace} key be set to
-delete the character to the left of the cursor and the @key{DEL} key set
-to delete the character underneath the cursor, like @kbd{C-d}, rather
-than the character to the left of the cursor.)
-
-@node Readline Movement Commands
-@subsection Readline Movement Commands
-
-
-The above table describes the most basic keystrokes that you need
-in order to do editing of the input line. For your convenience, many
-other commands have been added in addition to @kbd{C-b}, @kbd{C-f},
-@kbd{C-d}, and @key{DEL}. Here are some commands for moving more rapidly
-about the line.
-
-@table @kbd
-@item C-a
-Move to the start of the line.
-@item C-e
-Move to the end of the line.
-@item M-f
-Move forward a word, where a word is composed of letters and digits.
-@item M-b
-Move backward a word.
-@item C-l
-Clear the screen, reprinting the current line at the top.
-@end table
-
-Notice how @kbd{C-f} moves forward a character, while @kbd{M-f} moves
-forward a word. It is a loose convention that control keystrokes
-operate on characters while meta keystrokes operate on words.
-
-@node Readline Killing Commands
-@subsection Readline Killing Commands
-
-@cindex killing text
-@cindex yanking text
-
-@dfn{Killing} text means to delete the text from the line, but to save
-it away for later use, usually by @dfn{yanking} (re-inserting)
-it back into the line.
-(`Cut' and `paste' are more recent jargon for `kill' and `yank'.)
-
-If the description for a command says that it `kills' text, then you can
-be sure that you can get the text back in a different (or the same)
-place later.
-
-When you use a kill command, the text is saved in a @dfn{kill-ring}.
-Any number of consecutive kills save all of the killed text together, so
-that when you yank it back, you get it all. The kill
-ring is not line specific; the text that you killed on a previously
-typed line is available to be yanked back later, when you are typing
-another line.
-@cindex kill ring
-
-Here is the list of commands for killing text.
-
-@table @kbd
-@item C-k
-Kill the text from the current cursor position to the end of the line.
-
-@item M-d
-Kill from the cursor 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 @kbd{M-f}.
-
-@item M-@key{DEL}
-Kill from the cursor the start of the current word, or, if between
-words, to the start of the previous word.
-Word boundaries are the same as those used by @kbd{M-b}.
-
-@item C-w
-Kill from the cursor to the previous whitespace. This is different than
-@kbd{M-@key{DEL}} because the word boundaries differ.
-
-@end table
-
-Here is how to @dfn{yank} the text back into the line. Yanking
-means to copy the most-recently-killed text from the kill buffer.
-
-@table @kbd
-@item C-y
-Yank the most recently killed text back into the buffer at the cursor.
-
-@item M-y
-Rotate the kill-ring, and yank the new top. You can only do this if
-the prior command is @kbd{C-y} or @kbd{M-y}.
-@end table
-
-@node Readline Arguments
-@subsection Readline Arguments
-
-You can pass numeric arguments to Readline commands. Sometimes the
-argument acts as a repeat count, other times it is the @i{sign} of the
-argument that is significant. If you pass a negative argument to a
-command which normally acts in a forward direction, that command will
-act in a backward direction. For example, to kill text back to the
-start of the line, you might type @samp{M-- C-k}.
-
-The general way to pass numeric arguments to a command is to type meta
-digits before the command. If the first `digit' typed is a minus
-sign (@samp{-}), then the sign of the argument will be negative. Once
-you have typed one meta digit to get the argument started, you can type
-the remainder of the digits, and then the command. For example, to give
-the @kbd{C-d} command an argument of 10, you could type @samp{M-1 0 C-d},
-which will delete the next ten characters on the input line.
-
-@node Searching
-@subsection Searching for Commands in the History
-
-Readline provides commands for searching through the command history
-@ifset BashFeatures
-(@pxref{Bash History Facilities})
-@end ifset
-for lines containing a specified string.
-There are two search modes: @dfn{incremental} and @dfn{non-incremental}.
-
-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.
-To search backward in the history for a particular string, type
-@kbd{C-r}. Typing @kbd{C-s} searches forward through the history.
-The characters present in the value of the @code{isearch-terminators} variable
-are used to terminate an incremental search.
-If that variable has not been assigned a value, the @key{ESC} and
-@kbd{C-J} characters will terminate an incremental search.
-@kbd{C-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.
-
-To find other matching entries in the history list, type @kbd{C-r} or
-@kbd{C-s} 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 @key{RET} will terminate the search and accept
-the line, thereby executing the command from the history list.
-A movement command will terminate the search, make the last line found
-the current line, and begin editing.
-
-Readline remembers the last incremental search string. If two
-@kbd{C-r}s are typed without any intervening characters defining a new
-search string, any remembered search string is used.
-
-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.
-
-@node Readline Init File
-@section Readline Init File
-@cindex initialization file, readline
-
-Although the Readline library comes with a set of Emacs-like
-keybindings installed by default, it is possible to use a different set
-of keybindings.
-Any user can customize programs that use Readline by putting
-commands in an @dfn{inputrc} file, conventionally in his home directory.
-The name of this
-@ifset BashFeatures
-file is taken from the value of the shell variable @env{INPUTRC}. If
-@end ifset
-@ifclear BashFeatures
-file is taken from the value of the environment variable @env{INPUTRC}. If
-@end ifclear
-that variable is unset, the default is @file{~/.inputrc}. If that
-file does not exist or cannot be read, the ultimate default is
-@file{/etc/inputrc}.
-
-When a program which uses the Readline library starts up, the
-init file is read, and the key bindings are set.
-
-In addition, the @code{C-x C-r} command re-reads this init file, thus
-incorporating any changes that you might have made to it.
-
-@menu
-* Readline Init File Syntax:: Syntax for the commands in the inputrc file.
-
-* Conditional Init Constructs:: Conditional key bindings in the inputrc file.
-
-* Sample Init File:: An example inputrc file.
-@end menu
-
-@node Readline Init File Syntax
-@subsection Readline Init File Syntax
-
-There are only a few basic constructs allowed in the
-Readline init file. Blank lines are ignored.
-Lines beginning with a @samp{#} are comments.
-Lines beginning with a @samp{$} indicate conditional
-constructs (@pxref{Conditional Init Constructs}). Other lines
-denote variable settings and key bindings.
-
-@table @asis
-@item Variable Settings
-You can modify the run-time behavior of Readline by
-altering the values of variables in Readline
-using the @code{set} command within the init file.
-The syntax is simple:
-
-@example
-set @var{variable} @var{value}
-@end example
-
-@noindent
-Here, for example, is how to
-change from the default Emacs-like key binding to use
-@code{vi} line editing commands:
-
-@example
-set editing-mode vi
-@end example
-
-Variable names and values, where appropriate, are recognized without regard
-to case. Unrecognized variable names are ignored.
-
-Boolean variables (those that can be set to on or off) are set to on if
-the value is null or empty, @var{on} (case-insensitive), or 1. Any other
-value results in the variable being set to off.
-
-@ifset BashFeatures
-The @w{@code{bind -V}} command lists the current Readline variable names
-and values. @xref{Bash Builtins}.
-@end ifset
-
-A great deal of run-time behavior is changeable with the following
-variables.
-
-@cindex variables, readline
-@table @code
-
-@item bell-style
-@vindex bell-style
-Controls what happens when Readline wants to ring the terminal bell.
-If set to @samp{none}, Readline never rings the bell. If set to
-@samp{visible}, Readline uses a visible bell if one is available.
-If set to @samp{audible} (the default), Readline attempts to ring
-the terminal's bell.
-
-@item bind-tty-special-chars
-@vindex bind-tty-special-chars
-If set to @samp{on}, Readline attempts to bind the control characters
-treated specially by the kernel's terminal driver to their Readline
-equivalents.
-
-@item colored-stats
-@vindex colored-stats
-If set to @samp{on}, Readline displays possible completions using different
-colors to indicate their file type.
-The color definitions are taken from the value of the @env{LS_COLORS}
-environment variable.
-The default is @samp{off}.
-
-@item comment-begin
-@vindex comment-begin
-The string to insert at the beginning of the line when the
-@code{insert-comment} command is executed. The default value
-is @code{"#"}.
-
-@item completion-display-width
-@vindex completion-display-width
-The number of screen columns used to display possible matches
-when performing completion.
-The value is ignored if it is less than 0 or greater than the terminal
-screen width.
-A value of 0 will cause matches to be displayed one per line.
-The default value is -1.
-
-@item completion-ignore-case
-@vindex completion-ignore-case
-If set to @samp{on}, Readline performs filename matching and completion
-in a case-insensitive fashion.
-The default value is @samp{off}.
-
-@item completion-map-case
-@vindex completion-map-case
-If set to @samp{on}, and @var{completion-ignore-case} is enabled, Readline
-treats hyphens (@samp{-}) and underscores (@samp{_}) as equivalent when
-performing case-insensitive filename matching and completion.
-
-@item completion-prefix-display-length
-@vindex completion-prefix-display-length
-The length in characters of the common prefix of a list of possible
-completions that is displayed without modification. When set to a
-value greater than zero, common prefixes longer than this value are
-replaced with an ellipsis when displaying possible completions.
-
-@item completion-query-items
-@vindex completion-query-items
-The number of possible completions that determines when the user is
-asked whether the list of possibilities should be displayed.
-If the number of possible completions is greater than this value,
-Readline will ask the user whether or not he wishes to view
-them; otherwise, they are simply listed.
-This variable must be set to an integer value greater than or equal to 0.
-A negative value means Readline should never ask.
-The default limit is @code{100}.
-
-@item convert-meta
-@vindex convert-meta
-If set to @samp{on}, Readline will convert characters with the
-eighth bit set to an @sc{ascii} key sequence by stripping the eighth
-bit and prefixing an @key{ESC} character, converting them to a
-meta-prefixed key sequence. The default value is @samp{on}.
-
-@item disable-completion
-@vindex disable-completion
-If set to @samp{On}, Readline will inhibit word completion.
-Completion characters will be inserted into the line as if they had
-been mapped to @code{self-insert}. The default is @samp{off}.
-
-@item editing-mode
-@vindex editing-mode
-The @code{editing-mode} variable controls which default set of
-key bindings is used. By default, Readline starts up in Emacs editing
-mode, where the keystrokes are most similar to Emacs. This variable can be
-set to either @samp{emacs} or @samp{vi}.
-
-@item echo-control-characters
-When set to @samp{on}, on operating systems that indicate they support it,
-readline echoes a character corresponding to a signal generated from the
-keyboard. The default is @samp{on}.
-
-@item enable-keypad
-@vindex enable-keypad
-When set to @samp{on}, Readline will try to enable the application
-keypad when it is called. Some systems need this to enable the
-arrow keys. The default is @samp{off}.
-
-@item enable-meta-key
-When set to @samp{on}, Readline will try to enable any meta modifier
-key the terminal claims to support when it is called. On many terminals,
-the meta key is used to send eight-bit characters.
-The default is @samp{on}.
-
-@item expand-tilde
-@vindex expand-tilde
-If set to @samp{on}, tilde expansion is performed when Readline
-attempts word completion. The default is @samp{off}.
-
-@item history-preserve-point
-@vindex history-preserve-point
-If set to @samp{on}, the history code attempts to place the point (the
-current cursor position) at the
-same location on each history line retrieved with @code{previous-history}
-or @code{next-history}. The default is @samp{off}.
-
-@item history-size
-@vindex history-size
-Set the maximum number of history entries saved in the history list. If
-set to zero, the number of entries in the history list is not limited.
-
-@item horizontal-scroll-mode
-@vindex horizontal-scroll-mode
-This variable can be set to either @samp{on} or @samp{off}. Setting it
-to @samp{on} means that the text of the lines being edited will scroll
-horizontally on a single screen line when they are longer than the width
-of the screen, instead of wrapping onto a new screen line. By default,
-this variable is set to @samp{off}.
-
-@item input-meta
-@vindex input-meta
-@vindex meta-flag
-If set to @samp{on}, Readline will enable eight-bit input (it
-will not clear the eighth bit in the characters it reads),
-regardless of what the terminal claims it can support. The
-default value is @samp{off}. The name @code{meta-flag} is a
-synonym for this variable.
-
-@item isearch-terminators
-@vindex isearch-terminators
-The string of characters that should terminate an incremental search without
-subsequently executing the character as a command (@pxref{Searching}).
-If this variable has not been given a value, the characters @key{ESC} and
-@kbd{C-J} will terminate an incremental search.
-
-@item keymap
-@vindex keymap
-Sets Readline's idea of the current keymap for key binding commands.
-Acceptable @code{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}. The default value is @code{emacs}.
-The value of the @code{editing-mode} variable also affects the
-default keymap.
-
-@item mark-directories
-If set to @samp{on}, completed directory names have a slash
-appended. The default is @samp{on}.
-
-@item mark-modified-lines
-@vindex mark-modified-lines
-This variable, when set to @samp{on}, causes Readline to display an
-asterisk (@samp{*}) at the start of history lines which have been modified.
-This variable is @samp{off} by default.
-
-@item mark-symlinked-directories
-@vindex mark-symlinked-directories
-If set to @samp{on}, completed names which are symbolic links
-to directories have a slash appended (subject to the value of
-@code{mark-directories}).
-The default is @samp{off}.
-
-@item match-hidden-files
-@vindex match-hidden-files
-This variable, when set to @samp{on}, causes Readline to match files whose
-names begin with a @samp{.} (hidden files) when performing filename
-completion.
-If set to @samp{off}, the leading @samp{.} must be
-supplied by the user in the filename to be completed.
-This variable is @samp{on} by default.
-
-@item menu-complete-display-prefix
-@vindex menu-complete-display-prefix
-If set to @samp{on}, menu completion displays the common prefix of the
-list of possible completions (which may be empty) before cycling through
-the list. The default is @samp{off}.
-
-@item output-meta
-@vindex output-meta
-If set to @samp{on}, Readline will display characters with the
-eighth bit set directly rather than as a meta-prefixed escape
-sequence. The default is @samp{off}.
-
-@item page-completions
-@vindex page-completions
-If set to @samp{on}, Readline uses an internal @code{more}-like pager
-to display a screenful of possible completions at a time.
-This variable is @samp{on} by default.
-
-@item print-completions-horizontally
-If set to @samp{on}, Readline will display completions with matches
-sorted horizontally in alphabetical order, rather than down the screen.
-The default is @samp{off}.
-
-@item revert-all-at-newline
-@vindex revert-all-at-newline
-If set to @samp{on}, Readline will undo all changes to history lines
-before returning when @code{accept-line} is executed. By default,
-history lines may be modified and retain individual undo lists across
-calls to @code{readline}. The default is @samp{off}.
-
-@item show-all-if-ambiguous
-@vindex show-all-if-ambiguous
-This alters the default behavior of the completion functions. If
-set to @samp{on},
-words which have more than one possible completion cause the
-matches to be listed immediately instead of ringing the bell.
-The default value is @samp{off}.
-
-@item show-all-if-unmodified
-@vindex show-all-if-unmodified
-This alters the default behavior of the completion functions in
-a fashion similar to @var{show-all-if-ambiguous}.
-If set to @samp{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.
-The default value is @samp{off}.
-
-@item skip-completed-text
-@vindex skip-completed-text
-If set to @samp{on}, this alters the default completion behavior when
-inserting a single match into the line. It's only active when
-performing completion in the middle of a word. If enabled, readline
-does not insert characters from the completion that match characters
-after point in the word being completed, so portions of the word
-following the cursor are not duplicated.
-For instance, if this is enabled, attempting completion when the cursor
-is after the @samp{e} in @samp{Makefile} will result in @samp{Makefile}
-rather than @samp{Makefilefile}, assuming there is a single possible
-completion.
-The default value is @samp{off}.
-
-@item visible-stats
-@vindex visible-stats
-If set to @samp{on}, a character denoting a file's type
-is appended to the filename when listing possible
-completions. The default is @samp{off}.
-
-@end table
-
-@item Key Bindings
-The syntax for controlling key bindings in the init file is
-simple. First you need to find the name of the command that you
-want to change. The following sections contain tables of the command
-name, the default keybinding, if any, and a short description of what
-the command does.
-
-Once you know the name of the command, simply place on a line
-in the init file the name of the key
-you wish to bind the command to, a colon, and then the name of the
-command.
-There can be no space between the key name and the colon -- that will be
-interpreted as part of the key name.
-The name of the key can be expressed in different ways, depending on
-what you find most comfortable.
-
-In addition to command names, readline allows keys to be bound
-to a string that is inserted when the key is pressed (a @var{macro}).
-
-@ifset BashFeatures
-The @w{@code{bind -p}} command displays Readline function names and
-bindings in a format that can put directly into an initialization file.
-@xref{Bash Builtins}.
-@end ifset
-
-@table @asis
-@item @w{@var{keyname}: @var{function-name} or @var{macro}}
-@var{keyname} is the name of a key spelled out in English. For example:
-@example
-Control-u: universal-argument
-Meta-Rubout: backward-kill-word
-Control-o: "> output"
-@end example
-
-In the above example, @kbd{C-u} is bound to the function
-@code{universal-argument},
-@kbd{M-DEL} is bound to the function @code{backward-kill-word}, and
-@kbd{C-o} is bound to run the macro
-expressed on the right hand side (that is, to insert the text
-@samp{> output} into the line).
-
-A number of symbolic character names are recognized while
-processing this key binding syntax:
-@var{DEL},
-@var{ESC},
-@var{ESCAPE},
-@var{LFD},
-@var{NEWLINE},
-@var{RET},
-@var{RETURN},
-@var{RUBOUT},
-@var{SPACE},
-@var{SPC},
-and
-@var{TAB}.
-
-@item @w{"@var{keyseq}": @var{function-name} or @var{macro}}
-@var{keyseq} differs from @var{keyname} above in that strings
-denoting an entire key sequence can be specified, by placing
-the key sequence in double quotes. Some @sc{gnu} Emacs style key
-escapes can be used, as in the following example, but the
-special character names are not recognized.
-
-@example
-"\C-u": universal-argument
-"\C-x\C-r": re-read-init-file
-"\e[11~": "Function Key 1"
-@end example
-
-In the above example, @kbd{C-u} is again bound to the function
-@code{universal-argument} (just as it was in the first example),
-@samp{@kbd{C-x} @kbd{C-r}} is bound to the function @code{re-read-init-file},
-and @samp{@key{ESC} @key{[} @key{1} @key{1} @key{~}} is bound to insert
-the text @samp{Function Key 1}.
-
-@end table
-
-The following @sc{gnu} Emacs style escape sequences are available when
-specifying key sequences:
-
-@table @code
-@item @kbd{\C-}
-control prefix
-@item @kbd{\M-}
-meta prefix
-@item @kbd{\e}
-an escape character
-@item @kbd{\\}
-backslash
-@item @kbd{\"}
-@key{"}, a double quotation mark
-@item @kbd{\'}
-@key{'}, a single quote or apostrophe
-@end table
-
-In addition to the @sc{gnu} Emacs style escape sequences, a second
-set of backslash escapes is available:
-
-@table @code
-@item \a
-alert (bell)
-@item \b
-backspace
-@item \d
-delete
-@item \f
-form feed
-@item \n
-newline
-@item \r
-carriage return
-@item \t
-horizontal tab
-@item \v
-vertical tab
-@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)
-@end table
-
-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 @samp{"} and @samp{'}.
-For example, the following binding will make @samp{@kbd{C-x} \}
-insert a single @samp{\} into the line:
-@example
-"\C-x\\": "\\"
-@end example
-
-@end table
-
-@node Conditional Init Constructs
-@subsection Conditional Init Constructs
-
-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.
-
-@table @code
-@item $if
-The @code{$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.
-
-@table @code
-@item mode
-The @code{mode=} form of the @code{$if} directive is used to test
-whether Readline is in @code{emacs} or @code{vi} mode.
-This may be used in conjunction
-with the @samp{set keymap} command, for instance, to set bindings in
-the @code{emacs-standard} and @code{emacs-ctlx} keymaps only if
-Readline is starting out in @code{emacs} mode.
-
-@item term
-The @code{term=} 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
-@samp{=} is tested against both the full name of the terminal and
-the portion of the terminal name before the first @samp{-}. This
-allows @code{sun} to match both @code{sun} and @code{sun-cmd},
-for instance.
-
-@item application
-The @var{application} construct is used to include
-application-specific settings. Each program using the Readline
-library sets the @var{application name}, and you 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:
-@example
-$if Bash
-# Quote the current or previous word
-"\C-xq": "\eb\"\ef\""
-$endif
-@end example
-@end table
-
-@item $endif
-This command, as seen in the previous example, terminates an
-@code{$if} command.
-
-@item $else
-Commands in this branch of the @code{$if} directive are executed if
-the test fails.
-
-@item $include
-This directive takes a single filename as an argument and reads commands
-and bindings from that file.
-For example, the following directive reads from @file{/etc/inputrc}:
-@example
-$include /etc/inputrc
-@end example
-@end table
-
-@node Sample Init File
-@subsection Sample Init File
-
-Here is an example of an @var{inputrc} file. This illustrates key
-binding, variable assignment, and conditional syntax.
-
-@example
-@page
-# This file controls the behaviour of line input editing for
-# programs that use the GNU Readline library. Existing
-# programs include FTP, Bash, and GDB.
-#
-# You can re-read the inputrc file with C-x C-r.
-# Lines beginning with '#' are comments.
-#
-# First, include any systemwide bindings and variable
-# assignments from /etc/Inputrc
-$include /etc/Inputrc
-
-#
-# Set various bindings for emacs mode.
-
-set editing-mode emacs
-
-$if mode=emacs
-
-Meta-Control-h: backward-kill-word Text after the function name is ignored
-
-#
-# Arrow keys in keypad mode
-#
-#"\M-OD": backward-char
-#"\M-OC": forward-char
-#"\M-OA": previous-history
-#"\M-OB": next-history
-#
-# Arrow keys in ANSI mode
-#
-"\M-[D": backward-char
-"\M-[C": forward-char
-"\M-[A": previous-history
-"\M-[B": next-history
-#
-# Arrow keys in 8 bit keypad mode
-#
-#"\M-\C-OD": backward-char
-#"\M-\C-OC": forward-char
-#"\M-\C-OA": previous-history
-#"\M-\C-OB": next-history
-#
-# Arrow keys in 8 bit ANSI mode
-#
-#"\M-\C-[D": backward-char
-#"\M-\C-[C": forward-char
-#"\M-\C-[A": previous-history
-#"\M-\C-[B": next-history
-
-C-q: quoted-insert
-
-$endif
-
-# An old-style binding. This happens to be the default.
-TAB: complete
-
-# Macros that are convenient for shell interaction
-$if Bash
-# edit the path
-"\C-xp": "PATH=$@{PATH@}\e\C-e\C-a\ef\C-f"
-# prepare to type a quoted word --
-# insert open and close double quotes
-# and move to just after the open quote
-"\C-x\"": "\"\"\C-b"
-# insert a backslash (testing backslash escapes
-# in sequences and macros)
-"\C-x\\": "\\"
-# Quote the current or previous word
-"\C-xq": "\eb\"\ef\""
-# Add a binding to refresh the line, which is unbound
-"\C-xr": redraw-current-line
-# Edit variable on current line.
-"\M-\C-v": "\C-a\C-k$\C-y\M-\C-e\C-a\C-y="
-$endif
-
-# use a visible bell if one is available
-set bell-style visible
-
-# don't strip characters to 7 bits when reading
-set input-meta on
-
-# allow iso-latin1 characters to be inserted rather
-# than converted to prefix-meta sequences
-set convert-meta off
-
-# display characters with the eighth bit set directly
-# rather than as meta-prefixed characters
-set output-meta on
-
-# if there are more than 150 possible completions for
-# a word, ask the user if he wants to see all of them
-set completion-query-items 150
-
-# For FTP
-$if Ftp
-"\C-xg": "get \M-?"
-"\C-xt": "put \M-?"
-"\M-.": yank-last-arg
-$endif
-@end example
-
-@node Bindable Readline Commands
-@section Bindable Readline Commands
-
-@menu
-* Commands For Moving:: Moving about the line.
-* Commands For History:: Getting at previous lines.
-* Commands For Text:: Commands for changing text.
-* Commands For Killing:: Commands for killing and yanking.
-* Numeric Arguments:: Specifying numeric arguments, repeat counts.
-* Commands For Completion:: Getting Readline to do the typing for you.
-* Keyboard Macros:: Saving and re-executing typed characters
-* Miscellaneous Commands:: Other miscellaneous commands.
-@end menu
-
-This section describes Readline commands that may be bound to key
-sequences.
-@ifset BashFeatures
-You can list your key bindings by executing
-@w{@code{bind -P}} or, for a more terse format, suitable for an
-@var{inputrc} file, @w{@code{bind -p}}. (@xref{Bash Builtins}.)
-@end ifset
-Command names without an accompanying key sequence are unbound by default.
-
-In the following descriptions, @dfn{point} refers to the current cursor
-position, and @dfn{mark} refers to a cursor position saved by the
-@code{set-mark} command.
-The text between the point and mark is referred to as the @dfn{region}.
-
-@node Commands For Moving
-@subsection Commands For Moving
-@ftable @code
-@item beginning-of-line (C-a)
-Move to the start of the current line.
-
-@item end-of-line (C-e)
-Move to the end of the line.
-
-@item forward-char (C-f)
-Move forward a character.
-
-@item backward-char (C-b)
-Move back a character.
-
-@item forward-word (M-f)
-Move forward to the end of the next word.
-Words are composed of letters and digits.
-
-@item backward-word (M-b)
-Move back to the start of the current or previous word.
-Words are composed of letters and digits.
-
-@ifset BashFeatures
-@item shell-forward-word ()
-Move forward to the end of the next word.
-Words are delimited by non-quoted shell metacharacters.
-
-@item shell-backward-word ()
-Move back to the start of the current or previous word.
-Words are delimited by non-quoted shell metacharacters.
-@end ifset
-
-@item clear-screen (C-l)
-Clear the screen and redraw the current line,
-leaving the current line at the top of the screen.
-
-@item redraw-current-line ()
-Refresh the current line. By default, this is unbound.
-
-@end ftable
-
-@node Commands For History
-@subsection Commands For Manipulating The History
-
-@ftable @code
-@item accept-line (Newline or Return)
-@ifset BashFeatures
-Accept the line regardless of where the cursor is.
-If this line is
-non-empty, add it to the history list according to the setting of
-the @env{HISTCONTROL} and @env{HISTIGNORE} variables.
-If this line is a modified history line, then restore the history line
-to its original state.
-@end ifset
-@ifclear BashFeatures
-Accept the line regardless of where the cursor is.
-If this line is
-non-empty, it may be added to the history list for future recall with
-@code{add_history()}.
-If this line is a modified history line, the history line is restored
-to its original state.
-@end ifclear
-
-@item previous-history (C-p)
-Move `back' through the history list, fetching the previous command.
-
-@item next-history (C-n)
-Move `forward' through the history list, fetching the next command.
-
-@item beginning-of-history (M-<)
-Move to the first line in the history.
-
-@item end-of-history (M->)
-Move to the end of the input history, i.e., the line currently
-being entered.
-
-@item 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.
-
-@item forward-search-history (C-s)
-Search forward starting at the current line and moving `down' through
-the the history as necessary. This is an incremental search.
-
-@item non-incremental-reverse-search-history (M-p)
-Search backward starting at the current line and moving `up'
-through the history as necessary using a non-incremental search
-for a string supplied by the user.
-
-@item non-incremental-forward-search-history (M-n)
-Search forward starting at the current line and moving `down'
-through the the history as necessary using a non-incremental search
-for a string supplied by the user.
-
-@item history-search-forward ()
-Search forward through the history for the string of characters
-between the start of the current line and the point.
-The search string must match at the beginning of a history line.
-This is a non-incremental search.
-By default, this command is unbound.
-
-@item history-search-backward ()
-Search backward through the history for the string of characters
-between the start of the current line and the point.
-The search string must match at the beginning of a history line.
-This is a non-incremental search.
-By default, this command is unbound.
-
-@item history-substr-search-forward ()
-Search forward through the history for the string of characters
-between the start of the current line and the point.
-The search string may match anywhere in a history line.
-This is a non-incremental search.
-By default, this command is unbound.
-
-@item history-substr-search-backward ()
-Search backward through the history for the string of characters
-between the start of the current line and the point.
-The search string may match anywhere in a history line.
-This is a non-incremental search.
-By default, this command is unbound.
-
-@item 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 @var{n},
-insert the @var{n}th word from the previous command (the words
-in the previous command begin with word 0). A negative argument
-inserts the @var{n}th word from the end of the previous command.
-Once the argument @var{n} is computed, the argument is extracted
-as if the @samp{!@var{n}} history expansion had been specified.
-
-@item yank-last-arg (M-. or M-_)
-Insert last argument to the previous command (the last word of the
-previous history entry).
-With a numeric argument, behave exactly like @code{yank-nth-arg}.
-Successive calls to @code{yank-last-arg} move back through the history
-list, inserting the last word (or the word specified by the argument to
-the first call) of each line in turn.
-Any numeric argument supplied to these successive calls determines
-the direction to move through the history. A negative argument switches
-the direction through the history (back or forward).
-The history expansion facilities are used to extract the last argument,
-as if the @samp{!$} history expansion had been specified.
-
-@end ftable
-
-@node Commands For Text
-@subsection Commands For Changing Text
-
-@ftable @code
-@item 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 @code{delete-char}, then
-return @sc{eof}.
-
-@item backward-delete-char (Rubout)
-Delete the character behind the cursor. A numeric argument means
-to kill the characters instead of deleting them.
-
-@item 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. By default, this is not bound to a key.
-
-@item quoted-insert (C-q or C-v)
-Add the next character typed to the line verbatim. This is
-how to insert key sequences like @kbd{C-q}, for example.
-
-@ifclear BashFeatures
-@item tab-insert (M-@key{TAB})
-Insert a tab character.
-@end ifclear
-
-@item self-insert (a, b, A, 1, !, @dots{})
-Insert yourself.
-
-@item transpose-chars (C-t)
-Drag the character before the cursor forward over
-the character at the cursor, moving the
-cursor forward as well. If the insertion point
-is at the end of the line, then this
-transposes the last two characters of the line.
-Negative arguments have no effect.
-
-@item transpose-words (M-t)
-Drag the word before point past the word after point,
-moving point past that word as well.
-If the insertion point is at the end of the line, this transposes
-the last two words on the line.
-
-@item upcase-word (M-u)
-Uppercase the current (or following) word. With a negative argument,
-uppercase the previous word, but do not move the cursor.
-
-@item downcase-word (M-l)
-Lowercase the current (or following) word. With a negative argument,
-lowercase the previous word, but do not move the cursor.
-
-@item capitalize-word (M-c)
-Capitalize the current (or following) word. With a negative argument,
-capitalize the previous word, but do not move the cursor.
-
-@item 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
-@code{emacs} mode; @code{vi} mode does overwrite differently.
-Each call to @code{readline()} starts in insert mode.
-
-In overwrite mode, characters bound to @code{self-insert} replace
-the text at point rather than pushing the text to the right.
-Characters bound to @code{backward-delete-char} replace the character
-before point with a space.
-
-By default, this command is unbound.
-
-@end ftable
-
-@node Commands For Killing
-@subsection Killing And Yanking
-
-@ftable @code
-
-@item kill-line (C-k)
-Kill the text from point to the end of the line.
-
-@item backward-kill-line (C-x Rubout)
-Kill backward to the beginning of the line.
-
-@item unix-line-discard (C-u)
-Kill backward from the cursor to the beginning of the current line.
-
-@item kill-whole-line ()
-Kill all characters on the current line, no matter where point is.
-By default, this is unbound.
-
-@item 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 @code{forward-word}.
-
-@item backward-kill-word (M-@key{DEL})
-Kill the word behind point.
-Word boundaries are the same as @code{backward-word}.
-
-@ifset BashFeatures
-@item shell-kill-word ()
-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 @code{shell-forward-word}.
-
-@item shell-backward-kill-word ()
-Kill the word behind point.
-Word boundaries are the same as @code{shell-backward-word}.
-@end ifset
-
-@item 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.
-
-@item 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.
-
-@item delete-horizontal-space ()
-Delete all spaces and tabs around point. By default, this is unbound.
-
-@item kill-region ()
-Kill the text in the current region.
-By default, this command is unbound.
-
-@item copy-region-as-kill ()
-Copy the text in the region to the kill buffer, so it can be yanked
-right away. By default, this command is unbound.
-
-@item copy-backward-word ()
-Copy the word before point to the kill buffer.
-The word boundaries are the same as @code{backward-word}.
-By default, this command is unbound.
-
-@item copy-forward-word ()
-Copy the word following point to the kill buffer.
-The word boundaries are the same as @code{forward-word}.
-By default, this command is unbound.
-
-@item yank (C-y)
-Yank the top of the kill ring into the buffer at point.
-
-@item yank-pop (M-y)
-Rotate the kill-ring, and yank the new top. You can only do this if
-the prior command is @code{yank} or @code{yank-pop}.
-@end ftable
-
-@node Numeric Arguments
-@subsection Specifying Numeric Arguments
-@ftable @code
-
-@item digit-argument (@kbd{M-0}, @kbd{M-1}, @dots{} @kbd{M--})
-Add this digit to the argument already accumulating, or start a new
-argument. @kbd{M--} starts a negative argument.
-
-@item 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 @code{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.
-By default, this is not bound to a key.
-@end ftable
-
-@node Commands For Completion
-@subsection Letting Readline Type For You
-
-@ftable @code
-@item complete (@key{TAB})
-Attempt to perform completion on the text before point.
-The actual completion performed is application-specific.
-@ifset BashFeatures
-Bash attempts completion treating the text as a variable (if the
-text begins with @samp{$}), username (if the text begins with
-@samp{~}), hostname (if the text begins with @samp{@@}), or
-command (including aliases and functions) in turn. If none
-of these produces a match, filename completion is attempted.
-@end ifset
-@ifclear BashFeatures
-The default is filename completion.
-@end ifclear
-
-@item possible-completions (M-?)
-List the possible completions of the text before point.
-When displaying completions, Readline sets the number of columns used
-for display to the value of @code{completion-display-width}, the value of
-the environment variable @env{COLUMNS}, or the screen width, in that order.
-
-@item insert-completions (M-*)
-Insert all completions of the text before point that would have
-been generated by @code{possible-completions}.
-
-@item menu-complete ()
-Similar to @code{complete}, but replaces the word to be completed
-with a single match from the list of possible completions.
-Repeated execution of @code{menu-complete} 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 @code{bell-style})
-and the original text is restored.
-An argument of @var{n} moves @var{n} 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 @key{TAB}, but is unbound
-by default.
-
-@item menu-complete-backward ()
-Identical to @code{menu-complete}, but moves backward through the list
-of possible completions, as if @code{menu-complete} had been given a
-negative argument.
-
-@item delete-char-or-list ()
-Deletes the character under the cursor if not at the beginning or
-end of the line (like @code{delete-char}).
-If at the end of the line, behaves identically to
-@code{possible-completions}.
-This command is unbound by default.
-
-@ifset BashFeatures
-@item complete-filename (M-/)
-Attempt filename completion on the text before point.
-
-@item possible-filename-completions (C-x /)
-List the possible completions of the text before point,
-treating it as a filename.
-
-@item complete-username (M-~)
-Attempt completion on the text before point, treating
-it as a username.
-
-@item possible-username-completions (C-x ~)
-List the possible completions of the text before point,
-treating it as a username.
-
-@item complete-variable (M-$)
-Attempt completion on the text before point, treating
-it as a shell variable.
-
-@item possible-variable-completions (C-x $)
-List the possible completions of the text before point,
-treating it as a shell variable.
-
-@item complete-hostname (M-@@)
-Attempt completion on the text before point, treating
-it as a hostname.
-
-@item possible-hostname-completions (C-x @@)
-List the possible completions of the text before point,
-treating it as a hostname.
-
-@item 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.
-
-@item possible-command-completions (C-x !)
-List the possible completions of the text before point,
-treating it as a command name.
-
-@item dynamic-complete-history (M-@key{TAB})
-Attempt completion on the text before point, comparing
-the text against lines from the history list for possible
-completion matches.
-
-@item dabbrev-expand ()
-Attempt menu completion on the text before point, comparing
-the text against lines from the history list for possible
-completion matches.
-
-@item 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
-(@pxref{Brace Expansion}).
-
-@end ifset
-@end ftable
-
-@node Keyboard Macros
-@subsection Keyboard Macros
-@ftable @code
-
-@item start-kbd-macro (C-x ()
-Begin saving the characters typed into the current keyboard macro.
-
-@item end-kbd-macro (C-x ))
-Stop saving the characters typed into the current keyboard macro
-and save the definition.
-
-@item 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.
-
-@item print-last-kbd-macro ()
-Print the last keboard macro defined in a format suitable for the
-@var{inputrc} file.
-
-@end ftable
-
-@node Miscellaneous Commands
-@subsection Some Miscellaneous Commands
-@ftable @code
-
-@item re-read-init-file (C-x C-r)
-Read in the contents of the @var{inputrc} file, and incorporate
-any bindings or variable assignments found there.
-
-@item abort (C-g)
-Abort the current editing command and
-ring the terminal's bell (subject to the setting of
-@code{bell-style}).
-
-@item do-uppercase-version (M-a, M-b, M-@var{x}, @dots{})
-If the metafied character @var{x} is lowercase, run the command
-that is bound to the corresponding uppercase character.
-
-@item prefix-meta (@key{ESC})
-Metafy the next character typed. This is for keyboards
-without a meta key. Typing @samp{@key{ESC} f} is equivalent to typing
-@kbd{M-f}.
-
-@item undo (C-_ or C-x C-u)
-Incremental undo, separately remembered for each line.
-
-@item revert-line (M-r)
-Undo all changes made to this line. This is like executing the @code{undo}
-command enough times to get back to the beginning.
-
-@ifset BashFeatures
-@item tilde-expand (M-&)
-@end ifset
-@ifclear BashFeatures
-@item tilde-expand (M-~)
-@end ifclear
-Perform tilde expansion on the current word.
-
-@item set-mark (C-@@)
-Set the mark to the point. If a
-numeric argument is supplied, the mark is set to that position.
-
-@item 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.
-
-@item 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.
-
-@item 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.
-
-@item skip-csi-sequence ()
-Read enough characters to consume a multi-key sequence such as those
-defined for keys like Home and End. Such sequences begin with a
-Control Sequence Indicator (CSI), usually ESC-[. If this sequence is
-bound to "\e[", keys producing such sequences will have no effect
-unless explicitly bound to a readline command, instead of inserting
-stray characters into the editing buffer. This is unbound by default,
-but usually bound to ESC-[.
-
-@item insert-comment (M-#)
-Without a numeric argument, the value of the @code{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 @code{comment-begin}, the value is inserted, otherwise
-the characters in @code{comment-begin} are deleted from the beginning of
-the line.
-In either case, the line is accepted as if a newline had been typed.
-@ifset BashFeatures
-The default value of @code{comment-begin} 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.
-@end ifset
-
-@item 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 @var{inputrc} file. This command is unbound by default.
-
-@item dump-variables ()
-Print all of the settable 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 @var{inputrc} file. This command is unbound by default.
-
-@item 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 @var{inputrc} file. This command is unbound by default.
-
-@ifset BashFeatures
-@item 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.
-
-@item 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, a @samp{*} is appended before
-pathname expansion.
-
-@item glob-list-expansions (C-x g)
-The list of expansions that would have been generated by
-@code{glob-expand-word} is displayed, and the line is redrawn.
-If a numeric argument is supplied, a @samp{*} is appended before
-pathname expansion.
-
-@item display-shell-version (C-x C-v)
-Display version information about the current instance of Bash.
-
-@item 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 (@pxref{Shell Expansions}).
-
-@item history-expand-line (M-^)
-Perform history expansion on the current line.
-
-@item magic-space ()
-Perform history expansion on the current line and insert a space
-(@pxref{History Interaction}).
-
-@item alias-expand-line ()
-Perform alias expansion on the current line (@pxref{Aliases}).
-
-@item history-and-alias-expand-line ()
-Perform history and alias expansion on the current line.
-
-@item insert-last-argument (M-. or M-_)
-A synonym for @code{yank-last-arg}.
-
-@item 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.
-
-@item edit-and-execute-command (C-xC-e)
-Invoke an editor on the current command line, and execute the result as shell
-commands.
-Bash attempts to invoke
-@code{$VISUAL}, @code{$EDITOR}, and @code{emacs}
-as the editor, in that order.
-
-@end ifset
-
-@ifclear BashFeatures
-@item emacs-editing-mode (C-e)
-When in @code{vi} command mode, this causes a switch to @code{emacs}
-editing mode.
-
-@item vi-editing-mode (M-C-j)
-When in @code{emacs} editing mode, this causes a switch to @code{vi}
-editing mode.
-
-@end ifclear
-
-@end ftable
-
-@node Readline vi Mode
-@section Readline vi Mode
-
-While the Readline library does not have a full set of @code{vi}
-editing functions, it does contain enough to allow simple editing
-of the line. The Readline @code{vi} mode behaves as specified in
-the @sc{posix} standard.
-
-@ifset BashFeatures
-In order to switch interactively between @code{emacs} and @code{vi}
-editing modes, use the @samp{set -o emacs} and @samp{set -o vi}
-commands (@pxref{The Set Builtin}).
-@end ifset
-@ifclear BashFeatures
-In order to switch interactively between @code{emacs} and @code{vi}
-editing modes, use the command @kbd{M-C-j} (bound to emacs-editing-mode
-when in @code{vi} mode and to vi-editing-mode in @code{emacs} mode).
-@end ifclear
-The Readline default is @code{emacs} mode.
-
-When you enter a line in @code{vi} mode, you are already placed in
-`insertion' mode, as if you had typed an @samp{i}. Pressing @key{ESC}
-switches you into `command' mode, where you can edit the text of the
-line with the standard @code{vi} movement keys, move to previous
-history lines with @samp{k} and subsequent lines with @samp{j}, and
-so forth.
-
-@ifset BashFeatures
-@node Programmable Completion
-@section Programmable Completion
-@cindex programmable completion
-
-When word completion is attempted for an argument to a command for
-which a completion specification (a @var{compspec}) has been defined
-using the @code{complete} builtin (@pxref{Programmable Completion Builtins}),
-the programmable completion facilities are invoked.
-
-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 the empty string (completion attempted at the
-beginning of an empty line), any compspec defined with
-the @option{-E} option to @code{complete} is used.
-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.
-If those searches do not result in a compspec, any compspec defined with
-the @option{-D} option to @code{complete} is used as the default.
-
-Once a compspec has been found, it is used to generate the list of
-matching words.
-If a compspec is not found, the default Bash completion
-described above (@pxref{Commands For Completion}) is performed.
-
-First, the actions specified by the compspec are used.
-Only matches which are prefixed by the word being completed are
-returned.
-When the @option{-f} or @option{-d} option is used for filename or
-directory name completion, the shell variable @env{FIGNORE} is
-used to filter the matches.
-@xref{Bash Variables}, for a description of @env{FIGNORE}.
-
-Any completions specified by a filename expansion pattern to the
-@option{-G} option are generated next.
-The words generated by the pattern need not match the word being completed.
-The @env{GLOBIGNORE} shell variable is not used to filter the matches,
-but the @env{FIGNORE} shell variable is used.
-
-Next, the string specified as the argument to the @option{-W} option
-is considered.
-The string is first split using the characters in the @env{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 (@pxref{Shell Expansions}).
-The results are split using the rules described above
-(@pxref{Word Splitting}).
-The results of the expansion are prefix-matched against the word being
-completed, and the matching words become the possible completions.
-
-After these matches have been generated, any shell function or command
-specified with the @option{-F} and @option{-C} options is invoked.
-When the command or function is invoked, the @env{COMP_LINE},
-@env{COMP_POINT}, @env{COMP_KEY}, and @env{COMP_TYPE} variables are
-assigned values as described above (@pxref{Bash Variables}).
-If a shell function is being invoked, the @env{COMP_WORDS} and
-@env{COMP_CWORD} variables are also set.
-When the function or command is invoked, the first argument ($1) is the
-name of the command whose arguments are being completed, the
-second argument ($2) is the word being completed, and the third argument
-($3) 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.
-
-Any function specified with @option{-F} is invoked first.
-The function may use any of the shell facilities, including the
-@code{compgen} and @code{compopt} builtins described below
-(@pxref{Programmable Completion Builtins}), to generate the matches.
-It must put the possible completions in the @env{COMPREPLY} array
-variable, one per array element.
-
-Next, any command specified with the @option{-C} 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.
-
-After all of the possible completions are generated, any filter
-specified with the @option{-X} option is applied to the list.
-The filter is a pattern as used for pathname expansion; a @samp{&}
-in the pattern is replaced with the text of the word being completed.
-A literal @samp{&} 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 @samp{!} negates the pattern; in this case any completion
-not matching the pattern will be removed.
-
-Finally, any prefix and suffix specified with the @option{-P} and @option{-S}
-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.
-
-If the previously-applied actions do not generate any matches, and the
-@option{-o dirnames} option was supplied to @code{complete} when the
-compspec was defined, directory name completion is attempted.
-
-If the @option{-o plusdirs} option was supplied to @code{complete} when
-the compspec was defined, directory name completion is attempted and any
-matches are added to the results of the other actions.
-
-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 Bash completions are not attempted, and the Readline default
-of filename completion is disabled.
-If the @option{-o bashdefault} option was supplied to @code{complete} when
-the compspec was defined, the default Bash completions are attempted
-if the compspec generates no matches.
-If the @option{-o default} option was supplied to @code{complete} when the
-compspec was defined, Readline's default completion will be performed
-if the compspec (and, if attempted, the default Bash completions)
-generate no matches.
-
-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 @var{mark-directories} Readline variable, regardless
-of the setting of the @var{mark-symlinked-directories} Readline variable.
-
-There is some support for dynamically modifying completions. This is
-most useful when used in combination with a default completion specified
-with @option{-D}. It's possible for shell functions executed as completion
-handlers to indicate that completion should be retried by returning an
-exit status of 124. If a shell function returns 124, and changes
-the compspec associated with the command on which completion is being
-attempted (supplied as the first argument when the function is executed),
-programmable completion restarts from the beginning, with an
-attempt to find a new compspec for that command. This allows a set of
-completions to be built dynamically as completion is attempted, rather than
-being loaded all at once.
-
-For instance, assuming that there is a library of compspecs, each kept in a
-file corresponding to the name of the command, the following default
-completion function would load completions dynamically:
-
-@example
-_completion_loader()
-@{
- . "/etc/bash_completion.d/$1.sh" >/dev/null 2>&1 && return 124
-@}
-complete -D -F _completion_loader
-@end example
-
-@node Programmable Completion Builtins
-@section Programmable Completion Builtins
-@cindex completion builtins
-
-Three builtin commands are available to manipulate the programmable completion
-facilities: one to specify how the arguments to a particular command are to
-be completed, and two to modify the completion as it is happening.
-
-@table @code
-@item compgen
-@btindex compgen
-@example
-@code{compgen [@var{option}] [@var{word}]}
-@end example
-
-Generate possible completion matches for @var{word} according to
-the @var{option}s, which may be any option accepted by the
-@code{complete}
-builtin with the exception of @option{-p} and @option{-r}, and write
-the matches to the standard output.
-When using the @option{-F} or @option{-C} options, the various shell variables
-set by the programmable completion facilities, while available, will not
-have useful values.
-
-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 @var{word} is specified, only those completions matching @var{word}
-will be displayed.
-
-The return value is true unless an invalid option is supplied, or no
-matches were generated.
-
-@item complete
-@btindex complete
-@example
-@code{complete [-abcdefgjksuv] [-o @var{comp-option}] [-DE] [-A @var{action}] [-G @var{globpat}] [-W @var{wordlist}]
-[-F @var{function}] [-C @var{command}] [-X @var{filterpat}]
-[-P @var{prefix}] [-S @var{suffix}] @var{name} [@var{name} @dots{}]}
-@code{complete -pr [-DE] [@var{name} @dots{}]}
-@end example
-
-Specify how arguments to each @var{name} should be completed.
-If the @option{-p} 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 @option{-r} option removes a completion specification for
-each @var{name}, or, if no @var{name}s are supplied, all
-completion specifications.
-The @option{-D} option indicates that the remaining options and actions should
-apply to the ``default'' command completion; that is, completion attempted
-on a command for which no completion has previously been defined.
-The @option{-E} option indicates that the remaining options and actions should
-apply to ``empty'' command completion; that is, completion attempted on a
-blank line.
-
-The process of applying these completion specifications when word completion
-is attempted is described above (@pxref{Programmable Completion}). The
-@option{-D} option takes precedence over @option{-E}.
-
-Other options, if specified, have the following meanings.
-The arguments to the @option{-G}, @option{-W}, and @option{-X} options
-(and, if necessary, the @option{-P} and @option{-S} options)
-should be quoted to protect them from expansion before the
-@code{complete} builtin is invoked.
-
-
-@table @code
-@item -o @var{comp-option}
-The @var{comp-option} controls several aspects of the compspec's behavior
-beyond the simple generation of completions.
-@var{comp-option} may be one of:
-
-@table @code
-
-@item bashdefault
-Perform the rest of the default Bash completions if the compspec
-generates no matches.
-
-@item default
-Use Readline's default filename completion if the compspec generates
-no matches.
-
-@item dirnames
-Perform directory name completion if the compspec generates no matches.
-
-@item filenames
-Tell Readline that the compspec generates filenames, so it can perform any
-filename-specific processing (like adding a slash to directory names
-quoting special characters, or suppressing trailing spaces).
-This option is intended to be used with shell functions specified
-with @option{-F}.
-
-@item noquote
-Tell Readline not to quote the completed words if they are filenames
-(quoting filenames is the default).
-
-@item nospace
-Tell Readline not to append a space (the default) to words completed at
-the end of the line.
-
-@item 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.
-
-@end table
-
-@item -A @var{action}
-The @var{action} may be one of the following to generate a list of possible
-completions:
-
-@table @code
-@item alias
-Alias names. May also be specified as @option{-a}.
-
-@item arrayvar
-Array variable names.
-
-@item binding
-Readline key binding names (@pxref{Bindable Readline Commands}).
-
-@item builtin
-Names of shell builtin commands. May also be specified as @option{-b}.
-
-@item command
-Command names. May also be specified as @option{-c}.
-
-@item directory
-Directory names. May also be specified as @option{-d}.
-
-@item disabled
-Names of disabled shell builtins.
-
-@item enabled
-Names of enabled shell builtins.
-
-@item export
-Names of exported shell variables. May also be specified as @option{-e}.
-
-@item file
-File names. May also be specified as @option{-f}.
-
-@item function
-Names of shell functions.
-
-@item group
-Group names. May also be specified as @option{-g}.
-
-@item helptopic
-Help topics as accepted by the @code{help} builtin (@pxref{Bash Builtins}).
-
-@item hostname
-Hostnames, as taken from the file specified by the
-@env{HOSTFILE} shell variable (@pxref{Bash Variables}).
-
-@item job
-Job names, if job control is active. May also be specified as @option{-j}.
-
-@item keyword
-Shell reserved words. May also be specified as @option{-k}.
-
-@item running
-Names of running jobs, if job control is active.
-
-@item service
-Service names. May also be specified as @option{-s}.
-
-@item setopt
-Valid arguments for the @option{-o} option to the @code{set} builtin
-(@pxref{The Set Builtin}).
-
-@item shopt
-Shell option names as accepted by the @code{shopt} builtin
-(@pxref{Bash Builtins}).
-
-@item signal
-Signal names.
-
-@item stopped
-Names of stopped jobs, if job control is active.
-
-@item user
-User names. May also be specified as @option{-u}.
-
-@item variable
-Names of all shell variables. May also be specified as @option{-v}.
-@end table
-
-@item -C @var{command}
-@var{command} is executed in a subshell environment, and its output is
-used as the possible completions.
-
-@item -F @var{function}
-The shell function @var{function} is executed in the current shell
-environment.
-When it is executed, $1 is the name of the command whose arguments are
-being completed, $2 is the word being completed, and $3 is the word
-preceding the word being completed, as described above
-(@pxref{Programmable Completion}).
-When it finishes, the possible completions are retrieved from the value
-of the @env{COMPREPLY} array variable.
-
-@item -G @var{globpat}
-The filename expansion pattern @var{globpat} is expanded to generate
-the possible completions.
-
-@item -P @var{prefix}
-@var{prefix} is added at the beginning of each possible completion
-after all other options have been applied.
-
-@item -S @var{suffix}
-@var{suffix} is appended to each possible completion
-after all other options have been applied.
-
-@item -W @var{wordlist}
-The @var{wordlist} is split using the characters in the
-@env{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.
-
-@item -X @var{filterpat}
-@var{filterpat} 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
-@var{filterpat} is removed from the list.
-A leading @samp{!} in @var{filterpat} negates the pattern; in this
-case, any completion not matching @var{filterpat} is removed.
-@end table
-
-The return value is true unless an invalid option is supplied, an option
-other than @option{-p} or @option{-r} is supplied without a @var{name}
-argument, an attempt is made to remove a completion specification for
-a @var{name} for which no specification exists, or
-an error occurs adding a completion specification.
-
-@item compopt
-@btindex compopt
-@example
-@code{compopt} [-o @var{option}] [-DE] [+o @var{option}] [@var{name}]
-@end example
-Modify completion options for each @var{name} according to the
-@var{option}s, or for the currently-executing completion if no @var{name}s
-are supplied.
-If no @var{option}s are given, display the completion options for each
-@var{name} or the current completion.
-The possible values of @var{option} are those valid for the @code{complete}
-builtin described above.
-The @option{-D} option indicates that the remaining options should
-apply to the ``default'' command completion; that is, completion attempted
-on a command for which no completion has previously been defined.
-The @option{-E} option indicates that the remaining options should
-apply to ``empty'' command completion; that is, completion attempted on a
-blank line.
-
-The @option{-D} option takes precedence over @option{-E}.
-
-The return value is true unless an invalid option is supplied, an attempt
-is made to modify the options for a @var{name} for which no completion
-specification exists, or an output error occurs.
-
-@end table
-
-@node A Programmable Completion Example
-@section A Programmable Completion Example
-
-The most common way to obtain additional completion functionality beyond
-the default actions @code{complete} and @code{compgen} provide is to use
-a shell function and bind it to a particular command using @code{complete -F}.
-
-The following function provides completions for the @code{cd} builtin.
-It is a reasonably good example of what shell functions must do when
-used for completion. This function uses the word passsed as @code{$2}
-to determine the directory name to complete. You can also use the
-@code{COMP_WORDS} array variable; the current word is indexed by the
-@code{COMP_CWORD} variable.
-
-The function relies on the @code{complete} and @code{compgen} builtins
-to do much of the work, adding only the things that the Bash @code{cd}
-does beyond accepting basic directory names:
-tilde expansion (@pxref{Tilde Expansion}),
-searching directories in @var{$CDPATH}, which is described above
-(@pxref{Bourne Shell Builtins}),
-and basic support for the @code{cdable_vars} shell option
-(@pxref{The Shopt Builtin}).
-@code{_comp_cd} modifies the value of @var{IFS} so that it contains only
-a newline to accommodate file names containing spaces and tabs --
-@code{compgen} prints the possible completions it generates one per line.
-
-Possible completions go into the @var{COMPREPLY} array variable, one
-completion per array element. The programmable completion system retrieves
-the completions from there when the function returns.
-
-@example
-# A completion function for the cd builtin
-# based on the cd completion function from the bash_completion package
-_comp_cd()
-@{
- local IFS=$' \t\n' # normalize IFS
- local cur _skipdot _cdpath
- local i j k
-
- # Tilde expansion, with side effect of expanding tilde to full pathname
- case "$2" in
- \~*) eval cur="$2" ;;
- *) cur=$2 ;;
- esac
-
- # no cdpath or absolute pathname -- straight directory completion
- if [[ -z "$@{CDPATH:-@}" ]] || [[ "$cur" == @@(./*|../*|/*) ]]; then
- # compgen prints paths one per line; could also use while loop
- IFS=$'\n'
- COMPREPLY=( $(compgen -d -- "$cur") )
- IFS=$' \t\n'
- # CDPATH+directories in the current directory if not in CDPATH
- else
- IFS=$'\n'
- _skipdot=false
- # preprocess CDPATH to convert null directory names to .
- _cdpath=$@{CDPATH/#:/.:@}
- _cdpath=$@{_cdpath//::/:.:@}
- _cdpath=$@{_cdpath/%:/:.@}
- for i in $@{_cdpath//:/$'\n'@}; do
- if [[ $i -ef . ]]; then _skipdot=true; fi
- k="$@{#COMPREPLY[@@]@}"
- for j in $( compgen -d -- "$i/$cur" ); do
- COMPREPLY[k++]=$@{j#$i/@} # cut off directory
- done
- done
- $_skipdot || COMPREPLY+=( $(compgen -d -- "$cur") )
- IFS=$' \t\n'
- fi
-
- # variable names if appropriate shell option set and no completions
- if shopt -q cdable_vars && [[ $@{#COMPREPLY[@@]@} -eq 0 ]]; then
- COMPREPLY=( $(compgen -v -- "$cur") )
- fi
-
- return 0
-@}
-@end example
-
-We install the completion function using the @option{-F} option to
-@code{complete}:
-
-@example
-# Tell readline to quote appropriate and append slashes to directories;
-# use the bash default completion for other arguments
-complete -o filenames -o nospace -o bashdefault -F _comp_cd cd
-@end example
-
-@noindent
-Since we'd like Bash and Readline to take care of some
-of the other details for us, we use several other options to tell Bash
-and Readline what to do. The @option{-o filenames} option tells Readline
-that the possible completions should be treated as filenames, and quoted
-appropriately. That option will also cause Readline to append a slash to
-filenames it can determine are directories (which is why we might want to
-extend @code{_comp_cd} to append a slash if we're using directories found
-via @var{CDPATH}: Readline can't tell those completions are directories).
-The @option{-o nospace} option tells Readline to not append a space
-character to the directory name, in case we want to append to it.
-The @option{-o bashdefault} option brings in the rest of the "Bash default"
-completions -- possible completion that Bash adds to the default Readline
-set. These include things like command name completion, variable completion
-for words beginning with @samp{@{}, completions containing pathname
-expansion patterns (@pxref{Filename Expansion}), and so on.
-
-Once installed using @code{complete}, @code{_comp_cd} will be called every
-time we attempt word completion for a @code{cd} command.
-
-Many more examples -- an extensive collection of completions for most of
-the common GNU, Unix, and Linux commands -- are available as part of the
-bash_completion project. This is installed by default on many GNU/Linux
-distributions. Originally written by Ian Macdonald, the project now lives
-at @url{http://bash-completion.alioth.debian.org/}. There are ports for
-other systems such as Solaris and Mac OS X.
-
-An older version of the bash_completion package is distributed with bash
-in the @file{examples/complete} subdirectory.
-
-@end ifset
+++ /dev/null
-@ignore
-Copyright (C) 1988-2011 Free Software Foundation, Inc.
-@end ignore
-
-@set EDITION 6.2
-@set VERSION 6.2
-@set UPDATED December 21 2011
-@set UPDATED-MONTH December 2011
-
-@set LASTCHANGE Wed Dec 21 21:04:12 EST 2011
+++ /dev/null
-/* history.c -- standalone history library */
-
-/* Copyright (C) 1989-2011 Free Software Foundation, Inc.
-
- This file contains the GNU History Library (History), a set of
- routines for managing the text of previously typed lines.
-
- History is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- History 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 History. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/* 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 careful, 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];
-}
-
-HIST_ENTRY *
-alloc_history_entry (string, ts)
- char *string;
- char *ts;
-{
- HIST_ENTRY *temp;
-
- temp = (HIST_ENTRY *)xmalloc (sizeof (HIST_ENTRY));
-
- temp->line = string ? savestring (string) : string;
- temp->data = (char *)NULL;
- temp->timestamp = ts;
-
- return temp;
-}
-
-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) strtol (ts + 1, (char **)NULL, 10); /* 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 = alloc_history_entry (string, 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;
-
- if (string == 0)
- return;
- 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;
- xfree (hist);
- return (x);
-}
-
-HIST_ENTRY *
-copy_history_entry (hist)
- HIST_ENTRY *hist;
-{
- HIST_ENTRY *ret;
- char *ts;
-
- if (hist == 0)
- return hist;
-
- ret = alloc_history_entry (hist->line, (char *)NULL);
-
- ts = hist->timestamp ? savestring (hist->timestamp) : hist->timestamp;
- ret->timestamp = ts;
-
- ret->data = hist->data;
-
- return ret;
-}
-
-/* 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;
-}
+++ /dev/null
-/* isearch.c - incremental searching */
-
-/* **************************************************************** */
-/* */
-/* I-Search and Searching */
-/* */
-/* **************************************************************** */
-
-/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library (Readline), a library
- for reading lines of text with interactive input and history editing.
-
- Readline is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Readline is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#include <stdio.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# include "ansi_stdlib.h"
-#endif
-
-#include "rldefs.h"
-#include "rlmbutil.h"
-
-#include "readline.h"
-#include "history.h"
-
-#include "rlprivate.h"
-#include "xmalloc.h"
-
-/* Variables exported to other files in the readline library. */
-char *_rl_isearch_terminators = (char *)NULL;
-
-_rl_search_cxt *_rl_iscxt = 0;
-
-/* Variables imported from other files in the readline library. */
-extern HIST_ENTRY *_rl_saved_line_for_history;
-
-static int rl_search_history PARAMS((int, int));
-
-static _rl_search_cxt *_rl_isearch_init PARAMS((int));
-static void _rl_isearch_fini PARAMS((_rl_search_cxt *));
-static int _rl_isearch_cleanup PARAMS((_rl_search_cxt *, int));
-
-/* Last line found by the current incremental search, so we don't `find'
- identical lines many times in a row. Now part of isearch context. */
-/* static char *prev_line_found; */
-
-/* Last search string and its length. */
-static char *last_isearch_string;
-static int last_isearch_string_len;
-
-static char * const default_isearch_terminators = "\033\012";
-
-_rl_search_cxt *
-_rl_scxt_alloc (type, flags)
- int type, flags;
-{
- _rl_search_cxt *cxt;
-
- cxt = (_rl_search_cxt *)xmalloc (sizeof (_rl_search_cxt));
-
- cxt->type = type;
- cxt->sflags = flags;
-
- cxt->search_string = 0;
- cxt->search_string_size = cxt->search_string_index = 0;
-
- cxt->lines = 0;
- cxt->allocated_line = 0;
- cxt->hlen = cxt->hindex = 0;
-
- cxt->save_point = rl_point;
- cxt->save_mark = rl_mark;
- cxt->save_line = where_history ();
- cxt->last_found_line = cxt->save_line;
- cxt->prev_line_found = 0;
-
- cxt->save_undo_list = 0;
-
- cxt->keymap = _rl_keymap;
- cxt->okeymap = _rl_keymap;
-
- cxt->history_pos = 0;
- cxt->direction = 0;
-
- cxt->prevc = cxt->lastc = 0;
-
- cxt->sline = 0;
- cxt->sline_len = cxt->sline_index = 0;
-
- cxt->search_terminators = 0;
-
- return cxt;
-}
-
-void
-_rl_scxt_dispose (cxt, flags)
- _rl_search_cxt *cxt;
- int flags;
-{
- FREE (cxt->search_string);
- FREE (cxt->allocated_line);
- FREE (cxt->lines);
-
- xfree (cxt);
-}
-
-/* Search backwards through the history looking for a string which is typed
- interactively. Start with the current line. */
-int
-rl_reverse_search_history (sign, key)
- int sign, key;
-{
- return (rl_search_history (-sign, key));
-}
-
-/* Search forwards through the history looking for a string which is typed
- interactively. Start with the current line. */
-int
-rl_forward_search_history (sign, key)
- int sign, key;
-{
- return (rl_search_history (sign, key));
-}
-
-/* Display the current state of the search in the echo-area.
- SEARCH_STRING contains the string that is being searched for,
- DIRECTION is zero for forward, or non-zero for reverse,
- WHERE is the history list number of the current line. If it is
- -1, then this line is the starting one. */
-static void
-rl_display_search (search_string, 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);
- xfree (message);
- (*rl_redisplay_function) ();
-}
-
-static _rl_search_cxt *
-_rl_isearch_init (direction)
- int direction;
-{
- _rl_search_cxt *cxt;
- register int i;
- HIST_ENTRY **hlist;
-
- cxt = _rl_scxt_alloc (RL_SEARCH_ISEARCH, 0);
- if (direction < 0)
- cxt->sflags |= SF_REVERSE;
-
- cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
- : default_isearch_terminators;
-
- /* Create an arrary of pointers to the lines that we want to search. */
- hlist = history_list ();
- rl_maybe_replace_line ();
- i = 0;
- if (hlist)
- for (i = 0; hlist[i]; i++);
-
- /* Allocate space for this many lines, +1 for the current input line,
- and remember those lines. */
- cxt->lines = (char **)xmalloc ((1 + (cxt->hlen = i)) * sizeof (char *));
- for (i = 0; i < cxt->hlen; i++)
- cxt->lines[i] = hlist[i]->line;
-
- if (_rl_saved_line_for_history)
- cxt->lines[i] = _rl_saved_line_for_history->line;
- else
- {
- /* Keep track of this so we can free it. */
- cxt->allocated_line = (char *)xmalloc (1 + strlen (rl_line_buffer));
- strcpy (cxt->allocated_line, &rl_line_buffer[0]);
- cxt->lines[i] = cxt->allocated_line;
- }
-
- cxt->hlen++;
-
- /* The line where we start the search. */
- cxt->history_pos = cxt->save_line;
-
- rl_save_prompt ();
-
- /* Initialize search parameters. */
- cxt->search_string = (char *)xmalloc (cxt->search_string_size = 128);
- cxt->search_string[cxt->search_string_index = 0] = '\0';
-
- /* Normalize DIRECTION into 1 or -1. */
- cxt->direction = (direction >= 0) ? 1 : -1;
-
- cxt->sline = rl_line_buffer;
- cxt->sline_len = strlen (cxt->sline);
- cxt->sline_index = rl_point;
-
- _rl_iscxt = cxt; /* save globally */
-
- return cxt;
-}
-
-static void
-_rl_isearch_fini (cxt)
- _rl_search_cxt *cxt;
-{
- /* First put back the original state. */
- strcpy (rl_line_buffer, cxt->lines[cxt->save_line]);
-
- rl_restore_prompt ();
-
- /* Save the search string for possible later use. */
- FREE (last_isearch_string);
- last_isearch_string = cxt->search_string;
- last_isearch_string_len = cxt->search_string_index;
- cxt->search_string = 0;
-
- if (cxt->last_found_line < cxt->save_line)
- rl_get_previous_history (cxt->save_line - cxt->last_found_line, 0);
- else
- rl_get_next_history (cxt->last_found_line - cxt->save_line, 0);
-
- /* If the string was not found, put point at the end of the last matching
- line. If last_found_line == orig_line, we didn't find any matching
- history lines at all, so put point back in its original position. */
- if (cxt->sline_index < 0)
- {
- if (cxt->last_found_line == cxt->save_line)
- cxt->sline_index = cxt->save_point;
- else
- cxt->sline_index = strlen (rl_line_buffer);
- rl_mark = cxt->save_mark;
- }
-
- rl_point = cxt->sline_index;
- /* Don't worry about where to put the mark here; rl_get_previous_history
- and rl_get_next_history take care of it. */
-
- rl_clear_message ();
-}
-
-int
-_rl_search_getchar (cxt)
- _rl_search_cxt *cxt;
-{
- int c;
-
- /* Read a key and decide how to proceed. */
- RL_SETSTATE(RL_STATE_MOREINPUT);
- c = cxt->lastc = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_MOREINPUT);
-
-#if defined (HANDLE_MULTIBYTE)
- /* This ends up with C (and LASTC) being set to the last byte of the
- multibyte character. In most cases c == lastc == mb[0] */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- c = cxt->lastc = _rl_read_mbstring (cxt->lastc, cxt->mb, MB_LEN_MAX);
-#endif
-
- return c;
-}
-
-#define ENDSRCH_CHAR(c) \
- ((CTRL_CHAR (c) || META_CHAR (c) || (c) == RUBOUT) && ((c) != CTRL ('G')))
-
-/* Process just-read character C according to isearch context CXT. Return
- -1 if the caller should just free the context and return, 0 if we should
- break out of the loop, and 1 if we should continue to read characters. */
-int
-_rl_isearch_dispatch (cxt, c)
- _rl_search_cxt *cxt;
- int c;
-{
- int n, wstart, wlen, limit, cval;
- rl_command_func_t *f;
- Keymap m;
-
- f = (rl_command_func_t *)NULL;
-
- if (c < 0)
- {
- cxt->sflags |= SF_FAILED;
- cxt->history_pos = cxt->last_found_line;
- return -1;
- }
-
- /* If we are moving into a new keymap, modify cxt->keymap and go on.
- This can be a problem if c == ESC and we want to terminate the
- incremental search, so we check */
- if (c >= 0 && cxt->keymap[c].type == ISKMAP && strchr (cxt->search_terminators, cxt->lastc) == 0)
- {
- /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
- takes microseconds, so multiply by 1000. If we don't get any
- additional input and we this keymap shadows another function, process
- that key as if it was all we read. */
- if (_rl_keyseq_timeout > 0 &&
- RL_ISSTATE (RL_STATE_CALLBACK) == 0 &&
- RL_ISSTATE (RL_STATE_INPUTPENDING) == 0 &&
- _rl_pushed_input_available () == 0 &&
- ((Keymap)(cxt->keymap[c].function))[ANYOTHERKEY].function &&
- _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
- goto add_character;
-
- cxt->okeymap = cxt->keymap;
- cxt->keymap = FUNCTION_TO_KEYMAP (cxt->keymap, c);
- cxt->sflags |= SF_CHGKMAP;
- /* XXX - we should probably save this sequence, so we can do
- something useful if this doesn't end up mapping to a command we
- interpret here. Right now we just save the most recent character
- that caused the index into a new keymap. */
- cxt->prevc = c;
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- if (cxt->mb[1] == 0)
- {
- cxt->pmb[0] = c; /* XXX should be == cxt->mb[0] */
- cxt->pmb[1] = '\0';
- }
- else
- memcpy (cxt->pmb, cxt->mb, sizeof (cxt->pmb));
- }
-#endif
- return 1;
- }
-
-add_character:
-
- /* Translate the keys we do something with to opcodes. */
- if (c >= 0 && cxt->keymap[c].type == ISFUNC)
- {
- f = cxt->keymap[c].function;
-
- if (f == rl_reverse_search_history)
- cxt->lastc = (cxt->sflags & SF_REVERSE) ? -1 : -2;
- else if (f == rl_forward_search_history)
- cxt->lastc = (cxt->sflags & SF_REVERSE) ? -2 : -1;
- else if (f == rl_rubout)
- cxt->lastc = -3;
- else if (c == CTRL ('G') || f == rl_abort)
- cxt->lastc = -4;
- else if (c == CTRL ('W') || f == rl_unix_word_rubout) /* XXX */
- cxt->lastc = -5;
- else if (c == CTRL ('Y') || f == rl_yank) /* XXX */
- cxt->lastc = -6;
- }
-
- /* If we changed the keymap earlier while translating a key sequence into
- a command, restore it now that we've succeeded. */
- if (cxt->sflags & SF_CHGKMAP)
- {
- cxt->keymap = cxt->okeymap;
- cxt->sflags &= ~SF_CHGKMAP;
- /* If we indexed into a new keymap, but didn't map to a command that
- affects the search (lastc > 0), and the character that mapped to a
- new keymap would have ended the search (ENDSRCH_CHAR(cxt->prevc)),
- handle that now as if the previous char would have ended the search
- and we would have read the current character. */
- /* XXX - should we check cxt->mb? */
- if (cxt->lastc > 0 && ENDSRCH_CHAR (cxt->prevc))
- {
- rl_stuff_char (cxt->lastc);
- rl_execute_next (cxt->prevc);
- /* XXX - do we insert everything in cxt->pmb? */
- return (0);
- }
- /* Otherwise, if the current character is mapped to self-insert or
- nothing (i.e., not an editing command), and the previous character
- was a keymap index, then we need to insert both the previous
- character and the current character into the search string. */
- else if (cxt->lastc > 0 && cxt->prevc > 0 &&
- cxt->keymap[cxt->prevc].type == ISKMAP &&
- (f == 0 || f == rl_insert))
- {
- /* Make lastc be the next character read */
- /* XXX - do we insert everything in cxt->mb? */
- rl_execute_next (cxt->lastc);
- /* Dispatch on the previous character (insert into search string) */
- cxt->lastc = cxt->prevc;
-#if defined (HANDLE_MULTIBYTE)
- /* Have to overwrite cxt->mb here because dispatch uses it below */
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- if (cxt->pmb[1] == 0)
- {
- cxt->mb[0] = cxt->lastc; /* == cxt->prevc */
- cxt->mb[1] = '\0';
- }
- else
- memcpy (cxt->mb, cxt->pmb, sizeof (cxt->mb));
- }
-#endif
- cxt->prevc = 0;
- }
- else if (cxt->lastc > 0 && cxt->prevc > 0 && f && f != rl_insert)
- {
- rl_stuff_char (cxt->lastc);
- rl_execute_next (cxt->prevc);
- /* XXX - do we insert everything in cxt->pmb? */
- return (0);
- }
- }
-
- /* The characters in isearch_terminators (set from the user-settable
- variable isearch-terminators) are used to terminate the search but
- not subsequently execute the character as a command. The default
- value is "\033\012" (ESC and C-J). */
- if (cxt->lastc > 0 && strchr (cxt->search_terminators, cxt->lastc))
- {
- /* ESC still terminates the search, but if there is pending
- input or if input arrives within 0.1 seconds (on systems
- with select(2)) it is used as a prefix character
- with rl_execute_next. WATCH OUT FOR THIS! This is intended
- to allow the arrow keys to be used like ^F and ^B are used
- to terminate the search and execute the movement command.
- XXX - since _rl_input_available depends on the application-
- settable keyboard timeout value, this could alternatively
- use _rl_input_queued(100000) */
- if (cxt->lastc == ESC && _rl_input_available ())
- rl_execute_next (ESC);
- return (0);
- }
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
- {
- if (cxt->lastc >= 0 && (cxt->mb[0] && cxt->mb[1] == '\0') && ENDSRCH_CHAR (cxt->lastc))
- {
- /* This sets rl_pending_input to LASTC; it will be picked up the next
- time rl_read_key is called. */
- rl_execute_next (cxt->lastc);
- return (0);
- }
- }
- else
-#endif
- if (cxt->lastc >= 0 && ENDSRCH_CHAR (cxt->lastc))
- {
- /* This sets rl_pending_input to LASTC; it will be picked up the next
- time rl_read_key is called. */
- rl_execute_next (cxt->lastc);
- return (0);
- }
-
- /* Now dispatch on the character. `Opcodes' affect the search string or
- state. Other characters are added to the string. */
- switch (cxt->lastc)
- {
- /* search again */
- case -1:
- if (cxt->search_string_index == 0)
- {
- if (last_isearch_string)
- {
- cxt->search_string_size = 64 + last_isearch_string_len;
- cxt->search_string = (char *)xrealloc (cxt->search_string, cxt->search_string_size);
- strcpy (cxt->search_string, last_isearch_string);
- cxt->search_string_index = last_isearch_string_len;
- rl_display_search (cxt->search_string, (cxt->sflags & 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;
-
- if (cxt->mb[0] == 0 || cxt->mb[1] == 0)
- cxt->search_string[cxt->search_string_index++] = cxt->mb[0];
- else
- for (j = 0, l = RL_STRLEN (cxt->mb); j < l; )
- cxt->search_string[cxt->search_string_index++] = cxt->mb[j++];
- }
- else
-#endif
- cxt->search_string[cxt->search_string_index++] = cxt->lastc; /* XXX - was c instead of lastc */
- cxt->search_string[cxt->search_string_index] = '\0';
- break;
- }
-
- for (cxt->sflags &= ~(SF_FOUND|SF_FAILED);; )
- {
- limit = cxt->sline_len - cxt->search_string_index + 1;
-
- /* Search the current line. */
- while ((cxt->sflags & SF_REVERSE) ? (cxt->sline_index >= 0) : (cxt->sline_index < limit))
- {
- if (STREQN (cxt->search_string, cxt->sline + cxt->sline_index, cxt->search_string_index))
- {
- cxt->sflags |= SF_FOUND;
- break;
- }
- else
- cxt->sline_index += cxt->direction;
- }
- if (cxt->sflags & SF_FOUND)
- break;
-
- /* Move to the next line, but skip new copies of the line
- we just found and lines shorter than the string we're
- searching for. */
- do
- {
- /* Move to the next line. */
- cxt->history_pos += cxt->direction;
-
- /* At limit for direction? */
- if ((cxt->sflags & SF_REVERSE) ? (cxt->history_pos < 0) : (cxt->history_pos == cxt->hlen))
- {
- cxt->sflags |= SF_FAILED;
- break;
- }
-
- /* We will need these later. */
- cxt->sline = cxt->lines[cxt->history_pos];
- cxt->sline_len = strlen (cxt->sline);
- }
- while ((cxt->prev_line_found && STREQ (cxt->prev_line_found, cxt->lines[cxt->history_pos])) ||
- (cxt->search_string_index > cxt->sline_len));
-
- if (cxt->sflags & SF_FAILED)
- break;
-
- /* Now set up the line for searching... */
- cxt->sline_index = (cxt->sflags & SF_REVERSE) ? cxt->sline_len - cxt->search_string_index : 0;
- }
-
- if (cxt->sflags & SF_FAILED)
- {
- /* We cannot find the search string. Ding the bell. */
- rl_ding ();
- cxt->history_pos = cxt->last_found_line;
- 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
+++ /dev/null
-/* misc.c -- miscellaneous bindable readline functions. */
-
-/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library (Readline), a library
- for reading lines of text with interactive input and history editing.
-
- Readline is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Readline is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#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));
-
-extern int history_offset;
-
-/* 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);
- if (key < 0)
- return -1;
- 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;
- }
-
- return r;
-}
-
-/* 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);
-
- xfree (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);
- xfree (temp->line);
- FREE (temp->timestamp);
- xfree (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
-}
-
-/* Process and free undo lists attached to each history entry prior to the
- current entry, inclusive, reverting each line to its saved state. This
- is destructive, and state about the current line is lost. This is not
- intended to be called while actively editing, and the current line is
- not assumed to have been added to the history list. */
-void
-_rl_revert_all_lines ()
-{
- int hpos;
- HIST_ENTRY *entry;
- UNDO_LIST *ul, *saved_undo_list;
- char *lbuf;
-
- lbuf = savestring (rl_line_buffer);
- saved_undo_list = rl_undo_list;
- hpos = where_history ();
-
- entry = (hpos == history_length) ? previous_history () : current_history ();
- while (entry)
- {
- if (ul = (UNDO_LIST *)entry->data)
- {
- if (ul == saved_undo_list)
- saved_undo_list = 0;
- /* Set up rl_line_buffer and other variables from history entry */
- rl_replace_from_history (entry, 0); /* entry->line is now current */
- /* Undo all changes to this history entry */
- while (rl_undo_list)
- rl_do_undo ();
- /* And copy the reverted line back to the history entry, preserving
- the timestamp. */
- FREE (entry->line);
- entry->line = savestring (rl_line_buffer);
- entry->data = 0;
- }
- entry = previous_history ();
- }
-
- /* Restore history state */
- rl_undo_list = saved_undo_list; /* may have been set to null */
- history_set_pos (hpos);
-
- /* reset the line buffer */
- rl_replace_line (lbuf, 0);
- _rl_set_the_line ();
-
- /* and clean up */
- xfree (lbuf);
-}
-
-/* Free the history list, including private readline data and take care
- of pointer aliases to history data. Resets rl_undo_list if it points
- to an UNDO_LIST * saved as some history entry's data member. This
- should not be called while editing is active. */
-void
-rl_clear_history ()
-{
- HIST_ENTRY **hlist, *hent;
- register int i;
- UNDO_LIST *ul, *saved_undo_list;
-
- saved_undo_list = rl_undo_list;
- hlist = history_list (); /* direct pointer, not copy */
-
- for (i = 0; i < history_length; i++)
- {
- hent = hlist[i];
- if (ul = (UNDO_LIST *)hent->data)
- {
- if (ul == saved_undo_list)
- saved_undo_list = 0;
- _rl_free_undo_list (ul);
- hent->data = 0;
- }
- _rl_free_history_entry (hent);
- }
-
- history_offset = history_length = 0;
- rl_undo_list = saved_undo_list; /* should be NULL */
-}
-
-/* **************************************************************** */
-/* */
-/* 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_insert_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;
-}
+++ /dev/null
-/* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
-
-/* Copyright (C) 1987-2012 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library (Readline), a library
- for reading lines of text with interactive input and history editing.
-
- Readline is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Readline is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include "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 _rl_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 _rl_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;
-
-int rl_executing_key;
-char *rl_executing_keyseq = 0;
-int _rl_executing_keyseq_size = 0;
-
-/* Timeout (specified in milliseconds) when reading characters making up an
- ambiguous multiple-key sequence */
-int _rl_keyseq_timeout = 500;
-
-#define RESIZE_KEYSEQ_BUFFER() \
- do \
- { \
- if (rl_key_sequence_length + 2 >= _rl_executing_keyseq_size) \
- { \
- _rl_executing_keyseq_size += 16; \
- rl_executing_keyseq = xrealloc (rl_executing_keyseq, _rl_executing_keyseq_size); \
- } \
- } \
- while (0);
-
-/* Forward declarations used by the display, termcap, and history code. */
-
-/* **************************************************************** */
-/* */
-/* `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;
-
-/* Non-zero means to go through the history list at every newline (or
- whenever rl_done is set and readline returns) and revert each line to
- its initial state. */
-int _rl_revert_all_at_newline = 0;
-
-/* Non-zero means to honor the termios ECHOCTL bit and echo control
- characters corresponding to keyboard-generated signals. */
-int _rl_echo_control_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 0
- int in_callback;
-#endif
-
- /* If we are at EOF return a NULL string. */
- if (rl_pending_input == EOF)
- {
- rl_clear_pending_input ();
- return ((char *)NULL);
- }
-
-#if 0
- /* If readline() is called after installing a callback handler, temporarily
- turn off the callback state to avoid ensuing messiness. Patch supplied
- by the gdb folks. XXX -- disabled. This can be fooled and readline
- left in a strange state by a poorly-timed longjmp. */
- if (in_callback = RL_ISSTATE (RL_STATE_CALLBACK))
- RL_UNSETSTATE (RL_STATE_CALLBACK);
-#endif
-
- 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
-
-#if 0
- if (in_callback)
- RL_SETSTATE (RL_STATE_CALLBACK);
-#endif
-
-#if HAVE_DECL_AUDIT_TTY && defined (ENABLE_TTY_AUDIT_SUPPORT)
- if (value)
- _rl_audit_tty (value);
-#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;
-
- /* Enable the meta key only for the duration of readline(), if this
- terminal has one. */
- if (_rl_enable_meta)
- _rl_enable_meta_key ();
-
- 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 (_rl_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);
- xfree (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_insert_mode (1, 'i');
-#endif /* VI_MODE */
-
- if (rl_pre_input_hook)
- (*rl_pre_input_hook) ();
-
- RL_CHECK_SIGNALS ();
-}
-
-STATIC_CALLBACK char *
-readline_internal_teardown (eof)
- int eof;
-{
- char *temp;
- HIST_ENTRY *entry;
-
- RL_CHECK_SIGNALS ();
-
- /* 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);
- xfree (temp);
- }
-
- if (_rl_revert_all_at_newline)
- _rl_revert_all_lines ();
-
- /* 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 ();
-
- /* Disable the meta key, if this terminal has one. */
- _rl_disable_meta_key ();
-
- /* 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 (_rl_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
- _rl_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_executing_keyseq[0] = 0;
- }
-
- RL_SETSTATE(RL_STATE_READCMD);
- c = rl_read_key ();
- RL_UNSETSTATE(RL_STATE_READCMD);
-
- /* look at input.c:rl_getc() for the circumstances under which this will
- be returned; punt immediately on read error without converting it to
- a newline. */
- if (c == READERR)
- {
-#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)
- 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);
- RL_CHECK_SIGNALS ();
-
- /* 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;
-{
- xfree (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 */
- /* 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);
- if (nkey < 0)
- {
- _rl_abort_internal ();
- return -1;
- }
- r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg);
- cxt->flags |= KSEQ_DISPATCHED;
- }
- else
- r = cxt->childval;
-
- /* For now */
- if (r != -3) /* don't do this if we indicate there will be other matches */
- r = _rl_subseq_result (r, cxt->oldmap, cxt->okey, (cxt->flags & KSEQ_SUBSEQ));
-
- RL_CHECK_SIGNALS ();
- 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);
- RESIZE_KEYSEQ_BUFFER ();
- rl_executing_keyseq[rl_key_sequence_length++] = ESC;
- map = FUNCTION_TO_KEYMAP (map, ESC);
- key = UNMETA (key);
- return (_rl_dispatch (key, map));
- }
- 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_executing_key = key;
-
- RESIZE_KEYSEQ_BUFFER();
- rl_executing_keyseq[rl_key_sequence_length++] = key;
- rl_executing_keyseq[rl_key_sequence_length] = '\0';
-
- rl_dispatching = 1;
- RL_SETSTATE(RL_STATE_DISPATCHING);
- (*func) (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;
-
- RL_CHECK_SIGNALS ();
- }
- 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
-
- RESIZE_KEYSEQ_BUFFER ();
- rl_executing_keyseq[rl_key_sequence_length++] = key;
- _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
-
- /* Tentative inter-character timeout for potential multi-key
- sequences? If no input within timeout, abort sequence and
- act as if we got non-matching input. */
- /* _rl_keyseq_timeout specified in milliseconds; _rl_input_queued
- takes microseconds, so multiply by 1000 */
- if (_rl_keyseq_timeout > 0 &&
- ((rl_readline_state & (RL_STATE_INPUTPENDING|RL_STATE_MACROINPUT)) == 0) &&
- _rl_pushed_input_available () == 0 &&
- _rl_dispatching_keymap[ANYOTHERKEY].function &&
- _rl_input_queued (_rl_keyseq_timeout*1000) == 0)
- return (_rl_subseq_result (-2, map, key, got_subseq));
-
- newkey = _rl_subseq_getchar (key);
- if (newkey < 0)
- {
- _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)
- {
- rl_executing_keyseq[rl_key_sequence_length] = '\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 ();
-
- /* If the completion parser's default word break characters haven't
- been set yet, then do so now. */
- if (rl_completer_word_break_characters == (char *)NULL)
- rl_completer_word_break_characters = (char *)rl_basic_word_break_characters;
-
-#if defined (COLOR_SUPPORT)
- if (_rl_colored_stats)
- _rl_parse_colors ();
-#endif
-
- rl_executing_keyseq = malloc (_rl_executing_keyseq_size = 16);
- if (rl_executing_keyseq)
- rl_executing_keyseq[0] = '\0';
-}
-
-/* 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);
- /* Unbind vi_movement_keymap[ESC] to allow users to repeatedly hit ESC
- in vi command mode while still allowing the arrow keys to work. */
- if (vi_movement_keymap[ESC].type == ISKMAP)
- rl_bind_keyseq_in_map ("\033", (rl_command_func_t *)NULL, 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);
-}
+++ /dev/null
-/* rlprivate.h -- functions and variables global to the readline library,
- but not intended for use by applications. */
-
-/* Copyright (C) 1999-2012 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library (Readline), a library
- for reading lines of text with interactive input and history editing.
-
- Readline is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Readline is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#if !defined (_RL_PRIVATE_H_)
-#define _RL_PRIVATE_H_
-
-#include "rlconf.h" /* for VISIBLE_STATS */
-#include "rlstdc.h"
-#include "posixjmp.h" /* defines procenv_t */
-
-/*************************************************************************
- * *
- * Convenience definitions *
- * *
- *************************************************************************/
-
-#define EMACS_MODE() (rl_editing_mode == emacs_mode)
-#define VI_COMMAND_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_movement_keymap)
-#define VI_INSERT_MODE() (rl_editing_mode == vi_mode && _rl_keymap == vi_insertion_keymap)
-
-#define RL_CHECK_SIGNALS() \
- do { \
- if (_rl_caught_signal) _rl_signal_handler (_rl_caught_signal); \
- } while (0)
-
-#define RL_SIG_RECEIVED() (_rl_caught_signal != 0)
-#define RL_SIGINT_RECEIVED() (_rl_caught_signal == SIGINT)
-
-/*************************************************************************
- * *
- * Global structs undocumented in texinfo manual and not in readline.h *
- * *
- *************************************************************************/
-/* 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
-#define SF_CHGKMAP 0x08
-
-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;
-
- Keymap keymap; /* used when dispatching commands in search string */
- Keymap okeymap; /* original keymap */
-
- int history_pos;
- int direction;
-
- int prevc;
- int lastc;
-#if defined (HANDLE_MULTIBYTE)
- char mb[MB_LEN_MAX];
- char pmb[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;
-
-/* vi-mode commands that use result of motion command to define boundaries */
-#define VIM_DELETE 0x01
-#define VIM_CHANGE 0x02
-#define VIM_YANK 0x04
-
-/* various states for vi-mode commands that use motion commands. reflects
- RL_READLINE_STATE */
-#define VMSTATE_READ 0x01
-#define VMSTATE_NUMARG 0x02
-
-typedef struct __rl_vimotion_context
-{
- int op;
- int state;
- int flags; /* reserved */
- _rl_arg_cxt ncxt;
- int numeric_arg;
- int start, end; /* rl_point, rl_end */
- int key, motion; /* initial key, motion command */
-} _rl_vimotion_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 *));
-
-typedef void _rl_sigcleanup_func_t PARAMS((int, void *));
-
-/*************************************************************************
- * *
- * 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 */
-#if defined (COLOR_SUPPORT)
-extern int _rl_colored_stats;
-#endif
-
-/* readline.c */
-extern int rl_line_buffer_len;
-extern int rl_arg_sign;
-extern int rl_visible_prompt_length;
-extern int rl_byte_oriented;
-
-/* display.c */
-extern int rl_display_fixed;
-
-/* parens.c */
-extern int rl_blink_matching_paren;
-
-/*************************************************************************
- * *
- * Global functions and variables unused 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 */
-extern char *_rl_untranslate_macro_value PARAMS((char *, int));
-
-/* complete.c */
-extern void _rl_reset_completion_state PARAMS((void));
-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));
-
-extern void _rl_revert_all_lines PARAMS((void));
-
-/* 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 *));
-
-/* signals.c */
-extern void _rl_signal_handler PARAMS((int));
-
-extern void _rl_block_sigint PARAMS((void));
-extern void _rl_release_sigint PARAMS((void));
-extern void _rl_block_sigwinch PARAMS((void));
-extern void _rl_release_sigwinch PARAMS((void));
-
-/* terminal.c */
-extern void _rl_get_screen_size PARAMS((int, int));
-extern void _rl_sigwinch_resize_terminal PARAMS((void));
-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_disable_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_forward_char_internal PARAMS((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 *));
-extern void _rl_free_undo_list PARAMS((UNDO_LIST *));
-
-/* util.c */
-#if defined (USE_VARARGS) && defined (PREFER_STDARG)
-extern void _rl_ttymsg (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
-extern void _rl_errmsg (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
-extern void _rl_trace (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
-#else
-extern void _rl_ttymsg ();
-extern void _rl_errmsg ();
-extern void _rl_trace ();
-#endif
-extern void _rl_audit_tty PARAMS((char *));
-
-extern int _rl_tropen PARAMS((void));
-
-extern int _rl_abort_internal PARAMS((void));
-extern int _rl_null_function PARAMS((int, int));
-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));
-extern int _rl_vi_domove_callback PARAMS((_rl_vimotion_cxt *));
-
-/*************************************************************************
- * Undocumented private variables *
- *************************************************************************/
-
-/* bind.c */
-extern const char * const _rl_possible_control_prefixes[];
-extern const char * const _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_completion_prefix_display_length;
-extern int _rl_completion_columns;
-extern int _rl_print_completions_horizontally;
-extern int _rl_completion_case_fold;
-extern int _rl_completion_case_map;
-extern int _rl_match_hidden_files;
-extern int _rl_page_completions;
-extern int _rl_skip_completed_text;
-extern int _rl_menu_complete_prefix_first;
-
-/* display.c */
-extern int _rl_vis_botlin;
-extern int _rl_last_c_pos;
-extern int _rl_suppress_redisplay;
-extern int _rl_want_redisplay;
-
-/* 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;
-
-/* nls.c */
-extern int _rl_utf8locale;
-
-/* readline.c */
-extern int _rl_echoing_p;
-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 int _rl_revert_all_at_newline;
-extern int _rl_echo_control_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 _rl_top_level;
-extern _rl_keyseq_cxt *_rl_kscxt;
-
-extern int _rl_executing_keyseq_size;
-
-/* search.c */
-extern _rl_search_cxt *_rl_nscxt;
-
-/* signals.c */
-extern int _rl_interrupt_immediately;
-extern int volatile _rl_caught_signal;
-
-extern _rl_sigcleanup_func_t *_rl_sigcleanup;
-extern void *_rl_sigcleanarg;
-
-extern int _rl_echoctl;
-
-extern int _rl_intr_char;
-extern int _rl_quit_char;
-extern int _rl_susp_char;
-
-/* 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;
-extern _rl_vimotion_cxt *_rl_vimvcxt;
-
-#endif /* _RL_PRIVATE_H_ */
+++ /dev/null
-/* readline.c -- a general facility for reading lines of input
- with emacs style editing and completion. */
-
-/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
-
- This file is part of the GNU Readline Library (Readline), a library
- for reading lines of text with interactive input and history editing.
-
- Readline is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Readline is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Readline. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#define READLINE_LIBRARY
-
-#if defined (HAVE_CONFIG_H)
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#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 an UNDO_LIST */
-void
-_rl_free_undo_list (ul)
- UNDO_LIST *ul;
-{
- UNDO_LIST *release;
-
- while (ul)
- {
- release = ul;
- ul = ul->next;
-
- if (release->what == UNDO_DELETE)
- xfree (release->text);
-
- xfree (release);
- }
-}
-
-/* Free the existing undo list. */
-void
-rl_free_undo_list ()
-{
- UNDO_LIST *release, *orig_list;
-
- orig_list = rl_undo_list;
- _rl_free_undo_list (rl_undo_list);
- rl_undo_list = (UNDO_LIST *)NULL;
- replace_history_data (-1, (histdata_t *)orig_list, (histdata_t *)NULL);
-}
-
-UNDO_LIST *
-_rl_copy_undo_entry (entry)
- UNDO_LIST *entry;
-{
- UNDO_LIST *new;
-
- new = alloc_undo_entry (entry->what, entry->start, entry->end, (char *)NULL);
- new->text = entry->text ? savestring (entry->text) : 0;
- return new;
-}
-
-UNDO_LIST *
-_rl_copy_undo_list (head)
- UNDO_LIST *head;
-{
- UNDO_LIST *list, *new, *roving, *c;
-
- if (head == 0)
- return head;
-
- list = head;
- new = 0;
- while (list)
- {
- c = _rl_copy_undo_entry (list);
- if (new == 0)
- roving = new = c;
- else
- {
- roving->next = c;
- roving = roving->next;
- }
- list = list->next;
- }
-
- roving->next = 0;
- return new;
-}
-
-/* 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 == 0)
- 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);
- xfree (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);
-
- xfree (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 == 0)
- 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;
-}
+++ /dev/null
-/* strtrans.c - Translate and untranslate strings with ANSI-C escape sequences. */
-
-/* Copyright (C) 2000-2011 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <bashansi.h>
-#include <stdio.h>
-#include <chartypes.h>
-
-#include "shell.h"
-
-#include "shmbchar.h"
-#include "shmbutil.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;
- unsigned long v;
-
- if (string == 0 || *string == '\0')
- return ((char *)NULL);
-
-#if defined (HANDLE_MULTIBYTE)
- ret = (char *)xmalloc (6*len + 1);
-#else
- ret = (char *)xmalloc (2*len + 1); /* 2*len for possible CTLESC */
-#endif
- 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 = (int) 0x07; 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;
- }
- /*FALLTHROUGH*/
-#endif
- 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;
-#if defined (HANDLE_MULTIBYTE)
- case 'u':
- case 'U':
- temp = (c == 'u') ? 4 : 8; /* \uNNNN \UNNNNNNNN */
- for (v = 0; ISXDIGIT ((unsigned char)*s) && temp--; s++)
- v = (v * 16) + HEXVALUE (*s);
- if (temp == ((c == 'u') ? 4 : 8))
- {
- *r++ = '\\'; /* c remains unchanged */
- break;
- }
- else if (v <= 0x7f) /* <= 0x7f translates directly */
- {
- c = v;
- break;
- }
- else
- {
- temp = u32cconv (v, r);
- r += temp;
- continue;
- }
-#endif
- 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 && *s == 0)
- ; /* pass \c through */
- else if ((flags & 1) == 0 && (c = *s))
- {
- s++;
- if ((flags & 2) && c == '\\' && c == *s)
- s++; /* Posix requires $'\c\\' do backslash escaping */
- 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, sindex;
- unsigned char c;
- size_t slen, clen;
-#if defined (HANDLE_MULTIBYTE)
- int b;
- wchar_t wc;
-#endif
-
- if (str == 0 || *str == 0)
- return ((char *)0);
-
- l = strlen (str);
- rsize = 4 * l + 4;
- r = ret = (char *)xmalloc (rsize);
-
- *r++ = '$';
- *r++ = '\'';
-
- s = str;
- slen = strlen (str);
-
- for (s = str; c = *s; s++)
- {
- l = 1; /* 1 == add backslash; 0 == no backslash */
- clen = 1;
-
- switch (c)
- {
- case ESC: c = 'E'; break;
-#ifdef __STDC__
- case '\a': c = 'a'; break;
- case '\v': c = 'v'; break;
-#else
- case 0x07: 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 defined (HANDLE_MULTIBYTE)
- b = is_basic (c);
- if ((b == 0 && ((clen = mbrtowc (&wc, s, MB_CUR_MAX, 0)) < 0 || iswprint (wc) == 0)) ||
- (b == 1 && ISPRINT (c) == 0))
-#else
- if (ISPRINT (c) == 0)
-#endif
- {
- *r++ = '\\';
- *r++ = TOCHAR ((c >> 6) & 07);
- *r++ = TOCHAR ((c >> 3) & 07);
- *r++ = TOCHAR (c & 07);
- continue;
- }
- l = 0;
- break;
- }
- if (l)
- *r++ = '\\';
-
- if (clen == 1)
- *r++ = c;
- else
- for (b = 0; b < (int)clen; c = b ? *++s : c)
- *r++ = c;
- }
-
- *r++ = '\'';
- *r = '\0';
- if (rlen)
- *rlen = r - ret;
- return ret;
-}
-
-#if defined (HANDLE_MULTIBYTE)
-int
-ansic_wshouldquote (string)
- const char *string;
-{
- const wchar_t *wcs;
- wchar_t wcc;
-
- wchar_t *wcstr = NULL;
- size_t wclen, slen;
-
-
- slen = mbstowcs (wcstr, string, 0);
-
- if (slen == -1)
- slen = 0;
- wcstr = (wchar_t *)xmalloc (sizeof (wchar_t) * (slen + 1));
- mbstowcs (wcstr, string, slen + 1);
-
- for (wcs = wcstr; wcc = *wcs; wcs++)
- if (iswprint(wcc) == 0)
- {
- free (wcstr);
- return 1;
- }
-
- free (wcstr);
- return 0;
-}
-#endif
-
-/* 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 defined (HANDLE_MULTIBYTE)
- if (is_basic (c) == 0)
- return (ansic_wshouldquote (s));
-#endif
- 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);
- }
-}
+++ /dev/null
-/* unicode.c - functions to convert unicode characters */
-
-/* Copyright (C) 2010-2012 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#if defined (HANDLE_MULTIBYTE)
-
-#include <stdc.h>
-#include <wchar.h>
-#include <bashansi.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <limits.h>
-
-#if HAVE_ICONV
-# include <iconv.h>
-#endif
-
-#include <xmalloc.h>
-
-#ifndef USHORT_MAX
-# ifdef USHRT_MAX
-# define USHORT_MAX USHRT_MAX
-# else
-# define USHORT_MAX ((unsigned short) ~(unsigned short)0)
-# endif
-#endif
-
-#if !defined (STREQ)
-# define STREQ(a, b) ((a)[0] == (b)[0] && strcmp ((a), (b)) == 0)
-#endif /* !STREQ */
-
-#if defined (HAVE_LOCALE_CHARSET)
-extern const char *locale_charset __P((void));
-#else
-extern char *get_locale_var __P((char *));
-#endif
-
-static int u32init = 0;
-static int utf8locale = 0;
-#if defined (HAVE_ICONV)
-static iconv_t localconv;
-#endif
-
-#ifndef HAVE_LOCALE_CHARSET
-static char charsetbuf[40];
-
-static char *
-stub_charset ()
-{
- char *locale, *s, *t;
-
- locale = get_locale_var ("LC_CTYPE");
- if (locale == 0 || *locale == 0)
- {
- strcpy (charsetbuf, "ASCII");
- return charsetbuf;
- }
- s = strrchr (locale, '.');
- if (s)
- {
- strcpy (charsetbuf, s+1);
- t = strchr (charsetbuf, '@');
- if (t)
- *t = 0;
- return charsetbuf;
- }
- strcpy (charsetbuf, locale);
- return charsetbuf;
-}
-#endif
-
-void
-u32reset ()
-{
- u32init = 0;
- utf8locale = 0;
-}
-
-/* u32toascii ? */
-int
-u32tochar (x, s)
- unsigned long x;
- char *s;
-{
- int l;
-
- l = (x <= UCHAR_MAX) ? 1 : ((x <= USHORT_MAX) ? 2 : 4);
-
- if (x <= UCHAR_MAX)
- s[0] = x & 0xFF;
- else if (x <= USHORT_MAX) /* assume unsigned short = 16 bits */
- {
- s[0] = (x >> 8) & 0xFF;
- s[1] = x & 0xFF;
- }
- else
- {
- s[0] = (x >> 24) & 0xFF;
- s[1] = (x >> 16) & 0xFF;
- s[2] = (x >> 8) & 0xFF;
- s[3] = x & 0xFF;
- }
- s[l] = '\0';
- return l;
-}
-
-/* Convert unsigned 32-bit int to utf-8 character string */
-int
-u32toutf8 (wc, s)
- u_bits32_t wc;
- char *s;
-{
- int l;
-
- if (wc < 0x0080)
- {
- s[0] = (char)wc;
- l = 1;
- }
- else if (wc < 0x0800)
- {
- s[0] = (wc >> 6) | 0xc0;
- s[1] = (wc & 0x3f) | 0x80;
- l = 2;
- }
- else if (wc < 0x10000)
- {
- s[0] = (wc >> 12) | 0xe0;
- s[1] = ((wc >> 6) & 0x3f) | 0x80;
- s[2] = (wc & 0x3f) | 0x80;
- l = 3;
- }
- else if (wc < 0x200000)
- {
- s[0] = (wc >> 18) | 0xf0;
- s[1] = ((wc >> 12) & 0x3f) | 0x80;
- s[2] = ((wc >> 6) & 0x3f) | 0x80;
- s[3] = (wc & 0x3f) | 0x80;
- l = 4;
- }
- /* Strictly speaking, UTF-8 doesn't have characters longer than 4 bytes */
- else if (wc < 0x04000000)
- {
- s[0] = (wc >> 24) | 0xf8;
- s[1] = ((wc >> 18) & 0x3f) | 0x80;
- s[2] = ((wc >> 12) & 0x3f) | 0x80;
- s[3] = ((wc >> 6) & 0x3f) | 0x80;
- s[4] = (wc & 0x3f) | 0x80;
- l = 5;
- }
- else if (wc < 0x080000000)
- {
- s[0] = (wc >> 30) | 0xf8;
- s[1] = ((wc >> 24) & 0x3f) | 0x80;
- s[2] = ((wc >> 18) & 0x3f) | 0x80;
- s[3] = ((wc >> 12) & 0x3f) | 0x80;
- s[4] = ((wc >> 6) & 0x3f) | 0x80;
- s[5] = (wc & 0x3f) | 0x80;
- l = 6;
- }
- else
- l = 0;
-
- s[l] = '\0';
- return l;
-}
-
-/* Convert a 32-bit unsigned int (unicode) to a UTF-16 string. Rarely used,
- only if sizeof(wchar_t) == 2. */
-int
-u32toutf16 (c, s)
- u_bits32_t c;
- unsigned short *s;
-{
- int l;
-
- l = 0;
- if (c < 0x0d800)
- {
- s[0] = (unsigned short) (c & 0xFFFF);
- l = 1;
- }
- else if (c >= 0x0e000 && c <= 0x010ffff)
- {
- c -= 0x010000;
- s[0] = (unsigned short)((c >> 10) + 0xd800);
- s[1] = (unsigned short)((c & 0x3ff) + 0xdc00);
- l = 2;
- }
- s[l] = 0;
- return l;
-}
-
-/* convert a single unicode-32 character into a multibyte string and put the
- result in S, which must be large enough (at least MB_LEN_MAX bytes) */
-int
-u32cconv (c, s)
- unsigned long c;
- char *s;
-{
- wchar_t wc;
- wchar_t ws[3];
- int n;
-#if HAVE_ICONV
- const char *charset;
- char obuf[25], *optr;
- size_t obytesleft;
- const char *iptr;
- size_t sn;
-#endif
-
-#if __STDC_ISO_10646__
- wc = c;
- if (sizeof (wchar_t) == 4 && c <= 0x7fffffff)
- {
- n = wctomb (s, wc);
- if (n != -1)
- return n;
- }
- else if (sizeof (wchar_t) == 2)
- {
- if (u32toutf16 (c, ws))
- {
- n = wcstombs (s, ws, MB_LEN_MAX);
- if (n != -1)
- return n;
- }
- }
-#endif
-
-#if HAVE_NL_LANGINFO
- codeset = nl_langinfo (CODESET);
- if (STREQ (codeset, "UTF-8"))
- {
- n = u32toutf8 (c, s);
- return n;
- }
-#endif
-
-#if HAVE_ICONV
- /* this is mostly from coreutils-8.5/lib/unicodeio.c */
- if (u32init == 0)
- {
-# if HAVE_LOCALE_CHARSET
- charset = locale_charset (); /* XXX - fix later */
-# else
- charset = stub_charset ();
-# endif
- if (STREQ (charset, "UTF-8"))
- utf8locale = 1;
- else
- {
- localconv = iconv_open (charset, "UTF-8");
- if (localconv == (iconv_t)-1)
- localconv = iconv_open (charset, "ASCII");
- }
- u32init = 1;
- }
-
- if (utf8locale)
- {
- n = u32toutf8 (c, s);
- return n;
- }
-
- if (localconv == (iconv_t)-1)
- {
- n = u32tochar (c, s);
- return n;
- }
-
- n = u32toutf8 (c, s);
-
- optr = obuf;
- obytesleft = sizeof (obuf);
- iptr = s;
- sn = n;
-
- iconv (localconv, NULL, NULL, NULL, NULL);
-
- if (iconv (localconv, (ICONV_CONST char **)&iptr, &sn, &optr, &obytesleft) == (size_t)-1)
- return n; /* You get utf-8 if iconv fails */
-
- *optr = '\0';
-
- /* number of chars to be copied is optr - obuf if we want to do bounds
- checking */
- strcpy (s, obuf);
- return (optr - obuf);
-#endif
-
- n = u32tochar (c, s); /* fallback */
- return n;
-}
-#else
-void
-u32reset ()
-{
-}
-#endif /* HANDLE_MULTIBYTE */
+++ /dev/null
-/* locale.c - Miscellaneous internationalization functions. */
-
-/* Copyright (C) 1996-2009 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "config.h"
-
-#include "bashtypes.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if HAVE_LANGINFO_CODESET
-# include <langinfo.h>
-#endif
-
-#include "bashintl.h"
-#include "bashansi.h"
-#include <stdio.h>
-#include "chartypes.h"
-#include <errno.h>
-
-#include "shell.h"
-#include "input.h" /* For bash_input */
-
-#ifndef errno
-extern int errno;
-#endif
-
-int locale_utf8locale; /* unused for now */
-int locale_mb_cur_max; /* value of MB_CUR_MAX for current locale (LC_CTYPE) */
-
-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));
-static int locale_isutf8 __P((char *));
-
-/* 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);
-
- locale_mb_cur_max = MB_CUR_MAX;
-}
-
-/* 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;
-
-#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 ();
- locale_mb_cur_max = MB_CUR_MAX;
- }
-# 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;
- char *x;
-
- x = "";
- errno = 0;
- 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 ? ((x = setlocale (LC_ALL, lc_all)) != 0) : reset_locale_vars ();
- if (x == 0)
- {
- if (errno == 0)
- internal_warning(_("setlocale: LC_ALL: cannot change locale (%s)"), lc_all);
- else
- internal_warning(_("setlocale: LC_ALL: cannot change locale (%s): %s"), lc_all, strerror (errno));
- }
- locale_setblanks ();
- locale_mb_cur_max = MB_CUR_MAX;
- 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')
- {
- x = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
- locale_setblanks ();
- locale_mb_cur_max = MB_CUR_MAX;
- }
-# endif
- }
- else if (var[3] == 'C' && var[4] == 'O') /* LC_COLLATE */
- {
-# if defined (LC_COLLATE)
- if (lc_all == 0 || *lc_all == '\0')
- x = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
-# endif /* LC_COLLATE */
- }
- else if (var[3] == 'M' && var[4] == 'E') /* LC_MESSAGES */
- {
-# if defined (LC_MESSAGES)
- if (lc_all == 0 || *lc_all == '\0')
- x = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
-# endif /* LC_MESSAGES */
- }
- else if (var[3] == 'N' && var[4] == 'U') /* LC_NUMERIC */
- {
-# if defined (LC_NUMERIC)
- if (lc_all == 0 || *lc_all == '\0')
- x = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
-# endif /* LC_NUMERIC */
- }
- else if (var[3] == 'T' && var[4] == 'I') /* LC_TIME */
- {
-# if defined (LC_TIME)
- if (lc_all == 0 || *lc_all == '\0')
- x = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
-# endif /* LC_TIME */
- }
-#endif /* HAVE_SETLOCALE */
-
- if (x == 0)
- {
- if (errno == 0)
- internal_warning(_("setlocale: %s: cannot change locale (%s)"), var, get_locale_var (var));
- else
- internal_warning(_("setlocale: %s: cannot change locale (%s): %s"), var, get_locale_var (var), strerror (errno));
- }
-
- return (x != 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); /* XXX - mem leak? */
- if (locale == 0 || *locale == 0)
- locale = lang;
- if (locale == 0 || *locale == 0)
-#if 0
- locale = default_locale; /* system-dependent; not really portable. should it be "C"? */
-#else
- locale = "";
-#endif
- 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 ()
-{
- char *t;
-#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)
- t = setlocale (LC_CTYPE, get_locale_var ("LC_CTYPE"));
-# endif
-# if defined (LC_COLLATE)
- t = setlocale (LC_COLLATE, get_locale_var ("LC_COLLATE"));
-# endif
-# if defined (LC_MESSAGES)
- t = setlocale (LC_MESSAGES, get_locale_var ("LC_MESSAGES"));
-# endif
-# if defined (LC_NUMERIC)
- t = setlocale (LC_NUMERIC, get_locale_var ("LC_NUMERIC"));
-# endif
-# if defined (LC_TIME)
- t = setlocale (LC_TIME, get_locale_var ("LC_TIME"));
-# endif
-
- locale_setblanks ();
- locale_mb_cur_max = MB_CUR_MAX;
-
-#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;
- sh_syntaxtab[x] &= ~CBLANK;
- }
- else
- sh_syntaxtab[x] &= ~(CSHBRK|CBLANK);
- }
-}
-
-static int
-locale_isutf8 (lspec)
- char *lspec;
-{
- char *cp;
-
-#if HAVE_LANGINFO_CODESET
- cp = nl_langinfo (CODESET);
- return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8"));
-#else
- /* Take a shot */
- return (strstr (lspec, "UTF-8") || strstr (lspec, "utf8"));
-#endif
-}
+++ /dev/null
-/* parse.y - Yacc grammar for bash. */
-
-/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-%{
-#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, parse_and_execute_level;
-extern int posixly_correct;
-extern int last_command_exit_value;
-extern pid_t last_command_subst_pid;
-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 void rewind_input_string __P((void));
-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));
-static char *parse_comsub __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 (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 number of lines read from input while creating the current command. */
-int current_command_line_count;
-
-/* The number of lines in a command saved while we run parse_and_execute */
-int saved_command_line_count;
-
-/* The token that currently denotes the end of parse. */
-int shell_eof_token;
-
-/* The token currently being read. */
-int current_token;
-
-/* The current parser state. */
-int parser_state;
-
-/* 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 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 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;
-
-static int global_extglob;
-
-/* 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 source;
-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 COPROC
-%token COND_START COND_END COND_ERROR
-%token IN BANG TIME TIMEOPT TIMEIGN
-
-/* More general tokens. yylex () knows how to make these. */
-%token <word> WORD ASSIGNMENT_WORD REDIR_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 SEMI_AND SEMI_SEMI_AND
-%token LESS_LESS_MINUS AND_GREATER AND_GREATER_GREATER LESS_GREATER
-%token GREATER_BAR BAR_AND
-
-/* 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> coproc
-%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 '|' BAR_AND
-%%
-
-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); */
- if (parser_state & PST_CMDSUBST)
- parser_state |= PST_EOFTOKEN;
- YYACCEPT;
- }
- | '\n'
- {
- /* Case of regular command, but not a very
- interesting one. Return a NULL command. */
- global_command = (COMMAND *)NULL;
- if (parser_state & PST_CMDSUBST)
- parser_state |= PST_EOFTOKEN;
- YYACCEPT;
- }
- | error '\n'
- {
- /* Error during parsing. Return NULL command. */
- global_command = (COMMAND *)NULL;
- eof_encountered = 0;
- /* discard_parser_constructs (1); */
- if (interactive && parse_and_execute_level == 0)
- {
- 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
- {
- source.dest = 1;
- redir.filename = $2;
- $$ = make_redirection (source, r_output_direction, redir, 0);
- }
- | '<' WORD
- {
- source.dest = 0;
- redir.filename = $2;
- $$ = make_redirection (source, r_input_direction, redir, 0);
- }
- | NUMBER '>' WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_output_direction, redir, 0);
- }
- | NUMBER '<' WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_input_direction, redir, 0);
- }
- | REDIR_WORD '>' WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_output_direction, redir, REDIR_VARASSIGN);
- }
- | REDIR_WORD '<' WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_input_direction, redir, REDIR_VARASSIGN);
- }
- | GREATER_GREATER WORD
- {
- source.dest = 1;
- redir.filename = $2;
- $$ = make_redirection (source, r_appending_to, redir, 0);
- }
- | NUMBER GREATER_GREATER WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_appending_to, redir, 0);
- }
- | REDIR_WORD GREATER_GREATER WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_appending_to, redir, REDIR_VARASSIGN);
- }
- | GREATER_BAR WORD
- {
- source.dest = 1;
- redir.filename = $2;
- $$ = make_redirection (source, r_output_force, redir, 0);
- }
- | NUMBER GREATER_BAR WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_output_force, redir, 0);
- }
- | REDIR_WORD GREATER_BAR WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_output_force, redir, REDIR_VARASSIGN);
- }
- | LESS_GREATER WORD
- {
- source.dest = 0;
- redir.filename = $2;
- $$ = make_redirection (source, r_input_output, redir, 0);
- }
- | NUMBER LESS_GREATER WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_input_output, redir, 0);
- }
- | REDIR_WORD LESS_GREATER WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_input_output, redir, REDIR_VARASSIGN);
- }
- | LESS_LESS WORD
- {
- source.dest = 0;
- redir.filename = $2;
- $$ = make_redirection (source, r_reading_until, redir, 0);
- redir_stack[need_here_doc++] = $$;
- }
- | NUMBER LESS_LESS WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_reading_until, redir, 0);
- redir_stack[need_here_doc++] = $$;
- }
- | REDIR_WORD LESS_LESS WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_reading_until, redir, REDIR_VARASSIGN);
- redir_stack[need_here_doc++] = $$;
- }
- | LESS_LESS_MINUS WORD
- {
- source.dest = 0;
- redir.filename = $2;
- $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
- redir_stack[need_here_doc++] = $$;
- }
- | NUMBER LESS_LESS_MINUS WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_deblank_reading_until, redir, 0);
- redir_stack[need_here_doc++] = $$;
- }
- | REDIR_WORD LESS_LESS_MINUS WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_deblank_reading_until, redir, REDIR_VARASSIGN);
- redir_stack[need_here_doc++] = $$;
- }
- | LESS_LESS_LESS WORD
- {
- source.dest = 0;
- redir.filename = $2;
- $$ = make_redirection (source, r_reading_string, redir, 0);
- }
- | NUMBER LESS_LESS_LESS WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_reading_string, redir, 0);
- }
- | REDIR_WORD LESS_LESS_LESS WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_reading_string, redir, REDIR_VARASSIGN);
- }
- | LESS_AND NUMBER
- {
- source.dest = 0;
- redir.dest = $2;
- $$ = make_redirection (source, r_duplicating_input, redir, 0);
- }
- | NUMBER LESS_AND NUMBER
- {
- source.dest = $1;
- redir.dest = $3;
- $$ = make_redirection (source, r_duplicating_input, redir, 0);
- }
- | REDIR_WORD LESS_AND NUMBER
- {
- source.filename = $1;
- redir.dest = $3;
- $$ = make_redirection (source, r_duplicating_input, redir, REDIR_VARASSIGN);
- }
- | GREATER_AND NUMBER
- {
- source.dest = 1;
- redir.dest = $2;
- $$ = make_redirection (source, r_duplicating_output, redir, 0);
- }
- | NUMBER GREATER_AND NUMBER
- {
- source.dest = $1;
- redir.dest = $3;
- $$ = make_redirection (source, r_duplicating_output, redir, 0);
- }
- | REDIR_WORD GREATER_AND NUMBER
- {
- source.filename = $1;
- redir.dest = $3;
- $$ = make_redirection (source, r_duplicating_output, redir, REDIR_VARASSIGN);
- }
- | LESS_AND WORD
- {
- source.dest = 0;
- redir.filename = $2;
- $$ = make_redirection (source, r_duplicating_input_word, redir, 0);
- }
- | NUMBER LESS_AND WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_duplicating_input_word, redir, 0);
- }
- | REDIR_WORD LESS_AND WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_duplicating_input_word, redir, REDIR_VARASSIGN);
- }
- | GREATER_AND WORD
- {
- source.dest = 1;
- redir.filename = $2;
- $$ = make_redirection (source, r_duplicating_output_word, redir, 0);
- }
- | NUMBER GREATER_AND WORD
- {
- source.dest = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_duplicating_output_word, redir, 0);
- }
- | REDIR_WORD GREATER_AND WORD
- {
- source.filename = $1;
- redir.filename = $3;
- $$ = make_redirection (source, r_duplicating_output_word, redir, REDIR_VARASSIGN);
- }
- | GREATER_AND '-'
- {
- source.dest = 1;
- redir.dest = 0;
- $$ = make_redirection (source, r_close_this, redir, 0);
- }
- | NUMBER GREATER_AND '-'
- {
- source.dest = $1;
- redir.dest = 0;
- $$ = make_redirection (source, r_close_this, redir, 0);
- }
- | REDIR_WORD GREATER_AND '-'
- {
- source.filename = $1;
- redir.dest = 0;
- $$ = make_redirection (source, r_close_this, redir, REDIR_VARASSIGN);
- }
- | LESS_AND '-'
- {
- source.dest = 0;
- redir.dest = 0;
- $$ = make_redirection (source, r_close_this, redir, 0);
- }
- | NUMBER LESS_AND '-'
- {
- source.dest = $1;
- redir.dest = 0;
- $$ = make_redirection (source, r_close_this, redir, 0);
- }
- | REDIR_WORD LESS_AND '-'
- {
- source.filename = $1;
- redir.dest = 0;
- $$ = make_redirection (source, r_close_this, redir, REDIR_VARASSIGN);
- }
- | AND_GREATER WORD
- {
- source.dest = 1;
- redir.filename = $2;
- $$ = make_redirection (source, r_err_and_out, redir, 0);
- }
- | AND_GREATER_GREATER WORD
- {
- source.dest = 1;
- redir.filename = $2;
- $$ = make_redirection (source, r_append_err_and_out, redir, 0);
- }
- ;
-
-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; }
- | coproc
- { $$ = $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;
- }
- ;
-
-coproc: COPROC shell_command
- {
- $$ = make_coproc_command ("COPROC", $2);
- $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
- }
- | COPROC shell_command redirection_list
- {
- COMMAND *tc;
-
- tc = $2;
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = $3;
- }
- else
- tc->redirects = $3;
- $$ = make_coproc_command ("COPROC", $2);
- $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
- }
- | COPROC WORD shell_command
- {
- $$ = make_coproc_command ($2->word, $3);
- $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
- }
- | COPROC WORD shell_command redirection_list
- {
- COMMAND *tc;
-
- tc = $3;
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = $4;
- }
- else
- tc->redirects = $4;
- $$ = make_coproc_command ($2->word, $3);
- $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_SUBSHELL;
- }
- | COPROC simple_command
- {
- $$ = make_coproc_command ("COPROC", clean_simple_command ($2));
- $$->flags |= CMD_WANT_SUBSHELL|CMD_COPROC_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
- { $$ = $1; }
- | case_clause_sequence pattern_list SEMI_SEMI
- { $2->next = $1; $$ = $2; }
- | pattern_list SEMI_AND
- { $1->flags |= CASEPAT_FALLTHROUGH; $$ = $1; }
- | case_clause_sequence pattern_list SEMI_AND
- { $2->flags |= CASEPAT_FALLTHROUGH; $2->next = $1; $$ = $2; }
- | pattern_list SEMI_SEMI_AND
- { $1->flags |= CASEPAT_TESTNEXT; $$ = $1; }
- | case_clause_sequence pattern_list SEMI_SEMI_AND
- { $2->flags |= CASEPAT_TESTNEXT; $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 ();
- if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
- {
- global_command = $1;
- eof_encountered = 0;
- rewind_input_string ();
- YYACCEPT;
- }
- }
- | 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 ();
- if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
- {
- global_command = $1;
- eof_encountered = 0;
- rewind_input_string ();
- YYACCEPT;
- }
- }
- | simple_list1 ';'
- {
- $$ = $1;
- if (need_here_doc)
- gather_here_documents ();
- if ((parser_state & PST_CMDSUBST) && current_token == shell_eof_token)
- {
- global_command = $1;
- eof_encountered = 0;
- rewind_input_string ();
- YYACCEPT;
- }
- }
- ;
-
-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_command
- {
- if ($2)
- $2->flags ^= CMD_INVERT_RETURN; /* toggle */
- $$ = $2;
- }
- | timespec pipeline_command
- {
- if ($2)
- $2->flags |= $1;
- $$ = $2;
- }
- | 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';
- }
- | BANG list_terminator
- {
- ELEMENT x;
-
- /* This is just as unclean. Posix says that `!'
- by itself should be equivalent to `false'.
- 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 |= CMD_INVERT_RETURN;
- /* 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, '|'); }
- | pipeline BAR_AND newline_list pipeline
- {
- /* Make cmd1 |& cmd2 equivalent to cmd1 2>&1 | cmd2 */
- COMMAND *tc;
- REDIRECTEE rd, sd;
- REDIRECT *r;
-
- tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
- sd.dest = 2;
- rd.dest = 1;
- r = make_redirection (sd, r_duplicating_output, rd, 0);
- if (tc->redirects)
- {
- register REDIRECT *t;
- for (t = tc->redirects; t->next; t = t->next)
- ;
- t->next = r;
- }
- else
- tc->redirects = r;
-
- $$ = command_connect ($1, $4, '|');
- }
- | command
- { $$ = $1; }
- ;
-
-timespec: TIME
- { $$ = CMD_TIME_PIPELINE; }
- | TIME TIMEOPT
- { $$ = CMD_TIME_PIPELINE|CMD_TIME_POSIX; }
- | TIME TIMEOPT TIMEIGN
- { $$ = CMD_TIME_PIPELINE|CMD_TIME_POSIX; }
- ;
-%%
-
-/* 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
-
-/* 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 *)IMPOSSIBLE_TRAP_HANDLER;
- if (signal_is_ignored (SIGINT) == 0)
- {
- interrupt_immediately++;
- old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
- }
-
- current_readline_line = readline (current_readline_prompt ?
- current_readline_prompt : "");
-
- CHECK_TERMSIG;
- if (signal_is_ignored (SIGINT) == 0)
- {
- interrupt_immediately--;
- if (old_sigint != IMPOSSIBLE_TRAP_HANDLER)
- 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);
-}
-
-/* Count the number of characters we've consumed from bash_input.location.string
- and read into shell_input_line, but have not returned from shell_getc.
- That is the true input location. Rewind bash_input.location.string by
- that number of characters, so it points to the last character actually
- consumed by the parser. */
-static void
-rewind_input_string ()
-{
- int xchars;
-
- /* number of unconsumed characters in the input -- XXX need to take newlines
- into account, e.g., $(...\n) */
- xchars = shell_input_line_len - shell_input_line_index;
- if (bash_input.location.string[-1] == '\n')
- xchars++;
-
- /* XXX - how to reflect bash_input.location.string back to string passed to
- parse_and_execute or xparse_dolparen? xparse_dolparen needs to know how
- far into the string we parsed. parse_and_execute knows where bash_input.
- location.string is, and how far from orig_string that is -- that's the
- number of characters the command consumed. */
-
- /* bash_input.location.string - xchars should be where we parsed to */
- /* need to do more validation on xchars value for sanity -- test cases. */
- bash_input.location.string -= xchars;
-}
-
-/* **************************************************************** */
-/* */
-/* 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++;
-
- /* XXX - don't need terminate_immediately; getc_with_restart checks
- for terminating signals itself if read returns < 0 */
- 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;
-
-/* The line number offset set by assigning to LINENO. Not currently used. */
-int line_number_base = 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 (4 * sizeof (int));
- ret[0] = last_read_token;
- ret[1] = token_before_that;
- ret[2] = two_tokens_ago;
- ret[3] = current_token;
- 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];
- current_token = ts[3];
-}
-
-/*
- * 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, c, peekc, pass_next;
-
-#if defined (READLINE)
- if (no_line_editing && SHOULD_PROMPT ())
-#else
- if (SHOULD_PROMPT ())
-#endif
- print_prompt ();
-
- pass_next = indx = 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)
- {
- QUIT;
- 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;
-{
- char *ret;
- int n, c;
-
- prompt_string_pointer = &ps2_prompt;
- if (SHOULD_PROMPT())
- prompt_again ();
- ret = read_a_line (remove_quoted_newline);
-#if defined (HISTORY)
- if (ret && remember_on_history && (parser_state & PST_HEREDOC))
- {
- /* To make adding the the here-document body right, we need to rely
- on history_delimiting_chars() returning \n for the first line of
- the here-document body and the null string for the second and
- subsequent lines, so we avoid double newlines.
- current_command_line_count == 2 for the first line of the body. */
-
- current_command_line_count++;
- maybe_add_history (ret);
- }
-#endif /* HISTORY */
- return ret;
-}
-
-/* **************************************************************** */
-/* */
-/* 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
-#if defined (COPROCESS_SUPPORT)
- { "coproc", COPROC },
-#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 */
- { "--", TIMEIGN },
- { "-p", TIMEOPT },
- { "&&", AND_AND },
- { "||", OR_OR },
- { ">>", GREATER_GREATER },
- { "<<", LESS_LESS },
- { "<&", LESS_AND },
- { ">&", GREATER_AND },
- { ";;", SEMI_SEMI },
- { ";&", SEMI_AND },
- { ";;&", SEMI_SEMI_AND },
- { "<<-", LESS_LESS_MINUS },
- { "<<<", LESS_LESS_LESS },
- { "&>", AND_GREATER },
- { "&>>", AND_GREATER_GREATER },
- { "<>", LESS_GREATER },
- { ">|", GREATER_BAR },
- { "|&", BAR_AND },
- { "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 == 0)
- 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 (shell_input_line);
- 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 = ¤t_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 ();
- }
- }
-
-next_alias_char:
- 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. */
-pop_alias:
- if (uc == 0 && (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++;
- /* What do we do here if we're expanding an alias whose definition
- includes an escaped newline? If that's the last character in the
- alias expansion, we just pop the pushed string list (recall that
- we inhibit the appending of a space in mk_alexpansion() if newline
- is the last character). If it's not the last character, we need
- to consume the quoted newline and move to the next character in
- the expansion. */
-#if defined (ALIAS)
- if (expanding_alias () && shell_input_line[shell_input_line_index+1] == '\0')
- {
- uc = 0;
- goto pop_alias;
- }
- else if (expanding_alias () && shell_input_line[shell_input_line_index+1] != '\0')
- {
- shell_input_line_index++; /* skip newline */
- goto next_alias_char; /* and get next character */
- }
- else
-#endif
- goto restart_read;
- }
-
- if (uc == 0 && 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 && parse_and_execute_level == 0 && 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);
-
- if ((parser_state & PST_EOFTOKEN) && current_token == shell_eof_token)
- {
- current_token = yacc_EOF;
- if (bash_input.type == st_string)
- rewind_input_string ();
- }
- parser_state &= ~PST_EOFTOKEN;
-
- 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;
-
- r = 0;
- while (need_here_doc)
- {
- parser_state |= PST_HEREDOC;
- make_here_document (redir_stack[r++], line_number);
- parser_state &= ~PST_HEREDOC;
- 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) || (parser_state&PST_REDIRLIST) || \
- ((token) != SEMI_SEMI && (token) != SEMI_AND && (token) != SEMI_SEMI_AND && 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 the last character in the alias is a newline, don't add a trailing
- space to the expansion. Works with shell_getc above. */
- if (r[l - 1] != ' ' && r[l - 1] != '\n')
- 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)
- int i;
-
- if (posixly_correct && shell_compatibility_level > 41)
- {
- /* Quick check of the rest of the line to find the next token. If it
- begins with a `-', Posix says to not return `time' as the token.
- This was interp 267. */
- i = shell_input_line_index;
- while (i < shell_input_line_len && (shell_input_line[i] == ' ' || shell_input_line[i] == '\t'))
- i++;
- if (shell_input_line[i] == '-')
- return 0;
- }
-
- switch (last_read_token)
- {
- case 0:
- case ';':
- case '\n':
- case AND_AND:
- case OR_OR:
- case '&':
- case DO:
- case THEN:
- case ELSE:
- case '{': /* } */
- case '(': /* ) */
- case BANG: /* ! time pipeline */
- case TIME: /* time time pipeline */
- case TIMEOPT: /* time -p time pipeline */
- case TIMEIGN: /* time -p -- ... */
- 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 TIMEIGN if the last read token was TIMEOPT.
-
- ']]' 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);
- /* Handle -- after `time -p'. */
- if (last_read_token == TIMEOPT && tokstr[0] == '-' && tokstr[1] == '-' && !tokstr[2])
- return (TIMEIGN);
-#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;
-
-#if defined (EXTENDED_GLOB)
- /* Reset to global value of extended glob */
- if (parser_state & PST_EXTPAT)
- extended_glob = global_extglob;
-#endif
-
- 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;
-
- current_token = '\n'; /* XXX */
- 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);
- }
-
- if (parser_state & PST_REGEXP)
- goto tokword;
-
- /* 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 MBTEST(peek_char == '-')
- return (LESS_LESS_MINUS);
- else if MBTEST(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 */
-
- peek_char = shell_getc (1);
- if MBTEST(peek_char == '&')
- return (SEMI_SEMI_AND);
- else
- {
- shell_ungetc (peek_char);
- 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(character == '&' && peek_char == '>')
- {
- peek_char = shell_getc (1);
- if MBTEST(peek_char == '>')
- return (AND_GREATER_GREATER);
- else
- {
- shell_ungetc (peek_char);
- return (AND_GREATER);
- }
- }
- else if MBTEST(character == '|' && peek_char == '&')
- return (BAR_AND);
- else if MBTEST(character == ';' && peek_char == '&')
- {
- parser_state |= PST_CASEPAT;
-#if defined (ALIAS)
- parser_state &= ~PST_ALEXPNEXT;
-#endif /* ALIAS */
- return (SEMI_AND);
- }
-
- 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);
-
-tokword:
- /* 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 0x0001
-#define P_ALLOWESC 0x0002
-#define P_DQUOTE 0x0004
-#define P_COMMAND 0x0008 /* parsing a command, so look for comments */
-#define P_BACKQUOTE 0x0010 /* parsing a backquoted command substitution */
-#define P_ARRAYSUB 0x0020 /* parsing a [...] array subscript for assignment */
-#define P_DOLBRACE 0x0040 /* parsing a ${...} construct */
-
-/* Lexical state while parsing a grouping construct or $(...). */
-#define LEX_WASDOL 0x001
-#define LEX_CKCOMMENT 0x002
-#define LEX_INCOMMENT 0x004
-#define LEX_PASSNEXT 0x008
-#define LEX_RESWDOK 0x010
-#define LEX_CKCASE 0x020
-#define LEX_INCASE 0x040
-#define LEX_INHEREDOC 0x080
-#define LEX_HEREDELIM 0x100 /* reading here-doc delimiter */
-#define LEX_STRIPDOC 0x200 /* <<- strip tabs from here doc delim */
-#define LEX_INWORD 0x400
-
-#define COMSUB_META(ch) ((ch) == ';' || (ch) == '&' || (ch) == '|')
-
-#define CHECK_NESTRET_ERROR() \
- do { \
- if (nestret == &matched_pair_error) \
- { \
- free (ret); \
- return &matched_pair_error; \
- } \
- } while (0)
-
-#define APPEND_NESTRET() \
- do { \
- if (nestlen) \
- { \
- RESIZE_MALLOCED_BUFFER (ret, retind, nestlen, retsize, 64); \
- strcpy (ret + retind, nestret); \
- retind += nestlen; \
- } \
- } while (0)
-
-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, tflags;
- int nestlen, ttranslen, start_lineno;
- char *ret, *nestret, *ttrans;
- int retind, retsize, rflags;
- int dolbrace_state;
-
- dolbrace_state = (flags & P_DOLBRACE) ? DOLBRACE_PARAM : 0;
-
-/*itrace("parse_matched_pair[%d]: open = %c close = %c flags = %d", line_number, open, close, flags);*/
- count = 1;
- tflags = 0;
-
- if ((flags & P_COMMAND) && qc != '`' && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0)
- tflags |= LEX_CKCOMMENT;
-
- /* 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 != '\'' && (tflags & (LEX_PASSNEXT)) == 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 ();
-
- /* Don't bother counting parens or doing anything else if in a comment
- or part of a case statement */
- if (tflags & LEX_INCOMMENT)
- {
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
-
- if (ch == '\n')
- tflags &= ~LEX_INCOMMENT;
-
- 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((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
- tflags |= LEX_INCOMMENT;
-
- if (tflags & LEX_PASSNEXT) /* last char was backslash */
- {
- tflags &= ~LEX_PASSNEXT;
- 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 0
- if MBTEST(ch == CTLESC || ch == CTLNUL)
-#else
- if MBTEST(ch == CTLESC)
-#endif
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
- /* If we're reparsing the input (e.g., from parse_string_to_word_list),
- we've already prepended CTLESC to single-quoted results of $'...'.
- We may want to do this for other CTLESC-quoted characters in
- reparse, too. */
- else if MBTEST((parser_state & PST_REPARSE) && open == '\'' && (ch == CTLESC || ch == CTLNUL))
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- 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 && (tflags & LEX_WASDOL) && 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 we just read the ending character, don't bother continuing. */
- if (count == 0)
- break;
-
- if (open == '\'') /* '' inside grouping construct */
- {
- if MBTEST((flags & P_ALLOWESC) && ch == '\\')
- tflags |= LEX_PASSNEXT;
- continue;
- }
-
- if MBTEST(ch == '\\') /* backslashes */
- tflags |= LEX_PASSNEXT;
-
- /* Based on which dolstate is currently in (param, op, or word),
- decide what the op is. We're really only concerned if it's % or
- #, so we can turn on a flag that says whether or not we should
- treat single quotes as special when inside a double-quoted
- ${...}. This logic must agree with subst.c:extract_dollar_brace_string
- since they share the same defines. */
- if (flags & P_DOLBRACE)
- {
- /* ${param%[%]word} */
- if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '%' && retind > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- /* ${param#[#]word} */
- else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '#' && retind > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- /* ${param/[/]pat/rep} */
- else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '/' && retind > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- /* ${param^[^]pat} */
- else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '^' && retind > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- /* ${param,[,]pat} */
- else if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == ',' && retind > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- else if MBTEST(dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", ch) != 0)
- dolbrace_state = DOLBRACE_OP;
- else if MBTEST(dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", ch) == 0)
- dolbrace_state = DOLBRACE_WORD;
- }
-
- /* The big hammer. Single quotes aren't special in double quotes. The
- problem is that Posix used to say the single quotes are semi-special:
- within a double-quoted ${...} construct "an even number of
- unescaped double-quotes or single-quotes, if any, shall occur." */
- /* This was changed in Austin Group Interp 221 */
- if MBTEST(posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (flags & P_DQUOTE) && (flags & P_DOLBRACE) && ch == '\'')
- continue;
-
- /* Could also check open == '`' if we want to parse grouping constructs
- inside old-style command substitution. */
- if (open != close) /* a grouping construct */
- {
- if MBTEST(shellquote (ch))
- {
- /* '', ``, or "" inside $(...) or other grouping construct. */
- push_delimiter (dstack, ch);
- if MBTEST((tflags & LEX_WASDOL) && 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);
- CHECK_NESTRET_ERROR ();
-
- if MBTEST((tflags & LEX_WASDOL) && 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((tflags & LEX_WASDOL) && 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 $" */
- }
-
- APPEND_NESTRET ();
- FREE (nestret);
- }
- else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
- goto parse_dollar_word;
- }
- /* 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);
-
- CHECK_NESTRET_ERROR ();
- APPEND_NESTRET ();
-
- FREE (nestret);
- }
- else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
- /* check for $(), $[], or ${} inside quoted string. */
- {
-parse_dollar_word:
- if (open == ch) /* undo previous increment */
- count--;
- if (ch == '(') /* ) */
- nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
- else if (ch == '{') /* } */
- nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
- else if (ch == '[') /* ] */
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
-
- CHECK_NESTRET_ERROR ();
- APPEND_NESTRET ();
-
- FREE (nestret);
- }
- if MBTEST(ch == '$')
- tflags |= LEX_WASDOL;
- else
- tflags &= ~LEX_WASDOL;
- }
-
- ret[retind] = '\0';
- if (lenp)
- *lenp = retind;
-/*itrace("parse_matched_pair[%d]: returning %s", line_number, ret);*/
- return ret;
-}
-
-/* Parse a $(...) command substitution. This is messier than I'd like, and
- reproduces a lot more of the token-reading code than I'd like. */
-static char *
-parse_comsub (qc, open, close, lenp, flags)
- int qc; /* `"' if this construct is within double quotes */
- int open, close;
- int *lenp, flags;
-{
- int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
- int nestlen, ttranslen, start_lineno;
- char *ret, *nestret, *ttrans, *heredelim;
- int retind, retsize, rflags, hdlen;
-
- /* Posix interp 217 says arithmetic expressions have precedence, so
- assume $(( introduces arithmetic expansion and parse accordingly. */
- peekc = shell_getc (0);
- shell_ungetc (peekc);
- if (peekc == '(')
- return (parse_matched_pair (qc, open, close, lenp, 0));
-
-/*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
- count = 1;
- tflags = LEX_RESWDOK;
-
- if ((flags & P_COMMAND) && qc != '\'' && qc != '"' && (flags & P_DQUOTE) == 0)
- tflags |= LEX_CKCASE;
- if ((tflags & LEX_CKCASE) && (interactive == 0 || interactive_comments))
- tflags |= LEX_CKCOMMENT;
-
- /* RFLAGS is the set of flags we want to pass to recursive calls. */
- rflags = (flags & P_DQUOTE);
-
- ret = (char *)xmalloc (retsize = 64);
- retind = 0;
-
- start_lineno = line_number;
- lex_rwlen = lex_wlen = 0;
-
- heredelim = 0;
- lex_firstind = -1;
-
- while (count)
- {
-comsub_readchar:
- ch = shell_getc (qc != '\'' && (tflags & (LEX_INCOMMENT|LEX_PASSNEXT)) == 0);
-
- if (ch == EOF)
- {
-eof_error:
- free (ret);
- FREE (heredelim);
- parser_error (start_lineno, _("unexpected EOF while looking for matching `%c'"), close);
- EOF_Reached = 1; /* XXX */
- return (&matched_pair_error);
- }
-
- /* If we hit the end of a line and are reading the contents of a here
- document, and it's not the same line that the document starts on,
- check for this line being the here doc delimiter. Otherwise, if
- we're in a here document, mark the next character as the beginning
- of a line. */
- if (ch == '\n')
- {
- if ((tflags & LEX_HEREDELIM) && heredelim)
- {
- tflags &= ~LEX_HEREDELIM;
- tflags |= LEX_INHEREDOC;
- lex_firstind = retind + 1;
- }
- else if (tflags & LEX_INHEREDOC)
- {
- int tind;
- tind = lex_firstind;
- while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t')
- tind++;
- if (STREQN (ret + tind, heredelim, hdlen))
- {
- tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC);
-/*itrace("parse_comsub:%d: found here doc end `%s'", line_number, ret + tind);*/
- free (heredelim);
- heredelim = 0;
- lex_firstind = -1;
- }
- else
- lex_firstind = retind + 1;
- }
- }
-
- /* Possible reprompting. */
- if (ch == '\n' && SHOULD_PROMPT ())
- prompt_again ();
-
- /* XXX -- possibly allow here doc to be delimited by ending right
- paren. */
- if ((tflags & LEX_INHEREDOC) && ch == close && count == 1)
- {
- int tind;
-/*itrace("parse_comsub: in here doc, ch == close, retind - firstind = %d hdlen = %d retind = %d", retind-lex_firstind, hdlen, retind);*/
- tind = lex_firstind;
- while ((tflags & LEX_STRIPDOC) && ret[tind] == '\t')
- tind++;
- if (retind-tind == hdlen && STREQN (ret + tind, heredelim, hdlen))
- {
- tflags &= ~(LEX_STRIPDOC|LEX_INHEREDOC);
-/*itrace("parse_comsub:%d: found here doc end `%s'", line_number, ret + tind);*/
- free (heredelim);
- heredelim = 0;
- lex_firstind = -1;
- }
- }
-
- /* Don't bother counting parens or doing anything else if in a comment */
- if (tflags & (LEX_INCOMMENT|LEX_INHEREDOC))
- {
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
-
- if ((tflags & LEX_INCOMMENT) && ch == '\n')
-{
-/*itrace("parse_comsub:%d: lex_incomment -> 0 ch = `%c'", line_number, ch);*/
- tflags &= ~LEX_INCOMMENT;
-}
-
- continue;
- }
-
- if (tflags & LEX_PASSNEXT) /* last char was backslash */
- {
-/*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
- tflags &= ~LEX_PASSNEXT;
- 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 0
- if MBTEST(ch == CTLESC || ch == CTLNUL)
-#else
- if MBTEST(ch == CTLESC)
-#endif
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
-
- /* If this is a shell break character, we are not in a word. If not,
- we either start or continue a word. */
- if MBTEST(shellbreak (ch))
- {
- tflags &= ~LEX_INWORD;
-/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
- }
- else
- {
- if (tflags & LEX_INWORD)
- {
- lex_wlen++;
-/*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
- }
- else
- {
-/*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
- tflags |= LEX_INWORD;
- lex_wlen = 0;
- }
- }
-
- /* Skip whitespace */
- if MBTEST(shellblank (ch) && (tflags & LEX_HEREDELIM) == 0 && lex_rwlen == 0)
- {
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
- continue;
- }
-
- /* Either we are looking for the start of the here-doc delimiter
- (lex_firstind == -1) or we are reading one (lex_firstind >= 0).
- If this character is a shell break character and we are reading
- the delimiter, save it and note that we are now reading a here
- document. If we've found the start of the delimiter, note it by
- setting lex_firstind. Backslashes can quote shell metacharacters
- in here-doc delimiters. */
- if (tflags & LEX_HEREDELIM)
- {
- if (lex_firstind == -1 && shellbreak (ch) == 0)
- lex_firstind = retind;
-#if 0
- else if (heredelim && (tflags & LEX_PASSNEXT) == 0 && ch == '\n')
- {
- tflags |= LEX_INHEREDOC;
- tflags &= ~LEX_HEREDELIM;
- lex_firstind = retind + 1;
- }
-#endif
- else if (lex_firstind >= 0 && (tflags & LEX_PASSNEXT) == 0 && shellbreak (ch))
- {
- if (heredelim == 0)
- {
- nestret = substring (ret, lex_firstind, retind);
- heredelim = string_quote_removal (nestret, 0);
- free (nestret);
- hdlen = STRLEN(heredelim);
-/*itrace("parse_comsub:%d: found here doc delimiter `%s' (%d)", line_number, heredelim, hdlen);*/
- }
- if (ch == '\n')
- {
- tflags |= LEX_INHEREDOC;
- tflags &= ~LEX_HEREDELIM;
- lex_firstind = retind + 1;
- }
- else
- lex_firstind = -1;
- }
- }
-
- /* Meta-characters that can introduce a reserved word. Not perfect yet. */
- if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && (shellmeta(ch) || ch == '\n'))
- {
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
- peekc = shell_getc (1);
- if (ch == peekc && (ch == '&' || ch == '|' || ch == ';')) /* two-character tokens */
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = peekc;
-/*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
- tflags |= LEX_RESWDOK;
- lex_rwlen = 0;
- continue;
- }
- else if (ch == '\n' || COMSUB_META(ch))
- {
- shell_ungetc (peekc);
-/*itrace("parse_comsub:%d: set lex_reswordok = 1, ch = `%c'", line_number, ch);*/
- tflags |= LEX_RESWDOK;
- lex_rwlen = 0;
- continue;
- }
- else if (ch == EOF)
- goto eof_error;
- else
- {
- /* `unget' the character we just added and fall through */
- retind--;
- shell_ungetc (peekc);
- }
- }
-
- /* If we can read a reserved word, try to read one. */
- if (tflags & LEX_RESWDOK)
- {
- if MBTEST(islower (ch))
- {
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
- lex_rwlen++;
- continue;
- }
- else if MBTEST(lex_rwlen == 4 && shellbreak (ch))
- {
- if (STREQN (ret + retind - 4, "case", 4))
-{
- tflags |= LEX_INCASE;
-/*itrace("parse_comsub:%d: found `case', lex_incase -> 1 lex_reswdok -> 0", line_number);*/
-}
- else if (STREQN (ret + retind - 4, "esac", 4))
-{
- tflags &= ~LEX_INCASE;
-/*itrace("parse_comsub:%d: found `esac', lex_incase -> 0 lex_reswdok -> 0", line_number);*/
-}
- tflags &= ~LEX_RESWDOK;
- }
- else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
- ; /* don't modify LEX_RESWDOK if we're starting a comment */
- else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
- /* If we can read a reserved word and we're in case, we're at the
- point where we can read a new pattern list or an esac. We
- handle the esac case above. If we read a newline, we want to
- leave LEX_RESWDOK alone. If we read anything else, we want to
- turn off LEX_RESWDOK, since we're going to read a pattern list. */
-{
- tflags &= ~LEX_RESWDOK;
-/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', lex_reswordok -> 0", line_number, ch);*/
-}
- else if MBTEST(shellbreak (ch) == 0)
-{
- tflags &= ~LEX_RESWDOK;
-/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
-}
- }
-
- /* Might be the start of a here-doc delimiter */
- if MBTEST((tflags & LEX_INCOMMENT) == 0 && (tflags & LEX_CKCASE) && ch == '<')
- {
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
- peekc = shell_getc (1);
- if (peekc == EOF)
- goto eof_error;
- if (peekc == ch)
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = peekc;
- peekc = shell_getc (1);
- if (peekc == EOF)
- goto eof_error;
- if (peekc == '-')
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = peekc;
- tflags |= LEX_STRIPDOC;
- }
- else
- shell_ungetc (peekc);
- if (peekc != '<')
- {
- tflags |= LEX_HEREDELIM;
- lex_firstind = -1;
- }
- continue;
- }
- else
- ch = peekc; /* fall through and continue XXX */
- }
- else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
-{
-/*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
- tflags |= LEX_INCOMMENT;
-}
-
- if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
- {
- RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
- ret[retind++] = CTLESC;
- ret[retind++] = ch;
- continue;
- }
-#if 0
- else if MBTEST((tflags & LEX_INCASE) && ch == close && close == ')')
- tflags &= ~LEX_INCASE; /* XXX */
-#endif
- else if MBTEST(ch == close && (tflags & LEX_INCASE) == 0) /* ending delimiter */
-{
- count--;
-/*itrace("parse_comsub:%d: found close: count = %d", line_number, count);*/
-}
- else if MBTEST(((flags & P_FIRSTCLOSE) == 0) && (tflags & LEX_INCASE) == 0 && ch == open) /* nested begin */
-{
- count++;
-/*itrace("parse_comsub:%d: found open: count = %d", line_number, count);*/
-}
-
- /* Add this character. */
- RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
- ret[retind++] = ch;
-
- /* If we just read the ending character, don't bother continuing. */
- if (count == 0)
- break;
-
- if MBTEST(ch == '\\') /* backslashes */
- tflags |= LEX_PASSNEXT;
-
- if MBTEST(shellquote (ch))
- {
- /* '', ``, or "" inside $(...). */
- push_delimiter (dstack, ch);
- if MBTEST((tflags & LEX_WASDOL) && 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);
- CHECK_NESTRET_ERROR ();
-
- if MBTEST((tflags & LEX_WASDOL) && 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((tflags & LEX_WASDOL) && 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 $" */
- }
-
- APPEND_NESTRET ();
- FREE (nestret);
- }
- else if MBTEST((tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
- /* check for $(), $[], or ${} inside command substitution. */
- {
- if ((tflags & LEX_INCASE) == 0 && open == ch) /* undo previous increment */
- count--;
- if (ch == '(') /* ) */
- nestret = parse_comsub (0, '(', ')', &nestlen, (rflags|P_COMMAND) & ~P_DQUOTE);
- else if (ch == '{') /* } */
- nestret = parse_matched_pair (0, '{', '}', &nestlen, P_FIRSTCLOSE|P_DOLBRACE|rflags);
- else if (ch == '[') /* ] */
- nestret = parse_matched_pair (0, '[', ']', &nestlen, rflags);
-
- CHECK_NESTRET_ERROR ();
- APPEND_NESTRET ();
-
- FREE (nestret);
- }
- if MBTEST(ch == '$')
- tflags |= LEX_WASDOL;
- else
- tflags &= ~LEX_WASDOL;
- }
-
- FREE (heredelim);
- ret[retind] = '\0';
- if (lenp)
- *lenp = retind;
-/*itrace("parse_comsub:%d: returning `%s'", line_number, ret);*/
- return ret;
-}
-
-/* Recursively call the parser to parse a $(...) command substitution. */
-char *
-xparse_dolparen (base, string, indp, flags)
- char *base;
- char *string;
- int *indp;
- int flags;
-{
- sh_parser_state_t ps;
- sh_input_line_state_t ls;
- int orig_ind, nc, sflags;
- char *ret, *s, *ep, *ostring;
-
- /*yydebug = 1;*/
- orig_ind = *indp;
- ostring = string;
-
-/*itrace("xparse_dolparen: size = %d shell_input_line = `%s'", shell_input_line_size, shell_input_line);*/
- sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
- if (flags & SX_NOLONGJMP)
- sflags |= SEVAL_NOLONGJMP;
- save_parser_state (&ps);
- save_input_line_state (&ls);
-
- /*(*/
- parser_state |= PST_CMDSUBST|PST_EOFTOKEN; /* allow instant ')' */ /*(*/
- shell_eof_token = ')';
- parse_string (string, "command substitution", sflags, &ep);
-
- restore_parser_state (&ps);
- reset_parser ();
- /* reset_parser clears shell_input_line and associated variables */
- restore_input_line_state (&ls);
- if (interactive)
- token_to_read = 0;
-
- /* Need to find how many characters parse_and_execute consumed, update
- *indp, if flags != 0, copy the portion of the string parsed into RET
- and return it. If flags & 1 (EX_NOALLOC) we can return NULL. */
-
- /*(*/
- if (ep[-1] != ')')
- {
-#if DEBUG
- if (ep[-1] != '\n')
- itrace("xparse_dolparen:%d: ep[-1] != RPAREN (%d), ep = `%s'", line_number, ep[-1], ep);
-#endif
- while (ep > ostring && ep[-1] == '\n') ep--;
- }
-
- nc = ep - ostring;
- *indp = ep - base - 1;
-
- /*(*/
-#if DEBUG
- if (base[*indp] != ')')
- itrace("xparse_dolparen:%d: base[%d] != RPAREN (%d), base = `%s'", line_number, *indp, base[*indp], base);
-#endif
-
- if (flags & SX_NOALLOC)
- return (char *)NULL;
-
- if (nc == 0)
- {
- ret = xmalloc (1);
- ret[0] = '\0';
- }
- else
- ret = substring (ostring, 0, nc - 1);
-
- 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 && yylval.word->word[0] == '-' && yylval.word->word[2] == 0 && 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 (op->word[0] == '=' && (op->word[1] == '\0' || (op->word[1] == '=' && op->word[2] == '\0')))
- parser_state |= PST_EXTPAT;
- else if (op->word[0] == '!' && op->word[1] == '=' && op->word[2] == '\0')
- parser_state |= PST_EXTPAT;
- }
-#if defined (COND_REGEXP)
- else if (tok == WORD && STREQ (yylval.word->word, "=~"))
- {
- op = yylval.word;
- parser_state |= PST_REGEXP;
- }
-#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 */
- if (parser_state & PST_EXTPAT)
- extended_glob = 1;
- tok = read_token (READ);
- if (parser_state & PST_EXTPAT)
- extended_glob = global_extglob;
- parser_state &= ~(PST_REGEXP|PST_EXTPAT);
-
- 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;
-
- global_extglob = extended_glob;
- 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_escaped_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 COND_REGEXP
- /* When parsing a regexp as a single word inside a conditional command,
- we need to special-case characters special to both the shell and
- regular expressions. Right now, that is only '(' and '|'. */ /*)*/
- if MBTEST((parser_state & PST_REGEXP) && (character == '(' || character == '|')) /*)*/
- {
- if (character == '|')
- goto got_character;
-
- push_delimiter (dstack, character);
- 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;
- strcpy (token + token_index, ttok);
- token_index += ttoklen;
- FREE (ttok);
- dollar_present = all_digit_token = 0;
- goto next_character;
- }
-#endif /* COND_REGEXP */
-
-#ifdef EXTENDED_GLOB
- /* Parse a ksh-style extended pattern matching specification. */
- if MBTEST(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 + 3,
- 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|P_DOLBRACE);
- 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_comsub (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 + 3,
- 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 + 1,
- 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 == '$')
- {
- RESIZE_MALLOCED_BUFFER (token, token_index, 3,
- token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = '$';
- token[token_index++] = peek_char;
- dollar_present = 1;
- all_digit_token = 0;
- goto next_character;
- }
- else
- shell_ungetc (peek_char);
- }
-
-#if defined (ARRAY_VARS)
- /* Identify possible array subscript assignment; match [...]. If
- parser_state&PST_COMPASSIGN, we need to parse [sub]=words treating
- `sub' as if it were enclosed in double quotes. */
- else if MBTEST(character == '[' && /* ] */
- ((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
- (token_index == 0 && (parser_state&PST_COMPASSIGN))))
- {
- ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
- 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:
-
- if (character == CTLESC || character == CTLNUL)
- {
- RESIZE_MALLOCED_BUFFER (token, token_index, 2, token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
- token[token_index++] = CTLESC;
- }
- else
-got_escaped_character:
- RESIZE_MALLOCED_BUFFER (token, token_index, 1, token_buffer_size,
- TOKEN_DEFAULT_GROW_SIZE);
-
- token[token_index++] = character;
-
- all_digit_token &= DIGIT (character);
- dollar_present |= character == '$';
-
- 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:
-
- /* Calls to RESIZE_MALLOCED_BUFFER ensure there is sufficient room. */
- 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)
-#if 0
- yylval.number = lvalue;
- else
- yylval.number = -1;
- return (NUMBER);
-#else
- {
- yylval.number = lvalue;
- return (NUMBER);
- }
-#endif
- }
-
- /* 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;
-
- if (token[0] == '{' && token[token_index-1] == '}' &&
- (character == '<' || character == '>'))
- {
- /* can use token; already copied to the_word */
- token[token_index-1] = '\0';
- if (legal_identifier (token+1))
- {
- strcpy (the_word->word, token+1);
-/*itrace("read_token_word: returning REDIR_WORD for %s", the_word->word);*/
- return (REDIR_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 BAR_AND:
- case DO:
- case DONE:
- case ELIF:
- case ELSE:
- case ESAC:
- case FI:
- case IF:
- case OR_OR:
- case SEMI_SEMI:
- case SEMI_AND:
- case SEMI_SEMI_AND:
- case THEN:
- case TIME:
- case TIMEOPT:
- case TIMEIGN:
- case COPROC:
- case UNTIL:
- case WHILE:
- case 0:
- return 1;
- default:
-#if defined (COPROCESS_SUPPORT)
- if (last_read_token == WORD && token_before_that == COPROC)
- return 1;
-#endif
- if (last_read_token == WORD && token_before_that == FUNCTION)
- return 1;
- 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;
-}
-
-/* An interface to let the rest of the shell (primarily the completion
- system) know what the parser is expecting. */
-int
-parser_in_command_position ()
-{
- return (command_token_position (last_read_token));
-}
-
-#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 const int no_semi_successors[] = {
- '\n', '{', '(', ')', ';', '&', '|',
- CASE, DO, ELSE, IF, SEMI_SEMI, SEMI_AND, SEMI_SEMI_AND, 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. LINE is the line we're about to add; it helps
- make some more intelligent decisions in certain cases. */
-char *
-history_delimiting_chars (line)
- const char *line;
-{
- static int last_was_heredoc = 0; /* was the last entry the start of a here document? */
- register int i;
-
- if ((parser_state & PST_HEREDOC) == 0)
- last_was_heredoc = 0;
-
- if (dstack.delimiter_depth != 0)
- return ("\n");
-
- /* We look for current_command_line_count == 2 because we are looking to
- add the first line of the body of the here document (the second line
- of the command). We also keep LAST_WAS_HEREDOC as a private sentinel
- variable to note when we think we added the first line of a here doc
- (the one with a "<<" somewhere in it) */
- if (parser_state & PST_HEREDOC)
- {
- if (last_was_heredoc)
- {
- last_was_heredoc = 0;
- return "\n";
- }
- return (current_command_line_count == 2 ? "\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 `()' */
-
- /* If we're not in a here document, but we think we're about to parse one,
- and we would otherwise return a `;', return a newline to delimit the
- line with the here-doc delimiter */
- else if ((parser_state & PST_HEREDOC) == 0 && current_command_line_count > 1 && last_read_token == '\n' && strstr (line, "<<"))
- {
- last_was_heredoc = 1;
- return "\n";
- }
-
- 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, last_comsub_pid;
-#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);
-#if defined (HAVE_TZSET)
- sv_tz ("TZ"); /* XXX -- just make sure */
-#endif
- 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';
-
-#if defined (MACOSX)
- /* Convert from "fs" format to "input" format */
- temp = fnx_fromfs (t_string, strlen (t_string));
- if (temp != t_string)
- strcpy (t_string, temp);
-#endif
-
-#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)
- memmove (t_string, t + 1, strlen (t)); /* strlen(t) to copy NULL */
- }
- }
-#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));
-
- temp = trim_pathname (t_string, PATH_MAX - 1);
- /* 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;
- last_comsub_pid = last_command_subst_pid;
- list = expand_prompt_string (result, Q_DOUBLE_QUOTES, 0);
- free (result);
- result = string_list (list);
- dispose_words (list);
- last_command_exit_value = last_exit_value;
- last_command_subst_pid = last_comsub_pid;
- }
- 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, *p;
-
- if (message)
- {
- parser_error (line_number, "%s", message);
- if (interactive && EOF_Reached)
- EOF_Reached = 0;
- last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
- 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)))
- {
- if (ansic_shouldquote (msg))
- {
- p = ansic_quote (msg, 0, NULL);
- free (msg);
- msg = p;
- }
- parser_error (line_number, _("syntax error near unexpected token `%s'"), msg);
- free (msg);
-
- if (interactive == 0)
- print_offending_line ();
-
- last_command_exit_value = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
- 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 = parse_and_execute_level ? EX_BADSYNTAX : EX_BADUSAGE;
-}
-
-/* ??? 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|PST_REPARSE;
-
- 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|PST_REPARSE);
-
- 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 (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->prompt_string_pointer = prompt_string_pointer;
-
- 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)
- ps->pipestatus = save_pipestatus_array ();
-#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;
-
- ps->token = token;
- ps->token_buffer_size = token_buffer_size;
- /* Force reallocation on next call to read_token_word */
- token = 0;
- token_buffer_size = 0;
-
- return (ps);
-}
-
-void
-restore_parser_state (ps)
- sh_parser_state_t *ps;
-{
- 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;
-
- prompt_string_pointer = ps->prompt_string_pointer;
-
- 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)
- restore_pipestatus_array (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;
-
- FREE (token);
- token = ps->token;
- token_buffer_size = ps->token_buffer_size;
-}
-
-sh_input_line_state_t *
-save_input_line_state (ls)
- sh_input_line_state_t *ls;
-{
- if (ls == 0)
- ls = (sh_input_line_state_t *)xmalloc (sizeof (sh_input_line_state_t));
- if (ls == 0)
- return ((sh_input_line_state_t *)NULL);
-
- ls->input_line = shell_input_line;
- ls->input_line_size = shell_input_line_size;
- ls->input_line_len = shell_input_line_len;
- ls->input_line_index = shell_input_line_index;
-
- /* force reallocation */
- shell_input_line = 0;
- shell_input_line_size = shell_input_line_len = shell_input_line_index = 0;
-
- return ls;
-}
-
-void
-restore_input_line_state (ls)
- sh_input_line_state_t *ls;
-{
- FREE (shell_input_line);
- shell_input_line = ls->input_line;
- shell_input_line_size = ls->input_line_size;
- shell_input_line_len = ls->input_line_len;
- shell_input_line_index = ls->input_line_index;
-
- set_line_mbstate ();
-}
-
-/************************************************
- * *
- * 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 */
+++ /dev/null
-/* print_command -- A way to make readable commands from a command tree. */
-
-/* Copyright (C) 1989-2011 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#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_heredoc_header __P((REDIRECT *));
-static void print_heredoc_body __P((REDIRECT *));
-static void print_heredocs __P((REDIRECT *));
-static void print_deferred_heredocs __P((const char *));
-
-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;
-
-int xtrace_fd = -1;
-FILE *xtrace_fp = 0;
-
-#define CHECK_XTRACE_FP xtrace_fp = (xtrace_fp ? xtrace_fp : stderr)
-
-/* shell expansion characters: used in print_redirection_list */
-#define EXPCHAR(c) ((c) == '{' || (c) == '~' || (c) == '$' || (c) == '`')
-
-#define PRINT_DEFERRED_HEREDOCS(x) \
- do { \
- if (deferred_heredocs) \
- print_deferred_heredocs (x); \
- } while (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;
-static int printing_connection;
-static REDIRECT *deferred_heredocs;
-
-/* 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 = 0;
-static int indirection_stringsiz = 0;
-
-/* 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;
- deferred_heredocs = 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;
-{
- char s[3];
-
- 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++;
- printing_connection++;
- make_command_string_internal (command->value.Connection->first);
-
- switch (command->value.Connection->connector)
- {
- case '&':
- case '|':
- {
- char c = command->value.Connection->connector;
-
- s[0] = ' ';
- s[1] = c;
- s[2] = '\0';
-
- print_deferred_heredocs (s);
-
- if (c != '&' || command->value.Connection->second)
- {
- cprintf (" ");
- skip_this_indent++;
- }
- }
- break;
-
- case AND_AND:
- print_deferred_heredocs (" && ");
- if (command->value.Connection->second)
- skip_this_indent++;
- break;
-
- case OR_OR:
- print_deferred_heredocs (" || ");
- if (command->value.Connection->second)
- skip_this_indent++;
- break;
-
- case ';':
- if (deferred_heredocs == 0)
- {
- if (was_heredoc == 0)
- cprintf (";");
- else
- was_heredoc = 0;
- }
- else
- print_deferred_heredocs (inside_function_def ? "" : ";");
-
- 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);
- PRINT_DEFERRED_HEREDOCS ("");
- printing_connection--;
- 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);
- PRINT_DEFERRED_HEREDOCS ("");
- cprintf (" )");
- break;
-
- case cm_coproc:
- cprintf ("coproc %s ", command->value.Coproc->name);
- skip_this_indent++;
- make_command_string_internal (command->value.Coproc->command);
- 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);
-}
-
-void
-xtrace_set (fd, fp)
- int fd;
- FILE *fp;
-{
- if (fd >= 0 && sh_validfd (fd) == 0)
- {
- internal_error (_("xtrace_set: %d: invalid file descriptor"), fd);
- return;
- }
- if (fp == 0)
- {
- internal_error (_("xtrace_set: NULL file pointer"));
- return;
- }
- if (fd >= 0 && fileno (fp) != fd)
- internal_warning (_("xtrace fd (%d) != fileno xtrace fp (%d)"), fd, fileno (fp));
-
- xtrace_fd = fd;
- xtrace_fp = fp;
-}
-
-void
-xtrace_init ()
-{
- xtrace_set (-1, stderr);
-}
-
-void
-xtrace_reset ()
-{
- if (xtrace_fd >= 0 && xtrace_fp)
- {
- fflush (xtrace_fp);
- fclose (xtrace_fp);
- }
- else if (xtrace_fd >= 0)
- close (xtrace_fd);
-
- xtrace_fd = -1;
- xtrace_fp = stderr;
-}
-
-void
-xtrace_fdchk (fd)
- int fd;
-{
- if (fd == xtrace_fd)
- xtrace_reset ();
-}
-
-/* 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, ineed, old;
-
- ps4 = get_string_value ("PS4");
- if (indirection_string == 0)
- indirection_string = xmalloc (indirection_stringsiz = 100);
- indirection_string[0] = '\0';
-
- if (ps4 == 0 || *ps4 == '\0')
- return (indirection_string);
-
- old = change_flag ('x', FLAG_OFF);
- ps4 = decode_prompt_string (ps4);
- if (old)
- 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 || ps4_firstc_len < 0)
- {
- 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
-
- /* Dynamically resize indirection_string so we have room for everything
- and we don't have to truncate ps4 */
- ineed = (ps4_firstc_len * indirection_level) + strlen (ps4);
- if (ineed > indirection_stringsiz - 1)
- {
- indirection_stringsiz = ineed + 1;
- indirection_string = xrealloc (indirection_string, indirection_stringsiz);
- }
-
- for (i = j = 0; ps4_firstc[0] && j < indirection_level && i < indirection_stringsiz - 1; 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 < indirection_stringsiz - 1; 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;
-
- CHECK_XTRACE_FP;
-
- if (xflags)
- fprintf (xtrace_fp, "%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 (xtrace_fp, "%s=(%s)\n", name, nval);
- else
- fprintf (xtrace_fp, "%s=%s\n", name, nval);
-
- if (nval != value)
- FREE (nval);
-
- fflush (xtrace_fp);
-}
-
-/* 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;
-
- CHECK_XTRACE_FP;
-
- if (xtflags)
- fprintf (xtrace_fp, "%s", indirection_level_string ());
-
- for (w = list; w; w = w->next)
- {
- t = w->word->word;
- if (t == 0 || *t == '\0')
- fprintf (xtrace_fp, "''%s", w->next ? " " : "");
- else if (sh_contains_shell_metas (t))
- {
- x = sh_single_quote (t);
- fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
- free (x);
- }
- else if (ansic_shouldquote (t))
- {
- x = ansic_quote (t, 0, (int *)0);
- fprintf (xtrace_fp, "%s%s", x, w->next ? " " : "");
- free (x);
- }
- else
- fprintf (xtrace_fp, "%s%s", t, w->next ? " " : "");
- }
- fprintf (xtrace_fp, "\n");
- fflush (xtrace_fp);
-}
-
-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;
-{
- CHECK_XTRACE_FP;
- fprintf (xtrace_fp, "%s", indirection_level_string ());
- fprintf (xtrace_fp, "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);
- PRINT_DEFERRED_HEREDOCS ("");
- 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);
- PRINT_DEFERRED_HEREDOCS ("");
- 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;
-{
- CHECK_XTRACE_FP;
- fprintf (xtrace_fp, "%s", indirection_level_string ());
- fprintf (xtrace_fp, "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);
- PRINT_DEFERRED_HEREDOCS ("");
- 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);
- PRINT_DEFERRED_HEREDOCS ("");
-
- 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;
-{
- CHECK_XTRACE_FP;
- fprintf (xtrace_fp, "%s", indirection_level_string ());
- fprintf (xtrace_fp, "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;
- PRINT_DEFERRED_HEREDOCS ("");
- if (clauses->flags & CASEPAT_FALLTHROUGH)
- newline (";&");
- else if (clauses->flags & CASEPAT_TESTNEXT)
- newline (";;&");
- else
- 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);
- PRINT_DEFERRED_HEREDOCS ("");
- semicolon ();
- cprintf (" do\n"); /* was newline ("do\n"); */
- indentation += indentation_amount;
- make_command_string_internal (while_command->action);
- PRINT_DEFERRED_HEREDOCS ("");
- 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);
- PRINT_DEFERRED_HEREDOCS ("");
- indentation -= indentation_amount;
-
- if (if_command->false_case)
- {
- semicolon ();
- newline ("else\n");
- indentation += indentation_amount;
- make_command_string_internal (if_command->false_case);
- PRINT_DEFERRED_HEREDOCS ("");
- 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;
-{
- CHECK_XTRACE_FP;
- command_string_index = 0;
- fprintf (xtrace_fp, "%s", indirection_level_string ());
- fprintf (xtrace_fp, "[[ ");
- if (invert)
- fprintf (xtrace_fp, "! ");
-
- if (type == COND_UNARY)
- {
- fprintf (xtrace_fp, "%s ", op->word);
- fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
- }
- else if (type == COND_BINARY)
- {
- fprintf (xtrace_fp, "%s", (arg1 && *arg1) ? arg1 : "''");
- fprintf (xtrace_fp, " %s ", op->word);
- fprintf (xtrace_fp, "%s", (arg2 && *arg2) ? arg2 : "''");
- }
-
- fprintf (xtrace_fp, " ]]\n");
-
- fflush (xtrace_fp);
-}
-#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;
-
- CHECK_XTRACE_FP;
- fprintf (xtrace_fp, "%s", indirection_level_string ());
- fprintf (xtrace_fp, "(( ");
- for (w = list; w; w = w->next)
- fprintf (xtrace_fp, "%s%s", w->word->word, w->next ? " " : "");
- fprintf (xtrace_fp, " ))\n");
-
- fflush (xtrace_fp);
-}
-#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_heredocs (heredocs)
- REDIRECT *heredocs;
-{
- REDIRECT *hdtail;
-
- cprintf (" ");
- for (hdtail = heredocs; hdtail; hdtail = hdtail->next)
- {
- print_redirection (hdtail);
- cprintf ("\n");
- }
- was_heredoc = 1;
-}
-
-/* Print heredocs that are attached to the command before the connector
- represented by CSTRING. The parsing semantics require us to print the
- here-doc delimiters, then the connector (CSTRING), then the here-doc
- bodies. We don't print the connector if it's a `;', but we use it to
- note not to print an extra space after the last heredoc body and
- newline. */
-static void
-print_deferred_heredocs (cstring)
- const char *cstring;
-{
- REDIRECT *hdtail;
-
- for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
- {
- cprintf (" ");
- print_heredoc_header (hdtail);
- }
- if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
- cprintf ("%s", cstring);
- if (deferred_heredocs)
- cprintf ("\n");
- for (hdtail = deferred_heredocs; hdtail; hdtail = hdtail->next)
- {
- print_heredoc_body (hdtail);
- cprintf ("\n");
- }
- if (deferred_heredocs)
- {
- if (cstring && cstring[0] && (cstring[0] != ';' || cstring[1]))
- cprintf (" "); /* make sure there's at least one space */
- dispose_redirects (deferred_heredocs);
- was_heredoc = 1;
- }
- deferred_heredocs = (REDIRECT *)NULL;
-}
-
-static void
-print_redirection_list (redirects)
- REDIRECT *redirects;
-{
- REDIRECT *heredocs, *hdtail, *newredir;
- char *rw;
-
- 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->flags & REDIR_VARASSIGN) == 0 && redirects->redirector.dest == 1)
- {
- /* Temporarily translate it as the execution code does. */
- rw = redirects->redirectee.filename->word;
- if (rw && *rw != '-' && DIGIT (*rw) == 0 && EXPCHAR (*rw) == 0)
- 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 && printing_connection)
- deferred_heredocs = heredocs;
- else if (heredocs)
- {
- print_heredocs (heredocs);
- dispose_redirects (heredocs);
- }
-}
-
-static void
-print_heredoc_header (redirect)
- REDIRECT *redirect;
-{
- int kill_leading;
- char *x;
-
- kill_leading = redirect->instruction == r_deblank_reading_until;
-
- /* Here doc header */
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}", redirect->redirector.filename->word);
- else if (redirect->redirector.dest != 0)
- cprintf ("%d", redirect->redirector.dest);
-
- /* If the here document delimiter is quoted, single-quote it. */
- if (redirect->redirectee.filename->flags & W_QUOTED)
- {
- x = sh_single_quote (redirect->here_doc_eof);
- cprintf ("<<%s%s", kill_leading ? "-" : "", x);
- free (x);
- }
- else
- cprintf ("<<%s%s", kill_leading ? "-" : "", redirect->here_doc_eof);
-}
-
-static void
-print_heredoc_body (redirect)
- REDIRECT *redirect;
-{
- /* Here doc body */
- cprintf ("%s%s", redirect->redirectee.filename->word, redirect->here_doc_eof);
-}
-
-static void
-print_redirection (redirect)
- REDIRECT *redirect;
-{
- int redirector, redir_fd;
- WORD_DESC *redirectee, *redir_word;
-
- redirectee = redirect->redirectee.filename;
- redir_fd = redirect->redirectee.dest;
-
- redir_word = redirect->redirector.filename;
- redirector = redirect->redirector.dest;
-
- switch (redirect->instruction)
- {
- case r_input_direction:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}", redir_word->word);
- else if (redirector != 0)
- cprintf ("%d", redirector);
- cprintf ("< %s", redirectee->word);
- break;
-
- case r_output_direction:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}", redir_word->word);
- else if (redirector != 1)
- cprintf ("%d", redirector);
- cprintf ("> %s", redirectee->word);
- break;
-
- case r_inputa_direction: /* Redirection created by the shell. */
- cprintf ("&");
- break;
-
- case r_output_force:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}", redir_word->word);
- else if (redirector != 1)
- cprintf ("%d", redirector);
- cprintf (">|%s", redirectee->word);
- break;
-
- case r_appending_to:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}", redir_word->word);
- else if (redirector != 1)
- cprintf ("%d", redirector);
- cprintf (">> %s", redirectee->word);
- break;
-
- case r_input_output:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}", redir_word->word);
- else if (redirector != 1)
- cprintf ("%d", redirector);
- cprintf ("<> %s", redirectee->word);
- break;
-
- case r_deblank_reading_until:
- case r_reading_until:
- print_heredoc_header (redirect);
- cprintf ("\n");
- print_heredoc_body (redirect);
- break;
-
- case r_reading_string:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}", redir_word->word);
- else if (redirector != 0)
- cprintf ("%d", redirector);
-#if 0
- /* Don't need to check whether or not to requote, since original quotes
- are still intact. The only thing that has happened is that $'...'
- has been replaced with 'expanded ...'. */
- 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
-#endif
- cprintf ("<<< %s", redirect->redirectee.filename->word);
- break;
-
- case r_duplicating_input:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}<&%d", redir_word->word, redir_fd);
- else
- cprintf ("%d<&%d", redirector, redir_fd);
- break;
-
- case r_duplicating_output:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}>&%d", redir_word->word, redir_fd);
- else
- cprintf ("%d>&%d", redirector, redir_fd);
- break;
-
- case r_duplicating_input_word:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}<&%s", redir_word->word, redirectee->word);
- else
- cprintf ("%d<&%s", redirector, redirectee->word);
- break;
-
- case r_duplicating_output_word:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}>&%s", redir_word->word, redirectee->word);
- else
- cprintf ("%d>&%s", redirector, redirectee->word);
- break;
-
- case r_move_input:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}<&%d-", redir_word->word, redir_fd);
- else
- cprintf ("%d<&%d-", redirector, redir_fd);
- break;
-
- case r_move_output:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}>&%d-", redir_word->word, redir_fd);
- else
- cprintf ("%d>&%d-", redirector, redir_fd);
- break;
-
- case r_move_input_word:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}<&%s-", redir_word->word, redirectee->word);
- else
- cprintf ("%d<&%s-", redirector, redirectee->word);
- break;
-
- case r_move_output_word:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}>&%s-", redir_word->word, redirectee->word);
- else
- cprintf ("%d>&%s-", redirector, redirectee->word);
- break;
-
- case r_close_this:
- if (redirect->rflags & REDIR_VARASSIGN)
- cprintf ("{%s}>&-", redir_word->word);
- else
- cprintf ("%d>&-", redirector);
- break;
-
- case r_err_and_out:
- cprintf ("&>%s", redirectee->word);
- break;
-
- case r_append_err_and_out:
- cprintf ("&>>%s", redirectee->word);
- break;
- }
-}
-
-static void
-reset_locals ()
-{
- inside_function_def = 0;
- indentation = 0;
- printing_connection = 0;
- deferred_heredocs = 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);
- /* XXX - PRINT_DEFERRED_HEREDOCS (""); ? */
-
- 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.
- flags&FUNC_MULTILINE is non-zero to pretty-print, or zero for all on one line.
- flags&FUNC_EXTERNAL means convert from internal to external form
- */
-char *
-named_function_string (name, command, flags)
- char *name;
- COMMAND *command;
- int flags;
-{
- 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;
- deferred_heredocs = 0;
-
- if (name && *name)
- cprintf ("%s ", name);
-
- cprintf ("() ");
-
- if ((flags & FUNC_MULTILINE) == 0)
- {
- indentation = 1;
- indentation_amount = 0;
- }
- else
- {
- cprintf ("\n");
- indentation += indentation_amount;
- }
-
- inside_function_def++;
-
- cprintf ((flags & FUNC_MULTILINE) ? "{ \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);
- /* XXX - PRINT_DEFERRED_HEREDOCS (""); ? */
-
- 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 ((flags & FUNC_MULTILINE) == 0)
- {
-#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 */
- memmove (result + 2, result + 3, strlen (result) - 2);
-
-#endif
- }
-
- dispose_command (cmdcopy);
-
- if (flags & FUNC_EXTERNAL)
- result = remove_quoted_escapes (result);
-
- 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;
- }
- }
-
- va_end (args);
-
- 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 */
+++ /dev/null
-/* redir.c -- Functions to perform input and output redirection. */
-
-/* Copyright (C) 1997-2009 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "config.h"
-
-#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
- #pragma alloca
-#endif /* _AIX && RISC6000 && !__GNUC__ */
-
-#include <stdio.h>
-#include "bashtypes.h"
-#if !defined (_MINIX) && defined (HAVE_SYS_FILE_H)
-# include <sys/file.h>
-#endif
-#include "filecntl.h"
-#include "posixstat.h"
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#include <errno.h>
-
-#if !defined (errno)
-extern int errno;
-#endif
-
-#include "bashansi.h"
-#include "bashintl.h"
-#include "memalloc.h"
-
-#define NEED_FPURGE_DECL
-
-#include "shell.h"
-#include "flags.h"
-#include "execute_cmd.h"
-#include "redir.h"
-
-#if defined (BUFFERED_INPUT)
-# include "input.h"
-#endif
-
-#define SHELL_FD_BASE 10
-
-int expanding_redir;
-
-extern int posixly_correct;
-extern int last_command_exit_value;
-extern REDIRECT *redirection_undo_list;
-extern REDIRECT *exec_redirection_undo_list;
-
-/* Static functions defined and used in this file. */
-static void add_exec_redirect __P((REDIRECT *));
-static int add_undo_redirect __P((int, enum r_instruction, int));
-static int add_undo_close_redirect __P((int));
-static int expandable_redirection_filename __P((REDIRECT *));
-static int stdin_redirection __P((enum r_instruction, int));
-static int undoablefd __P((int));
-static int do_redirection_internal __P((REDIRECT *, int));
-
-static int write_here_document __P((int, WORD_DESC *));
-static int write_here_string __P((int, WORD_DESC *));
-static int here_document_to_fd __P((WORD_DESC *, enum r_instruction));
-
-static int redir_special_open __P((int, char *, int, int, enum r_instruction));
-static int noclobber_open __P((char *, int, int, enum r_instruction));
-static int redir_open __P((char *, int, int, enum r_instruction));
-
-static int redir_varassign __P((REDIRECT *, int));
-static int redir_varvalue __P((REDIRECT *));
-
-/* Spare redirector used when translating [N]>&WORD[-] or [N]<&WORD[-] to
- a new redirection and when creating the redirection undo list. */
-static REDIRECTEE rd;
-
-/* Set to errno when a here document cannot be created for some reason.
- Used to print a reasonable error message. */
-static int heredoc_errno;
-
-#define REDIRECTION_ERROR(r, e, fd) \
-do { \
- if ((r) < 0) \
- { \
- if (fd >= 0) \
- close (fd); \
- last_command_exit_value = EXECUTION_FAILURE;\
- return ((e) == 0 ? EINVAL : (e));\
- } \
-} while (0)
-
-void
-redirection_error (temp, error)
- REDIRECT *temp;
- int error;
-{
- char *filename, *allocname;
- int oflags;
-
- allocname = 0;
- if (temp->rflags & REDIR_VARASSIGN)
- filename = allocname = savestring (temp->redirector.filename->word);
- else if (temp->redirector.dest < 0)
- /* This can happen when read_token_word encounters overflow, like in
- exec 4294967297>x */
- filename = _("file descriptor out of range");
-#ifdef EBADF
- /* This error can never involve NOCLOBBER */
- else if (error != NOCLOBBER_REDIRECT && temp->redirector.dest >= 0 && error == EBADF)
- {
- /* If we're dealing with two file descriptors, we have to guess about
- which one is invalid; in the cases of r_{duplicating,move}_input and
- r_{duplicating,move}_output we're here because dup2() failed. */
- switch (temp->instruction)
- {
- case r_duplicating_input:
- case r_duplicating_output:
- case r_move_input:
- case r_move_output:
- filename = allocname = itos (temp->redirectee.dest);
- break;
- case r_duplicating_input_word:
- if (temp->redirector.dest == 0) /* Guess */
- filename = temp->redirectee.filename->word; /* XXX */
- else
- filename = allocname = itos (temp->redirector.dest);
- break;
- case r_duplicating_output_word:
- if (temp->redirector.dest == 1) /* Guess */
- filename = temp->redirectee.filename->word; /* XXX */
- else
- filename = allocname = itos (temp->redirector.dest);
- break;
- default:
- filename = allocname = itos (temp->redirector.dest);
- break;
- }
- }
-#endif
- else if (expandable_redirection_filename (temp))
- {
-expandable_filename:
- if (posixly_correct && interactive_shell == 0)
- {
- oflags = temp->redirectee.filename->flags;
- temp->redirectee.filename->flags |= W_NOGLOB;
- }
- filename = allocname = redirection_expand (temp->redirectee.filename);
- if (posixly_correct && interactive_shell == 0)
- temp->redirectee.filename->flags = oflags;
- if (filename == 0)
- filename = temp->redirectee.filename->word;
- }
- else if (temp->redirectee.dest < 0)
- filename = "file descriptor out of range";
- else
- filename = allocname = itos (temp->redirectee.dest);
-
- switch (error)
- {
- case AMBIGUOUS_REDIRECT:
- internal_error (_("%s: ambiguous redirect"), filename);
- break;
-
- case NOCLOBBER_REDIRECT:
- internal_error (_("%s: cannot overwrite existing file"), filename);
- break;
-
-#if defined (RESTRICTED_SHELL)
- case RESTRICTED_REDIRECT:
- internal_error (_("%s: restricted: cannot redirect output"), filename);
- break;
-#endif /* RESTRICTED_SHELL */
-
- case HEREDOC_REDIRECT:
- internal_error (_("cannot create temp file for here-document: %s"), strerror (heredoc_errno));
- break;
-
- case BADVAR_REDIRECT:
- internal_error (_("%s: cannot assign fd to variable"), filename);
- break;
-
- default:
- internal_error ("%s: %s", filename, strerror (error));
- break;
- }
-
- FREE (allocname);
-}
-
-/* Perform the redirections on LIST. If flags & RX_ACTIVE, then actually
- make input and output file descriptors, otherwise just do whatever is
- neccessary for side effecting. flags & RX_UNDOABLE says to remember
- how to undo the redirections later, if non-zero. If flags & RX_CLEXEC
- is non-zero, file descriptors opened in do_redirection () have their
- close-on-exec flag set. */
-int
-do_redirections (list, flags)
- REDIRECT *list;
- int flags;
-{
- int error;
- REDIRECT *temp;
-
- if (flags & RX_UNDOABLE)
- {
- if (redirection_undo_list)
- {
- dispose_redirects (redirection_undo_list);
- redirection_undo_list = (REDIRECT *)NULL;
- }
- if (exec_redirection_undo_list)
- dispose_exec_redirects ();
- }
-
- for (temp = list; temp; temp = temp->next)
- {
- error = do_redirection_internal (temp, flags);
- if (error)
- {
- redirection_error (temp, error);
- return (error);
- }
- }
- return (0);
-}
-
-/* Return non-zero if the redirection pointed to by REDIRECT has a
- redirectee.filename that can be expanded. */
-static int
-expandable_redirection_filename (redirect)
- REDIRECT *redirect;
-{
- switch (redirect->instruction)
- {
- case r_output_direction:
- case r_appending_to:
- case r_input_direction:
- case r_inputa_direction:
- case r_err_and_out:
- case r_append_err_and_out:
- case r_input_output:
- case r_output_force:
- case r_duplicating_input_word:
- case r_duplicating_output_word:
- case r_move_input_word:
- case r_move_output_word:
- return 1;
-
- default:
- return 0;
- }
-}
-
-/* Expand the word in WORD returning a string. If WORD expands to
- multiple words (or no words), then return NULL. */
-char *
-redirection_expand (word)
- WORD_DESC *word;
-{
- char *result;
- WORD_LIST *tlist1, *tlist2;
- WORD_DESC *w;
-
- w = copy_word (word);
- if (posixly_correct)
- w->flags |= W_NOSPLIT;
-
- tlist1 = make_word_list (w, (WORD_LIST *)NULL);
- expanding_redir = 1;
- tlist2 = expand_words_no_vars (tlist1);
- expanding_redir = 0;
- dispose_words (tlist1);
-
- if (!tlist2 || tlist2->next)
- {
- /* We expanded to no words, or to more than a single word.
- Dispose of the word list and return NULL. */
- if (tlist2)
- dispose_words (tlist2);
- return ((char *)NULL);
- }
- result = string_list (tlist2); /* XXX savestring (tlist2->word->word)? */
- dispose_words (tlist2);
- return (result);
-}
-
-static int
-write_here_string (fd, redirectee)
- int fd;
- WORD_DESC *redirectee;
-{
- char *herestr;
- int herelen, n, e;
-
- expanding_redir = 1;
- herestr = expand_string_to_string (redirectee->word, 0);
- expanding_redir = 0;
- herelen = STRLEN (herestr);
-
- n = write (fd, herestr, herelen);
- if (n == herelen)
- {
- n = write (fd, "\n", 1);
- herelen = 1;
- }
- e = errno;
- FREE (herestr);
- if (n != herelen)
- {
- if (e == 0)
- e = ENOSPC;
- return e;
- }
- return 0;
-}
-
-/* Write the text of the here document pointed to by REDIRECTEE to the file
- descriptor FD, which is already open to a temp file. Return 0 if the
- write is successful, otherwise return errno. */
-static int
-write_here_document (fd, redirectee)
- int fd;
- WORD_DESC *redirectee;
-{
- char *document;
- int document_len, fd2;
- FILE *fp;
- register WORD_LIST *t, *tlist;
-
- /* Expand the text if the word that was specified had
- no quoting. The text that we expand is treated
- exactly as if it were surrounded by double quotes. */
-
- if (redirectee->flags & W_QUOTED)
- {
- document = redirectee->word;
- document_len = strlen (document);
- /* Set errno to something reasonable if the write fails. */
- if (write (fd, document, document_len) < document_len)
- {
- if (errno == 0)
- errno = ENOSPC;
- return (errno);
- }
- else
- return 0;
- }
-
- expanding_redir = 1;
- tlist = expand_string (redirectee->word, Q_HERE_DOCUMENT);
- expanding_redir = 0;
-
- if (tlist)
- {
- /* Try using buffered I/O (stdio) and writing a word
- at a time, letting stdio do the work of buffering
- for us rather than managing our own strings. Most
- stdios are not particularly fast, however -- this
- may need to be reconsidered later. */
- if ((fd2 = dup (fd)) < 0 || (fp = fdopen (fd2, "w")) == NULL)
- {
- if (fd2 >= 0)
- close (fd2);
- return (errno);
- }
- errno = 0;
- for (t = tlist; t; t = t->next)
- {
- /* This is essentially the body of
- string_list_internal expanded inline. */
- document = t->word->word;
- document_len = strlen (document);
- if (t != tlist)
- putc (' ', fp); /* separator */
- fwrite (document, document_len, 1, fp);
- if (ferror (fp))
- {
- if (errno == 0)
- errno = ENOSPC;
- fd2 = errno;
- fclose(fp);
- dispose_words (tlist);
- return (fd2);
- }
- }
- dispose_words (tlist);
- if (fclose (fp) != 0)
- {
- if (errno == 0)
- errno = ENOSPC;
- return (errno);
- }
- }
- return 0;
-}
-
-/* Create a temporary file holding the text of the here document pointed to
- by REDIRECTEE, and return a file descriptor open for reading to the temp
- file. Return -1 on any error, and make sure errno is set appropriately. */
-static int
-here_document_to_fd (redirectee, ri)
- WORD_DESC *redirectee;
- enum r_instruction ri;
-{
- char *filename;
- int r, fd, fd2;
-
- fd = sh_mktmpfd ("sh-thd", MT_USERANDOM|MT_USETMPDIR, &filename);
-
- /* If we failed for some reason other than the file existing, abort */
- if (fd < 0)
- {
- FREE (filename);
- return (fd);
- }
-
- errno = r = 0; /* XXX */
- /* write_here_document returns 0 on success, errno on failure. */
- if (redirectee->word)
- r = (ri != r_reading_string) ? write_here_document (fd, redirectee)
- : write_here_string (fd, redirectee);
-
- if (r)
- {
- close (fd);
- unlink (filename);
- free (filename);
- errno = r;
- return (-1);
- }
-
- /* In an attempt to avoid races, we close the first fd only after opening
- the second. */
- /* Make the document really temporary. Also make it the input. */
- fd2 = open (filename, O_RDONLY|O_BINARY, 0600);
-
- if (fd2 < 0)
- {
- r = errno;
- unlink (filename);
- free (filename);
- close (fd);
- errno = r;
- return -1;
- }
-
- close (fd);
- if (unlink (filename) < 0)
- {
- r = errno;
- close (fd2);
- free (filename);
- errno = r;
- return (-1);
- }
-
- free (filename);
- return (fd2);
-}
-
-#define RF_DEVFD 1
-#define RF_DEVSTDERR 2
-#define RF_DEVSTDIN 3
-#define RF_DEVSTDOUT 4
-#define RF_DEVTCP 5
-#define RF_DEVUDP 6
-
-/* A list of pattern/value pairs for filenames that the redirection
- code handles specially. */
-static STRING_INT_ALIST _redir_special_filenames[] = {
-#if !defined (HAVE_DEV_FD)
- { "/dev/fd/[0-9]*", RF_DEVFD },
-#endif
-#if !defined (HAVE_DEV_STDIN)
- { "/dev/stderr", RF_DEVSTDERR },
- { "/dev/stdin", RF_DEVSTDIN },
- { "/dev/stdout", RF_DEVSTDOUT },
-#endif
-#if defined (NETWORK_REDIRECTIONS)
- { "/dev/tcp/*/*", RF_DEVTCP },
- { "/dev/udp/*/*", RF_DEVUDP },
-#endif
- { (char *)NULL, -1 }
-};
-
-static int
-redir_special_open (spec, filename, flags, mode, ri)
- int spec;
- char *filename;
- int flags, mode;
- enum r_instruction ri;
-{
- int fd;
-#if !defined (HAVE_DEV_FD)
- intmax_t lfd;
-#endif
-
- fd = -1;
- switch (spec)
- {
-#if !defined (HAVE_DEV_FD)
- case RF_DEVFD:
- if (all_digits (filename+8) && legal_number (filename+8, &lfd) && lfd == (int)lfd)
- {
- fd = lfd;
- fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
- }
- else
- fd = AMBIGUOUS_REDIRECT;
- break;
-#endif
-
-#if !defined (HAVE_DEV_STDIN)
- case RF_DEVSTDIN:
- fd = fcntl (0, F_DUPFD, SHELL_FD_BASE);
- break;
- case RF_DEVSTDOUT:
- fd = fcntl (1, F_DUPFD, SHELL_FD_BASE);
- break;
- case RF_DEVSTDERR:
- fd = fcntl (2, F_DUPFD, SHELL_FD_BASE);
- break;
-#endif
-
-#if defined (NETWORK_REDIRECTIONS)
- case RF_DEVTCP:
- case RF_DEVUDP:
-#if defined (HAVE_NETWORK)
- fd = netopen (filename);
-#else
- internal_warning (_("/dev/(tcp|udp)/host/port not supported without networking"));
- fd = open (filename, flags, mode);
-#endif
- break;
-#endif /* NETWORK_REDIRECTIONS */
- }
-
- return fd;
-}
-
-/* Open FILENAME with FLAGS in noclobber mode, hopefully avoiding most
- race conditions and avoiding the problem where the file is replaced
- between the stat(2) and open(2). */
-static int
-noclobber_open (filename, flags, mode, ri)
- char *filename;
- int flags, mode;
- enum r_instruction ri;
-{
- int r, fd;
- struct stat finfo, finfo2;
-
- /* If the file exists and is a regular file, return an error
- immediately. */
- r = stat (filename, &finfo);
- if (r == 0 && (S_ISREG (finfo.st_mode)))
- return (NOCLOBBER_REDIRECT);
-
- /* If the file was not present (r != 0), make sure we open it
- exclusively so that if it is created before we open it, our open
- will fail. Make sure that we do not truncate an existing file.
- Note that we don't turn on O_EXCL unless the stat failed -- if
- the file was not a regular file, we leave O_EXCL off. */
- flags &= ~O_TRUNC;
- if (r != 0)
- {
- fd = open (filename, flags|O_EXCL, mode);
- return ((fd < 0 && errno == EEXIST) ? NOCLOBBER_REDIRECT : fd);
- }
- fd = open (filename, flags, mode);
-
- /* If the open failed, return the file descriptor right away. */
- if (fd < 0)
- return (errno == EEXIST ? NOCLOBBER_REDIRECT : fd);
-
- /* OK, the open succeeded, but the file may have been changed from a
- non-regular file to a regular file between the stat and the open.
- We are assuming that the O_EXCL open handles the case where FILENAME
- did not exist and is symlinked to an existing file between the stat
- and open. */
-
- /* If we can open it and fstat the file descriptor, and neither check
- revealed that it was a regular file, and the file has not been replaced,
- return the file descriptor. */
- if ((fstat (fd, &finfo2) == 0) && (S_ISREG (finfo2.st_mode) == 0) &&
- r == 0 && (S_ISREG (finfo.st_mode) == 0) &&
- same_file (filename, filename, &finfo, &finfo2))
- return fd;
-
- /* The file has been replaced. badness. */
- close (fd);
- errno = EEXIST;
- return (NOCLOBBER_REDIRECT);
-}
-
-static int
-redir_open (filename, flags, mode, ri)
- char *filename;
- int flags, mode;
- enum r_instruction ri;
-{
- int fd, r;
-
- r = find_string_in_alist (filename, _redir_special_filenames, 1);
- if (r >= 0)
- return (redir_special_open (r, filename, flags, mode, ri));
-
- /* If we are in noclobber mode, you are not allowed to overwrite
- existing files. Check before opening. */
- if (noclobber && CLOBBERING_REDIRECT (ri))
- {
- fd = noclobber_open (filename, flags, mode, ri);
- if (fd == NOCLOBBER_REDIRECT)
- return (NOCLOBBER_REDIRECT);
- }
- else
- {
- fd = open (filename, flags, mode);
-#if defined (AFS)
- if ((fd < 0) && (errno == EACCES))
- {
- fd = open (filename, flags & ~O_CREAT, mode);
- errno = EACCES; /* restore errno */
- }
-#endif /* AFS */
- }
-
- return fd;
-}
-
-static int
-undoablefd (fd)
- int fd;
-{
- int clexec;
-
- clexec = fcntl (fd, F_GETFD, 0);
- if (clexec == -1 || (fd >= SHELL_FD_BASE && clexec == 1))
- return 0;
- return 1;
-}
-
-/* Do the specific redirection requested. Returns errno or one of the
- special redirection errors (*_REDIRECT) in case of error, 0 on success.
- If flags & RX_ACTIVE is zero, then just do whatever is neccessary to
- produce the appropriate side effects. flags & RX_UNDOABLE, if non-zero,
- says to remember how to undo each redirection. If flags & RX_CLEXEC is
- non-zero, then we set all file descriptors > 2 that we open to be
- close-on-exec. */
-static int
-do_redirection_internal (redirect, flags)
- REDIRECT *redirect;
- int flags;
-{
- WORD_DESC *redirectee;
- int redir_fd, fd, redirector, r, oflags;
- intmax_t lfd;
- char *redirectee_word;
- enum r_instruction ri;
- REDIRECT *new_redirect;
- REDIRECTEE sd;
-
- redirectee = redirect->redirectee.filename;
- redir_fd = redirect->redirectee.dest;
- redirector = redirect->redirector.dest;
- ri = redirect->instruction;
-
- if (redirect->flags & RX_INTERNAL)
- flags |= RX_INTERNAL;
-
- if (TRANSLATE_REDIRECT (ri))
- {
- /* We have [N]>&WORD[-] or [N]<&WORD[-] (or {V}>&WORD[-] or {V}<&WORD-).
- and WORD, then translate the redirection into a new one and
- continue. */
- redirectee_word = redirection_expand (redirectee);
-
- /* XXX - what to do with [N]<&$w- where w is unset or null? ksh93
- closes N. */
- if (redirectee_word == 0)
- return (AMBIGUOUS_REDIRECT);
- else if (redirectee_word[0] == '-' && redirectee_word[1] == '\0')
- {
- sd = redirect->redirector;
- rd.dest = 0;
- new_redirect = make_redirection (sd, r_close_this, rd, 0);
- }
- else if (all_digits (redirectee_word))
- {
- sd = redirect->redirector;
- if (legal_number (redirectee_word, &lfd) && (int)lfd == lfd)
- rd.dest = lfd;
- else
- rd.dest = -1; /* XXX */
- switch (ri)
- {
- case r_duplicating_input_word:
- new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
- break;
- case r_duplicating_output_word:
- new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
- break;
- case r_move_input_word:
- new_redirect = make_redirection (sd, r_move_input, rd, 0);
- break;
- case r_move_output_word:
- new_redirect = make_redirection (sd, r_move_output, rd, 0);
- break;
- }
- }
- else if (ri == r_duplicating_output_word && (redirect->rflags & REDIR_VARASSIGN) == 0 && redirector == 1)
- {
- sd = redirect->redirector;
- rd.filename = make_bare_word (redirectee_word);
- new_redirect = make_redirection (sd, r_err_and_out, rd, 0);
- }
- else
- {
- free (redirectee_word);
- return (AMBIGUOUS_REDIRECT);
- }
-
- free (redirectee_word);
-
- /* Set up the variables needed by the rest of the function from the
- new redirection. */
- if (new_redirect->instruction == r_err_and_out)
- {
- char *alloca_hack;
-
- /* Copy the word without allocating any memory that must be
- explicitly freed. */
- redirectee = (WORD_DESC *)alloca (sizeof (WORD_DESC));
- xbcopy ((char *)new_redirect->redirectee.filename,
- (char *)redirectee, sizeof (WORD_DESC));
-
- alloca_hack = (char *)
- alloca (1 + strlen (new_redirect->redirectee.filename->word));
- redirectee->word = alloca_hack;
- strcpy (redirectee->word, new_redirect->redirectee.filename->word);
- }
- else
- /* It's guaranteed to be an integer, and shouldn't be freed. */
- redirectee = new_redirect->redirectee.filename;
-
- redir_fd = new_redirect->redirectee.dest;
- redirector = new_redirect->redirector.dest;
- ri = new_redirect->instruction;
-
- /* Overwrite the flags element of the old redirect with the new value. */
- redirect->flags = new_redirect->flags;
- dispose_redirects (new_redirect);
- }
-
- switch (ri)
- {
- case r_output_direction:
- case r_appending_to:
- case r_input_direction:
- case r_inputa_direction:
- case r_err_and_out: /* command &>filename */
- case r_append_err_and_out: /* command &>> filename */
- case r_input_output:
- case r_output_force:
- if (posixly_correct && interactive_shell == 0)
- {
- oflags = redirectee->flags;
- redirectee->flags |= W_NOGLOB;
- }
- redirectee_word = redirection_expand (redirectee);
- if (posixly_correct && interactive_shell == 0)
- redirectee->flags = oflags;
-
- if (redirectee_word == 0)
- return (AMBIGUOUS_REDIRECT);
-
-#if defined (RESTRICTED_SHELL)
- if (restricted && (WRITE_REDIRECT (ri)))
- {
- free (redirectee_word);
- return (RESTRICTED_REDIRECT);
- }
-#endif /* RESTRICTED_SHELL */
-
- fd = redir_open (redirectee_word, redirect->flags, 0666, ri);
- free (redirectee_word);
-
- if (fd == NOCLOBBER_REDIRECT)
- return (fd);
-
- if (fd < 0)
- return (errno);
-
- if (flags & RX_ACTIVE)
- {
- if (redirect->rflags & REDIR_VARASSIGN)
- {
- redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE); /* XXX try this for now */
- r = errno;
- if (redirector < 0)
- sys_error (_("redirection error: cannot duplicate fd"));
- REDIRECTION_ERROR (redirector, r, fd);
- }
-
- if (flags & RX_UNDOABLE)
- {
- /* Only setup to undo it if the thing to undo is active. */
- if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
- r = add_undo_redirect (redirector, ri, -1);
- else
- r = add_undo_close_redirect (redirector);
- if (r < 0 && (redirect->rflags & REDIR_VARASSIGN))
- close (redirector);
- REDIRECTION_ERROR (r, errno, fd);
- }
-
-#if defined (BUFFERED_INPUT)
- check_bash_input (redirector);
-#endif
-
- /* Make sure there is no pending output before we change the state
- of the underlying file descriptor, since the builtins use stdio
- for output. */
- if (redirector == 1 && fileno (stdout) == redirector)
- {
- fflush (stdout);
- fpurge (stdout);
- }
- else if (redirector == 2 && fileno (stderr) == redirector)
- {
- fflush (stderr);
- fpurge (stderr);
- }
-
- if (redirect->rflags & REDIR_VARASSIGN)
- {
- if ((r = redir_varassign (redirect, redirector)) < 0)
- {
- close (redirector);
- close (fd);
- return (r); /* XXX */
- }
- }
- else if ((fd != redirector) && (dup2 (fd, redirector) < 0))
- return (errno);
-
-#if defined (BUFFERED_INPUT)
- /* Do not change the buffered stream for an implicit redirection
- of /dev/null to fd 0 for asynchronous commands without job
- control (r_inputa_direction). */
- if (ri == r_input_direction || ri == r_input_output)
- duplicate_buffered_stream (fd, redirector);
-#endif /* BUFFERED_INPUT */
-
- /*
- * If we're remembering, then this is the result of a while, for
- * or until loop with a loop redirection, or a function/builtin
- * executing in the parent shell with a redirection. In the
- * function/builtin case, we want to set all file descriptors > 2
- * to be close-on-exec to duplicate the effect of the old
- * for i = 3 to NOFILE close(i) loop. In the case of the loops,
- * both sh and ksh leave the file descriptors open across execs.
- * The Posix standard mentions only the exec builtin.
- */
- if ((flags & RX_CLEXEC) && (redirector > 2))
- SET_CLOSE_ON_EXEC (redirector);
- }
-
- if (fd != redirector)
- {
-#if defined (BUFFERED_INPUT)
- if (INPUT_REDIRECT (ri))
- close_buffered_fd (fd);
- else
-#endif /* !BUFFERED_INPUT */
- close (fd); /* Don't close what we just opened! */
- }
-
- /* If we are hacking both stdout and stderr, do the stderr
- redirection here. XXX - handle {var} here? */
- if (ri == r_err_and_out || ri == r_append_err_and_out)
- {
- if (flags & RX_ACTIVE)
- {
- if (flags & RX_UNDOABLE)
- add_undo_redirect (2, ri, -1);
- if (dup2 (1, 2) < 0)
- return (errno);
- }
- }
- break;
-
- case r_reading_until:
- case r_deblank_reading_until:
- case r_reading_string:
- /* REDIRECTEE is a pointer to a WORD_DESC containing the text of
- the new input. Place it in a temporary file. */
- if (redirectee)
- {
- fd = here_document_to_fd (redirectee, ri);
-
- if (fd < 0)
- {
- heredoc_errno = errno;
- return (HEREDOC_REDIRECT);
- }
-
- if (redirect->rflags & REDIR_VARASSIGN)
- {
- redirector = fcntl (fd, F_DUPFD, SHELL_FD_BASE); /* XXX try this for now */
- r = errno;
- if (redirector < 0)
- sys_error (_("redirection error: cannot duplicate fd"));
- REDIRECTION_ERROR (redirector, r, fd);
- }
-
- if (flags & RX_ACTIVE)
- {
- if (flags & RX_UNDOABLE)
- {
- /* Only setup to undo it if the thing to undo is active. */
- if ((fd != redirector) && (fcntl (redirector, F_GETFD, 0) != -1))
- r = add_undo_redirect (redirector, ri, -1);
- else
- r = add_undo_close_redirect (redirector);
- if (r < 0 && (redirect->rflags & REDIR_VARASSIGN))
- close (redirector);
- REDIRECTION_ERROR (r, errno, fd);
- }
-
-#if defined (BUFFERED_INPUT)
- check_bash_input (redirector);
-#endif
- if (redirect->rflags & REDIR_VARASSIGN)
- {
- if ((r = redir_varassign (redirect, redirector)) < 0)
- {
- close (redirector);
- close (fd);
- return (r); /* XXX */
- }
- }
- else if (fd != redirector && dup2 (fd, redirector) < 0)
- {
- r = errno;
- close (fd);
- return (r);
- }
-
-#if defined (BUFFERED_INPUT)
- duplicate_buffered_stream (fd, redirector);
-#endif
-
- if ((flags & RX_CLEXEC) && (redirector > 2))
- SET_CLOSE_ON_EXEC (redirector);
- }
-
- if (fd != redirector)
-#if defined (BUFFERED_INPUT)
- close_buffered_fd (fd);
-#else
- close (fd);
-#endif
- }
- break;
-
- case r_duplicating_input:
- case r_duplicating_output:
- case r_move_input:
- case r_move_output:
- if ((flags & RX_ACTIVE) && (redirect->rflags & REDIR_VARASSIGN))
- {
- redirector = fcntl (redir_fd, F_DUPFD, SHELL_FD_BASE); /* XXX try this for now */
- r = errno;
- if (redirector < 0)
- sys_error (_("redirection error: cannot duplicate fd"));
- REDIRECTION_ERROR (redirector, r, -1);
- }
-
- if ((flags & RX_ACTIVE) && (redir_fd != redirector))
- {
- if (flags & RX_UNDOABLE)
- {
- /* Only setup to undo it if the thing to undo is active. */
- if (fcntl (redirector, F_GETFD, 0) != -1)
- r = add_undo_redirect (redirector, ri, redir_fd);
- else
- r = add_undo_close_redirect (redirector);
- if (r < 0 && (redirect->rflags & REDIR_VARASSIGN))
- close (redirector);
- REDIRECTION_ERROR (r, errno, -1);
- }
-#if defined (BUFFERED_INPUT)
- check_bash_input (redirector);
-#endif
- if (redirect->rflags & REDIR_VARASSIGN)
- {
- if ((r = redir_varassign (redirect, redirector)) < 0)
- {
- close (redirector);
- return (r); /* XXX */
- }
- }
- /* This is correct. 2>&1 means dup2 (1, 2); */
- else if (dup2 (redir_fd, redirector) < 0)
- return (errno);
-
-#if defined (BUFFERED_INPUT)
- if (ri == r_duplicating_input || ri == r_move_input)
- duplicate_buffered_stream (redir_fd, redirector);
-#endif /* BUFFERED_INPUT */
-
- /* First duplicate the close-on-exec state of redirectee. dup2
- leaves the flag unset on the new descriptor, which means it
- stays open. Only set the close-on-exec bit for file descriptors
- greater than 2 in any case, since 0-2 should always be open
- unless closed by something like `exec 2<&-'. It should always
- be safe to set fds > 2 to close-on-exec if they're being used to
- save file descriptors < 2, since we don't need to preserve the
- state of the close-on-exec flag for those fds -- they should
- always be open. */
- /* if ((already_set || set_unconditionally) && (ok_to_set))
- set_it () */
-#if 0
- if (((fcntl (redir_fd, F_GETFD, 0) == 1) || redir_fd < 2 || (flags & RX_CLEXEC)) &&
- (redirector > 2))
-#else
- if (((fcntl (redir_fd, F_GETFD, 0) == 1) || (redir_fd < 2 && (flags & RX_INTERNAL)) || (flags & RX_CLEXEC)) &&
- (redirector > 2))
-#endif
- SET_CLOSE_ON_EXEC (redirector);
-
- /* When undoing saving of non-standard file descriptors (>=3) using
- file descriptors >= SHELL_FD_BASE, we set the saving fd to be
- close-on-exec and use a flag to decide how to set close-on-exec
- when the fd is restored. */
- if ((redirect->flags & RX_INTERNAL) && (redirect->flags & RX_SAVCLEXEC) && redirector >= 3 && (redir_fd >= SHELL_FD_BASE || (redirect->flags & RX_SAVEFD)))
- SET_OPEN_ON_EXEC (redirector);
-
- /* dup-and-close redirection */
- if (ri == r_move_input || ri == r_move_output)
- {
- xtrace_fdchk (redir_fd);
-
- close (redir_fd);
-#if defined (COPROCESS_SUPPORT)
- coproc_fdchk (redir_fd); /* XXX - loses coproc fds */
-#endif
- }
- }
- break;
-
- case r_close_this:
- if (flags & RX_ACTIVE)
- {
- if (redirect->rflags & REDIR_VARASSIGN)
- {
- redirector = redir_varvalue (redirect);
- if (redirector < 0)
- return AMBIGUOUS_REDIRECT;
- }
-
- r = 0;
- if ((flags & RX_UNDOABLE) && (fcntl (redirector, F_GETFD, 0) != -1))
- {
- r = add_undo_redirect (redirector, ri, -1);
- REDIRECTION_ERROR (r, errno, redirector);
- }
-
-#if defined (COPROCESS_SUPPORT)
- coproc_fdchk (redirector);
-#endif
- xtrace_fdchk (redirector);
-
-#if defined (BUFFERED_INPUT)
- check_bash_input (redirector);
- close_buffered_fd (redirector);
-#else /* !BUFFERED_INPUT */
- close (redirector);
-#endif /* !BUFFERED_INPUT */
- }
- break;
-
- case r_duplicating_input_word:
- case r_duplicating_output_word:
- break;
- }
- return (0);
-}
-
-/* Remember the file descriptor associated with the slot FD,
- on REDIRECTION_UNDO_LIST. Note that the list will be reversed
- before it is executed. Any redirections that need to be undone
- even if REDIRECTION_UNDO_LIST is discarded by the exec builtin
- are also saved on EXEC_REDIRECTION_UNDO_LIST. FDBASE says where to
- start the duplicating. If it's less than SHELL_FD_BASE, we're ok,
- and can use SHELL_FD_BASE (-1 == don't care). If it's >= SHELL_FD_BASE,
- we have to make sure we don't use fdbase to save a file descriptor,
- since we're going to use it later (e.g., make sure we don't save fd 0
- to fd 10 if we have a redirection like 0<&10). If the value of fdbase
- puts the process over its fd limit, causing fcntl to fail, we try
- again with SHELL_FD_BASE. Return 0 on success, -1 on error. */
-static int
-add_undo_redirect (fd, ri, fdbase)
- int fd;
- enum r_instruction ri;
- int fdbase;
-{
- int new_fd, clexec_flag, savefd_flag;
- REDIRECT *new_redirect, *closer, *dummy_redirect;
- REDIRECTEE sd;
-
- savefd_flag = 0;
- new_fd = fcntl (fd, F_DUPFD, (fdbase < SHELL_FD_BASE) ? SHELL_FD_BASE : fdbase+1);
- if (new_fd < 0)
- new_fd = fcntl (fd, F_DUPFD, SHELL_FD_BASE);
- if (new_fd < 0)
- {
- new_fd = fcntl (fd, F_DUPFD, 0);
- savefd_flag = 1;
- }
-
- if (new_fd < 0)
- {
- sys_error (_("redirection error: cannot duplicate fd"));
- return (-1);
- }
-
- clexec_flag = fcntl (fd, F_GETFD, 0);
-
- sd.dest = new_fd;
- rd.dest = 0;
- closer = make_redirection (sd, r_close_this, rd, 0);
- closer->flags |= RX_INTERNAL;
- dummy_redirect = copy_redirects (closer);
-
- sd.dest = fd;
- rd.dest = new_fd;
- if (fd == 0)
- new_redirect = make_redirection (sd, r_duplicating_input, rd, 0);
- else
- new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
- new_redirect->flags |= RX_INTERNAL;
- if (savefd_flag)
- new_redirect->flags |= RX_SAVEFD;
- if (clexec_flag == 0 && fd >= 3 && (new_fd >= SHELL_FD_BASE || savefd_flag))
- new_redirect->flags |= RX_SAVCLEXEC;
- new_redirect->next = closer;
-
- closer->next = redirection_undo_list;
- redirection_undo_list = new_redirect;
-
- /* Save redirections that need to be undone even if the undo list
- is thrown away by the `exec' builtin. */
- add_exec_redirect (dummy_redirect);
-
- /* experimental: if we're saving a redirection to undo for a file descriptor
- above SHELL_FD_BASE, add a redirection to be undone if the exec builtin
- causes redirections to be discarded. There needs to be a difference
- between fds that are used to save other fds and then are the target of
- user redirections and fds that are just the target of user redirections.
- We use the close-on-exec flag to tell the difference; fds > SHELL_FD_BASE
- that have the close-on-exec flag set are assumed to be fds used internally
- to save others. */
- if (fd >= SHELL_FD_BASE && ri != r_close_this && clexec_flag)
- {
- sd.dest = fd;
- rd.dest = new_fd;
- new_redirect = make_redirection (sd, r_duplicating_output, rd, 0);
- new_redirect->flags |= RX_INTERNAL;
-
- add_exec_redirect (new_redirect);
- }
-
- /* File descriptors used only for saving others should always be
- marked close-on-exec. Unfortunately, we have to preserve the
- close-on-exec state of the file descriptor we are saving, since
- fcntl (F_DUPFD) sets the new file descriptor to remain open
- across execs. If, however, the file descriptor whose state we
- are saving is <= 2, we can just set the close-on-exec flag,
- because file descriptors 0-2 should always be open-on-exec,
- and the restore above in do_redirection() will take care of it. */
- if (clexec_flag || fd < 3)
- SET_CLOSE_ON_EXEC (new_fd);
- else if (redirection_undo_list->flags & RX_SAVCLEXEC)
- SET_CLOSE_ON_EXEC (new_fd);
-
- return (0);
-}
-
-/* Set up to close FD when we are finished with the current command
- and its redirections. Return 0 on success, -1 on error. */
-static int
-add_undo_close_redirect (fd)
- int fd;
-{
- REDIRECT *closer;
- REDIRECTEE sd;
-
- sd.dest = fd;
- rd.dest = 0;
- closer = make_redirection (sd, r_close_this, rd, 0);
- closer->flags |= RX_INTERNAL;
- closer->next = redirection_undo_list;
- redirection_undo_list = closer;
-
- return 0;
-}
-
-static void
-add_exec_redirect (dummy_redirect)
- REDIRECT *dummy_redirect;
-{
- dummy_redirect->next = exec_redirection_undo_list;
- exec_redirection_undo_list = dummy_redirect;
-}
-
-/* Return 1 if the redirection specified by RI and REDIRECTOR alters the
- standard input. */
-static int
-stdin_redirection (ri, redirector)
- enum r_instruction ri;
- int redirector;
-{
- switch (ri)
- {
- case r_input_direction:
- case r_inputa_direction:
- case r_input_output:
- case r_reading_until:
- case r_deblank_reading_until:
- case r_reading_string:
- return (1);
- case r_duplicating_input:
- case r_duplicating_input_word:
- case r_close_this:
- return (redirector == 0);
- case r_output_direction:
- case r_appending_to:
- case r_duplicating_output:
- case r_err_and_out:
- case r_append_err_and_out:
- case r_output_force:
- case r_duplicating_output_word:
- return (0);
- }
- return (0);
-}
-
-/* Return non-zero if any of the redirections in REDIRS alter the standard
- input. */
-int
-stdin_redirects (redirs)
- REDIRECT *redirs;
-{
- REDIRECT *rp;
- int n;
-
- for (n = 0, rp = redirs; rp; rp = rp->next)
- if ((rp->rflags & REDIR_VARASSIGN) == 0)
- n += stdin_redirection (rp->instruction, rp->redirector.dest);
- return n;
-}
-
-/* These don't yet handle array references */
-static int
-redir_varassign (redir, fd)
- REDIRECT *redir;
- int fd;
-{
- WORD_DESC *w;
- SHELL_VAR *v;
-
- w = redir->redirector.filename;
- v = bind_var_to_int (w->word, fd);
- if (v == 0 || readonly_p (v) || noassign_p (v))
- return BADVAR_REDIRECT;
-
- return 0;
-}
-
-static int
-redir_varvalue (redir)
- REDIRECT *redir;
-{
- SHELL_VAR *v;
- char *val;
- intmax_t vmax;
- int i;
-
- /* XXX - handle set -u here? */
- v = find_variable (redir->redirector.filename->word);
- if (v == 0 || invisible_p (v))
- return -1;
-
- val = get_variable_value (v);
- if (val == 0 || *val == 0)
- return -1;
-
- if (legal_number (val, &vmax) < 0)
- return -1;
-
- i = vmax; /* integer truncation */
- return i;
-}
+++ /dev/null
-/* 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-2012 Free Software Foundation, Inc.
-
- This file is part of GNU Bash, the Bourne Again SHell.
-
- Bash is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Bash is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with Bash. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "config.h"
-
-#include "bashtypes.h"
-#include <stdio.h>
-#include "chartypes.h"
-#if defined (HAVE_PWD_H)
-# include <pwd.h>
-#endif
-#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 "parser.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 "typemax.h"
-
-#include "builtins/getopt.h"
-#include "builtins/common.h"
-
-#include "builtins/builtext.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_ASSOCVAR 4
-
-#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 `pflags' argument to param_expand() */
-#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
-#define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */
-#define PF_NOSPLIT2 0x04 /* same as W_NOSPLIT2 */
-#define PF_ASSIGNRHS 0x08 /* same as W_ASSIGNRHS */
-
-/* These defs make it easier to use the editor. */
-#define LBRACE '{'
-#define RBRACE '}'
-#define LPAREN '('
-#define RPAREN ')'
-
-#if defined (HANDLE_MULTIBYTE)
-#define WLPAREN L'('
-#define WRPAREN L')'
-#endif
-
-/* 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) \
- ((posixly_correct == 0 && (c) == '#') || (posixly_correct == 0 && (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
-
-/* Sentinel to tell when we are performing variable assignments preceding a
- command name and putting them into the environment. Used to make sure
- we use the temporary environment when looking up variable values. */
-int assigning_in_environment;
-
-/* 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 and so it can be saved and restored by the trap handlers. */
-WORD_LIST *subst_assign_varlist = (WORD_LIST *)NULL;
-
-/* Extern functions and variables from different files. */
-extern int last_command_exit_value, last_command_exit_signal;
-extern int subshell_environment, line_number;
-extern int subshell_level, parse_and_execute_level, sourcelevel;
-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;
-
-/* 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 *make_quoted_char __P((int));
-static WORD_LIST *quote_list __P((WORD_LIST *));
-
-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 *, int));
-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 int skip_matched_pair __P((const char *, int, 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_upattern __P((char *, char *, int, char **, char **));
-#if defined (HANDLE_MULTIBYTE)
-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((SHELL_VAR *, char *, int, char *, int));
-#endif
-static char *parameter_brace_remove_pattern __P((char *, char *, int, char *, int, int, int));
-
-static char *process_substitute __P((char *, int));
-
-static char *read_comsub __P((int, 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, int, arrayind_t *));
-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((SHELL_VAR *, char *, char *, int, intmax_t *, intmax_t *));
-static int get_var_and_type __P((char *, char *, arrayind_t, int, int, SHELL_VAR **, char **));
-static char *mb_substring __P((char *, int, int));
-static char *parameter_brace_substring __P((char *, char *, int, char *, int, int));
-
-static int shouldexp_replacement __P((char *));
-
-static char *pos_params_pat_subst __P((char *, char *, char *, int));
-
-static char *parameter_brace_patsub __P((char *, char *, int, char *, int, int));
-
-static char *pos_params_casemod __P((char *, char *, int, int));
-static char *parameter_brace_casemod __P((char *, char *, int, int, char *, int, int));
-
-static WORD_DESC *parameter_brace_expand __P((char *, int *, 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
-#if defined (ARRAY_VARS)
-static int make_internal_declare __P((char *, char *));
-#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 */
-/* */
-/* **************************************************************** */
-
-#if defined (DEBUG)
-void
-dump_word_flags (flags)
- int flags;
-{
- int f;
-
- f = flags;
- fprintf (stderr, "%d -> ", f);
- if (f & W_ASSIGNASSOC)
- {
- f &= ~W_ASSIGNASSOC;
- fprintf (stderr, "W_ASSIGNASSOC%s", f ? "|" : "");
- }
- if (f & W_HASCTLESC)
- {
- f &= ~W_HASCTLESC;
- fprintf (stderr, "W_HASCTLESC%s", f ? "|" : "");
- }
- if (f & W_NOPROCSUB)
- {
- f &= ~W_NOPROCSUB;
- fprintf (stderr, "W_NOPROCSUB%s", f ? "|" : "");
- }
- if (f & W_DQUOTE)
- {
- f &= ~W_DQUOTE;
- fprintf (stderr, "W_DQUOTE%s", f ? "|" : "");
- }
- if (f & W_HASQUOTEDNULL)
- {
- f &= ~W_HASQUOTEDNULL;
- fprintf (stderr, "W_HASQUOTEDNULL%s", f ? "|" : "");
- }
- if (f & W_ASSIGNARG)
- {
- f &= ~W_ASSIGNARG;
- fprintf (stderr, "W_ASSIGNARG%s", f ? "|" : "");
- }
- if (f & W_ASSNBLTIN)
- {
- f &= ~W_ASSNBLTIN;
- fprintf (stderr, "W_ASSNBLTIN%s", f ? "|" : "");
- }
- if (f & W_COMPASSIGN)
- {
- f &= ~W_COMPASSIGN;
- fprintf (stderr, "W_COMPASSIGN%s", f ? "|" : "");
- }
- if (f & W_NOEXPAND)
- {
- f &= ~W_NOEXPAND;
- fprintf (stderr, "W_NOEXPAND%s", f ? "|" : "");
- }
- if (f & W_ITILDE)
- {
- f &= ~W_ITILDE;
- fprintf (stderr, "W_ITILDE%s", f ? "|" : "");
- }
- if (f & W_NOTILDE)
- {
- f &= ~W_NOTILDE;
- fprintf (stderr, "W_NOTILDE%s", f ? "|" : "");
- }
- if (f & W_ASSIGNRHS)
- {
- f &= ~W_ASSIGNRHS;
- fprintf (stderr, "W_ASSIGNRHS%s", f ? "|" : "");
- }
- if (f & W_NOCOMSUB)
- {
- f &= ~W_NOCOMSUB;
- fprintf (stderr, "W_NOCOMSUB%s", f ? "|" : "");
- }
- if (f & W_DOLLARSTAR)
- {
- f &= ~W_DOLLARSTAR;
- fprintf (stderr, "W_DOLLARSTAR%s", f ? "|" : "");
- }
- if (f & W_DOLLARAT)
- {
- f &= ~W_DOLLARAT;
- fprintf (stderr, "W_DOLLARAT%s", f ? "|" : "");
- }
- if (f & W_TILDEEXP)
- {
- f &= ~W_TILDEEXP;
- fprintf (stderr, "W_TILDEEXP%s", f ? "|" : "");
- }
- if (f & W_NOSPLIT2)
- {
- f &= ~W_NOSPLIT2;
- fprintf (stderr, "W_NOSPLIT2%s", f ? "|" : "");
- }
- if (f & W_NOGLOB)
- {
- f &= ~W_NOGLOB;
- fprintf (stderr, "W_NOGLOB%s", f ? "|" : "");
- }
- if (f & W_NOSPLIT)
- {
- f &= ~W_NOSPLIT;
- fprintf (stderr, "W_NOSPLIT%s", f ? "|" : "");
- }
- if (f & W_GLOBEXP)
- {
- f &= ~W_GLOBEXP;
- fprintf (stderr, "W_GLOBEXP%s", f ? "|" : "");
- }
- if (f & W_ASSIGNMENT)
- {
- f &= ~W_ASSIGNMENT;
- fprintf (stderr, "W_ASSIGNMENT%s", f ? "|" : "");
- }
- if (f & W_QUOTED)
- {
- f &= ~W_QUOTED;
- fprintf (stderr, "W_QUOTED%s", f ? "|" : "");
- }
- if (f & W_HASDOLLAR)
- {
- f &= ~W_HASDOLLAR;
- fprintf (stderr, "W_HASDOLLAR%s", f ? "|" : "");
- }
- fprintf (stderr, "\n");
- fflush (stderr);
-}
-#endif
-
-#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 & SX_VARNAME)
- is non-zero, and array variables have been compiled into the shell,
- everything between a `[' and a corresponding `]' is skipped over.
- If (flags & SX_NOALLOC) is non-zero, don't return the substring, just
- update SINDEX. If (flags & SX_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 & SX_VARNAME) && c == '[')
- {
- int ni;
- /* If this is an array subscript, skip over it and continue. */
- ni = skipsubscript (string, i, 0);
- 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 & SX_REQMATCH) && found == 0)
- {
- *sindex = i;
- return (&extract_string_error);
- }
-
- temp = (flags & SX_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)
- {
- /* XXX - take another look at this in light of Interp 221 */
- /* 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_command_subst (string, &si, 0);
- else
- ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 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_command_subst (string, &si, SX_NOALLOC);
- else
- ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, SX_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, flags)
- char *string;
- size_t slen;
- int *sindex;
- char *charlist;
- int flags;
-{
- register int i;
-#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 ((flags & SX_NOCTLESC) == 0 && c == CTLESC)
- {
- i += 2;
- continue;
- }
- /* Even if flags contains SX_NOCTLESC, we let CTLESC quoting CTLNUL
- through, to protect the CTLNULs from later calls to
- remove_quoted_nulls. */
- else if ((flags & SX_NOESCCTLNUL) == 0 && c == CTLESC && string[i+1] == CTLNUL)
- {
- 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 ")". )
- XFLAGS is additional flags to pass to other extraction functions. */
-char *
-extract_command_subst (string, sindex, xflags)
- char *string;
- int *sindex;
- int xflags;
-{
- if (string[*sindex] == LPAREN)
- return (extract_delimited_string (string, sindex, "$(", "(", ")", xflags|SX_COMMAND)); /*)*/
- else
- {
- xflags |= (no_longjmp_on_fatal_error ? SX_NOLONGJMP : 0);
- return (xparse_dolparen (string, string+*sindex, sindex, xflags));
- }
-}
-
-/* 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, "(", ")", SX_COMMAND));
-}
-#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. See COMMENT_BEGIN define in parse.y */
- if ((flags & SX_COMMAND) && c == '#' && (i == 0 || string[i - 1] == '\n' || shellblank (string[i - 1])))
- {
- in_comment = 1;
- ADVANCE_CHAR (string, slen, i);
- continue;
- }
-
- if (c == CTLESC || c == '\\')
- {
- pass_character++;
- i++;
- continue;
- }
-
- /* Process a nested command substitution, but only if we're parsing an
- arithmetic substitution. */
- if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN)
- {
- si = i + 2;
- t = extract_command_subst (string, &si, flags|SX_NOALLOC);
- i = si + 1;
- 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|SX_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|SX_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|SX_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)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- report_error (_("bad substitution: no closing `%s' in %s"), closer, string);
- exp_jump_to_top_level (DISCARD);
- }
- else
- {
- *sindex = i;
- return (char *)NULL;
- }
- }
-
- si = i - *sindex - len_closer + 1;
- if (flags & SX_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, dolbrace_state;
- char *result, *t;
- DECLARE_MBSTATE;
-
- pass_character = 0;
- nesting_level = 1;
- slen = strlen (string + *sindex) + *sindex;
-
- /* The handling of dolbrace_state needs to agree with the code in parse.y:
- parse_matched_pair(). The different initial value is to handle the
- case where this function is called to parse the word in
- ${param op word} (SX_WORD). */
- dolbrace_state = (flags & SX_WORD) ? DOLBRACE_WORD : DOLBRACE_PARAM;
- if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && (flags & SX_POSIXEXP))
- dolbrace_state = DOLBRACE_QUOTE;
-
- 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|SX_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_command_subst (string, &si, flags|SX_NOALLOC);
- i = si + 1;
- continue;
- }
-
-#if 0
- /* 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;
- }
-#else /* XXX - bash-4.2 */
- /* Pass the contents of double-quoted strings through verbatim. */
- if (c == '"')
- {
- si = i + 1;
- i = skip_double_quoted (string, slen, si);
- /* skip_XXX_quoted leaves index one past close quote */
- continue;
- }
-
- if (c == '\'')
- {
-/*itrace("extract_dollar_brace_string: c == single quote flags = %d quoted = %d dolbrace_state = %d", flags, quoted, dolbrace_state);*/
- if (posixly_correct && shell_compatibility_level > 41 && dolbrace_state != DOLBRACE_QUOTE && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
- ADVANCE_CHAR (string, slen, i);
- else
- {
- si = i + 1;
- i = skip_single_quoted (string, slen, si);
- }
-
- continue;
- }
-#endif
-
- /* move past this character, which was not special. */
- ADVANCE_CHAR (string, slen, i);
-
- /* This logic must agree with parse.y:parse_matched_pair, since they
- share the same defines. */
- if (dolbrace_state == DOLBRACE_PARAM && c == '%' && (i - *sindex) > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- else if (dolbrace_state == DOLBRACE_PARAM && c == '#' && (i - *sindex) > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- else if (dolbrace_state == DOLBRACE_PARAM && c == '/' && (i - *sindex) > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- else if (dolbrace_state == DOLBRACE_PARAM && c == '^' && (i - *sindex) > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- else if (dolbrace_state == DOLBRACE_PARAM && c == ',' && (i - *sindex) > 1)
- dolbrace_state = DOLBRACE_QUOTE;
- else if (dolbrace_state == DOLBRACE_PARAM && strchr ("#%^,~:-=?+/", c) != 0)
- dolbrace_state = DOLBRACE_OP;
- else if (dolbrace_state == DOLBRACE_OP && strchr ("#%^,~:-=?+/", c) == 0)
- dolbrace_state = DOLBRACE_WORD;
- }
-
- if (c == 0 && nesting_level)
- {
- if (no_longjmp_on_fatal_error == 0)
- { /* { */
- last_command_exit_value = EXECUTION_FAILURE;
- report_error (_("bad substitution: no closing `%s' in %s"), "}", string);
- exp_jump_to_top_level (DISCARD);
- }
- else
- {
- *sindex = i;
- return ((char *)NULL);
- }
- }
-
- result = (flags & SX_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
-
-#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
-
-/* This function assumes s[i] == open; returns with s[ret] == close; used to
- parse array subscripts. FLAGS & 1 means to not attempt to skip over
- matched pairs of quotes or backquotes, or skip word expansions; it is
- intended to be used after expansion has been performed and during final
- assignment parsing (see arrayfunc.c:assign_compound_array_list()). */
-static int
-skip_matched_pair (string, start, open, close, flags)
- const char *string;
- int start, open, close, flags;
-{
- int i, pass_next, backq, si, c, count;
- size_t slen;
- char *temp, *ss;
- DECLARE_MBSTATE;
-
- slen = strlen (string + start) + start;
- no_longjmp_on_fatal_error = 1;
-
- i = start + 1; /* skip over leading bracket */
- count = 1;
- pass_next = backq = 0;
- ss = (char *)string;
- 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 ((flags & 1) == 0 && c == '`')
- {
- backq = 1;
- i++;
- continue;
- }
- else if ((flags & 1) == 0 && c == open)
- {
- count++;
- i++;
- continue;
- }
- else if (c == close)
- {
- count--;
- if (count == 0)
- break;
- i++;
- continue;
- }
- else if ((flags & 1) == 0 && (c == '\'' || c == '"'))
- {
- i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
- : skip_double_quoted (ss, slen, ++i);
- /* no increment, the skip functions increment past the closing quote. */
- }
- else if ((flags&1) == 0 && 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 (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
- else
- temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
- i = si;
- if (string[i] == '\0') /* don't increment i past EOS in loop */
- break;
- i++;
- continue;
- }
- else
- ADVANCE_CHAR (string, slen, i);
- }
-
- CQ_RETURN(i);
-}
-
-#if defined (ARRAY_VARS)
-int
-skipsubscript (string, start, flags)
- const char *string;
- int start, flags;
-{
- return (skip_matched_pair (string, start, '[', ']', flags));
-}
-#endif
-
-/* 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, flags)
- char *string;
- int start;
- char *delims;
- int flags;
-{
- int i, pass_next, backq, si, c, invert, skipquote, skipcmd;
- size_t slen;
- char *temp, open[3];
- DECLARE_MBSTATE;
-
- slen = strlen (string + start) + start;
- if (flags & SD_NOJMP)
- no_longjmp_on_fatal_error = 1;
- invert = (flags & SD_INVERT);
- skipcmd = (flags & SD_NOSKIPCMD) == 0;
-
- i = start;
- pass_next = backq = 0;
- while (c = string[i])
- {
- /* If this is non-zero, we should not let quote characters be delimiters
- and the current character is a single or double quote. We should not
- test whether or not it's a delimiter until after we skip single- or
- double-quoted strings. */
- skipquote = ((flags & SD_NOQUOTEDELIM) && (c == '\'' || c =='"'));
- 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 (skipquote == 0 && invert == 0 && member (c, delims))
- break;
- 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 == '$' && ((skipcmd && 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, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
- else
- temp = extract_dollar_brace_string (string, &si, 0, SX_NOALLOC);
- i = si;
- if (string[i] == '\0') /* don't increment i past EOS in loop */
- break;
- i++;
- continue;
- }
-#if defined (PROCESS_SUBSTITUTION)
- else if (skipcmd && (c == '<' || c == '>') && string[i+1] == LPAREN)
- {
- si = i + 2;
- if (string[si] == '\0')
- CQ_RETURN(si);
- temp = extract_process_subst (string, (c == '<') ? "<(" : ">(", &si);
- free (temp); /* no SX_ALLOC here */
- i = si;
- if (string[i] == '\0')
- break;
- i++;
- continue;
- }
-#endif /* PROCESS_SUBSTITUTION */
-#if defined (EXTENDED_GLOB)
- else if ((flags & SD_EXTGLOB) && extended_glob && string[i+1] == LPAREN && member (c, "?*+!@"))
- {
- si = i + 2;
- if (string[si] == '\0')
- CQ_RETURN(si);
-
- open[0] = c;
- open[1] = LPAREN;
- open[2] = '\0';
- temp = extract_delimited_string (string, &si, open, "(", ")", SX_NOALLOC); /* ) */
-
- i = si;
- if (string[i] == '\0') /* don't increment i past EOS in loop */
- break;
- i++;
- continue;
- }
-#endif
- else if ((skipquote || invert) && (member (c, delims) == 0))
- break;
- else
- ADVANCE_CHAR (string, slen, i);
- }
-
- CQ_RETURN(i);
-}
-
-#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. */
-
-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);
-}
-
-/* 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, flags, nwp, cwp)
- char *string;
- int slen;
- char *delims;
- int sentinel, flags;
- int *nwp, *cwp;
-{
- int ts, te, i, nw, cw, ifs_split, dflags;
- 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 whitespace 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;
- dflags = flags|SD_NOJMP;
- while (1)
- {
- te = skip_to_delim (string, ts, d, dflags);
-
- /* 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 (or past the end of the previously-found token,
- possible if the end of the line is composed solely of IFS whitespace)
- add an additional null argument and set the current word pointer to that. */
- if (cwp && cw == -1 && (sentinel >= slen || sentinel >= te))
- {
- if (whitespace (string[sentinel - 1]))
- {
- token = "";
- ret = add_string_to_list (token, ret);
- nw++;
- }
- cw = nw;
- }
-
- if (nwp)
- *nwp = nw;
- if (cwp)
- *cwp = cw;
-
- FREE (d2);
-
- 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, " "));
-}
-
-/* An external interface that can be used by the rest of the shell to
- obtain a string containing the first character in $IFS. Handles all
- the multibyte complications. If LENP is non-null, it is set to the
- length of the returned string. */
-char *
-ifs_firstchar (lenp)
- int *lenp;
-{
- char *ret;
- int len;
-
- ret = xmalloc (MB_LEN_MAX + 1);
-#if defined (HANDLE_MULTIBYTE)
- if (ifs_firstc_len == 1)
- {
- ret[0] = ifs_firstc[0];
- ret[1] = '\0';
- len = ret[0] ? 1 : 0;
- }
- else
- {
- memcpy (ret, ifs_firstc, ifs_firstc_len);
- ret[len = ifs_firstc_len] = '\0';
- }
-#else
- ret[0] = ifs_firstc;
- ret[1] = '\0';
- len = ret[0] ? 0 : 1;
-#endif
-
- if (lenp)
- *lenp = len;
-
- return ret;
-}
-
-/* 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
-
- /* XXX -- why call quote_list if ifs == 0? we can get away without doing
- it now that quote_escapes quotes spaces */
- tlist = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES|Q_PATQUOTE))
- ? quote_list (list)
- : list_quote_escapes (list);
-
- ret = string_list_internal (tlist, sep);
-#if defined (HANDLE_MULTIBYTE) && !defined (__GNUC__)
- free (sep);
-#endif
- return ret;
-}
-
-/* Turn the positional paramters into a string, understanding quoting and
- the various subtleties of using the first character of $IFS as the
- separator. Calls string_list_dollar_at, string_list_dollar_star, and
- string_list as appropriate. */
-char *
-string_list_pos_params (pchar, list, quoted)
- int pchar;
- WORD_LIST *list;
- int quoted;
-{
- char *ret;
- WORD_LIST *tlist;
-
- if (pchar == '*' && (quoted & Q_DOUBLE_QUOTES))
- {
- tlist = quote_list (list);
- word_list_remove_quoted_nulls (tlist);
- ret = string_list_dollar_star (tlist);
- }
- else if (pchar == '*' && (quoted & Q_HERE_DOCUMENT))
- {
- tlist = quote_list (list);
- word_list_remove_quoted_nulls (tlist);
- ret = string_list (tlist);
- }
- else if (pchar == '*')
- {
- /* Even when unquoted, string_list_dollar_star does the right thing
- making sure that the first character of $IFS is used as the
- separator. */
- ret = string_list_dollar_star (list);
- }
- else if (pchar == '@' && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
- /* We use string_list_dollar_at, but only if the string is quoted, since
- that quotes the escapes if it's not, which we don't want. We could
- use string_list (the old code did), but that doesn't do the right
- thing if the first character of $IFS is not a space. We use
- string_list_dollar_star if the string is unquoted so we make sure that
- the elements of $@ are separated by the first character of $IFS for
- later splitting. */
- ret = string_list_dollar_at (list, quoted);
- else if (pchar == '@')
- ret = string_list_dollar_star (list);
- else
- ret = string_list ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) ? quote_list (list) : list);
-
- 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, xflags;
- 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';
- for (xflags = 0, s = ifs_value; s && *s; s++)
- {
- if (*s == CTLESC) xflags |= SX_NOCTLESC;
- else if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
- }
-
- 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, xflags);
- 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, xflags;
- size_t slen;
-
- if (!stringp || !*stringp || !**stringp)
- return ((char *)NULL);
-
- sh_style_split = separators && separators[0] == ' ' &&
- separators[1] == '\t' &&
- separators[2] == '\n' &&
- separators[3] == '\0';
- for (xflags = 0, s = ifs_value; s && *s; s++)
- {
- if (*s == CTLESC) xflags |= SX_NOCTLESC;
- if (*s == CTLNUL) xflags |= SX_NOESCCTLNUL;
- }
-
- s = *stringp;
- 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, xflags);
-
- /* 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, mkassoc;
- WORD_LIST *list;
-
- mklocal = flags & ASS_MKLOCAL;
- mkassoc = flags & ASS_MKASSOC;
-
- if (mklocal && variable_context)
- {
- v = find_variable (name);
- list = expand_compound_array_assignment (v, value, flags);
- if (mkassoc)
- v = make_local_assoc_variable (name);
- else if (v == 0 || (array_p (v) == 0 && assoc_p (v) == 0) || v->context != variable_context)
- v = make_local_array_variable (name, 0);
- 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, appendop, assign_list, aflags, retval;
- char *name, *value, *temp;
- 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] == '=')
- {
- if (name[offset - 1] == '+')
- {
- appendop = 1;
- name[offset - 1] = '\0';
- }
-
- name[offset] = 0; /* might need this set later */
- temp = name + offset + 1;
-
-#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 = mbschr (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;
- if (word->flags & W_ASSIGNASSOC)
- aflags |= ASS_MKASSOC;
- entry = do_compound_assignment (name, value, aflags);
- }
- else
-#endif /* ARRAY_VARS */
- entry = bind_variable (name, value, aflags);
-
- stupidly_hack_special_variables (name);
-
-#if 1
- /* Return 1 if the assignment seems to have been performed correctly. */
- if (entry == 0 || readonly_p (entry))
- retval = 0; /* assignment failure */
- else if (noassign_p (entry))
- {
- last_command_exit_value = EXECUTION_FAILURE;
- retval = 1; /* error status, but not assignment failure */
- }
- else
- retval = 1;
-
- if (entry && retval != 0 && noassign_p (entry) == 0)
- VUNSETATTR (entry, att_invisible);
-
- ASSIGN_RETURN (retval);
-#else
- if (entry)
- VUNSETATTR (entry, att_invisible);
-
- ASSIGN_RETURN (entry ? ((readonly_p (entry) == 0) && noassign_p (entry) == 0) : 0);
-#endif
-}
-
-/* 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, flags)
- WORD_DESC *word;
- int flags;
-{
- 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);
-
- if (start == 0) /* handle ${@:0[:x]} specially */
- {
- t = make_word_list (make_word (dollar_vars[0]), params);
- save = params = t;
- }
-
- for (i = start ? 1 : 0; 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;
-
- ret = string_list_pos_params (string[0], h, quoted);
-
- 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;
- int quoted;
-{
- 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 1, 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. If
- SPECIAL is 2, this is an rhs argument for the =~ operator, and should
- be quoted appropriately for regcomp/regexec. The caller is responsible
- for removing the backslashes if the unquoted word is needed later. */
-char *
-cond_expand_word (w, special)
- WORD_DESC *w;
- int special;
-{
- char *r, *p;
- WORD_LIST *l;
- int qflags;
-
- if (w->word == 0 || w->word[0] == '\0')
- return ((char *)NULL);
-
- w->flags |= W_NOSPLIT2;
- 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
- {
- qflags = QGLOB_CVTNULL;
- if (special == 2)
- qflags |= QGLOB_REGEXP;
- p = string_list (l);
- r = quote_string_for_globbing (p, qflags);
- 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.
- Since this does not perform word splitting, it leaves quoted nulls
- in the result. */
-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, wflags)
- char *string;
- int quoted;
- int wflags;
-{
- WORD_LIST *value;
- WORD_DESC td;
-
- if (string == 0 || *string == 0)
- return ((WORD_LIST *)NULL);
-
- td.flags = wflags;
- 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 = W_NOSPLIT2; /* no splitting, remove "" and '' */
- 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 (word splitting
- and filename generation). If IFS is null, we quote spaces as well, just
- in case we split on spaces later (in the case of unquoted $@, we will
- eventually attempt to split the entire word on spaces). Corresponding
- code exists in dequote_escapes. Even if we don't end up splitting on
- spaces, quoting spaces is not a problem. This should never be called on
- a string that is quoted with single or double quotes or part of a here
- document (effectively double-quoted). */
-char *
-quote_escapes (string)
- char *string;
-{
- register char *s, *t;
- size_t slen;
- char *result, *send;
- int quote_spaces, skip_ctlesc, skip_ctlnul;
- DECLARE_MBSTATE;
-
- slen = strlen (string);
- send = string + slen;
-
- quote_spaces = (ifs_value && *ifs_value == 0);
-
- for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
- skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
-
- t = result = (char *)xmalloc ((slen * 2) + 1);
- s = string;
-
- while (*s)
- {
- if ((skip_ctlesc == 0 && *s == CTLESC) || (skip_ctlnul == 0 && *s == CTLNUL) || (quote_spaces && *s == ' '))
- *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. */
-char *
-dequote_escapes (string)
- char *string;
-{
- register char *s, *t, *s1;
- size_t slen;
- char *result, *send;
- int quote_spaces;
- DECLARE_MBSTATE;
-
- if (string == 0)
- return string;
-
- slen = strlen (string);
- send = string + slen;
-
- t = result = (char *)xmalloc (slen + 1);
-
- if (strchr (string, CTLESC) == 0)
- return (strcpy (result, string));
-
- quote_spaces = (ifs_value && *ifs_value == 0);
-
- s = string;
- while (*s)
- {
- if (*s == CTLESC && (s[1] == CTLESC || s[1] == CTLNUL || (quote_spaces && s[1] == ' ')))
- {
- 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.
- This turns "" into QUOTED_NULL, so the W_HASQUOTEDNULL flag needs to be
- set in any resultant WORD_DESC where this value is the word. */
-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, returning a new string. This turns "" into QUOTED_NULL, so
- the W_HASQUOTEDNULL flag needs to be set in any resultant WORD_DESC where
- this value is the word. */
-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-quote 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);
- if (*t == 0)
- w->word->flags |= W_HASQUOTEDNULL; /* XXX - turn on W_HASQUOTEDNULL here? */
- w->word->flags |= W_QUOTED;
- free (t);
- }
- return list;
-}
-
-/* De-quote quoted characters in each word in LIST. */
-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);
- if (QUOTED_NULL (tlist->word->word))
- tlist->word->flags &= ~W_HASQUOTEDNULL;
- free (tlist->word->word);
- tlist->word->word = s;
- }
- return list;
-}
-
-/* Remove CTLESC protecting a CTLESC or CTLNUL in place. Return the passed
- string. */
-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. */
-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++;
- continue;
- }
-
- 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
-
-/* Returns its first argument if nothing matched; new memory otherwise */
-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 (param); /* no match, return original string */
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* Returns its first argument if nothing matched; new memory otherwise */
-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 (wparam); /* no match, return original string */
-}
-#endif /* HANDLE_MULTIBYTE */
-
-static char *
-remove_pattern (param, pattern, op)
- char *param, *pattern;
- int op;
-{
- char *xret;
-
- 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;
-
- n = xdupmbstowcs (&wpattern, NULL, pattern);
- if (n == (size_t)-1)
- {
- xret = remove_upattern (param, pattern, op);
- return ((xret == param) ? savestring (param) : xret);
- }
- n = xdupmbstowcs (&wparam, NULL, param);
- if (n == (size_t)-1)
- {
- free (wpattern);
- xret = remove_upattern (param, pattern, op);
- return ((xret == param) ? savestring (param) : xret);
- }
- oret = ret = remove_wpattern (wparam, n, wpattern, op);
- /* Don't bother to convert wparam back to multibyte string if nothing
- matched; just return copy of original string */
- if (ret == wparam)
- {
- free (wparam);
- free (wpattern);
- return (savestring (param));
- }
-
- 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
- {
- xret = remove_upattern (param, pattern, op);
- return ((xret == param) ? savestring (param) : xret);
- }
-}
-
-/* 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, mlen;
- register char *p, *p1, *npat;
- char *end;
- int n1;
-
- /* 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[0] == '*' && pat[1] == LPAREN && extended_glob) || pat[len - 1] != '*')
- {
- p = npat = (char *)xmalloc (len + 3);
- p1 = pat;
- if (*p1 != '*' || (*p1 == '*' && p1[1] == LPAREN && extended_glob))
- *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;
-
- mlen = umatchlen (pat, len);
-
- switch (mtype)
- {
- case MATCH_ANY:
- for (p = string; p <= end; p++)
- {
- if (match_pattern_char (pat, p))
- {
-#if 0
- for (p1 = end; p1 >= p; p1--)
-#else
- p1 = (mlen == -1) ? end : p + mlen;
- /* p1 - p = length of portion of string to be considered
- p = current position in string
- mlen = number of characters consumed by match (-1 for entire string)
- end = end of string
- we want to break immediately if the potential match len
- is greater than the number of characters remaining in the
- string
- */
- if (p1 > end)
- break;
- for ( ; p1 >= p; p1--)
-#endif
- {
- c = *p1; *p1 = '\0';
- if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
- {
- *p1 = c;
- *sp = p;
- *ep = p1;
- return 1;
- }
- *p1 = c;
-#if 1
- /* If MLEN != -1, we have a fixed length pattern. */
- if (mlen != -1)
- break;
-#endif
- }
- }
- }
-
- return (0);
-
- case MATCH_BEG:
- if (match_pattern_char (pat, string) == 0)
- return (0);
-
-#if 0
- for (p = end; p >= string; p--)
-#else
- for (p = (mlen == -1) ? end : string + mlen; p >= string; p--)
-#endif
- {
- c = *p; *p = '\0';
- if (strmatch (pat, string, FNMATCH_EXTFLAG) == 0)
- {
- *p = c;
- *sp = string;
- *ep = p;
- return 1;
- }
- *p = c;
-#if 1
- /* If MLEN != -1, we have a fixed length pattern. */
- if (mlen != -1)
- break;
-#endif
- }
-
- return (0);
-
- case MATCH_END:
-#if 0
- for (p = string; p <= end; p++)
-#else
- for (p = end - ((mlen == -1) ? len : mlen); p <= end; p++)
-#endif
- {
- if (strmatch (pat, p, FNMATCH_EXTFLAG) == 0)
- {
- *sp = p;
- *ep = end;
- return 1;
- }
-#if 1
- /* If MLEN != -1, we have a fixed length pattern. */
- if (mlen != -1)
- break;
-#endif
- }
-
- return (0);
- }
-
- return (0);
-}
-
-#if defined (HANDLE_MULTIBYTE)
-/* 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;
- size_t len;
- int mlen;
- int n, n1, n2, simple;
-
- simple = (wpat[0] != L'\\' && wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'[');
-#if defined (EXTENDED_GLOB)
- if (extended_glob)
- simple |= (wpat[1] != L'(' || (wpat[0] != L'*' && wpat[0] != L'?' && wpat[0] != L'+' && wpat[0] != L'!' && wpat[0] != L'@')); /*)*/
-#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. */
- len = wcslen (wpat);
- if (wpat[0] != L'*' || (wpat[0] == L'*' && wpat[1] == WLPAREN && extended_glob) || wpat[len - 1] != L'*')
- {
- wp = nwpat = (wchar_t *)xmalloc ((len + 3) * sizeof (wchar_t));
- wp1 = wpat;
- if (*wp1 != L'*' || (*wp1 == '*' && wp1[1] == WLPAREN && extended_glob))
- *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);
-
- mlen = wmatchlen (wpat, wstrlen);
-
-/* itrace("wmatchlen (%ls) -> %d", wpat, mlen); */
- switch (mtype)
- {
- case MATCH_ANY:
- for (n = 0; n <= wstrlen; n++)
- {
-#if 1
- n2 = simple ? (*wpat == wstring[n]) : match_pattern_wchar (wpat, wstring + n);
-#else
- n2 = match_pattern_wchar (wpat, wstring + n);
-#endif
- if (n2)
- {
-#if 0
- for (n1 = wstrlen; n1 >= n; n1--)
-#else
- n1 = (mlen == -1) ? wstrlen : n + mlen;
- if (n1 > wstrlen)
- break;
-
- for ( ; n1 >= n; n1--)
-#endif
- {
- 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;
-#if 1
- /* If MLEN != -1, we have a fixed length pattern. */
- if (mlen != -1)
- break;
-#endif
- }
- }
- }
-
- return (0);
-
- case MATCH_BEG:
- if (match_pattern_wchar (wpat, wstring) == 0)
- return (0);
-
-#if 0
- for (n = wstrlen; n >= 0; n--)
-#else
- for (n = (mlen == -1) ? wstrlen : mlen; n >= 0; n--)
-#endif
- {
- 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;
-#if 1
- /* If MLEN != -1, we have a fixed length pattern. */
- if (mlen != -1)
- break;
-#endif
- }
-
- return (0);
-
- case MATCH_END:
-#if 0
- for (n = 0; n <= wstrlen; n++)
-#else
- for (n = wstrlen - ((mlen == -1) ? wstrlen : mlen); n <= wstrlen; n++)
-#endif
- {
- if (wcsmatch (wpat, wstring + n, FNMATCH_EXTFLAG) == 0)
- {
- *sp = indices[n];
- *ep = indices[wstrlen];
- return 1;
- }
-#if 1
- /* If MLEN != -1, we have a fixed length pattern. */
- if (mlen != -1)
- break;
-#endif
- }
-
- 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;
- size_t slen, plen, mslen, mplen;
-#endif
-
- if (string == 0 || *string == 0 || pat == 0 || *pat == 0)
- return (0);
-
-#if defined (HANDLE_MULTIBYTE)
- if (MB_CUR_MAX > 1)
- {
-#if 0
- slen = STRLEN (string);
- mslen = MBSLEN (string);
- plen = STRLEN (pat);
- mplen = MBSLEN (pat);
- if (slen == mslen && plen == mplen)
-#else
- if (mbsmbchar (string) == 0 && mbsmbchar (pat) == 0)
-#endif
- return (match_upattern (string, pat, mtype, sp, ep));
-
- 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 *);
- tword = string_list_pos_params (itype, l, quoted);
- 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 (var, pattern, patspec, varname, quoted)
- SHELL_VAR *var;
- char *pattern;
- int patspec;
- char *varname; /* so we can figure out how it's indexed */
- int quoted;
-{
- ARRAY *a;
- HASH_TABLE *h;
- 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];
-
- a = (v && array_p (v)) ? array_cell (v) : 0;
- h = (v && assoc_p (v)) ? assoc_cell (v) : 0;
-
- list = a ? array_to_word_list (a) : (h ? assoc_to_word_list (h) : 0);
- 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, ind, patstr, rtype, quoted, flags)
- char *varname, *value;
- int ind;
- char *patstr;
- int rtype, quoted, flags;
-{
- 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, ind, quoted, flags, &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++;
-
- /* Need to pass getpattern newly-allocated memory in case of expansion --
- the expansion code will free the passed string on an error. */
- temp1 = savestring (patstr);
- pattern = getpattern (temp1, quoted, 1);
- free (temp1);
-
- 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 = (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
- ? quote_string (temp1)
- : quote_escapes (temp1);
- free (temp1);
- temp1 = val;
- }
- break;
-#if defined (ARRAY_VARS)
- case VT_ARRAYVAR:
- temp1 = array_remove_pattern (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;
-#if defined (HANDLE_MULTIBYTE)
- if (ifs_firstc[0] == 0)
-#else
- if (ifs_firstc == 0)
-#endif
- word->flags |= W_NOSPLIT;
- word->flags |= W_NOSPLIT2;
- 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. Virtually identical to expand_word_unsplit;
- could be combined if implementations don't diverge. */
-WORD_LIST *
-expand_word_leave_quoted (word, quoted)
- WORD_DESC *word;
- int quoted;
-{
- WORD_LIST *result;
-
- expand_no_split_dollar_star = 1;
-#if defined (HANDLE_MULTIBYTE)
- if (ifs_firstc[0] == 0)
-#else
- if (ifs_firstc == 0)
-#endif
- word->flags |= W_NOSPLIT;
- word->flags |= W_NOSPLIT2;
- result = call_expand_word_internal (word, quoted, 0, (int *)NULL, (int *)NULL);
- expand_no_split_dollar_star = 0;
-
- return result;
-}
-
-#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;
-
-char *
-copy_fifo_list (sizep)
- int *sizep;
-{
- if (sizep)
- *sizep = 0;
- return (char *)NULL;
-}
-
-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 (i)
- int 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;
- }
-}
-
-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;
-}
-
-/* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
- from some point in the past, and close all open FIFOs in fifo_list
- that are not marked as active in LIST. If LIST is NULL, close
- everything in fifo_list. LSIZE is the number of elements in LIST, in
- case it's larger than fifo_list_size (size of fifo_list). */
-void
-close_new_fifos (list, lsize)
- char *list;
- int lsize;
-{
- int i;
-
- if (list == 0)
- {
- unlink_fifo_list ();
- return;
- }
-
- for (i = 0; i < lsize; i++)
- if (list[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1)
- unlink_fifo (i);
-
- for (i = lsize; i < fifo_list_size; i++)
- unlink_fifo (i);
-}
-
-int
-fifos_pending ()
-{
- return nfifo;
-}
-
-int
-num_fifos ()
-{
- return nfifo;
-}
-
-static char *
-make_named_pipe ()
-{
- char *tname;
-
- tname = sh_mktmpname ("sh-np", MT_USERANDOM|MT_USETMPDIR);
- 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. */
-
-char *
-copy_fifo_list (sizep)
- int *sizep;
-{
- char *ret;
-
- if (nfds == 0 || totfds == 0)
- {
- if (sizep)
- *sizep = 0;
- return (char *)NULL;
- }
-
- if (sizep)
- *sizep = totfds;
- ret = (char *)xmalloc (totfds);
- return (memcpy (ret, dev_fd_list, totfds));
-}
-
-static void
-add_fifo_list (fd)
- int fd;
-{
- if (dev_fd_list == 0 || 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++;
-}
-
-int
-fifos_pending ()
-{
- return 0; /* used for cleanup; not needed with /dev/fd */
-}
-
-int
-num_fifos ()
-{
- return nfds;
-}
-
-void
-unlink_fifo (fd)
- int fd;
-{
- if (dev_fd_list[fd])
- {
- close (fd);
- dev_fd_list[fd] = 0;
- nfds--;
- }
-}
-
-void
-unlink_fifo_list ()
-{
- register int i;
-
- if (nfds == 0)
- return;
-
- for (i = 0; nfds && i < totfds; i++)
- unlink_fifo (i);
-
- nfds = 0;
-}
-
-/* Take LIST, which is a snapshot copy of dev_fd_list from some point in
- the past, and close all open fds in dev_fd_list that are not marked
- as open in LIST. If LIST is NULL, close everything in dev_fd_list.
- LSIZE is the number of elements in LIST, in case it's larger than
- totfds (size of dev_fd_list). */
-void
-close_new_fifos (list, lsize)
- char *list;
- int lsize;
-{
- int i;
-
- if (list == 0)
- {
- unlink_fifo_list ();
- return;
- }
-
- for (i = 0; i < lsize; i++)
- if (list[i] == 0 && i < totfds && dev_fd_list[i])
- unlink_fifo (i);
-
- for (i = lsize; i < totfds; i++)
- unlink_fifo (i);
-}
-
-#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) + 8);
-
- 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 == 0)
- {
- 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 (); /* XXX - what about special builtins? bash-4.2 */
- setup_async_signals ();
- subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
- }
-
-#if defined (JOB_CONTROL)
- set_sigchld_handler ();
- stop_making_children ();
- /* XXX - should we only do this in the parent? (as in command subst) */
- 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 (_("cannot 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, rflag)
- int fd, quoted;
- int *rflag;
-{
- char *istring, buf[128], *bufp, *s;
- int istring_index, istring_size, c, tflag, skip_ctlesc, skip_ctlnul;
- ssize_t bufn;
-
- istring = (char *)NULL;
- istring_index = istring_size = bufn = tflag = 0;
-
- for (skip_ctlesc = skip_ctlnul = 0, s = ifs_value; s && *s; s++)
- skip_ctlesc |= *s == CTLESC, skip_ctlnul |= *s == CTLNUL;
-
- /* Read the output of the command through the pipe. This may need to be
- changed to understand multibyte characters in the future. */
- 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);
-
- /* This is essentially quote_string inline */
- if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) /* || c == CTLESC || c == CTLNUL */)
- istring[istring_index++] = CTLESC;
- /* Escape CTLESC and CTLNUL in the output to protect those characters
- from the rest of the word expansions (word splitting and globbing.)
- This is essentially quote_escapes inline. */
- else if (skip_ctlesc == 0 && c == CTLESC)
- {
- tflag |= W_HASCTLESC;
- istring[istring_index++] = CTLESC;
- }
- else if ((skip_ctlnul == 0 && c == CTLNUL) || (c == ' ' && (ifs_value && *ifs_value == 0)))
- 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);
- if (rflag)
- *rflag = tflag;
- 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);
-
- if (rflag)
- *rflag = tflag;
- return istring;
-}
-
-/* Perform command substitution on STRING. This returns a WORD_DESC * with the
- contained string possibly quoted. */
-WORD_DESC *
-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, tflag;
- WORD_DESC *ret;
-
- 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 ((WORD_DESC *)NULL);
-
- if (wordexp_only && read_but_dont_execute)
- {
- last_command_exit_value = EX_WEXPCOMSUB;
- 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 && sourcelevel == 0) ? 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;
- pid = make_child ((char *)NULL, subshell_environment&SUBSHELL_ASYNC);
- last_asynchronous_pid = old_async_pid;
-
- if (pid == 0)
- {
- /* Reset the signal handlers in the child, but don't free the
- trap strings. Set a flag noting that we have to free the
- trap strings if we run trap to change a signal disposition. */
- reset_signal_handlers ();
- subshell_environment |= SUBSHELL_RESETTRAP;
- }
-
-#if defined (JOB_CONTROL)
- /* XXX DO THIS ONLY IN PARENT ? XXX */
- set_sigchld_handler ();
- stop_making_children ();
- if (pid != 0)
- 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 ((WORD_DESC *)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]);
-
-#ifdef __CYGWIN__
- /* Let stdio know the fd may have changed from text to binary mode, and
- make sure to preserve stdout line buffering. */
- freopen (NULL, "w", stdout);
- sh_setlinebuf (stdout);
-#endif /* __CYGWIN__ */
-
- /* 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);
-itrace("command_substitute: %s", string);
- /* 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 ();
-#if defined (PROCESS_SUBSTITUTION)
- unlink_fifo_list ();
-#endif
- exit (rc);
- }
- else
- {
-#if defined (JOB_CONTROL) && defined (PGRP_PIPE)
- close_pgrp_pipe ();
-#endif /* JOB_CONTROL && PGRP_PIPE */
-
- close (fildes[1]);
-
- tflag = 0;
- istring = read_comsub (fildes[0], quoted, &tflag);
-
- 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 (interactive && pipeline_pgrp != (pid_t)0 && (subshell_environment & SUBSHELL_ASYNC) == 0)
- give_terminal_to (pipeline_pgrp, 0);
-#endif /* JOB_CONTROL */
-
- ret = alloc_word_desc ();
- ret->word = istring;
- ret->flags = tflag;
-
- return ret;
- }
-}
-
-/********************************************************
- * *
- * Utility functions for parameter expansion *
- * *
- ********************************************************/
-
-#if defined (ARRAY_VARS)
-
-static arrayind_t
-array_length_reference (s)
- char *s;
-{
- int len;
- arrayind_t ind;
- char *akey;
- char *t, c;
- ARRAY *array;
- HASH_TABLE *h;
- 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 || (assoc_p (var) == 0 && array_p (var) == 0)) && unbound_vars_is_error)
- {
- c = *--t;
- *t = '\0';
- last_command_exit_value = EXECUTION_FAILURE;
- 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;
- h = assoc_p (var) ? assoc_cell (var) : (HASH_TABLE *)NULL;
-
- if (ALL_ELEMENT_SUB (t[0]) && t[1] == ']')
- {
- if (assoc_p (var))
- return (h ? assoc_num_elements (h) : 0);
- else if (array_p (var))
- return (array ? array_num_elements (array) : 0);
- else
- return (var_isset (var) ? 1 : 0);
- }
-
- if (assoc_p (var))
- {
- t[len - 1] = '\0';
- akey = expand_assignment_string_to_string (t, 0); /* [ */
- t[len - 1] = ']';
- if (akey == 0 || *akey == 0)
- {
- err_badarraysub (t);
- FREE (akey);
- return (-1);
- }
- t = assoc_reference (assoc_cell (var), akey);
- free (akey);
- }
- else
- {
- ind = array_expand_index (var, 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 = MB_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 = mbschr (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, pflags, indp)
- char *name;
- int var_is_special, quoted, pflags;
- arrayind_t *indp;
-{
- WORD_DESC *ret;
- char *temp, *tt;
- intmax_t arg_index;
- SHELL_VAR *var;
- int atype, rflags;
- arrayind_t ind;
-
- ret = 0;
- temp = 0;
- rflags = 0;
-
- if (indp)
- *indp = INTMAX_MIN;
-
- /* 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, pflags);
- free (tt);
- }
-#if defined (ARRAY_VARS)
- else if (valid_array_reference (name))
- {
- /* XXX - does this leak if name[@] or name[*]? */
- temp = array_value (name, quoted, 0, &atype, &ind);
- if (atype == 0 && temp)
- {
- temp = (*temp && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
- ? quote_string (temp)
- : quote_escapes (temp);
- rflags |= W_ARRAYIND;
- if (indp)
- *indp = ind;
- }
- else if (atype == 1 && temp && QUOTED_NULL (temp) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)))
- rflags |= W_HASQUOTEDNULL;
- }
-#endif
- else if (var = find_variable (name))
- {
- if (var_isset (var) && invisible_p (var) == 0)
- {
-#if defined (ARRAY_VARS)
- if (assoc_p (var))
- temp = assoc_reference (assoc_cell (var), "0");
- else if (array_p (var))
- temp = array_reference (array_cell (var), 0);
- else
- temp = 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;
- ret->flags |= rflags;
- }
- 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, PF_IGNUNBOUND, 0);
- 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, 0, 0);
- 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 (for sh backwards compatibility). */
- 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 = make_quoted_char ('\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);
-
- /* From Posix group discussion Feb-March 2010. Issue 7 0000221 */
- free (temp);
-
- w->word = t1;
- 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;
-
- last_command_exit_value = EXECUTION_FAILURE; /* ensure it's non-zero */
- 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} */
-}
-
-/* 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; /* XXX - error if set -u set? */
- 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);
- if (t == 0 && unbound_vars_is_error)
- return INTMAX_MIN;
- number = MB_STRLEN (t);
- FREE (t);
- }
-#if defined (ARRAY_VARS)
- else if ((var = find_variable (name + 1)) && (invisible_p (var) == 0) && (array_p (var) || assoc_p (var)))
- {
- if (assoc_p (var))
- t = assoc_reference (assoc_cell (var), "0");
- else
- t = array_reference (array_cell (var), 0);
- if (t == 0 && unbound_vars_is_error)
- return INTMAX_MIN;
- 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 = t ? MB_STRLEN (t) : 0;
- 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 (v, value, substr, vtype, e1p, e2p)
- SHELL_VAR *v;
- char *value, *substr;
- int vtype;
- intmax_t *e1p, *e2p;
-{
- char *t, *temp1, *temp2;
- arrayind_t len;
- int expok;
-#if defined (ARRAY_VARS)
- ARRAY *a;
- HASH_TABLE *h;
-#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;
- if (*e1p == 0)
- len++; /* add one arg if counting from $0 */
- break;
-#if defined (ARRAY_VARS)
- case VT_ARRAYVAR:
- /* For arrays, the first value deals with array indices. Negative
- offsets count from one past the array's maximum index. Associative
- arrays treat the number of elements as the maximum index. */
- if (assoc_p (v))
- {
- h = assoc_cell (v);
- len = assoc_num_elements (h) + (*e1p < 0);
- }
- else
- {
- a = (ARRAY *)value;
- 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 = assoc_p (v) ? assoc_num_elements (h) : 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 ((vtype == VT_ARRAYVAR || vtype == VT_POSPARMS) && *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
- {
- if (*e2p < 0)
- {
- *e2p += len;
- if (*e2p < 0 || *e2p < *e1p)
- {
- internal_error (_("%s: substring expression < 0"), t);
- return (0);
- }
- }
- else
- *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).
- QUOTED is the standard description of quoting state, using Q_* defines.
- FLAGS is currently a set of flags to pass to array_value. If IND is
- non-null and not INTMAX_MIN, and FLAGS includes AV_USEIND, IND is
- passed to array_value so the array index is not computed again.
- 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, ind, quoted, flags, varp, valp)
- char *varname, *value;
- arrayind_t ind;
- int quoted, flags;
- SHELL_VAR **varp;
- char **valp;
-{
- int vtype;
- char *temp;
-#if defined (ARRAY_VARS)
- SHELL_VAR *v;
-#endif
- arrayind_t lind;
-
- /* 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 we want to signal array_value to use an already-computed index,
- set LIND to that index */
- lind = (ind != INTMAX_MIN && (flags & AV_USEIND)) ? ind : 0;
- if (v && (array_p (v) || assoc_p (v)))
- { /* [ */
- if (ALL_ELEMENT_SUB (temp[0]) && temp[1] == ']')
- {
- /* Callers have to differentiate betwen indexed and associative */
- vtype = VT_ARRAYVAR;
- if (temp[0] == '*')
- vtype |= VT_STARSUB;
- *valp = array_p (v) ? (char *)array_cell (v) : (char *)assoc_cell (v);
- }
- else
- {
- vtype = VT_ARRAYMEMBER;
- *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
- }
- *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
- {
- vtype = VT_ARRAYMEMBER;
- *varp = v;
- *valp = array_value (varname, Q_DOUBLE_QUOTES, flags, (int *)NULL, &lind);
- }
- }
- else if ((v = find_variable (varname)) && (invisible_p (v) == 0) && (assoc_p (v) || array_p (v)))
- {
- vtype = VT_ARRAYMEMBER;
- *varp = v;
- *valp = assoc_p (v) ? assoc_reference (assoc_cell (v), "0") : 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, ind, substr, quoted, flags)
- char *varname, *value;
- int ind;
- char *substr;
- int quoted, flags;
-{
- 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, ind, quoted, flags, &v, &val);
- if (vtype == -1)
- {
- this_command_name = oname;
- return ((char *)NULL);
- }
-
- starsub = vtype & VT_STARSUB;
- vtype &= ~VT_STARSUB;
-
- r = verify_substring_values (v, val, substr, vtype, &e1, &e2);
- this_command_name = oname;
- if (r <= 0)
- {
- if (vtype == VT_VARIABLE)
- FREE (val);
- 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:
- if (assoc_p (v))
- /* we convert to list and take first e2 elements starting at e1th
- element -- officially undefined for now */
- temp = assoc_subrange (assoc_cell (v), e1, e2, starsub, quoted);
- else
- /* 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). */
- temp = array_subrange (array_cell (v), e1, e2, starsub, quoted);
- /* array_subrange now calls array_quote_escapes as appropriate, so the
- caller no longer needs to. */
- break;
-#endif
- default:
- temp = (char *)NULL;
- }
-
- return temp;
-}
-
-/****************************************************************/
-/* */
-/* Functions to perform pattern substitution on variable values */
-/* */
-/****************************************************************/
-
-static int
-shouldexp_replacement (s)
- char *s;
-{
- register char *p;
-
- for (p = s; p && *p; p++)
- {
- if (*p == '\\')
- p++;
- else if (*p == '&')
- return 1;
- }
- return 0;
-}
-
-char *
-pat_subst (string, pat, rep, mflags)
- char *string, *pat, *rep;
- int mflags;
-{
- char *ret, *s, *e, *str, *rstr, *mstr;
- int rsize, rptr, l, replen, mtype, rxpand, rslen, mlen;
-
- if (string == 0)
- return (savestring (""));
-
- mtype = mflags & MATCH_TYPEMASK;
-
-#if 0 /* bash-4.2 ? */
- rxpand = (rep && *rep) ? shouldexp_replacement (rep) : 0;
-#else
- rxpand = 0;
-#endif
-
- /* 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.
- * These don't understand or process `&' in the replacement string.
- */
- 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;
-
- if (rxpand)
- {
- int x;
- mlen = e - s;
- mstr = xmalloc (mlen + 1);
- for (x = 0; x < mlen; x++)
- mstr[x] = s[x];
- mstr[mlen] = '\0';
- rstr = strcreplace (rep, '&', mstr, 0);
- rslen = strlen (rstr);
- }
- else
- {
- rstr = rep;
- rslen = replen;
- }
-
- RESIZE_MALLOCED_BUFFER (ret, rptr, (l + rslen), 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, rstr, rslen);
- rptr += rslen;
- }
- str = e; /* e == end of match */
-
- if (rstr != rep)
- free (rstr);
-
- if (((mflags & MATCH_GLOBREP) == 0) || mtype != MATCH_ANY)
- break;
-
- if (s == e)
- {
- /* On a zero-length match, make sure we copy one character, since
- we increment one character to avoid infinite recursion. */
- RESIZE_MALLOCED_BUFFER (ret, rptr, 1, rsize, 64);
- ret[rptr++] = *str++;
- e++; /* avoid infinite recursion on zero-length match */
- }
- }
-
- /* Now copy the unmatched portion of the input string */
- if (str && *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;
- int pchar, qflags;
-
- 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;
- }
-
- pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
- qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
-
-#if 0
- if ((mflags & (MATCH_QUOTED|MATCH_STARSUB)) == (MATCH_QUOTED|MATCH_STARSUB))
- ret = string_list_dollar_star (quote_list (save));
- else if ((mflags & MATCH_STARSUB) == MATCH_STARSUB)
- ret = string_list_dollar_star (save);
- else if ((mflags & MATCH_QUOTED) == MATCH_QUOTED)
- ret = string_list_dollar_at (save, qflags);
- else
- ret = string_list_dollar_star (save);
-#else
- ret = string_list_pos_params (pchar, save, qflags);
-#endif
-
- 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, ind, patsub, quoted, flags)
- char *varname, *value;
- int ind;
- char *patsub;
- int quoted, flags;
-{
- int vtype, mflags, starsub, delim;
- 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, ind, quoted, flags, &v, &val);
- if (vtype == -1)
- return ((char *)NULL);
-
- starsub = vtype & VT_STARSUB;
- vtype &= ~VT_STARSUB;
-
- mflags = 0;
- /* PATSUB is never NULL when this is called. */
- 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 the pattern starts with a `/', make sure we skip over it when looking
- for the replacement delimiter. */
- delim = skip_to_delim (lpatsub, ((*patsub == '/') ? 1 : 0), "/", 0);
- if (lpatsub[delim] == '/')
- {
- lpatsub[delim] = 0;
- rep = lpatsub + delim + 1;
- }
- 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. Make sure we don't anchor the pattern
- at the beginning or end of the string if we're doing global replacement,
- though. */
- p = pat;
- if (mflags & MATCH_GLOBREP)
- mflags |= MATCH_ANY;
- 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 = (mflags & MATCH_QUOTED) ? quote_string (temp) : 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 = assoc_p (v) ? assoc_patsub (assoc_cell (v), p, rep, mflags)
- : array_patsub (array_cell (v), p, rep, mflags);
- /* Don't call quote_escapes anymore; array_patsub calls
- array_quote_escapes as appropriate before adding the
- space separators; ditto for assoc_patsub. */
- break;
-#endif
- }
-
- FREE (pat);
- FREE (rep);
- free (lpatsub);
-
- return temp;
-}
-
-/****************************************************************/
-/* */
-/* Functions to perform case modification on variable values */
-/* */
-/****************************************************************/
-
-/* Do case modification on the positional parameters. */
-
-static char *
-pos_params_modcase (string, pat, modop, mflags)
- char *string, *pat;
- int modop;
- int mflags;
-{
- WORD_LIST *save, *params;
- WORD_DESC *w;
- char *ret;
- int pchar, qflags;
-
- save = params = list_rest_of_args ();
- if (save == 0)
- return ((char *)NULL);
-
- for ( ; params; params = params->next)
- {
- ret = sh_modcase (params->word->word, pat, modop);
- w = alloc_word_desc ();
- w->word = ret ? ret : savestring ("");
- dispose_word (params->word);
- params->word = w;
- }
-
- pchar = (mflags & MATCH_STARSUB) == MATCH_STARSUB ? '*' : '@';
- qflags = (mflags & MATCH_QUOTED) == MATCH_QUOTED ? Q_DOUBLE_QUOTES : 0;
-
- ret = string_list_pos_params (pchar, save, qflags);
- dispose_words (save);
-
- return (ret);
-}
-
-/* Perform case modification on VALUE, which is the expansion of
- VARNAME. MODSPEC is an expression supplying the type of modification
- to perform. QUOTED is a flags word containing the type of quoting
- currently in effect. */
-static char *
-parameter_brace_casemod (varname, value, ind, modspec, patspec, quoted, flags)
- char *varname, *value;
- int ind, modspec;
- char *patspec;
- int quoted, flags;
-{
- int vtype, starsub, modop, mflags, x;
- char *val, *temp, *pat, *p, *lpat, *tt;
- SHELL_VAR *v;
-
- if (value == 0)
- return ((char *)NULL);
-
- this_command_name = varname;
-
- vtype = get_var_and_type (varname, value, ind, quoted, flags, &v, &val);
- if (vtype == -1)
- return ((char *)NULL);
-
- starsub = vtype & VT_STARSUB;
- vtype &= ~VT_STARSUB;
-
- modop = 0;
- mflags = 0;
- if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
- mflags |= MATCH_QUOTED;
- if (starsub)
- mflags |= MATCH_STARSUB;
-
- p = patspec;
- if (modspec == '^')
- {
- x = p && p[0] == modspec;
- modop = x ? CASE_UPPER : CASE_UPFIRST;
- p += x;
- }
- else if (modspec == ',')
- {
- x = p && p[0] == modspec;
- modop = x ? CASE_LOWER : CASE_LOWFIRST;
- p += x;
- }
- else if (modspec == '~')
- {
- x = p && p[0] == modspec;
- modop = x ? CASE_TOGGLEALL : CASE_TOGGLE;
- p += x;
- }
-
- lpat = p ? savestring (p) : 0;
- /* Perform the same expansions on the pattern as performed by the
- pattern removal expansions. FOR LATER */
- pat = lpat ? getpattern (lpat, quoted, 1) : 0;
-
- /* OK, now we do the case modification. */
- switch (vtype)
- {
- case VT_VARIABLE:
- case VT_ARRAYMEMBER:
- temp = sh_modcase (val, pat, modop);
- if (vtype == VT_VARIABLE)
- FREE (val);
- if (temp)
- {
- tt = (mflags & MATCH_QUOTED) ? quote_string (temp) : quote_escapes (temp);
- free (temp);
- temp = tt;
- }
- break;
-
- case VT_POSPARMS:
- temp = pos_params_modcase (val, pat, modop, mflags);
- if (temp && (mflags & MATCH_QUOTED) == 0)
- {
- tt = quote_escapes (temp);
- free (temp);
- temp = tt;
- }
- break;
-
-#if defined (ARRAY_VARS)
- case VT_ARRAYVAR:
- temp = assoc_p (v) ? assoc_modcase (assoc_cell (v), pat, modop, mflags)
- : array_modcase (array_cell (v), pat, modop, mflags);
- /* Don't call quote_escapes; array_modcase calls array_quote_escapes
- as appropriate before adding the space separators; ditto for
- assoc_modcase. */
- break;
-#endif
- }
-
- FREE (pat);
- free (lpat);
-
- 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] == LPAREN)
- count++;
- else if (s[i] == RPAREN)
- {
- 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, pflags, quoted_dollar_atp, contains_dollar_at)
- char *string;
- int *indexp, quoted, *quoted_dollar_atp, *contains_dollar_at, pflags;
-{
- int check_nullness, var_is_set, var_is_null, var_is_special;
- int want_substring, want_indir, want_patsub, want_casemod;
- char *name, *value, *temp, *temp1;
- WORD_DESC *tdesc, *ret;
- int t_index, sindex, c, tflag, modspec;
- intmax_t number;
- arrayind_t ind;
-
- temp = temp1 = value = (char *)NULL;
- var_is_set = var_is_null = var_is_special = check_nullness = 0;
- want_substring = want_indir = want_patsub = want_casemod = 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, "}", SX_VARNAME);
- else
-#if defined (CASEMOD_EXPANSIONS)
- /* To enable case-toggling expansions using the `~' operator character
- change the 1 to 0. */
-# if defined (CASEMOD_CAPCASE)
- name = string_extract (string, &t_index, "#%^,~:-=?+/}", SX_VARNAME);
-# else
- name = string_extract (string, &t_index, "#%^,:-=?+/}", SX_VARNAME);
-# endif /* CASEMOD_CAPCASE */
-#else
- name = string_extract (string, &t_index, "#%:-=?+/}", SX_VARNAME);
-#endif /* CASEMOD_EXPANSIONS */
-
- ret = 0;
- tflag = 0;
-
- ind = INTMAX_MIN;
-
- /* 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 && VALID_SPECIAL_LENGTH_PARAM (string[t_index])) ||
- (sindex == t_index - 1 && string[sindex] == '!' && VALID_INDIR_PARAM (string[t_index])))
- {
- t_index++;
- temp1 = string_extract (string, &t_index, "#%:-=?+/}", 0);
- name = (char *)xrealloc (name, 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 */) /* XXX */
- want_patsub = 1;
-#if defined (CASEMOD_EXPANSIONS)
- else if (c == '^' || c == ',' || c == '~')
- {
- modspec = c;
- want_casemod = 1;
- }
-#endif
-
- /* 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);
- if (number == INTMAX_MIN && unbound_vars_is_error)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- err_unboundvar (name+1);
- free (name);
- return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
- }
- 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);
- dispose_words (xlist);
- free (temp1);
- *indexp = sindex;
-
- free (name);
-
- 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); /* handles assoc vars too */
- 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, PF_IGNUNBOUND|(pflags&PF_NOSPLIT2), &ind);
-
- 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, (c == '%' || c == '#' || c =='/' || c == '^' || c == ',' || c ==':') ? SX_POSIXEXP|SX_WORD : SX_WORD);
- if (string[sindex] == RBRACE)
- sindex++;
- else
- goto bad_substitution;
- }
- else
- value = (char *)NULL;
-
- *indexp = sindex;
-
- /* All the cases where an expansion can possibly generate an unbound
- variable error. */
- if (want_substring || want_patsub || want_casemod || c == '#' || c == '%' || c == RBRACE)
- {
- if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
- {
- last_command_exit_value = EXECUTION_FAILURE;
- err_unboundvar (name);
- FREE (value);
- FREE (temp);
- free (name);
- return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
- }
- }
-
- /* If this is a substring spec, process it and add the result. */
- if (want_substring)
- {
- temp1 = parameter_brace_substring (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
- 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;
- if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
- ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
- return ret;
- }
- else if (want_patsub)
- {
- temp1 = parameter_brace_patsub (name, temp, ind, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
- 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;
- if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
- ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
- return ret;
- }
-#if defined (CASEMOD_EXPANSIONS)
- else if (want_casemod)
- {
- temp1 = parameter_brace_casemod (name, temp, ind, modspec, value, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
- 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;
- if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
- ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
- return ret;
- }
-#endif
-
- /* Do the right thing based on which character ended the variable name. */
- switch (c)
- {
- default:
- case '\0':
- bad_substitution:
- last_command_exit_value = EXECUTION_FAILURE;
- report_error (_("%s: bad substitution"), string ? string : "??");
- FREE (value);
- FREE (temp);
- free (name);
- return &expand_wdesc_error;
-
- case RBRACE:
- 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, ind, value, c, quoted, (tflag & W_ARRAYIND) ? AV_USEIND : 0);
- free (temp);
- free (value);
- free (name);
-
- ret = alloc_word_desc ();
- ret->word = temp1;
- if (temp1 && QUOTED_NULL (temp1) && (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)))
- ret->flags |= W_QUOTED|W_HASQUOTEDNULL;
- return ret;
-
- 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)
- {
- /* From Posix discussion on austin-group list. Issue 221
- requires that backslashes escaping `}' inside
- double-quoted ${...} be removed. */
- if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
- quoted |= Q_DOLBRACE;
- 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)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- 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;
-
- /* From Posix discussion on austin-group list. Issue 221 requires
- that backslashes escaping `}' inside double-quoted ${...} be
- removed. */
- if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
- quoted |= Q_DOLBRACE;
- 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';
- last_command_exit_value = EXECUTION_FAILURE;
- err_unboundvar (uerror);
- 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';
- last_command_exit_value = EXECUTION_FAILURE;
- err_unboundvar (uerror);
- 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 0
- /* According to austin-group posix proposal by Geoff Clare in
- <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
-
- "The shell shall write a message to standard error and
- immediately exit when it tries to expand an unset parameter
- other than the '@' and '*' special parameters."
- */
-
- if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
- {
- uerror[0] = '$';
- uerror[1] = '*';
- uerror[2] = '\0';
- last_command_exit_value = EXECUTION_FAILURE;
- err_unboundvar (uerror);
- return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
- }
-#endif
-
- /* 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|Q_PATQUOTE))
- {
- /* 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|Q_PATQUOTE)) ? string_list_dollar_star (list) : string_list (list);
- if (temp)
- {
- 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 ();
-
-#if 0
- /* According to austin-group posix proposal by Geoff Clare in
- <20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
-
- "The shell shall write a message to standard error and
- immediately exit when it tries to expand an unset parameter
- other than the '@' and '*' special parameters."
- */
-
- if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
- {
- uerror[0] = '$';
- uerror[1] = '@';
- uerror[2] = '\0';
- last_command_exit_value = EXECUTION_FAILURE;
- err_unboundvar (uerror);
- return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
- }
-#endif
-
- /* 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. */
- /* XXX - should this test include Q_PATQUOTE? */
- 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. */
-#if 0
- temp = string_list_dollar_at (list, quoted);
-#else
- temp = string_list_dollar_at (list, (pflags & PF_ASSIGNRHS) ? (quoted|Q_DOUBLE_QUOTES) : quoted);
-#endif
-
- dispose_words (list);
- break;
-
- case LBRACE:
- tdesc = parameter_brace_expand (string, &zindex, quoted, pflags,
- 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, 0);
- 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);
-#if 0
- internal_warning (_("future versions of the shell will force evaluation as an arithmetic substitution"));
-#endif
- 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
- {
- tdesc = command_substitute (temp, quoted);
- temp1 = tdesc ? tdesc->word : (char *)NULL;
- if (tdesc)
- dispose_word_desc (tdesc);
- }
- 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;
- if (temp == 0)
- {
- temp = savestring (string);
- if (expanded_something)
- *expanded_something = 0;
- goto return0;
- }
-
- /* 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 (assoc_p (var) || array_p (var))
- {
- temp = array_p (var) ? array_reference (array_cell (var), 0)
- : assoc_reference (assoc_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)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- 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 pflags; /* flags passed to param_expand */
-
- 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))
- {
- if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
- goto add_ifs_character;
- else
- 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
- if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
- goto add_ifs_character;
- else
- goto add_character;
-
- case ':':
- if (word->flags & W_NOTILDE)
- {
- if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
- goto add_ifs_character;
- else
- goto add_character;
- }
-
- if ((word->flags & (W_ASSIGNMENT|W_ASSIGNRHS|W_TILDEEXP)) &&
- string[sindex+1] == '~')
- word->flags |= W_ITILDE;
-
- if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c))
- goto add_ifs_character;
- else
- 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;
- if (isexp == 0 && (word->flags & (W_NOSPLIT|W_NOSPLIT2)) == 0 && isifs (c) && (quoted & (Q_DOUBLE_QUOTES|Q_HERE_DOCUMENT)) == 0)
- goto add_ifs_character;
- else
- 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_quoted_string; /* XXX was add_string */
- }
- else
- {
- FREE (temp);
- goto add_character;
- }
-
- case '$':
- if (expanded_something)
- *expanded_something = 1;
-
- has_dollar_at = 0;
- pflags = (word->flags & W_NOCOMSUB) ? PF_NOCOMSUB : 0;
- if (word->flags & W_NOSPLIT2)
- pflags |= PF_NOSPLIT2;
- if (word->flags & W_ASSIGNRHS)
- pflags |= PF_ASSIGNRHS;
- tword = param_expand (string, &sindex, quoted, expanded_something,
- &has_dollar_at, "ed_dollar_at,
- &had_quoted_null, pflags);
-
- 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 ? tword->word : (char *)NULL;
- dispose_word_desc (tword);
-
- goto add_string;
- break;
-
- case '`': /* Backquoted command substitution. */
- {
- t_index = sindex++;
-
- temp = string_extract (string, &sindex, "`", SX_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;
- }
- last_command_exit_value = EXECUTION_FAILURE;
- 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);
- tword = command_substitute (temp, quoted);
- temp1 = tword ? tword->word : (char *)NULL;
- if (tword)
- dispose_word_desc (tword);
- }
- 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;
-
- /* From Posix discussion on austin-group list: Backslash escaping
- a } in ${...} is removed. Issue 0000221 */
- if ((quoted & Q_DOLBRACE) && c == RBRACE)
- {
- SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
- }
- else 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)
- {
-#if 0
- if (quoted_dollar_at && (word->flags & W_NOSPLIT2))
- temp = string_list_internal (quote_list (list), " ");
- else
-#endif
- /* 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. The execption to
- this is when we are going to be performing word splitting,
- since we have to preserve a null argument if the next character
- will cause word splitting. */
- if (temp == 0 && quoted_state == PARTIALLY_QUOTED && (word->flags & (W_NOSPLIT|W_NOSPLIT2)))
- 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 " $@ " */
- add_ifs_character:
- 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 (c == 0)
- {
- *r++ = '\\';
- break;
- }
- 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;
- ifs_value = (v && value_cell (v)) ? value_cell (v) : " \t\n";
-
- /* 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 (result == 0)
- result = e = tresult;
- else
- {
- e->next = tresult;
- while (e->next)
- e = e->next;
- }
- }
- 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;
-{
- set_pipestatus_from_exit (last_command_exit_value);
-
- /* Cleanup code goes here. */
- expand_no_split_dollar_star = 0; /* XXX */
- expanding_redir = 0;
- assigning_in_environment = 0;
-
- if (parse_and_execute_level == 0)
- top_level_cleanup (); /* from sig.c */
-
- 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 == 0)
- 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)
- {
- last_command_exit_value = EXECUTION_FAILURE;
- report_error (_("no match: %s"), tlist->word->word);
- exp_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;
-
- if ((tlist->word->flags & (W_COMPASSIGN|W_ASSIGNARG)) == (W_COMPASSIGN|W_ASSIGNARG))
- {
-/*itrace("brace_expand_word_list: %s: W_COMPASSIGN|W_ASSIGNARG", tlist->word->word);*/
- PREPEND_LIST (tlist, output_list);
- continue;
- }
-
- /* 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 `mbschr', 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 (mbschr (tlist->word->word, LBRACE))
- {
- expansions = brace_expand (tlist->word->word);
-
- for (eindex = 0; temp_string = expansions[eindex]; eindex++)
- {
- w = alloc_word_desc ();
- w->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;
- else
- w = make_word_flags (w, temp_string);
-
- output_list = make_word_list (w, output_list);
- }
- 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
-
-#if defined (ARRAY_VARS)
-/* Take WORD, a compound associative array assignment, and internally run
- 'declare -A w', where W is the variable name portion of WORD. */
-static int
-make_internal_declare (word, option)
- char *word;
- char *option;
-{
- int t;
- WORD_LIST *wl;
- WORD_DESC *w;
-
- w = make_word (word);
-
- t = assignment (w->word, 0);
- w->word[t] = '\0';
-
- wl = make_word_list (w, (WORD_LIST *)NULL);
- wl = make_word_list (make_word (option), wl);
-
- return (declare_builtin (wl));
-}
-#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;
-
- if (tlist->word->flags & W_ASSIGNASSOC)
- make_internal_declare (tlist->word->word, "-A");
-
- t = do_word_assignment (tlist->word, 0);
- 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|W_ASSIGNASSOC);
- }
-#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, 0);
- /* 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;
- int is_special_builtin, is_builtin_or_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;
-
- is_builtin_or_func = (new_list && new_list->word && (find_shell_builtin (new_list->word->word) || find_function (new_list->word->word)));
- /* Posix says that special builtins exit if a variable assignment error
- occurs in an assignment preceding it. */
- is_special_builtin = (posixly_correct && new_list && new_list->word && find_special_builtin (new_list->word->word));
-
- for (temp_list = subst_assign_varlist; temp_list; temp_list = temp_list->next)
- {
- this_command_name = (char *)NULL;
- assigning_in_environment = (assign_func == assign_in_env);
- tint = (*assign_func) (temp_list->word, is_builtin_or_func);
- assigning_in_environment = 0;
- /* 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 && is_special_builtin)
- 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);
-}
+++ /dev/null
-:; ./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...
-:;
+++ /dev/null
-#! /bin/sh
-for cmd in sh bash ash ksh zsh
-do
- echo
- echo $cmd:
- for demo in shx?
- do
- $cmd $demo
- done
-done